From 83b209aee3981a513623d5631d88e600111e10c5 Mon Sep 17 00:00:00 2001 From: zuoqian Date: Tue, 11 Feb 2025 14:59:57 +0800 Subject: [PATCH 001/121] arm64: dts: miniitx macb2 rgmii add rx and tx default delay Signed-off-by: zuoqian --- arch/arm64/boot/dts/phytium/pe2204-miniitx-board.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/phytium/pe2204-miniitx-board.dts b/arch/arm64/boot/dts/phytium/pe2204-miniitx-board.dts index fe9288f6a1..2513b7b5e2 100644 --- a/arch/arm64/boot/dts/phytium/pe2204-miniitx-board.dts +++ b/arch/arm64/boot/dts/phytium/pe2204-miniitx-board.dts @@ -225,7 +225,7 @@ &macb0 { }; &macb2 { - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; use-mii; status = "okay"; }; -- Gitee From 439ed90bb630f354795222fe672ae32a29a7c333 Mon Sep 17 00:00:00 2001 From: Xiao Cong Date: Fri, 26 Jul 2024 14:08:50 +0800 Subject: [PATCH 002/121] PCI: ep: Add phytium pcie ep driver version information This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Signed-off-by: Xiao Cong Signed-off-by: Wang Yinfeng Change-Id: Iadfa10ef57cfa0ee7d1970d82afae11c00f96680 --- drivers/pci/controller/pcie-phytium-ep.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-phytium-ep.c b/drivers/pci/controller/pcie-phytium-ep.c index e25c7cdfb4..dbe166dbab 100644 --- a/drivers/pci/controller/pcie-phytium-ep.c +++ b/drivers/pci/controller/pcie-phytium-ep.c @@ -19,6 +19,8 @@ #include "pcie-phytium-ep.h" #include "pcie-phytium-register.h" +#define PHYTIUM_PCIE_RP_DRIVER_VERSION "1.1.1" + #define PHYTIUM_PCIE_EP_IRQ_PCI_ADDR_NONE 0x0 #define PHYTIUM_PCIE_EP_IRQ_PCI_ADDR_LEGACY 0x1 @@ -461,9 +463,10 @@ static struct platform_driver phytium_pcie_ep_driver = { .probe = phytium_pcie_ep_probe, .remove = phytium_pcie_ep_remove, }; - +MODULE_DEVICE_TABLE(of, phytium_pcie_ep_of_match); module_platform_driver(phytium_pcie_ep_driver); MODULE_LICENSE("GPL"); +MODULE_VERSION(PHYTIUM_PCIE_RP_DRIVER_VERSION); MODULE_AUTHOR("Yang Xun "); MODULE_DESCRIPTION("Phytium PCIe Controller Endpoint driver"); -- Gitee From c143eb06e5d5380f0190cd7317388f802f13f3f4 Mon Sep 17 00:00:00 2001 From: Huangjie Date: Thu, 17 Oct 2024 17:18:03 +0800 Subject: [PATCH 003/121] pci: ep: phytium epc driver compatible with pd2008 Signed-off-by: Huangjie --- drivers/pci/controller/pcie-phytium-ep.c | 35 +++++++++++++++++++----- drivers/pci/controller/pcie-phytium-ep.h | 7 +++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/pci/controller/pcie-phytium-ep.c b/drivers/pci/controller/pcie-phytium-ep.c index dbe166dbab..e6438dd06c 100644 --- a/drivers/pci/controller/pcie-phytium-ep.c +++ b/drivers/pci/controller/pcie-phytium-ep.c @@ -337,12 +337,31 @@ static const struct pci_epc_ops phytium_pcie_epc_ops = { .start = phytium_pcie_ep_start, }; +static const struct phytium_pcie_ep_config pd2008_pcie_ep_config = +{ + .hpb_perf_base_limit_offs = 0xA30, +}; +static const struct phytium_pcie_ep_config pe2204_pcie_ep_config = +{ + .hpb_perf_base_limit_offs = 0xA40, +}; + +static const struct of_device_id phytium_pcie_ep_of_match[] = { + { .compatible = "phytium,pd2008-pcie-ep", + .data = &pd2008_pcie_ep_config }, + { .compatible = "phytium,pe2204-pcie-ep", + .data = &pe2204_pcie_ep_config }, + { }, +}; static int phytium_pcie_ep_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct of_device_id *match = NULL; struct phytium_pcie_ep *priv = NULL; + const struct phytium_pcie_ep_config *pcie_ep_config = + &pe2204_pcie_ep_config; struct resource *res; struct device_node *np = dev->of_node; struct pci_epc *epc; @@ -352,6 +371,13 @@ static int phytium_pcie_ep_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + match = of_match_node(phytium_pcie_ep_of_match, pdev->dev.of_node); + if (match && match->data) { + pcie_ep_config = match->data; + } + priv->hpb_perf_base_limit_offs = + pcie_ep_config->hpb_perf_base_limit_offs; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg"); priv->reg_base = devm_ioremap_resource(dev, res); if (IS_ERR(priv->reg_base)) { @@ -423,13 +449,13 @@ static int phytium_pcie_ep_probe(struct platform_device *pdev) & C0_PREF_BASE_MASK) << C0_PREF_BASE_SHIFT; value |= (((lower_32_bits(priv->mem_res->end) >> C0_PREF_VALUE_SHIFT) & C0_PREF_LIMIT_MASK) << C0_PREF_LIMIT_SHIFT); - phytium_hpb_writel(priv, PHYTIUM_HPB_C0_PREF_BASE_LIMIT, value); + phytium_hpb_writel(priv, priv->hpb_perf_base_limit_offs, value); value = ((upper_32_bits(priv->mem_res->start) >> C0_PREF_UP32_VALUE_SHIFT) & C0_PREF_BASE_UP32_MASK) << C0_PREF_BASE_UP32_SHIFT; value |= (((upper_32_bits(priv->mem_res->end) >> C0_PREF_UP32_VALUE_SHIFT) & C0_PREF_LIMIT_UP32_MASK) << C0_PREF_LIMIT_UP32_SHIFT); - phytium_hpb_writel(priv, PHYTIUM_HPB_C0_PREF_BASE_LIMIT_UP32, value); + phytium_hpb_writel(priv, priv->hpb_perf_base_limit_offs + 0x04, value); dev_dbg(dev, "exit %s successful\n", __func__); return 0; @@ -450,11 +476,6 @@ static int phytium_pcie_ep_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id phytium_pcie_ep_of_match[] = { - { .compatible = "phytium,pd2008-pcie-ep" }, - { }, -}; - static struct platform_driver phytium_pcie_ep_driver = { .driver = { .name = "phytium-pcie-ep", diff --git a/drivers/pci/controller/pcie-phytium-ep.h b/drivers/pci/controller/pcie-phytium-ep.h index 10cece4fc5..57fbe52140 100644 --- a/drivers/pci/controller/pcie-phytium-ep.h +++ b/drivers/pci/controller/pcie-phytium-ep.h @@ -8,13 +8,20 @@ #ifndef __PCIE_PHYTIUM_EP_H__ #define __PCIE_PHYTIUM_EP_H__ +#include #include "pcie-phytium-register.h" #define IRQ_MAPPING_SIZE 0x1000 + +struct phytium_pcie_ep_config { + u32 hpb_perf_base_limit_offs; +}; + struct phytium_pcie_ep { void __iomem *reg_base; struct resource *mem_res; void __iomem *hpb_base; + u32 hpb_perf_base_limit_offs; unsigned int max_regions; unsigned long ob_region_map; phys_addr_t *ob_addr; -- Gitee From 7b2626cd2d74d7cb3a73c4cea9f18adf91a9114e Mon Sep 17 00:00:00 2001 From: Huangjie Date: Thu, 17 Oct 2024 17:30:03 +0800 Subject: [PATCH 004/121] pci: ep: add get_features() interface for phytium epc driver Signed-off-by: Huangjie --- drivers/pci/controller/pcie-phytium-ep.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/pci/controller/pcie-phytium-ep.c b/drivers/pci/controller/pcie-phytium-ep.c index e6438dd06c..21167429a5 100644 --- a/drivers/pci/controller/pcie-phytium-ep.c +++ b/drivers/pci/controller/pcie-phytium-ep.c @@ -325,6 +325,18 @@ static int phytium_pcie_ep_start(struct pci_epc *epc) return 0; } +static const struct pci_epc_features phytium_pcie_epc_features = { + .linkup_notifier = false, + .msi_capable = true, + .msix_capable = false, +}; + +static const struct pci_epc_features* +phytium_pcie_ep_get_features(struct pci_epc *epc, u8 func_no) +{ + return &phytium_pcie_epc_features; +} + static const struct pci_epc_ops phytium_pcie_epc_ops = { .write_header = phytium_pcie_ep_write_header, .set_bar = phytium_pcie_ep_set_bar, @@ -335,6 +347,7 @@ static const struct pci_epc_ops phytium_pcie_epc_ops = { .get_msi = phytium_pcie_ep_get_msi, .raise_irq = phytium_pcie_ep_raise_irq, .start = phytium_pcie_ep_start, + .get_features = phytium_pcie_ep_get_features, }; static const struct phytium_pcie_ep_config pd2008_pcie_ep_config = -- Gitee From f2d59a7bbc8f7e13f58da7a19fc3f092f3649bf2 Mon Sep 17 00:00:00 2001 From: Huangjie Date: Fri, 25 Oct 2024 15:02:44 +0800 Subject: [PATCH 005/121] pci: ep: modify phytium epc driver compatible value Signed-off-by: Huangjie --- drivers/pci/controller/pcie-phytium-ep.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/pci/controller/pcie-phytium-ep.c b/drivers/pci/controller/pcie-phytium-ep.c index 21167429a5..6bedb5bf42 100644 --- a/drivers/pci/controller/pcie-phytium-ep.c +++ b/drivers/pci/controller/pcie-phytium-ep.c @@ -350,21 +350,21 @@ static const struct pci_epc_ops phytium_pcie_epc_ops = { .get_features = phytium_pcie_ep_get_features, }; -static const struct phytium_pcie_ep_config pd2008_pcie_ep_config = +static const struct phytium_pcie_ep_config pcie_ep_1p0_config = { .hpb_perf_base_limit_offs = 0xA30, }; -static const struct phytium_pcie_ep_config pe2204_pcie_ep_config = +static const struct phytium_pcie_ep_config pcie_ep_2p0_config = { .hpb_perf_base_limit_offs = 0xA40, }; static const struct of_device_id phytium_pcie_ep_of_match[] = { - { .compatible = "phytium,pd2008-pcie-ep", - .data = &pd2008_pcie_ep_config }, - { .compatible = "phytium,pe2204-pcie-ep", - .data = &pe2204_pcie_ep_config }, + { .compatible = "phytium,pcie-ep-1.0", + .data = &pcie_ep_1p0_config }, + { .compatible = "phytium,pcie-ep-2.0", + .data = &pcie_ep_2p0_config }, { }, }; @@ -374,7 +374,7 @@ static int phytium_pcie_ep_probe(struct platform_device *pdev) const struct of_device_id *match = NULL; struct phytium_pcie_ep *priv = NULL; const struct phytium_pcie_ep_config *pcie_ep_config = - &pe2204_pcie_ep_config; + &pcie_ep_2p0_config; struct resource *res; struct device_node *np = dev->of_node; struct pci_epc *epc; -- Gitee From 93bd8b0af36e32af4a6846481270afeb3359653a Mon Sep 17 00:00:00 2001 From: Huangjie Date: Fri, 25 Oct 2024 15:30:55 +0800 Subject: [PATCH 006/121] pci: ep: modify phytium epc driver version to v1.1.2 Signed-off-by: Huangjie --- drivers/pci/controller/pcie-phytium-ep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/controller/pcie-phytium-ep.c b/drivers/pci/controller/pcie-phytium-ep.c index 6bedb5bf42..ad12e2487c 100644 --- a/drivers/pci/controller/pcie-phytium-ep.c +++ b/drivers/pci/controller/pcie-phytium-ep.c @@ -19,7 +19,7 @@ #include "pcie-phytium-ep.h" #include "pcie-phytium-register.h" -#define PHYTIUM_PCIE_RP_DRIVER_VERSION "1.1.1" +#define PHYTIUM_PCIE_EP_DRIVER_VERSION "1.1.2" #define PHYTIUM_PCIE_EP_IRQ_PCI_ADDR_NONE 0x0 #define PHYTIUM_PCIE_EP_IRQ_PCI_ADDR_LEGACY 0x1 @@ -501,6 +501,6 @@ MODULE_DEVICE_TABLE(of, phytium_pcie_ep_of_match); module_platform_driver(phytium_pcie_ep_driver); MODULE_LICENSE("GPL"); -MODULE_VERSION(PHYTIUM_PCIE_RP_DRIVER_VERSION); +MODULE_VERSION(PHYTIUM_PCIE_EP_DRIVER_VERSION); MODULE_AUTHOR("Yang Xun "); MODULE_DESCRIPTION("Phytium PCIe Controller Endpoint driver"); -- Gitee From fd033cdeb835da3ca8b4d326df274cfbf65d11ef Mon Sep 17 00:00:00 2001 From: Huangjie Date: Fri, 25 Oct 2024 15:35:25 +0800 Subject: [PATCH 007/121] dt-bindings: pci: add phytium pcie epc driver bindings Signed-off-by: Huangjie --- .../bindings/pci/phytium,phytium-pcie-ep.txt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/phytium,phytium-pcie-ep.txt diff --git a/Documentation/devicetree/bindings/pci/phytium,phytium-pcie-ep.txt b/Documentation/devicetree/bindings/pci/phytium,phytium-pcie-ep.txt new file mode 100644 index 0000000000..0067be87b1 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/phytium,phytium-pcie-ep.txt @@ -0,0 +1,22 @@ +* Phytium PCIe endpoint controller + +Required properties: +- compatible: Should contain "phytium,pcie-ep-1.0" or + "phytium,pcie-ep-2.0" +- reg: Should contain the controller register base address, AXI interface + region base address and hpb register base address respectively. +- reg-names: Must be "reg", "mem" and "hpb" respectively. +- max-outbound-regions: Set to maximum number of outbound regions. +- max-functions: Maximum number of functions that can be configured (default 1). + +Example: + +ep0: ep@0x29030000 { + compatible = "phytium,pcie-ep-1.0"; + reg = <0x0 0x29030000 0x0 0x10000>, + <0x11 0x00000000 0x1 0x00000000>, + <0x0 0x29101000 0x0 0x1000>; + reg-names = "reg", "mem", "hpb"; + max-outbound-regions = <3>; + max-functions = /bits/ 8 <1>; +}; -- Gitee From dc7530309b4a2508a788342b82b2c952170cc95b Mon Sep 17 00:00:00 2001 From: Huangjie Date: Fri, 7 Feb 2025 13:40:03 +0800 Subject: [PATCH 008/121] pci: ep: add virtual function number in pci_epc ops Signed-off-by: Huangjie --- drivers/pci/controller/pcie-phytium-ep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/controller/pcie-phytium-ep.c b/drivers/pci/controller/pcie-phytium-ep.c index ad12e2487c..2f75ee1d2a 100644 --- a/drivers/pci/controller/pcie-phytium-ep.c +++ b/drivers/pci/controller/pcie-phytium-ep.c @@ -332,7 +332,7 @@ static const struct pci_epc_features phytium_pcie_epc_features = { }; static const struct pci_epc_features* -phytium_pcie_ep_get_features(struct pci_epc *epc, u8 func_no) +phytium_pcie_ep_get_features(struct pci_epc *epc, u8 func_no, u8 vfunc_no) { return &phytium_pcie_epc_features; } -- Gitee From 3b7cd9f787bcf7fabd7ac6397d3e5cade1ca7cf4 Mon Sep 17 00:00:00 2001 From: Wang Yinfeng Date: Wed, 8 May 2024 14:25:03 +0800 Subject: [PATCH 009/121] arm/arm64: Bugfix the CPU MPIDR definition of phytium FTC303 core This patch Fixed MPIDR definition to 0x303 in phytium FTC303 series core. Mainline: Open-Source Signed-off-by: Wang Yinfeng Signed-off-by: Li Mingzhe Change-Id: I013783e6774661a67726a11ea09b0413b921017e --- arch/arm64/include/asm/cputype.h | 4 ++-- arch/arm64/kernel/cpufeature.c | 2 +- arch/arm64/kernel/proton-pack.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index a51c5ae081..9cf44f567f 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -149,7 +149,7 @@ #define MICROSOFT_CPU_PART_AZURE_COBALT_100 0xD49 /* Based on r0p0 of ARM Neoverse N2 */ -#define PHYTIUM_CPU_PART_FTC310 0x660 +#define PHYTIUM_CPU_PART_FTC303 0x303 #define PHYTIUM_CPU_PART_FTC660 0x660 #define PHYTIUM_CPU_PART_FTC661 0x661 #define PHYTIUM_CPU_PART_FTC662 0x662 @@ -223,7 +223,7 @@ #define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) #define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1) -#define MIDR_PHYTIUM_FTC310 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC310) +#define MIDR_PHYTIUM_FTC303 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC303) #define MIDR_PHYTIUM_FTC660 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC660) #define MIDR_PHYTIUM_FTC661 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC661) #define MIDR_PHYTIUM_PS17064 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC662) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index cc55214d4d..6355818501 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1686,7 +1686,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), MIDR_ALL_VERSIONS(MIDR_HISI_TSV110), MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL), - MIDR_ALL_VERSIONS(MIDR_PHYTIUM_FTC310), + MIDR_ALL_VERSIONS(MIDR_PHYTIUM_FTC303), MIDR_ALL_VERSIONS(MIDR_PHYTIUM_FTC660), MIDR_ALL_VERSIONS(MIDR_PHYTIUM_FTC661), MIDR_ALL_VERSIONS(MIDR_PHYTIUM_PS17064), diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index 19b1fa4acd..acce23aca1 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -160,7 +160,7 @@ static enum mitigation_state spectre_v2_get_cpu_hw_mitigation_state(void) MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), MIDR_ALL_VERSIONS(MIDR_HISI_TSV110), - MIDR_ALL_VERSIONS(MIDR_PHYTIUM_FTC310), + MIDR_ALL_VERSIONS(MIDR_PHYTIUM_FTC303), MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_SILVER), MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER), MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER), @@ -471,7 +471,7 @@ static enum mitigation_state spectre_v4_get_cpu_hw_mitigation_state(void) MIDR_ALL_VERSIONS(MIDR_CORTEX_A53), MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), - MIDR_ALL_VERSIONS(MIDR_PHYTIUM_FTC310), + MIDR_ALL_VERSIONS(MIDR_PHYTIUM_FTC303), MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER), MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER), { /* sentinel */ }, -- Gitee From 1ed603cd93296e432c6322f6fac2d968170eafd0 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 14:33:32 +0800 Subject: [PATCH 010/121] net/phytmac:Added high address check A maximum of three DMA ring addresses can be allocated, and check whether the high addresses in multiple queues are consistent after the address is assigned. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Ifd4d5c486341e1ed4cc1e433799bc53d15647f15 --- drivers/net/ethernet/phytium/phytmac_main.c | 103 ++++++++++++++------ 1 file changed, 74 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index c172103a97..07f8476946 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -46,6 +46,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); #define RX_BUFFER_MULTIPLE 64 /* bytes */ #define MAX_MTU 3072 #define RING_ADDR_INTERVAL 128 +#define MAX_RING_ADDR_ALLOC_TIMES 3 #define RX_RING_BYTES(pdata) (sizeof(struct phytmac_dma_desc) \ * (pdata)->rx_ring_size) @@ -60,6 +61,23 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); * space in the SRAM (16KB) even when there is. */ +static int phytmac_queue_phyaddr_check(struct phytmac *pdata, dma_addr_t ring_base_addr, + int offset) +{ + u32 bus_addr_high; + int i; + + /* Check the high address of the DMA ring. */ + bus_addr_high = upper_32_bits(ring_base_addr); + for (i = 1; i < pdata->queues_num; i++) { + ring_base_addr += offset; + if (bus_addr_high != upper_32_bits(ring_base_addr)) + return -EFAULT; + } + + return 0; +} + static int phytmac_change_mtu(struct net_device *ndev, int new_mtu) { if (netif_running(ndev)) @@ -176,7 +194,6 @@ static int phytmac_mdio_write_c45(struct mii_bus *bus, int mii_id, int devad, in return 0; } - static inline int hash_bit_value(int bitnr, __u8 *addr) { if (addr[bitnr / 8] & (1 << (bitnr % 8))) @@ -397,19 +414,36 @@ static int phytmac_alloc_tx_resource(struct phytmac *pdata) struct phytmac_dma_desc *tx_ring_base; dma_addr_t tx_ring_base_addr; unsigned int q; - int size; + int tx_offset; + int tx_size; + int size = 0; + int ret, i; + + tx_offset = TX_RING_BYTES(pdata) + pdata->tx_bd_prefetch + RING_ADDR_INTERVAL; + tx_size = pdata->queues_num * tx_offset; + for (i = 0; i < MAX_RING_ADDR_ALLOC_TIMES + 1; i++) { + if (i == MAX_RING_ADDR_ALLOC_TIMES) + goto err; + + tx_ring_base = dma_alloc_coherent(pdata->dev, tx_size, + &tx_ring_base_addr, GFP_KERNEL); + if (!tx_ring_base) + continue; - size = pdata->queues_num * (TX_RING_BYTES(pdata) + pdata->tx_bd_prefetch + - RING_ADDR_INTERVAL); - tx_ring_base = dma_alloc_coherent(pdata->dev, size, - &tx_ring_base_addr, GFP_KERNEL); - if (!tx_ring_base) - goto err; + ret = phytmac_queue_phyaddr_check(pdata, tx_ring_base_addr, + tx_offset); + if (ret) { + dma_free_coherent(pdata->dev, tx_size, tx_ring_base, + tx_ring_base_addr); + continue; + } else { + break; + } + } for (q = 0, queue = pdata->queues; q < pdata->queues_num; ++q, ++queue) { - size = TX_RING_BYTES(pdata) + pdata->tx_bd_prefetch + RING_ADDR_INTERVAL; - queue->tx_ring = (void *)tx_ring_base + q * size; - queue->tx_ring_addr = tx_ring_base_addr + q * size; + queue->tx_ring = (void *)tx_ring_base + q * tx_offset; + queue->tx_ring_addr = tx_ring_base_addr + q * tx_offset; if (!queue->tx_ring) goto err; @@ -428,7 +462,6 @@ static int phytmac_alloc_tx_resource(struct phytmac *pdata) "Allocated %d TX struct tx_skb entries at %p\n", pdata->tx_ring_size, queue->tx_skb); } - tx_ring_base = NULL; return 0; err: @@ -443,21 +476,37 @@ static int phytmac_alloc_rx_resource(struct phytmac *pdata) struct phytmac_hw_if *hw_if = pdata->hw_if; struct phytmac_dma_desc *rx_ring_base; dma_addr_t rx_ring_base_addr; + int rx_offset; + int rx_size; unsigned int q; - int size; - int i; + int size = 0; + int ret, i; - size = pdata->queues_num * (RX_RING_BYTES(pdata) + pdata->rx_bd_prefetch + - RING_ADDR_INTERVAL); - rx_ring_base = dma_alloc_coherent(pdata->dev, size, - &rx_ring_base_addr, GFP_KERNEL); - if (!rx_ring_base) - goto err; + rx_offset = RX_RING_BYTES(pdata) + pdata->rx_bd_prefetch + RING_ADDR_INTERVAL; + rx_size = pdata->queues_num * rx_offset; + for (i = 0; i < MAX_RING_ADDR_ALLOC_TIMES + 1; i++) { + if (i == MAX_RING_ADDR_ALLOC_TIMES) + goto err; + + rx_ring_base = dma_alloc_coherent(pdata->dev, rx_size, + &rx_ring_base_addr, GFP_KERNEL); + if (!rx_ring_base) + continue; + + ret = phytmac_queue_phyaddr_check(pdata, rx_ring_base_addr, + rx_offset); + if (ret) { + dma_free_coherent(pdata->dev, rx_size, rx_ring_base, + rx_ring_base_addr); + continue; + } else { + break; + } + } for (q = 0, queue = pdata->queues; q < pdata->queues_num; ++q, ++queue) { - size = RX_RING_BYTES(pdata) + pdata->rx_bd_prefetch + RING_ADDR_INTERVAL; - queue->rx_ring = (void *)rx_ring_base + q * size; - queue->rx_ring_addr = rx_ring_base_addr + q * size; + queue->rx_ring = (void *)rx_ring_base + q * rx_offset; + queue->rx_ring_addr = rx_ring_base_addr + q * rx_offset; if (!queue->rx_ring) goto err; @@ -479,7 +528,6 @@ static int phytmac_alloc_rx_resource(struct phytmac *pdata) "Allocated %d RX struct sk_buff entries at %p\n", pdata->rx_ring_size, queue->rx_skb); } - rx_ring_base = NULL; return 0; err: @@ -763,7 +811,7 @@ static void phytmac_rx_clean(struct phytmac_queue *queue) } paddr = dma_map_single(pdata->dev, skb->data, - pdata->rx_buffer_len, DMA_FROM_DEVICE); + pdata->rx_buffer_len, DMA_FROM_DEVICE); if (dma_mapping_error(pdata->dev, paddr)) { dev_kfree_skb(skb); break; @@ -1368,14 +1416,12 @@ void phytmac_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, phy_modes(interface), speed, duplex); hw_if->pcs_linkup(pdata, interface, speed, duplex); } - static const struct phylink_pcs_ops phytmac_pcs_phylink_ops = { .pcs_config = phytmac_pcs_config, .pcs_link_up = phytmac_pcs_link_up, }; - static struct phylink_pcs *phytmac_mac_select_pcs(struct phylink_config *config, - phy_interface_t interface) + phy_interface_t interface) { struct phytmac *pdata = netdev_priv(to_net_dev(config->dev)); @@ -1391,7 +1437,6 @@ static struct phylink_pcs *phytmac_mac_select_pcs(struct phylink_config *config, return &pdata->phylink_pcs; } - static void phytmac_mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state) { -- Gitee From 6848fd7516a4ab90e013a42513bb8c8b6a8b6cf8 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 14:52:58 +0800 Subject: [PATCH 011/121] net/phytmac: Adjust the code style Fix spelling mistakes and replace the default value with a macro definition. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Icc51d45f0fb10eb8dad8aad59f839f2c0406653c --- drivers/net/ethernet/phytium/phytmac_main.c | 4 +++- drivers/net/ethernet/phytium/phytmac_v1.c | 4 ++-- drivers/net/ethernet/phytium/phytmac_v1.h | 8 ++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index 07f8476946..ca1a03fa35 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -1416,10 +1416,12 @@ void phytmac_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, phy_modes(interface), speed, duplex); hw_if->pcs_linkup(pdata, interface, speed, duplex); } + static const struct phylink_pcs_ops phytmac_pcs_phylink_ops = { .pcs_config = phytmac_pcs_config, .pcs_link_up = phytmac_pcs_link_up, }; + static struct phylink_pcs *phytmac_mac_select_pcs(struct phylink_config *config, phy_interface_t interface) { @@ -1766,7 +1768,7 @@ static int phytmac_open(struct net_device *ndev) ret = phytmac_phylink_connect(pdata); if (ret) { - netdev_err(ndev, "phylink connet failed,(error %d)\n", + netdev_err(ndev, "phylink connect failed,(error %d)\n", ret); goto reset_hw; } diff --git a/drivers/net/ethernet/phytium/phytmac_v1.c b/drivers/net/ethernet/phytium/phytmac_v1.c index ec95c6c79b..4a690b6a96 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.c +++ b/drivers/net/ethernet/phytium/phytmac_v1.c @@ -414,7 +414,7 @@ static int phytmac_init_hw(struct phytmac *pdata) PHYTMAC_WRITE(pdata, PHYTMAC_DCONFIG, dmaconfig); if (pdata->capacities & PHYTMAC_CAPS_TAILPTR) - PHYTMAC_WRITE(pdata, PHYTMAC_TAIL_ENABLE, 0x80000001); + PHYTMAC_WRITE(pdata, PHYTMAC_TAIL_ENABLE, PHYTMAC_BIT(TXTAIL_ENABLE)); if (phy_interface_mode_is_8023z(pdata->phy_interface)) phytmac_pcs_software_reset(pdata, 1); @@ -945,7 +945,7 @@ static void phytmac_tx_start(struct phytmac_queue *queue) if (pdata->capacities & PHYTMAC_CAPS_TAILPTR) PHYTMAC_WRITE(pdata, PHYTMAC_TAILPTR(queue->index), - BIT(31) | queue->tx_tail); + PHYTMAC_BIT(TXTAIL_UPDATE) | queue->tx_tail); if (pdata->capacities & PHYTMAC_CAPS_START) PHYTMAC_WRITE(pdata, PHYTMAC_NCTRL, diff --git a/drivers/net/ethernet/phytium/phytmac_v1.h b/drivers/net/ethernet/phytium/phytmac_v1.h index d8de2c26ca..2cabadfed2 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.h +++ b/drivers/net/ethernet/phytium/phytmac_v1.h @@ -356,6 +356,14 @@ extern struct phytmac_hw_if phytmac_1p0_hw; #define PHYTMAC_VLAN_ID_INDEX 10 #define PHYTMAC_VLAN_ID_WIDTH 1 +/* Bitfields in TAILPTR */ +#define PHYTMAC_TXTAIL_UPDATE_INDEX 31 /* Update tx tail */ +#define PHYTMAC_TXTAIL_UPDATE_WIDTH 1 + +/* Bitfields in TAIL_ENABLE */ +#define PHYTMAC_TXTAIL_ENABLE_INDEX 0 /* Enable tx tail */ +#define PHYTMAC_TXTAIL_ENABLE_WIDTH 1 + #define PHYTMAC_TSEC_WIDTH (PHYTMAC_SECH_WIDTH + PHYTMAC_SECL_WIDTH) #define SEC_MAX_VAL (((u64)1 << PHYTMAC_TSEC_WIDTH) - 1) #define NSEC_MAX_VAL ((1 << PHYTMAC_NSEC_WIDTH) - 1) -- Gitee From 66403a1703bf00c249e081103f7efbc2867c53bc Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 14:55:39 +0800 Subject: [PATCH 012/121] net/phytmac: Get device type error fixed We should return -EOPNOTSUPP to the unsupported device types, otherwise the wireless attribute will be added by default. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Ie0522ed5c744ddc885ab633dac5ecc9661c580f2 --- drivers/net/ethernet/phytium/phytmac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index ca1a03fa35..058f9647b8 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -1843,7 +1843,7 @@ static int phytmac_close(struct net_device *ndev) static int phytmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct phytmac *pdata = netdev_priv(dev); - int ret; + int ret = -EOPNOTSUPP; if (!netif_running(dev)) return -EINVAL; -- Gitee From a728bf473513902c773a61d68ea35a1dd08c39d6 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 14:57:15 +0800 Subject: [PATCH 013/121] net/phytmac: Modify the method of obtaining the link status Firstly, modify the state of pdata->speed and pdata->duplex to be obtained in the phytmac_mac_config. Secondly, the base.speed and base.duplex in the phytmac_get_link_ ksettings were changed from the default values to pdata. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Ifda2028cfd32381f97b57ad1a46f0861c0c21105 --- .../net/ethernet/phytium/phytmac_ethtool.c | 45 +++++++------------ drivers/net/ethernet/phytium/phytmac_pci.c | 2 +- drivers/net/ethernet/phytium/phytmac_v2.c | 1 + 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac_ethtool.c b/drivers/net/ethernet/phytium/phytmac_ethtool.c index 592d2d9dc6..7cddb01802 100644 --- a/drivers/net/ethernet/phytium/phytmac_ethtool.c +++ b/drivers/net/ethernet/phytium/phytmac_ethtool.c @@ -382,43 +382,32 @@ static int phytmac_get_link_ksettings(struct net_device *ndev, u32 advertising = 0; if (!ndev->phydev) { + kset->base.port = PORT_FIBRE; + kset->base.transceiver = XCVR_INTERNAL; + kset->base.duplex = pdata->duplex; + kset->base.speed = pdata->speed; + if (pdata->phy_interface == PHY_INTERFACE_MODE_USXGMII || pdata->phy_interface == PHY_INTERFACE_MODE_10GBASER) { supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE | SUPPORTED_Pause; advertising = ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE | ADVERTISED_Pause; - kset->base.port = PORT_FIBRE; - kset->base.transceiver = XCVR_INTERNAL; - kset->base.duplex = DUPLEX_FULL; - kset->base.speed = SPEED_10000; } else if (pdata->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { - supported = SUPPORTED_2500baseX_Full | SUPPORTED_Pause; - advertising = ADVERTISED_2500baseX_Full | ADVERTISED_Pause; - kset->base.port = PORT_FIBRE; - kset->base.transceiver = XCVR_INTERNAL; - kset->base.duplex = DUPLEX_FULL; - kset->base.speed = SPEED_2500; + supported = SUPPORTED_2500baseX_Full + | SUPPORTED_FIBRE | SUPPORTED_Pause; + advertising = ADVERTISED_2500baseX_Full + | ADVERTISED_FIBRE | ADVERTISED_Pause; } else if (pdata->phy_interface == PHY_INTERFACE_MODE_1000BASEX) { - supported = SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full - | SUPPORTED_10baseT_Full | SUPPORTED_FIBRE - | SUPPORTED_Pause; - advertising = ADVERTISED_1000baseT_Full | ADVERTISED_100baseT_Full - | ADVERTISED_10baseT_Full | ADVERTISED_FIBRE - | ADVERTISED_Pause; - kset->base.port = PORT_FIBRE; - kset->base.transceiver = XCVR_INTERNAL; - kset->base.duplex = DUPLEX_FULL; - kset->base.speed = SPEED_100; + supported = SUPPORTED_1000baseT_Full + | SUPPORTED_FIBRE | SUPPORTED_Pause; + advertising = ADVERTISED_1000baseT_Full + | ADVERTISED_FIBRE | ADVERTISED_Pause; } else if (pdata->phy_interface == PHY_INTERFACE_MODE_SGMII) { - supported = SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full - | SUPPORTED_10baseT_Full | SUPPORTED_FIBRE | SUPPORTED_Pause; - advertising = ADVERTISED_1000baseT_Full | ADVERTISED_100baseT_Full - | ADVERTISED_10baseT_Full | ADVERTISED_FIBRE | ADVERTISED_Pause; - kset->base.port = PORT_FIBRE; - kset->base.transceiver = XCVR_INTERNAL; - kset->base.duplex = DUPLEX_FULL; - kset->base.speed = SPEED_1000; + supported = SUPPORTED_1000baseT_Full + | SUPPORTED_FIBRE | SUPPORTED_Pause; + advertising = ADVERTISED_1000baseT_Full + | ADVERTISED_FIBRE | ADVERTISED_Pause; } ethtool_convert_legacy_u32_to_link_mode(kset->link_modes.supported, diff --git a/drivers/net/ethernet/phytium/phytmac_pci.c b/drivers/net/ethernet/phytium/phytmac_pci.c index fd21bf80f1..af69329fe0 100644 --- a/drivers/net/ethernet/phytium/phytmac_pci.c +++ b/drivers/net/ethernet/phytium/phytmac_pci.c @@ -225,7 +225,7 @@ struct phytmac_data phytmac_1000basex = { .use_mii = false, .speed = 1000, .duplex = true, - .interface = PHY_INTERFACE_MODE_SGMII, + .interface = PHY_INTERFACE_MODE_1000BASEX, .properties = fl_properties[0], }; diff --git a/drivers/net/ethernet/phytium/phytmac_v2.c b/drivers/net/ethernet/phytium/phytmac_v2.c index df142aa679..41e5df4122 100644 --- a/drivers/net/ethernet/phytium/phytmac_v2.c +++ b/drivers/net/ethernet/phytium/phytmac_v2.c @@ -842,6 +842,7 @@ static int phytmac_pcs_linkdown(struct phytmac *pdata) static unsigned int phytmac_pcs_get_link(struct phytmac *pdata, phy_interface_t interface) { if (interface == PHY_INTERFACE_MODE_SGMII || + interface == PHY_INTERFACE_MODE_1000BASEX || interface == PHY_INTERFACE_MODE_2500BASEX) return PHYTMAC_READ_BITS(pdata, PHYTMAC_NETWORK_STATUS, LINK); else if (interface == PHY_INTERFACE_MODE_USXGMII || -- Gitee From 11ba74ddc3fcd568a41284b08ff69a86809e38fa Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 15:02:13 +0800 Subject: [PATCH 014/121] net/phytmac: Support usxgmii wol feature Support usxgmii wol by change the value of registers, including wol register, int register, net config register and spec_add1 register. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Ie651779a4bc2487aaaa51b24c69a5cc9d8de3784 --- drivers/net/ethernet/phytium/phytmac_main.c | 12 ++++++------ drivers/net/ethernet/phytium/phytmac_v1.c | 9 +++++++++ drivers/net/ethernet/phytium/phytmac_v1.h | 11 +++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index 058f9647b8..28b6dc86f6 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -1732,12 +1732,6 @@ static int phytmac_open(struct net_device *ndev) hw_if->reset_hw(pdata); - ret = phytmac_get_mac_address(pdata); - if (ret) { - netdev_err(ndev, "phytmac get mac address failed\n"); - goto reset_hw; - } - ret = netif_set_real_num_tx_queues(ndev, pdata->queues_num); if (ret) { netdev_err(ndev, "error setting real tx queue number\n"); @@ -2123,6 +2117,12 @@ int phytmac_drv_probe(struct phytmac *pdata) goto err_phylink_init; } + ret = phytmac_get_mac_address(pdata); + if (ret) { + netdev_err(ndev, "phytmac get mac address failed\n"); + goto err_phylink_init; + } + if (netif_msg_probe(pdata)) dev_dbg(pdata->dev, "probe successfully! Phytium %s at 0x%08lx irq %d (%pM)\n", "MAC", ndev->base_addr, ndev->irq, ndev->dev_addr); diff --git a/drivers/net/ethernet/phytium/phytmac_v1.c b/drivers/net/ethernet/phytium/phytmac_v1.c index 4a690b6a96..b96547e54d 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.c +++ b/drivers/net/ethernet/phytium/phytmac_v1.c @@ -489,6 +489,15 @@ static int phytmac_set_wake(struct phytmac *pdata, int wake) value |= PHYTMAC_BIT(MCAST); PHYTMAC_WRITE(pdata, PHYTMAC_WOL, value); + if (wake) { + PHYTMAC_WRITE(pdata, PHYTMAC_IE, PHYTMAC_BIT(WOL_RECEIVE_ENABLE)); + value = PHYTMAC_READ(pdata, PHYTMAC_NCONFIG) | PHYTMAC_BIT(IGNORE_RX_FCS); + PHYTMAC_WRITE(pdata, PHYTMAC_NCONFIG, value); + } else { + PHYTMAC_WRITE(pdata, PHYTMAC_ID, PHYTMAC_BIT(WOL_RECEIVE_DISABLE)); + value = PHYTMAC_READ(pdata, PHYTMAC_NCONFIG) & ~PHYTMAC_BIT(IGNORE_RX_FCS); + PHYTMAC_WRITE(pdata, PHYTMAC_NCONFIG, value); + } return 0; } diff --git a/drivers/net/ethernet/phytium/phytmac_v1.h b/drivers/net/ethernet/phytium/phytmac_v1.h index 2cabadfed2..1f49d4ec79 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.h +++ b/drivers/net/ethernet/phytium/phytmac_v1.h @@ -140,6 +140,8 @@ extern struct phytmac_hw_if phytmac_1p0_hw; #define PHYTMAC_DBW_128 4 #define PHYTMAC_RCO_EN_INDEX 24 /* Receive checksum offload enable */ #define PHYTMAC_RCO_EN_WIDTH 1 +#define PHYTMAC_IGNORE_RX_FCS_INDEX 26 +#define PHYTMAC_IGNORE_RX_FCS_WIDTH 1 #define PHYTMAC_SGMII_EN_INDEX 27 /* Sgmii mode enable */ #define PHYTMAC_SGMII_EN_WIDTH 1 @@ -364,6 +366,15 @@ extern struct phytmac_hw_if phytmac_1p0_hw; #define PHYTMAC_TXTAIL_ENABLE_INDEX 0 /* Enable tx tail */ #define PHYTMAC_TXTAIL_ENABLE_WIDTH 1 +/* Bitfields in INT ENABLE */ +#define PHYTMAC_WOL_RECEIVE_ENABLE_INDEX 28 /* Enable wol_event_recieve */ +#define PHYTMAC_WOL_RECEIVE_ENABLE_WIDTH 1 + +/* Bitfields in INT DISABLE */ +#define PHYTMAC_WOL_RECEIVE_DISABLE_INDEX 28 /* Disable wol_event_recieve */ +#define PHYTMAC_WOL_RECEIVE_DISABLE_WIDTH 1 + + #define PHYTMAC_TSEC_WIDTH (PHYTMAC_SECH_WIDTH + PHYTMAC_SECL_WIDTH) #define SEC_MAX_VAL (((u64)1 << PHYTMAC_TSEC_WIDTH) - 1) #define NSEC_MAX_VAL ((1 << PHYTMAC_NSEC_WIDTH) - 1) -- Gitee From 1040f4e7b52143571a6fa9e85e13cd0c1642aafc Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 15:04:49 +0800 Subject: [PATCH 015/121] net/phytmac: Roll back rx_clean version Roll back rx_clean version to not use batching. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Ie6e7585304ac6a7b9101e04c5af5219b3a361996 --- drivers/net/ethernet/phytium/phytmac.h | 2 -- drivers/net/ethernet/phytium/phytmac_main.c | 24 ++++++++------------- drivers/net/ethernet/phytium/phytmac_v1.c | 23 ++++++-------------- 3 files changed, 16 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h index b90e155149..33c0fc7841 100644 --- a/drivers/net/ethernet/phytium/phytmac.h +++ b/drivers/net/ethernet/phytium/phytmac.h @@ -38,7 +38,6 @@ #define MIN_TX_RING_SIZE 64 #define MIN_RX_RING_SIZE 64 #define DEFAULT_TX_DESC_MIN_FREE 64 -#define DEFAULT_RX_DESC_MIN_FREE 64 #define MEMORY_SIZE 4096 #define MHU_SIZE 0x20 @@ -499,7 +498,6 @@ struct phytmac_hw_if { struct packet_info *packet); void (*init_rx_map)(struct phytmac_queue *queue, u32 index); unsigned int (*rx_map)(struct phytmac_queue *queue, u32 index, dma_addr_t addr); - unsigned int (*rx_clean)(struct phytmac_queue *queue, u32 cleaned_count); void (*transmit)(struct phytmac_queue *queue); void (*restart)(struct phytmac *pdata); int (*tx_complete)(const struct phytmac_dma_desc *desc); diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index 28b6dc86f6..0053412c26 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -793,16 +793,12 @@ static void phytmac_rx_clean(struct phytmac_queue *queue) unsigned int index, space; dma_addr_t paddr; struct sk_buff *skb; - unsigned int rx_unclean = 0; space = CIRC_SPACE(queue->rx_head, queue->rx_tail, pdata->rx_ring_size); - if (space < DEFAULT_RX_DESC_MIN_FREE) - return; - - index = queue->rx_head & (pdata->rx_ring_size - 1); while (space > 0) { + index = queue->rx_head & (pdata->rx_ring_size - 1); if (!queue->rx_skb[index]) { skb = netdev_alloc_skb(pdata->ndev, pdata->rx_buffer_len); if (unlikely(!skb)) { @@ -811,7 +807,7 @@ static void phytmac_rx_clean(struct phytmac_queue *queue) } paddr = dma_map_single(pdata->dev, skb->data, - pdata->rx_buffer_len, DMA_FROM_DEVICE); + pdata->rx_buffer_len, DMA_FROM_DEVICE); if (dma_mapping_error(pdata->dev, paddr)) { dev_kfree_skb(skb); break; @@ -820,21 +816,19 @@ static void phytmac_rx_clean(struct phytmac_queue *queue) queue->rx_skb[index] = skb; hw_if->rx_map(queue, index, paddr); + } else { + hw_if->rx_map(queue, index, 0); } - index = (index + 1) & (pdata->rx_ring_size - 1); - rx_unclean++; + queue->rx_head++; + if (queue->rx_head >= pdata->rx_ring_size) + queue->rx_head &= (pdata->rx_ring_size - 1); + space--; } /* make newly descriptor to hardware */ wmb(); - hw_if->rx_clean(queue, rx_unclean); - /* make newly descriptor to hardware */ - wmb(); - queue->rx_head += rx_unclean; - if (queue->rx_head >= pdata->rx_ring_size) - queue->rx_head &= (pdata->rx_ring_size - 1); } static int phytmac_rx(struct phytmac_queue *queue, struct napi_struct *napi, @@ -1203,7 +1197,7 @@ static unsigned int phytmac_tx_map(struct phytmac *pdata, { dma_addr_t mapping; struct phytmac_hw_if *hw_if = pdata->hw_if; - unsigned int len, i, tx_tail = queue->tx_tail; + unsigned int len, i, tx_tail; struct phytmac_tx_skb *tx_skb = NULL; unsigned int offset, size, count = 0; unsigned int f, nr_frags = skb_shinfo(skb)->nr_frags; diff --git a/drivers/net/ethernet/phytium/phytmac_v1.c b/drivers/net/ethernet/phytium/phytmac_v1.c index b96547e54d..b823a07a73 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.c +++ b/drivers/net/ethernet/phytium/phytmac_v1.c @@ -927,22 +927,14 @@ static unsigned int phytmac_rx_map_desc(struct phytmac_queue *queue, addr |= PHYTMAC_BIT(RX_WRAP); desc->desc1 = 0; desc->desc2 = upper_32_bits(addr); - desc->desc0 = lower_32_bits(addr) | PHYTMAC_BIT(RX_USED); - } - return 0; -} - -static unsigned int phytmac_rx_clean_desc(struct phytmac_queue *queue, u32 count) -{ - struct phytmac_dma_desc *desc; - u32 index = queue->rx_head + count - 1; - - while (count) { - desc = phytmac_get_rx_desc(queue, index); - desc->desc0 &= ~PHYTMAC_BIT(RX_USED); + /* Make newly descriptor to hardware */ + dma_wmb(); + desc->desc0 = lower_32_bits(addr); + } else { + desc->desc1 = 0; + /* Make newly descriptor to hardware */ dma_wmb(); - index--; - count--; + desc->desc0 &= ~PHYTMAC_BIT(RX_USED); } return 0; @@ -1386,7 +1378,6 @@ struct phytmac_hw_if phytmac_1p0_hw = { .get_desc_addr = phytmac_get_desc_addr, .init_rx_map = phytmac_init_rx_map_desc, .rx_map = phytmac_rx_map_desc, - .rx_clean = phytmac_rx_clean_desc, .rx_checksum = phytmac_rx_checksum, .rx_single_buffer = phytmac_rx_single_buffer, .rx_pkt_start = phytmac_rx_sof, -- Gitee From bb1fd376f46bcf15d08af0210af4b45ca5990fcb Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 15:09:08 +0800 Subject: [PATCH 016/121] net/phytmac: Override rx_skb allocation function Changing the way netdev_alloc_skb function assigns SKB directly, so that MAC driver alloc pages in advance and build SKB in the phytmac RX function. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Ia765cea707d97a212ab9864c139a6198668c8604 --- drivers/net/ethernet/phytium/phytmac.h | 24 +- drivers/net/ethernet/phytium/phytmac_main.c | 432 +++++++++++++++----- drivers/net/ethernet/phytium/phytmac_v1.c | 11 - drivers/net/ethernet/phytium/phytmac_v2.c | 11 - 4 files changed, 341 insertions(+), 137 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h index 33c0fc7841..363bc65c72 100644 --- a/drivers/net/ethernet/phytium/phytmac.h +++ b/drivers/net/ethernet/phytium/phytmac.h @@ -307,6 +307,13 @@ struct phytmac_tx_ts { u32 ts_2; }; +struct phytmac_rx_buffer { + dma_addr_t addr; + struct page *page; + __u16 page_offset; + __u16 pagecnt_bias; +}; + struct phytmac_queue { struct phytmac *pdata; int irq; @@ -328,8 +335,9 @@ struct phytmac_queue { dma_addr_t rx_ring_addr; unsigned int rx_head; unsigned int rx_tail; + unsigned int rx_next_to_alloc; struct phytmac_dma_desc *rx_ring; - struct sk_buff **rx_skb; + struct phytmac_rx_buffer *rx_buffer_info; struct napi_struct rx_napi; struct phytmac_queue_stats stats; @@ -503,7 +511,6 @@ struct phytmac_hw_if { int (*tx_complete)(const struct phytmac_dma_desc *desc); int (*rx_complete)(const struct phytmac_dma_desc *desc); int (*get_rx_pkt_len)(struct phytmac *pdata, const struct phytmac_dma_desc *desc); - dma_addr_t (*get_desc_addr)(const struct phytmac_dma_desc *desc); bool (*rx_checksum)(const struct phytmac_dma_desc *desc); void (*set_desc_rxused)(struct phytmac_dma_desc *desc); bool (*rx_single_buffer)(const struct phytmac_dma_desc *desc); @@ -572,6 +579,19 @@ struct phytmac_hw_if { #define PHYTMAC_READ_DATA0(pdata) PHYTMAC_MHU_READ(pdata, PHYTMAC_MHU_CPP_DATA0) #define PHYTMAC_TIMEOUT 1000000000 /* in usecs */ +#define PHYTMAC_GFP_FLAGS \ + (GFP_ATOMIC | __GFP_NOWARN | GFP_DMA | __GFP_DMA32) +#define PHYTMAC_RX_DMA_ATTR \ + (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING) +#define PHYTMAC_SKB_PAD (NET_SKB_PAD) + +#define PHYTMAC_RXBUFFER_2048 2048 +#define PHYTMAC_MAX_FRAME_BUILD_SKB \ + (SKB_WITH_OVERHEAD(PHYTMAC_RXBUFFER_2048) - PHYTMAC_SKB_PAD) + +#define PHYTMAC_RX_PAGE_ORDER 0 +#define PHYTMAC_RX_PAGE_SIZE (PAGE_SIZE << PHYTMAC_RX_PAGE_ORDER) + struct phytmac_tx_skb *phytmac_get_tx_skb(struct phytmac_queue *queue, unsigned int index); inline struct phytmac_dma_desc *phytmac_get_tx_desc(struct phytmac_queue *queue, diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index 0053412c26..a2b3ed84e8 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include "phytmac.h" #include "phytmac_ptp.h" @@ -293,15 +295,12 @@ static struct net_device_stats *phytmac_get_stats(struct net_device *dev) return nstat; } -static int phytmac_calc_rx_buf_len(struct phytmac *pdata, u32 mtu) +static inline int phytmac_calc_rx_buf_len(void) { - unsigned int size = mtu + ETH_HLEN + ETH_FCS_LEN; - int rx_buf_len = roundup(size, RX_BUFFER_MULTIPLE); - - netdev_dbg(pdata->ndev, "mtu [%u] rx_buffer_size [%u]\n", - mtu, rx_buf_len); - - return rx_buf_len; +#if (PAGE_SIZE < 8192) + return PHYTMAC_MAX_FRAME_BUILD_SKB; +#endif + return PHYTMAC_RXBUFFER_2048; } inline struct phytmac_dma_desc *phytmac_get_rx_desc(struct phytmac_queue *queue, @@ -310,12 +309,6 @@ inline struct phytmac_dma_desc *phytmac_get_rx_desc(struct phytmac_queue *queue, return &queue->rx_ring[index & (queue->pdata->rx_ring_size - 1)]; } -struct sk_buff *phytmac_get_rx_skb(struct phytmac_queue *queue, - unsigned int index) -{ - return queue->rx_skb[index & (queue->pdata->rx_ring_size - 1)]; -} - struct phytmac_tx_skb *phytmac_get_tx_skb(struct phytmac_queue *queue, unsigned int index) { @@ -328,6 +321,49 @@ inline struct phytmac_dma_desc *phytmac_get_tx_desc(struct phytmac_queue *queue, return &queue->tx_ring[index & (queue->pdata->tx_ring_size - 1)]; } +static void phytmac_rx_unmap(struct phytmac_queue *queue) +{ + struct phytmac_rx_buffer *rx_buffer_info; + struct phytmac *pdata = queue->pdata; + int i; + + if (queue->rx_buffer_info) { + /* Free all the Rx ring sk_buffs */ + i = queue->rx_tail; + + while (i != queue->rx_next_to_alloc) { + rx_buffer_info = &queue->rx_buffer_info[i]; + + /* Invalidate cache lines that may have been written to by + * device so that we avoid corrupting memory. + */ + dma_sync_single_range_for_cpu(pdata->dev, + rx_buffer_info->addr, + rx_buffer_info->page_offset, + pdata->rx_buffer_len, + DMA_FROM_DEVICE); + + /* free resources associated with mapping */ + dma_unmap_page_attrs(pdata->dev, + rx_buffer_info->addr, + PHYTMAC_RX_PAGE_SIZE, + DMA_FROM_DEVICE, + PHYTMAC_RX_DMA_ATTR); + + __page_frag_cache_drain(rx_buffer_info->page, + rx_buffer_info->pagecnt_bias); + + i++; + if (i == pdata->rx_ring_size) + i = 0; + } + + queue->rx_tail = 0; + queue->rx_head = 0; + queue->rx_next_to_alloc = 0; + } +} + static int phytmac_free_tx_resource(struct phytmac *pdata) { struct phytmac_queue *queue; @@ -362,14 +398,10 @@ static int phytmac_free_tx_resource(struct phytmac *pdata) static int phytmac_free_rx_resource(struct phytmac *pdata) { struct phytmac_queue *queue; - struct sk_buff *skb; - struct phytmac_dma_desc *desc; - struct phytmac_hw_if *hw_if = pdata->hw_if; struct phytmac_dma_desc *rx_ring_base = NULL; dma_addr_t rx_ring_base_addr; - dma_addr_t addr; unsigned int q; - int size, i; + int size; queue = pdata->queues; if (queue->rx_ring) { @@ -378,25 +410,15 @@ static int phytmac_free_rx_resource(struct phytmac *pdata) } for (q = 0, queue = pdata->queues; q < pdata->queues_num; ++q, ++queue) { - if (queue->rx_skb) { - for (i = 0; i < pdata->rx_ring_size; i++) { - skb = phytmac_get_rx_skb(queue, i); - if (skb) { - desc = &queue->rx_ring[i]; - addr = hw_if->get_desc_addr(desc); - dma_unmap_single(pdata->dev, addr, pdata->rx_buffer_len, - DMA_FROM_DEVICE); - dev_kfree_skb_any(skb); - skb = NULL; - } - } - - kfree(queue->rx_skb); - queue->rx_skb = NULL; - } + phytmac_rx_unmap(queue); if (queue->rx_ring) queue->rx_ring = NULL; + + if (queue->rx_buffer_info) { + vfree(queue->rx_buffer_info); + queue->rx_buffer_info = NULL; + } } if (rx_ring_base) { @@ -450,7 +472,7 @@ static int phytmac_alloc_tx_resource(struct phytmac *pdata) if (netif_msg_drv(pdata)) netdev_info(pdata->ndev, "Allocated TX ring for queue %u of %d bytes at %08lx\n", - q, size, (unsigned long)queue->tx_ring_addr); + q, tx_offset, (unsigned long)queue->tx_ring_addr); size = pdata->tx_ring_size * sizeof(struct phytmac_tx_skb); queue->tx_skb = kzalloc(size, GFP_KERNEL); @@ -473,7 +495,6 @@ static int phytmac_alloc_tx_resource(struct phytmac *pdata) static int phytmac_alloc_rx_resource(struct phytmac *pdata) { struct phytmac_queue *queue; - struct phytmac_hw_if *hw_if = pdata->hw_if; struct phytmac_dma_desc *rx_ring_base; dma_addr_t rx_ring_base_addr; int rx_offset; @@ -513,20 +534,12 @@ static int phytmac_alloc_rx_resource(struct phytmac *pdata) if (netif_msg_drv(pdata)) netdev_info(pdata->ndev, "Allocated RX ring for queue %u of %d bytes at %08lx\n", - q, size, (unsigned long)queue->rx_ring_addr); + q, rx_offset, (unsigned long)queue->rx_ring_addr); - for (i = 0; i < pdata->rx_ring_size; i++) - hw_if->init_rx_map(queue, i); - - size = pdata->rx_ring_size * sizeof(struct sk_buff *); - queue->rx_skb = kzalloc(size, GFP_KERNEL); - if (!queue->rx_skb) + size = pdata->rx_ring_size * sizeof(struct phytmac_rx_buffer); + queue->rx_buffer_info = vzalloc(size); + if (!queue->rx_buffer_info) goto err; - - if (netif_msg_drv(pdata)) - netdev_info(pdata->ndev, - "Allocated %d RX struct sk_buff entries at %p\n", - pdata->rx_ring_size, queue->rx_skb); } return 0; @@ -538,10 +551,9 @@ static int phytmac_alloc_rx_resource(struct phytmac *pdata) static int phytmac_alloc_resource(struct phytmac *pdata) { - struct net_device *ndev = pdata->ndev; int ret; - pdata->rx_buffer_len = phytmac_calc_rx_buf_len(pdata, ndev->mtu); + pdata->rx_buffer_len = phytmac_calc_rx_buf_len(); if (netif_msg_drv(pdata)) netdev_info(pdata->ndev, "alloc resource, rx_buffer_len = %d\n", @@ -652,30 +664,226 @@ static void phytmac_dump_pkt(struct phytmac *pdata, struct sk_buff *skb, bool tx skb->data, skb->len, true); } +static bool phytmac_alloc_mapped_page(struct phytmac *pdata, + struct phytmac_rx_buffer *bi) +{ + struct page *page = bi->page; + dma_addr_t dma; + + /* since we are recycling buffers we should seldom need to alloc */ + if (likely(page)) + return true; + + /* alloc new page for storage */ + page = __dev_alloc_pages(PHYTMAC_GFP_FLAGS, PHYTMAC_RX_PAGE_ORDER); + if (unlikely(!page)) { + netdev_err(pdata->ndev, "rx alloc page failed\n"); + return false; + } + + /* map page for use */ + dma = dma_map_page_attrs(pdata->dev, page, 0, + PHYTMAC_RX_PAGE_SIZE, + DMA_FROM_DEVICE, PHYTMAC_RX_DMA_ATTR); + if (dma_mapping_error(pdata->dev, dma)) { + __free_pages(page, PHYTMAC_RX_PAGE_ORDER); + return false; + } + + bi->addr = dma; + bi->page = page; + bi->page_offset = PHYTMAC_SKB_PAD; + bi->pagecnt_bias = 1; + + return true; +} + +static inline bool phytmac_page_is_reserved(struct page *page) +{ + return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page); +} + +static bool phytmac_can_reuse_rx_page(struct phytmac_rx_buffer *rx_buffer) +{ + unsigned int pagecnt_bias = rx_buffer->pagecnt_bias; + struct page *page = rx_buffer->page; + + /* avoid re-using remote pages */ + if (unlikely(phytmac_page_is_reserved(page))) + return false; + +#if (PAGE_SIZE < 8192) + /* if we are only owner of page we can reuse it */ + if (unlikely((page_ref_count(page) - pagecnt_bias) > 1)) + return false; +#else +#define PHYTMAC_LAST_OFFSET \ + (SKB_WITH_OVERHEAD(PAGE_SIZE) - PHYTMAC_RXBUFFER_2048) + + if (rx_buffer->page_offset > PHYTMAC_LAST_OFFSET) + return false; +#endif + + /* If we have drained the page fragment pool we need to update + * the pagecnt_bias and page count so that we fully restock the + * number of references the driver holds. + */ + if (unlikely(!pagecnt_bias)) { + page_ref_add(page, USHRT_MAX); + rx_buffer->pagecnt_bias = USHRT_MAX; + } + + return true; +} + +static void phytmac_reuse_rx_page(struct phytmac_queue *queue, + struct phytmac_rx_buffer *old_buff) +{ + struct phytmac_rx_buffer *new_buff; + struct phytmac *pdata = queue->pdata; + u16 nta = queue->rx_next_to_alloc; + + new_buff = &queue->rx_buffer_info[nta & (pdata->rx_ring_size - 1)]; + + /* update, and store next to alloc */ + nta++; + queue->rx_next_to_alloc = (nta < pdata->rx_ring_size) ? nta : 0; + + /* Transfer page from old buffer to new buffer. + * Move each member individually to avoid possible store + * forwarding stalls. + */ + new_buff->addr = old_buff->addr; + new_buff->page = old_buff->page; + new_buff->page_offset = old_buff->page_offset; + new_buff->pagecnt_bias = old_buff->pagecnt_bias; +} + +static struct phytmac_rx_buffer *phytmac_get_rx_buffer(struct phytmac_queue *queue, + unsigned int index, + const unsigned int size) +{ + struct phytmac_rx_buffer *rx_buffer; + struct phytmac *pdata = queue->pdata; + + rx_buffer = &queue->rx_buffer_info[index & (pdata->rx_ring_size - 1)]; + prefetchw(rx_buffer->page); + + /* we are reusing so sync this buffer for CPU use */ + dma_sync_single_range_for_cpu(pdata->dev, + rx_buffer->addr, + rx_buffer->page_offset, + size, + DMA_FROM_DEVICE); + + rx_buffer->pagecnt_bias--; + + return rx_buffer; +} + +static void phytmac_put_rx_buffer(struct phytmac_queue *queue, + struct phytmac_rx_buffer *rx_buffer) +{ + struct phytmac *pdata = queue->pdata; + + if (phytmac_can_reuse_rx_page(rx_buffer)) { + /* hand second half of page back to the ring */ + phytmac_reuse_rx_page(queue, rx_buffer); + } else { + dma_unmap_page_attrs(pdata->dev, rx_buffer->addr, + PHYTMAC_RX_PAGE_SIZE, + DMA_FROM_DEVICE, PHYTMAC_RX_DMA_ATTR); + __page_frag_cache_drain(rx_buffer->page, + rx_buffer->pagecnt_bias); + } + + /* clear contents of rx_buffer */ + rx_buffer->page = NULL; +} + +static void phytmac_add_rx_frag(struct phytmac_queue *queue, + struct phytmac_rx_buffer *rx_buffer, + struct sk_buff *skb, + unsigned int size) +{ + unsigned int truesize; + +#if (PAGE_SIZE < 8192) + truesize = PHYTMAC_RX_PAGE_SIZE / 2; +#else + truesize = SKB_DATA_ALIGN(PHYTMAC_SKB_PAD + size); +#endif + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, + rx_buffer->page_offset, size, truesize); +#if (PAGE_SIZE < 8192) + rx_buffer->page_offset ^= truesize; +#else + rx_buffer->page_offset += truesize; +#endif +} + +static struct sk_buff *phytmac_build_skb(struct phytmac_rx_buffer *rx_buffer, + struct phytmac_dma_desc *desc, + unsigned int size) +{ + struct sk_buff *skb; + unsigned int truesize; + void *va; + +#if (PAGE_SIZE < 8192) + truesize = PHYTMAC_RX_PAGE_SIZE / 2; +#else + truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + + SKB_DATA_ALIGN(PHYTMAC_SKB_PAD + size); +#endif + + va = page_address(rx_buffer->page) + rx_buffer->page_offset; + /* prefetch first cache line of first page */ + prefetch(va); + + /* build an skb around the page buffer */ + skb = build_skb(va - PHYTMAC_SKB_PAD, truesize); + if (unlikely(!skb)) + return NULL; + + /* update pointers within the skb to store the data */ + skb_reserve(skb, PHYTMAC_SKB_PAD); + __skb_put(skb, size); + + /* update buffer offset */ +#if (PAGE_SIZE < 8192) + rx_buffer->page_offset ^= truesize; +#else + rx_buffer->page_offset += truesize; +#endif + + return skb; +} + static struct sk_buff *phytmac_rx_single(struct phytmac_queue *queue, struct phytmac_dma_desc *desc) { struct phytmac *pdata = queue->pdata; struct phytmac_hw_if *hw_if = pdata->hw_if; - struct sk_buff *skb; + struct phytmac_rx_buffer *rx_buffer; + struct sk_buff *skb = NULL; unsigned int len; - dma_addr_t addr; - skb = phytmac_get_rx_skb(queue, queue->rx_tail); + len = hw_if->get_rx_pkt_len(pdata, desc); + rx_buffer = phytmac_get_rx_buffer(queue, queue->rx_tail, len); + + skb = phytmac_build_skb(rx_buffer, desc, len); if (unlikely(!skb)) { netdev_err(pdata->ndev, - "inconsistent Rx descriptor chain\n"); + "rx single build skb failed\n"); pdata->ndev->stats.rx_dropped++; queue->stats.rx_dropped++; + rx_buffer->pagecnt_bias++; return NULL; } - queue->rx_skb[queue->rx_tail & (pdata->rx_ring_size - 1)] = NULL; - len = hw_if->get_rx_pkt_len(pdata, desc); - addr = hw_if->get_desc_addr(desc); + phytmac_put_rx_buffer(queue, rx_buffer); - skb_put(skb, len); - dma_unmap_single(pdata->dev, addr, - pdata->rx_buffer_len, DMA_FROM_DEVICE); skb->protocol = eth_type_trans(skb, pdata->ndev); skb_checksum_none_assert(skb); @@ -691,64 +899,65 @@ static struct sk_buff *phytmac_rx_single(struct phytmac_queue *queue, struct phy } static struct sk_buff *phytmac_rx_frame(struct phytmac_queue *queue, - unsigned int first_frag, unsigned int last_frag, int len) + unsigned int first_frag, unsigned int last_frag, + unsigned int total_len) { - unsigned int offset = 0; unsigned int frag = 0; - unsigned int entry = 0; - dma_addr_t addr = 0; struct sk_buff *skb; struct phytmac_dma_desc *desc; struct phytmac *pdata = queue->pdata; struct phytmac_hw_if *hw_if = pdata->hw_if; unsigned int frag_len = pdata->rx_buffer_len; + unsigned int offset = frag_len; + struct phytmac_rx_buffer *rx_buffer; if (netif_msg_drv(pdata)) netdev_info(pdata->ndev, "rx frame %u - %u (len %u)\n", - first_frag, last_frag, len); + first_frag, last_frag, total_len); + + desc = phytmac_get_rx_desc(queue, first_frag); + rx_buffer = phytmac_get_rx_buffer(queue, first_frag, frag_len); - skb = netdev_alloc_skb(pdata->ndev, len); - if (!skb) { + skb = phytmac_build_skb(rx_buffer, desc, frag_len); + if (unlikely(!skb)) { + netdev_err(pdata->ndev, "rx frame build skb failed\n"); pdata->ndev->stats.rx_dropped++; - netdev_err(pdata->ndev, "rx frame alloc skb failed\n"); + queue->stats.rx_dropped++; + rx_buffer->pagecnt_bias++; return NULL; } - skb_checksum_none_assert(skb); + phytmac_put_rx_buffer(queue, rx_buffer); - if (pdata->ndev->features & NETIF_F_RXCSUM && - !(pdata->ndev->flags & IFF_PROMISC) && - hw_if->rx_checksum(phytmac_get_rx_desc(queue, last_frag))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - - skb_put(skb, len); + for (frag = first_frag + 1; ; frag++) { + desc = phytmac_get_rx_desc(queue, frag); + rx_buffer = phytmac_get_rx_buffer(queue, frag, frag_len); - for (frag = first_frag; ; frag++) { - if (offset + frag_len > len) { + if (offset + frag_len > total_len) { if (unlikely(frag != last_frag)) { dev_kfree_skb_any(skb); + phytmac_put_rx_buffer(queue, rx_buffer); return NULL; } - frag_len = len - offset; + frag_len = total_len - offset; } - desc = phytmac_get_rx_desc(queue, frag); - addr = hw_if->get_desc_addr(desc); - dma_sync_single_for_cpu(pdata->dev, addr, frag_len, - DMA_FROM_DEVICE); - - entry = frag & (pdata->rx_ring_size - 1); - skb_copy_to_linear_data_offset(skb, offset, queue->rx_skb[entry]->data, frag_len); - - offset += pdata->rx_buffer_len; + phytmac_add_rx_frag(queue, rx_buffer, skb, frag_len); + phytmac_put_rx_buffer(queue, rx_buffer); - dma_sync_single_for_device(pdata->dev, addr, frag_len, - DMA_FROM_DEVICE); + offset += frag_len; if (frag == last_frag) break; } + skb_checksum_none_assert(skb); + + if (pdata->ndev->features & NETIF_F_RXCSUM && + !(pdata->ndev->flags & IFF_PROMISC) && + hw_if->rx_checksum(phytmac_get_rx_desc(queue, last_frag))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->protocol = eth_type_trans(skb, pdata->ndev); if (netif_msg_pktdata(pdata)) phytmac_dump_pkt(pdata, skb, false); @@ -764,10 +973,13 @@ static struct sk_buff *phytmac_rx_mbuffer(struct phytmac_queue *queue) struct sk_buff *skb = NULL; unsigned int rx_tail = 0; int first_frag = -1; - int len; + unsigned int len; for (rx_tail = queue->rx_tail; ; rx_tail++) { desc = phytmac_get_rx_desc(queue, rx_tail); + if (!hw_if->rx_complete(desc)) + return NULL; + if (hw_if->rx_pkt_start(desc)) { if (first_frag != -1) hw_if->clear_rx_desc(queue, first_frag, rx_tail); @@ -791,34 +1003,24 @@ static void phytmac_rx_clean(struct phytmac_queue *queue) struct phytmac *pdata = queue->pdata; struct phytmac_hw_if *hw_if = pdata->hw_if; unsigned int index, space; - dma_addr_t paddr; - struct sk_buff *skb; + struct phytmac_rx_buffer *rx_buf_info; space = CIRC_SPACE(queue->rx_head, queue->rx_tail, pdata->rx_ring_size); while (space > 0) { index = queue->rx_head & (pdata->rx_ring_size - 1); - if (!queue->rx_skb[index]) { - skb = netdev_alloc_skb(pdata->ndev, pdata->rx_buffer_len); - if (unlikely(!skb)) { - netdev_err(pdata->ndev, "rx clean alloc skb failed\n"); - break; - } + rx_buf_info = &queue->rx_buffer_info[index]; - paddr = dma_map_single(pdata->dev, skb->data, - pdata->rx_buffer_len, DMA_FROM_DEVICE); - if (dma_mapping_error(pdata->dev, paddr)) { - dev_kfree_skb(skb); - break; - } - - queue->rx_skb[index] = skb; + if (!phytmac_alloc_mapped_page(pdata, rx_buf_info)) + break; + /* sync the buffer for use by the device */ + dma_sync_single_range_for_device(pdata->dev, rx_buf_info->addr, + rx_buf_info->page_offset, + pdata->rx_buffer_len, + DMA_FROM_DEVICE); - hw_if->rx_map(queue, index, paddr); - } else { - hw_if->rx_map(queue, index, 0); - } + hw_if->rx_map(queue, index, rx_buf_info->addr + rx_buf_info->page_offset); queue->rx_head++; if (queue->rx_head >= pdata->rx_ring_size) @@ -827,6 +1029,7 @@ static void phytmac_rx_clean(struct phytmac_queue *queue) space--; } + queue->rx_next_to_alloc = queue->rx_head; /* make newly descriptor to hardware */ wmb(); } @@ -922,7 +1125,7 @@ static int phytmac_maybe_wake_tx_queue(struct phytmac_queue *queue) { struct phytmac *pdata = queue->pdata; int space = CIRC_CNT(queue->tx_tail, queue->tx_head, - pdata->tx_ring_size); + pdata->tx_ring_size); return (space <= (3 * pdata->tx_ring_size / 4)) ? 1 : 0; } @@ -1291,14 +1494,18 @@ static inline void phytmac_init_ring(struct phytmac *pdata) struct phytmac_hw_if *hw_if = pdata->hw_if; struct phytmac_queue *queue; unsigned int q = 0; + int i; for (queue = pdata->queues; q < pdata->queues_num; ++q) { queue->tx_head = 0; queue->tx_tail = 0; hw_if->clear_tx_desc(queue); + for (i = 0; i < pdata->rx_ring_size; i++) + hw_if->init_rx_map(queue, i); queue->rx_head = 0; queue->rx_tail = 0; + queue->rx_next_to_alloc = 0; phytmac_rx_clean(queue); ++queue; } @@ -1751,7 +1958,6 @@ static int phytmac_open(struct net_device *ndev) ++queue; } - phytmac_init_ring(pdata); hw_if->init_hw(pdata); ret = phytmac_phylink_connect(pdata); diff --git a/drivers/net/ethernet/phytium/phytmac_v1.c b/drivers/net/ethernet/phytium/phytmac_v1.c index b823a07a73..9582b58734 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.c +++ b/drivers/net/ethernet/phytium/phytmac_v1.c @@ -986,16 +986,6 @@ static int phytmac_rx_pkt_len(struct phytmac *pdata, const struct phytmac_dma_de return desc->desc1 & PHYTMAC_FRAME_MASK; } -static dma_addr_t phytmac_get_desc_addr(const struct phytmac_dma_desc *desc) -{ - dma_addr_t addr = 0; - - addr = ((u64)(desc->desc2) << 32); - - addr |= (desc->desc0 & 0xfffffffc); - return addr; -} - static bool phytmac_rx_checksum(const struct phytmac_dma_desc *desc) { u32 value = desc->desc1; @@ -1375,7 +1365,6 @@ struct phytmac_hw_if phytmac_1p0_hw = { .tx_complete = phytmac_tx_complete, .rx_complete = phytmac_rx_complete, .get_rx_pkt_len = phytmac_rx_pkt_len, - .get_desc_addr = phytmac_get_desc_addr, .init_rx_map = phytmac_init_rx_map_desc, .rx_map = phytmac_rx_map_desc, .rx_checksum = phytmac_rx_checksum, diff --git a/drivers/net/ethernet/phytium/phytmac_v2.c b/drivers/net/ethernet/phytium/phytmac_v2.c index 41e5df4122..bcfc8ad68e 100644 --- a/drivers/net/ethernet/phytium/phytmac_v2.c +++ b/drivers/net/ethernet/phytium/phytmac_v2.c @@ -952,16 +952,6 @@ static int phytmac_rx_pkt_len(struct phytmac *pdata, const struct phytmac_dma_de return desc->desc1 & PHYTMAC_RXFRMLEN_MASK; } -static dma_addr_t phytmac_get_desc_addr(const struct phytmac_dma_desc *desc) -{ - dma_addr_t addr = 0; - - addr = ((u64)(desc->desc2) << 32); - - addr |= (desc->desc0 & 0xfffffffc); - return addr; -} - static bool phytmac_rx_checksum(const struct phytmac_dma_desc *desc) { u32 value = desc->desc1; @@ -1229,7 +1219,6 @@ struct phytmac_hw_if phytmac_2p0_hw = { .tx_complete = phytmac_tx_complete, .rx_complete = phytmac_rx_complete, .get_rx_pkt_len = phytmac_rx_pkt_len, - .get_desc_addr = phytmac_get_desc_addr, .init_rx_map = phytmac_init_rx_map_desc, .rx_map = phytmac_rx_map_desc, .rx_checksum = phytmac_rx_checksum, -- Gitee From 38380eb6dd3618217d0bc254e0d4b126b331c0c1 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 15:10:12 +0800 Subject: [PATCH 017/121] net/phytmac: Round down rx_buf_len to 64 bytes DMA config register needs the rx_buf_len to be aligned to 64-bytes. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I7535ac7d8abaf80397b39ec1a16b1b959c9decfd --- drivers/net/ethernet/phytium/phytmac_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index a2b3ed84e8..72b5a15870 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -298,9 +298,9 @@ static struct net_device_stats *phytmac_get_stats(struct net_device *dev) static inline int phytmac_calc_rx_buf_len(void) { #if (PAGE_SIZE < 8192) - return PHYTMAC_MAX_FRAME_BUILD_SKB; + return rounddown(PHYTMAC_MAX_FRAME_BUILD_SKB, RX_BUFFER_MULTIPLE); #endif - return PHYTMAC_RXBUFFER_2048; + return rounddown(PHYTMAC_RXBUFFER_2048, RX_BUFFER_MULTIPLE); } inline struct phytmac_dma_desc *phytmac_get_rx_desc(struct phytmac_queue *queue, -- Gitee From 8f25123cc1d1a2ee58e4a61da2ba52e423a13ecf Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Fri, 26 Apr 2024 15:11:35 +0800 Subject: [PATCH 018/121] net/phytmac: Add version display for phytmac driver Add support for Using the ethtool -i interface or modinfo phytmac/phytmac_platform command to display driver version information. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I6577196db18b5b71252ed1e890bb997693460b2d --- drivers/net/ethernet/phytium/phytmac.h | 2 +- drivers/net/ethernet/phytium/phytmac_ethtool.c | 16 ++++++++++++++++ drivers/net/ethernet/phytium/phytmac_main.c | 1 + drivers/net/ethernet/phytium/phytmac_pci.c | 1 + drivers/net/ethernet/phytium/phytmac_platform.c | 1 + 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h index 363bc65c72..7e6cf22d7b 100644 --- a/drivers/net/ethernet/phytium/phytmac.h +++ b/drivers/net/ethernet/phytium/phytmac.h @@ -13,7 +13,7 @@ #define PHYTMAC_DRV_NAME "phytium-mac" #define PHYTMAC_DRV_DESC "PHYTIUM Ethernet Driver" - +#define PHYTMAC_DRIVER_VERSION "1.0.0" #define PHYTMAC_DEFAULT_MSG_ENABLE \ (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ diff --git a/drivers/net/ethernet/phytium/phytmac_ethtool.c b/drivers/net/ethernet/phytium/phytmac_ethtool.c index 7cddb01802..4f63259114 100644 --- a/drivers/net/ethernet/phytium/phytmac_ethtool.c +++ b/drivers/net/ethernet/phytium/phytmac_ethtool.c @@ -2,6 +2,8 @@ #include #include +#include +#include #include "phytmac.h" #include "phytmac_v1.h" #include "phytmac_v2.h" @@ -502,6 +504,19 @@ static inline void phytmac_set_msglevel(struct net_device *ndev, u32 level) pdata->msg_enable = level; } +static void phytmac_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *drvinfo) +{ + struct phytmac *pdata = netdev_priv(ndev); + + strscpy(drvinfo->driver, PHYTMAC_DRV_NAME, sizeof(drvinfo->driver)); + strscpy(drvinfo->version, PHYTMAC_DRIVER_VERSION, sizeof(drvinfo->version)); + + if (pdata->platdev) + strscpy(drvinfo->bus_info, pdata->platdev->name, sizeof(drvinfo->bus_info)); + else if (pdata->pcidev) + strscpy(drvinfo->bus_info, pci_name(pdata->pcidev), sizeof(drvinfo->bus_info)); +} + static const struct ethtool_ops phytmac_ethtool_ops = { .get_regs_len = phytmac_get_regs_len, .get_regs = phytmac_get_regs, @@ -524,6 +539,7 @@ static const struct ethtool_ops phytmac_ethtool_ops = { .set_channels = phytmac_set_channels, .get_wol = phytmac_get_wol, .set_wol = phytmac_set_wol, + .get_drvinfo = phytmac_get_drvinfo, }; void phytmac_set_ethtool_ops(struct net_device *ndev) diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index 72b5a15870..79170097fd 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -2488,4 +2488,5 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Phytium Ethernet driver"); MODULE_AUTHOR("Wenting Song"); MODULE_ALIAS("platform:phytmac"); +MODULE_VERSION(PHYTMAC_DRIVER_VERSION); diff --git a/drivers/net/ethernet/phytium/phytmac_pci.c b/drivers/net/ethernet/phytium/phytmac_pci.c index af69329fe0..60bd296d8f 100644 --- a/drivers/net/ethernet/phytium/phytmac_pci.c +++ b/drivers/net/ethernet/phytium/phytmac_pci.c @@ -316,3 +316,4 @@ module_pci_driver(phytmac_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Phytium NIC PCI wrapper"); +MODULE_VERSION(PHYTMAC_DRIVER_VERSION); diff --git a/drivers/net/ethernet/phytium/phytmac_platform.c b/drivers/net/ethernet/phytium/phytmac_platform.c index 305ff5866e..9390056fdc 100644 --- a/drivers/net/ethernet/phytium/phytmac_platform.c +++ b/drivers/net/ethernet/phytium/phytmac_platform.c @@ -253,3 +253,4 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Phytium Ethernet driver"); MODULE_AUTHOR("Wenting Song"); MODULE_ALIAS("platform:phytmac"); +MODULE_VERSION(PHYTMAC_DRIVER_VERSION); -- Gitee From 63d1449e25be6d4e0a3a6b9d0be14b59327e75fa Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Mon, 29 Apr 2024 10:47:47 +0800 Subject: [PATCH 019/121] net/phytmac: Bugfix about dma conflict problem When setting RX_USED bit of the last descriptor for rx ring to 1, which will lead to the soft think it' valid and cause dma conflict. So change valid condition according to RX_USED bit and non-zero address. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I784537d0d55665587e01a186499416e48d46ad35 --- drivers/net/ethernet/phytium/phytmac.h | 5 +++-- drivers/net/ethernet/phytium/phytmac_main.c | 19 ++++++++-------- drivers/net/ethernet/phytium/phytmac_v1.c | 25 ++++++++++++++++++--- drivers/net/ethernet/phytium/phytmac_v1.h | 1 - drivers/net/ethernet/phytium/phytmac_v2.c | 25 ++++++++++++++++++--- 5 files changed, 56 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h index 7e6cf22d7b..6eb1d7d1b8 100644 --- a/drivers/net/ethernet/phytium/phytmac.h +++ b/drivers/net/ethernet/phytium/phytmac.h @@ -13,7 +13,7 @@ #define PHYTMAC_DRV_NAME "phytium-mac" #define PHYTMAC_DRV_DESC "PHYTIUM Ethernet Driver" -#define PHYTMAC_DRIVER_VERSION "1.0.0" +#define PHYTMAC_DRIVER_VERSION "1.0.1" #define PHYTMAC_DEFAULT_MSG_ENABLE \ (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ @@ -509,13 +509,14 @@ struct phytmac_hw_if { void (*transmit)(struct phytmac_queue *queue); void (*restart)(struct phytmac *pdata); int (*tx_complete)(const struct phytmac_dma_desc *desc); - int (*rx_complete)(const struct phytmac_dma_desc *desc); + bool (*rx_complete)(const struct phytmac_dma_desc *desc); int (*get_rx_pkt_len)(struct phytmac *pdata, const struct phytmac_dma_desc *desc); bool (*rx_checksum)(const struct phytmac_dma_desc *desc); void (*set_desc_rxused)(struct phytmac_dma_desc *desc); bool (*rx_single_buffer)(const struct phytmac_dma_desc *desc); bool (*rx_pkt_start)(const struct phytmac_dma_desc *desc); bool (*rx_pkt_end)(const struct phytmac_dma_desc *desc); + unsigned int (*zero_rx_desc_addr)(struct phytmac_dma_desc *desc); void (*clear_rx_desc)(struct phytmac_queue *queue, int begin, int end); void (*clear_tx_desc)(struct phytmac_queue *queue); /* ptp */ diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index 79170097fd..d932d011b2 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -442,6 +442,7 @@ static int phytmac_alloc_tx_resource(struct phytmac *pdata) int ret, i; tx_offset = TX_RING_BYTES(pdata) + pdata->tx_bd_prefetch + RING_ADDR_INTERVAL; + tx_offset = ALIGN(tx_offset, 4096); tx_size = pdata->queues_num * tx_offset; for (i = 0; i < MAX_RING_ADDR_ALLOC_TIMES + 1; i++) { if (i == MAX_RING_ADDR_ALLOC_TIMES) @@ -504,6 +505,7 @@ static int phytmac_alloc_rx_resource(struct phytmac *pdata) int ret, i; rx_offset = RX_RING_BYTES(pdata) + pdata->rx_bd_prefetch + RING_ADDR_INTERVAL; + rx_offset = ALIGN(rx_offset, 4096); rx_size = pdata->queues_num * rx_offset; for (i = 0; i < MAX_RING_ADDR_ALLOC_TIMES + 1; i++) { if (i == MAX_RING_ADDR_ALLOC_TIMES) @@ -698,18 +700,13 @@ static bool phytmac_alloc_mapped_page(struct phytmac *pdata, return true; } -static inline bool phytmac_page_is_reserved(struct page *page) -{ - return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page); -} - static bool phytmac_can_reuse_rx_page(struct phytmac_rx_buffer *rx_buffer) { unsigned int pagecnt_bias = rx_buffer->pagecnt_bias; struct page *page = rx_buffer->page; - /* avoid re-using remote pages */ - if (unlikely(phytmac_page_is_reserved(page))) + /* avoid re-using remote and pfmemalloc pages */ + if (!dev_page_is_reusable(page)) return false; #if (PAGE_SIZE < 8192) @@ -824,7 +821,6 @@ static void phytmac_add_rx_frag(struct phytmac_queue *queue, } static struct sk_buff *phytmac_build_skb(struct phytmac_rx_buffer *rx_buffer, - struct phytmac_dma_desc *desc, unsigned int size) { struct sk_buff *skb; @@ -871,8 +867,9 @@ static struct sk_buff *phytmac_rx_single(struct phytmac_queue *queue, struct phy len = hw_if->get_rx_pkt_len(pdata, desc); rx_buffer = phytmac_get_rx_buffer(queue, queue->rx_tail, len); + hw_if->zero_rx_desc_addr(desc); - skb = phytmac_build_skb(rx_buffer, desc, len); + skb = phytmac_build_skb(rx_buffer, len); if (unlikely(!skb)) { netdev_err(pdata->ndev, "rx single build skb failed\n"); @@ -917,8 +914,9 @@ static struct sk_buff *phytmac_rx_frame(struct phytmac_queue *queue, desc = phytmac_get_rx_desc(queue, first_frag); rx_buffer = phytmac_get_rx_buffer(queue, first_frag, frag_len); + hw_if->zero_rx_desc_addr(desc); - skb = phytmac_build_skb(rx_buffer, desc, frag_len); + skb = phytmac_build_skb(rx_buffer, frag_len); if (unlikely(!skb)) { netdev_err(pdata->ndev, "rx frame build skb failed\n"); pdata->ndev->stats.rx_dropped++; @@ -932,6 +930,7 @@ static struct sk_buff *phytmac_rx_frame(struct phytmac_queue *queue, for (frag = first_frag + 1; ; frag++) { desc = phytmac_get_rx_desc(queue, frag); rx_buffer = phytmac_get_rx_buffer(queue, frag, frag_len); + hw_if->zero_rx_desc_addr(desc); if (offset + frag_len > total_len) { if (unlikely(frag != last_frag)) { diff --git a/drivers/net/ethernet/phytium/phytmac_v1.c b/drivers/net/ethernet/phytium/phytmac_v1.c index 9582b58734..1d7c2e1759 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.c +++ b/drivers/net/ethernet/phytium/phytmac_v1.c @@ -940,6 +940,14 @@ static unsigned int phytmac_rx_map_desc(struct phytmac_queue *queue, return 0; } +static unsigned int phytmac_zero_rx_desc_addr(struct phytmac_dma_desc *desc) +{ + desc->desc2 = 0; + desc->desc0 = PHYTMAC_BIT(RX_USED); + + return 0; +} + static void phytmac_tx_start(struct phytmac_queue *queue) { struct phytmac *pdata = queue->pdata; @@ -973,9 +981,19 @@ static int phytmac_tx_complete(const struct phytmac_dma_desc *desc) return PHYTMAC_GET_BITS(desc->desc1, TX_USED); } -static int phytmac_rx_complete(const struct phytmac_dma_desc *desc) +static bool phytmac_rx_complete(const struct phytmac_dma_desc *desc) { - return (desc->desc0 & PHYTMAC_BIT(RX_USED)) != 0; + dma_addr_t addr; + bool used; + + used = desc->desc0 & PHYTMAC_BIT(RX_USED); + addr = ((u64)(desc->desc2) << 32); + addr |= desc->desc0 & 0xfffffff8; + + if (used != 0 && addr != 0) + return true; + else + return false; } static int phytmac_rx_pkt_len(struct phytmac *pdata, const struct phytmac_dma_desc *desc) @@ -1024,7 +1042,7 @@ static void phytmac_clear_rx_desc(struct phytmac_queue *queue, int begin, int en if (begin > end) tmp = end + queue->pdata->rx_ring_size; - for (frag = begin; frag != end; frag++) { + for (frag = begin; frag != tmp; frag++) { desc = phytmac_get_rx_desc(queue, frag); desc->desc0 &= ~PHYTMAC_BIT(RX_USED); } @@ -1373,6 +1391,7 @@ struct phytmac_hw_if phytmac_1p0_hw = { .rx_pkt_end = phytmac_rx_eof, .clear_rx_desc = phytmac_clear_rx_desc, .clear_tx_desc = phytmac_clear_tx_desc, + .zero_rx_desc_addr = phytmac_zero_rx_desc_addr, /* ptp */ .init_ts_hw = phytmac_ptp_init_hw, .set_time = phytmac_set_time, diff --git a/drivers/net/ethernet/phytium/phytmac_v1.h b/drivers/net/ethernet/phytium/phytmac_v1.h index 1f49d4ec79..32bb129491 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.h +++ b/drivers/net/ethernet/phytium/phytmac_v1.h @@ -374,7 +374,6 @@ extern struct phytmac_hw_if phytmac_1p0_hw; #define PHYTMAC_WOL_RECEIVE_DISABLE_INDEX 28 /* Disable wol_event_recieve */ #define PHYTMAC_WOL_RECEIVE_DISABLE_WIDTH 1 - #define PHYTMAC_TSEC_WIDTH (PHYTMAC_SECH_WIDTH + PHYTMAC_SECL_WIDTH) #define SEC_MAX_VAL (((u64)1 << PHYTMAC_TSEC_WIDTH) - 1) #define NSEC_MAX_VAL ((1 << PHYTMAC_NSEC_WIDTH) - 1) diff --git a/drivers/net/ethernet/phytium/phytmac_v2.c b/drivers/net/ethernet/phytium/phytmac_v2.c index bcfc8ad68e..25f1ba6c1d 100644 --- a/drivers/net/ethernet/phytium/phytmac_v2.c +++ b/drivers/net/ethernet/phytium/phytmac_v2.c @@ -934,14 +934,32 @@ static unsigned int phytmac_rx_map_desc(struct phytmac_queue *queue, u32 index, return 0; } +static unsigned int phytmac_zero_rx_desc_addr(struct phytmac_dma_desc *desc) +{ + desc->desc2 = 0; + desc->desc0 = PHYTMAC_BIT(RXUSED); + + return 0; +} + static int phytmac_tx_complete(const struct phytmac_dma_desc *desc) { return PHYTMAC_GET_BITS(desc->desc1, TXUSED); } -static int phytmac_rx_complete(const struct phytmac_dma_desc *desc) +static bool phytmac_rx_complete(const struct phytmac_dma_desc *desc) { - return PHYTMAC_GET_BITS(desc->desc0, RXUSED); + dma_addr_t addr; + bool used; + + used = PHYTMAC_GET_BITS(desc->desc0, RXUSED); + addr = ((u64)(desc->desc2) << 32); + addr |= desc->desc0 & 0xfffffff8; + + if (used != 0 && addr != 0) + return true; + else + return false; } static int phytmac_rx_pkt_len(struct phytmac *pdata, const struct phytmac_dma_desc *desc) @@ -990,7 +1008,7 @@ static void phytmac_clear_rx_desc(struct phytmac_queue *queue, int begin, int en if (begin > end) tmp = end + queue->pdata->rx_ring_size; - for (frag = begin; frag != end; frag++) { + for (frag = begin; frag != tmp; frag++) { desc = phytmac_get_rx_desc(queue, frag); desc->desc0 &= ~PHYTMAC_BIT(RXUSED); } @@ -1227,6 +1245,7 @@ struct phytmac_hw_if phytmac_2p0_hw = { .rx_pkt_end = phytmac_rx_eof, .clear_rx_desc = phytmac_clear_rx_desc, .clear_tx_desc = phytmac_clear_tx_desc, + .zero_rx_desc_addr = phytmac_zero_rx_desc_addr, /* ptp */ .init_ts_hw = phytmac_ptp_init_hw, -- Gitee From 6302b0ab85a13bec77c34afd9e0a015ac3b0ceda Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Mon, 29 Apr 2024 18:23:45 +0800 Subject: [PATCH 020/121] net/phytmac: Bugfix MAC address change when rmmod and insmod module The eth_hw_addr_random function cause systemd-udevd to generate MAC address, which will modify the default MAC address. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Ie9fa00c3a4c9310104fd888526571df95f15c664 --- drivers/net/ethernet/phytium/phytmac.h | 2 +- drivers/net/ethernet/phytium/phytmac_main.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h index 6eb1d7d1b8..cb9359c7bd 100644 --- a/drivers/net/ethernet/phytium/phytmac.h +++ b/drivers/net/ethernet/phytium/phytmac.h @@ -13,7 +13,7 @@ #define PHYTMAC_DRV_NAME "phytium-mac" #define PHYTMAC_DRV_DESC "PHYTIUM Ethernet Driver" -#define PHYTMAC_DRIVER_VERSION "1.0.1" +#define PHYTMAC_DRIVER_VERSION "1.0.2" #define PHYTMAC_DEFAULT_MSG_ENABLE \ (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index d932d011b2..732358ea40 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -2208,7 +2208,6 @@ static int phytmac_init(struct phytmac *pdata) ndev->netdev_ops = &phytmac_netdev_ops; phytmac_set_ethtool_ops(ndev); - eth_hw_addr_random(pdata->ndev); if (ndev->hw_features & NETIF_F_NTUPLE) { INIT_LIST_HEAD(&pdata->rx_fs_list.list); -- Gitee From 6b70dbeaafdc06a66410e77bfba11c5595f25a4e Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Tue, 21 May 2024 14:20:05 +0800 Subject: [PATCH 021/121] net/phytmac: Bugfix MAC 10/100M speed does't work problem Gigabit_mode_enable bit should be clear when the speed is switched to 10M/100M. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I16e54d6e173c15c890788cf0bdcff2facca0f490 --- drivers/net/ethernet/phytium/phytmac.h | 2 +- drivers/net/ethernet/phytium/phytmac_ethtool.c | 2 +- drivers/net/ethernet/phytium/phytmac_v1.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h index cb9359c7bd..bc0d2670c2 100644 --- a/drivers/net/ethernet/phytium/phytmac.h +++ b/drivers/net/ethernet/phytium/phytmac.h @@ -13,7 +13,7 @@ #define PHYTMAC_DRV_NAME "phytium-mac" #define PHYTMAC_DRV_DESC "PHYTIUM Ethernet Driver" -#define PHYTMAC_DRIVER_VERSION "1.0.2" +#define PHYTMAC_DRIVER_VERSION "1.0.3" #define PHYTMAC_DEFAULT_MSG_ENABLE \ (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ diff --git a/drivers/net/ethernet/phytium/phytmac_ethtool.c b/drivers/net/ethernet/phytium/phytmac_ethtool.c index 4f63259114..a97a4c28c0 100644 --- a/drivers/net/ethernet/phytium/phytmac_ethtool.c +++ b/drivers/net/ethernet/phytium/phytmac_ethtool.c @@ -429,7 +429,7 @@ static int phytmac_set_link_ksettings(struct net_device *ndev, int ret = 0; if (!ndev->phydev) { - netdev_err(ndev, "fixed link interface not supported set link\n"); + netdev_err(ndev, "Without a PHY, setting link is not supported\n"); ret = -EOPNOTSUPP; } else { phy_ethtool_set_link_ksettings(ndev, kset); diff --git a/drivers/net/ethernet/phytium/phytmac_v1.c b/drivers/net/ethernet/phytium/phytmac_v1.c index 1d7c2e1759..20595aca17 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.c +++ b/drivers/net/ethernet/phytium/phytmac_v1.c @@ -182,7 +182,7 @@ static int phytmac_mac_linkup(struct phytmac *pdata, phy_interface_t interface, config = PHYTMAC_READ(pdata, PHYTMAC_NCONFIG); - config &= ~(PHYTMAC_BIT(SPEED) | PHYTMAC_BIT(FD)); + config &= ~(PHYTMAC_BIT(SPEED) | PHYTMAC_BIT(FD) | PHYTMAC_BIT(GM_EN)); if (speed == SPEED_100) config |= PHYTMAC_BIT(SPEED); -- Gitee From 208eea22dc1168e25ee4720a67f9c453938cd5ac Mon Sep 17 00:00:00 2001 From: Lai Xueyu Date: Wed, 13 Mar 2024 16:43:47 +0800 Subject: [PATCH 022/121] mmc: phytium: Fix dead loops issue in CMD11 process In special situation, it may cause a dead loop in the update CMD11 process while waiting for the register state. So we changed it to poll timeout. Mainline: Open-Source Signed-off-by: Lai Xueyu Signed-off-by: Wang Yinfeng Change-Id: I837c5d496d842af23aa0cb6e8640f8985786c085 --- drivers/mmc/host/phytium-mci.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/phytium-mci.c b/drivers/mmc/host/phytium-mci.c index b511d893be..4a535d68f1 100644 --- a/drivers/mmc/host/phytium-mci.c +++ b/drivers/mmc/host/phytium-mci.c @@ -151,10 +151,17 @@ static void phytium_mci_send_cmd(struct phytium_mci_host *host, u32 cmd, u32 arg static void phytium_mci_update_cmd11(struct phytium_mci_host *host, u32 cmd) { + int rc; + u32 data; + writel(MCI_CMD_START | cmd, host->base + MCI_CMD); - while (readl(host->base + MCI_CMD) & MCI_CMD_START) - cpu_relax(); + rc = readl_relaxed_poll_timeout(host->base + MCI_CMD, + data, + !(data & MCI_CMD_START), + 0, 100 * 1000); + if (rc == -ETIMEDOUT) + pr_debug("%s %d, timeout mci_cmd: 0x%08x\n", __func__, __LINE__, data); } static void phytium_mci_set_clk(struct phytium_mci_host *host, struct mmc_ios *ios) -- Gitee From 737b0d5de93e9d0ee00eb5675084eda6e038c4fd Mon Sep 17 00:00:00 2001 From: WangHao Date: Mon, 22 Apr 2024 02:47:43 +0000 Subject: [PATCH 023/121] drm/phytium: Adjust log printing level Adjust log printing level to reduce repetitive information printing. Mainline: Open-Source Signed-off-by: Wang Hao Signed-off-by: Wang Yinfeng Change-Id: Ibcd3952d1513398c1d8fb8c3967854af103c12d6 --- drivers/gpu/drm/phytium/phytium_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/phytium/phytium_dp.c b/drivers/gpu/drm/phytium/phytium_dp.c index b9a07b74b8..78eac4fde1 100644 --- a/drivers/gpu/drm/phytium/phytium_dp.c +++ b/drivers/gpu/drm/phytium/phytium_dp.c @@ -2222,13 +2222,13 @@ phytium_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display case 8: break; default: - pr_info("not support bpc(%d)\n", display_info->bpc); + DRM_DEBUG_KMS("not support bpc(%d)\n", display_info->bpc); display_info->bpc = 8; break; } if ((display_info->color_formats & DRM_COLOR_FORMAT_RGB444) == 0) { - pr_info("not support color_format(%d)\n", display_info->color_formats); + DRM_DEBUG_KMS("not support color_format(%d)\n", display_info->color_formats); display_info->color_formats = DRM_COLOR_FORMAT_RGB444; } -- Gitee From 5c833b41d1c369ae772a67ac6cb528dd0a328d36 Mon Sep 17 00:00:00 2001 From: Xiao Cong Date: Tue, 21 May 2024 11:25:17 +0800 Subject: [PATCH 024/121] PCIe: phytium: Disable SRIOV cabability when pe220x work as BMC cards PE220x can not support SRIOV when working as BMC cards, which will cause some system crash problem. So disable it by default. Mainline: Open-Source Signed-off-by: Xiao Cong Signed-off-by: Wang Yinfeng Change-Id: I62a4e1a67f208082971936db9831f72d05ef6758 --- drivers/pci/iov.c | 4 ++++ include/linux/pci_ids.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 25dbe85c42..f74c83f033 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -900,6 +900,10 @@ int pci_iov_init(struct pci_dev *dev) if (!pci_is_pcie(dev)) return -ENODEV; + if ((dev->vendor == PCI_VENDOR_ID_PHYTIUM) + && (dev->device == PCI_DEVICE_ID_PHYTIUM_PE220X)) + return -ENODEV; + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); if (pos) return sriov_init(dev, pos); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 8520a5c682..4c01b8cf24 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -3222,5 +3222,6 @@ #define PCI_VENDOR_ID_NCUBE 0x10ff #define PCI_VENDOR_ID_PHYTIUM 0x1db7 +#define PCI_DEVICE_ID_PHYTIUM_PE220X 0xdc3e #endif /* _LINUX_PCI_IDS_H */ -- Gitee From 03e2543fef5c164f1386ff761e590ba3af3f7741 Mon Sep 17 00:00:00 2001 From: Dai Jingtao Date: Tue, 2 Apr 2024 14:57:24 +0800 Subject: [PATCH 025/121] i2s:phytium: Add support for headphone detect Using i2s-gpio for headphone detect. Mainline: Open-Source Signed-off-by: Dai Jingtao Signed-off-by: Wang Yinfeng Change-Id: I4962567f9af59a7f5cfb9c7d3e27bd2090b07758 --- sound/soc/phytium/local.h | 34 ++++++++ sound/soc/phytium/phytium_i2s.c | 136 +++++++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 3 deletions(-) diff --git a/sound/soc/phytium/local.h b/sound/soc/phytium/local.h index 8cc80d1d10..54c4d2a6de 100644 --- a/sound/soc/phytium/local.h +++ b/sound/soc/phytium/local.h @@ -81,6 +81,36 @@ #define DMA_STS 0x0008 +#define I2S_HEADPHONE_ENABLE 1 +#define I2S_HEADPHONE_DISABLE 0 + +#define I2S_GPIO(x) BIT(x) +#define I2S_GPIO_BASE 0xD00 + +/* I2S GPIO registers */ +#define I2S_GPIO_SWPORTA_DR 0x00 /* WR Port A Output Data Register */ + #define I2S_HEADPHONE_FRONT (!I2S_GPIO(1)) + #define I2S_HEADPHONE_REAR I2S_GPIO(1) +#define I2S_GPIO_SWPORTA_DDR 0x04 /* WR Port A Data Direction Register */ + #define I2S_GPIO_INPUT(x) (!I2S_GPIO(x)) + #define I2S_GPIO_OUTPUT(x) I2S_GPIO(x) +#define I2S_GPIO_EXT_PORTA 0x08 /* RO Port A Input Data Register */ +#define I2S_GPIO_SWPORTB_DR 0x0c /* WR Port B Output Data Register */ +#define I2S_GPIO_SWPORTB_DDR 0x10 /* WR Port B Data Direction Register */ +#define I2S_GPIO_EXT_PORTB 0x14 /* RO Port B Input Data Register */ + +#define I2S_GPIO_INTEN 0x18 /* WR Port A Interrput Enable Register */ +#define I2S_GPIO_INTMASK 0x1c /* WR Port A Interrupt Mask Register */ +#define I2S_GPIO_INTTYPE_LEVEL 0x20 /* WR Port A Interrupt Level Register */ + #define I2S_GPIO_LEVEL(x) (!I2S_GPIO(x)) + #define I2S_GPIO_EDGE(x) I2S_GPIO(x) +#define I2S_GPIO_INT_POLARITY 0x24 /* WR Port A Interrupt Polarity Register */ + #define I2S_GPIO_DOWN(x) (!I2S_GPIO(x)) + #define I2S_GPIO_UP(x) I2S_GPIO(x) +#define I2S_GPIO_INTSTATUS 0x28 /* RO Port A Interrupt Status Register */ +#define I2S_GPIO_DEBOUNCE 0x34 /* WR Debounce Enable Register */ +#define I2S_GPIO_PORTA_EOI 0x38 /* WO Port A Clear Interrupt Register */ + /* max number of fragments - we may use more if allocating more pages for BDL */ #define BDL_SIZE 4096 #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) @@ -281,7 +311,10 @@ struct i2s_phytium { u32 paddr; void __iomem *regs; void __iomem *regs_db; + void __iomem *regs_gpio; int irq_id; + int gpio_irq_id; + bool detect; /* for pending irqs */ struct work_struct irq_pending_work; @@ -289,6 +322,7 @@ struct i2s_phytium { /* sync probing */ struct completion probe_wait; struct work_struct probe_work; + struct delayed_work i2s_gpio_work; /* extra flags */ unsigned int pcie:1; diff --git a/sound/soc/phytium/phytium_i2s.c b/sound/soc/phytium/phytium_i2s.c index 9119cdae1c..c804f77d02 100644 --- a/sound/soc/phytium/phytium_i2s.c +++ b/sound/soc/phytium/phytium_i2s.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "local.h" @@ -46,11 +47,25 @@ #define EIGHT_CHANNEL_SUPPORT 8 /* up to 7.1 */ struct pdata_px210_mfd { - struct device *dev; + struct device *dev; char *name; int clk_base; }; +static struct snd_soc_jack hs_jack; + +/* Headset jack detection DAPM pins */ +static struct snd_soc_jack_pin hs_jack_pins[] = { + { + .pin = "FrontIn", + .mask = SND_JACK_MICROPHONE, + }, + { + .pin = "Front", + .mask = SND_JACK_HEADPHONE, + }, +}; + static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val) { writel(val, io_base + reg); @@ -151,6 +166,72 @@ irqreturn_t azx_i2s_interrupt(int irq, void *dev_id) return IRQ_RETVAL(handled); } +int azx_i2s_enable_gpio(struct i2s_phytium *i2s) +{ + u32 val; + + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_SWPORTA_DDR, + (I2S_GPIO_INPUT(0) | I2S_GPIO_OUTPUT(1))); + val = i2s_read_reg(i2s->regs_gpio, I2S_GPIO_SWPORTA_DDR); + if (val != (I2S_GPIO_INPUT(0) | I2S_GPIO_OUTPUT(1))) + goto enable_err; + + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_INTMASK, !I2S_GPIO(0)); + val = i2s_read_reg(i2s->regs_gpio, I2S_GPIO_INTMASK); + if (val != !I2S_GPIO(0)) + goto enable_err; + + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_INTTYPE_LEVEL, I2S_GPIO_EDGE(0)); + val = i2s_read_reg(i2s->regs_gpio, I2S_GPIO_INTTYPE_LEVEL); + if (val != I2S_GPIO_EDGE(0)) + goto enable_err; + + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_INT_POLARITY, I2S_GPIO_DOWN(0)); + val = i2s_read_reg(i2s->regs_gpio, I2S_GPIO_INT_POLARITY); + if (val != I2S_GPIO_DOWN(0)) + goto enable_err; + + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_INTEN, I2S_GPIO(0)); + val = i2s_read_reg(i2s->regs_gpio, I2S_GPIO_INTEN); + if (val != I2S_GPIO(0)) + goto enable_err; + + return 0; +enable_err: + return -EBUSY; +} + +static void i2s_gpio_jack_work(struct work_struct *work) +{ + struct i2s_phytium *i2s = container_of(work, struct i2s_phytium, i2s_gpio_work.work); + u32 val; + + val = i2s_read_reg(i2s->regs_gpio, I2S_GPIO_INT_POLARITY); + if (val == 1) { + snd_soc_jack_report(&hs_jack, I2S_HEADPHONE_DISABLE, SND_JACK_HEADSET); + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_SWPORTA_DR, I2S_HEADPHONE_REAR); + } else { + snd_soc_jack_report(&hs_jack, I2S_HEADPHONE_ENABLE, SND_JACK_HEADSET); + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_SWPORTA_DR, I2S_HEADPHONE_FRONT); + } + val = ~val; + val &= 0x1; + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_INT_POLARITY, val); +} + +irqreturn_t azx_i2s_gpio_interrupt(int irq, void *dev_id) +{ + struct azx *chip = dev_id; + struct i2s_phytium *i2s = container_of(chip, struct i2s_phytium, chip); + bool handled = true; + + queue_delayed_work(system_power_efficient_wq, &i2s->i2s_gpio_work, + msecs_to_jiffies(100)); + + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_PORTA_EOI, I2S_GPIO(0)); + return IRQ_RETVAL(handled); +} + static int azx_acquire_irq(struct azx *chip, int do_disconnect) { struct i2sc_bus *bus = azx_bus(chip); @@ -165,6 +246,22 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) return err; } + if (i2s->detect) { + err = azx_i2s_enable_gpio(i2s); + if (err < 0) { + dev_err(i2s->dev, "failed to enable gpio irq\n"); + return err; + } + + err = devm_request_irq(i2s->dev, i2s->gpio_irq_id, azx_i2s_gpio_interrupt, + IRQF_SHARED, + "phytium i2s gpio", chip); + if (err < 0) { + dev_err(i2s->dev, "failed to request gpio irq\n"); + return err; + } + } + bus->irq = i2s->irq_id; return 0; @@ -370,6 +467,10 @@ static int phytium_i2s_resume(struct snd_soc_component *component) } i2s_write_reg(dev->regs, CLK_CFG0, dev->cfg); i2s_write_reg(dev->regs, CLK_CFG1, 0xf); + + if (dev->detect) + azx_i2s_enable_gpio(dev); + return 0; } #else @@ -377,6 +478,21 @@ static int phytium_i2s_resume(struct snd_soc_component *component) #define phytium_i2s_resume NULL #endif +static int phytium_i2s_component_probe(struct snd_soc_component *component) +{ + struct snd_soc_card *card = component->card; + int ret; + + ret = snd_soc_card_jack_new_pins(card, "Headset Jack", SND_JACK_HEADSET, + &hs_jack, hs_jack_pins, + ARRAY_SIZE(hs_jack_pins)); + if (ret < 0) { + dev_err(component->dev, "Cannot create jack\n"); + return ret; + } + return 0; +} + static struct snd_soc_dai_driver phytium_i2s_dai = { .playback = { .stream_name = "i2s-Playback", @@ -967,6 +1083,7 @@ static const struct snd_soc_component_driver phytium_i2s_component = { .pointer = phytium_pcm_pointer, .suspend = phytium_i2s_suspend, .resume = phytium_i2s_resume, + .probe = phytium_i2s_component_probe, .legacy_dai_naming = 1, }; @@ -1265,6 +1382,8 @@ static int i2s_phytium_create(struct platform_device *pdev, } INIT_WORK(&i2s->probe_work, azx_probe_work); + if (i2s->detect) + INIT_DELAYED_WORK(&i2s->i2s_gpio_work, i2s_gpio_jack_work); *rchip = chip; return 0; } @@ -1324,17 +1443,28 @@ static int phytium_i2s_probe(struct platform_device *pdev) i2s->paddr = res->start; i2s->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2s->regs)) + return PTR_ERR(i2s->regs); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); i2s->regs_db = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(i2s->regs)) - return PTR_ERR(i2s->regs); + if (IS_ERR(i2s->regs_db)) + return PTR_ERR(i2s->regs_db); i2s->irq_id = platform_get_irq(pdev, 0); if (i2s->irq_id < 0) return i2s->irq_id; + i2s->gpio_irq_id = platform_get_irq(pdev, 1); + i2s->detect = true; + + if (i2s->gpio_irq_id < 0) + i2s->detect = false; + else + i2s->regs_gpio = i2s->regs + I2S_GPIO_BASE; + i2s->i2s_reg_comp1 = I2S_COMP_PARAM_1; i2s->i2s_reg_comp2 = I2S_COMP_PARAM_2; -- Gitee From 281bdfeaa814f9d386fb5f83fb500d1692018fee Mon Sep 17 00:00:00 2001 From: He Qiong Date: Mon, 1 Jul 2024 14:08:41 +0800 Subject: [PATCH 026/121] virt: phytium: Add ARM64 support for CPU hotplug Register CPU hotplug for ARM64, add mapping between GICC and physical CPU and modify CPU initial state. Mainline: Open-Source Signed-off-by: He Qiong Signed-off-by: Wang Yinfeng Change-Id: Ida64fbdab52d8c6599f837733fb3a5841b92027a --- arch/arm64/kernel/acpi.c | 33 +++++++++++++++++++++++++++++++++ arch/arm64/kernel/setup.c | 23 ++++++++++++++++++++++- arch/arm64/kernel/smp.c | 16 ++++++++++------ 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index dba8fcec7f..31deddea5c 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -517,3 +518,35 @@ int acpi_ffh_address_space_arch_handler(acpi_integer *value, void *region_contex return ret; } #endif /* CONFIG_ACPI_FFH */ + +int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 acpi_id, + int *pcpu) +{ + int cpu, nid; + + cpu = acpi_map_cpuid(physid, acpi_id); + if (cpu < 0) { + pr_info("Unable to map GICC to logical cpu number\n"); + return cpu; + } + nid = acpi_get_node(handle); + if (nid != NUMA_NO_NODE) { + set_cpu_numa_node(cpu, nid); + numa_add_cpu(cpu); + } + + *pcpu = cpu; + set_cpu_present(cpu, true); + + return 0; +} +EXPORT_SYMBOL(acpi_map_cpu); + +int acpi_unmap_cpu(int cpu) +{ + set_cpu_present(cpu, false); + numa_clear_node(cpu); + + return 0; +} +EXPORT_SYMBOL(acpi_unmap_cpu); diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index c583d1f335..80ba335158 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -403,7 +403,7 @@ static int __init topology_init(void) { int i; - for_each_possible_cpu(i) { + for_each_present_cpu(i) { struct cpu *cpu = &per_cpu(cpu_data.cpu, i); cpu->hotpluggable = cpu_can_disable(i); register_cpu(cpu, i); @@ -454,3 +454,24 @@ static int __init check_mmu_enabled_at_boot(void) return 0; } device_initcall_sync(check_mmu_enabled_at_boot); + +#ifdef CONFIG_HOTPLUG_CPU + +int arch_register_cpu(int num) +{ + struct cpu *cpu = &per_cpu(cpu_data.cpu, num); + + cpu->hotpluggable = 1; + return register_cpu(cpu, num); +} +EXPORT_SYMBOL(arch_register_cpu); + +void arch_unregister_cpu(int num) +{ + struct cpu *cpu = &per_cpu(cpu_data.cpu, num); + + unregister_cpu(cpu); +} +EXPORT_SYMBOL(arch_unregister_cpu); + +#endif diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 14365ef842..82c9c82ee0 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -522,16 +522,14 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) { u64 hwid = processor->arm_mpidr; - if (!(processor->flags & ACPI_MADT_ENABLED)) { - pr_debug("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid); - return; - } - if (hwid & ~MPIDR_HWID_BITMASK || hwid == INVALID_HWID) { pr_err("skipping CPU entry with invalid MPIDR 0x%llx\n", hwid); return; } + if (!(processor->flags & ACPI_MADT_ENABLED)) + pr_debug("disabled CPU entry with 0x%llx MPIDR\n", hwid); + if (is_mpidr_duplicate(cpu_count, hwid)) { pr_err("duplicate CPU MPIDR 0x%llx in MADT\n", hwid); return; @@ -754,7 +752,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (err) continue; - set_cpu_present(cpu, true); + if (acpi_disabled) { + set_cpu_present(cpu, true); + } else { + if ((cpu_madt_gicc[cpu].flags & ACPI_MADT_ENABLED)) + set_cpu_present(cpu, true); + } + numa_store_cpu_info(cpu); } } -- Gitee From e29f9777df1314839cc18df3679fb51997897404 Mon Sep 17 00:00:00 2001 From: Wu Jinyong Date: Wed, 31 Jul 2024 10:19:23 +0800 Subject: [PATCH 027/121] i2c: phytium: Fix stop interrupt in slave mode This patch is to fix an issue where the STOP interrupt signal is triggered too early in slave mode. The complete data processing flow is that all other interrupt signals are processed,and the STOP interrupt signal is processed last.However,the STOP interrupt signal is triggered too early,which terminates the later data processing flow premanturely. Modify the interrupt handler,when there is a data interrupt,empty the RXFIFO to make sure all the data are processed,and then process the STOP interrupt. Mainline: Open-Source Signed-off-by: Wu Jinyong Signed-off-by: Wang Yinfeng Change-Id: I41296a9aad4a33e14c17d4e906bfac68a94a559a --- drivers/i2c/busses/i2c-phytium-slave.c | 71 ++++++++++---------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/drivers/i2c/busses/i2c-phytium-slave.c b/drivers/i2c/busses/i2c-phytium-slave.c index 2f0076561b..3d6f3c3932 100644 --- a/drivers/i2c/busses/i2c-phytium-slave.c +++ b/drivers/i2c/busses/i2c-phytium-slave.c @@ -146,62 +146,44 @@ static int i2c_phytium_irq_handler_slave(struct phytium_i2c_dev *dev) stat = phytium_readl(dev, IC_INTR_STAT); enabled = phytium_readl(dev, IC_ENABLE); raw_stat = phytium_readl(dev, IC_RAW_INTR_STAT); - slave_activity = ((phytium_readl(dev, IC_STATUS) & - IC_STATUS_SLAVE_ACTIVITY) >> 6); + slave_activity = + ((phytium_readl(dev, IC_STATUS) & IC_STATUS_SLAVE_ACTIVITY) >> 6); if (!enabled || !(raw_stat & ~IC_INTR_ACTIVITY) || !dev->slave) return 0; - dev_dbg(dev->dev, - "%#x STATUS SLAVE_ACTIVITY=%#x : RAW_INTR_STAT=%#x : INTR_STAT=%#x\n", - enabled, slave_activity, raw_stat, stat); + stat = i2c_phytium_read_clear_intrbits_slave(dev); - if ((stat & IC_INTR_RX_FULL) && (stat & IC_INTR_STOP_DET)) - i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val); + if (stat & IC_INTR_RX_FULL) { + if (dev->status != STATUS_WRITE_IN_PROGRESS) { + dev->status = STATUS_WRITE_IN_PROGRESS; + i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val); + } + do { + val = phytium_readl(dev, IC_DATA_CMD); + i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, &val); + val = phytium_readl(dev, IC_STATUS); + } while (val & BIT(3)); + } if (stat & IC_INTR_RD_REQ) { if (slave_activity) { - if (stat & IC_INTR_RX_FULL) { - val = phytium_readl(dev, IC_DATA_CMD); - - if (!i2c_slave_event(dev->slave, - I2C_SLAVE_WRITE_RECEIVED, - &val)) { - dev_vdbg(dev->dev, "Byte %X acked!", - val); - } - phytium_readl(dev, IC_CLR_RD_REQ); - stat = i2c_phytium_read_clear_intrbits_slave(dev); + phytium_readl(dev, IC_CLR_RD_REQ); + if (!(dev->status & STATUS_READ_IN_PROGRESS)) { + i2c_slave_event(dev->slave, I2C_SLAVE_READ_REQUESTED, &val); + dev->status |= STATUS_READ_IN_PROGRESS; + dev->status &= ~STATUS_WRITE_IN_PROGRESS; } else { - phytium_readl(dev, IC_CLR_RD_REQ); - phytium_readl(dev, IC_CLR_RX_UNDER); - stat = i2c_phytium_read_clear_intrbits_slave(dev); + i2c_slave_event(dev->slave, + I2C_SLAVE_READ_PROCESSED, &val); } - if (!i2c_slave_event(dev->slave, - I2C_SLAVE_READ_REQUESTED, - &val)) - phytium_writel(dev, val, IC_DATA_CMD); + phytium_writel(dev, val, IC_DATA_CMD); } } - if (stat & IC_INTR_RX_DONE) { - if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED, - &val)) - phytium_readl(dev, IC_CLR_RX_DONE); - - i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val); - stat = i2c_phytium_read_clear_intrbits_slave(dev); - return 1; - } - - if (stat & IC_INTR_RX_FULL) { - val = phytium_readl(dev, IC_DATA_CMD); - if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, - &val)) - dev_vdbg(dev->dev, "Byte %X acked!", val); - } else { + if (stat & IC_INTR_STOP_DET) { i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val); - stat = i2c_phytium_read_clear_intrbits_slave(dev); + dev->status = STATUS_IDLE; } return 1; @@ -212,7 +194,6 @@ static irqreturn_t i2c_phytium_isr_slave(int this_irq, void *dev_id) struct phytium_i2c_dev *dev = dev_id; int ret; - i2c_phytium_read_clear_intrbits_slave(dev); ret = i2c_phytium_irq_handler_slave(dev); if (ret > 0) complete(&dev->cmd_complete); @@ -237,12 +218,14 @@ int i2c_phytium_probe_slave(struct phytium_i2c_dev *dev) dev->disable = i2c_phytium_disable; dev->disable_int = i2c_phytium_disable_int; + dev->status = STATUS_IDLE; + ret = dev->init(dev); if (ret) return ret; snprintf(adap->name, sizeof(adap->name), - "Synopsys DesignWare I2C Slave adapter"); + "Phytium I2C Slave adapter"); adap->retries = 3; adap->algo = &i2c_phytium_algo; adap->dev.parent = dev->dev; -- Gitee From 24fd38a60f53effd6b4058bc462a4454ab0b75a2 Mon Sep 17 00:00:00 2001 From: Wu Jinyong Date: Thu, 30 May 2024 15:07:55 +0800 Subject: [PATCH 028/121] i3c: phytium: Restricting the use of driver on the phytium platforms. This patch uses the marco definition of CONFIG_ARCH_PHYTIUM to restrict the use of certain code segments on the phytium platforms, and does not compile this code for other platform, such as on X86 platform. Mainline: Open-Source Signed-off-by: Wu Jinyong Signed-off-by: Wang Yinfeng Change-Id: I4102fd36b70f0bfbeb97a896c95071f613974bc7 --- drivers/i3c/master.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 826f2877d5..a72fdea491 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -19,7 +19,7 @@ #include #include -#ifdef CONFIG_ACPI +#if defined(CONFIG_ACPI) && defined(CONFIG_ARCH_PHYTIUM) #include "i3c_master_acpi.h" #endif #include "internals.h" @@ -2252,7 +2252,7 @@ static int of_populate_i3c_bus(struct i3c_master_controller *master) return 0; } -#ifdef CONFIG_ACPI +#if defined(CONFIG_ACPI) && defined(CONFIG_ARCH_PHYTIUM) static int i3c_acpi_master_add_i2c_boardinfo(struct i3c_master_controller *master, struct acpi_device *adev, struct i3c_acpi_lookup *look_up) { @@ -2364,7 +2364,6 @@ static int i3c_acpi_master_get_slave_info(struct i3c_master_controller *master, return ret; } - static bool i3c_master_check_cpu_workaround(void) { u32 cpu_implementor; @@ -2916,7 +2915,7 @@ int i3c_master_register(struct i3c_master_controller *master, ret = of_populate_i3c_bus(master); if (ret) goto err_put_dev; -#ifdef CONFIG_ACPI +#if defined(CONFIG_ACPI) && defined(CONFIG_ARCH_PHYTIUM) i3c_acpi_register_devices(master); #endif list_for_each_entry(i2cbi, &master->boardinfo.i2c, node) { -- Gitee From 5ae1f4c29a17f43d48077cb3f72e741234a4fe94 Mon Sep 17 00:00:00 2001 From: Wu Jinyong Date: Tue, 9 Jul 2024 11:55:03 +0800 Subject: [PATCH 029/121] i3c:phytium: Enhance the logicality of parsing functions. This patch modifies the judgment criteria of parsing functions, making the code read more logically. Mainline: Open-Source Signed-off-by: Wu Jinyong Signed-off-by: Wang Yinfeng Change-Id: I65d7cbc946bf2c65573f9e2a8300d57215d554c3 --- drivers/i3c/i3c_master_acpi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/i3c/i3c_master_acpi.c b/drivers/i3c/i3c_master_acpi.c index 9346d882aa..d1c6189dc8 100644 --- a/drivers/i3c/i3c_master_acpi.c +++ b/drivers/i3c/i3c_master_acpi.c @@ -25,8 +25,9 @@ static int i3c_master_acpi_parse_val(union acpi_object *store_elements, char *me if (package_count == 2) { acpi_elements = acpi_elements[i].package.elements; - if (acpi_elements[0].type == ACPI_TYPE_STRING) { - if (!strcmp(acpi_elements[0].string.pointer, method)) { + if ((acpi_elements[0].type == ACPI_TYPE_STRING) && + (!strcmp(acpi_elements[0].string.pointer, method))) { + if (acpi_elements[1].type == ACPI_TYPE_INTEGER) { *value = acpi_elements[1].integer.value; ret = 0; break; -- Gitee From 6798baddad7aa65f2bbbc9e23a5a8618dceed60c Mon Sep 17 00:00:00 2001 From: Wu Jinyong Date: Fri, 29 Nov 2024 14:35:11 +0800 Subject: [PATCH 030/121] i2c:phytium: Combine normal mode into master-slave switching mode This patch combines normal mode into master-slave switching mode,the application can use master mode or slave mode or master-slave switching mode. Mainline: Open-Source Signed-off-by: Wu Jinyong Signed-off-by: Wang Yinfeng Change-Id: Ic18ed6eca2f841d895017af4914b021fafc27c2b --- drivers/i2c/busses/Makefile | 2 +- drivers/i2c/busses/i2c-phytium-common.c | 44 +- drivers/i2c/busses/i2c-phytium-core.h | 49 +- ...i2c-phytium-master.c => i2c-phytium-mix.c} | 515 ++++++++++++++---- drivers/i2c/busses/i2c-phytium-platform.c | 49 +- 5 files changed, 472 insertions(+), 187 deletions(-) rename drivers/i2c/busses/{i2c-phytium-master.c => i2c-phytium-mix.c} (51%) diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 96b78a36f3..36e48488f7 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -94,7 +94,7 @@ obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi-core.o i2c-pasemi-pci.o obj-$(CONFIG_I2C_APPLE) += i2c-pasemi-core.o i2c-pasemi-platform.o obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o obj-$(CONFIG_I2C_PHYTIUM_CORE) += i2c-phytium-core.o -i2c-phytium-core-objs := i2c-phytium-common.o i2c-phytium-master.o i2c-phytium-slave.o +i2c-phytium-core-objs := i2c-phytium-common.o i2c-phytium-mix.o obj-$(CONFIG_I2C_PHYTIUM_PCI) += i2c-phytium-pci.o obj-$(CONFIG_I2C_PHYTIUM_PLATFORM) += i2c-phytium-platform.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o diff --git a/drivers/i2c/busses/i2c-phytium-common.c b/drivers/i2c/busses/i2c-phytium-common.c index 2c866fa8e8..b008e6a10b 100644 --- a/drivers/i2c/busses/i2c-phytium-common.c +++ b/drivers/i2c/busses/i2c-phytium-common.c @@ -2,11 +2,6 @@ /* * Phytium I2C adapter driver. * - * Derived from Synopysys I2C driver. - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * Copyright (C) 2009 Provigent Ltd. - * * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. */ #include @@ -20,6 +15,7 @@ #include #include #include +#include #include "i2c-phytium-core.h" @@ -96,22 +92,7 @@ int i2c_phytium_set_sda_hold(struct phytium_i2c_dev *dev) void __i2c_phytium_disable(struct phytium_i2c_dev *dev) { - int timeout = 100; - - do { - __i2c_phytium_disable_nowait(dev); - if ((phytium_readl(dev, IC_ENABLE_STATUS) & 1) == 0) - return; - - /* - * Wait 10 times the signaling period of the highest I2C - * transfer supported by the driver (for 400KHz this is - * 25us). - */ - usleep_range(25, 250); - } while (timeout--); - - dev_warn(dev->dev, "timeout in disabling adapter\n"); + __i2c_phytium_disable_nowait(dev); } unsigned long i2c_phytium_clk_rate(struct phytium_i2c_dev *dev) @@ -134,23 +115,12 @@ int i2c_phytium_prepare_clk(struct phytium_i2c_dev *dev, bool prepare) } EXPORT_SYMBOL_GPL(i2c_phytium_prepare_clk); -int i2c_phytium_wait_bus_not_busy(struct phytium_i2c_dev *dev) +int i2c_phytium_check_bus_not_busy(struct phytium_i2c_dev *dev) { - int timeout = 20; /* 20 ms */ - - while (phytium_readl(dev, IC_STATUS) & IC_STATUS_ACTIVITY) { - if (timeout <= 0) { - dev_warn(dev->dev, "timeout waiting for bus ready\n"); - i2c_recover_bus(&dev->adapter); - - if (phytium_readl(dev, IC_STATUS) & IC_STATUS_ACTIVITY) - return -ETIMEDOUT; - return 0; - } - timeout--; - usleep_range(1000, 1100); - } - + if (dev->slave_state != SLAVE_STATE_IDLE) + return -EAGAIN; + if (phytium_readl(dev, IC_STATUS) & IC_STATUS_ACTIVITY) + return -ETIMEDOUT; return 0; } diff --git a/drivers/i2c/busses/i2c-phytium-core.h b/drivers/i2c/busses/i2c-phytium-core.h index 7423ccb1b0..62900e1115 100644 --- a/drivers/i2c/busses/i2c-phytium-core.h +++ b/drivers/i2c/busses/i2c-phytium-core.h @@ -2,11 +2,6 @@ /* * Phytium I2C adapter driver. * - * Derived from Synopysys I2C driver. - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * Copyright (C) 2009 Provigent Ltd. - * * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. */ @@ -14,8 +9,13 @@ #include #include +#include + +#define I2C_PHYTIUM_DRV_VERSION "1.0.0" + #define IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \ I2C_FUNC_SMBUS_BYTE | \ + I2C_FUNC_SMBUS_QUICK | \ I2C_FUNC_SMBUS_BYTE_DATA | \ I2C_FUNC_SMBUS_WORD_DATA | \ I2C_FUNC_SMBUS_BLOCK_DATA | \ @@ -93,7 +93,6 @@ #define IC_INTR_SMBALERT_IN_N 0x20000 #define IC_INTR_DEFAULT_MASK (IC_INTR_RX_FULL | \ - IC_INTR_TX_ABRT | \ IC_INTR_STOP_DET) #define IC_INTR_MASTER_MASK (IC_INTR_DEFAULT_MASK | \ IC_INTR_TX_EMPTY) @@ -104,7 +103,8 @@ #define IC_INTR_SMBUS_MASK (IC_INTR_MASTER_MASK | \ IC_INTR_SMBCLK_EXT_LOW_TIMEOUT | \ IC_INTR_SMBCLK_TMO_LOW_TIMEOUT | \ - IC_INTR_SMBSDA_LOW_TIMEOUT) + IC_INTR_SMBSDA_LOW_TIMEOUT | \ + IC_INTR_SMBALERT_IN_N) #define IC_STATUS_ACTIVITY 0x1 #define IC_STATUS_TFE BIT(2) @@ -115,6 +115,15 @@ #define IC_SDA_HOLD_RX_MASK GENMASK(23, IC_SDA_HOLD_RX_SHIFT) #define IC_ERR_TX_ABRT 0x1 +#define IC_ERR_SMBLK_READ_ZERO BIT(31) + +#define IC_ENABLE_EN BIT(0) +#define IC_ENABLE_ALERT_EN BIT(5) +#define IC_ENABLE_RXDATA_ADVANCE_EN BIT(11) +#define IC_ENABLE_MASK (IC_ENABLE_EN | \ + IC_ENABLE_ALERT_EN | \ + IC_ENABLE_RXDATA_ADVANCE_EN) +#define IC_DISABLE_MASK IC_ENABLE_ALERT_EN #define IC_TAR_10BITADDR_MASTER BIT(12) @@ -131,6 +140,15 @@ #define PHYTIUM_IC_MASTER 0 #define PHYTIUM_IC_SLAVE 1 +#if IS_ENABLED(CONFIG_I2C_SLAVE) +enum i2c_slave_state { + SLAVE_STATE_IDLE, + SLAVE_STATE_RECV, + SLAVE_STATE_SEND, + SLAVE_STATE_REQUEST, + SLAVE_STATE_RESPONSE +}; +#endif #define ABRT_7B_ADDR_NOACK 0 #define ABRT_10ADDR1_NOACK 1 #define ABRT_10ADDR2_NOACK 2 @@ -178,6 +196,12 @@ struct phytium_i2c_dev { struct clk *clk; struct reset_control *rst; int mode; + + u32 capability; +#if IS_ENABLED(CONFIG_I2C_SLAVE) + enum i2c_slave_state slave_state; +#endif + spinlock_t i2c_lock; struct i2c_client *slave; u32 (*get_clk_rate_khz)(struct phytium_i2c_dev *dev); @@ -220,6 +244,7 @@ struct phytium_i2c_dev { u16 hs_lcnt; bool pm_disabled; + bool first_time_init_master; void (*disable)(struct phytium_i2c_dev *dev); void (*disable_int)(struct phytium_i2c_dev *dev); int (*init)(struct phytium_i2c_dev *dev); @@ -233,7 +258,7 @@ u32 phytium_readl(struct phytium_i2c_dev *dev, int offset); void phytium_writel(struct phytium_i2c_dev *dev, u32 b, int offset); unsigned long i2c_phytium_clk_rate(struct phytium_i2c_dev *dev); int i2c_phytium_prepare_clk(struct phytium_i2c_dev *dev, bool prepare); -int i2c_phytium_wait_bus_not_busy(struct phytium_i2c_dev *dev); +int i2c_phytium_check_bus_not_busy(struct phytium_i2c_dev *dev); int i2c_phytium_handle_tx_abort(struct phytium_i2c_dev *dev); u32 i2c_phytium_func(struct i2c_adapter *adap); void i2c_phytium_disable(struct phytium_i2c_dev *dev); @@ -244,16 +269,14 @@ u32 i2c_phytium_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset); static inline void __i2c_phytium_enable(struct phytium_i2c_dev *dev) { - phytium_writel(dev, 1, IC_ENABLE); + phytium_writel(dev, IC_ENABLE_MASK, IC_ENABLE); } static inline void __i2c_phytium_disable_nowait(struct phytium_i2c_dev *dev) { - phytium_writel(dev, 0, IC_ENABLE); + phytium_writel(dev, IC_DISABLE_MASK, IC_ENABLE); } void __i2c_phytium_disable(struct phytium_i2c_dev *dev); - +void i2c_phytium_configure_master(struct phytium_i2c_dev *dev); extern int i2c_phytium_probe(struct phytium_i2c_dev *dev); - -extern int i2c_phytium_probe_slave(struct phytium_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-phytium-master.c b/drivers/i2c/busses/i2c-phytium-mix.c similarity index 51% rename from drivers/i2c/busses/i2c-phytium-master.c rename to drivers/i2c/busses/i2c-phytium-mix.c index ca745b146b..748042c9fe 100644 --- a/drivers/i2c/busses/i2c-phytium-master.c +++ b/drivers/i2c/busses/i2c-phytium-mix.c @@ -2,13 +2,9 @@ /* * Phytium I2C adapter driver. * - * Derived from Synopysys I2C driver. - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * Copyright (C) 2009 Provigent Ltd. - * * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. */ +#include #include #include #include @@ -22,6 +18,78 @@ #include "i2c-phytium-core.h" +#define I2C_TRANS_READ_CMD BIT(8) +#define I2C_TRANS_STOP_CMD BIT(9) +#define I2C_TRANS_RESTART_CMD BIT(10) +#define I2C_QUICK_CMD_BIT_SET BIT(13) +#define DEFAULT_TIMEOUT (DEFAULT_CLOCK_FREQUENCY / 1000 * 35) + +static int i2c_phytium_recover_controller(struct phytium_i2c_dev *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->i2c_lock, flags); + + reset_control_reset(dev->rst); +#if IS_ENABLED(CONFIG_I2C_SLAVE) + dev->slave_state = SLAVE_STATE_IDLE; + dev->status = STATUS_IDLE; + if (dev->slave) + phytium_writel(dev, dev->slave->addr, IC_SAR); +#endif + + spin_unlock_irqrestore(&dev->i2c_lock, flags); + return 0; +} + +static int i2c_phytium_init_slave(struct phytium_i2c_dev *dev) +{ + /* Disable the adapter. */ + __i2c_phytium_disable(dev); + + /* Write SDA hold time if supported */ + if (dev->sda_hold_time) + phytium_writel(dev, dev->sda_hold_time, IC_SDA_HOLD); + + /* Configure Tx/Rx FIFO threshold levels. */ + phytium_writel(dev, 0, IC_TX_TL); + phytium_writel(dev, 0, IC_RX_TL); + dev->mode = PHYTIUM_IC_SLAVE; + + /* Configure the I2C slave. */ + dev->slave_cfg = IC_CON_RX_FIFO_FULL_HLD_CTRL | IC_CON_RESTART_EN | + IC_CON_STOP_DET_IFADDRESSED; + phytium_writel(dev, dev->slave_cfg, IC_CON); + phytium_writel(dev, IC_INTR_SLAVE_MASK, IC_INTR_MASK); + + return 0; +} + +void i2c_phytium_configure_master(struct phytium_i2c_dev *dev) +{ + struct i2c_timings *t = &dev->timings; + + dev->functionality = I2C_FUNC_10BIT_ADDR | IC_DEFAULT_FUNCTIONALITY | + I2C_FUNC_SLAVE; + + dev->master_cfg = + IC_CON_MASTER | IC_CON_SLAVE_DISABLE | IC_CON_RESTART_EN; + + dev->mode = PHYTIUM_IC_MASTER; + + switch (t->bus_freq_hz) { + case 100000: + dev->master_cfg |= IC_CON_SPEED_STD; + break; + case 3400000: + dev->master_cfg |= IC_CON_SPEED_HIGH; + break; + default: + dev->master_cfg |= IC_CON_SPEED_FAST; + } +} +EXPORT_SYMBOL_GPL(i2c_phytium_configure_master); + static int i2c_phytium_init_master(struct phytium_i2c_dev *dev) { /* Disable the adapter */ @@ -40,7 +108,7 @@ static int i2c_phytium_init_master(struct phytium_i2c_dev *dev) phytium_writel(dev, dev->hs_hcnt, IC_HS_SCL_HCNT); phytium_writel(dev, dev->hs_lcnt, IC_HS_SCL_LCNT); } - + dev->mode = PHYTIUM_IC_MASTER; /* Write SDA hold time if supported */ if (dev->sda_hold_time) phytium_writel(dev, dev->sda_hold_time, IC_SDA_HOLD); @@ -50,11 +118,29 @@ static int i2c_phytium_init_master(struct phytium_i2c_dev *dev) phytium_writel(dev, 0, IC_RX_TL); /* Configure the I2C master */ + if (dev->first_time_init_master == false) { + i2c_phytium_configure_master(dev); + dev->first_time_init_master = true; + } phytium_writel(dev, dev->master_cfg, IC_CON); return 0; } +#if IS_ENABLED(CONFIG_I2C_SLAVE) +static void i2c_phytium_change_mode(int target_mode, struct phytium_i2c_dev *dev) +{ + if (target_mode == PHYTIUM_IC_MASTER) { + dev->disable_int(dev); + dev->disable(dev); + i2c_phytium_init_master(dev); + } else { + i2c_phytium_init_slave(dev); + __i2c_phytium_enable(dev); + } +} +#endif + static void i2c_phytium_xfer_init(struct phytium_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; @@ -63,6 +149,9 @@ static void i2c_phytium_xfer_init(struct phytium_i2c_dev *dev) /* Disable the adapter */ __i2c_phytium_disable(dev); + if ((dev->capability & I2C_FUNC_SMBUS_QUICK) && (msgs[0].len == 0)) + ic_tar = I2C_QUICK_CMD_BIT_SET; + /* If the slave address is 10-bit address, enable 10BITADDR */ ic_con = phytium_readl(dev, IC_CON); if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { @@ -104,23 +193,26 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) u8 *buf = dev->tx_buf; bool need_restart = false; - intr_mask = IC_INTR_MASTER_MASK; + intr_mask = IC_INTR_SMBUS_MASK; for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { u32 flags = msgs[dev->msg_write_idx].flags; if (msgs[dev->msg_write_idx].addr != addr) { - dev_err(dev->dev, - "%s: invalid target address\n", __func__); dev->msg_err = -EINVAL; break; } + /* If the register dose not support smbus block read function, + * then use the operation of program code + */ + if (!(dev->capability & I2C_FUNC_SMBUS_BLOCK_DATA) && + (flags & I2C_M_RECV_LEN)) + msgs[dev->msg_write_idx].len = 1 + I2C_SMBUS_BLOCK_MAX; if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { /* new i2c_msg */ buf = msgs[dev->msg_write_idx].buf; buf_len = msgs[dev->msg_write_idx].len; - if ((dev->master_cfg & IC_CON_RESTART_EN) && (dev->msg_write_idx > 0)) need_restart = true; @@ -128,16 +220,14 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) tx_limit = dev->tx_fifo_depth - phytium_readl(dev, IC_TXFLR); rx_limit = dev->tx_fifo_depth - phytium_readl(dev, IC_RXFLR); - while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { u32 cmd = 0; - if (dev->msg_write_idx == dev->msgs_num - 1 && - buf_len == 1 && !(flags & I2C_M_RECV_LEN)) - cmd |= BIT(9); + if (dev->msg_write_idx == dev->msgs_num - 1 && buf_len == 1) + cmd |= I2C_TRANS_STOP_CMD; if (need_restart) { - cmd |= BIT(10); + cmd |= I2C_TRANS_RESTART_CMD; need_restart = false; } @@ -146,7 +236,7 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) if (dev->rx_outstanding >= dev->rx_fifo_depth) break; - phytium_writel(dev, cmd | 0x100, IC_DATA_CMD); + phytium_writel(dev, cmd | I2C_TRANS_READ_CMD, IC_DATA_CMD); rx_limit--; dev->rx_outstanding++; } else { @@ -164,22 +254,30 @@ static void i2c_phytium_xfer_msg(struct phytium_i2c_dev *dev) * I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop * the transaction here. */ - if (buf_len > 0 || flags & I2C_M_RECV_LEN) { + if (buf_len > 0) { /* more bytes to be written */ dev->status |= STATUS_WRITE_IN_PROGRESS; break; } - dev->status &= ~STATUS_WRITE_IN_PROGRESS; } + /*This is use for quick cmd*/ + if ((dev->capability & I2C_FUNC_SMBUS_QUICK) && (msgs[0].len == 0)) { + if (msgs[0].flags == I2C_M_RD) + phytium_writel(dev, I2C_TRANS_STOP_CMD | I2C_TRANS_READ_CMD, + IC_DATA_CMD); + else + phytium_writel(dev, I2C_TRANS_STOP_CMD, IC_DATA_CMD); + } + if (dev->msg_write_idx == dev->msgs_num) intr_mask &= ~IC_INTR_TX_EMPTY; if (dev->msg_err) intr_mask = 0; - phytium_writel(dev, intr_mask, IC_INTR_MASK); + phytium_writel(dev, intr_mask, IC_INTR_MASK); } static u8 i2c_phytium_recv_len(struct phytium_i2c_dev *dev, u8 len) @@ -191,10 +289,17 @@ static u8 i2c_phytium_recv_len(struct phytium_i2c_dev *dev, u8 len) * Adjust the buffer length and mask the flag * after receiving the first byte. */ + if (len > I2C_SMBUS_BLOCK_MAX) + len = 0; + len += (flags & I2C_CLIENT_PEC) ? 2 : 1; dev->tx_buf_len = len - min_t(u8, len, dev->rx_outstanding); - msgs[dev->msg_read_idx].len = len; - msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN; + + /* require adding one byte to trigger the i2c_phytium_xfer finishing the transaction. */ + if (dev->tx_buf_len == 0) { + dev->tx_buf_len = 1; + len = dev->rx_outstanding + 1; + } return len; } @@ -226,9 +331,19 @@ static void i2c_phytium_read(struct phytium_i2c_dev *dev) *buf = phytium_readl(dev, IC_DATA_CMD); /* Ensure length byte is a valid value */ - if (flags & I2C_M_RECV_LEN && - *buf <= I2C_SMBUS_BLOCK_MAX && *buf > 0) { + if (flags & I2C_M_RECV_LEN) { + msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN; len = i2c_phytium_recv_len(dev, *buf); + if (*buf > I2C_SMBUS_BLOCK_MAX || *buf == 0) { + dev_err(dev->dev, + "The value %d is out of the SMBus range [1~32]\n", + *buf); + *buf = 0; + dev->cmd_err = IC_ERR_SMBLK_READ_ZERO; + } else { + msgs[dev->msg_read_idx].len = *buf + + ((flags & I2C_CLIENT_PEC) ? 2 : 1); + } } buf++; dev->rx_outstanding--; @@ -240,21 +355,28 @@ static void i2c_phytium_read(struct phytium_i2c_dev *dev) dev->rx_buf = buf; return; } - dev->status &= ~STATUS_READ_IN_PROGRESS; } } -static int i2c_phytium_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num) +static int i2c_phytium_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], + int num) { struct phytium_i2c_dev *dev = i2c_get_adapdata(adapter); int ret; + unsigned long flags; dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); - pm_runtime_get_sync(dev->dev); + ret = pm_runtime_get_sync(dev->dev); + if (ret < 0) { + dev_err(dev->dev, "pm runtime get sync err.\n"); + goto pm_exit; + } + spin_lock_irqsave(&dev->i2c_lock, flags); reinit_completion(&dev->cmd_complete); + dev->msgs = msgs; dev->msgs_num = num; dev->cmd_err = 0; @@ -265,22 +387,30 @@ static int i2c_phytium_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], dev->abort_source = 0; dev->rx_outstanding = 0; - ret = i2c_phytium_wait_bus_not_busy(dev); + ret = i2c_phytium_check_bus_not_busy(dev); if (ret < 0) goto done; +#if IS_ENABLED(CONFIG_I2C_SLAVE) + if (dev->slave_cfg) + i2c_phytium_change_mode(PHYTIUM_IC_MASTER, dev); +#endif + /* Start the transfers */ i2c_phytium_xfer_init(dev); - + spin_unlock_irqrestore(&dev->i2c_lock, flags); /* Wait for tx to complete */ - if (!wait_for_completion_timeout(&dev->cmd_complete, adapter->timeout)) { + if (!wait_for_completion_timeout(&dev->cmd_complete, + adapter->timeout)) { dev_err(dev->dev, "controller timed out\n"); - i2c_recover_bus(&dev->adapter); - i2c_phytium_init_master(dev); + i2c_phytium_recover_controller(dev); + spin_lock_irqsave(&dev->i2c_lock, flags); + if (!dev->slave_cfg) + i2c_phytium_init_master(dev); ret = -ETIMEDOUT; goto done; } - + spin_lock_irqsave(&dev->i2c_lock, flags); __i2c_phytium_disable_nowait(dev); if (dev->msg_err) { @@ -295,29 +425,99 @@ static int i2c_phytium_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], /* We have got an error */ if (dev->cmd_err == IC_ERR_TX_ABRT) { + spin_unlock_irqrestore(&dev->i2c_lock, flags); ret = i2c_phytium_handle_tx_abort(dev); + spin_lock_irqsave(&dev->i2c_lock, flags); goto done; } - if (dev->status) - dev_err(dev->dev, "transfer terminated early.\n"); - ret = -EIO; done: +#if IS_ENABLED(CONFIG_I2C_SLAVE) + if (dev->slave_cfg) + i2c_phytium_change_mode(PHYTIUM_IC_SLAVE, dev); + dev->status = STATUS_IDLE; + dev->slave_state = SLAVE_STATE_IDLE; +#endif + spin_unlock_irqrestore(&dev->i2c_lock, flags); + +pm_exit: + pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); return ret; } +#if IS_ENABLED(CONFIG_I2C_SLAVE) +static int i2c_phytium_reg_slave(struct i2c_client *slave) +{ + int ret = 0; + unsigned long flags; + struct phytium_i2c_dev *dev = i2c_get_adapdata(slave->adapter); + + spin_lock_irqsave(&dev->i2c_lock, flags); + + if (dev->slave) { + ret = -EBUSY; + goto abort; + } + if (slave->flags & I2C_CLIENT_TEN) { + ret = -EAFNOSUPPORT; + goto abort; + } + pm_runtime_get_sync(dev->dev); + + /* + * Set slave address in the IC_SAR register, + * the address to which the i2c responds. + */ + i2c_phytium_init_slave(dev); + phytium_writel(dev, slave->addr, IC_SAR); + dev->slave = slave; + dev->mode = PHYTIUM_IC_SLAVE; + __i2c_phytium_enable(dev); + + dev->cmd_err = 0; + dev->msg_write_idx = 0; + dev->msg_read_idx = 0; + dev->msg_err = 0; + dev->status = STATUS_IDLE; + dev->abort_source = 0; + dev->rx_outstanding = 0; + +abort: + spin_unlock_irqrestore(&dev->i2c_lock, flags); + return ret; +} + +static int i2c_phytium_unreg_slave(struct i2c_client *slave) +{ + unsigned long flags; + struct phytium_i2c_dev *dev = i2c_get_adapdata(slave->adapter); + + spin_lock_irqsave(&dev->i2c_lock, flags); + + dev->disable_int(dev); + dev->disable(dev); + dev->slave = NULL; + pm_runtime_put(dev->dev); + + dev->mode = PHYTIUM_IC_MASTER; + i2c_phytium_init_master(dev); + spin_unlock_irqrestore(&dev->i2c_lock, flags); + return 0; +} +#endif + static const struct i2c_algorithm i2c_phytium_algo = { .master_xfer = i2c_phytium_xfer, .functionality = i2c_phytium_func, -}; - -static const struct i2c_adapter_quirks i2c_phytium_quirks = { - .flags = I2C_AQ_NO_ZERO_LEN, +#if IS_ENABLED(CONFIG_I2C_SLAVE) + .reg_slave = i2c_phytium_reg_slave, + .unreg_slave = i2c_phytium_unreg_slave, +#endif }; static u32 i2c_phytium_read_clear_intrbits(struct phytium_i2c_dev *dev) @@ -335,7 +535,8 @@ static u32 i2c_phytium_read_clear_intrbits(struct phytium_i2c_dev *dev) if (stat & IC_INTR_RD_REQ) phytium_readl(dev, IC_CLR_RD_REQ); if (stat & IC_INTR_TX_ABRT) { - dev->abort_source = phytium_readl(dev, IC_TX_ABRT_SOURCE); + if (dev->mode == PHYTIUM_IC_MASTER) + dev->abort_source = phytium_readl(dev, IC_TX_ABRT_SOURCE); phytium_readl(dev, IC_CLR_TX_ABRT); } if (stat & IC_INTR_RX_DONE) @@ -362,12 +563,14 @@ static u32 i2c_phytium_read_clear_intrbits(struct phytium_i2c_dev *dev) static int i2c_phytium_irq_handler_master(struct phytium_i2c_dev *dev) { - u32 stat; + u32 stat, raw_stat; + raw_stat = phytium_readl(dev, IC_RAW_INTR_STAT); stat = i2c_phytium_read_clear_intrbits(dev); /* SMBus interrupt */ - if (stat & (IC_INTR_SMBCLK_EXT_LOW_TIMEOUT | IC_INTR_SMBCLK_TMO_LOW_TIMEOUT)) { + if (stat & + (IC_INTR_SMBCLK_EXT_LOW_TIMEOUT | IC_INTR_SMBCLK_TMO_LOW_TIMEOUT)) { phytium_writel(dev, phytium_readl(dev, IC_ENABLE) & (~BIT(6)), IC_ENABLE); phytium_writel(dev, phytium_readl(dev, IC_ENABLE) | BIT(4), @@ -384,15 +587,25 @@ static int i2c_phytium_irq_handler_master(struct phytium_i2c_dev *dev) if (stat & IC_INTR_SMBALERT_IN_N && dev->ara) i2c_handle_smbus_alert(dev->ara); - if (stat & IC_INTR_TX_ABRT) { - dev->cmd_err |= IC_ERR_TX_ABRT; - dev->status = STATUS_IDLE; - - /* Anytime TX_ABRT is set, the contents of the tx/rx - * buffers are flushed. Make sure to skip them. - */ - phytium_writel(dev, 0, IC_INTR_MASK); - goto abort; + if (raw_stat & IC_INTR_TX_ABRT) { + if (stat & IC_INTR_TX_ABRT) { + dev->cmd_err |= IC_ERR_TX_ABRT; + dev->status = STATUS_IDLE; + + /* Anytime TX_ABRT is set, the contents of the tx/rx + * buffers are flushed. Make sure to skip them. + */ + phytium_writel(dev, 0, IC_INTR_MASK); + goto abort; + } else if (stat & IC_INTR_STOP_DET) { + dev->cmd_err |= IC_ERR_TX_ABRT; + dev->status = STATUS_IDLE; + phytium_readl(dev, IC_CLR_TX_ABRT); + phytium_writel(dev, 0, IC_INTR_MASK); + + complete(&dev->cmd_complete); + return 0; + } } if (stat & IC_INTR_RX_FULL) @@ -402,10 +615,9 @@ static int i2c_phytium_irq_handler_master(struct phytium_i2c_dev *dev) i2c_phytium_xfer_msg(dev); abort: - if ((stat & (IC_INTR_TX_ABRT | IC_INTR_STOP_DET)) || - dev->msg_err) + if ((stat & IC_INTR_TX_ABRT) || (stat & IC_INTR_STOP_DET) || dev->msg_err) { complete(&dev->cmd_complete); - else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { + } else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { /* Workaround to trigger pending interrupt */ stat = phytium_readl(dev, IC_INTR_MASK); i2c_phytium_disable_int(dev); @@ -415,6 +627,93 @@ static int i2c_phytium_irq_handler_master(struct phytium_i2c_dev *dev) return 0; } +static int i2c_phytium_irq_handler_slave(struct phytium_i2c_dev *dev) +{ + u32 raw_stat, stat, enabled; + u8 val, slave_activity; + + enabled = phytium_readl(dev, IC_ENABLE); + raw_stat = phytium_readl(dev, IC_RAW_INTR_STAT); + slave_activity = + ((phytium_readl(dev, IC_STATUS) & IC_STATUS_SLAVE_ACTIVITY) >> + 6); + + if (!enabled || !(raw_stat & ~IC_INTR_ACTIVITY) || !dev->slave) + return 0; + + stat = i2c_phytium_read_clear_intrbits(dev); + + if (stat & IC_INTR_RX_FULL) { + if (dev->status != STATUS_WRITE_IN_PROGRESS) { + dev->status = STATUS_WRITE_IN_PROGRESS; + i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, + &val); + dev->slave_state = SLAVE_STATE_RECV; + } + do { + val = phytium_readl(dev, IC_DATA_CMD); + i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, + &val); + val = phytium_readl(dev, IC_STATUS); + } while (val & BIT(3)); + } + + if (stat & IC_INTR_RD_REQ) { + if (slave_activity) { + phytium_readl(dev, IC_CLR_RD_REQ); + + if (!(dev->status & STATUS_READ_IN_PROGRESS)) { + i2c_slave_event(dev->slave, + I2C_SLAVE_READ_REQUESTED, &val); + dev->status |= STATUS_READ_IN_PROGRESS; + dev->status &= ~STATUS_WRITE_IN_PROGRESS; + dev->slave_state = SLAVE_STATE_SEND; + + } else { + i2c_slave_event(dev->slave, + I2C_SLAVE_READ_PROCESSED, &val); + } + phytium_writel(dev, val, IC_DATA_CMD); + } + } + + if (stat & IC_INTR_STOP_DET) { + i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val); +#if IS_ENABLED(CONFIG_I2C_SLAVE) + dev->status = STATUS_IDLE; + dev->slave_state = SLAVE_STATE_IDLE; +#endif + } + + return 1; +} + +static irqreturn_t i2c_phytium_isr(int this_irq, void *dev_id) +{ + struct phytium_i2c_dev *dev = dev_id; + u32 stat, enabled; + + spin_lock(&dev->i2c_lock); + +#if IS_ENABLED(CONFIG_I2C_SLAVE) + if (dev->mode == PHYTIUM_IC_SLAVE) { + i2c_phytium_irq_handler_slave(dev); + spin_unlock(&dev->i2c_lock); + return IRQ_HANDLED; + } +#endif + enabled = phytium_readl(dev, IC_ENABLE); + stat = phytium_readl(dev, IC_RAW_INTR_STAT); + if (!enabled || !(stat & ~IC_INTR_ACTIVITY)) { + spin_unlock(&dev->i2c_lock); + return IRQ_NONE; + } + + i2c_phytium_irq_handler_master(dev); + spin_unlock(&dev->i2c_lock); + return IRQ_HANDLED; +} + static int i2c_phytium_set_timings_master(struct phytium_i2c_dev *dev) { const char *mode_str, *fp_str = ""; @@ -430,24 +729,21 @@ static int i2c_phytium_set_timings_master(struct phytium_i2c_dev *dev) /* Calculate SCL timing parameters for standard mode if not set */ if (!dev->ss_hcnt || !dev->ss_lcnt) { ic_clk = i2c_phytium_clk_rate(dev); - dev->ss_hcnt = - i2c_phytium_scl_hcnt(ic_clk, - 4000, /* tHD;STA = tHIGH = 4.0 us */ - sda_falling_time, - 0, /* 0: DW default, 1: Ideal */ - 0); /* No offset */ + dev->ss_hcnt = i2c_phytium_scl_hcnt( + ic_clk, 4000, /* tHD;STA = tHIGH = 4.0 us */ + sda_falling_time, 0, /* 0: DW default, 1: Ideal */ + 0); /* No offset */ dev->ss_lcnt = - i2c_phytium_scl_lcnt(ic_clk, - 4700, /* tLOW = 4.7 us */ - scl_falling_time, - 0); /* No offset */ + i2c_phytium_scl_lcnt(ic_clk, 4700, /* tLOW = 4.7 us */ + scl_falling_time, + 0); /* No offset */ } - dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n", - dev->ss_hcnt, dev->ss_lcnt); + dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n", dev->ss_hcnt, + dev->ss_lcnt); /* * Set SCL timing parameters for fast mode or fast mode plus. Only - * difference is the timing parameter values since the registers are - * the same. + * difference is the timing parameter values since the registers + * are the same. */ if (t->bus_freq_hz == 1000000) { /* @@ -466,20 +762,17 @@ static int i2c_phytium_set_timings_master(struct phytium_i2c_dev *dev) */ if (!dev->fs_hcnt || !dev->fs_lcnt) { ic_clk = i2c_phytium_clk_rate(dev); - dev->fs_hcnt = - i2c_phytium_scl_hcnt(ic_clk, - 600, /* tHD;STA = tHIGH = 0.6 us */ - sda_falling_time, - 0, /* 0: DW default, 1: Ideal */ - 0); /* No offset */ + dev->fs_hcnt = i2c_phytium_scl_hcnt( + ic_clk, 600, /* tHD;STA = tHIGH = 0.6 us */ + sda_falling_time, 0, /* 0: DW default, 1: Ideal */ + 0); /* No offset */ dev->fs_lcnt = - i2c_phytium_scl_lcnt(ic_clk, - 1300, /* tLOW = 1.3 us */ - scl_falling_time, - 0); /* No offset */ + i2c_phytium_scl_lcnt(ic_clk, 1300, /* tLOW = 1.3 us */ + scl_falling_time, + 0); /* No offset */ } - dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n", - fp_str, dev->fs_hcnt, dev->fs_lcnt); + dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n", fp_str, + dev->fs_hcnt, dev->fs_lcnt); if (dev->hs_hcnt && dev->hs_lcnt) dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n", @@ -505,19 +798,18 @@ static int i2c_phytium_set_timings_master(struct phytium_i2c_dev *dev) return ret; } -static irqreturn_t i2c_phytium_isr(int this_irq, void *dev_id) +static int i2c_phytium_enable_smbus_alert(struct phytium_i2c_dev *i2c_dev) { - struct phytium_i2c_dev *dev = dev_id; - u32 stat, enabled; + struct i2c_adapter *adap = &i2c_dev->adapter; + struct i2c_smbus_alert_setup setup; - enabled = phytium_readl(dev, IC_ENABLE); - stat = phytium_readl(dev, IC_RAW_INTR_STAT); - if (!enabled || !(stat & ~IC_INTR_ACTIVITY)) - return IRQ_NONE; + setup.irq = 0; + i2c_dev->ara = i2c_new_smbus_alert_device(adap, &setup); - i2c_phytium_irq_handler_master(dev); + if (IS_ERR(i2c_dev->ara)) + return PTR_ERR(i2c_dev->ara); - return IRQ_HANDLED; + return 0; } int i2c_phytium_probe(struct phytium_i2c_dev *dev) @@ -525,13 +817,21 @@ int i2c_phytium_probe(struct phytium_i2c_dev *dev) struct i2c_adapter *adapter = &dev->adapter; unsigned long irq_flags; int ret; + u32 alert = 0; init_completion(&dev->cmd_complete); + if (dev->mode == PHYTIUM_IC_MASTER) { + snprintf(adapter->name, sizeof(adapter->name), + "Phytium I2C Adapter"); + dev->init = i2c_phytium_init_master; + } else if (dev->mode == PHYTIUM_IC_SLAVE) { + snprintf(adapter->name, sizeof(adapter->name), + "Phytium I2C Slave Adapter"); + dev->init = i2c_phytium_init_slave; + } - dev->init = i2c_phytium_init_master; dev->disable = i2c_phytium_disable; dev->disable_int = i2c_phytium_disable_int; - ret = i2c_phytium_set_timings_master(dev); if (ret) return ret; @@ -540,16 +840,14 @@ int i2c_phytium_probe(struct phytium_i2c_dev *dev) if (ret) return ret; - /* XXX: should be initialized in firmware, remove it in future */ -#define DEFAULT_TIMEOUT (DEFAULT_CLOCK_FREQUENCY / 1000 * 35) - phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBCLK_LOW_MEXT); - phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBCLK_LOW_TIMEOUT); - phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBDAT_STUCK_TIMEOUT); + if (dev->mode == PHYTIUM_IC_MASTER) { + phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBCLK_LOW_MEXT); + phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBCLK_LOW_TIMEOUT); + phytium_writel(dev, DEFAULT_TIMEOUT, IC_SMBDAT_STUCK_TIMEOUT); + } - snprintf(adapter->name, sizeof(adapter->name), "Phytium I2C adapter"); adapter->retries = 3; adapter->algo = &i2c_phytium_algo; - adapter->quirks = &i2c_phytium_quirks; adapter->dev.parent = dev->dev; i2c_set_adapdata(adapter, dev); @@ -559,7 +857,8 @@ int i2c_phytium_probe(struct phytium_i2c_dev *dev) ret = devm_request_irq(dev->dev, dev->irq, i2c_phytium_isr, irq_flags, dev_name(dev->dev), dev); if (ret) { - dev_err(dev->dev, "failed to request irq %i: %d\n", dev->irq, ret); + dev_err(dev->dev, "failed to request irq %i: %d\n", dev->irq, + ret); return ret; } @@ -573,11 +872,27 @@ int i2c_phytium_probe(struct phytium_i2c_dev *dev) ret = i2c_add_numbered_adapter(adapter); if (ret) dev_err(dev->dev, "fail to add adapter: %d\n", ret); + + if (of_property_read_bool(dev->dev->of_node, "smbus-alert")) + alert = 1; + else if (has_acpi_companion(dev->dev)) + fwnode_property_read_u32_array(dev->dev->fwnode, "smbus_alert", &alert, 1); + + if (alert) { + ret = i2c_phytium_enable_smbus_alert(dev); + if (ret) { + dev_err(dev->dev, + "failed to enable SMBus alert protocol (%d)\n", ret); + } + } + pm_runtime_put_noidle(dev->dev); return ret; } EXPORT_SYMBOL_GPL(i2c_phytium_probe); -MODULE_DESCRIPTION("Phytium I2C bus master adapter"); +MODULE_AUTHOR("Wu Jinyong "); +MODULE_DESCRIPTION("Phytium I2C bus controller adapter"); MODULE_LICENSE("GPL"); +MODULE_VERSION(I2C_PHYTIUM_DRV_VERSION); diff --git a/drivers/i2c/busses/i2c-phytium-platform.c b/drivers/i2c/busses/i2c-phytium-platform.c index 6f4de15570..084135a718 100644 --- a/drivers/i2c/busses/i2c-phytium-platform.c +++ b/drivers/i2c/busses/i2c-phytium-platform.c @@ -2,11 +2,6 @@ /* * Phytium I2C adapter driver. * - * Derived from Synopysys I2C driver. - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * Copyright (C) 2009 Provigent Ltd. - * * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. */ @@ -119,29 +114,6 @@ static inline int phytium_i2c_acpi_configure(struct platform_device *pdev) } #endif -static void i2c_phytium_configure_master(struct phytium_i2c_dev *dev) -{ - struct i2c_timings *t = &dev->timings; - - dev->functionality = I2C_FUNC_10BIT_ADDR | IC_DEFAULT_FUNCTIONALITY; - - dev->master_cfg = IC_CON_MASTER | IC_CON_SLAVE_DISABLE | - IC_CON_RESTART_EN; - - dev->mode = PHYTIUM_IC_MASTER; - - switch (t->bus_freq_hz) { - case 100000: - dev->master_cfg |= IC_CON_SPEED_STD; - break; - case 3400000: - dev->master_cfg |= IC_CON_SPEED_HIGH; - break; - default: - dev->master_cfg |= IC_CON_SPEED_FAST; - } -} - static void i2c_phytium_configure_slave(struct phytium_i2c_dev *dev) { dev->functionality = I2C_FUNC_SLAVE | IC_DEFAULT_FUNCTIONALITY; @@ -164,7 +136,6 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) 0, 100000, 400000, 1000000, 3400000 }; - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -180,6 +151,11 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) dev->dev = &pdev->dev; dev->irq = irq; + dev->first_time_init_master = false; +#if IS_ENABLED(CONFIG_I2C_SLAVE) + dev->slave_state = SLAVE_STATE_IDLE; +#endif + spin_lock_init(&dev->i2c_lock); platform_set_drvdata(pdev, dev); dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); @@ -231,11 +207,12 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) goto exit_reset; } - if (i2c_detect_slave_mode(&pdev->dev)) + if (i2c_detect_slave_mode(&pdev->dev)) { i2c_phytium_configure_slave(dev); - else + } else { + dev->first_time_init_master = true; i2c_phytium_configure_master(dev); - + } dev->clk = devm_clk_get(&pdev->dev, NULL); if (!i2c_phytium_prepare_clk(dev, true)) { u64 clk_khz; @@ -257,6 +234,9 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) adap->class = I2C_CLASS_DEPRECATED; ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev)); adap->dev.of_node = pdev->dev.of_node; + adap->dev.fwnode = pdev->dev.fwnode; + + dev->capability = 0; dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE | @@ -272,10 +252,7 @@ static int phytium_i2c_plat_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - if (dev->mode == PHYTIUM_IC_SLAVE) - ret = i2c_phytium_probe_slave(dev); - else - ret = i2c_phytium_probe(dev); + ret = i2c_phytium_probe(dev); if (ret) goto exit_probe; -- Gitee From c2fadbcef157d4c989e48951ef3ee4c5c9f0950b Mon Sep 17 00:00:00 2001 From: Wu Jinyong Date: Fri, 10 Jan 2025 14:14:40 +0800 Subject: [PATCH 031/121] i2c:phytium: Add phytium i2c_pci driver management information This patch adds i2c_pci management information for adapting the merged version of the I2C driver. Mainline: Open-Source Signed-off-by: Wu Jinyong Signed-off-by: Wang Yinfeng Change-Id: I1e4a234609ba21229342516fcdc2db214f5496e2 --- drivers/i2c/busses/i2c-phytium-pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/i2c/busses/i2c-phytium-pci.c b/drivers/i2c/busses/i2c-phytium-pci.c index c63abddd09..91d8cabcd9 100644 --- a/drivers/i2c/busses/i2c-phytium-pci.c +++ b/drivers/i2c/busses/i2c-phytium-pci.c @@ -183,6 +183,10 @@ static int i2c_phytium_pci_probe(struct pci_dev *pdev, dev->irq = pdev->irq; dev->flags |= controller->flags; +#if IS_ENABLED(CONFIG_I2C_SLAVE) + dev->slave_state = SLAVE_STATE_IDLE; +#endif + spin_lock_init(&dev->i2c_lock); dev->functionality = controller->functionality | IC_DEFAULT_FUNCTIONALITY; dev->master_cfg = controller->bus_cfg; if (controller->scl_sda_cfg) { @@ -205,6 +209,8 @@ static int i2c_phytium_pci_probe(struct pci_dev *pdev, ACPI_COMPANION_SET(&adapter->dev, ACPI_COMPANION(&pdev->dev)); adapter->nr = controller->bus_num; + dev->capability = 0; + dev->first_time_init_master = true; ret = i2c_phytium_probe(dev); if (ret) goto out; -- Gitee From f286587848f8ce9b5549025b0b59281d9db72348 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Wed, 5 Jun 2024 14:18:32 +0800 Subject: [PATCH 032/121] net/macb: Remove the unused code in MACB driver This patch removed the unused code in MACB driver. Mainline: Open-Source Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I73b1f72c15f03892c50ce03b76b782b743c75dec --- drivers/net/ethernet/cadence/macb_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 8a677582ef..bcc9d9122d 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -6021,9 +6021,6 @@ static int __maybe_unused macb_resume(struct device *dev) macb_set_rx_mode(netdev); macb_restore_features(bp); rtnl_lock(); - if (!device_may_wakeup(&bp->dev->dev)) - phy_init(bp->sgmii_phy); - phylink_start(bp->phylink); rtnl_unlock(); -- Gitee From 8d39770954f7f0518fecd0d2706927d9a5fa1bd4 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Thu, 5 Sep 2024 13:44:45 +0800 Subject: [PATCH 033/121] net/macb: Supported S4 suspend and resume function The MPE bit needs to be enabled after resume. Mainline: Open-Source Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: Ifef8dcfdf3c46a1361e96cef972214aa27045deb --- drivers/net/ethernet/cadence/macb_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index bcc9d9122d..ce11e8258e 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3191,6 +3191,10 @@ static void macb_init_hw(struct macb *bp) macb_reset_hw(bp); macb_set_hwaddr(bp); + config = macb_readl(bp, NCR); + config |= MACB_BIT(MPE); + macb_writel(bp, NCR, config); + config = macb_mdc_clk_div(bp); config |= MACB_BF(RBOF, NET_IP_ALIGN); /* Make eth data aligned */ config |= MACB_BIT(DRFCS); /* Discard Rx FCS */ -- Gitee From 2125d9fb57a00257d35808355e8b343359e7cebd Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Thu, 5 Sep 2024 13:47:46 +0800 Subject: [PATCH 034/121] net/macb: Bugfix kernel panic when unloading driver module When the network port is linked, the clk_disable_unprepare function will be called twice, one of them is in the unregister_netdev, and the double clk_disable will cause a kernel panic. Mainline: Open-Source Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I50b41785dd462b06632399f598d83eeec8e11f74 --- drivers/net/ethernet/cadence/macb_main.c | 31 +++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index ce11e8258e..5f88f388fa 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -5850,8 +5850,16 @@ static int macb_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); if (!pm_runtime_suspended(&pdev->dev)) { - macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, - bp->rx_clk, bp->tsu_clk); + if (__clk_is_enabled(bp->pclk)) + clk_disable_unprepare(bp->pclk); + if (__clk_is_enabled(bp->hclk)) + clk_disable_unprepare(bp->hclk); + if (__clk_is_enabled(bp->tx_clk)) + clk_disable_unprepare(bp->tx_clk); + if (__clk_is_enabled(bp->rx_clk)) + clk_disable_unprepare(bp->rx_clk); + if (__clk_is_enabled(bp->tsu_clk)) + clk_disable_unprepare(bp->tsu_clk); pm_runtime_set_suspended(&pdev->dev); } phylink_destroy(bp->phylink); @@ -6040,10 +6048,21 @@ static int __maybe_unused macb_runtime_suspend(struct device *dev) struct net_device *netdev = dev_get_drvdata(dev); struct macb *bp = netdev_priv(netdev); - if (!(device_may_wakeup(dev))) - macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, bp->rx_clk, bp->tsu_clk); - else if (!(bp->caps & MACB_CAPS_NEED_TSUCLK)) - macb_clks_disable(NULL, NULL, NULL, NULL, bp->tsu_clk); + if (!(device_may_wakeup(dev))) { + if (__clk_is_enabled(bp->pclk)) + clk_disable_unprepare(bp->pclk); + if (__clk_is_enabled(bp->hclk)) + clk_disable_unprepare(bp->hclk); + if (__clk_is_enabled(bp->tx_clk)) + clk_disable_unprepare(bp->tx_clk); + if (__clk_is_enabled(bp->rx_clk)) + clk_disable_unprepare(bp->rx_clk); + if (__clk_is_enabled(bp->tsu_clk)) + clk_disable_unprepare(bp->tsu_clk); + } else if (!(bp->caps & MACB_CAPS_NEED_TSUCLK)) { + if (__clk_is_enabled(bp->tsu_clk)) + clk_disable_unprepare(bp->tsu_clk); + } return 0; } -- Gitee From 69b744d8ad894630b2ab92a10e98d9378d46fbf5 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Thu, 26 Sep 2024 16:08:54 +0800 Subject: [PATCH 035/121] net/macb: Add 2.5G speed support for MACB driver Adapt to 2.5G speed for phytium MACB driver, including 2.5G electrical ports and 2.5G optical ports. Mainline: Open-Source Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I1c4a16b2a460a51f056858870ac39809a079c262 --- drivers/net/ethernet/cadence/macb_main.c | 34 +++++++++++++++++------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 5f88f388fa..c6b3d0b565 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -809,7 +809,21 @@ static void phytium_gem1p0_sel_clk(struct macb *bp, int speed) gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/ gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/ } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { - if (speed == SPEED_1000) { + if (speed == SPEED_2500) { + gem_writel(bp, DIV_SEL0_LN, 0x1); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/ + gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/ + gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/ + gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/ + gem_writel(bp, TX_CLK_SEL2, 0x1); /*0x1c28*/ + gem_writel(bp, TX_CLK_SEL3, 0x1); /*0x1c2c*/ + gem_writel(bp, RX_CLK_SEL0, 0x1); /*0x1c30*/ + gem_writel(bp, RX_CLK_SEL1, 0x0); /*0x1c34*/ + gem_writel(bp, TX_CLK_SEL3_0, 0x0); /*0x1c70*/ + gem_writel(bp, TX_CLK_SEL4_0, 0x0); /*0x1c74*/ + gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/ + gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/ + } else if (speed == SPEED_1000) { gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/ gem_writel(bp, DIV_SEL1_LN, 0x8); /*0x1c0c*/ @@ -981,10 +995,16 @@ static void macb_mac_link_up(struct phylink_config *config, if (speed == SPEED_2500) { u32 network_ctrl; + u32 pcsctrl, old_pcsctrl; network_ctrl = macb_readl(bp, NCR); network_ctrl |= MACB_BIT(2PT5G); macb_writel(bp, NCR, network_ctrl); + + old_pcsctrl = gem_readl(bp, PCSCNTRL); + pcsctrl = old_pcsctrl & ~GEM_BIT(PCSAUTONEG); + if (old_pcsctrl != pcsctrl) + gem_writel(bp, PCSCNTRL, pcsctrl); } if (bp->phy_interface == PHY_INTERFACE_MODE_10GBASER || @@ -1127,11 +1147,11 @@ static int macb_mii_probe(struct net_device *dev) bp->phylink_config.type = PHYLINK_NETDEV; bp->phylink_config.mac_managed_pm = true; - if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { + if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII || + bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { bp->phylink_config.poll_fixed_state = true; bp->phylink_config.get_fixed_state = macb_get_pcs_fixed_state; - } else if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX || - bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) { + } else if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) { bp->phylink_config.poll_fixed_state = true; bp->phylink_config.get_fixed_state = macb_get_usx_pcs_fixed_state; } @@ -1167,12 +1187,6 @@ static int macb_mii_probe(struct net_device *dev) } } - if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII || - bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { - bp->phylink_config.poll_fixed_state = true; - bp->phylink_config.get_fixed_state = macb_get_pcs_fixed_state; - } - bp->phylink = phylink_create(&bp->phylink_config, bp->pdev->dev.fwnode, bp->phy_interface, &macb_phylink_ops); if (IS_ERR(bp->phylink)) { -- Gitee From 79713f441b63dff522888248573ea109a7479b7a Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Wed, 6 Nov 2024 11:36:43 +0800 Subject: [PATCH 036/121] net/macb: Change the minimum rx ring size to 128 If the budget is equal to 64, gem_rx can exit after receiving a maximum of budget packets. If the ring size is changed to 64, a descriptor that has not been refilled is considered to be a valid descriptor to be received, and the error "inconsistent Rx descriptor chain" is reported. So we need to limit the minimum rx ring size to be greater than 64. Mainline: Open-Source Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I3607a3b229bf88d02c2a78e4bb2885e678a29279 --- drivers/net/ethernet/cadence/macb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index c6b3d0b565..5cfc47ec80 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -57,7 +57,7 @@ struct sifive_fu540_macb_mgmt { #define RX_BUFFER_MULTIPLE 64 /* bytes */ #define DEFAULT_RX_RING_SIZE 512 /* must be power of 2 */ -#define MIN_RX_RING_SIZE 64 +#define MIN_RX_RING_SIZE 128 #define MAX_RX_RING_SIZE 8192 #define RX_RING_BYTES(bp) (macb_dma_desc_get_size(bp) \ * (bp)->rx_ring_size) -- Gitee From 54275325efea1b3794d564c38c4187c43accff94 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Wed, 6 Nov 2024 11:42:21 +0800 Subject: [PATCH 037/121] net/macb: Fixed the CPU stall issue in S4 test In the S4 test, it is possible that macb_mac_link_down concurrency with macb_tx_interrupt caused an endless loop, which in turn caused the CPU to stall. So, it is necessary to clear the tx_used bit in macb_mac_link_down to break the condition for the macb_tx_interrupt to enter the loop. Mainline: Open-Source Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I2186315cb6fa7c383923a30ded061a1d0a6eb9a1 --- drivers/net/ethernet/cadence/macb_main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 5cfc47ec80..18e28ac80f 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -112,6 +112,8 @@ struct sifive_fu540_macb_mgmt { static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budget); +static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, + dma_addr_t addr); /* DMA buffer descriptor might be different size * depends on hardware configuration: @@ -744,6 +746,7 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode, struct macb *bp = netdev_priv(ndev); struct macb_tx_skb *tx_skb; struct macb_queue *queue; + struct macb_dma_desc *tx_desc = NULL; unsigned int q; u32 ctrl; int i; @@ -763,12 +766,18 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode, /* Tx clean */ for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { + spin_lock(&queue->tx_ptr_lock); for (i = 0; i < bp->tx_ring_size; i++) { tx_skb = macb_tx_skb(queue, i); /* free unsent skb buffers */ if (tx_skb) macb_tx_unmap(bp, tx_skb, 0); + + tx_desc = macb_tx_desc(queue, i); + macb_set_addr(bp, tx_desc, 0); + tx_desc->ctrl &= ~MACB_BIT(TX_USED); } + spin_unlock(&queue->tx_ptr_lock); } netif_tx_stop_all_queues(ndev); -- Gitee From e65724d633b36c06629968e0b3e26b4b93e4d651 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Wed, 6 Nov 2024 16:33:22 +0800 Subject: [PATCH 038/121] net/macb: Udapte dts for pe220x platforms Update phytium MACB compatible description of dts for pe220x platforms. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I881e13c0e39e7024c06c0f5cd0706979dedf6344 --- arch/arm64/boot/dts/phytium/pe2201.dtsi | 4 ++-- arch/arm64/boot/dts/phytium/pe2202.dtsi | 8 ++++---- arch/arm64/boot/dts/phytium/pe2204.dtsi | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm64/boot/dts/phytium/pe2201.dtsi b/arch/arm64/boot/dts/phytium/pe2201.dtsi index 82512bcb9f..ed4b674b31 100644 --- a/arch/arm64/boot/dts/phytium/pe2201.dtsi +++ b/arch/arm64/boot/dts/phytium/pe2201.dtsi @@ -245,7 +245,7 @@ sgpio: sgpio@2807d000 { }; macb0: ethernet@32010000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x32010000 0x0 0x2000>; interrupts = , , @@ -258,7 +258,7 @@ macb0: ethernet@32010000 { }; macb1: ethernet@32012000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x32012000 0x0 0x2000>; interrupts = , , diff --git a/arch/arm64/boot/dts/phytium/pe2202.dtsi b/arch/arm64/boot/dts/phytium/pe2202.dtsi index 7ece269cfd..4e6446da32 100644 --- a/arch/arm64/boot/dts/phytium/pe2202.dtsi +++ b/arch/arm64/boot/dts/phytium/pe2202.dtsi @@ -176,7 +176,7 @@ sata1: sata@32014000 { }; macb0: ethernet@3200c000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x3200c000 0x0 0x2000>; interrupts = , , @@ -193,7 +193,7 @@ macb0: ethernet@3200c000 { }; macb1: ethernet@3200e000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x3200e000 0x0 0x2000>; interrupts = , , @@ -206,7 +206,7 @@ macb1: ethernet@3200e000 { }; macb2: ethernet@32010000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x32010000 0x0 0x2000>; interrupts = , , @@ -220,7 +220,7 @@ macb2: ethernet@32010000 { }; macb3: ethernet@32012000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x32012000 0x0 0x2000>; interrupts = , , diff --git a/arch/arm64/boot/dts/phytium/pe2204.dtsi b/arch/arm64/boot/dts/phytium/pe2204.dtsi index 5d8f2d6fff..228264b282 100644 --- a/arch/arm64/boot/dts/phytium/pe2204.dtsi +++ b/arch/arm64/boot/dts/phytium/pe2204.dtsi @@ -211,7 +211,7 @@ sata1: sata@32014000 { }; macb0: ethernet@3200c000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x3200c000 0x0 0x2000>; interrupts = , , @@ -229,7 +229,7 @@ macb0: ethernet@3200c000 { }; macb1: ethernet@3200e000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x3200e000 0x0 0x2000>; interrupts = , , @@ -242,7 +242,7 @@ macb1: ethernet@3200e000 { }; macb2: ethernet@32010000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x32010000 0x0 0x2000>; interrupts = , , @@ -255,7 +255,7 @@ macb2: ethernet@32010000 { }; macb3: ethernet@32012000 { - compatible = "cdns,phytium-gem"; + compatible = "cdns,phytium-gem-1.0"; reg = <0x0 0x32012000 0x0 0x2000>; interrupts = , , -- Gitee From e1983bd12b88ce9b07660251c9d73d400cbab2e0 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Thu, 27 Jun 2024 10:09:53 +0800 Subject: [PATCH 039/121] net/phytmac: Adapt interface type 2500BASE-x Add 2500BASE-x interface type support for phytmac driver. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I9e0f81c8c9224a89be17714fb8a1b2905499f8bf --- drivers/net/ethernet/phytium/phytmac.h | 2 +- drivers/net/ethernet/phytium/phytmac_main.c | 10 +++++++--- drivers/net/ethernet/phytium/phytmac_v1.c | 21 +++++++++++++++------ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h index bc0d2670c2..a4e0d4e4fa 100644 --- a/drivers/net/ethernet/phytium/phytmac.h +++ b/drivers/net/ethernet/phytium/phytmac.h @@ -13,7 +13,7 @@ #define PHYTMAC_DRV_NAME "phytium-mac" #define PHYTMAC_DRV_DESC "PHYTIUM Ethernet Driver" -#define PHYTMAC_DRIVER_VERSION "1.0.3" +#define PHYTMAC_DRIVER_VERSION "1.0.4" #define PHYTMAC_DEFAULT_MSG_ENABLE \ (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index 732358ea40..43c15b8baf 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -1726,6 +1726,9 @@ static void phytmac_mac_link_up(struct phylink_config *config, pdata->pause = rx_pause; } + pdata->speed = speed; + pdata->duplex = duplex; + phytmac_init_ring(pdata); for (q = 0, queue = pdata->queues; q < pdata->queues_num; ++q, ++queue) @@ -1844,11 +1847,12 @@ static void phytmac_validate(struct phylink_config *config, if (state->interface == PHY_INTERFACE_MODE_5GBASER) phylink_set(mask, 5000baseT_Full); - if (state->interface == PHY_INTERFACE_MODE_1000BASEX || - state->interface == PHY_INTERFACE_MODE_SGMII || + if (state->interface == PHY_INTERFACE_MODE_1000BASEX) + phylink_set(mask, 1000baseX_Full); + + if (state->interface == PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_rgmii(state->interface)) { phylink_set(mask, 1000baseT_Full); - phylink_set(mask, 1000baseX_Full); phylink_set(mask, 1000baseT_Half); phylink_set(mask, 10baseT_Half); phylink_set(mask, 10baseT_Full); diff --git a/drivers/net/ethernet/phytium/phytmac_v1.c b/drivers/net/ethernet/phytium/phytmac_v1.c index 20595aca17..72a6eeaec3 100644 --- a/drivers/net/ethernet/phytium/phytmac_v1.c +++ b/drivers/net/ethernet/phytium/phytmac_v1.c @@ -1078,12 +1078,15 @@ static void phytmac_mac_interface_config(struct phytmac *pdata, unsigned int mod config |= PHYTMAC_BIT(SGMII_EN) | PHYTMAC_BIT(PCS_EN); if (state->speed == SPEED_1000) config |= PHYTMAC_BIT(GM_EN); - else if (state->speed == SPEED_2500) - config |= PHYTMAC_BIT(2PT5G); + else if (state->speed == SPEED_2500) { + ctrl |= PHYTMAC_BIT(2PT5G); + config |= PHYTMAC_BIT(GM_EN); + } } else if (state->interface == PHY_INTERFACE_MODE_1000BASEX) { config |= PHYTMAC_BIT(PCS_EN) | PHYTMAC_BIT(GM_EN); } else if (state->interface == PHY_INTERFACE_MODE_2500BASEX) { - config |= PHYTMAC_BIT(2PT5G) | PHYTMAC_BIT(PCS_EN); + ctrl |= PHYTMAC_BIT(2PT5G); + config |= PHYTMAC_BIT(PCS_EN) | PHYTMAC_BIT(GM_EN); } else if (state->interface == PHY_INTERFACE_MODE_10GBASER || state->interface == PHY_INTERFACE_MODE_USXGMII || state->interface == PHY_INTERFACE_MODE_5GBASER) { @@ -1111,11 +1114,17 @@ static void phytmac_mac_interface_config(struct phytmac *pdata, unsigned int mod if (old_config ^ config) PHYTMAC_WRITE(pdata, PHYTMAC_NCONFIG, config); - /* Disable AN for SGMII fixed link configuration, enable otherwise.*/ - if (state->interface == PHY_INTERFACE_MODE_SGMII) - phytmac_enable_autoneg(pdata, mode == MLO_AN_FIXED ? 0 : 1); + /* Disable AN for SGMII fixed link or speed equal to 2.5G, enable otherwise.*/ + if (state->interface == PHY_INTERFACE_MODE_SGMII) { + if (state->speed == SPEED_2500 || mode == MLO_AN_FIXED) + phytmac_enable_autoneg(pdata, 0); + else + phytmac_enable_autoneg(pdata, 1); + } if (state->interface == PHY_INTERFACE_MODE_1000BASEX) phytmac_enable_autoneg(pdata, 1); + if (state->interface == PHY_INTERFACE_MODE_2500BASEX) + phytmac_enable_autoneg(pdata, 0); } static unsigned int phytmac_pcs_get_link(struct phytmac *pdata, -- Gitee From 4c06f35e7d80ce9c350cfcfe8f35ec66326a12c0 Mon Sep 17 00:00:00 2001 From: Li Wencheng Date: Thu, 27 Jun 2024 10:15:06 +0800 Subject: [PATCH 040/121] net/phytmac: Support WOL interaction with BIOS It should notify the BIOS to enable or disable the WOL function. This patch adds support for it. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng Change-Id: I1c900bc38faff9d0054c38329e55df8dd16e8d28 --- drivers/net/ethernet/phytium/phytmac.h | 3 +- .../net/ethernet/phytium/phytmac_ethtool.c | 1 + drivers/net/ethernet/phytium/phytmac_main.c | 34 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/phytium/phytmac.h b/drivers/net/ethernet/phytium/phytmac.h index a4e0d4e4fa..df4ec49a08 100644 --- a/drivers/net/ethernet/phytium/phytmac.h +++ b/drivers/net/ethernet/phytium/phytmac.h @@ -13,7 +13,7 @@ #define PHYTMAC_DRV_NAME "phytium-mac" #define PHYTMAC_DRV_DESC "PHYTIUM Ethernet Driver" -#define PHYTMAC_DRIVER_VERSION "1.0.4" +#define PHYTMAC_DRIVER_VERSION "1.0.5" #define PHYTMAC_DEFAULT_MSG_ENABLE \ (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ @@ -607,4 +607,5 @@ int phytmac_drv_resume(struct phytmac *pdata); struct phytmac *phytmac_alloc_pdata(struct device *dev); void phytmac_free_pdata(struct phytmac *pdata); int phytmac_reset_ringsize(struct phytmac *pdata, u32 rx_size, u32 tx_size); +void phytmac_set_bios_wol_enable(struct phytmac *pdata, u32 wol); #endif diff --git a/drivers/net/ethernet/phytium/phytmac_ethtool.c b/drivers/net/ethernet/phytium/phytmac_ethtool.c index a97a4c28c0..306a9934de 100644 --- a/drivers/net/ethernet/phytium/phytmac_ethtool.c +++ b/drivers/net/ethernet/phytium/phytmac_ethtool.c @@ -131,6 +131,7 @@ static int phytmac_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) pdata->wol |= PHYTMAC_WAKE_MCAST; device_set_wakeup_enable(pdata->dev, pdata->wol ? 1 : 0); + phytmac_set_bios_wol_enable(pdata, pdata->wol ? 1 : 0); return 0; } diff --git a/drivers/net/ethernet/phytium/phytmac_main.c b/drivers/net/ethernet/phytium/phytmac_main.c index 43c15b8baf..fd29c647e2 100644 --- a/drivers/net/ethernet/phytium/phytmac_main.c +++ b/drivers/net/ethernet/phytium/phytmac_main.c @@ -111,6 +111,8 @@ static int phytmac_set_mac_address(struct net_device *netdev, void *addr) hw_if->set_mac_address(pdata, saddr->sa_data); + phytmac_set_bios_wol_enable(pdata, pdata->wol ? 1 : 0); + return 0; } @@ -1971,6 +1973,7 @@ static int phytmac_open(struct net_device *ndev) } phylink_start(pdata->phylink); + phytmac_set_bios_wol_enable(pdata, pdata->wol ? 1 : 0); netif_tx_start_all_queues(pdata->ndev); @@ -2121,6 +2124,37 @@ static netdev_features_t phytmac_features_check(struct sk_buff *skb, return features; } +void phytmac_set_bios_wol_enable(struct phytmac *pdata, u32 wol) +{ + struct net_device *ndev = pdata->ndev; + + if (ndev->phydev) { +#ifdef CONFIG_ACPI + if (has_acpi_companion(pdata->dev)) { + acpi_handle handle = ACPI_HANDLE(pdata->dev); + + if (acpi_has_method(handle, "PWOL")) { + union acpi_object args[] = { + { .type = ACPI_TYPE_INTEGER, }, + }; + struct acpi_object_list arg_input = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_status status; + + /* Set the input parameters */ + args[0].integer.value = wol; + + status = acpi_evaluate_object(handle, "PWOL", &arg_input, NULL); + if (ACPI_FAILURE(status)) + netdev_err(ndev, "The PWOL method failed to be executed.\n"); + } + } +#endif + } +} + int phytmac_reset_ringsize(struct phytmac *pdata, u32 rx_size, u32 tx_size) { int ret = 0; -- Gitee From c435cc3aa73fee4ae5d363cf91b55a602e16d8e1 Mon Sep 17 00:00:00 2001 From: Lai Xueyu Date: Thu, 16 Nov 2023 10:41:03 +0800 Subject: [PATCH 041/121] mmc: phytium: Add software write protection function Add software write protection function for SD card driver. Mainline: Open-Source Signed-off-by: Lai Xueyu Signed-off-by: Wang Yinfeng Change-Id: I80bcd725f16cf25ada23056c7019bb42e0523070 --- drivers/mmc/host/phytium-mci.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/mmc/host/phytium-mci.c b/drivers/mmc/host/phytium-mci.c index 4a535d68f1..3b78fd61d2 100644 --- a/drivers/mmc/host/phytium-mci.c +++ b/drivers/mmc/host/phytium-mci.c @@ -62,6 +62,7 @@ static void phytium_mci_init_adma_table(struct phytium_mci_host *host, struct phytium_mci_dma *dma); static void phytium_mci_init_hw(struct phytium_mci_host *host); static int phytium_mci_get_cd(struct mmc_host *mmc); +static int phytium_mci_get_ro(struct mmc_host *mmc); static int phytium_mci_err_irq(struct phytium_mci_host *host, u32 dmac_events, u32 events); static void sdr_set_bits(void __iomem *reg, u32 bs) @@ -1409,6 +1410,20 @@ static int phytium_mci_get_cd(struct mmc_host *mmc) return 1; } +static int phytium_mci_get_ro(struct mmc_host *mmc) +{ + struct phytium_mci_host *host = mmc_priv(mmc); + u32 status; + + status = readl(host->base + MCI_CARD_WRTPRT); + + dev_dbg(host->dev, "mci_get_ro status %d\n", status); + if ((status & 0x1) == 0x1) + return 1; + + return 0; +} + static int phytium_mci_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios) { struct phytium_mci_host *host = mmc_priv(mmc); @@ -1502,6 +1517,7 @@ static struct mmc_host_ops phytium_mci_ops = { .request = phytium_mci_ops_request, .set_ios = phytium_mci_ops_set_ios, .get_cd = phytium_mci_get_cd, + .get_ro = phytium_mci_get_ro, .enable_sdio_irq = phytium_mci_enable_sdio_irq, .ack_sdio_irq = phytium_mci_ack_sdio_irq, .card_busy = phytium_mci_card_busy, -- Gitee From 01c7d8a439589a08fa1413c10b6b4e0b6b5e1a9d Mon Sep 17 00:00:00 2001 From: Lai Xueyu Date: Thu, 16 Nov 2023 10:57:51 +0800 Subject: [PATCH 042/121] mmc: phytium: Add MCI_CLK_DIVIDER function Add MCI_CLK_DIVIDER function to optimize phase settings. Mainline: Open-Source Signed-off-by: Lai Xueyu Signed-off-by: Wang Yinfeng Change-Id: Ie3704fbcf62ea27eb0fc5173d5dd31449dcb62f3 --- drivers/mmc/host/phytium-mci.c | 8 ++++++-- drivers/mmc/host/phytium-mci.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/phytium-mci.c b/drivers/mmc/host/phytium-mci.c index 3b78fd61d2..758cc130a6 100644 --- a/drivers/mmc/host/phytium-mci.c +++ b/drivers/mmc/host/phytium-mci.c @@ -235,8 +235,12 @@ static void phytium_mci_set_clk(struct phytium_mci_host *host, struct mmc_ios *i } } - dev_dbg(host->dev, "UHS_REG_EXT ext: %x, CLKDIV: %x\n", - readl(host->base + MCI_UHS_REG_EXT), readl(host->base + MCI_CLKDIV)); + if (div >= 2) + writel(((2 * (div & 0xff)) & 0xffff), host->base + MCI_CLK_DIVIDER); + + dev_dbg(host->dev, "UHS_REG_EXT ext: %x, CLKDIV: %x MCI_CLK_DIVIDER %x %x\n", + readl(host->base + MCI_UHS_REG_EXT), readl(host->base + MCI_CLKDIV), + readl(host->base + MCI_CLK_DIVIDER), ((2 * (div & 0xff)) & 0xffff)); sdr_set_bits(host->base + MCI_CLKENA, MCI_CLKENA_CCLK_ENABLE); diff --git a/drivers/mmc/host/phytium-mci.h b/drivers/mmc/host/phytium-mci.h index 90f51b9ee1..e2d6d0b3a8 100644 --- a/drivers/mmc/host/phytium-mci.h +++ b/drivers/mmc/host/phytium-mci.h @@ -104,6 +104,7 @@ #define MCI_UHS_REG_EXT 0x108 /* the UHS register extension */ #define MCI_EMMC_DDR_REG 0x10C /* the EMMC DDR reg */ #define MCI_ENABLE_SHIFT 0x110 /* the enable phase shift reg */ +#define MCI_CLK_DIVIDER 0x114 /* CLK DIVIDER */ #define MCI_DATA 0x200 /* the data FIFO access */ /* Command register defines */ -- Gitee From f92d106d071bf88e1a2636b596cc64b71f672848 Mon Sep 17 00:00:00 2001 From: Chen Zhenhua Date: Wed, 31 Jan 2024 11:18:14 +0800 Subject: [PATCH 043/121] mmc: phytium: Add emmc DDR feature support The patch adds support for emmc DDR feature. Mainline: Open-Source Signed-off-by: Chen Zhenhua Signed-off-by: Wang Yinfeng Change-Id: I04cc5641b3b0001b8734fc4f8bfa06dca8787ca3 --- drivers/mmc/host/phytium-mci.c | 23 ++++++++++++++++++++--- drivers/mmc/host/phytium-mci.h | 4 +++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/phytium-mci.c b/drivers/mmc/host/phytium-mci.c index 758cc130a6..d9f0236794 100644 --- a/drivers/mmc/host/phytium-mci.c +++ b/drivers/mmc/host/phytium-mci.c @@ -44,7 +44,7 @@ static const u32 data_ints_mask = MCI_INT_MASK_DTO | MCI_INT_MASK_DCRC | MCI_INT MCI_INT_MASK_SBE_BCI; static const u32 cmd_err_ints_mask = MCI_INT_MASK_RTO | MCI_INT_MASK_RCRC | MCI_INT_MASK_RE | MCI_INT_MASK_DCRC | MCI_INT_MASK_DRTO | - MCI_MASKED_INTS_SBE_BCI; + MCI_MASKED_INTS_SBE_BCI | MCI_MASKED_INTS_EBE; static const u32 dmac_ints_mask = MCI_DMAC_INT_ENA_FBE | MCI_DMAC_INT_ENA_DU | MCI_DMAC_INT_ENA_NIS | MCI_DMAC_INT_ENA_AIS; @@ -187,7 +187,7 @@ static void phytium_mci_set_clk(struct phytium_mci_host *host, struct mmc_ios *i host->clk_rate, ios->clock); if (ios->clock >= 25000000) - tmp_ext_reg = 0x202; + tmp_ext_reg = 0x102; else if (ios->clock == 400000) tmp_ext_reg = 0x502; else @@ -235,6 +235,17 @@ static void phytium_mci_set_clk(struct phytium_mci_host *host, struct mmc_ios *i } } + if (!(readl(host->base + MCI_CLKDIV) & 0xff00) && + (ios->timing == MMC_TIMING_MMC_DDR52 || + ios->timing == MMC_TIMING_MMC_HS400 || + ios->timing == MMC_TIMING_UHS_DDR50)) { + sdr_set_bits(host->base + MCI_CNTRL, MCI_CNTRL_CRC_SERIAL_DATA); + sdr_set_bits(host->base + MCI_CNTRL, MCI_CNTRL_DRV_SHIFT_EN); + } else { + sdr_clr_bits(host->base + MCI_CNTRL, MCI_CNTRL_CRC_SERIAL_DATA); + sdr_clr_bits(host->base + MCI_CNTRL, MCI_CNTRL_DRV_SHIFT_EN); + } + if (div >= 2) writel(((2 * (div & 0xff)) & 0xffff), host->base + MCI_CLK_DIVIDER); @@ -1260,6 +1271,7 @@ static void phytium_mci_init_hw(struct phytium_mci_host *host) sdr_set_bits(host->base + MCI_CLKENA, MCI_CLKENA_CCLK_ENABLE); sdr_set_bits(host->base + MCI_UHS_REG_EXT, MCI_EXT_CLK_ENABLE); sdr_clr_bits(host->base + MCI_UHS_REG, MCI_UHS_REG_VOLT); + sdr_clr_bits(host->base + MCI_EMMC_DDR_REG, MCI_EMMC_DDR_CYCLE); phytium_mci_reset_hw(host); @@ -1362,8 +1374,13 @@ static void phytium_mci_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct phytium_mci_host *host = mmc_priv(mmc); - if (ios->timing == MMC_TIMING_MMC_DDR52 || ios->timing == MMC_TIMING_UHS_DDR50) + if (ios->timing == MMC_TIMING_MMC_DDR52 || + ios->timing == MMC_TIMING_MMC_HS400 || + ios->timing == MMC_TIMING_UHS_DDR50) { sdr_set_bits(host->base + MCI_UHS_REG, MCI_UHS_REG_DDR); + sdr_set_bits(host->base + MCI_CNTRL, MCI_CNTRL_START_BIT_MODE); + sdr_clr_bits(host->base + MCI_EMMC_DDR_REG, MCI_EMMC_DDR_CYCLE); + } else sdr_clr_bits(host->base + MCI_UHS_REG, MCI_UHS_REG_DDR); diff --git a/drivers/mmc/host/phytium-mci.h b/drivers/mmc/host/phytium-mci.h index e2d6d0b3a8..9d3e86a4d5 100644 --- a/drivers/mmc/host/phytium-mci.h +++ b/drivers/mmc/host/phytium-mci.h @@ -133,12 +133,14 @@ #define MCI_CNTRL_CONTROLLER_RESET (0x1 << 0) /* RW */ #define MCI_CNTRL_FIFO_RESET (0x1 << 1) /* RW */ #define MCI_CNTRL_DMA_RESET (0x1 << 2) /* RW */ -#define MCI_CNTRL_RES (0x1 << 3) /* */ +#define MCI_CNTRL_DRV_SHIFT_EN (0x1 << 3) /* */ #define MCI_CNTRL_INT_ENABLE (0x1 << 4) /* RW */ #define MCI_CNTRL_DMA_ENABLE (0x1 << 5) /* RW */ #define MCI_CNTRL_READ_WAIT (0x1 << 6) /* RW */ #define MCI_CNTRL_SEND_IRQ_RESPONSE (0x1 << 7) /* RW */ #define MCI_CNTRL_ABORT_READ_DATA (0x1 << 8) /* RW */ +#define MCI_CNTRL_START_BIT_MODE (0x1 << 9) /* RW */ +#define MCI_CNTRL_CRC_SERIAL_DATA (0x1 << 10) /* RW */ #define MCI_CNTRL_ENDIAN (0x1 << 11) /* RW */ //#define MCI_CNTRL_CARD_VOLTAGE_A (0xF << 16) /* RW */ //#define MCI_CNTRL_CARD_VOLTAGE_B (0xF << 20) /* RW */ -- Gitee From cb1972660e272b58c70cc19c883925037197ec19 Mon Sep 17 00:00:00 2001 From: Lai Xueyu Date: Thu, 21 Nov 2024 10:07:39 +0800 Subject: [PATCH 044/121] mmc: phytium: Fixed SD voltage switch issue Add some time delay to wait for voltage switch complete. Mainline: Open-Source Signed-off-by: Lai Xueyu Signed-off-by: Wang Yinfeng Change-Id: Ic7a584cedbab742c12f01b2ce9f6c03135a21460 --- drivers/mmc/host/phytium-mci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/phytium-mci.c b/drivers/mmc/host/phytium-mci.c index d9f0236794..8be02664b4 100644 --- a/drivers/mmc/host/phytium-mci.c +++ b/drivers/mmc/host/phytium-mci.c @@ -253,6 +253,9 @@ static void phytium_mci_set_clk(struct phytium_mci_host *host, struct mmc_ios *i readl(host->base + MCI_UHS_REG_EXT), readl(host->base + MCI_CLKDIV), readl(host->base + MCI_CLK_DIVIDER), ((2 * (div & 0xff)) & 0xffff)); + if (cur_cmd_index == SD_SWITCH_VOLTAGE) + msleep(40); + sdr_set_bits(host->base + MCI_CLKENA, MCI_CLKENA_CCLK_ENABLE); if (cur_cmd_index == SD_SWITCH_VOLTAGE) -- Gitee From aefad7c9661de8f45e99e05e0a55920745fc5c65 Mon Sep 17 00:00:00 2001 From: Zhou Zheng Date: Wed, 13 Nov 2024 10:28:04 +0000 Subject: [PATCH 045/121] i2s:phytium: Add clear and mask interrupt operations Adding actions to clear and mask interrupts before the interrupt handler is registered for the i2s driver. Mainline: Open-Source Signed-off-by: Zhou Zheng Signed-off-by: Wang Yinfeng Change-Id: If8923517b4b8e0f8b580fb75b39ffef5bbf09963 --- sound/soc/phytium/phytium_i2s.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/sound/soc/phytium/phytium_i2s.c b/sound/soc/phytium/phytium_i2s.c index c804f77d02..03164316b8 100644 --- a/sound/soc/phytium/phytium_i2s.c +++ b/sound/soc/phytium/phytium_i2s.c @@ -237,6 +237,15 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) struct i2sc_bus *bus = azx_bus(chip); struct i2s_phytium *i2s = container_of(chip, struct i2s_phytium, chip); int err; + u32 status; + + status = i2s_read_reg(i2s->regs_db, DMA_STS); + if (status & 0x1) + i2s_write_reg(i2s->regs_db, DMA_STS, 0x1); + if (status & 0x100) + i2s_write_reg(i2s->regs_db, DMA_STS, 0x100); + + i2s_write_reg(i2s->regs_db, DMA_MASK_INT, 0x0); err = devm_request_irq(i2s->dev, i2s->irq_id, azx_i2s_interrupt, IRQF_SHARED, "phytium i2s", chip); @@ -247,11 +256,8 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) } if (i2s->detect) { - err = azx_i2s_enable_gpio(i2s); - if (err < 0) { - dev_err(i2s->dev, "failed to enable gpio irq\n"); - return err; - } + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_PORTA_EOI, I2S_GPIO(0)); + i2s_write_reg(i2s->regs_gpio, I2S_GPIO_INTMASK, 0x1); err = devm_request_irq(i2s->dev, i2s->gpio_irq_id, azx_i2s_gpio_interrupt, IRQF_SHARED, @@ -260,6 +266,13 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) dev_err(i2s->dev, "failed to request gpio irq\n"); return err; } + + err = azx_i2s_enable_gpio(i2s); + if (err < 0) { + dev_err(i2s->dev, "failed to enable gpio irq\n"); + return err; + } + } bus->irq = i2s->irq_id; -- Gitee From 21dca9d283219338c1f65ce26f1dc07ece2061de Mon Sep 17 00:00:00 2001 From: Dai Jingtao Date: Tue, 23 Jul 2024 17:17:37 +0800 Subject: [PATCH 046/121] i2s: phytium: Add I2S driver version information This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Dai Jingtao Signed-off-by: Wang Yinfeng Change-Id: I0b35df60f5b518d0439bab009e6d204413059825 --- sound/soc/codecs/es8336.c | 3 +++ sound/soc/codecs/es8388.c | 3 +++ sound/soc/phytium/phytium_i2s.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/sound/soc/codecs/es8336.c b/sound/soc/codecs/es8336.c index 2d666ab283..e1aaa1bc05 100644 --- a/sound/soc/codecs/es8336.c +++ b/sound/soc/codecs/es8336.c @@ -30,6 +30,8 @@ #include #include #include "es8336.h" + +#define ES8336_V1_VERSION "1.0.0" #define ES8336_MUTE (1 << 5) static struct snd_soc_component *es8336_component; @@ -1071,3 +1073,4 @@ static struct i2c_driver es8336_i2c_driver = { module_i2c_driver(es8336_i2c_driver); MODULE_DESCRIPTION("ASoC es8336 driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(ES8336_V1_VERSION); diff --git a/sound/soc/codecs/es8388.c b/sound/soc/codecs/es8388.c index 11959e97e6..57ef3c747a 100644 --- a/sound/soc/codecs/es8388.c +++ b/sound/soc/codecs/es8388.c @@ -23,6 +23,8 @@ #include #include +#define ES8388_V1_VERSION "1.0.0" + static const unsigned int rates_12288[] = { 8000, 12000, 16000, 24000, 32000, 48000, 96000, }; @@ -817,3 +819,4 @@ module_i2c_driver(es8388_i2c_driver); MODULE_DESCRIPTION("ASoC ES8388 driver"); MODULE_AUTHOR("Yiqun Zhang "); MODULE_LICENSE("GPL"); +MODULE_VERSION(ES8388_V1_VERSION); diff --git a/sound/soc/phytium/phytium_i2s.c b/sound/soc/phytium/phytium_i2s.c index 03164316b8..ace159cd51 100644 --- a/sound/soc/phytium/phytium_i2s.c +++ b/sound/soc/phytium/phytium_i2s.c @@ -31,6 +31,7 @@ #include #include "local.h" +#define PHYTIUM_I2S_V1_VERSION "1.0.0" #define NUM_CAPTURE 1 #define NUM_PLAYBACK 1 @@ -1574,3 +1575,4 @@ module_platform_driver(phytium_i2s_driver); MODULE_DESCRIPTION("Phytium I2S Driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Zhang Yiqun "); +MODULE_VERSION(PHYTIUM_I2S_V1_VERSION); -- Gitee From eaa31acbb00730386b87d364a7034a26fa7fd12a Mon Sep 17 00:00:00 2001 From: Zhou Zheng Date: Fri, 1 Nov 2024 02:43:32 +0000 Subject: [PATCH 047/121] codec: phytium: Bugfix issue after S4 recovery Add operations to restore codec register after resuming from S4, which makes the codes work normally. Mainline: Open-Source Signed-off-by: Zhou Zheng Signed-off-by: Wang Yinfeng Change-Id: Ic551ae20b299a5549f74ca80a67a467f47d04e49 --- sound/soc/codecs/es8336.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/sound/soc/codecs/es8336.c b/sound/soc/codecs/es8336.c index e1aaa1bc05..a7ae3d1cba 100644 --- a/sound/soc/codecs/es8336.c +++ b/sound/soc/codecs/es8336.c @@ -828,31 +828,14 @@ static int es8336_suspend(struct snd_soc_component *component) static int es8336_resume(struct snd_soc_component *component) { - struct es8336_priv *es8336 = snd_soc_component_get_drvdata(component); + struct regmap *regmap = dev_get_regmap(component->dev, NULL); int ret; - es8336_reset(component); /* UPDATED BY DAVID,15-3-5 */ - ret = snd_soc_component_read(component, ES8336_CLKMGR_ADCDIV2_REG05); - if (!ret) { - es8336_init_regs(component); - snd_soc_component_write(component, ES8336_GPIO_SEL_REG4D, 0x02); - /* max debance time, enable interrupt, low active */ - snd_soc_component_write(component, ES8336_GPIO_DEBUNCE_INT_REG4E, 0xf3); - /* es8336_set_bias_level(component, SND_SOC_BIAS_OFF); */ - snd_soc_component_write(component, ES8336_CPHP_OUTEN_REG17, 0x00); - snd_soc_component_write(component, ES8336_DAC_PDN_REG2F, 0x11); - snd_soc_component_write(component, ES8336_CPHP_LDOCTL_REG1B, 0x03); - snd_soc_component_write(component, ES8336_CPHP_PDN2_REG1A, 0x22); - snd_soc_component_write(component, ES8336_CPHP_PDN1_REG19, 0x06); - snd_soc_component_write(component, ES8336_HPMIX_SWITCH_REG14, 0x00); - snd_soc_component_write(component, ES8336_HPMIX_PDN_REG15, 0x33); - snd_soc_component_write(component, ES8336_HPMIX_VOL_REG16, 0x00); - if (!es8336->hp_inserted) - snd_soc_component_write(component, ES8336_SYS_PDN_REG0D, 0x3F); - snd_soc_component_write(component, ES8336_SYS_LP1_REG0E, 0xFF); - snd_soc_component_write(component, ES8336_SYS_LP2_REG0F, 0xFF); - snd_soc_component_write(component, ES8336_CLKMGR_CLKSW_REG01, 0xF3); - snd_soc_component_update_bits(component, ES8336_ADC_PDN_LINSEL_REG22, 0xC0, 0xC0); + regcache_mark_dirty(regmap); + ret = regcache_sync(regmap); + if (ret) { + dev_err(component->dev, "unable to sync regcache\n"); + return ret; } return 0; } @@ -933,6 +916,8 @@ const struct regmap_config es8336_regmap_config = { .cache_type = REGCACHE_RBTREE, .reg_defaults = es8336_reg_defaults, .num_reg_defaults = ARRAY_SIZE(es8336_reg_defaults), + .use_single_read = true, + .use_single_write = true, }; static const struct snd_soc_component_driver soc_component_dev_es8336 = { -- Gitee From d246b6e270bda668ef644054c7c8efd493c95285 Mon Sep 17 00:00:00 2001 From: Zhou Zheng Date: Thu, 25 Jul 2024 02:25:15 +0000 Subject: [PATCH 048/121] ASoC: phytium: Add machine driver version information This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Zhou Zheng Signed-off-by: Wang Yinfeng Change-Id: I909280ac26f0f41c1b18803715877adf861fcd79 --- sound/soc/phytium/pmdk_es8336.c | 2 ++ sound/soc/phytium/pmdk_es8388.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/sound/soc/phytium/pmdk_es8336.c b/sound/soc/phytium/pmdk_es8336.c index 258aa64035..1008533b28 100644 --- a/sound/soc/phytium/pmdk_es8336.c +++ b/sound/soc/phytium/pmdk_es8336.c @@ -8,6 +8,7 @@ #include #include +#define PMDK_ES8336_VERSION "1.0.0" /* PMDK widgets */ static const struct snd_soc_dapm_widget pmdk_es8336_dapm_widgets[] = { @@ -95,3 +96,4 @@ module_platform_driver(pmdk_sound_driver); MODULE_AUTHOR("Zhang Yiqun "); MODULE_DESCRIPTION("ALSA SoC PMDK ES8336"); MODULE_LICENSE("GPL"); +MODULE_VERSION(PMDK_ES8336_VERSION); diff --git a/sound/soc/phytium/pmdk_es8388.c b/sound/soc/phytium/pmdk_es8388.c index dcee078b17..066fa46ed4 100644 --- a/sound/soc/phytium/pmdk_es8388.c +++ b/sound/soc/phytium/pmdk_es8388.c @@ -9,6 +9,8 @@ #include #include +#define PMDK_ES8388_VERSION "1.0.0" + static struct snd_soc_jack hs_jack; /* Headset jack detection DAPM pins */ @@ -167,3 +169,4 @@ module_platform_driver(pmdk_sound_driver); MODULE_AUTHOR("Zhang Yiqun"); MODULE_DESCRIPTION("ALSA SoC PMDK ES8388"); MODULE_LICENSE("GPL"); +MODULE_VERSION(PMDK_ES8388_VERSION); -- Gitee From 7f0e766dfd03d194926d9feadc5870d7ce1607dc Mon Sep 17 00:00:00 2001 From: YuDa Date: Fri, 14 Jun 2024 08:09:43 +0000 Subject: [PATCH 049/121] drm/phytium: Modify driver to adapt to ARM and X86_64 compiles Modify Makefile and code by adding conditional compilation to adapt to ARM and X86_64 architecture compilers. Mainline: Open-Source Signed-off-by: Yu Da Signed-off-by: Wang Yinfeng Change-Id: I7f9132c8b8c65b8d4bb3b915608fbf532c0b0745 --- drivers/gpu/drm/phytium/Makefile | 5 +++++ drivers/gpu/drm/phytium/pe220x_dc.c | 2 ++ drivers/gpu/drm/phytium/phytium_crtc.c | 20 ++++++++++++++++++++ drivers/gpu/drm/phytium/phytium_gem.c | 4 ++-- drivers/gpu/drm/phytium/px210_dc.c | 2 ++ 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/phytium/Makefile b/drivers/gpu/drm/phytium/Makefile index 2dc7ea1118..2e730a02f1 100644 --- a/drivers/gpu/drm/phytium/Makefile +++ b/drivers/gpu/drm/phytium/Makefile @@ -16,3 +16,8 @@ phytium-dc-drm-y := phytium_display_drv.o \ obj-$(CONFIG_DRM_PHYTIUM) += phytium-dc-drm.o CFLAGS_REMOVE_phytium_crtc.o += -mgeneral-regs-only +ifeq ($(ARCH), x86) + FPU_CFLAGS += -mhard-float + FPU_CFLAGS += -msse -msse2 + CFLAGS_phytium_crtc.o += $(FPU_CFLAGS) +endif \ No newline at end of file diff --git a/drivers/gpu/drm/phytium/pe220x_dc.c b/drivers/gpu/drm/phytium/pe220x_dc.c index b465dbb615..886bf6071c 100644 --- a/drivers/gpu/drm/phytium/pe220x_dc.c +++ b/drivers/gpu/drm/phytium/pe220x_dc.c @@ -7,7 +7,9 @@ #include #include +#if defined(__arm__) || defined(__aarch64__) #include +#endif #include #include "phytium_display_drv.h" #include "pe220x_reg.h" diff --git a/drivers/gpu/drm/phytium/phytium_crtc.c b/drivers/gpu/drm/phytium/phytium_crtc.c index 8adc1c6e10..a2c736f7fd 100644 --- a/drivers/gpu/drm/phytium/phytium_crtc.c +++ b/drivers/gpu/drm/phytium/phytium_crtc.c @@ -6,7 +6,11 @@ #include #include +#if defined(__arm__) || defined(__aarch64__) #include +#elif defined(__x86_64) +#include +#endif #include #include "phytium_display_drv.h" #include "phytium_crtc.h" @@ -276,14 +280,22 @@ static void phytium_dc_scaling_config(struct drm_crtc *crtc, memset(&kernel_info_width, 0, sizeof(struct filter_blit_array)); kernel_info_width.kernelStates = tmp; memset(kernel_info_width.kernelStates, 0, KERNELSTATES); +#if defined(__arm__) || defined(__aarch64__) kernel_neon_begin(); +#elif defined(__x86_64__) + kernel_fpu_begin(); +#endif dc_calculate_sync_table(FRAMEBUFFER_HORIZONTAL_FILTER_TAP, phytium_crtc->src_width, phytium_crtc->dst_width, &kernel_info_width); memset(kernelStates, 0, sizeof(kernelStates)); memcpy(kernelStates, kernel_info_width.kernelStates + 1, KERNELSTATES - 4); +#if defined(__arm__) || defined(__aarch64__) kernel_neon_end(); +#elif defined(__x86_64__) + kernel_fpu_end(); +#endif phytium_writel_reg(priv, HORI_FILTER_INDEX, group_offset, PHYTIUM_DC_FRAMEBUFFER_HORI_FILTER_INDEX); for (i = 0; i < 128; i++) { @@ -294,12 +306,20 @@ static void phytium_dc_scaling_config(struct drm_crtc *crtc, memset(&kernel_info_width, 0, sizeof(struct filter_blit_array)); kernel_info_width.kernelStates = tmp; memset(kernel_info_width.kernelStates, 0, KERNELSTATES); +#if defined(__arm__) || defined(__aarch64__) kernel_neon_begin(); +#elif defined(__x86_64__) + kernel_fpu_begin(); +#endif dc_calculate_sync_table(FRAMEBUFFER_FILTER_TAP, phytium_crtc->src_height, phytium_crtc->dst_height, &kernel_info_width); memset(kernelStates, 0, sizeof(kernelStates)); memcpy(kernelStates, kernel_info_width.kernelStates + 1, KERNELSTATES - 4); +#if defined(__arm__) || defined(__aarch64__) kernel_neon_end(); +#elif defined(__x86_64__) + kernel_fpu_end(); +#endif phytium_writel_reg(priv, VERT_FILTER_INDEX, group_offset, PHYTIUM_DC_FRAMEBUFFER_VERT_FILTER_INDEX); for (i = 0; i < 128; i++) diff --git a/drivers/gpu/drm/phytium/phytium_gem.c b/drivers/gpu/drm/phytium/phytium_gem.c index 7d962076f7..8234b6b6e8 100644 --- a/drivers/gpu/drm/phytium/phytium_gem.c +++ b/drivers/gpu/drm/phytium/phytium_gem.c @@ -95,7 +95,7 @@ phytium_gem_prime_get_sg_table(struct drm_gem_object *obj) DRM_ERROR("failed to allocate sg\n"); goto sgt_free; } - page = phys_to_page(phytium_gem_obj->phys_addr); + page = pfn_to_page(__phys_to_pfn(phytium_gem_obj->phys_addr)); sg_set_page(sgt->sgl, page, PAGE_ALIGN(phytium_gem_obj->size), 0); } else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_UNIFIED) { ret = dma_get_sgtable_attrs(dev->dev, sgt, phytium_gem_obj->vaddr, @@ -449,7 +449,7 @@ struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, uns DRM_ERROR("fail to allocate carveout memory with size %lx\n", size); goto failed_dma_alloc; } - page = phys_to_page(phytium_gem_obj->phys_addr); + page = pfn_to_page(__phys_to_pfn(phytium_gem_obj->phys_addr)); phytium_gem_obj->iova = dma_map_page(dev->dev, page, 0, size, DMA_TO_DEVICE); if (dma_mapping_error(dev->dev, phytium_gem_obj->iova)) { DRM_ERROR("fail to dma map carveout memory with size %lx\n", size); diff --git a/drivers/gpu/drm/phytium/px210_dc.c b/drivers/gpu/drm/phytium/px210_dc.c index 84fd44a130..6b416fc773 100644 --- a/drivers/gpu/drm/phytium/px210_dc.c +++ b/drivers/gpu/drm/phytium/px210_dc.c @@ -6,7 +6,9 @@ #include #include +#if defined(__arm__) || defined(__aarch64__) #include +#endif #include #include "phytium_display_drv.h" #include "px210_reg.h" -- Gitee From 875f7c91922e791b2723c1645e5ee85a1ffc8ec5 Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Fri, 7 Feb 2025 14:30:44 +0800 Subject: [PATCH 050/121] Revert "drm: phytium: fix build error after merge 6.6.63" This reverts commit 6552f24a71b15aa3bbef2471f56d670c670ab032. --- drivers/gpu/drm/phytium/pe220x_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/phytium/pe220x_dp.c b/drivers/gpu/drm/phytium/pe220x_dp.c index c41446f065..b564843610 100644 --- a/drivers/gpu/drm/phytium/pe220x_dp.c +++ b/drivers/gpu/drm/phytium/pe220x_dp.c @@ -410,7 +410,7 @@ static void pe220x_dp_hw_enable_backlight(struct phytium_dp_device *phytium_dp) pwm_get_state(phytium_dp->pwm, &state); state.enabled = true; pwm_set_relative_duty_cycle(&state, 50, 100); - ret = pwm_apply_might_sleep(phytium_dp->pwm, &state); + ret = pwm_apply_state(phytium_dp->pwm, &state); gpiod_set_value(priv->edp_bl_en, 1); if (ret < 0) @@ -455,7 +455,7 @@ static int pe220x_dp_hw_set_backlight(struct phytium_dp_device *phytium_dp, uint pwm_set_relative_duty_cycle(&state, level, 100); - ret = pwm_apply_might_sleep(phytium_dp->pwm, &state); + ret = pwm_apply_state(phytium_dp->pwm, &state); if (ret < 0) DRM_ERROR("%s: failed to set backlight\n", __func__); out: -- Gitee From 839ffa89fbb3c4e2a772686c78067458a2568d6f Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Fri, 7 Feb 2025 14:31:01 +0800 Subject: [PATCH 051/121] Revert "drm/phytium: Add PWM backlight control for pe220x eDP" This reverts commit ca88f9f76cc337e8793f23e7884a7dcd20c49898. --- drivers/gpu/drm/phytium/pe220x_dp.c | 64 ++++++++++--------- drivers/gpu/drm/phytium/pe220x_dp.h | 3 +- drivers/gpu/drm/phytium/phytium_display_drv.h | 5 -- drivers/gpu/drm/phytium/phytium_dp.c | 1 - drivers/gpu/drm/phytium/phytium_dp.h | 1 - drivers/gpu/drm/phytium/phytium_panel.c | 4 +- drivers/gpu/drm/phytium/phytium_pci.c | 2 - drivers/gpu/drm/phytium/phytium_platform.c | 46 ------------- drivers/gpu/drm/phytium/px210_dp.h | 1 - 9 files changed, 38 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/phytium/pe220x_dp.c b/drivers/gpu/drm/phytium/pe220x_dp.c index b564843610..08597ae2f2 100644 --- a/drivers/gpu/drm/phytium/pe220x_dp.c +++ b/drivers/gpu/drm/phytium/pe220x_dp.c @@ -5,9 +5,6 @@ * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. */ -#include -#include -#include #include "phytium_display_drv.h" #include "pe220x_reg.h" #include "phytium_dp.h" @@ -382,9 +379,13 @@ static void pe220x_dp_hw_poweron_panel(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; + int port = phytium_dp->port; int ret = 0; - gpiod_set_value(priv->edp_power_en, 1); + phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | PANEL_POWER_ENABLE, + 0, PE220X_DC_CMD_REGISTER(port)); + ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), + FLAG_REQUEST, FLAG_REPLY); if (ret < 0) DRM_ERROR("%s: failed to poweron panel\n", __func__); } @@ -393,9 +394,13 @@ static void pe220x_dp_hw_poweroff_panel(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; + int port = phytium_dp->port; int ret = 0; - gpiod_set_value(priv->edp_power_en, 0); + phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | PANEL_POWER_DISABLE, + 0, PE220X_DC_CMD_REGISTER(port)); + ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), + FLAG_REQUEST, FLAG_REPLY); if (ret < 0) DRM_ERROR("%s: failed to poweroff panel\n", __func__); } @@ -404,15 +409,12 @@ static void pe220x_dp_hw_enable_backlight(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - struct pwm_state state; - int ret = 0; + int port = phytium_dp->port, ret = 0; - pwm_get_state(phytium_dp->pwm, &state); - state.enabled = true; - pwm_set_relative_duty_cycle(&state, 50, 100); - ret = pwm_apply_state(phytium_dp->pwm, &state); - - gpiod_set_value(priv->edp_bl_en, 1); + phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | BACKLIGHT_ENABLE, + 0, PE220X_DC_CMD_REGISTER(port)); + ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), + FLAG_REQUEST, FLAG_REPLY); if (ret < 0) DRM_ERROR("%s: failed to enable backlight\n", __func__); } @@ -421,41 +423,45 @@ static void pe220x_dp_hw_disable_backlight(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; + int port = phytium_dp->port; int ret = 0; - gpiod_set_value(priv->edp_bl_en, 0); + phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | BACKLIGHT_DISABLE, + 0, PE220X_DC_CMD_REGISTER(port)); + ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), + FLAG_REQUEST, FLAG_REPLY); if (ret < 0) - DRM_ERROR("%s: failed to disable backlight, ret = %d\n", __func__, ret); + DRM_ERROR("%s: failed to disable backlight\n", __func__); } static uint32_t pe220x_dp_hw_get_backlight(struct phytium_dp_device *phytium_dp) { - struct pwm_state state; - uint32_t level; + struct drm_device *dev = phytium_dp->dev; + struct phytium_display_private *priv = dev->dev_private; + int config; + uint32_t group_offset = priv->address_transform_base; - pwm_get_state(phytium_dp->pwm, &state); - level = pwm_get_relative_duty_cycle(&state, 100); - return level; + config = phytium_readl_reg(priv, group_offset, PE220X_DC_ADDRESS_TRANSFORM_BACKLIGHT_VALUE); + return ((config >> BACKLIGHT_VALUE_SHIFT) & BACKLIGHT_VALUE_MASK); } static int pe220x_dp_hw_set_backlight(struct phytium_dp_device *phytium_dp, uint32_t level) { - struct pwm_state state; + struct drm_device *dev = phytium_dp->dev; + struct phytium_display_private *priv = dev->dev_private; + int port = phytium_dp->port; + int config = 0; int ret = 0; if (level > PE220X_DP_BACKLIGHT_MAX) { ret = -EINVAL; goto out; } - pwm_get_state(phytium_dp->pwm, &state); - state.enabled = true; - state.period = phytium_dp->pwm->args.period; - if (state.period == 0) - DRM_ERROR("%s: set pwm period to 0\n", __func__); - - pwm_set_relative_duty_cycle(&state, level, 100); - ret = pwm_apply_state(phytium_dp->pwm, &state); + config = FLAG_REQUEST | CMD_BACKLIGHT | ((level & BACKLIGHT_MASK) << BACKLIGHT_SHIFT); + phytium_writel_reg(priv, config, 0, PE220X_DC_CMD_REGISTER(port)); + ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), + FLAG_REQUEST, FLAG_REPLY); if (ret < 0) DRM_ERROR("%s: failed to set backlight\n", __func__); out: diff --git a/drivers/gpu/drm/phytium/pe220x_dp.h b/drivers/gpu/drm/phytium/pe220x_dp.h index f9cf8a0d4f..78bb26c7b7 100644 --- a/drivers/gpu/drm/phytium/pe220x_dp.h +++ b/drivers/gpu/drm/phytium/pe220x_dp.h @@ -8,8 +8,7 @@ #ifndef __PE220X_DP_H__ #define __PE220X_DP_H__ -#define PE220X_DP_BACKLIGHT_MAX 99 -#define PE220X_DP_BACKLIGHT_MIN 2 +#define PE220X_DP_BACKLIGHT_MAX 100 void pe220x_dp_func_register(struct phytium_dp_device *phytium_dp); #endif /* __PE220X_DP_H__ */ diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.h b/drivers/gpu/drm/phytium/phytium_display_drv.h index 587614f5b2..d9d750eee3 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.h +++ b/drivers/gpu/drm/phytium/phytium_display_drv.h @@ -8,7 +8,6 @@ #define __PHYTIUM_DISPLAY_DRV_H__ #include -#include #include #define DEBUG_LOG 0 @@ -70,9 +69,7 @@ struct phytium_device_info { unsigned int hdisplay_max; unsigned int vdisplay_max; unsigned int backlight_max; - unsigned int backlight_min; unsigned long address_mask; - struct pwm_device *pwm; }; struct phytium_display_private { @@ -118,8 +115,6 @@ struct phytium_display_private { /* DMA info */ int dma_inited; struct dma_chan *dma_chan; - /*BL GPIO info*/ - struct gpio_desc *edp_bl_en, *edp_power_en; }; static inline unsigned int diff --git a/drivers/gpu/drm/phytium/phytium_dp.c b/drivers/gpu/drm/phytium/phytium_dp.c index 78eac4fde1..0c6d30e800 100644 --- a/drivers/gpu/drm/phytium/phytium_dp.c +++ b/drivers/gpu/drm/phytium/phytium_dp.c @@ -2594,7 +2594,6 @@ int phytium_dp_init(struct drm_device *dev, int port) if (phytium_dp_is_edp(phytium_dp, port)) { phytium_dp->is_edp = true; type = DRM_MODE_CONNECTOR_eDP; - phytium_dp->pwm = priv->info.pwm; phytium_dp_panel_init_backlight_funcs(phytium_dp); phytium_edp_backlight_off(phytium_dp); phytium_edp_panel_poweroff(phytium_dp); diff --git a/drivers/gpu/drm/phytium/phytium_dp.h b/drivers/gpu/drm/phytium/phytium_dp.h index c4915dd403..6ce7cd7142 100644 --- a/drivers/gpu/drm/phytium/phytium_dp.h +++ b/drivers/gpu/drm/phytium/phytium_dp.h @@ -113,7 +113,6 @@ struct phytium_dp_device { struct phytium_panel panel; struct drm_display_mode native_mode; - struct pwm_device *pwm; }; union phytium_phy_tp { diff --git a/drivers/gpu/drm/phytium/phytium_panel.c b/drivers/gpu/drm/phytium/phytium_panel.c index 15fe45f426..f2d0088e38 100644 --- a/drivers/gpu/drm/phytium/phytium_panel.c +++ b/drivers/gpu/drm/phytium/phytium_panel.c @@ -195,7 +195,7 @@ static void phytium_dp_hw_setup_backlight(struct phytium_panel *panel) struct phytium_display_private *priv = dev->dev_private; panel->max = priv->info.backlight_max; - panel->min = priv->info.backlight_min; + panel->min = 0; panel->level = phytium_dp_hw_get_backlight(panel); } @@ -211,7 +211,7 @@ void phytium_dp_panel_init_backlight_funcs(struct phytium_dp_device *phytium_dp) phytium_dp->panel.set_backlight = phytium_dp_aux_set_backlight; phytium_dp->panel.get_backlight = phytium_dp_aux_get_backlight; } else { - DRM_DEBUG_KMS("PWM Backlight Control Supported!\n"); + DRM_DEBUG_KMS("SE Backlight Control Supported!\n"); phytium_dp->panel.setup_backlight = phytium_dp_hw_setup_backlight; phytium_dp->panel.enable_backlight = phytium_dp_hw_enable_backlight; phytium_dp->panel.disable_backlight = phytium_dp_hw_disable_backlight; diff --git a/drivers/gpu/drm/phytium/phytium_pci.c b/drivers/gpu/drm/phytium/phytium_pci.c index 80a1db064e..e046c299da 100644 --- a/drivers/gpu/drm/phytium/phytium_pci.c +++ b/drivers/gpu/drm/phytium/phytium_pci.c @@ -402,7 +402,6 @@ static const struct phytium_device_info px210_info = { .vdisplay_max = PX210_DC_VDISPLAY_MAX, .address_mask = PX210_DC_ADDRESS_MASK, .backlight_max = PX210_DP_BACKLIGHT_MAX, - .backlight_min = PX210_DP_BACKLIGHT_MIN, }; static const struct phytium_device_info pe220x_info = { @@ -413,7 +412,6 @@ static const struct phytium_device_info pe220x_info = { .vdisplay_max = PE220X_DC_VDISPLAY_MAX, .address_mask = PE220X_DC_ADDRESS_MASK, .backlight_max = PE220X_DP_BACKLIGHT_MAX, - .backlight_min = PE220X_DP_BACKLIGHT_MIN, }; static const struct pci_device_id phytium_display_pci_ids[] = { diff --git a/drivers/gpu/drm/phytium/phytium_platform.c b/drivers/gpu/drm/phytium/phytium_platform.c index 32c4a3efeb..df0dce0497 100644 --- a/drivers/gpu/drm/phytium/phytium_platform.c +++ b/drivers/gpu/drm/phytium/phytium_platform.c @@ -10,9 +10,6 @@ #include #include #include -#include -#include -#include #include "phytium_display_drv.h" #include "phytium_platform.h" #include "phytium_dp.h" @@ -128,27 +125,6 @@ phytium_platform_private_init(struct platform_device *pdev) dev_err(&pdev->dev, "missing edp_mask property from dts\n"); goto failed; } - if (priv->info.edp_mask) { - priv->info.pwm = devm_pwm_get(&pdev->dev, NULL); - if (IS_ERR(priv->info.pwm)) { - dev_err(&pdev->dev, "Failed to request PWM device: %ld\n", - PTR_ERR(priv->info.pwm)); - goto failed; - } - priv->edp_bl_en = gpiod_get(&pdev->dev, "edp-bl-en", GPIOD_OUT_HIGH); - if (!priv->edp_bl_en) { - dev_err(&pdev->dev, "Failed to get edp_en gpio\n"); - goto failed; - } - priv->edp_power_en = gpiod_get(&pdev->dev, "edp-power-en", GPIOD_OUT_HIGH); - if (!priv->edp_power_en) { - dev_err(&pdev->dev, "Failed to get edp_pwr_en gpio\n"); - goto failed; - } - // set GPIO pin output - gpiod_direction_output(priv->edp_power_en, 0); - gpiod_direction_output(priv->edp_bl_en, 0); - } } else if (has_acpi_companion(&pdev->dev)) { phytium_info = (struct phytium_device_info *)acpi_device_get_match_data(&pdev->dev); if (!phytium_info) { @@ -168,27 +144,6 @@ phytium_platform_private_init(struct platform_device *pdev) dev_err(&pdev->dev, "missing edp_mask property from acpi\n"); goto failed; } - if (priv->info.edp_mask) { - priv->info.pwm = devm_pwm_get(&pdev->dev, NULL); - if (IS_ERR(priv->info.pwm)) { - dev_err(&pdev->dev, "Failed to request PWM device: %ld\n", - PTR_ERR(priv->info.pwm)); - goto failed; - } - priv->edp_bl_en = gpiod_get(&pdev->dev, "edp-bl-en", GPIOD_OUT_HIGH); - if (!priv->edp_bl_en) { - dev_err(&pdev->dev, "Failed to get edp_en gpio\n"); - goto failed; - } - priv->edp_power_en = gpiod_get(&pdev->dev, "edp-power-en", GPIOD_OUT_HIGH); - if (!priv->edp_power_en) { - dev_err(&pdev->dev, "Failed to get edp_pwr_en gpio\n"); - goto failed; - } - // set GPIO pin output - gpiod_direction_output(priv->edp_power_en, 0); - gpiod_direction_output(priv->edp_bl_en, 0); - } } priv->info.num_pipes = 0; @@ -332,7 +287,6 @@ static const struct phytium_device_info pe220x_info = { .vdisplay_max = PE220X_DC_VDISPLAY_MAX, .address_mask = PE220X_DC_ADDRESS_MASK, .backlight_max = PE220X_DP_BACKLIGHT_MAX, - .backlight_min = PE220X_DP_BACKLIGHT_MIN, }; static const struct of_device_id display_of_match[] = { diff --git a/drivers/gpu/drm/phytium/px210_dp.h b/drivers/gpu/drm/phytium/px210_dp.h index b62a3c833a..07e40265f0 100644 --- a/drivers/gpu/drm/phytium/px210_dp.h +++ b/drivers/gpu/drm/phytium/px210_dp.h @@ -8,7 +8,6 @@ #define __PX210_DP_H__ #define PX210_DP_BACKLIGHT_MAX 100 -#define PX210_DP_BACKLIGHT_MIN 0 void px210_dp_func_register(struct phytium_dp_device *phytium_dp); #endif /* __PX210_DP_H__ */ -- Gitee From 6d9c15db19864ffddad529551a94adf34a690f10 Mon Sep 17 00:00:00 2001 From: YuDa Date: Tue, 23 Jul 2024 08:58:45 +0000 Subject: [PATCH 052/121] drm/phytium: Add dc patches for BMC device This add dc patches for BMC device as following: 1) Modify the reset logic in BMC mode. 2) Disable hardware cursor and gamma, currently only support for XRGB888. 3) Add the ioctl interface to indentify whether the current device is a BMC device. Mainline: Open-Source Signed-off-by: Yang Xun Signed-off-by: Yu Da Signed-off-by: Wang Yinfeng Change-Id: I6f13481c32267c17c16390abfc6384d2dbbefe07 --- drivers/gpu/drm/phytium/pe220x_dc.c | 120 ++++++++++++------ drivers/gpu/drm/phytium/pe220x_dc.h | 3 + drivers/gpu/drm/phytium/phytium_crtc.c | 21 ++- drivers/gpu/drm/phytium/phytium_display_drv.c | 13 ++ drivers/gpu/drm/phytium/phytium_display_drv.h | 2 + drivers/gpu/drm/phytium/phytium_pci.c | 2 + drivers/gpu/drm/phytium/phytium_plane.c | 7 +- drivers/gpu/drm/phytium/phytium_platform.c | 1 + 8 files changed, 121 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/phytium/pe220x_dc.c b/drivers/gpu/drm/phytium/pe220x_dc.c index 886bf6071c..cfdecad435 100644 --- a/drivers/gpu/drm/phytium/pe220x_dc.c +++ b/drivers/gpu/drm/phytium/pe220x_dc.c @@ -58,6 +58,10 @@ static const unsigned int pe220x_primary_formats[] = { DRM_FORMAT_NV21, }; +static const unsigned int pe220x_bmc_primary_formats[] = { + DRM_FORMAT_XRGB8888, +}; + static uint64_t pe220x_primary_formats_modifiers[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID @@ -111,49 +115,76 @@ void pe220x_dc_hw_reset(struct drm_crtc *crtc) int config = 0; int phys_pipe = phytium_crtc->phys_pipe; - /* disable pixel clock for bmc mode */ - if (phys_pipe == 0) - pe220x_dc_hw_disable(crtc); - config = phytium_readl_reg(priv, 0, PE220X_DC_CLOCK_CONTROL); - config &= (~(DC0_CORE_RESET | DC1_CORE_RESET | AXI_RESET | AHB_RESET)); - if (phys_pipe == 0) { - phytium_writel_reg(priv, config | DC0_CORE_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET | AHB_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config | DC0_CORE_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); + if (priv->info.bmc_mode) { + pe220x_dc_hw_disable(crtc); + config &= (~(DC0_CORE_RESET | DC1_CORE_RESET | AHB_RESET)); + if (phys_pipe == 0) { + phytium_writel_reg(priv, config | DC0_CORE_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC0_CORE_RESET | AHB_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC0_CORE_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + } else { + phytium_writel_reg(priv, config | DC1_CORE_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC1_CORE_RESET | AHB_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC1_CORE_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + } + } else { - phytium_writel_reg(priv, config | DC1_CORE_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET | AHB_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config | DC1_CORE_RESET, - 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); - phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL); - udelay(20); + config &= (~(DC0_CORE_RESET | DC1_CORE_RESET | AXI_RESET | AHB_RESET)); + if (phys_pipe == 0) { + phytium_writel_reg(priv, config | DC0_CORE_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET | AHB_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC0_CORE_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + } else { + phytium_writel_reg(priv, config | DC1_CORE_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET | AHB_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config | DC1_CORE_RESET, + 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL); + udelay(20); + } } } @@ -218,6 +249,15 @@ void pe220x_dc_hw_plane_get_primary_format(const uint64_t **format_modifiers, *format_count = ARRAY_SIZE(pe220x_primary_formats); } +void pe220x_dc_bmc_hw_plane_get_primary_format(const uint64_t **format_modifiers, + const uint32_t **formats, + uint32_t *format_count) +{ + *format_modifiers = pe220x_primary_formats_modifiers; + *formats = pe220x_bmc_primary_formats; + *format_count = ARRAY_SIZE(pe220x_bmc_primary_formats); +} + void pe220x_dc_hw_plane_get_cursor_format(const uint64_t **format_modifiers, const uint32_t **formats, uint32_t *format_count) diff --git a/drivers/gpu/drm/phytium/pe220x_dc.h b/drivers/gpu/drm/phytium/pe220x_dc.h index 5840795cba..1fd0db3b8d 100644 --- a/drivers/gpu/drm/phytium/pe220x_dc.h +++ b/drivers/gpu/drm/phytium/pe220x_dc.h @@ -22,6 +22,9 @@ extern int pe220x_dc_hw_fb_format_check(const struct drm_mode_fb_cmd2 *mode_cmd, extern void pe220x_dc_hw_plane_get_primary_format(const uint64_t **format_modifiers, const uint32_t **formats, uint32_t *format_count); +extern void pe220x_dc_bmc_hw_plane_get_primary_format(const uint64_t **format_modifiers, + const uint32_t **formats, + uint32_t *format_count); extern void pe220x_dc_hw_plane_get_cursor_format(const uint64_t **format_modifiers, const uint32_t **formats, uint32_t *format_count); diff --git a/drivers/gpu/drm/phytium/phytium_crtc.c b/drivers/gpu/drm/phytium/phytium_crtc.c index a2c736f7fd..b0c1f49806 100644 --- a/drivers/gpu/drm/phytium/phytium_crtc.c +++ b/drivers/gpu/drm/phytium/phytium_crtc.c @@ -591,7 +591,8 @@ phytium_crtc_atomic_enable(struct drm_crtc *crtc, else config &= (~FRAMEBUFFER_SCALE_ENABLE); - config |= FRAMEBUFFER_GAMMA_ENABLE; + if (!priv->info.bmc_mode) + config |= FRAMEBUFFER_GAMMA_ENABLE; if (crtc->state->gamma_lut) phytium_crtc_gamma_set(crtc); @@ -768,6 +769,7 @@ int phytium_crtc_init(struct drm_device *dev, int phys_pipe) struct phytium_crtc_state *phytium_crtc_state; struct phytium_plane *phytium_primary_plane = NULL; struct phytium_plane *phytium_cursor_plane = NULL; + struct drm_plane *cursor_base = NULL; struct phytium_display_private *priv = dev->dev_private; int ret; @@ -810,16 +812,21 @@ int phytium_crtc_init(struct drm_device *dev, int phys_pipe) goto failed_create_primary; } - phytium_cursor_plane = phytium_cursor_plane_create(dev, phys_pipe); - if (IS_ERR(phytium_cursor_plane)) { - ret = PTR_ERR(phytium_cursor_plane); - DRM_ERROR("create cursor plane failed, phys_pipe(%d)\n", phys_pipe); - goto failed_create_cursor; + if (priv->info.bmc_mode) { + cursor_base = NULL; + } else { + phytium_cursor_plane = phytium_cursor_plane_create(dev, phys_pipe); + if (IS_ERR(phytium_cursor_plane)) { + ret = PTR_ERR(phytium_cursor_plane); + DRM_ERROR("create cursor plane failed, phys_pipe(%d)\n", phys_pipe); + goto failed_create_cursor; + } + cursor_base = &phytium_cursor_plane->base; } ret = drm_crtc_init_with_planes(dev, &phytium_crtc->base, &phytium_primary_plane->base, - &phytium_cursor_plane->base, + cursor_base, &phytium_crtc_funcs, "phys_pipe %d", phys_pipe); diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.c b/drivers/gpu/drm/phytium/phytium_display_drv.c index c311c1c977..97e34d8722 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.c +++ b/drivers/gpu/drm/phytium/phytium_display_drv.c @@ -289,8 +289,11 @@ static void phytium_display_unload(struct drm_device *dev) * The device specific ioctl range is 0x40 to 0x79. */ #define DRM_PHYTIUM_VRAM_TYPE_DEVICE 0x0 +#define DRM_PHYTIUM_BMC_DEVICE 0x1 #define DRM_IOCTL_PHYTIUM_VRAM_TYPE_DEVICE DRM_IO(DRM_COMMAND_BASE\ + DRM_PHYTIUM_VRAM_TYPE_DEVICE) +#define DRM_IOCTL_PHYTIUM_IS_BMC_DEVICE DRM_IO(DRM_COMMAND_BASE\ + + DRM_PHYTIUM_BMC_DEVICE) static int phytium_ioctl_check_vram_device(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -300,10 +303,20 @@ static int phytium_ioctl_check_vram_device(struct drm_device *dev, void *data, return ((priv->support_memory_type == MEMORY_TYPE_VRAM_DEVICE) ? 1 : 0); } +static int phytium_ioctl_check_bmc_device(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct phytium_display_private *priv = dev->dev_private; + + return priv->info.bmc_mode ? 1 : 0; +} + static const struct drm_ioctl_desc phytium_ioctls[] = { /* for test, none so far */ DRM_IOCTL_DEF_DRV(PHYTIUM_VRAM_TYPE_DEVICE, phytium_ioctl_check_vram_device, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(PHYTIUM_IS_BMC_DEVICE, phytium_ioctl_check_bmc_device, + DRM_AUTH|DRM_UNLOCKED), }; static const struct file_operations phytium_drm_driver_fops = { diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.h b/drivers/gpu/drm/phytium/phytium_display_drv.h index d9d750eee3..cbf043c994 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.h +++ b/drivers/gpu/drm/phytium/phytium_display_drv.h @@ -65,6 +65,8 @@ struct phytium_device_info { unsigned char num_pipes; unsigned char total_pipes; unsigned char edp_mask; + bool bmc_mode; + unsigned char reserve[2]; unsigned int crtc_clock_max; unsigned int hdisplay_max; unsigned int vdisplay_max; diff --git a/drivers/gpu/drm/phytium/phytium_pci.c b/drivers/gpu/drm/phytium/phytium_pci.c index e046c299da..e81c4c7acf 100644 --- a/drivers/gpu/drm/phytium/phytium_pci.c +++ b/drivers/gpu/drm/phytium/phytium_pci.c @@ -402,6 +402,7 @@ static const struct phytium_device_info px210_info = { .vdisplay_max = PX210_DC_VDISPLAY_MAX, .address_mask = PX210_DC_ADDRESS_MASK, .backlight_max = PX210_DP_BACKLIGHT_MAX, + .bmc_mode = false, }; static const struct phytium_device_info pe220x_info = { @@ -412,6 +413,7 @@ static const struct phytium_device_info pe220x_info = { .vdisplay_max = PE220X_DC_VDISPLAY_MAX, .address_mask = PE220X_DC_ADDRESS_MASK, .backlight_max = PE220X_DP_BACKLIGHT_MAX, + .bmc_mode = true, }; static const struct pci_device_id phytium_display_pci_ids[] = { diff --git a/drivers/gpu/drm/phytium/phytium_plane.c b/drivers/gpu/drm/phytium/phytium_plane.c index bc28ad8d45..228c637b87 100644 --- a/drivers/gpu/drm/phytium/phytium_plane.c +++ b/drivers/gpu/drm/phytium/phytium_plane.c @@ -580,7 +580,12 @@ struct phytium_plane *phytium_primary_plane_create(struct drm_device *dev, int p phytium_plane->dc_hw_update_primary_hi_addr = px210_dc_hw_update_primary_hi_addr; phytium_plane->dc_hw_update_cursor_hi_addr = NULL; } else if (IS_PE220X(priv)) { - phytium_plane->dc_hw_plane_get_format = pe220x_dc_hw_plane_get_primary_format; + if (priv->info.bmc_mode) + phytium_plane->dc_hw_plane_get_format = + pe220x_dc_bmc_hw_plane_get_primary_format; + else + phytium_plane->dc_hw_plane_get_format = + pe220x_dc_hw_plane_get_primary_format; phytium_plane->dc_hw_update_dcreq = NULL; phytium_plane->dc_hw_update_primary_hi_addr = pe220x_dc_hw_update_primary_hi_addr; phytium_plane->dc_hw_update_cursor_hi_addr = NULL; diff --git a/drivers/gpu/drm/phytium/phytium_platform.c b/drivers/gpu/drm/phytium/phytium_platform.c index df0dce0497..278d90a3fa 100644 --- a/drivers/gpu/drm/phytium/phytium_platform.c +++ b/drivers/gpu/drm/phytium/phytium_platform.c @@ -287,6 +287,7 @@ static const struct phytium_device_info pe220x_info = { .vdisplay_max = PE220X_DC_VDISPLAY_MAX, .address_mask = PE220X_DC_ADDRESS_MASK, .backlight_max = PE220X_DP_BACKLIGHT_MAX, + .bmc_mode = false, }; static const struct of_device_id display_of_match[] = { -- Gitee From 08e9e7d5a4f655775ab64b585ca6a302e97dfa04 Mon Sep 17 00:00:00 2001 From: YuDa Date: Tue, 23 Jul 2024 09:00:05 +0000 Subject: [PATCH 053/121] drm/phytium: Change the drm driver name for pe220x If the current device is pe220x, change the drm driver name from dc to pe220x. Mainline: Open-Source Signed-off-by: Yu Da Signed-off-by: Wang Yinfeng Change-Id: I03ef9562f58ac3487a7930d89b9a72208ab13078 --- drivers/gpu/drm/phytium/phytium_pci.c | 6 ++++++ drivers/gpu/drm/phytium/phytium_platform.c | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/phytium/phytium_pci.c b/drivers/gpu/drm/phytium/phytium_pci.c index e81c4c7acf..9b88b6e021 100644 --- a/drivers/gpu/drm/phytium/phytium_pci.c +++ b/drivers/gpu/drm/phytium/phytium_pci.c @@ -256,6 +256,12 @@ static int phytium_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e struct phytium_display_private *priv = NULL; struct drm_device *dev = NULL; int ret = 0; + struct phytium_device_info *phytium_info = (struct phytium_device_info *)ent->driver_data; + + if (phytium_info) { + if (phytium_info->platform_mask & BIT(PHYTIUM_PLATFORM_PE220X)) + phytium_display_drm_driver.name = "pe220x"; + } ret = phytium_remove_conflicting_framebuffers(pdev); if (ret) { diff --git a/drivers/gpu/drm/phytium/phytium_platform.c b/drivers/gpu/drm/phytium/phytium_platform.c index 278d90a3fa..64bbdebfc4 100644 --- a/drivers/gpu/drm/phytium/phytium_platform.c +++ b/drivers/gpu/drm/phytium/phytium_platform.c @@ -193,8 +193,23 @@ static int phytium_platform_probe(struct platform_device *pdev) { struct phytium_display_private *priv = NULL; struct drm_device *dev = NULL; + struct phytium_device_info *phytium_info = NULL; int ret = 0; + if (pdev->dev.of_node) { + phytium_info = (struct phytium_device_info *)of_device_get_match_data(&pdev->dev); + if (phytium_info) { + if (phytium_info->platform_mask & BIT(PHYTIUM_PLATFORM_PE220X)) + phytium_display_drm_driver.name = "pe220x"; + } + } else if (has_acpi_companion(&pdev->dev)) { + phytium_info = (struct phytium_device_info *)acpi_device_get_match_data(&pdev->dev); + if (phytium_info) { + if (phytium_info->platform_mask & BIT(PHYTIUM_PLATFORM_PE220X)) + phytium_display_drm_driver.name = "pe220x"; + } + } + dev = drm_dev_alloc(&phytium_display_drm_driver, &pdev->dev); if (IS_ERR(dev)) { DRM_ERROR("failed to allocate drm_device\n"); -- Gitee From b0b7f7d54b2a6f3bbeb2260d977891a30662907d Mon Sep 17 00:00:00 2001 From: YuDa Date: Tue, 23 Jul 2024 09:01:15 +0000 Subject: [PATCH 054/121] drm/phytium: Add PWM backlight control for pe220x eDP When the pe220x is connected with eDP, the backlight of eDP screen is controlled using PWM and GPIO modules Mainline: Open-Source Signed-off-by: Yu Da Signed-off-by: Wang Yinfeng Change-Id: I801011c1d06892797062f519232ba4c90060e206 --- drivers/gpu/drm/phytium/pe220x_dp.c | 65 +++++++++---------- drivers/gpu/drm/phytium/pe220x_dp.h | 3 +- drivers/gpu/drm/phytium/phytium_display_drv.h | 5 ++ drivers/gpu/drm/phytium/phytium_dp.c | 1 + drivers/gpu/drm/phytium/phytium_dp.h | 1 + drivers/gpu/drm/phytium/phytium_panel.c | 4 +- drivers/gpu/drm/phytium/phytium_pci.c | 2 + drivers/gpu/drm/phytium/phytium_platform.c | 57 ++++++++++++++++ drivers/gpu/drm/phytium/px210_dp.h | 1 + 9 files changed, 100 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/phytium/pe220x_dp.c b/drivers/gpu/drm/phytium/pe220x_dp.c index 08597ae2f2..e8e5bd17fa 100644 --- a/drivers/gpu/drm/phytium/pe220x_dp.c +++ b/drivers/gpu/drm/phytium/pe220x_dp.c @@ -4,7 +4,9 @@ * * Copyright (c) 2021-2024 Phytium Technology Co., Ltd. */ - +#include +#include +#include #include "phytium_display_drv.h" #include "pe220x_reg.h" #include "phytium_dp.h" @@ -379,13 +381,9 @@ static void pe220x_dp_hw_poweron_panel(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port; int ret = 0; - phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | PANEL_POWER_ENABLE, - 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + gpiod_set_value(priv->edp_power_en, 1); if (ret < 0) DRM_ERROR("%s: failed to poweron panel\n", __func__); } @@ -394,13 +392,9 @@ static void pe220x_dp_hw_poweroff_panel(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port; int ret = 0; - phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | PANEL_POWER_DISABLE, - 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + gpiod_set_value(priv->edp_power_en, 0); if (ret < 0) DRM_ERROR("%s: failed to poweroff panel\n", __func__); } @@ -409,12 +403,15 @@ static void pe220x_dp_hw_enable_backlight(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port, ret = 0; + struct pwm_state state; + int ret = 0; + + pwm_get_state(phytium_dp->pwm, &state); + state.enabled = true; + pwm_set_relative_duty_cycle(&state, 50, 100); + ret = pwm_apply_state(phytium_dp->pwm, &state); - phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | BACKLIGHT_ENABLE, - 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + gpiod_set_value(priv->edp_bl_en, 1); if (ret < 0) DRM_ERROR("%s: failed to enable backlight\n", __func__); } @@ -423,45 +420,41 @@ static void pe220x_dp_hw_disable_backlight(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port; int ret = 0; - phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | BACKLIGHT_DISABLE, - 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + gpiod_set_value(priv->edp_bl_en, 0); if (ret < 0) - DRM_ERROR("%s: failed to disable backlight\n", __func__); + DRM_ERROR("%s: failed to disable backlight, ret = %d\n", __func__, ret); } static uint32_t pe220x_dp_hw_get_backlight(struct phytium_dp_device *phytium_dp) { - struct drm_device *dev = phytium_dp->dev; - struct phytium_display_private *priv = dev->dev_private; - int config; - uint32_t group_offset = priv->address_transform_base; + struct pwm_state state; + uint32_t level; - config = phytium_readl_reg(priv, group_offset, PE220X_DC_ADDRESS_TRANSFORM_BACKLIGHT_VALUE); - return ((config >> BACKLIGHT_VALUE_SHIFT) & BACKLIGHT_VALUE_MASK); + pwm_get_state(phytium_dp->pwm, &state); + level = pwm_get_relative_duty_cycle(&state, 100); + return level; } static int pe220x_dp_hw_set_backlight(struct phytium_dp_device *phytium_dp, uint32_t level) { - struct drm_device *dev = phytium_dp->dev; - struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port; - int config = 0; + struct pwm_state state; int ret = 0; if (level > PE220X_DP_BACKLIGHT_MAX) { ret = -EINVAL; goto out; } + pwm_get_state(phytium_dp->pwm, &state); + state.enabled = true; + state.period = phytium_dp->pwm->args.period; + if (state.period == 0) + DRM_ERROR("%s: set pwm period to 0\n", __func__); + + pwm_set_relative_duty_cycle(&state, level, 100); - config = FLAG_REQUEST | CMD_BACKLIGHT | ((level & BACKLIGHT_MASK) << BACKLIGHT_SHIFT); - phytium_writel_reg(priv, config, 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + ret = pwm_apply_state(phytium_dp->pwm, &state); if (ret < 0) DRM_ERROR("%s: failed to set backlight\n", __func__); out: diff --git a/drivers/gpu/drm/phytium/pe220x_dp.h b/drivers/gpu/drm/phytium/pe220x_dp.h index 78bb26c7b7..f9cf8a0d4f 100644 --- a/drivers/gpu/drm/phytium/pe220x_dp.h +++ b/drivers/gpu/drm/phytium/pe220x_dp.h @@ -8,7 +8,8 @@ #ifndef __PE220X_DP_H__ #define __PE220X_DP_H__ -#define PE220X_DP_BACKLIGHT_MAX 100 +#define PE220X_DP_BACKLIGHT_MAX 99 +#define PE220X_DP_BACKLIGHT_MIN 2 void pe220x_dp_func_register(struct phytium_dp_device *phytium_dp); #endif /* __PE220X_DP_H__ */ diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.h b/drivers/gpu/drm/phytium/phytium_display_drv.h index cbf043c994..23e6f8a8c8 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.h +++ b/drivers/gpu/drm/phytium/phytium_display_drv.h @@ -8,6 +8,7 @@ #define __PHYTIUM_DISPLAY_DRV_H__ #include +#include #include #define DEBUG_LOG 0 @@ -71,7 +72,9 @@ struct phytium_device_info { unsigned int hdisplay_max; unsigned int vdisplay_max; unsigned int backlight_max; + unsigned int backlight_min; unsigned long address_mask; + struct pwm_device *pwm; }; struct phytium_display_private { @@ -117,6 +120,8 @@ struct phytium_display_private { /* DMA info */ int dma_inited; struct dma_chan *dma_chan; + /*BL GPIO info*/ + struct gpio_desc *edp_bl_en, *edp_power_en; }; static inline unsigned int diff --git a/drivers/gpu/drm/phytium/phytium_dp.c b/drivers/gpu/drm/phytium/phytium_dp.c index 0c6d30e800..78eac4fde1 100644 --- a/drivers/gpu/drm/phytium/phytium_dp.c +++ b/drivers/gpu/drm/phytium/phytium_dp.c @@ -2594,6 +2594,7 @@ int phytium_dp_init(struct drm_device *dev, int port) if (phytium_dp_is_edp(phytium_dp, port)) { phytium_dp->is_edp = true; type = DRM_MODE_CONNECTOR_eDP; + phytium_dp->pwm = priv->info.pwm; phytium_dp_panel_init_backlight_funcs(phytium_dp); phytium_edp_backlight_off(phytium_dp); phytium_edp_panel_poweroff(phytium_dp); diff --git a/drivers/gpu/drm/phytium/phytium_dp.h b/drivers/gpu/drm/phytium/phytium_dp.h index 6ce7cd7142..c4915dd403 100644 --- a/drivers/gpu/drm/phytium/phytium_dp.h +++ b/drivers/gpu/drm/phytium/phytium_dp.h @@ -113,6 +113,7 @@ struct phytium_dp_device { struct phytium_panel panel; struct drm_display_mode native_mode; + struct pwm_device *pwm; }; union phytium_phy_tp { diff --git a/drivers/gpu/drm/phytium/phytium_panel.c b/drivers/gpu/drm/phytium/phytium_panel.c index f2d0088e38..15fe45f426 100644 --- a/drivers/gpu/drm/phytium/phytium_panel.c +++ b/drivers/gpu/drm/phytium/phytium_panel.c @@ -195,7 +195,7 @@ static void phytium_dp_hw_setup_backlight(struct phytium_panel *panel) struct phytium_display_private *priv = dev->dev_private; panel->max = priv->info.backlight_max; - panel->min = 0; + panel->min = priv->info.backlight_min; panel->level = phytium_dp_hw_get_backlight(panel); } @@ -211,7 +211,7 @@ void phytium_dp_panel_init_backlight_funcs(struct phytium_dp_device *phytium_dp) phytium_dp->panel.set_backlight = phytium_dp_aux_set_backlight; phytium_dp->panel.get_backlight = phytium_dp_aux_get_backlight; } else { - DRM_DEBUG_KMS("SE Backlight Control Supported!\n"); + DRM_DEBUG_KMS("PWM Backlight Control Supported!\n"); phytium_dp->panel.setup_backlight = phytium_dp_hw_setup_backlight; phytium_dp->panel.enable_backlight = phytium_dp_hw_enable_backlight; phytium_dp->panel.disable_backlight = phytium_dp_hw_disable_backlight; diff --git a/drivers/gpu/drm/phytium/phytium_pci.c b/drivers/gpu/drm/phytium/phytium_pci.c index 9b88b6e021..a8742a8ea5 100644 --- a/drivers/gpu/drm/phytium/phytium_pci.c +++ b/drivers/gpu/drm/phytium/phytium_pci.c @@ -408,6 +408,7 @@ static const struct phytium_device_info px210_info = { .vdisplay_max = PX210_DC_VDISPLAY_MAX, .address_mask = PX210_DC_ADDRESS_MASK, .backlight_max = PX210_DP_BACKLIGHT_MAX, + .backlight_min = PX210_DP_BACKLIGHT_MIN, .bmc_mode = false, }; @@ -419,6 +420,7 @@ static const struct phytium_device_info pe220x_info = { .vdisplay_max = PE220X_DC_VDISPLAY_MAX, .address_mask = PE220X_DC_ADDRESS_MASK, .backlight_max = PE220X_DP_BACKLIGHT_MAX, + .backlight_min = PE220X_DP_BACKLIGHT_MIN, .bmc_mode = true, }; diff --git a/drivers/gpu/drm/phytium/phytium_platform.c b/drivers/gpu/drm/phytium/phytium_platform.c index 64bbdebfc4..69dedbb75a 100644 --- a/drivers/gpu/drm/phytium/phytium_platform.c +++ b/drivers/gpu/drm/phytium/phytium_platform.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include "phytium_display_drv.h" #include "phytium_platform.h" #include "phytium_dp.h" @@ -125,6 +128,29 @@ phytium_platform_private_init(struct platform_device *pdev) dev_err(&pdev->dev, "missing edp_mask property from dts\n"); goto failed; } + if (priv->info.edp_mask) { + priv->info.pwm = devm_pwm_get(&pdev->dev, NULL); + if (IS_ERR(priv->info.pwm)) { + dev_err(&pdev->dev, "Failed to request PWM device: %ld\n", + PTR_ERR(priv->info.pwm)); + goto failed; + } + priv->edp_bl_en = gpiod_get(&pdev->dev, "edp-bl-en", GPIOD_OUT_HIGH); + if (IS_ERR(priv->edp_bl_en)) { + dev_err(&pdev->dev, "Failed to get edp_en gpio\n"); + priv->edp_bl_en = NULL; + goto failed; + } + priv->edp_power_en = gpiod_get(&pdev->dev, "edp-power-en", GPIOD_OUT_HIGH); + if (IS_ERR(priv->edp_power_en)) { + dev_err(&pdev->dev, "Failed to get edp_pwr_en gpio\n"); + priv->edp_power_en = NULL; + goto failed_gpio_power_init; + } + // set GPIO pin output + gpiod_direction_output(priv->edp_power_en, 0); + gpiod_direction_output(priv->edp_bl_en, 0); + } } else if (has_acpi_companion(&pdev->dev)) { phytium_info = (struct phytium_device_info *)acpi_device_get_match_data(&pdev->dev); if (!phytium_info) { @@ -144,6 +170,29 @@ phytium_platform_private_init(struct platform_device *pdev) dev_err(&pdev->dev, "missing edp_mask property from acpi\n"); goto failed; } + if (priv->info.edp_mask) { + priv->info.pwm = devm_pwm_get(&pdev->dev, NULL); + if (IS_ERR(priv->info.pwm)) { + dev_err(&pdev->dev, "Failed to request PWM device: %ld\n", + PTR_ERR(priv->info.pwm)); + goto failed; + } + priv->edp_bl_en = gpiod_get(&pdev->dev, "edp-bl-en", GPIOD_OUT_HIGH); + if (IS_ERR(priv->edp_bl_en)) { + dev_err(&pdev->dev, "Failed to get edp_en gpio\n"); + priv->edp_bl_en = NULL; + goto failed; + } + priv->edp_power_en = gpiod_get(&pdev->dev, "edp-power-en", GPIOD_OUT_HIGH); + if (IS_ERR(priv->edp_power_en)) { + dev_err(&pdev->dev, "Failed to get edp_pwr_en gpio\n"); + priv->edp_power_en = NULL; + goto failed_gpio_power_init; + } + // set GPIO pin output + gpiod_direction_output(priv->edp_power_en, 0); + gpiod_direction_output(priv->edp_bl_en, 0); + } } priv->info.num_pipes = 0; @@ -174,6 +223,8 @@ phytium_platform_private_init(struct platform_device *pdev) return priv; +failed_gpio_power_init: + gpiod_put(priv->edp_bl_en); failed: devm_kfree(&pdev->dev, platform_priv); exit: @@ -186,6 +237,11 @@ static void phytium_platform_private_fini(struct platform_device *pdev) struct phytium_display_private *priv = dev->dev_private; struct phytium_platform_private *platform_priv = to_platform_priv(priv); + if (priv->edp_power_en) + gpiod_put(priv->edp_power_en); + if (priv->edp_bl_en) + gpiod_put(priv->edp_bl_en); + devm_kfree(&pdev->dev, platform_priv); } @@ -302,6 +358,7 @@ static const struct phytium_device_info pe220x_info = { .vdisplay_max = PE220X_DC_VDISPLAY_MAX, .address_mask = PE220X_DC_ADDRESS_MASK, .backlight_max = PE220X_DP_BACKLIGHT_MAX, + .backlight_min = PE220X_DP_BACKLIGHT_MIN, .bmc_mode = false, }; diff --git a/drivers/gpu/drm/phytium/px210_dp.h b/drivers/gpu/drm/phytium/px210_dp.h index 07e40265f0..b62a3c833a 100644 --- a/drivers/gpu/drm/phytium/px210_dp.h +++ b/drivers/gpu/drm/phytium/px210_dp.h @@ -8,6 +8,7 @@ #define __PX210_DP_H__ #define PX210_DP_BACKLIGHT_MAX 100 +#define PX210_DP_BACKLIGHT_MIN 0 void px210_dp_func_register(struct phytium_dp_device *phytium_dp); #endif /* __PX210_DP_H__ */ -- Gitee From 31b1dbd980453314194576b1105955d3f8e5873a Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Fri, 7 Feb 2025 14:34:34 +0800 Subject: [PATCH 055/121] Revert "Revert "drm: phytium: fix build error after merge 6.6.63"" This reverts commit a39360e3c11423f201855c22d9f1844bb4769212. --- drivers/gpu/drm/phytium/pe220x_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/phytium/pe220x_dp.c b/drivers/gpu/drm/phytium/pe220x_dp.c index e8e5bd17fa..528dd429ea 100644 --- a/drivers/gpu/drm/phytium/pe220x_dp.c +++ b/drivers/gpu/drm/phytium/pe220x_dp.c @@ -409,7 +409,7 @@ static void pe220x_dp_hw_enable_backlight(struct phytium_dp_device *phytium_dp) pwm_get_state(phytium_dp->pwm, &state); state.enabled = true; pwm_set_relative_duty_cycle(&state, 50, 100); - ret = pwm_apply_state(phytium_dp->pwm, &state); + ret = pwm_apply_might_sleep(phytium_dp->pwm, &state); gpiod_set_value(priv->edp_bl_en, 1); if (ret < 0) @@ -454,7 +454,7 @@ static int pe220x_dp_hw_set_backlight(struct phytium_dp_device *phytium_dp, uint pwm_set_relative_duty_cycle(&state, level, 100); - ret = pwm_apply_state(phytium_dp->pwm, &state); + ret = pwm_apply_might_sleep(phytium_dp->pwm, &state); if (ret < 0) DRM_ERROR("%s: failed to set backlight\n", __func__); out: -- Gitee From 3155c3ca0ac99829dbe8ecf59cb2b6e478a35cb3 Mon Sep 17 00:00:00 2001 From: YuDa Date: Wed, 24 Jul 2024 00:42:39 +0000 Subject: [PATCH 056/121] drm/phytium: Add driver version information This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Yu Da Signed-off-by: Wang Yinfeng Change-Id: Ie9daeb6c1fa8650c674cd8589e015092d6ac605e --- drivers/gpu/drm/phytium/phytium_display_drv.c | 1 + drivers/gpu/drm/phytium/phytium_display_drv.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.c b/drivers/gpu/drm/phytium/phytium_display_drv.c index 97e34d8722..6807f91793 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.c +++ b/drivers/gpu/drm/phytium/phytium_display_drv.c @@ -460,5 +460,6 @@ module_init(phytium_display_init); module_exit(phytium_display_exit); MODULE_LICENSE("GPL"); +MODULE_VERSION(DC_DRIVER_VERSION); MODULE_AUTHOR("Yang Xun "); MODULE_DESCRIPTION("Phytium Display Controller"); diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.h b/drivers/gpu/drm/phytium/phytium_display_drv.h index 23e6f8a8c8..accfd65fe2 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.h +++ b/drivers/gpu/drm/phytium/phytium_display_drv.h @@ -21,6 +21,7 @@ #define DRV_DATE "20201220" #define DRV_MAJOR 1 #define DRV_MINOR 1 +#define DC_DRIVER_VERSION "1.0.0" /* come from GPU */ #define DRM_FORMAT_MOD_VENDOR_PHYTIUM 0x92 -- Gitee From ef1a9c77c8ebe4508afaea870450def404dda56d Mon Sep 17 00:00:00 2001 From: YuDa Date: Mon, 12 Aug 2024 07:09:35 +0000 Subject: [PATCH 057/121] drm/phytium: Remove unbinding driver interface The destroy interface in phytium_fb.c is called to destroy the gem obj of the fbcon when unbundle operation is performed. And the fb_destroy interface causes the same piece of memory to be freed repeatedly. So remove this interface. Mainline: Open-Source Signed-off-by: Yu Da Signed-off-by: Wang Yinfeng Change-Id: I508b124d27e11d8a602f3435a2b9cfde002be1a6 --- drivers/gpu/drm/phytium/phytium_fbdev.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/phytium/phytium_fbdev.c b/drivers/gpu/drm/phytium/phytium_fbdev.c index 8c424fc35e..da28813132 100644 --- a/drivers/gpu/drm/phytium/phytium_fbdev.c +++ b/drivers/gpu/drm/phytium/phytium_fbdev.c @@ -16,14 +16,6 @@ #define PHYTIUM_MAX_CONNECTOR 1 #define helper_to_drm_private(x) container_of(x, struct phytium_display_private, fbdev_helper) -static void phytium_fbdev_destroy(struct fb_info *info) -{ - struct drm_fb_helper *helper = info->par; - struct phytium_display_private *priv = helper_to_drm_private(helper); - - phytium_gem_free_object(&priv->fbdev_phytium_gem->base); -} - static int phytium_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct drm_fb_helper *helper = info->par; @@ -35,7 +27,6 @@ static int phytium_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) static const struct fb_ops phytium_fbdev_ops = { .owner = THIS_MODULE, .fb_mmap = phytium_fbdev_mmap, - .fb_destroy = phytium_fbdev_destroy, DRM_FB_HELPER_DEFAULT_OPS, __FB_DEFAULT_IOMEM_OPS_RDWR, __FB_DEFAULT_IOMEM_OPS_DRAW, -- Gitee From 3881c5ed05e24a9ba81c53081e1978bca8f68749 Mon Sep 17 00:00:00 2001 From: YuDa Date: Thu, 26 Sep 2024 06:46:51 +0000 Subject: [PATCH 058/121] drm/phytium: Change the maximum resolution supported by pe220x Change the maximum resolution supported by pe220x from 3840x2160 to 1920x1080. Mainline: Open-Source Signed-off-by: YuDa Signed-off-by: Wang Yinfeng Change-Id: Id5a1dde6e10df4ce815518e3fed62d3a84246397 --- drivers/gpu/drm/phytium/pe220x_dc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/phytium/pe220x_dc.h b/drivers/gpu/drm/phytium/pe220x_dc.h index 1fd0db3b8d..8902d11348 100644 --- a/drivers/gpu/drm/phytium/pe220x_dc.h +++ b/drivers/gpu/drm/phytium/pe220x_dc.h @@ -9,8 +9,8 @@ #define __PE220X_DC_H__ #define PE220X_DC_PIX_CLOCK_MAX (594000) -#define PE220X_DC_HDISPLAY_MAX 3840 -#define PE220X_DC_VDISPLAY_MAX 2160 +#define PE220X_DC_HDISPLAY_MAX 1920 +#define PE220X_DC_VDISPLAY_MAX 1080 #define PE220X_DC_ADDRESS_MASK 0x7f extern void pe220x_dc_hw_vram_init(struct phytium_display_private *priv, -- Gitee From 2dbd75465152f3df897427971e3d391c5873f9c9 Mon Sep 17 00:00:00 2001 From: Dai Jingtao Date: Fri, 27 Dec 2024 14:07:38 +0800 Subject: [PATCH 059/121] hda: phytium: Add link reset in resume process Link reset was done in BIOS before, which may cause pop when resumed from S3. To avoid pop, reset link in resume process. Mainline: NA Signed-off-by: Dai Jingtao Signed-off-by: Wang Yinfeng Change-Id: Ia87951f90c1f9fa5569b5dd2c3f8578f6a1cc23c --- sound/pci/hda/hda_phytium.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_phytium.c b/sound/pci/hda/hda_phytium.c index 86cd17120b..0394e57c56 100644 --- a/sound/pci/hda/hda_phytium.c +++ b/sound/pci/hda/hda_phytium.c @@ -477,7 +477,7 @@ static int azx_resume(struct device *dev) snd_hdac_bus_exit_link_reset(bus); usleep_range(1000, 1200); - azx_init_chip(chip, 0); + azx_init_chip(chip, 1); snd_power_change_state(card, SNDRV_CTL_POWER_D0); -- Gitee From bdebc60226db55efa329f8f762008d100bab9e47 Mon Sep 17 00:00:00 2001 From: Dai Jingtao Date: Sat, 28 Dec 2024 16:05:10 +0800 Subject: [PATCH 060/121] hda: phytium: Add runtime PM autosuspend function Codec should be power on during the process of probe. Driver keep power usage counter larger than 1 to ensure it. But the count doesn't decrease to 0 after probe is done, which causing codec can't go into runtime suspend. Add pm_runtime_put_autosuspend function to ensure codec can sleep when there is no audio task. Mainline: NA Signed-off-by: Dai Jingtao Signed-off-by: Wang Yinfeng Change-Id: Icc9a4887014a8b2a54966f5b747d35b740ce539b --- sound/pci/hda/hda_phytium.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/pci/hda/hda_phytium.c b/sound/pci/hda/hda_phytium.c index 0394e57c56..18e5faac71 100644 --- a/sound/pci/hda/hda_phytium.c +++ b/sound/pci/hda/hda_phytium.c @@ -967,6 +967,7 @@ static int hda_ft_probe(struct platform_device *pdev) return err; } +#define codec_power_count(codec) codec->core.dev.power.usage_count.counter /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { [AZX_DRIVER_FT] = 4, @@ -979,6 +980,7 @@ static int azx_probe_continue(struct azx *chip) int dev = chip->dev_index; int err; struct hdac_bus *bus = azx_bus(chip); + struct hda_codec *codec; hda->probe_continued = 1; @@ -1011,6 +1013,14 @@ static int azx_probe_continue(struct azx *chip) if (azx_has_pm_runtime(chip)) pm_runtime_put_noidle(hddev); + + list_for_each_codec(codec, &chip->bus) { + if (codec_power_count(codec) > 0) { + pm_runtime_mark_last_busy(&codec->core.dev); + pm_runtime_put_autosuspend(&codec->core.dev); + } + } + return err; out_free: -- Gitee From ab7903511a120e2556b4fb47074b87cd4cb77996 Mon Sep 17 00:00:00 2001 From: Peng Min Date: Wed, 24 Jul 2024 10:35:30 +0800 Subject: [PATCH 061/121] spi: phytium: Add SPI driver version description After adding the driver version description, you can use the modinfo command to view the driver version information. Mainline: Open-Source Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng Change-Id: I0f0a92e64c99317c8107c00b4b16880764be810d --- drivers/spi/spi-phytium-pci.c | 3 +++ drivers/spi/spi-phytium-plat.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/spi/spi-phytium-pci.c b/drivers/spi/spi-phytium-pci.c index 6ef8acfe5c..985aa0ed5b 100644 --- a/drivers/spi/spi-phytium-pci.c +++ b/drivers/spi/spi-phytium-pci.c @@ -26,6 +26,7 @@ #include "spi-phytium.h" #define DRIVER_NAME "phytium_spi_pci" +#define DRIVER_VERSION "1.0.0" static int phytium_spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -109,6 +110,7 @@ static const struct pci_device_id phytium_device_pci_tbl[] = { { PCI_VDEVICE(PHYTIUM, 0xdc2c) }, {}, }; +MODULE_DEVICE_TABLE(pci, phytium_device_pci_tbl); static struct pci_driver phytium_spi_pci_driver = { .name = DRIVER_NAME, @@ -125,3 +127,4 @@ module_pci_driver(phytium_spi_pci_driver); MODULE_AUTHOR("Yiqun Zhang "); MODULE_DESCRIPTION("PCI Driver for Phytium SPI controller core"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRIVER_VERSION); diff --git a/drivers/spi/spi-phytium-plat.c b/drivers/spi/spi-phytium-plat.c index 9b82c5c016..01101e501a 100644 --- a/drivers/spi/spi-phytium-plat.c +++ b/drivers/spi/spi-phytium-plat.c @@ -29,6 +29,7 @@ #include "spi-phytium.h" #define DRIVER_NAME "phytium_spi" +#define DRIVER_VERSION "1.0.0" struct phytium_spi_clk { struct phytium_spi fts; @@ -169,3 +170,4 @@ module_platform_driver(phytium_spi_driver); MODULE_AUTHOR("Yiqun Zhang "); MODULE_DESCRIPTION("Platform Driver for Phytium SPI controller core"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRIVER_VERSION); -- Gitee From c66176ca9bcdfe9756af330dfb934e5415786c7f Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Fri, 7 Feb 2025 15:22:40 +0800 Subject: [PATCH 062/121] Revert "drivers: mtd: resolve Call trace during MTD driver initialization" This reverts commit 44b2a1d6817e9d428842dcf46b953a8d719a24af. --- drivers/mtd/mtdpart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 17a44b31c0..941acf5332 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -583,7 +583,7 @@ static int mtd_part_acpi_parse(struct mtd_info *master, struct mtd_part_parser *parser; struct acpi_device *adev; struct fwnode_handle *child; - const char *compat = NULL; + const char *compat; const char *fixed = "acpi-partitions"; int ret, err = 0; int compare = 1; -- Gitee From 4e8dc6c934b21eba639228072af597121dde8a63 Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Fri, 7 Feb 2025 15:23:01 +0800 Subject: [PATCH 063/121] Revert "mtd: parsers: Add ACPI table support for qspi/spi driver" This reverts commit a26362b58e23338e0131e719fddf6f36b21de6bc. --- MAINTAINERS | 1 - drivers/mtd/mtdcore.c | 9 +- drivers/mtd/mtdpart.c | 54 +---------- drivers/mtd/parsers/Kconfig | 9 -- drivers/mtd/parsers/Makefile | 2 - drivers/mtd/parsers/acpipart_core.c | 142 ---------------------------- drivers/mtd/spi-nor/core.c | 13 --- drivers/spi/spi-phytium-qspi.c | 77 +++++---------- include/linux/mtd/partitions.h | 4 - 9 files changed, 31 insertions(+), 280 deletions(-) delete mode 100644 drivers/mtd/parsers/acpipart_core.c diff --git a/MAINTAINERS b/MAINTAINERS index d265d1a06c..27a3ed1e46 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17487,7 +17487,6 @@ F: drivers/mfd/phytium_px210_i2s_mmd.c F: drivers/mmc/host/phytium-mci* F: drivers/mmc/host/phytium-sdci.* F: drivers/mtd/nand/raw/phytium_nand* -F: drivers/mtd/parsers/acpipart_core.c F: drivers/net/can/phytium/* F: drivers/net/ethernet/Kconfig F: drivers/net/ethernet/Makefile diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index c5a59c4881..97ca2a897f 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -743,8 +743,7 @@ int add_mtd_device(struct mtd_info *mtd) dev_set_name(&mtd->dev, "mtd%d", i); dev_set_drvdata(&mtd->dev, mtd); mtd_check_of_node(mtd); - if (mtd->dev.of_node) - of_node_get(mtd_get_of_node(mtd)); + of_node_get(mtd_get_of_node(mtd)); error = device_register(&mtd->dev); if (error) { put_device(&mtd->dev); @@ -906,8 +905,7 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, config.ignore_wp = true; config.reg_read = reg_read; config.size = size; - if (IS_ENABLED(CONFIG_OF)) - config.of_node = np; + config.of_node = np; config.priv = mtd; nvmem = nvmem_register(&config); @@ -915,8 +913,7 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, if (IS_ERR(nvmem) && PTR_ERR(nvmem) == -EOPNOTSUPP) nvmem = NULL; - if (IS_ENABLED(CONFIG_OF)) - of_node_put(np); + of_node_put(np); return nvmem; } diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 941acf5332..23483db8f3 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -19,8 +19,6 @@ #include #include -#include -#include #include "mtdcore.h" /* @@ -506,14 +504,12 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser); static const char * const default_mtd_part_types[] = { "cmdlinepart", "ofpart", - "acpipart", NULL }; /* Check DT only when looking for subpartitions. */ static const char * const default_subpartition_types[] = { "ofpart", - "acpipart", NULL }; @@ -577,44 +573,6 @@ static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat return ret; } -static int mtd_part_acpi_parse(struct mtd_info *master, - struct mtd_partitions *pparts) -{ - struct mtd_part_parser *parser; - struct acpi_device *adev; - struct fwnode_handle *child; - const char *compat; - const char *fixed = "acpi-partitions"; - int ret, err = 0; - int compare = 1; - struct device *dev = &master->dev; - - if (has_acpi_companion(dev)) - adev = ACPI_COMPANION(dev); - if (!mtd_is_partition(master)) { - fwnode_property_read_string(dev->fwnode, "fixed", &compat); - if (compat) - compare = strcmp(compat, fixed); - } - - device_for_each_child_node(dev, child) { - if (compat && !compare) { - parser = mtd_part_parser_get(fixed); - if (!parser && !request_module("%s", fixed)) - parser = mtd_part_parser_get(fixed); - if (parser) { - ret = mtd_part_do_parse(parser, master, pparts, NULL); - if (ret > 0) - return ret; - mtd_part_parser_put(parser); - if (ret < 0 && !err) - err = ret; - } - } - } - return err; -} - static int mtd_part_of_parse(struct mtd_info *master, struct mtd_partitions *pparts) { @@ -633,7 +591,7 @@ static int mtd_part_of_parse(struct mtd_info *master, dev = master->dev.parent; np = mtd_get_of_node(master); - if (mtd_is_partition(master) && np) + if (mtd_is_partition(master)) of_node_get(np); else np = of_get_child_by_name(np, "partitions"); @@ -654,8 +612,7 @@ static int mtd_part_of_parse(struct mtd_info *master, ret = mtd_part_do_parse(parser, master, pparts, NULL); if (ret > 0) { of_platform_populate(np, NULL, NULL, dev); - if (np) - of_node_put(np); + of_node_put(np); return ret; } mtd_part_parser_put(parser); @@ -663,8 +620,7 @@ static int mtd_part_of_parse(struct mtd_info *master, err = ret; } of_platform_populate(np, NULL, NULL, dev); - if (np) - of_node_put(np); + of_node_put(np); /* * For backward compatibility we have to try the "fixed-partitions" @@ -722,9 +678,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, * should be used. It requires a bit different logic so it is * handled in a separated function. */ - if (!strcmp(*types, "acpipart")) { - ret = mtd_part_acpi_parse(master, &pparts); - } else if (!strcmp(*types, "ofpart")) { + if (!strcmp(*types, "ofpart")) { ret = mtd_part_of_parse(master, &pparts); } else { pr_debug("%s: parsing partitions %s\n", master->name, diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index ae1870d271..60738edcd5 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -96,15 +96,6 @@ config MTD_OF_PARTS_LINKSYS_NS two "firmware" partitions. Currently used firmware has to be detected using CFE environment variable. -config MTD_ACPI_PARTS - tristate "ACPI partitioning parser" - default y - depends on ACPI - help - This provides an acpi partition parser, which is used to parse the - partition map described in ACPI table, as the children of the flash - memory struct. - config MTD_PARSER_IMAGETAG tristate "Parser for BCM963XX Image Tag format partitions" depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile index 2679fd7668..0e70b621a1 100644 --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile @@ -8,8 +8,6 @@ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o ofpart-y += ofpart_core.o ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o -obj-$(CONFIG_MTD_ACPI_PARTS) += acpipart.o -acpipart-y += acpipart_core.o obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o obj-$(CONFIG_MTD_AFS_PARTS) += afs.o obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o diff --git a/drivers/mtd/parsers/acpipart_core.c b/drivers/mtd/parsers/acpipart_core.c deleted file mode 100644 index dde80407a6..0000000000 --- a/drivers/mtd/parsers/acpipart_core.c +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Flash partitions described by the acpi table - * - * Author: Wang Hanmo - */ - -#include -#include -#include -#include -#include -#include -#include - -static const struct acpi_device_id parse_acpipart_match_table[]; - -static int parse_acpi_fixed_partitions(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - const struct acpi_device_id *acpi_id; - const char *partname; - int nr_parts, i, ret = 0; - struct acpi_device *adev; - struct fwnode_handle *child_handle; - bool dedicated = true; - struct device *dev; - - dev = &master->dev; - adev = ACPI_COMPANION(&master->dev); - - if (!master->parent) {/*master*/ - device_get_next_child_node(dev, child_handle); - if (!child_handle) { - pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", - master->name, child_handle); - dedicated = false; - } - } - - acpi_id = acpi_match_device(parse_acpipart_match_table, dev); - if (dedicated && !acpi_id) - return 0; - - nr_parts = 0; - device_for_each_child_node(dev, child_handle) { - nr_parts++; - } - - if (nr_parts == 0) - return 0; - parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - i = 0; - device_for_each_child_node(dev, child_handle) { - u64 offset, length; - bool bool_match; - - fwnode_property_read_u64(child_handle, "offset", &offset); - fwnode_property_read_u64(child_handle, "length", &length); - if (!offset && !length) { - if (dedicated) { - pr_debug("%s: acpipart partition %pOF (%pOF) missing reg property.\n", - master->name, child_handle, - dev->fwnode); - goto acpipart_fail; - } else { - nr_parts--; - continue; - } - } - - parts[i].offset = offset; - parts[i].size = length; - parts[i].fwnode = child_handle; - if (!fwnode_property_read_string(child_handle, "label", &partname)) - parts[i].name = partname; - bool_match = fwnode_property_read_bool(child_handle, "read-only"); - if (bool_match) - parts[i].mask_flags |= MTD_WRITEABLE; - bool_match = fwnode_property_read_bool(child_handle, "lock"); - if (bool_match) - parts[i].mask_flags |= MTD_POWERUP_LOCK; - bool_match = fwnode_property_read_bool(child_handle, "slc-mode"); - if (bool_match) - parts[i].mask_flags |= MTD_SLC_ON_MLC_EMULATION; - i++; - } - - if (!nr_parts) - goto acpipart_none; - - *pparts = parts; - ret = nr_parts; - return ret; - -acpipart_fail: - pr_err("%s: error parsing acpipart partition %pOF (%pOF)\n", - master->name, child_handle, dev->fwnode); - ret = -EINVAL; -acpipart_none: - kfree(parts); - return ret; -} - -static const struct acpi_device_id parse_acpipart_match_table[] = { - /* Generic */ - { "acpi-partitions", 0 }, - /* Customized */ - {}, -}; - -MODULE_DEVICE_TABLE(acpi, parse_acpipart_match_table); - -static struct mtd_part_parser acpipart_parser = { - .parse_fn = parse_acpi_fixed_partitions, - .name = "acpi-fixed-partitions", - .acpi_match_table = ACPI_PTR(parse_acpipart_match_table), -}; - -static int __init acpipart_parser_init(void) -{ - register_mtd_parser(&acpipart_parser); - return 0; -} - -static void __exit acpipart_parser_exit(void) -{ - deregister_mtd_parser(&acpipart_parser); -} - -module_init(acpipart_parser_init); -module_exit(acpipart_parser_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Parser for MTD partitioning information in acpi table"); -MODULE_AUTHOR("Wang Hanmo "); -MODULE_ALIAS("acpi-partitions"); diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 0810e27d98..249258342e 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -7,7 +7,6 @@ * Copyright (C) 2014, Freescale Semiconductor, Inc. */ -#include #include #include #include @@ -18,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -3624,7 +3622,6 @@ static int spi_nor_probe(struct spi_mem *spimem) struct spi_device *spi = spimem->spi; struct flash_platform_data *data = dev_get_platdata(&spi->dev); struct spi_nor *nor; - struct acpi_device *adev; /* * Enable all caps by default. The core will mask them after * checking what's really supported using spi_mem_supports_op(). @@ -3640,10 +3637,6 @@ static int spi_nor_probe(struct spi_mem *spimem) nor->spimem = spimem; nor->dev = &spi->dev; spi_nor_set_flash_node(nor, spi->dev.of_node); - adev = ACPI_COMPANION(nor->dev); - nor->mtd.dev.fwnode = spi->dev.fwnode; - - device_property_read_string(&spi->dev, "_HID", &nor->mtd.name); spi_mem_set_drvdata(spimem, nor); @@ -3783,11 +3776,6 @@ static const struct of_device_id spi_nor_of_table[] = { }; MODULE_DEVICE_TABLE(of, spi_nor_of_table); -static const struct acpi_device_id spi_nor_acpi_table[] = { - {"PHYT8009", 0}, - { }, -}; -MODULE_DEVICE_TABLE(acpi, spi_nor_acpi_table); /* * REVISIT: many of these chips have deep power-down modes, which * should clearly be entered on suspend() to minimize power use. @@ -3799,7 +3787,6 @@ static struct spi_mem_driver spi_nor_driver = { .name = "spi-nor", .of_match_table = spi_nor_of_table, .dev_groups = spi_nor_sysfs_groups, - .acpi_match_table = spi_nor_acpi_table, }, .id_table = spi_nor_dev_ids, }, diff --git a/drivers/spi/spi-phytium-qspi.c b/drivers/spi/spi-phytium-qspi.c index 4022d565a9..56525be797 100644 --- a/drivers/spi/spi-phytium-qspi.c +++ b/drivers/spi/spi-phytium-qspi.c @@ -5,7 +5,6 @@ * Copyright (c) 2022-2023, Phytium Technology Co., Ltd. */ -#include #include #include #include @@ -15,7 +14,6 @@ #include #include #include -#include #include #include @@ -621,7 +619,6 @@ static int phytium_qspi_probe(struct platform_device *pdev) int i, ret; struct spi_mem *mem; struct spi_nor *nor; - const char **reg_name_array; ctrl = spi_alloc_master(dev, sizeof(*qspi)); if (!ctrl) @@ -632,36 +629,19 @@ static int phytium_qspi_probe(struct platform_device *pdev) SPI_TX_DUAL | SPI_TX_QUAD; ctrl->setup = phytium_qspi_setup; ctrl->num_chipselect = PHYTIUM_QSPI_MAX_NORCHIP; - if (IS_ENABLED(CONFIG_OF)) - ctrl->dev.of_node = dev->of_node; - else if (IS_ENABLED(CONFIG_ACPI) && has_acpi_companion(dev)) - ctrl->dev.fwnode = dev->fwnode; + ctrl->dev.of_node = dev->of_node; qspi = spi_controller_get_devdata(ctrl); qspi->ctrl = ctrl; - reg_name_array = kcalloc(4, sizeof(*reg_name_array), GFP_KERNEL); - if (dev->of_node) - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi"); - else if (has_acpi_companion(dev)) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - fwnode_property_read_string_array(dev->fwnode, - "reg-names", reg_name_array, 2); - res->name = reg_name_array[0]; - } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi"); qspi->io_base = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->io_base)) { ret = PTR_ERR(qspi->io_base); goto probe_master_put; } - if (dev->of_node) - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm"); - else if (has_acpi_companion(dev)) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - res->name = reg_name_array[1]; - } - + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm"); qspi->mm_base = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->mm_base)) { ret = PTR_ERR(qspi->mm_base); @@ -675,34 +655,31 @@ static int phytium_qspi_probe(struct platform_device *pdev) } qspi->used_size = 0; - if (dev->of_node) { - qspi->clk = devm_clk_get(dev, NULL); - if (IS_ERR(qspi->clk)) { - ret = PTR_ERR(qspi->clk); - goto probe_master_put; - } + qspi->clk = devm_clk_get(dev, NULL); + if (IS_ERR(qspi->clk)) { + ret = PTR_ERR(qspi->clk); + goto probe_master_put; + } - qspi->clk_rate = clk_get_rate(qspi->clk); - if (!qspi->clk_rate) { - ret = -EINVAL; - goto probe_master_put; - } + qspi->clk_rate = clk_get_rate(qspi->clk); + if (!qspi->clk_rate) { + ret = -EINVAL; + goto probe_master_put; + } - pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); - goto probe_master_put; - } + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + goto probe_master_put; + } - ret = clk_prepare_enable(qspi->clk); - if (ret) { - dev_err(dev, "Failed to enable PCLK of the controller.\n"); - goto probe_clk_failed; - } - } else if (has_acpi_companion(dev)) { - qspi->clk_rate = 50000000; + ret = clk_prepare_enable(qspi->clk); + if (ret) { + dev_err(dev, "Failed to enable PCLK of the controller.\n"); + goto probe_clk_failed; } + qspi->nodirmap = device_property_present(dev, "no-direct-mapping"); ctrl->mem_ops = qspi->nodirmap ? &phytium_qspi_mem_ops_nodirmap : @@ -819,12 +796,7 @@ static const struct of_device_id phytium_qspi_of_match[] = { { .compatible = "phytium,qspi-nor" }, { } }; -static const struct acpi_device_id phytium_qspi_acpi_match[] = { - { "PHYT0011", 0 }, - { } -}; MODULE_DEVICE_TABLE(of, phytium_qspi_of_match); -MODULE_DEVICE_TABLE(acpi, phytium_qspi_acpi_match); static struct platform_driver phytium_qspi_driver = { .probe = phytium_qspi_probe, @@ -832,7 +804,6 @@ static struct platform_driver phytium_qspi_driver = { .driver = { .name = "phytium-qspi", .of_match_table = of_match_ptr(phytium_qspi_of_match), - .acpi_match_table = ACPI_PTR(phytium_qspi_acpi_match), .pm = &phytium_qspi_pm_ops, }, }; diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 73f16747d9..b74a539ec5 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -51,7 +51,6 @@ struct mtd_partition { uint32_t mask_flags; /* master MTD flags to mask out for this partition */ uint32_t add_flags; /* flags to add to the partition */ struct device_node *of_node; - struct fwnode_handle *fwnode; }; #define MTDPART_OFS_RETAIN (-3) @@ -62,8 +61,6 @@ struct mtd_partition { struct mtd_info; struct device_node; -struct acpi_device; -struct hwnode_handle; /** * struct mtd_part_parser_data - used to pass data to MTD partition parsers. @@ -83,7 +80,6 @@ struct mtd_part_parser { struct module *owner; const char *name; const struct of_device_id *of_match_table; - const struct acpi_device_id *acpi_match_table; int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, struct mtd_part_parser_data *); void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); -- Gitee From 322b7edaa83ded0cb6fa09c3b11f0a5c5534ae24 Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Fri, 7 Feb 2025 15:24:09 +0800 Subject: [PATCH 064/121] Revert "Revert "UEFI mode acpi table support for qspi/spi driver"" This reverts commit 08d701b13dbe316e68e6651cbac63add9509a5d7. --- MAINTAINERS | 1 + drivers/mtd/mtdcore.c | 9 +- drivers/mtd/mtdpart.c | 55 ++++++++++- drivers/mtd/parsers/Kconfig | 9 ++ drivers/mtd/parsers/Makefile | 2 + drivers/mtd/parsers/acpipart_core.c | 143 ++++++++++++++++++++++++++++ drivers/mtd/spi-nor/core.c | 13 +++ drivers/spi/spi-phytium-qspi.c | 77 ++++++++++----- include/linux/mtd/partitions.h | 4 + 9 files changed, 282 insertions(+), 31 deletions(-) create mode 100644 drivers/mtd/parsers/acpipart_core.c diff --git a/MAINTAINERS b/MAINTAINERS index 27a3ed1e46..d265d1a06c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17487,6 +17487,7 @@ F: drivers/mfd/phytium_px210_i2s_mmd.c F: drivers/mmc/host/phytium-mci* F: drivers/mmc/host/phytium-sdci.* F: drivers/mtd/nand/raw/phytium_nand* +F: drivers/mtd/parsers/acpipart_core.c F: drivers/net/can/phytium/* F: drivers/net/ethernet/Kconfig F: drivers/net/ethernet/Makefile diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 97ca2a897f..c5a59c4881 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -743,7 +743,8 @@ int add_mtd_device(struct mtd_info *mtd) dev_set_name(&mtd->dev, "mtd%d", i); dev_set_drvdata(&mtd->dev, mtd); mtd_check_of_node(mtd); - of_node_get(mtd_get_of_node(mtd)); + if (mtd->dev.of_node) + of_node_get(mtd_get_of_node(mtd)); error = device_register(&mtd->dev); if (error) { put_device(&mtd->dev); @@ -905,7 +906,8 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, config.ignore_wp = true; config.reg_read = reg_read; config.size = size; - config.of_node = np; + if (IS_ENABLED(CONFIG_OF)) + config.of_node = np; config.priv = mtd; nvmem = nvmem_register(&config); @@ -913,7 +915,8 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, if (IS_ERR(nvmem) && PTR_ERR(nvmem) == -EOPNOTSUPP) nvmem = NULL; - of_node_put(np); + if (IS_ENABLED(CONFIG_OF)) + of_node_put(np); return nvmem; } diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 23483db8f3..3cda38902b 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -19,6 +19,8 @@ #include #include +#include +#include #include "mtdcore.h" /* @@ -504,12 +506,14 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser); static const char * const default_mtd_part_types[] = { "cmdlinepart", "ofpart", + "acpipart", NULL }; /* Check DT only when looking for subpartitions. */ static const char * const default_subpartition_types[] = { "ofpart", + "acpipart", NULL }; @@ -573,6 +577,45 @@ static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat return ret; } +static int mtd_part_acpi_parse(struct mtd_info *master, + struct mtd_partitions *pparts) +{ + struct mtd_part_parser *parser; + struct acpi_device *adev; + struct fwnode_handle *child; + const char *compat; + const char *fixed = "acpi-fixed-partitions"; + int ret, err = 0; + int compare = 1; + struct device *dev = &master->dev; + + if (has_acpi_companion(dev)) + adev = ACPI_COMPANION(dev); + if (!mtd_is_partition(master)) { + fwnode_property_read_string(dev->fwnode, "fixed", &compat); + if (compat) + compare = strcmp(compat, fixed); + } + + //all child node + device_for_each_child_node(dev, child) { + if (compat && !compare) { + parser = mtd_part_parser_get(fixed); + if (!parser && !request_module("%s", fixed)) + parser = mtd_part_parser_get(fixed); + if (parser) { + ret = mtd_part_do_parse(parser, master, pparts, NULL); + if (ret > 0) + return ret; + mtd_part_parser_put(parser); + if (ret < 0 && !err) + err = ret; + } + } + } + return err; +} + static int mtd_part_of_parse(struct mtd_info *master, struct mtd_partitions *pparts) { @@ -591,7 +634,7 @@ static int mtd_part_of_parse(struct mtd_info *master, dev = master->dev.parent; np = mtd_get_of_node(master); - if (mtd_is_partition(master)) + if (mtd_is_partition(master) && np) of_node_get(np); else np = of_get_child_by_name(np, "partitions"); @@ -612,7 +655,8 @@ static int mtd_part_of_parse(struct mtd_info *master, ret = mtd_part_do_parse(parser, master, pparts, NULL); if (ret > 0) { of_platform_populate(np, NULL, NULL, dev); - of_node_put(np); + if (np) + of_node_put(np); return ret; } mtd_part_parser_put(parser); @@ -620,7 +664,8 @@ static int mtd_part_of_parse(struct mtd_info *master, err = ret; } of_platform_populate(np, NULL, NULL, dev); - of_node_put(np); + if (np) + of_node_put(np); /* * For backward compatibility we have to try the "fixed-partitions" @@ -678,7 +723,9 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types, * should be used. It requires a bit different logic so it is * handled in a separated function. */ - if (!strcmp(*types, "ofpart")) { + if (!strcmp(*types, "acpipart")) { + ret = mtd_part_acpi_parse(master, &pparts); + } else if (!strcmp(*types, "ofpart")) { ret = mtd_part_of_parse(master, &pparts); } else { pr_debug("%s: parsing partitions %s\n", master->name, diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index 60738edcd5..ae1870d271 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -96,6 +96,15 @@ config MTD_OF_PARTS_LINKSYS_NS two "firmware" partitions. Currently used firmware has to be detected using CFE environment variable. +config MTD_ACPI_PARTS + tristate "ACPI partitioning parser" + default y + depends on ACPI + help + This provides an acpi partition parser, which is used to parse the + partition map described in ACPI table, as the children of the flash + memory struct. + config MTD_PARSER_IMAGETAG tristate "Parser for BCM963XX Image Tag format partitions" depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile index 0e70b621a1..2679fd7668 100644 --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile @@ -8,6 +8,8 @@ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o ofpart-y += ofpart_core.o ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o +obj-$(CONFIG_MTD_ACPI_PARTS) += acpipart.o +acpipart-y += acpipart_core.o obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o obj-$(CONFIG_MTD_AFS_PARTS) += afs.o obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o diff --git a/drivers/mtd/parsers/acpipart_core.c b/drivers/mtd/parsers/acpipart_core.c new file mode 100644 index 0000000000..4ed29fc5e4 --- /dev/null +++ b/drivers/mtd/parsers/acpipart_core.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Flash partitions described by the acpi table + * + * Author: Wang Hanmo + */ + +#include +#include +#include +#include +#include +#include +#include + +static const struct acpi_device_id parse_acpipart_match_table[]; + +static int parse_acpi_fixed_partitions(struct mtd_info *master, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct mtd_partition *parts; + struct acpi_device_id *acpi_id; + const char *partname; + int nr_parts, i, ret = 0; + struct acpi_device *adev; + struct fwnode_handle *child; + struct fwnode_handle *child_handle; + bool dedicated = true; + struct device *dev; + + dev = &master->dev; + adev = ACPI_COMPANION(&master->dev); + + if (!master->parent) {/*master*/ + device_get_next_child_node(dev, child_handle); + if (!child_handle) { + pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n", + master->name, child_handle); + dedicated = false; + } + } + + acpi_id = acpi_match_device(parse_acpipart_match_table, dev); + if (dedicated && !acpi_id) + return 0; + + nr_parts = 0; + device_for_each_child_node(dev, child_handle) { + nr_parts++; + } + + if (nr_parts == 0) + return 0; + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + + i = 0; + device_for_each_child_node(dev, child_handle) { + u64 offset, length; + bool bool_match; + + fwnode_property_read_u64(child_handle, "offset", &offset); + fwnode_property_read_u64(child_handle, "length", &length); + if (!offset && !length) { + if (dedicated) { + pr_debug("%s: acpipart partition %pOF (%pOF) missing reg property.\n", + master->name, child_handle, + dev->fwnode); + goto acpipart_fail; + } else { + nr_parts--; + continue; + } + } + + parts[i].offset = offset; + parts[i].size = length; + parts[i].fwnode = child_handle; + if (!fwnode_property_read_string(child_handle, "label", &partname)) + parts[i].name = partname; + bool_match = fwnode_property_read_bool(child_handle, "read-only"); + if (bool_match) + parts[i].mask_flags |= MTD_WRITEABLE; + bool_match = fwnode_property_read_bool(child_handle, "lock"); + if (bool_match) + parts[i].mask_flags |= MTD_POWERUP_LOCK; + bool_match = fwnode_property_read_bool(child_handle, "slc-mode"); + if (bool_match) + parts[i].mask_flags |= MTD_SLC_ON_MLC_EMULATION; + i++; + } + + if (!nr_parts) + goto acpipart_none; + + *pparts = parts; + ret = nr_parts; + return ret; + +acpipart_fail: + pr_err("%s: error parsing acpipart partition %pOF (%pOF)\n", + master->name, child_handle, dev->fwnode); + ret = -EINVAL; +acpipart_none: + kfree(parts); + return ret; +} + +static const struct acpi_device_id parse_acpipart_match_table[] = { + /* Generic */ + { "acpi-fixed-partitions", 0 }, + /* Customized */ + {}, +}; + +MODULE_DEVICE_TABLE(acpi, parse_acpipart_match_table); + +static struct mtd_part_parser acpipart_parser = { + .parse_fn = parse_acpi_fixed_partitions, + .name = "acpi-fixed-partitions", + .acpi_match_table = ACPI_PTR(parse_acpipart_match_table), +}; + +static int __init acpipart_parser_init(void) +{ + register_mtd_parser(&acpipart_parser); + return 0; +} + +static void __exit acpipart_parser_exit(void) +{ + deregister_mtd_parser(&acpipart_parser); +} + +module_init(acpipart_parser_init); +module_exit(acpipart_parser_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Parser for MTD partitioning information in acpi table"); +MODULE_AUTHOR("wanghanmo "); +MODULE_ALIAS("acpi-fixed-partitions"); diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 249258342e..0810e27d98 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -7,6 +7,7 @@ * Copyright (C) 2014, Freescale Semiconductor, Inc. */ +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -3622,6 +3624,7 @@ static int spi_nor_probe(struct spi_mem *spimem) struct spi_device *spi = spimem->spi; struct flash_platform_data *data = dev_get_platdata(&spi->dev); struct spi_nor *nor; + struct acpi_device *adev; /* * Enable all caps by default. The core will mask them after * checking what's really supported using spi_mem_supports_op(). @@ -3637,6 +3640,10 @@ static int spi_nor_probe(struct spi_mem *spimem) nor->spimem = spimem; nor->dev = &spi->dev; spi_nor_set_flash_node(nor, spi->dev.of_node); + adev = ACPI_COMPANION(nor->dev); + nor->mtd.dev.fwnode = spi->dev.fwnode; + + device_property_read_string(&spi->dev, "_HID", &nor->mtd.name); spi_mem_set_drvdata(spimem, nor); @@ -3776,6 +3783,11 @@ static const struct of_device_id spi_nor_of_table[] = { }; MODULE_DEVICE_TABLE(of, spi_nor_of_table); +static const struct acpi_device_id spi_nor_acpi_table[] = { + {"PHYT8009", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, spi_nor_acpi_table); /* * REVISIT: many of these chips have deep power-down modes, which * should clearly be entered on suspend() to minimize power use. @@ -3787,6 +3799,7 @@ static struct spi_mem_driver spi_nor_driver = { .name = "spi-nor", .of_match_table = spi_nor_of_table, .dev_groups = spi_nor_sysfs_groups, + .acpi_match_table = spi_nor_acpi_table, }, .id_table = spi_nor_dev_ids, }, diff --git a/drivers/spi/spi-phytium-qspi.c b/drivers/spi/spi-phytium-qspi.c index 56525be797..4022d565a9 100644 --- a/drivers/spi/spi-phytium-qspi.c +++ b/drivers/spi/spi-phytium-qspi.c @@ -5,6 +5,7 @@ * Copyright (c) 2022-2023, Phytium Technology Co., Ltd. */ +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include @@ -619,6 +621,7 @@ static int phytium_qspi_probe(struct platform_device *pdev) int i, ret; struct spi_mem *mem; struct spi_nor *nor; + const char **reg_name_array; ctrl = spi_alloc_master(dev, sizeof(*qspi)); if (!ctrl) @@ -629,19 +632,36 @@ static int phytium_qspi_probe(struct platform_device *pdev) SPI_TX_DUAL | SPI_TX_QUAD; ctrl->setup = phytium_qspi_setup; ctrl->num_chipselect = PHYTIUM_QSPI_MAX_NORCHIP; - ctrl->dev.of_node = dev->of_node; + if (IS_ENABLED(CONFIG_OF)) + ctrl->dev.of_node = dev->of_node; + else if (IS_ENABLED(CONFIG_ACPI) && has_acpi_companion(dev)) + ctrl->dev.fwnode = dev->fwnode; qspi = spi_controller_get_devdata(ctrl); qspi->ctrl = ctrl; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi"); + reg_name_array = kcalloc(4, sizeof(*reg_name_array), GFP_KERNEL); + if (dev->of_node) + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi"); + else if (has_acpi_companion(dev)) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + fwnode_property_read_string_array(dev->fwnode, + "reg-names", reg_name_array, 2); + res->name = reg_name_array[0]; + } qspi->io_base = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->io_base)) { ret = PTR_ERR(qspi->io_base); goto probe_master_put; } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm"); + if (dev->of_node) + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm"); + else if (has_acpi_companion(dev)) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + res->name = reg_name_array[1]; + } + qspi->mm_base = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->mm_base)) { ret = PTR_ERR(qspi->mm_base); @@ -655,31 +675,34 @@ static int phytium_qspi_probe(struct platform_device *pdev) } qspi->used_size = 0; - qspi->clk = devm_clk_get(dev, NULL); - if (IS_ERR(qspi->clk)) { - ret = PTR_ERR(qspi->clk); - goto probe_master_put; - } + if (dev->of_node) { + qspi->clk = devm_clk_get(dev, NULL); + if (IS_ERR(qspi->clk)) { + ret = PTR_ERR(qspi->clk); + goto probe_master_put; + } - qspi->clk_rate = clk_get_rate(qspi->clk); - if (!qspi->clk_rate) { - ret = -EINVAL; - goto probe_master_put; - } + qspi->clk_rate = clk_get_rate(qspi->clk); + if (!qspi->clk_rate) { + ret = -EINVAL; + goto probe_master_put; + } - pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); - goto probe_master_put; - } + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + goto probe_master_put; + } - ret = clk_prepare_enable(qspi->clk); - if (ret) { - dev_err(dev, "Failed to enable PCLK of the controller.\n"); - goto probe_clk_failed; + ret = clk_prepare_enable(qspi->clk); + if (ret) { + dev_err(dev, "Failed to enable PCLK of the controller.\n"); + goto probe_clk_failed; + } + } else if (has_acpi_companion(dev)) { + qspi->clk_rate = 50000000; } - qspi->nodirmap = device_property_present(dev, "no-direct-mapping"); ctrl->mem_ops = qspi->nodirmap ? &phytium_qspi_mem_ops_nodirmap : @@ -796,7 +819,12 @@ static const struct of_device_id phytium_qspi_of_match[] = { { .compatible = "phytium,qspi-nor" }, { } }; +static const struct acpi_device_id phytium_qspi_acpi_match[] = { + { "PHYT0011", 0 }, + { } +}; MODULE_DEVICE_TABLE(of, phytium_qspi_of_match); +MODULE_DEVICE_TABLE(acpi, phytium_qspi_acpi_match); static struct platform_driver phytium_qspi_driver = { .probe = phytium_qspi_probe, @@ -804,6 +832,7 @@ static struct platform_driver phytium_qspi_driver = { .driver = { .name = "phytium-qspi", .of_match_table = of_match_ptr(phytium_qspi_of_match), + .acpi_match_table = ACPI_PTR(phytium_qspi_acpi_match), .pm = &phytium_qspi_pm_ops, }, }; diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index b74a539ec5..73f16747d9 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -51,6 +51,7 @@ struct mtd_partition { uint32_t mask_flags; /* master MTD flags to mask out for this partition */ uint32_t add_flags; /* flags to add to the partition */ struct device_node *of_node; + struct fwnode_handle *fwnode; }; #define MTDPART_OFS_RETAIN (-3) @@ -61,6 +62,8 @@ struct mtd_partition { struct mtd_info; struct device_node; +struct acpi_device; +struct hwnode_handle; /** * struct mtd_part_parser_data - used to pass data to MTD partition parsers. @@ -80,6 +83,7 @@ struct mtd_part_parser { struct module *owner; const char *name; const struct of_device_id *of_match_table; + const struct acpi_device_id *acpi_match_table; int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, struct mtd_part_parser_data *); void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); -- Gitee From 1ef993b5313e1ce69a6f4c66718814b7208ef69e Mon Sep 17 00:00:00 2001 From: Wang Hanmo Date: Tue, 11 Jun 2024 11:18:55 +0800 Subject: [PATCH 065/121] mtd: phytium: Fix issues with standard descriptions Some descriptions in the driver do not comply with the ACPI spec. This patch modifies the problematic string and solves the non-compliance with the ACPI spec problem. Mainline: NA Signed-off-by: Wang Hanmo Signed-off-by: Wang Yinfeng Change-Id: I91d350627b060034d1fc90cc15d7e9bc74d2bbc7 --- drivers/mtd/mtdpart.c | 4 ++-- drivers/mtd/parsers/acpipart_core.c | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 3cda38902b..2dc8e4ca42 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -583,8 +583,8 @@ static int mtd_part_acpi_parse(struct mtd_info *master, struct mtd_part_parser *parser; struct acpi_device *adev; struct fwnode_handle *child; - const char *compat; - const char *fixed = "acpi-fixed-partitions"; + const char *compat = ""; + const char *fixed = "acpi-partitions"; int ret, err = 0; int compare = 1; struct device *dev = &master->dev; diff --git a/drivers/mtd/parsers/acpipart_core.c b/drivers/mtd/parsers/acpipart_core.c index 4ed29fc5e4..06060738a3 100644 --- a/drivers/mtd/parsers/acpipart_core.c +++ b/drivers/mtd/parsers/acpipart_core.c @@ -20,11 +20,10 @@ static int parse_acpi_fixed_partitions(struct mtd_info *master, struct mtd_part_parser_data *data) { struct mtd_partition *parts; - struct acpi_device_id *acpi_id; + const struct acpi_device_id *acpi_id; const char *partname; int nr_parts, i, ret = 0; struct acpi_device *adev; - struct fwnode_handle *child; struct fwnode_handle *child_handle; bool dedicated = true; struct device *dev; @@ -110,7 +109,7 @@ static int parse_acpi_fixed_partitions(struct mtd_info *master, static const struct acpi_device_id parse_acpipart_match_table[] = { /* Generic */ - { "acpi-fixed-partitions", 0 }, + { "acpi-partitions", 0 }, /* Customized */ {}, }; @@ -119,7 +118,7 @@ MODULE_DEVICE_TABLE(acpi, parse_acpipart_match_table); static struct mtd_part_parser acpipart_parser = { .parse_fn = parse_acpi_fixed_partitions, - .name = "acpi-fixed-partitions", + .name = "acpi-partitions", .acpi_match_table = ACPI_PTR(parse_acpipart_match_table), }; @@ -139,5 +138,5 @@ module_exit(acpipart_parser_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Parser for MTD partitioning information in acpi table"); -MODULE_AUTHOR("wanghanmo "); -MODULE_ALIAS("acpi-fixed-partitions"); +MODULE_AUTHOR("Wang Hanmo "); +MODULE_ALIAS("acpi-partitions"); -- Gitee From b14950c6a973c0890aac737d72abefd69ae8e6f3 Mon Sep 17 00:00:00 2001 From: Yuquan Wang Date: Mon, 23 Sep 2024 18:17:04 +0800 Subject: [PATCH 066/121] mtd: phytium: Add uefi support for flash memory This patch adds support for flash memory using CFI standard interface in UEFI mode. Mainline: NA Signed-off-by: Yuquan Wang Signed-off-by: Wang Yinfeng Change-Id: I014c9d80dc55f615ad775abf2ad823095077ced6 --- drivers/mtd/maps/Kconfig | 9 +++++++++ drivers/mtd/maps/physmap-core.c | 31 +++++++++++++++++++++++++++++-- include/linux/mtd/mtd.h | 6 ++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index e098ae937c..e910b432f7 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -75,6 +75,15 @@ config MTD_PHYSMAP_OF physically into the CPU's memory. The mapping description here is taken from OF device tree. +config MTD_PHYSMAP_ACPI + bool "Memory device in physical memory map based on ACPI description" + depends on MTD_PHYSMAP + help + This provides a 'mapping' driver which allows the NOR Flash, ROM + and RAM driver code to communicate with chips which are mapped + physically into the CPU's memory. The mapping description here is + taken from ACPI table. + config MTD_PHYSMAP_BT1_ROM bool "Baikal-T1 Boot ROMs OF-based physical memory map handling" depends on MTD_PHYSMAP_OF diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index 9be71b045b..4ceff03d3b 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "physmap-bt1-rom.h" #include "physmap-gemini.h" @@ -409,12 +410,22 @@ static int physmap_flash_of_init(struct platform_device *dev) } #endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */ +#if IS_ENABLED(CONFIG_MTD_PHYSMAP_ACPI) +static const struct acpi_device_id physmap_flash_ids[] = { + { "ACPI0018" }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, physmap_flash_ids); +#else /* IS_ENABLED(CONFIG_MTD_PHYSMAP_ACPI) */ +#define physmap_flash_ids NULL +#endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_ACPI) */ + static const char * const rom_probe_types[] = { "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", }; static const char * const part_probe_types[] = { - "cmdlinepart", "RedBoot", "afs", NULL + "cmdlinepart", "RedBoot", "afs", "acpipart", NULL }; static int physmap_flash_pdata_init(struct platform_device *dev) @@ -424,6 +435,18 @@ static int physmap_flash_pdata_init(struct platform_device *dev) unsigned int i; int err; +#ifdef CONFIG_MTD_PHYSMAP_ACPI + u32 bankwidth; + + fwnode_property_read_u32(dev->dev.fwnode, "bank-width", &bankwidth); + + struct physmap_flash_data acpi_data = { + .width = bankwidth, + }; + + dev->dev.platform_data = &acpi_data; +#endif + physmap_data = dev_get_platdata(&dev->dev); if (!physmap_data) return -EINVAL; @@ -454,7 +477,7 @@ static int physmap_flash_probe(struct platform_device *dev) int err = 0; int i; - if (!dev->dev.of_node && !dev_get_platdata(&dev->dev)) + if (!dev->dev.of_node && !dev->dev.fwnode && !dev_get_platdata(&dev->dev)) return -EINVAL; info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); @@ -598,6 +621,9 @@ static int physmap_flash_probe(struct platform_device *dev) spin_lock_init(&info->vpp_lock); mtd_set_of_node(info->cmtd, dev->dev.of_node); + + mtd_set_fwnode(info->cmtd, dev->dev.fwnode); + err = mtd_device_parse_register(info->cmtd, info->part_types, NULL, info->parts, info->nparts); if (err) @@ -631,6 +657,7 @@ static struct platform_driver physmap_flash_driver = { .driver = { .name = "physmap-flash", .of_match_table = of_flash_match, + .acpi_match_table = physmap_flash_ids, }, }; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 914a9f974b..a22816384a 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -458,6 +458,12 @@ static inline void mtd_set_pairing_scheme(struct mtd_info *mtd, mtd->pairing = pairing; } +static inline void mtd_set_fwnode(struct mtd_info *mtd, + struct fwnode_handle *fwnode) +{ + mtd->dev.fwnode = fwnode; +} + static inline void mtd_set_of_node(struct mtd_info *mtd, struct device_node *np) { -- Gitee From 818d13ae669bb150a00e5af60eb4342f622ffe6e Mon Sep 17 00:00:00 2001 From: Peng Min Date: Thu, 28 Nov 2024 15:28:21 +0800 Subject: [PATCH 067/121] spi: phytium: Dynamically get the clock in the ACPI table Originally, the SPI driver wrote the controller clock as a fixed value, but now it is modified to obtain dynamiclly. Mainline: Open-Source Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng Change-Id: I6d6c350437bd7c544418c31ba40f4aa47d0ee3f5 --- drivers/spi/spi-phytium-plat.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-phytium-plat.c b/drivers/spi/spi-phytium-plat.c index 01101e501a..178bd90dc1 100644 --- a/drivers/spi/spi-phytium-plat.c +++ b/drivers/spi/spi-phytium-plat.c @@ -31,6 +31,8 @@ #define DRIVER_NAME "phytium_spi" #define DRIVER_VERSION "1.0.0" +#define SPI_PHYTIUM_DEFAULT_CLK_RATE 50000000 + struct phytium_spi_clk { struct phytium_spi fts; struct clk *clk; @@ -38,12 +40,14 @@ struct phytium_spi_clk { static int phytium_spi_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct phytium_spi_clk *ftsc; struct phytium_spi *fts; struct resource *mem; int ret; int num_cs; - int global_cs; + int global_cs = 0; + u32 clk_rate = SPI_PHYTIUM_DEFAULT_CLK_RATE; ftsc = devm_kzalloc(&pdev->dev, sizeof(struct phytium_spi_clk), GFP_KERNEL); @@ -82,7 +86,8 @@ static int phytium_spi_probe(struct platform_device *pdev) fts->max_freq = clk_get_rate(ftsc->clk); } else if (has_acpi_companion(&pdev->dev)) { - fts->max_freq = 48000000; + fwnode_property_read_u32(dev->fwnode, "spi-clock", &clk_rate); + fts->max_freq = clk_rate; } fts->bus_num = pdev->id; -- Gitee From f0a2cae0be1e71a55b721f4790e4ae51fc972366 Mon Sep 17 00:00:00 2001 From: Peng Min Date: Tue, 16 Jul 2024 15:13:04 +0800 Subject: [PATCH 068/121] spi-nor: core: Add 1-4-4 mode to SPI flash driver The original driver supports only 1-1-4 mode. This patch adds 1-4-4 mode to SPI flash driver. You can set 1-4-4 mode by adding a new description to the devicetree. Mainline: Open-Source Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng Change-Id: I4581e84fcf710868eb3f4591294a2afb7b0ac96c --- drivers/mtd/spi-nor/core.c | 4 +++ drivers/spi/spi-mem.c | 19 ++++++++++ drivers/spi/spi.c | 73 ++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 2 ++ 4 files changed, 98 insertions(+) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 0810e27d98..fcca6ce65f 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2791,6 +2791,10 @@ static void spi_nor_no_sfdp_init_params(struct spi_nor *nor) spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_4], 0, 8, SPINOR_OP_READ_1_1_4, SNOR_PROTO_1_1_4); + params->hwcaps.mask |= SNOR_HWCAPS_READ_1_4_4; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_4_4], + 0, 8, SPINOR_OP_READ_1_4_4, + SNOR_PROTO_1_4_4); } if (no_sfdp_flags & SPI_NOR_OCTAL_READ) { diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index edd7430d4c..6e33632f8e 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "internals.h" @@ -142,6 +143,24 @@ static int spi_check_buswidth_req(struct spi_mem *mem, u8 buswidth, bool tx) static bool spi_mem_check_buswidth(struct spi_mem *mem, const struct spi_mem_op *op) { + u32 proto; + + if (op->data.dir == SPI_MEM_DATA_OUT) + proto = mem->spi->tx_proto; + else if (op->data.dir == SPI_MEM_DATA_IN) + proto = mem->spi->rx_proto; + + if (op->data.dir != SPI_MEM_NO_DATA) { + if (op->cmd.buswidth > spi_nor_get_protocol_inst_nbits(proto)) + return false; + if (op->addr.buswidth > spi_nor_get_protocol_addr_nbits(proto)) + return false; + if (op->dummy.buswidth > spi_nor_get_protocol_addr_nbits(proto)) + return false; + if (op->data.buswidth > spi_nor_get_protocol_data_nbits(proto)) + return false; + } + if (spi_check_buswidth_req(mem, op->cmd.buswidth, true)) return false; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5c57c7378e..74c2ea9b81 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #define CREATE_TRACE_POINTS @@ -2320,6 +2321,18 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, if (!of_property_read_u32(nc, "spi-max-frequency", &value)) spi->max_speed_hz = value; + if (!of_property_read_u32(nc, "spi-rx-proto", &value)) + spi->rx_proto = value; + if (!of_property_read_u32(nc, "spi-tx-proto", &value)) + spi->tx_proto = value; + + if (spi->rx_proto != SNOR_PROTO_1_1_4 && + spi->rx_proto != SNOR_PROTO_1_4_4 && + spi->rx_proto != SNOR_PROTO_1_1_2) + spi->rx_proto = SNOR_PROTO_1_1_1; + if (spi->tx_proto != SNOR_PROTO_1_1_4) + spi->tx_proto = SNOR_PROTO_1_1_1; + /* Device CS delays */ of_spi_parse_dt_cs_delay(nc, &spi->cs_setup, "spi-cs-setup-delay-ns"); of_spi_parse_dt_cs_delay(nc, &spi->cs_hold, "spi-cs-hold-delay-ns"); @@ -2640,6 +2653,8 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, struct acpi_spi_lookup lookup = {}; struct spi_device *spi; int ret; + int rx_val = 1, tx_val = 1; + int rx_proto = 1, tx_proto = 1; if (!ctlr && index == -1) return ERR_PTR(-EINVAL); @@ -2654,6 +2669,52 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, acpi_spi_add_resource, &lookup); acpi_dev_free_resource_list(&resource_list); + if (!fwnode_property_read_u32(&adev->fwnode, "spi-tx-bus-width", &tx_val)) { + switch (tx_val) { + case 0: + lookup.mode |= SPI_NO_TX; + break; + case 1: + break; + case 2: + lookup.mode |= SPI_TX_DUAL; + break; + case 4: + lookup.mode |= SPI_TX_QUAD; + break; + case 8: + lookup.mode |= SPI_TX_OCTAL; + break; + default: + dev_warn(&lookup.ctlr->dev, "spi-tx-bus-width %d not supported\n", tx_val); + break; + } + } + if (!fwnode_property_read_u32(&adev->fwnode, "spi-rx-bus-width", &rx_val)) { + switch (rx_val) { + case 0: + lookup.mode |= SPI_NO_RX; + break; + case 1: + break; + case 2: + lookup.mode |= SPI_RX_DUAL; + break; + case 4: + lookup.mode |= SPI_RX_QUAD; + break; + case 8: + lookup.mode |= SPI_RX_OCTAL; + break; + default: + dev_warn(&lookup.ctlr->dev, "spi-rx-bus-width %d not supported\n", rx_val); + break; + } + } + + fwnode_property_read_u32(&adev->fwnode, "spi-rx-proto", &rx_proto); + fwnode_property_read_u32(&adev->fwnode, "spi-tx-proto", &tx_proto); + if (ret < 0) /* Found SPI in _CRS but it points to another controller */ return ERR_PTR(ret); @@ -2682,6 +2743,18 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, spi->bits_per_word = lookup.bits_per_word; spi_set_chipselect(spi, 0, lookup.chip_select); + if (rx_proto) + spi->rx_proto = rx_proto; + if (tx_proto) + spi->tx_proto = tx_proto; + + if (spi->rx_proto != SNOR_PROTO_1_1_4 && + spi->rx_proto != SNOR_PROTO_1_4_4 && + spi->rx_proto != SNOR_PROTO_1_1_2) + spi->rx_proto = SNOR_PROTO_1_1_1; + if (spi->tx_proto != SNOR_PROTO_1_1_4) + spi->tx_proto = SNOR_PROTO_1_1_1; + return spi; } EXPORT_SYMBOL_GPL(acpi_spi_device_alloc); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index e5baf43bcf..5a3bbe3194 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -208,6 +208,8 @@ struct spi_device { */ #define SPI_MODE_KERNEL_MASK (~(BIT(29) - 1)) u32 mode; + u32 rx_proto; + u32 tx_proto; int irq; void *controller_state; void *controller_data; -- Gitee From 9a11141378c96b015f3ad6710f3d7ae057f2a7ec Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 20 May 2024 16:30:12 +0800 Subject: [PATCH 069/121] gpio: phytium: Set value first when setting output direction This patch sets the output value firstly when setting output direction to avoid brief low-level interference timing sequence. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: Ia56c1a276b5a70348baf6c793dd3613217a5fd9b --- drivers/gpio/gpio-phytium-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-phytium-core.c b/drivers/gpio/gpio-phytium-core.c index 8ea7cafc4c..3fa75b8567 100644 --- a/drivers/gpio/gpio-phytium-core.c +++ b/drivers/gpio/gpio-phytium-core.c @@ -129,14 +129,13 @@ int phytium_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, return -EINVAL; ddr = gpio->regs + GPIO_SWPORTA_DDR + (loc.port * GPIO_PORT_STRIDE); + phytium_gpio_set(gc, offset, value); raw_spin_lock_irqsave(&gpio->lock, flags); writel(readl(ddr) | BIT(loc.offset), ddr); raw_spin_unlock_irqrestore(&gpio->lock, flags); - phytium_gpio_set(gc, offset, value); - return 0; } EXPORT_SYMBOL_GPL(phytium_gpio_direction_output); -- Gitee From c8fdcf0480710752aafca786ced4a7b049772ee1 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Tue, 10 Sep 2024 17:31:38 +0800 Subject: [PATCH 070/121] gpio: phytium: Optimize the logic of suspend and resume This patch disables interrupts when gpio suspends and recoveries interrupts at the end of resume. Add the function of suspend flag to prevent other processes from resuming interrupts in advance. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: Ie106ce6a54dba7c5df827cdb37e9f605d1c88e00 --- drivers/gpio/gpio-phytium-core.c | 2 ++ drivers/gpio/gpio-phytium-core.h | 1 + drivers/gpio/gpio-phytium-pci.c | 7 ++++++- drivers/gpio/gpio-phytium-platform.c | 7 ++++++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-phytium-core.c b/drivers/gpio/gpio-phytium-core.c index 3fa75b8567..aa8bd196ce 100644 --- a/drivers/gpio/gpio-phytium-core.c +++ b/drivers/gpio/gpio-phytium-core.c @@ -271,6 +271,8 @@ void phytium_gpio_irq_enable(struct irq_data *d) unsigned long flags; u32 val; + if (gpio->is_resuming) + return; /* Only port A can provide interrupt source */ if (irqd_to_hwirq(d) >= gpio->ngpio[0]) return; diff --git a/drivers/gpio/gpio-phytium-core.h b/drivers/gpio/gpio-phytium-core.h index 3d8c6e7b35..381fc841de 100644 --- a/drivers/gpio/gpio-phytium-core.h +++ b/drivers/gpio/gpio-phytium-core.h @@ -63,6 +63,7 @@ struct phytium_gpio { struct gpio_chip gc; unsigned int ngpio[2]; int irq[32]; + int is_resuming; #ifdef CONFIG_PM_SLEEP struct phytium_gpio_ctx ctx; #endif diff --git a/drivers/gpio/gpio-phytium-pci.c b/drivers/gpio/gpio-phytium-pci.c index e194e3582f..3e4c1edd97 100644 --- a/drivers/gpio/gpio-phytium-pci.c +++ b/drivers/gpio/gpio-phytium-pci.c @@ -85,6 +85,7 @@ static int phytium_gpio_pci_probe(struct pci_dev *pdev, const struct pci_device_ girq = &gpio->gc.irq; girq->handler = handle_bad_irq; girq->default_type = IRQ_TYPE_NONE; + gpio->is_resuming = 0; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, @@ -132,11 +133,13 @@ static int phytium_gpio_pci_suspend(struct device *dev) gpio->ctx.ext_portb = readl(gpio->regs + GPIO_EXT_PORTB); gpio->ctx.inten = readl(gpio->regs + GPIO_INTEN); + gpio->is_resuming = 1; gpio->ctx.intmask = readl(gpio->regs + GPIO_INTMASK); gpio->ctx.inttype_level = readl(gpio->regs + GPIO_INTTYPE_LEVEL); gpio->ctx.int_polarity = readl(gpio->regs + GPIO_INT_POLARITY); gpio->ctx.debounce = readl(gpio->regs + GPIO_DEBOUNCE); + writel(0, gpio->regs + GPIO_INTEN); raw_spin_unlock_irqrestore(&gpio->lock, flags); return 0; @@ -157,7 +160,6 @@ static int phytium_gpio_pci_resume(struct device *dev) writel(gpio->ctx.swportb_ddr, gpio->regs + GPIO_SWPORTB_DDR); writel(gpio->ctx.ext_portb, gpio->regs + GPIO_EXT_PORTB); - writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN); writel(gpio->ctx.intmask, gpio->regs + GPIO_INTMASK); writel(gpio->ctx.inttype_level, gpio->regs + GPIO_INTTYPE_LEVEL); writel(gpio->ctx.int_polarity, gpio->regs + GPIO_INT_POLARITY); @@ -165,6 +167,9 @@ static int phytium_gpio_pci_resume(struct device *dev) writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI); + writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN); + gpio->is_resuming = 0; + raw_spin_unlock_irqrestore(&gpio->lock, flags); return 0; diff --git a/drivers/gpio/gpio-phytium-platform.c b/drivers/gpio/gpio-phytium-platform.c index 2f808b89e4..4774bb1f23 100644 --- a/drivers/gpio/gpio-phytium-platform.c +++ b/drivers/gpio/gpio-phytium-platform.c @@ -105,6 +105,7 @@ static int phytium_gpio_probe(struct platform_device *pdev) girq = &gpio->gc.irq; girq->handler = handle_bad_irq; girq->default_type = IRQ_TYPE_NONE; + gpio->is_resuming = 0; for (irq_count = 0; irq_count < platform_irq_count(pdev); irq_count++) { gpio->irq[irq_count] = -ENXIO; @@ -149,11 +150,13 @@ static int phytium_gpio_suspend(struct device *dev) gpio->ctx.ext_portb = readl(gpio->regs + GPIO_EXT_PORTB); gpio->ctx.inten = readl(gpio->regs + GPIO_INTEN); + gpio->is_resuming = 1; gpio->ctx.intmask = readl(gpio->regs + GPIO_INTMASK); gpio->ctx.inttype_level = readl(gpio->regs + GPIO_INTTYPE_LEVEL); gpio->ctx.int_polarity = readl(gpio->regs + GPIO_INT_POLARITY); gpio->ctx.debounce = readl(gpio->regs + GPIO_DEBOUNCE); + writel(0, gpio->regs + GPIO_INTEN); raw_spin_unlock_irqrestore(&gpio->lock, flags); return 0; @@ -174,7 +177,6 @@ static int phytium_gpio_resume(struct device *dev) writel(gpio->ctx.swportb_ddr, gpio->regs + GPIO_SWPORTB_DDR); writel(gpio->ctx.ext_portb, gpio->regs + GPIO_EXT_PORTB); - writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN); writel(gpio->ctx.intmask, gpio->regs + GPIO_INTMASK); writel(gpio->ctx.inttype_level, gpio->regs + GPIO_INTTYPE_LEVEL); writel(gpio->ctx.int_polarity, gpio->regs + GPIO_INT_POLARITY); @@ -182,6 +184,9 @@ static int phytium_gpio_resume(struct device *dev) writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI); + writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN); + gpio->is_resuming = 0; + raw_spin_unlock_irqrestore(&gpio->lock, flags); return 0; -- Gitee From 60e84ca0e3584d91120e5f2396ad123d4bea8ea1 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 9 Sep 2024 15:34:00 +0800 Subject: [PATCH 071/121] gpio: phytium: Modify the irq handler logic In non-irq sharing mode, now it supports to handle the irq interrupts of its owm pin. This avoids the problem of irq being transmitted to the unwanted CPU. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I6a4ccbbafbe7c34f6053fad1dc808fd9afad7b3b --- drivers/gpio/gpio-phytium-core.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-phytium-core.c b/drivers/gpio/gpio-phytium-core.c index aa8bd196ce..1bda08c856 100644 --- a/drivers/gpio/gpio-phytium-core.c +++ b/drivers/gpio/gpio-phytium-core.c @@ -327,19 +327,36 @@ void phytium_gpio_irq_handler(struct irq_desc *desc) struct irq_chip *irqchip = irq_desc_get_chip(desc); unsigned long pending; int offset; + int index = -1; + unsigned int index_found = 0; chained_irq_enter(irqchip, desc); pending = readl(gpio->regs + GPIO_INTSTATUS); + + if (gc->irq.num_parents > 1) { + for (index = 0 ; index < gc->irq.num_parents; index++) { + if (gc->irq.parents[index] == desc->irq_data.irq) { + index_found = 1; + break; + } + } + if (index_found == 0) { + pr_err("Can't find index for this gpio interrupt.\n"); + index = -1; + } + } + if (pending) { for_each_set_bit(offset, &pending, gpio->ngpio[0]) { - int gpio_irq = irq_find_mapping(gc->irq.domain, - offset); - generic_handle_irq(gpio_irq); - - if ((irq_get_trigger_type(gpio_irq) & - IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) - phytium_gpio_toggle_trigger(gpio, offset); + if (index == -1 || offset == index) { + int gpio_irq = irq_find_mapping(gc->irq.domain, + offset); + generic_handle_irq(gpio_irq); + if ((irq_get_trigger_type(gpio_irq) & + IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) + phytium_gpio_toggle_trigger(gpio, offset); + } } } -- Gitee From 0791bc2a23161a7f61b48a8579052238f8bd7d23 Mon Sep 17 00:00:00 2001 From: Chen Zhenhua Date: Sun, 28 Apr 2024 12:31:03 +0800 Subject: [PATCH 072/121] usb: phytium: Improve the endpoint managerment algorithm and some bugs When the device endpoint number is greater than 6, the endpoint management algorithm sometimes appears the endpoint management error. Fix the problem that when the device uses more than 6 endpoints at the same time, the dirver reports an abnormal empty pointer. Mainline: Open-Source Signed-off-by: Chen Zhenhua Signed-off-by: Wang Yinfeng Change-Id: I9a45fec02fc3664a862c43abdf637bf648700e9b --- drivers/usb/phytium/host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/phytium/host.c b/drivers/usb/phytium/host.c index 8d58eaa99d..fc87a1b968 100644 --- a/drivers/usb/phytium/host.c +++ b/drivers/usb/phytium/host.c @@ -1317,7 +1317,7 @@ static int hc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) usb_endpoint_dir_in(host_ep_desc)); if (req->epNum > MAX_INSTANCE_EP_NUM) { pr_err("Not enough endpoint resource for remap\n"); - dump_ep_remap_pool(priv, usb_endpoint_dir_in(host_ep_desc)); + dump_ep_remap_pool(priv, usb_endpoint_num(host_ep_desc)); req->epNum = MAX_INSTANCE_EP_NUM; } -- Gitee From 8076316adf8a73de9fd938223f2df576256fb3c9 Mon Sep 17 00:00:00 2001 From: Chen Zhenhua Date: Tue, 30 Jul 2024 10:31:09 +0800 Subject: [PATCH 073/121] usb: phytium: Fix some U disks with slow read and write rates issue This patch is used to fix some U disks with slow read and write rates, From the protocol point of view, the BULK transmission USB controller does not need to use the bInterval value of the BULK endpoint, but this USB controller uses this bInterval value, and we needs to correct this value actively, otherwise the read and write rate of some U disks will be slow. Mainline: Open-Source Signed-off-by: Chen Zhenhua Signed-off-by: Wang Yinfeng Change-Id: Ib1908cc557ddb571ca8addb4f32439662085c078 --- drivers/usb/phytium/host.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/phytium/host.c b/drivers/usb/phytium/host.c index fc87a1b968..84c8b04bf3 100644 --- a/drivers/usb/phytium/host.c +++ b/drivers/usb/phytium/host.c @@ -2049,6 +2049,12 @@ unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, if (usb_endpoint_xfer_control(&desc) || usb_endpoint_xfer_bulk(&desc)) { if (desc.bInterval == 0) return interval; + + if (usb_endpoint_xfer_bulk(&desc)) { + interval = 1; + return interval; + } + interval = fls(desc.bInterval) - 1; interval = clamp_val(interval, 0, 15); interval = 1 << interval; -- Gitee From 94c4c4d6a5bd0dcb05c110840193267b73c928e1 Mon Sep 17 00:00:00 2001 From: Chen Zhenhua Date: Sat, 12 Oct 2024 11:16:49 +0800 Subject: [PATCH 074/121] usb: phytium: Add driver version information This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Chen Zhenhua Signed-off-by: Wang Yinfeng Change-Id: I9885957066a5391d27915bbb7fbe7f7671d22591 --- drivers/usb/phytium/platform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/phytium/platform.c b/drivers/usb/phytium/platform.c index 48f35b19ad..37b7b3635a 100644 --- a/drivers/usb/phytium/platform.c +++ b/drivers/usb/phytium/platform.c @@ -11,6 +11,7 @@ #include "core.h" #include "hw-regs.h" +#define PHYTIUM_OTG_V1_VERSION "1.0.0" #define PHYTIUM_OTG_USB_LOADED 3 #define USB2_2_BASE_ADDRESS 0x31800000 @@ -215,3 +216,4 @@ module_platform_driver(phytium_otg_driver); MODULE_AUTHOR("Chen Zhenhua "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Phytium usb platform wrapper"); +MODULE_VERSION(PHYTIUM_OTG_V1_VERSION); -- Gitee From c1424454c903cf0144dbcc7001fbf2349a944789 Mon Sep 17 00:00:00 2001 From: Chen Zhenhua Date: Tue, 27 Feb 2024 14:01:52 +0800 Subject: [PATCH 075/121] xhci: Enable Phytium SOC to support S1 wake-up function This patch makes Phytium SOC to support S1 wake-up function. Mainline: Open-Source Signed-off-by: Chen Zhenhua Signed-off-by: Wang Yinfeng Change-Id: I937ae6fc5101f64fda70c553c5cbbeda9f354811 --- drivers/usb/host/xhci-plat.c | 2 +- drivers/usb/host/xhci-ring.c | 6 ++++++ drivers/usb/host/xhci.c | 19 +++++++++++++++++++ drivers/usb/host/xhci.h | 3 +++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 9420d7a565..7aa8dc4ca3 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -114,7 +114,7 @@ static const struct xhci_plat_priv xhci_plat_brcm = { }; static const struct xhci_plat_priv xhci_plat_phytium_pe220x = { - .quirks = XHCI_RESET_ON_RESUME, + .quirks = XHCI_RESET_ON_RESUME | XHCI_S1_SUSPEND_WAKEUP, }; static const struct of_device_id usb_xhci_of_match[] = { diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 6e38b6b480..4587b652ce 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3154,6 +3154,12 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) goto out; } + if (status & STS_WAKEUP) { + status |= STS_WAKEUP; + writel(status, &xhci->op_regs->status); + ret = IRQ_HANDLED; + } + if (!(status & STS_EINT)) goto out; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f005ce1f91..5fa6c8909c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -936,6 +936,18 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) return -ETIMEDOUT; } } + + if (xhci->quirks & XHCI_S1_SUSPEND_WAKEUP) { + if (device_may_wakeup(xhci_to_hcd(xhci)->self.controller) && do_wakeup) { + if (enable_irq_wake(hcd->irq)) + xhci_err(xhci, "failed to enable irq wakes\n"); + + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + if (xhci->shared_hcd) + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + } + } + spin_unlock_irq(&xhci->lock); /* @@ -982,6 +994,13 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg) time_before(jiffies, xhci->usb3_rhub.bus_state.next_statechange)) msleep(100); + if (xhci->quirks & XHCI_S1_SUSPEND_WAKEUP) { + if (device_may_wakeup(xhci_to_hcd(xhci)->self.controller)) { + if (disable_irq_wake(hcd->irq)) + xhci_err(xhci, "failed to disable irq wakes\n"); + } + } + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); if (xhci->shared_hcd) set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 38a64838bc..e80d040cd6 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -159,6 +159,8 @@ struct xhci_op_regs { /* USBSTS - USB status - status bitmasks */ /* HC not running - set to 1 when run/stop bit is cleared. */ #define STS_HALT XHCI_STS_HALT +/* event wakeup interrupt */ +#define STS_WAKEUP (1 << 1) /* serious error, e.g. PCI parity error. The HC will clear the run/stop bit. */ #define STS_FATAL (1 << 2) /* event interrupt - clear this prior to clearing any IP flags in IR set*/ @@ -1661,6 +1663,7 @@ struct xhci_hcd { #define XHCI_WRITE_64_HI_LO BIT_ULL(47) #define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48) #define XHCI_SLOWDOWN_QUIRK BIT_ULL(49) +#define XHCI_S1_SUSPEND_WAKEUP BIT_ULL(50) unsigned int num_active_eps; unsigned int limit_active_eps; -- Gitee From c4c9374fae81402725c67246a6791bc0e8dbd88b Mon Sep 17 00:00:00 2001 From: Chen Zhenhua Date: Tue, 10 Dec 2024 12:01:55 +0800 Subject: [PATCH 076/121] usb: phytium: Fix synchronous transmission correction algorithm For synchronous transmission transaction of full speed devices, there is no need to make special corrections to the bInterval value, just ensure that the bInterval value is between 1 and 16. Mainline: Open-Source Signed-off-by: Chen Zhenhua Signed-off-by: Wang Yinfeng Change-Id: I3ff2f38d79ba5ca39475d4fc8541d2519b9450d7 --- drivers/usb/phytium/host.c | 11 +++++------ drivers/usb/phytium/platform.c | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/usb/phytium/host.c b/drivers/usb/phytium/host.c index 84c8b04bf3..4216524799 100644 --- a/drivers/usb/phytium/host.c +++ b/drivers/usb/phytium/host.c @@ -2060,7 +2060,7 @@ unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, interval = 1 << interval; if ((1 << interval) != desc.bInterval) pr_debug("rounding to %d microframes, desc %d microframes\n", - 1 << interval, desc.bInterval); + 1 << interval, desc.bInterval); break; } @@ -2069,16 +2069,15 @@ unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, interval = 1 << interval; if (interval != desc.bInterval - 1) pr_debug("rounding to %d %sframes\n", 1 << interval, - speed == USB_SPEED_FULL ? "" : "micro"); + speed == USB_SPEED_FULL ? "" : "micro"); } break; case USB_SPEED_FULL: if (usb_endpoint_xfer_isoc(&desc)) { - interval = clamp_val(desc.bInterval, 1, 16) - 1; + interval = clamp_val(desc.bInterval, 1, 16); if (interval != desc.bInterval - 1) pr_debug("rounding to %d %sframes\n", 1 << interval, - speed == USB_SPEED_FULL ? "" : "micro"); - interval += 3; + speed == USB_SPEED_FULL ? "" : "micro"); break; } fallthrough; @@ -2088,7 +2087,7 @@ unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, interval = clamp_val(interval, 3, 10); if ((1 << interval) != desc.bInterval * 8) pr_debug("rounding to %d microframes, desc %d microframes\n", - 1 << interval, desc.bInterval); + 1 << interval, desc.bInterval); } } diff --git a/drivers/usb/phytium/platform.c b/drivers/usb/phytium/platform.c index 37b7b3635a..9c1d07c8e0 100644 --- a/drivers/usb/phytium/platform.c +++ b/drivers/usb/phytium/platform.c @@ -11,7 +11,7 @@ #include "core.h" #include "hw-regs.h" -#define PHYTIUM_OTG_V1_VERSION "1.0.0" +#define PHYTIUM_OTG_V1_VERSION "1.0.1" #define PHYTIUM_OTG_USB_LOADED 3 #define USB2_2_BASE_ADDRESS 0x31800000 -- Gitee From 10b3f45595fa4c626e727dd93a6fb0763c26c09b Mon Sep 17 00:00:00 2001 From: Chen Zhenhua Date: Thu, 9 Jan 2025 14:18:37 +0800 Subject: [PATCH 077/121] usb: phytium: Add Copyright information This patch add Copyright information for USB driver. Mainline: Open-Source Signed-off-by: Chen Zhenhua Signed-off-by: Wang Yinfeng Change-Id: Id144745804bb1ddb8cc2f0b043456a9ba958d7d8 --- drivers/usb/phytium/core.c | 4 ++++ drivers/usb/phytium/core.h | 4 ++++ drivers/usb/phytium/dma.c | 4 ++++ drivers/usb/phytium/dma.h | 4 ++++ drivers/usb/phytium/gadget.c | 4 ++++ drivers/usb/phytium/gadget.h | 4 ++++ drivers/usb/phytium/host.c | 4 ++++ drivers/usb/phytium/host_api.h | 4 ++++ drivers/usb/phytium/hw-regs.h | 5 +++++ drivers/usb/phytium/pci.c | 4 ++++ drivers/usb/phytium/platform.c | 7 ++++++- 11 files changed, 47 insertions(+), 1 deletion(-) diff --git a/drivers/usb/phytium/core.c b/drivers/usb/phytium/core.c index c0182c0770..ed2d1d661c 100644 --- a/drivers/usb/phytium/core.c +++ b/drivers/usb/phytium/core.c @@ -1,5 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #include "core.h" int phytium_core_reset(struct phytium_cusb *config, bool skip_wait) diff --git a/drivers/usb/phytium/core.h b/drivers/usb/phytium/core.h index f563672cca..0237476bea 100644 --- a/drivers/usb/phytium/core.h +++ b/drivers/usb/phytium/core.h @@ -1,5 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #ifndef __PHYTIUM_CORE_H__ #define __PHYTIUM_CORE_H__ diff --git a/drivers/usb/phytium/dma.c b/drivers/usb/phytium/dma.c index acc0674cf5..3048a89de8 100644 --- a/drivers/usb/phytium/dma.c +++ b/drivers/usb/phytium/dma.c @@ -1,5 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #include #include #include "core.h" diff --git a/drivers/usb/phytium/dma.h b/drivers/usb/phytium/dma.h index f2c25e6006..cecc38c99f 100644 --- a/drivers/usb/phytium/dma.h +++ b/drivers/usb/phytium/dma.h @@ -1,5 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #ifndef __PHYTIUM_DMA_H__ #define __PHYTIUM_DMA_H__ diff --git a/drivers/usb/phytium/gadget.c b/drivers/usb/phytium/gadget.c index e5e1625d78..db33e6a192 100644 --- a/drivers/usb/phytium/gadget.c +++ b/drivers/usb/phytium/gadget.c @@ -1,5 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #include #include "gadget.h" #include "dma.h" diff --git a/drivers/usb/phytium/gadget.h b/drivers/usb/phytium/gadget.h index d87b55ade7..6d7bd4b328 100644 --- a/drivers/usb/phytium/gadget.h +++ b/drivers/usb/phytium/gadget.h @@ -1,5 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #ifndef __PHYTIUM_GADGET_H_ #define __PHYTIUM_GADGET_H_ diff --git a/drivers/usb/phytium/host.c b/drivers/usb/phytium/host.c index 4216524799..8572c58f41 100644 --- a/drivers/usb/phytium/host.c +++ b/drivers/usb/phytium/host.c @@ -1,5 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #include #include #include diff --git a/drivers/usb/phytium/host_api.h b/drivers/usb/phytium/host_api.h index b99d2b4980..6003954eb1 100644 --- a/drivers/usb/phytium/host_api.h +++ b/drivers/usb/phytium/host_api.h @@ -1,5 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #ifndef __PHYTIUM_HOST_API_H_ #define __PHYTIUM_HOST_API_H_ diff --git a/drivers/usb/phytium/hw-regs.h b/drivers/usb/phytium/hw-regs.h index 8da9f8e9b9..8200ac3cf7 100644 --- a/drivers/usb/phytium/hw-regs.h +++ b/drivers/usb/phytium/hw-regs.h @@ -1,4 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #ifndef __LINUX_PHYTIUM_HW_REGS #define __LINUX_PHYTIUM_HW_REGS diff --git a/drivers/usb/phytium/pci.c b/drivers/usb/phytium/pci.c index b4d675effb..21f373cc4f 100644 --- a/drivers/usb/phytium/pci.c +++ b/drivers/usb/phytium/pci.c @@ -1,5 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #include #include #include diff --git a/drivers/usb/phytium/platform.c b/drivers/usb/phytium/platform.c index 9c1d07c8e0..c61b544bae 100644 --- a/drivers/usb/phytium/platform.c +++ b/drivers/usb/phytium/platform.c @@ -1,4 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright (c) 2022, Phytium Technology Co., Ltd. + */ + #include #include //#include @@ -11,7 +16,7 @@ #include "core.h" #include "hw-regs.h" -#define PHYTIUM_OTG_V1_VERSION "1.0.1" +#define PHYTIUM_OTG_V1_VERSION "1.0.2" #define PHYTIUM_OTG_USB_LOADED 3 #define USB2_2_BASE_ADDRESS 0x31800000 -- Gitee From f83f12fa8a780273092f607b97f81ab9c68e52eb Mon Sep 17 00:00:00 2001 From: Wang Min Date: Wed, 24 Jul 2024 20:09:25 +0800 Subject: [PATCH 078/121] media: phytium-jpeg: Fixed some JPEG driver issues The commit fixed the below issues. 1) Intialize the driver first version. 2) Supprot the feature of set the sampling mode, such as V4L2_JPEG_CHROMA_SUBSAMPLING_420,V4L2_JPEG_CHROMA_SUBSAMPLING_444 and other modes. 3) Adjust the order of altering resolution procedures. Mainline: Open-Source Signed-off-by: Wang Min Signed-off-by: Wang Yinfeng Change-Id: Ifdd49c7d1926d8b09f00acb6bc3d4a768dbc8524 --- .../platform/phytium/phytium_jpeg_core.c | 133 +++++++++++++++--- .../platform/phytium/phytium_jpeg_core.h | 4 +- 2 files changed, 116 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/phytium/phytium_jpeg_core.c b/drivers/media/platform/phytium/phytium_jpeg_core.c index 014af0162c..ea4c7084df 100644 --- a/drivers/media/platform/phytium/phytium_jpeg_core.c +++ b/drivers/media/platform/phytium/phytium_jpeg_core.c @@ -71,7 +71,13 @@ static u32 phytium_jpeg_header[PHYTIUM_JPEG_HEADER_SIZE] = { static char yuv_mode_str[YUV_MODE_STR_LEN] = { "yuv444" }; module_param_string(yuv_mode, yuv_mode_str, sizeof(yuv_mode_str), 0444); -MODULE_PARM_DESC(yuv_mode, "Users select one mode from such modes as 'yuv444', or 'yuv422', or 'yuv420'. If no mode is set, the driver adapts defaults mode 'yuv444'."); +MODULE_PARM_DESC(yuv_mode, "Users select one mode from such modes as\n" + " \t\t'yuv444', or 'yuv422', or 'yuv420'. If no mode is set,\n" + " \t\tthe driver adapts defaults mode 'yuv444'."); + +/* The below global variables are used to filter same log-print lines */ +static bool first_invalid = true; +static bool cur_non_zero = true; static u32 phytium_jpeg_read(struct phytium_jpeg_dev *jpeg_dev, u32 reg) { @@ -166,18 +172,19 @@ static void phytium_jpeg_off(struct phytium_jpeg_dev *jpeg_dev) u32 clear_all_interrupt = INT_FIFO_OVERFLOW | INT_OCM_BUF_OVERFLOW | INT_JPEG_ENCODE_COMPLETE | INT_VIDEO_FORMAT_CHANGE; - if (!test_bit(VIDEO_CLOCKS_ON, &jpeg_dev->status)) { - dev_info(jpeg_dev->dev, "JPEG Engine is already off.\n"); - return; - } - /* disable all interrupt */ phytium_jpeg_write(jpeg_dev, INT_STATUS_CTRL_REG, disable_all_interrupt); /* clear all interrupt */ phytium_jpeg_write(jpeg_dev, INT_STATUS_CTRL_REG, clear_all_interrupt); + /* disable JPEG engine */ phytium_jpeg_update(jpeg_dev, TRANSFORM_INFO_REG, TRANSINFO_ENABLE_ENGINE, 0); + if (!test_bit(VIDEO_CLOCKS_ON, &jpeg_dev->status)) { + dev_info(jpeg_dev->dev, "JPEG Engine is already off.\n"); + return; + } + clear_bit(VIDEO_CLOCKS_ON, &jpeg_dev->status); /* wait 50 ms */ mdelay(50); @@ -218,21 +225,27 @@ static void phytium_jpeg_get_resolution(struct phytium_jpeg_dev *jpeg_dev) if (width * height != 0) { detected_timings->width = width; detected_timings->height = height; + jpeg_dev->v4l2_input_status = 0; + cur_non_zero = true; + } else { + /* filter some repeated log-print lines */ + first_invalid = cur_non_zero; + cur_non_zero = false; } - jpeg_dev->v4l2_input_status = 0; - /* * Resolution is changed will trigger an interrupt, resolution detecting * also is disable during process interrupt. So re-enable. */ phytium_jpeg_enable_source_detecting(jpeg_dev); - dev_info(jpeg_dev->dev, "Change resolution: %uX%u\n", width, height); + + if (cur_non_zero == true || first_invalid == true) + dev_info(jpeg_dev->dev, "Change resolution: %uX%u\n", width, height); } static void phytium_jpeg_set_resolution(struct phytium_jpeg_dev *jpeg_dev) { - struct v4l2_bt_timings *active_timings = &jpeg_dev->active_timings; + struct v4l2_bt_timings *active_timings = &jpeg_dev->active_timings; int i; int src_addrs[OCM_BUF_NUM]; /* @@ -479,6 +492,9 @@ static int phytium_jpeg_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { int ret; + u32 source_info; + u32 width; + u32 height; struct phytium_jpeg_dev *jpeg_dev = video_drvdata(file); /* @@ -500,6 +516,15 @@ static int phytium_jpeg_query_dv_timings(struct file *file, void *priv, timings->type = V4L2_DV_BT_656_1120; timings->bt = jpeg_dev->detected_timings; + /* Get resolution from SRC_VGA_INFO_REG */ + source_info = phytium_jpeg_read(jpeg_dev, SRC_VGA_INFO_REG); + width = (source_info & SRC_HOR_PIXELS) >> SRC_WIDTH_SHIFT; + height = (source_info & SRC_VER_PIXELS) >> SRC_HEIGHT_SHIFT; + + /* Check if that the current resolution is zero. */ + if (width == 0 || height == 0) + jpeg_dev->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL; + return jpeg_dev->v4l2_input_status ? -ENOLINK : 0; } @@ -738,10 +763,11 @@ static int phytium_jpeg_start_frame(struct phytium_jpeg_dev *jpeg_dev) unsigned long status; struct phytium_jpeg_buffer *jpeg_buf; - if (jpeg_dev->v4l2_input_status) { - dev_err(jpeg_dev->dev, "No signal; needn't start frame\n"); + /* JPEG Engine shouldn't be enable to compress in the case no signal is input JPEG Engine. + * V4L2_IN_ST_NO_SIGNAL + */ + if (jpeg_dev->v4l2_input_status) return 0; - } spin_lock_irqsave(&jpeg_dev->hw_lock, status); jpeg_buf = list_first_entry_or_null(&jpeg_dev->buffers, @@ -855,7 +881,7 @@ static int phytium_jpeg_buf_prepare(struct vb2_buffer *vb) static inline struct phytium_jpeg_buffer * phytium_vb2buf_to_dstbuf(struct vb2_v4l2_buffer *buf) { - return container_of(buf, struct phytium_jpeg_buffer, vb); + return container_of(buf, struct phytium_jpeg_buffer, vb); } static void phytium_jpeg_buf_queue(struct vb2_buffer *vb) @@ -914,7 +940,12 @@ static irqreturn_t phytium_jpeg_irq(int irq, void *arg) u32 frame_size; if (test_bit(VIDEO_POWEROFF, &jpeg_dev->status)) { - dev_info(jpeg_dev->dev, "jpeg engine is requested to poweroff\n"); + dev_info(jpeg_dev->dev, "jpeg engine is requested to poweroff 0x%x\n", + phytium_jpeg_read(jpeg_dev, INT_STATUS_CTRL_REG)); + /* Disable interruption */ + phytium_jpeg_update(jpeg_dev, INT_STATUS_CTRL_REG, STS_VE_JPEG_CODE_COMP_EN, 0); + /* clear all interruption of the hardware's buffers */ + phytium_jpeg_update(jpeg_dev, INT_STATUS_CTRL_REG, INT_JPEG_ENCODE_COMPLETE, 1); return IRQ_HANDLED; } @@ -1065,7 +1096,7 @@ static irqreturn_t phytium_jpeg_timer31_irq(int irq, void *arg) /* clear timer interrupt status */ writel(0x8, jpeg_dev->timer31_addr + 0x2c); - /* clear JPEG Engine's poweroff status */ + /* clear JPEG Engine's poweroff status */ clear_bit(VIDEO_POWEROFF, &jpeg_dev->status); dev_info(jpeg_dev->dev, "timer31 set jpeg status 0x%lx\n", jpeg_dev->status); @@ -1105,13 +1136,23 @@ static irqreturn_t phytium_jpeg_timer30_irq(int irq, void *arg) struct phytium_jpeg_dev *jpeg_dev = arg; struct arm_smccc_res res; + u32 disable_all_interrupt = 0; + u32 clear_all_interrupt = INT_FIFO_OVERFLOW | INT_OCM_BUF_OVERFLOW | + INT_JPEG_ENCODE_COMPLETE | INT_VIDEO_FORMAT_CHANGE; + /* disable timer interrupt */ writel(0, jpeg_dev->timer30_addr); /* clear timer interrupt status */ writel(0x8, jpeg_dev->timer30_addr + 0x2c); - /* Disable interruption */ - phytium_jpeg_update(jpeg_dev, INT_STATUS_CTRL_REG, STS_VE_JPEG_CODE_COMP_EN, 0); + /* disable all interrupts */ + phytium_jpeg_write(jpeg_dev, INT_STATUS_CTRL_REG, disable_all_interrupt); + udelay(5); + /* clear all interrupts */ + phytium_jpeg_write(jpeg_dev, INT_STATUS_CTRL_REG, clear_all_interrupt); + + /* disable JPEG engine */ + phytium_jpeg_update(jpeg_dev, TRANSFORM_INFO_REG, 0, 0); /* call SE to poweroff JPEG Engine */ arm_smccc_smc(0xc300fff4, 0x9, 0x2, 0x80000020, 0, 0, 0, 0, &res); @@ -1201,12 +1242,44 @@ static int phytium_jpeg_init(struct phytium_jpeg_dev *jpeg_dev) } +/* The function is provided for user space adjusts the sampling mode. */ +static int phytium_jpeg_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct phytium_jpeg_dev *jpeg_dev = container_of(ctrl->handler, + struct phytium_jpeg_dev, + ctrl_handler); + if (ctrl->id != V4L2_CID_JPEG_CHROMA_SUBSAMPLING) + return -EINVAL; + + switch (ctrl->val) { + case V4L2_JPEG_CHROMA_SUBSAMPLING_420: + strscpy(yuv_mode_str, "yuv420", sizeof(yuv_mode_str)); + break; + case V4L2_JPEG_CHROMA_SUBSAMPLING_422: + strscpy(yuv_mode_str, "yuv422", sizeof(yuv_mode_str)); + break; + default: + strscpy(yuv_mode_str, "yuv444", sizeof(yuv_mode_str)); + } + phytium_jpeg_set_yuv_mode(jpeg_dev); + dev_info(jpeg_dev->dev, "current sample mode is %s\n", yuv_mode_str); + return 0; +} + +static const struct v4l2_ctrl_ops phytium_jpeg_ctrl_ops = { + .s_ctrl = phytium_jpeg_set_ctrl, +}; + + static int phytium_jpeg_setup_video(struct phytium_jpeg_dev *jpeg_dev) { struct v4l2_device *v4l2_dev = &jpeg_dev->v4l2_dev; struct vb2_queue *dst_vq = &jpeg_dev->queue; struct video_device *vdev = &jpeg_dev->vdev; + const u64 mask = ~(BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_444) | + BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_422) | + BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_420)); int ret; jpeg_dev->pix_fmt.pixelformat = V4L2_PIX_FMT_JPEG; @@ -1222,6 +1295,20 @@ static int phytium_jpeg_setup_video(struct phytium_jpeg_dev *jpeg_dev) } /* Register how many v4l2 controls to a handler */ + v4l2_ctrl_handler_init(&jpeg_dev->ctrl_handler, 1); + v4l2_ctrl_new_std_menu(&jpeg_dev->ctrl_handler, &phytium_jpeg_ctrl_ops, + V4L2_CID_JPEG_CHROMA_SUBSAMPLING, + V4L2_JPEG_CHROMA_SUBSAMPLING_420, mask, + V4L2_JPEG_CHROMA_SUBSAMPLING_444); + + if (jpeg_dev->ctrl_handler.error) { + v4l2_ctrl_handler_free(&jpeg_dev->ctrl_handler); + dev_err(jpeg_dev->dev, "Failed to init v4l2 controls:%d\n", + jpeg_dev->ctrl_handler.error); + goto err_v4l2_register; + } + v4l2_dev->ctrl_handler = &jpeg_dev->ctrl_handler; + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; dst_vq->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF; dst_vq->dev = v4l2_dev->dev; @@ -1234,6 +1321,7 @@ static int phytium_jpeg_setup_video(struct phytium_jpeg_dev *jpeg_dev) dst_vq->min_buffers_needed = CAPTURE_BUF_NUMBER; ret = vb2_queue_init(dst_vq); if (ret) { + v4l2_ctrl_handler_free(&jpeg_dev->ctrl_handler); dev_err(jpeg_dev->dev, "Failed to init vb2 queue\n"); goto err_v4l2_register; } @@ -1244,7 +1332,7 @@ static int phytium_jpeg_setup_video(struct phytium_jpeg_dev *jpeg_dev) V4L2_CAP_STREAMING; vdev->v4l2_dev = v4l2_dev; strscpy(vdev->name, PHYTIUM_JPEG_NAME, sizeof(vdev->name)); - vdev->vfl_type = VFL_TYPE_VIDEO; + vdev->vfl_type = VFL_TYPE_VIDEO; /* The newest kernel using VFL_TYPE_VIDEO */ vdev->vfl_dir = VFL_DIR_RX; vdev->release = video_device_release_empty; vdev->ioctl_ops = &phytium_jpeg_ioctl_ops; @@ -1263,7 +1351,7 @@ static int phytium_jpeg_setup_video(struct phytium_jpeg_dev *jpeg_dev) err_video_register: vb2_queue_release(dst_vq); - + v4l2_ctrl_handler_free(&jpeg_dev->ctrl_handler); err_v4l2_register: v4l2_device_unregister(v4l2_dev); return ret; @@ -1352,10 +1440,14 @@ static int phytium_jpeg_remove(struct platform_device *pdev) phytium_jpeg_off(jpeg_dev); + phytium_jpeg_write(jpeg_dev, TRANSFORM_INFO_REG, 0); + video_unregister_device(&jpeg_dev->vdev); vb2_queue_release(&jpeg_dev->queue); + v4l2_ctrl_handler_free(&jpeg_dev->ctrl_handler); + v4l2_device_unregister(v4l2_dev); of_reserved_mem_device_release(dev); @@ -1375,5 +1467,6 @@ static struct platform_driver phytium_jpeg_driver = { module_platform_driver(phytium_jpeg_driver); MODULE_DESCRIPTION("Phytium JPEG Encoder driver"); +MODULE_VERSION(JPEG_DRIVER_VERSION); MODULE_AUTHOR("Wang Min "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/phytium/phytium_jpeg_core.h b/drivers/media/platform/phytium/phytium_jpeg_core.h index 27e32b2d3c..111cfefb97 100644 --- a/drivers/media/platform/phytium/phytium_jpeg_core.h +++ b/drivers/media/platform/phytium/phytium_jpeg_core.h @@ -36,6 +36,7 @@ #include #define PHYTIUM_JPEG_NAME "phytium-jpeg" +#define JPEG_DRIVER_VERSION "1.0.0" #define MAX_FRAME_RATE 60 #define MAX_HEIGHT 1080 #define MAX_WIDTH 1920 @@ -45,7 +46,7 @@ #define MAX_PIXEL_CLOCK (1920 * 1080 * 60) /* 1920 x 1080 x 60Hz */ #define SOURCE_RESOLUTION_DETECT_TIMEOUT msecs_to_jiffies(500) -#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(0) +#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(250) #define INVALID_RESOLUTION_DELAY msecs_to_jiffies(250) #define STOP_TIMEOUT msecs_to_jiffies(1000) @@ -128,6 +129,7 @@ struct phytium_jpeg_dev { unsigned int frame_rate; void __iomem *timer30_addr; void __iomem *timer31_addr; + struct v4l2_ctrl_handler ctrl_handler; }; struct phytium_jpeg_config { -- Gitee From 531f5d8363c02d1521f22c147719facf938f7d17 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Tue, 5 Nov 2024 15:05:02 +0800 Subject: [PATCH 079/121] dts: phytium: Add snoop node description for pe220x platforms Add snoop description for pe220x platforms, which usually used as BMC cards. Mainline: NA Signed-off-by: Li Yuze Change-Id: Id9e0b900b79bfb68f70690280888e11306e39323 --- arch/arm64/boot/dts/phytium/pe220x.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/phytium/pe220x.dtsi b/arch/arm64/boot/dts/phytium/pe220x.dtsi index ad6a184631..92d7b70b61 100644 --- a/arch/arm64/boot/dts/phytium/pe220x.dtsi +++ b/arch/arm64/boot/dts/phytium/pe220x.dtsi @@ -278,6 +278,13 @@ ddma1: dma-controller@28004000 { dma-channels = <8>; }; + snoop: snoop@28010000 { + compatible = "phytium,snoop-ctrl"; + reg = <0x0 0x28010000 0x1000>; + interrupts = ; + snoop-ports = <0x80>; + }; + lpc: lpc@28010000 { compatible = "simple-mfd", "syscon"; reg = <0x0 0x28010000 0x0 0x1000>; -- Gitee From 99ecb5930730fcca2511e23d2a81f25115510e6c Mon Sep 17 00:00:00 2001 From: Lan Hengyu Date: Wed, 20 Mar 2024 13:44:00 +0800 Subject: [PATCH 080/121] snoop: phytium: Add the driver of phytium snoop driver This patch add the driver of phytium snoop controller. Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng --- MAINTAINERS | 1 + drivers/misc/Kconfig | 11 + drivers/misc/Makefile | 1 + drivers/misc/phytium-snoop-ctrl.c | 329 ++++++++++++++++++++++++++++++ 4 files changed, 342 insertions(+) create mode 100644 drivers/misc/phytium-snoop-ctrl.c diff --git a/MAINTAINERS b/MAINTAINERS index d265d1a06c..f36ad00510 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17484,6 +17484,7 @@ F: drivers/mailbox/phytium_mailbox.c F: drivers/media/platform/phytium-jpeg/phytium_jpeg* F: drivers/mfd/phytium_px210_i2s_lsd.c F: drivers/mfd/phytium_px210_i2s_mmd.c +F: drivers/misc/phytium-snoop-ctrl.c F: drivers/mmc/host/phytium-mci* F: drivers/mmc/host/phytium-sdci.* F: drivers/mtd/nand/raw/phytium_nand* diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index cadd4a820c..a36a8868bb 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -104,6 +104,17 @@ config PHANTOM If you choose to build module, its name will be phantom. If unsure, say N here. +config PHYTIUM_SNOOP_CTRL + tristate "Phytium snoop controller support" + depends on ARCH_PHYTIUM && REGMAP && MFD_SYSCON + default n + help + Say Y here if you want BMC to snoop 80h port. + + Provides a driver to control the phytium snoop interface which + allows the BMC to listen on and save the data written by the + host to an arbitrary I/O port. + config TIFM_CORE tristate "TI Flash Media interface support" depends on PCI diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index f2a4d1ff65..16480d807b 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_LKDTM) += lkdtm/ obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o obj-$(CONFIG_PHANTOM) += phantom.o +obj-$(CONFIG_PHYTIUM_SNOOP_CTRL) += phytium-snoop-ctrl.o obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o diff --git a/drivers/misc/phytium-snoop-ctrl.c b/drivers/misc/phytium-snoop-ctrl.c new file mode 100644 index 0000000000..aedb15bbfa --- /dev/null +++ b/drivers/misc/phytium-snoop-ctrl.c @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Provides a simple driver to control the PHYTIUM snoop ctrl interface which + * allows the BMC to listen on and save the data written by + * the host to an arbitrary I/O port. + * + * Typically used by the BMC to "watch" host boot progress via port + * 0x80 writes made by the BIOS during the boot process. + * + * Copyright (c) 2019-2023, Phytium Technology Co., Ltd. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "phytium-snoop-ctrl" + +#define NUM_SNOOP_CHANNELS 2 +#define SNOOP_FIFO_SIZE 2048 + +#define snp_enable_reg 0x150 +#define snp_enable_reg_snp1_en BIT(0) +#define snp_enable_reg_snp1_int_en BIT(1) +#define snp_enable_reg_snp2_en BIT(2) +#define snp_enable_reg_snp2_int_en BIT(3) + +#define snp_status_reg 0x154 +#define snp_status_reg_snp1_int BIT(0) +#define snp_status_reg_snp2_int BIT(1) + +#define snp_addr_reg 0x158 +#define snp_addr_reg_snp1_addr GENMASK(15, 0) +#define snp_addr_reg_snp1_shift 0 +#define snp_addr_reg_snp2_addr GENMASK(31, 16) +#define snp_addr_reg_snp2_shift 16 + +#define snp_data_reg 0x15c +#define snp_data_reg_snp1_data_reg GENMASK(7, 0) +#define snp_data_reg_snp1_shift 0 +#define snp_data_reg_snp2_data_reg GENMASK(15, 8) +#define snp_data_reg_snp2_shift 8 + +#define SNOOP_DRIVER_VERSION "1.1.1" + +struct phytium_snoop_ctrl_channel { + struct kfifo fifo; + wait_queue_head_t wq; + struct miscdevice miscdev; +}; + +struct phytium_snoop_ctrl { + struct regmap *regmap; + int irq; + struct phytium_snoop_ctrl_channel chan[NUM_SNOOP_CHANNELS]; +}; + +static struct phytium_snoop_ctrl_channel *snoop_file_to_chan(struct file *file) +{ + return container_of(file->private_data, + struct phytium_snoop_ctrl_channel, + miscdev); +} + +static ssize_t snoop_file_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct phytium_snoop_ctrl_channel *chan = snoop_file_to_chan(file); + unsigned int copied; + int ret = 0; + + if (kfifo_is_empty(&chan->fifo)) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + ret = wait_event_interruptible(chan->wq, + !kfifo_is_empty(&chan->fifo)); + if (ret == -ERESTARTSYS) + return -EINTR; + } + ret = kfifo_to_user(&chan->fifo, buffer, count, &copied); + + return ret ? ret : copied; +} + +static unsigned int snoop_file_poll(struct file *file, + struct poll_table_struct *pt) +{ + struct phytium_snoop_ctrl_channel *chan = snoop_file_to_chan(file); + + poll_wait(file, &chan->wq, pt); + return !kfifo_is_empty(&chan->fifo) ? POLLIN : 0; +} + +static const struct file_operations snoop_fops = { + .owner = THIS_MODULE, + .read = snoop_file_read, + .poll = snoop_file_poll, + .llseek = noop_llseek, +}; + +/* Save a byte to a FIFO and discard the oldest byte if FIFO is full */ +static void put_fifo_with_discard(struct phytium_snoop_ctrl_channel *chan, u8 val) +{ + if (!kfifo_initialized(&chan->fifo)) + return; + if (kfifo_is_full(&chan->fifo)) + kfifo_skip(&chan->fifo); + kfifo_put(&chan->fifo, val); + wake_up_interruptible(&chan->wq); +} + +static irqreturn_t phytium_snoop_ctrl_irq(int irq, void *arg) +{ + struct phytium_snoop_ctrl *snoop_ctrl = arg; + u32 reg, data; + + if (regmap_read(snoop_ctrl->regmap, snp_status_reg, ®)) + return IRQ_NONE; + + /* Check if one of the snoop channels is interrupting */ + reg &= (snp_status_reg_snp1_int | snp_status_reg_snp2_int); + if (!reg) + return IRQ_NONE; + + /* Ack pending IRQs */ + regmap_write(snoop_ctrl->regmap, snp_status_reg, reg); + + /* Read and save most recent snoop'ed data byte to FIFO */ + regmap_read(snoop_ctrl->regmap, snp_data_reg, &data); + + if (reg & snp_status_reg_snp1_int) { + u8 val = (data & snp_data_reg_snp1_data_reg) >> snp_data_reg_snp1_shift; + + put_fifo_with_discard(&snoop_ctrl->chan[0], val); + } + if (reg & snp_status_reg_snp2_int) { + u8 val = (data & snp_data_reg_snp2_data_reg) >> snp_data_reg_snp2_shift; + + put_fifo_with_discard(&snoop_ctrl->chan[1], val); + } + + return IRQ_HANDLED; +} + +static int phytium_snoop_ctrl_config_irq(struct phytium_snoop_ctrl *snoop_ctrl, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int rc; + + snoop_ctrl->irq = platform_get_irq(pdev, 0); + if (!snoop_ctrl->irq) + return -ENODEV; + + rc = devm_request_irq(dev, snoop_ctrl->irq, + phytium_snoop_ctrl_irq, IRQF_SHARED, + DEVICE_NAME, snoop_ctrl); + if (rc < 0) { + dev_warn(dev, "Unable to request IRQ %d\n", snoop_ctrl->irq); + snoop_ctrl->irq = 0; + return rc; + } + + return 0; +} + +static int phytium_enable_snoop(struct phytium_snoop_ctrl *snoop_ctrl, + struct device *dev, + int channel, u16 snoop_port) +{ + int rc = 0; + u32 snp_enable_reg_en, snp_addr_reg_mask, snp_addr_reg_shift; + + init_waitqueue_head(&snoop_ctrl->chan[channel].wq); + /* Create FIFO datastructure */ + rc = kfifo_alloc(&snoop_ctrl->chan[channel].fifo, + SNOOP_FIFO_SIZE, GFP_KERNEL); + if (rc) + return rc; + + snoop_ctrl->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR; + snoop_ctrl->chan[channel].miscdev.name = + devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel); + snoop_ctrl->chan[channel].miscdev.fops = &snoop_fops; + snoop_ctrl->chan[channel].miscdev.parent = dev; + rc = misc_register(&snoop_ctrl->chan[channel].miscdev); + if (rc) + return rc; + + /* Enable snoop channel at requested port */ + switch (channel) { + case 0: + snp_enable_reg_en = snp_enable_reg_snp1_en | snp_enable_reg_snp1_int_en; + snp_addr_reg_mask = snp_addr_reg_snp1_addr; + snp_addr_reg_shift = snp_addr_reg_snp1_shift; + break; + case 1: + snp_enable_reg_en = snp_enable_reg_snp2_en | snp_enable_reg_snp2_int_en; + snp_addr_reg_mask = snp_addr_reg_snp2_addr; + snp_addr_reg_shift = snp_addr_reg_snp2_shift; + break; + default: + return -EINVAL; + } + + regmap_update_bits(snoop_ctrl->regmap, + snp_enable_reg, snp_enable_reg_en, snp_enable_reg_en); + regmap_update_bits(snoop_ctrl->regmap, snp_addr_reg, snp_addr_reg_mask, + snoop_port << snp_addr_reg_shift); + return rc; +} + +static void phytium_disable_snoop(struct phytium_snoop_ctrl *snoop_ctrl, + int channel) +{ + switch (channel) { + case 0: + regmap_update_bits(snoop_ctrl->regmap, snp_enable_reg, + snp_enable_reg_snp1_en | snp_enable_reg_snp1_int_en, + 0); + break; + case 1: + regmap_update_bits(snoop_ctrl->regmap, snp_enable_reg, + snp_enable_reg_snp2_en | snp_enable_reg_snp2_int_en, + 0); + break; + default: + return; + } + + kfifo_free(&snoop_ctrl->chan[channel].fifo); + misc_deregister(&snoop_ctrl->chan[channel].miscdev); +} + +static int phytium_snoop_ctrl_probe(struct platform_device *pdev) +{ + struct phytium_snoop_ctrl *snoop_ctrl; + struct device *dev; + u32 port; + int rc; + + dev = &pdev->dev; + + snoop_ctrl = devm_kzalloc(dev, sizeof(*snoop_ctrl), GFP_KERNEL); + if (!snoop_ctrl) + return -ENOMEM; + + snoop_ctrl->regmap = syscon_node_to_regmap( + pdev->dev.of_node); + if (IS_ERR(snoop_ctrl->regmap)) { + dev_err(dev, "Couldn't get regmap\n"); + return -ENODEV; + } + + dev_set_drvdata(&pdev->dev, snoop_ctrl); + + rc = of_property_read_u32_index(dev->of_node, "snoop-ports", 0, &port); + if (rc) { + dev_err(dev, "no snoop ports configured\n"); + return -ENODEV; + } + + rc = phytium_snoop_ctrl_config_irq(snoop_ctrl, pdev); + if (rc) + return rc; + + rc = phytium_enable_snoop(snoop_ctrl, dev, 0, port); + if (rc) + return rc; + + /* Configuration of 2nd snoop channel port is optional */ + if (of_property_read_u32_index(dev->of_node, "snoop-ports", + 1, &port) == 0) { + rc = phytium_enable_snoop(snoop_ctrl, dev, 1, port); + if (rc) + phytium_disable_snoop(snoop_ctrl, 0); + } + + return rc; +} + +static int phytium_snoop_ctrl_remove(struct platform_device *pdev) +{ + struct phytium_snoop_ctrl *snoop_ctrl = dev_get_drvdata(&pdev->dev); + + /* Disable both snoop channels */ + phytium_disable_snoop(snoop_ctrl, 0); + phytium_disable_snoop(snoop_ctrl, 1); + + return 0; +} + + +static const struct of_device_id phytium_snoop_ctrl_match[] = { + { .compatible = "phytium,snoop-ctrl"}, + { }, +}; + +static struct platform_driver phytium_snoop_ctrl_driver = { + .driver = { + .name = DEVICE_NAME, + .of_match_table = phytium_snoop_ctrl_match, + }, + .probe = phytium_snoop_ctrl_probe, + .remove = phytium_snoop_ctrl_remove, +}; + +module_platform_driver(phytium_snoop_ctrl_driver); + +MODULE_DEVICE_TABLE(of, phytium_snoop_ctrl_match); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lan Hengyu lanhengyu1395@phytium.com.cn"); +MODULE_DESCRIPTION("Driver to control Phytium snoop controller functionality"); +MODULE_VERSION(SNOOP_DRIVER_VERSION); -- Gitee From 0930b8bd5f5982eb9d3a515a5f28ebab2ccba633 Mon Sep 17 00:00:00 2001 From: Lan Hengyu Date: Wed, 20 Mar 2024 13:36:43 +0800 Subject: [PATCH 081/121] dt-bindings: Phytium: Update snoop controller devicetree description This patch update the DT description for the Phytium snoop controller. Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng --- .../bindings/misc/phytium,snoop-ctrl.yaml | 44 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/phytium,snoop-ctrl.yaml diff --git a/Documentation/devicetree/bindings/misc/phytium,snoop-ctrl.yaml b/Documentation/devicetree/bindings/misc/phytium,snoop-ctrl.yaml new file mode 100644 index 0000000000..db6f165a7d --- /dev/null +++ b/Documentation/devicetree/bindings/misc/phytium,snoop-ctrl.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/misc/phytium,snoop-ctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Phytium BMC Snoop Controller + +maintainers: + - Lan Hengyu + +description: + The snoop controller allows the BMC to listen on and record the data + bytes written by the Host to the target I/O ports. + +properties: + compatible: + items: + - enum: + - phytium,snoop-ctrl + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + snoop-ports: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: Ports to snoop + +required: + - compatible + - interrupts + - snoop-ports + +examples: + - | + snoop: snoop@28010000 { + compatible = "phytium,snoop-ctrl"; + reg = <0x0 0x28010000 0x1000>; + interrupts = ; + + snoop-ports = <0x80>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index f36ad00510..44adda4f4b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17446,6 +17446,7 @@ F: Documentation/devicetree/bindings/ipmi/phytium,bt-bmc.yaml F: Documentation/devicetree/bindings/ipmi/phytium,kcs-bmc.yaml F: Documentation/devicetree/bindings/leds/phytnet_led.yaml F: Documentation/devicetree/bindings/mailbox/phytium,mbox.yaml +F: Documentation/devicetree/bindings/misc/phytium,snoop-ctrl.yaml F: Documentation/devicetree/bindings/mmc/phytium,mci.yaml F: Documentation/devicetree/bindings/mmc/phytium,sdci.yaml F: Documentation/devicetree/bindings/mtd/phytium,nfc.yaml -- Gitee From 04c443f8bbc3e37f46cdefb49b3c26b27003da71 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Wed, 5 Jun 2024 17:13:09 +0800 Subject: [PATCH 082/121] tacho: phytium: optimize the method to get resources This patch optimize the method to get resources in tacho driver. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I01ca2ee5ecf9c418b972481bbcdb593b0ecd068b --- drivers/hwmon/tacho-phytium.c | 54 +++++++++-------------------------- 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/drivers/hwmon/tacho-phytium.c b/drivers/hwmon/tacho-phytium.c index 00a773014f..85e68bfa55 100644 --- a/drivers/hwmon/tacho-phytium.c +++ b/drivers/hwmon/tacho-phytium.c @@ -236,41 +236,24 @@ static const struct attribute_group *capture_groups[] = { static int phytium_tacho_get_work_mode(struct phytium_tacho *tacho) { - struct device_node *nc = tacho->dev->of_node; struct fwnode_handle *fwn = tacho->dev->fwnode; - if (of_property_read_bool(nc, "tacho")) + if (fwnode_property_read_bool(fwn, "tacho")) return tacho_mode; - else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( - fwn, "tacho")) - return tacho_mode; - if (of_property_read_bool(nc, "capture")) - return capture_mode; - else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( - fwn, "capture")) + if (fwnode_property_read_bool(fwn, "capture")) return capture_mode; return tacho_mode; } static int phytium_tacho_get_edge_mode(struct phytium_tacho *tacho) { - struct device_node *nc = tacho->dev->of_node; struct fwnode_handle *fwn = tacho->dev->fwnode; - if (of_property_read_bool(nc, "up")) - return rising_edge; - else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( - fwn, "up")) + if (fwnode_property_read_bool(fwn, "up")) return rising_edge; - if (of_property_read_bool(nc, "down")) + if (fwnode_property_read_bool(fwn, "down")) return falling_edge; - else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( - fwn, "down")) - return falling_edge; - if (of_property_read_bool(nc, "double")) - return double_edge; - else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( - fwn, "double")) + if (fwnode_property_read_bool(fwn, "double")) return double_edge; return rising_edge; } @@ -278,15 +261,10 @@ static int phytium_tacho_get_edge_mode(struct phytium_tacho *tacho) static int phytium_tacho_get_debounce(struct phytium_tacho *tacho) { u32 value; - struct device_node *nc = tacho->dev->of_node; struct fwnode_handle *fwn = tacho->dev->fwnode; - if (!of_property_read_u32(nc, "debounce-level", &value)) + if (!fwnode_property_read_u32(fwn, "debounce-level", &value)) return value; - if (has_acpi_companion(tacho->dev)) { - if (!fwnode_property_read_u32(fwn, "debounce-level", &value)) - return value; - } return 0; } @@ -303,6 +281,7 @@ static int phytium_tacho_probe(struct platform_device *pdev) struct resource *res; struct phytium_tacho *tacho; int ret; + u32 fre; tacho = devm_kzalloc(dev, sizeof(*tacho), GFP_KERNEL); if (!tacho) @@ -320,24 +299,19 @@ static int phytium_tacho_probe(struct platform_device *pdev) return PTR_ERR(tacho->base); } + tacho->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(tacho->clk)) + return PTR_ERR(tacho->clk); + ret = clk_prepare_enable(tacho->clk); + if (ret) + return ret; + if (!has_acpi_companion(tacho->dev)) { - tacho->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(tacho->clk)) - return PTR_ERR(tacho->clk); - ret = clk_prepare_enable(tacho->clk); - if (ret) - return ret; tacho->freq = clk_get_rate(tacho->clk); } else { - u32 fre; - - ret = clk_prepare_enable(tacho->clk); - if (ret) - return ret; fwnode_property_read_u32(tacho->dev->fwnode, "clock-frequency", &fre); tacho->freq = fre; } - tacho->irq = platform_get_irq(pdev, 0); if (tacho->irq < 0) { dev_err(&pdev->dev, "no irq resource?\n"); -- Gitee From 59f90bde0be6cae0dcbe05c39720bca8cf7ea739 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 29 Jul 2024 15:46:26 +0800 Subject: [PATCH 083/121] tacho: phytium: Add tacho driver version messages This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: Iecd67cf5303995ee75abee35de553ff10e5b6404 --- drivers/hwmon/tacho-phytium.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hwmon/tacho-phytium.c b/drivers/hwmon/tacho-phytium.c index 85e68bfa55..818a471a8e 100644 --- a/drivers/hwmon/tacho-phytium.c +++ b/drivers/hwmon/tacho-phytium.c @@ -57,6 +57,8 @@ #define TIMER_INT_CLR_MASK GENMASK(5, 0) +#define TACHO_DRIVER_VERSION "1.1.1" + enum tacho_modes { tacho_mode = 1, capture_mode, @@ -388,3 +390,4 @@ module_platform_driver(phytium_tacho_driver); MODULE_AUTHOR("Zhang Yiqun "); MODULE_DESCRIPTION("Phytium tachometer driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(TACHO_DRIVER_VERSION); -- Gitee From 494796af296e141f35a30eb43cd90c292c889e91 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 6 Jan 2025 17:12:19 +0800 Subject: [PATCH 084/121] tacho: phytium: Fixed tacho driver probe failure issue Fixed tacho driver probe failure issue caused by failure to read clock data when using uefi startup. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I6484c978a35638cba29e346095d93409edbaa828 --- drivers/hwmon/tacho-phytium.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/hwmon/tacho-phytium.c b/drivers/hwmon/tacho-phytium.c index 818a471a8e..f61ed5ac60 100644 --- a/drivers/hwmon/tacho-phytium.c +++ b/drivers/hwmon/tacho-phytium.c @@ -56,6 +56,7 @@ #define TIMER_START_VALUE_REG 0x38 #define TIMER_INT_CLR_MASK GENMASK(5, 0) +#define TIMER_TACHO_DEFAULT_FREQ 0x2FAF080 #define TACHO_DRIVER_VERSION "1.1.1" @@ -301,18 +302,18 @@ static int phytium_tacho_probe(struct platform_device *pdev) return PTR_ERR(tacho->base); } - tacho->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(tacho->clk)) - return PTR_ERR(tacho->clk); - ret = clk_prepare_enable(tacho->clk); - if (ret) - return ret; - + tacho->freq = TIMER_TACHO_DEFAULT_FREQ; if (!has_acpi_companion(tacho->dev)) { - tacho->freq = clk_get_rate(tacho->clk); + tacho->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(tacho->clk) || clk_prepare_enable(tacho->clk)) + dev_err(&pdev->dev, "Tacho get clocks failed\n"); + else + tacho->freq = clk_get_rate(tacho->clk); } else { - fwnode_property_read_u32(tacho->dev->fwnode, "clock-frequency", &fre); - tacho->freq = fre; + if (fwnode_property_read_u32(tacho->dev->fwnode, "clock-frequency", &fre)) + dev_err(&pdev->dev, "Tacho get clock-frequency failed\n"); + else + tacho->freq = fre; } tacho->irq = platform_get_irq(pdev, 0); if (tacho->irq < 0) { -- Gitee From 5ab96250be17dad5a91e03657fdbd6f2d0bb81b8 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 29 Jul 2024 15:34:28 +0800 Subject: [PATCH 085/121] pwm:phytium: Add PWM driver version messages This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I018a4d532abe168ae5589e30da493c851d31ed52 --- drivers/pwm/pwm-phytium.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pwm/pwm-phytium.c b/drivers/pwm/pwm-phytium.c index 98ae864a82..a754c1628b 100644 --- a/drivers/pwm/pwm-phytium.c +++ b/drivers/pwm/pwm-phytium.c @@ -47,6 +47,8 @@ #define PWM_N(x) ((0x400)*(x)) #define MAX_PARAMETER 2 +#define PWM_DRIVER_VERSION "1.1.1" + struct phytium_pwm_state { int rst; int cntmod; @@ -588,3 +590,4 @@ module_platform_driver(pwm_phytium_driver); MODULE_DESCRIPTION("Phytium SoC PWM driver"); MODULE_AUTHOR("Yang Liu "); MODULE_LICENSE("GPL"); +MODULE_VERSION(PWM_DRIVER_VERSION); -- Gitee From 859422c70b766fd0a517d03435983f1ba66400b4 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 29 Jul 2024 15:42:16 +0800 Subject: [PATCH 086/121] edac:phytium: Add EDAC driver version messages This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: Ibcff6b3a006d38aea6197c15524d79c36ba4f8db --- drivers/edac/phytium_edac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/edac/phytium_edac.c b/drivers/edac/phytium_edac.c index af6a729816..49230b89c0 100644 --- a/drivers/edac/phytium_edac.c +++ b/drivers/edac/phytium_edac.c @@ -38,6 +38,8 @@ #define MAX_ERR_GROUP 3 +#define EDAC_DRIVER_VERSION "1.1.1" + struct phytium_edac { struct device *dev; void __iomem **ras_base; @@ -479,3 +481,4 @@ module_platform_driver(phytium_edac_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Huangjie "); +MODULE_VERSION(EDAC_DRIVER_VERSION); -- Gitee From ed1813b757a2dcd21c3d368045caa6143079ed88 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 29 Jul 2024 15:45:33 +0800 Subject: [PATCH 087/121] dma: phytium: Add DDMA driver version messages This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I74a32567793eb19ebb03ecff980454a92fdf32c5 --- drivers/dma/phytium/phytium-ddmac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/phytium/phytium-ddmac.c b/drivers/dma/phytium/phytium-ddmac.c index 768236d994..32de9cccc9 100644 --- a/drivers/dma/phytium/phytium-ddmac.c +++ b/drivers/dma/phytium/phytium-ddmac.c @@ -29,6 +29,7 @@ #include #include "phytium-ddmac.h" +#define DDMA_DRIVER_VERSION "1.1.1" static inline struct phytium_ddma_device *to_ddma_device(struct dma_chan *chan) { return container_of(chan->device, struct phytium_ddma_device, dma_dev); @@ -955,3 +956,4 @@ module_exit(phytium_ddma_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Phytium DDMA Controller platform driver"); MODULE_AUTHOR("Huang Jie "); +MODULE_VERSION(DDMA_DRIVER_VERSION); -- Gitee From 1254ef44ae8b1d59e7378592842291a600f84ece Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 29 Jul 2024 15:48:08 +0800 Subject: [PATCH 088/121] w1: phytium: Add W1 driver version messages This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I1d5be3b657739517e2f8ac8de86095133469fa5b --- drivers/w1/masters/phytium_w1.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/w1/masters/phytium_w1.c b/drivers/w1/masters/phytium_w1.c index 0cb62258da..0d1e5522a5 100644 --- a/drivers/w1/masters/phytium_w1.c +++ b/drivers/w1/masters/phytium_w1.c @@ -56,6 +56,8 @@ #define PHY_W1M_MAX_USER 4 +#define W1_DRIVER_VERSION "1.1.1" + static DECLARE_WAIT_QUEUE_HEAD(w1m_wait_queue); struct w1m_data { @@ -641,3 +643,4 @@ module_platform_driver(phytium_w1m_driver); MODULE_AUTHOR("Zhu Mingshuai "); MODULE_DESCRIPTION("Phytium w1 bus master driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(W1_DRIVER_VERSION); -- Gitee From 6bd949d77e932ae0a6cb0950f56196ec38aebd90 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Mon, 29 Jul 2024 15:32:40 +0800 Subject: [PATCH 089/121] kcs/bt:phytium: Add KCS/BT driver version messages This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Wu Jinyong Signed-off-by: Wang Yinfeng Change-Id: I1e54f67d1504ae6762a2944ae0ca718b33f0d7c3 --- drivers/char/ipmi/bt_bmc_phytium.c | 3 +++ drivers/char/ipmi/kcs_bmc_phytium.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/drivers/char/ipmi/bt_bmc_phytium.c b/drivers/char/ipmi/bt_bmc_phytium.c index 1d4a50c14f..69567e7fe7 100644 --- a/drivers/char/ipmi/bt_bmc_phytium.c +++ b/drivers/char/ipmi/bt_bmc_phytium.c @@ -72,6 +72,8 @@ #define BT_BMC_BUFFER_SIZE 256 +#define BT_BMC_DRIVER_VERSION "1.1.1" + struct bt_bmc { struct device dev; struct miscdevice miscdev; @@ -531,3 +533,4 @@ module_platform_driver(bt_bmc_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cheng Quan "); MODULE_DESCRIPTION("Phytium device interface to the KCS BMC device"); +MODULE_VERSION(KCS_BMC_DRIVER_VERSION); -- Gitee From 5f254bf5798c9d814394cef2faa1b9344c939c0d Mon Sep 17 00:00:00 2001 From: Feng Jun Date: Wed, 31 Jul 2024 17:23:06 +0800 Subject: [PATCH 090/121] uart:phytium: Add UART driver version message This patch add driver version information, which will be used to synchronize and manage driver patches in the future. Mainline: Open-Source Signed-off-by: Feng Jun Signed-off-by: Wang Yinfeng Change-Id: Iafe550db16f95bd1fabb4232d68161c4aed97e7a --- drivers/tty/serial/phytium-uart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/phytium-uart.c b/drivers/tty/serial/phytium-uart.c index c21cf90216..3b80854fa0 100644 --- a/drivers/tty/serial/phytium-uart.c +++ b/drivers/tty/serial/phytium-uart.c @@ -23,7 +23,7 @@ #include #define DRV_NAME "phytium_uart" - +#define PHYT_UART_DRV_VERSION "1.1.0" #define REG_DR 0x00 #define REG_FR 0x18 #define REG_IBRD 0x24 @@ -924,4 +924,5 @@ module_exit(phytium_uart_exit); MODULE_AUTHOR("Chen Baozi "); MODULE_DESCRIPTION("Phytium PCI serial port driver"); +MODULE_VERSION(PHYT_UART_DRV_VERSION); MODULE_LICENSE("GPL"); -- Gitee From 1cfd71147e649f03574ec9c2d8ac624c36dd6a38 Mon Sep 17 00:00:00 2001 From: Peng Min Date: Wed, 24 Jul 2024 10:39:59 +0800 Subject: [PATCH 091/121] nand: phytium: Add NAND driver version description After adding the driver version description, you can use the modinfo command to view the driver version information. Mainline: Open-Source Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng Change-Id: If18de35ca817ea52138cbb693024485ce53932b0 --- drivers/mtd/nand/raw/phytium_nand_pci.c | 2 ++ drivers/mtd/nand/raw/phytium_nand_plat.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/mtd/nand/raw/phytium_nand_pci.c b/drivers/mtd/nand/raw/phytium_nand_pci.c index 62e64adea5..a24a37d6e8 100644 --- a/drivers/mtd/nand/raw/phytium_nand_pci.c +++ b/drivers/mtd/nand/raw/phytium_nand_pci.c @@ -11,6 +11,7 @@ #include "phytium_nand.h" #define DRV_NAME "phytium_nand_pci" +#define DRV_VERSION "1.0.0" static struct mtd_partition partition_info[] = { { @@ -148,3 +149,4 @@ module_pci_driver(phytium_pci_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("PCI driver for Phytium NAND controller"); MODULE_AUTHOR("Zhu Mingshuai "); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/mtd/nand/raw/phytium_nand_plat.c b/drivers/mtd/nand/raw/phytium_nand_plat.c index 411a53a667..5e0bd67c8a 100644 --- a/drivers/mtd/nand/raw/phytium_nand_plat.c +++ b/drivers/mtd/nand/raw/phytium_nand_plat.c @@ -20,6 +20,7 @@ #include "phytium_nand.h" #define DRV_NAME "phytium_nand_plat" +#define DRV_VERSION "1.0.0" static int phytium_nfc_plat_probe(struct platform_device *pdev) { @@ -136,3 +137,4 @@ module_platform_driver(phytium_nfc_plat_driver) MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Phytium NAND controller Platform driver"); MODULE_AUTHOR("Zhu Mingshuai "); +MODULE_VERSION(DRV_VERSION); -- Gitee From 33efee490f31f7d5634a9b0d84fd2a41d9861a5d Mon Sep 17 00:00:00 2001 From: Zhou Yulin Date: Wed, 11 Jan 2023 18:24:15 +0800 Subject: [PATCH 092/121] mtd: rawnand: phytium: Bugfix nand driver memory leak problem Memory allocated by cmd is not released during writing and reading pages. Mainline: Open-Source Signed-off-by: Zhou Yulin Signed-off-by: Wang Yinfeng Change-Id: I2b2fcd561757dd16ba3a6c3737261a2c6da25b31 --- drivers/mtd/nand/raw/phytium_nand.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/phytium_nand.c b/drivers/mtd/nand/raw/phytium_nand.c index 2763455f37..14f7242fec 100644 --- a/drivers/mtd/nand/raw/phytium_nand.c +++ b/drivers/mtd/nand/raw/phytium_nand.c @@ -1271,8 +1271,10 @@ static int phytium_nand_page_read_hwecc(struct mtd_info *mtd, struct nand_chip * cond_delay(nfc_op->cle_ale_delay_ns); ret = phytium_nfc_wait_op(chip, nfc_op->rdy_timeout_ms); - if (ret) + if (ret) { + kfree(nfc_op); return ret; + } cond_delay(nfc_op->rdy_delay_ns * 1000); @@ -1483,6 +1485,7 @@ static int phytium_nand_page_write_hwecc(struct mtd_info *mtd, struct nand_chip cond_delay(nfc_op->rdy_delay_ns * 1000); out: + kfree(nfc_op); return ret; } -- Gitee From 6712a14724afb3a5b8bc155e1aff6fe870496717 Mon Sep 17 00:00:00 2001 From: Peng Min Date: Tue, 14 Jan 2025 15:22:36 +0800 Subject: [PATCH 093/121] nand: phytium: Resolved a call trace warning message in the driver registration times. When the driver is registered, the spin lock is used directly without initialization, resulting in a call trace warning. Mainline: Open-Source Signed-off-by: Peng Min Change-Id: I3d149407670811c6c11e6a2c3f157542751be9b8 --- drivers/mtd/nand/raw/phytium_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/phytium_nand.c b/drivers/mtd/nand/raw/phytium_nand.c index 14f7242fec..efb6064df5 100644 --- a/drivers/mtd/nand/raw/phytium_nand.c +++ b/drivers/mtd/nand/raw/phytium_nand.c @@ -2025,6 +2025,8 @@ int phytium_nand_init(struct phytium_nfc *nfc) nfc->controller.ops = &phytium_nand_controller_ops; INIT_LIST_HEAD(&nfc->chips); + spin_lock_init(&nfc->spinlock); + /* Init the controller and then probe the chips */ ret = phytium_nfc_init(nfc); if (ret) @@ -2034,8 +2036,6 @@ int phytium_nand_init(struct phytium_nfc *nfc) if (ret) goto out; - spin_lock_init(&nfc->spinlock); - out: return ret; } -- Gitee From a1007d57955505812e346ec0df0c3403b97540e0 Mon Sep 17 00:00:00 2001 From: Peng Min Date: Wed, 24 Jul 2024 10:37:41 +0800 Subject: [PATCH 094/121] qspi: phytium: Add QSPI driver version description After adding the driver version description, you can use the modinfo command to view the driver version information. Mainline: Open-Source Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng Change-Id: I841661d0618e736fd5f0f73b94b4e3e9deac84a1 --- drivers/spi/spi-phytium-qspi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-phytium-qspi.c b/drivers/spi/spi-phytium-qspi.c index 4022d565a9..1324573ab8 100644 --- a/drivers/spi/spi-phytium-qspi.c +++ b/drivers/spi/spi-phytium-qspi.c @@ -21,6 +21,7 @@ #include #include +#define DRIVER_VERSION "1.0.0" #define QSPI_FLASH_CAP_REG 0x00 #define QSPI_FLASH_CAP_NUM_SHIFT 3 @@ -841,3 +842,4 @@ module_platform_driver(phytium_qspi_driver); MODULE_AUTHOR("Chen Baozi "); MODULE_DESCRIPTION("Phytium Quad SPI driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRIVER_VERSION); -- Gitee From fa52dbb578c99e1467991c6c20e217e623ca69e8 Mon Sep 17 00:00:00 2001 From: Peng Min Date: Thu, 5 Dec 2024 15:59:07 +0800 Subject: [PATCH 095/121] qspi: phytium: Adapt flash different capacity based on CPU MPIDR For the capacity register, the old controller only supports multiple flash of the same size, while the new QSPI controller supports multiple flash of different size. In this driver, the CPU MPIDR register is used to distinguish different QSPI controller. Mainline: Open-Source Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng Change-Id: I297c2f5127d384c58adf4c878675252057da2e50 --- drivers/spi/spi-phytium-qspi.c | 102 +++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi-phytium-qspi.c b/drivers/spi/spi-phytium-qspi.c index 1324573ab8..836596f127 100644 --- a/drivers/spi/spi-phytium-qspi.c +++ b/drivers/spi/spi-phytium-qspi.c @@ -21,9 +21,14 @@ #include #include -#define DRIVER_VERSION "1.0.0" +#define DRIVER_VERSION "1.0.1" + +#define PHYTIUM_CPU_PART_FTC862 0x862 + +#define MIDR_PHYTIUM_FTC862 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC862) #define QSPI_FLASH_CAP_REG 0x00 +#define QSPI_FLASH_CAP_NUM_SHIFT_NEW 16 #define QSPI_FLASH_CAP_NUM_SHIFT 3 #define QSPI_FLASH_CAP_NUM_MASK (0x3 << QSPI_FLASH_CAP_NUM_SHIFT) #define QSPI_FLASH_CAP_CAP_SHIFT 0 @@ -147,6 +152,7 @@ #define XFER_PROTO_2_2_2 0x5 #define XFER_PROTO_4_4_4 0x6 +#define WR_CFG_NODIR_VALUE 0x5000000 struct phytium_qspi_flash { u32 cs; u32 clk_div; @@ -251,6 +257,44 @@ static int phytium_spi_nor_protocol_encode(const struct spi_mem_op *op, u32 *cod return ret; } +static int phytium_qspi_flash_capacity_encode_new(u32 size, + u32 *cap, int i) +{ + int ret = 0; + + switch (size) { + case SZ_4M: + *cap |= (0x0 >> (4 * i)); + break; + case SZ_8M: + *cap |= (0x1 >> (4 * i)); + break; + case SZ_16M: + *cap |= (0x2 >> (4 * i)); + break; + case SZ_32M: + *cap |= (0x3 >> (4 * i)); + break; + case SZ_64M: + *cap |= (0x4 >> (4 * i)); + break; + case SZ_128M: + *cap |= (0x5 >> (4 * i)); + break; + case SZ_256M: + *cap |= (0x6 >> (4 * i)); + break; + case SZ_512M: + *cap |= (0x7 >> (4 * i)); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + static int phytium_qspi_flash_capacity_encode(u32 size, u32 *cap) { int ret = 0; @@ -623,6 +667,7 @@ static int phytium_qspi_probe(struct platform_device *pdev) struct spi_mem *mem; struct spi_nor *nor; const char **reg_name_array; + bool new_capacity = false; ctrl = spi_alloc_master(dev, sizeof(*qspi)); if (!ctrl) @@ -709,6 +754,11 @@ static int phytium_qspi_probe(struct platform_device *pdev) &phytium_qspi_mem_ops_nodirmap : &phytium_qspi_mem_ops; + if ((read_cpuid_id() & MIDR_CPU_MODEL_MASK) == MIDR_PHYTIUM_FTC862) { + dev_warn(dev, "capacity register(0x00) is the latest design\n"); + new_capacity = true; + } + qspi->dev = dev; platform_set_drvdata(pdev, qspi); @@ -735,25 +785,38 @@ static int phytium_qspi_probe(struct platform_device *pdev) } } } + if (!new_capacity) { + for (i = 1; qspi->fnum > i && i < PHYTIUM_QSPI_MAX_NORCHIP; i++) { + if (qspi->flash[i].size != qspi->flash[0].size) { + dev_err(dev, "Flashes are of different sizes.\n"); + ret = -EINVAL; + goto probe_setup_failed; + } + } - for (i = 1; qspi->fnum > i && i < PHYTIUM_QSPI_MAX_NORCHIP; i++) { - if (qspi->flash[i].size != qspi->flash[0].size) { - dev_err(dev, "Flashes are of different sizes.\n"); - ret = -EINVAL; + ret = phytium_qspi_flash_capacity_encode(qspi->flash[0].size, + &qspi->flash_cap); + if (ret) { + dev_err(dev, "Flash size is invalid.\n"); goto probe_setup_failed; } - } - ret = phytium_qspi_flash_capacity_encode(qspi->flash[0].size, - &qspi->flash_cap); - if (ret) { - dev_err(dev, "Flash size is invalid.\n"); - goto probe_setup_failed; + qspi->flash_cap |= (qspi->fnum - 1) << QSPI_FLASH_CAP_NUM_SHIFT; + } else { + for (i = 0; qspi->fnum > i && i < PHYTIUM_QSPI_MAX_NORCHIP; i++) { + ret = phytium_qspi_flash_capacity_encode_new(qspi->flash[i].size, + &qspi->flash_cap, i); + if (ret) { + dev_err(dev, "Flash size is invalid.\n"); + goto probe_setup_failed; + } + } + qspi->flash_cap |= (qspi->fnum - 1) << QSPI_FLASH_CAP_NUM_SHIFT_NEW; } - qspi->flash_cap |= qspi->fnum << QSPI_FLASH_CAP_NUM_SHIFT; - writel_relaxed(qspi->flash_cap, qspi->io_base + QSPI_FLASH_CAP_REG); + } else { + writel_relaxed(WR_CFG_NODIR_VALUE, qspi->io_base + QSPI_WR_CFG_REG); } return 0; @@ -804,10 +867,15 @@ static int __maybe_unused phytium_qspi_resume(struct device *dev) { struct phytium_qspi *qspi = dev_get_drvdata(dev); - /* set rd_cfg reg, wr_cfg reg and flash_capacity reg after resume */ - writel_relaxed(qspi->rd_cfg_reg, qspi->io_base + QSPI_RD_CFG_REG); - writel_relaxed(qspi->wr_cfg_reg, qspi->io_base + QSPI_WR_CFG_REG); - writel_relaxed(qspi->flash_cap, qspi->io_base + QSPI_FLASH_CAP_REG); + if (!qspi->nodirmap) { + /* set rd_cfg reg and flash_capacity reg after resume */ + writel_relaxed(qspi->rd_cfg_reg, qspi->io_base + QSPI_RD_CFG_REG); + writel_relaxed(qspi->wr_cfg_reg, qspi->io_base + QSPI_WR_CFG_REG); + writel_relaxed(qspi->flash_cap, qspi->io_base + QSPI_FLASH_CAP_REG); + } else { + writel_relaxed(WR_CFG_NODIR_VALUE, qspi->io_base + QSPI_WR_CFG_REG); + } + return pm_runtime_force_resume(dev); } -- Gitee From 83a0bbf4f491284f5b683453d39278b5cbbb5cf3 Mon Sep 17 00:00:00 2001 From: Peng Min Date: Thu, 5 Dec 2024 16:01:05 +0800 Subject: [PATCH 096/121] qspi: phytium: Dynamically get the clock in the ACPI table Originally, the QSPI driver write the controller clock as a fixed value, but now it is modified to obtain dynamically. Mainline: Open-Source Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng Change-Id: Ie119580be596a235df7c84fed2bab648d589f1bb --- drivers/spi/spi-phytium-qspi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-phytium-qspi.c b/drivers/spi/spi-phytium-qspi.c index 836596f127..745f0afc0c 100644 --- a/drivers/spi/spi-phytium-qspi.c +++ b/drivers/spi/spi-phytium-qspi.c @@ -21,7 +21,7 @@ #include #include -#define DRIVER_VERSION "1.0.1" +#define DRIVER_VERSION "1.0.2" #define PHYTIUM_CPU_PART_FTC862 0x862 @@ -153,6 +153,9 @@ #define XFER_PROTO_4_4_4 0x6 #define WR_CFG_NODIR_VALUE 0x5000000 + +#define QSPI_DEFAULT_CLK 500000000 + struct phytium_qspi_flash { u32 cs; u32 clk_div; @@ -668,6 +671,7 @@ static int phytium_qspi_probe(struct platform_device *pdev) struct spi_nor *nor; const char **reg_name_array; bool new_capacity = false; + u32 clk_rate = QSPI_DEFAULT_CLK; ctrl = spi_alloc_master(dev, sizeof(*qspi)); if (!ctrl) @@ -747,7 +751,8 @@ static int phytium_qspi_probe(struct platform_device *pdev) goto probe_clk_failed; } } else if (has_acpi_companion(dev)) { - qspi->clk_rate = 50000000; + fwnode_property_read_u32(dev->fwnode, "spi-clock", &clk_rate); + qspi->clk_rate = clk_rate; } qspi->nodirmap = device_property_present(dev, "no-direct-mapping"); ctrl->mem_ops = qspi->nodirmap ? -- Gitee From 4628f08fa0a321682b8e44163b2b1012e52aebeb Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Fri, 3 Jan 2025 14:59:08 +0800 Subject: [PATCH 097/121] Base_ctrl: phytium: Add driver for base controller This driver provides interface functions for reading and writing base controller address. Mainline: NA Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I963ccac25c7e3500f54ddab7f27e8f6ebd52c55c --- MAINTAINERS | 1 + drivers/acpi/Kconfig | 7 ++ drivers/acpi/Makefile | 1 + drivers/acpi/phytium_base_ctrl.c | 210 +++++++++++++++++++++++++++++++ drivers/acpi/phytium_base_ctrl.h | 27 ++++ 5 files changed, 246 insertions(+) create mode 100644 drivers/acpi/phytium_base_ctrl.c create mode 100644 drivers/acpi/phytium_base_ctrl.h diff --git a/MAINTAINERS b/MAINTAINERS index 44adda4f4b..8d8096d094 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17464,6 +17464,7 @@ F: Documentation/devicetree/bindings/w1/phytium,w1.yaml F: arch/arm64/boot/dts/phytium/* F: arch/arm64/include/asm/ras.h F: arch/arm64/kernel/ras.c +F: drivers/acpi/phytium_base_ctrl.c F: drivers/char/hw_random/phytium-rng.c F: drivers/char/ipmi/bt_bmc_phytium.c F: drivers/char/ipmi/kcs_bmc_phytium.c diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index cee82b473d..48e7d00bac 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -45,6 +45,13 @@ if ACPI config ACPI_LEGACY_TABLES_LOOKUP bool +config PHYTIUM_BASE_CTRL + bool "Phytium base ctrl driver" + default y + help + This driver provides interface functions for reading and + writing phytium base controller device address. + config ARCH_MIGHT_HAVE_ACPI_PDC bool diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index eaa09bf52f..e483aa370c 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -42,6 +42,7 @@ acpi-y += resource.o acpi-y += acpi_processor.o acpi-y += processor_core.o acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o +acpi-$(CONFIG_PHYTIUM_BASE_CTRL) += phytium_base_ctrl.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-$(CONFIG_PCI) += pci_root.o pci_link.o pci_irq.o diff --git a/drivers/acpi/phytium_base_ctrl.c b/drivers/acpi/phytium_base_ctrl.c new file mode 100644 index 0000000000..5ebfd0794a --- /dev/null +++ b/drivers/acpi/phytium_base_ctrl.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * base_ctrl driver for Phytium. + * + * Copyright (C) 2021-2024, Phytium Technology Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "phytium_base_ctrl.h" + +#define BASE_CTRL_DRIVER_VERSION "1.1.0" + +static struct phytium_base_ctrl *boot_base_ctrl; + +int phytium_base_ctrl_irq(void) +{ + if (!boot_base_ctrl) + return -ENODEV; + + return boot_base_ctrl->irq; +} +EXPORT_SYMBOL(phytium_base_ctrl_irq); + +int base_ctrl_read_int_status(void) +{ + unsigned long flags; + u16 value; + + if (!boot_base_ctrl) + return 0; + + spin_lock_irqsave(&boot_base_ctrl->lock, flags); + value = readw(boot_base_ctrl->base + boot_base_ctrl->int_status_reg); + spin_unlock_irqrestore(&boot_base_ctrl->lock, flags); + + return value; +} +EXPORT_SYMBOL(base_ctrl_read_int_status); + +void base_ctrl_write_int_clear(int val) +{ + unsigned long flags; + + if (!boot_base_ctrl) + return; + + spin_lock_irqsave(&boot_base_ctrl->lock, flags); + writew(val, boot_base_ctrl->base + boot_base_ctrl->int_clear_reg); + spin_unlock_irqrestore(&boot_base_ctrl->lock, flags); +} +EXPORT_SYMBOL(base_ctrl_write_int_clear); + +bool phytium_check_cpu(void) +{ +#ifdef CONFIG_ARCH_PHYTIUM + if (read_cpuid_implementor() == ARM_CPU_IMP_PHYTIUM) + return true; +#endif + return false; +} +EXPORT_SYMBOL(phytium_check_cpu); + +u8 base_ctrl_readb(unsigned long offset) +{ + unsigned long flags; + u8 value; + + if (!boot_base_ctrl) + return 1; + + spin_lock_irqsave(&boot_base_ctrl->lock, flags); + value = readb(boot_base_ctrl->base + offset); + spin_unlock_irqrestore(&boot_base_ctrl->lock, flags); + return value; +} +EXPORT_SYMBOL(base_ctrl_readb); + +u32 base_ctrl_readl(unsigned long offset) +{ + unsigned long flags; + u32 value; + + if (!boot_base_ctrl) + return 1; + + spin_lock_irqsave(&boot_base_ctrl->lock, flags); + value = readl(boot_base_ctrl->base + offset); + spin_unlock_irqrestore(&boot_base_ctrl->lock, flags); + + return value; +} +EXPORT_SYMBOL(base_ctrl_readl); + +int base_ctrl_writeb(unsigned long offset, u8 value) +{ + unsigned long flags; + + if (!boot_base_ctrl) + return 0; + + spin_lock_irqsave(&boot_base_ctrl->lock, flags); + writeb(value, boot_base_ctrl->base + offset); + spin_unlock_irqrestore(&boot_base_ctrl->lock, flags); + + return 0; +} +EXPORT_SYMBOL(base_ctrl_writeb); + +int base_ctrl_writel(unsigned long offset, u32 value) +{ + unsigned long flags; + + if (!boot_base_ctrl) + return 0; + + spin_lock_irqsave(&boot_base_ctrl->lock, flags); + writel(value, boot_base_ctrl->base + offset); + spin_unlock_irqrestore(&boot_base_ctrl->lock, flags); + + return 0; +} +EXPORT_SYMBOL(base_ctrl_writel); + +static int phytium_base_ctrl_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct phytium_base_ctrl *base_ctrl; + int error = -1; + + base_ctrl = devm_kzalloc(dev, sizeof(*base_ctrl), GFP_KERNEL); + if (!base_ctrl) + return -ENOMEM; + + base_ctrl->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENOENT; + + base_ctrl->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_ctrl->base)) { + dev_err(&pdev->dev, "region map failed\n"); + return PTR_ERR(base_ctrl->base); + } + + base_ctrl->irq = platform_get_irq(pdev, 0); + if (base_ctrl->irq < 0) { + dev_err(&pdev->dev, "no irq resource?\n"); + return base_ctrl->irq; + } + + error = device_property_read_u32(&pdev->dev, "int_state", + &base_ctrl->int_status_reg); + if (error) + base_ctrl->int_status_reg = base_ctrl_INT_STATE; + + error = device_property_read_u32(&pdev->dev, "clr_int", + &base_ctrl->int_clear_reg); + if (error) + base_ctrl->int_clear_reg = base_ctrl_CLR_INT; + + spin_lock_init(&base_ctrl->lock); + boot_base_ctrl = base_ctrl; + platform_set_drvdata(pdev, base_ctrl); + + return 0; +} + +static const struct acpi_device_id base_ctrl_acpi_match[] = { + { "PHYT0007", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, base_ctrl_acpi_match); + +static struct platform_driver phytium_base_ctrl_driver = { + .probe = phytium_base_ctrl_probe, + .driver = { + .name = "phytium_base_ctrl", + .acpi_match_table = ACPI_PTR(base_ctrl_acpi_match), + }, +}; + +module_platform_driver(phytium_base_ctrl_driver); + +static int __init phytium_base_ctrl_init(void) +{ + platform_driver_register(&phytium_base_ctrl_driver); + return 0; +} + +static void __exit phytium_base_ctrl_exit(void) +{ + platform_driver_unregister(&phytium_base_ctrl_driver); +} + +early_initcall(phytium_base_ctrl_init); +MODULE_AUTHOR("Li Yuze "); +MODULE_DESCRIPTION("Phytium base_ctrl driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(BASE_CTRL_DRIVER_VERSION); diff --git a/drivers/acpi/phytium_base_ctrl.h b/drivers/acpi/phytium_base_ctrl.h new file mode 100644 index 0000000000..017f21e5ac --- /dev/null +++ b/drivers/acpi/phytium_base_ctrl.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * acpi/phytium_base_ctrl.h + * + * Copyright (C) 2021-2024, Phytium Technology Co., Ltd. + */ + +#define base_ctrl_INT_STATE 0x7FFFFC4 +#define base_ctrl_CLR_INT 0x7FFFFC0 + +struct phytium_base_ctrl { + struct device *dev; + void __iomem *base; + int irq; + spinlock_t lock; + u32 int_status_reg; + u32 int_clear_reg; +}; + +int phytium_base_ctrl_irq(void); +u8 base_ctrl_readb(unsigned long offset); +u32 base_ctrl_readl(unsigned long offset); +bool phytium_check_cpu(void); +int base_ctrl_writeb(unsigned long offset, u8 value); +int base_ctrl_writel(unsigned long offset, u32 value); +int base_ctrl_read_int_status(void); +void base_ctrl_write_int_clear(int val); -- Gitee From 036f49667f1b3f3e9b272a9f8425df0aa15c3dd7 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Fri, 3 Jan 2025 15:18:53 +0800 Subject: [PATCH 098/121] i8042: Add support for phytium platforms Add phytium platforms support for the basis of native i8042 driver. Mainline: NA Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I1ef4f3cc3340e076793964aa22eb9e68b6bb2f69 --- drivers/input/serio/i8042-io.h | 24 +++++++++++++++---- drivers/input/serio/i8042.c | 43 +++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index 64590b86eb..8dfb23df58 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h @@ -2,7 +2,9 @@ #ifndef _I8042_IO_H #define _I8042_IO_H - +#ifdef CONFIG_ARCH_PHYTIUM +#include "../../acpi/phytium_base_ctrl.h" +#endif /* * Names. */ @@ -42,22 +44,34 @@ extern int of_i8042_aux_irq; static inline int i8042_read_data(void) { - return inb(I8042_DATA_REG); + if (phytium_check_cpu() == true) + return base_ctrl_readb(I8042_DATA_REG); + else + return inb(I8042_DATA_REG); } static inline int i8042_read_status(void) { - return inb(I8042_STATUS_REG); + if (phytium_check_cpu() == true) + return base_ctrl_readb(I8042_STATUS_REG); + else + return inb(I8042_STATUS_REG); } static inline void i8042_write_data(int val) { - outb(val, I8042_DATA_REG); + if (phytium_check_cpu() == true) + base_ctrl_writeb(I8042_DATA_REG, val); + else + outb(val, I8042_DATA_REG); } static inline void i8042_write_command(int val) { - outb(val, I8042_COMMAND_REG); + if (phytium_check_cpu() == true) + base_ctrl_writeb(I8042_COMMAND_REG, val); + else + outb(val, I8042_COMMAND_REG); } static inline int i8042_platform_init(void) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 29340f8095..a821c241d2 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -536,6 +536,9 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) spin_lock_irqsave(&i8042_lock, flags); + if (phytium_check_cpu() == true) + base_ctrl_write_int_clear(0x0); + str = i8042_read_status(); if (unlikely(~str & I8042_STR_OBF)) { spin_unlock_irqrestore(&i8042_lock, flags); @@ -1457,7 +1460,7 @@ static int i8042_setup_aux(void) int error; int i; - if (i8042_check_aux()) + if (!phytium_check_cpu() && i8042_check_aux()) return -ENODEV; if (i8042_nomux || i8042_check_mux()) { @@ -1474,10 +1477,12 @@ static int i8042_setup_aux(void) aux_enable = i8042_enable_mux_ports; } - error = request_irq(I8042_AUX_IRQ, i8042_interrupt, IRQF_SHARED, - "i8042", i8042_platform_device); - if (error) - goto err_free_ports; + if (!phytium_check_cpu()) { + error = request_irq(I8042_AUX_IRQ, i8042_interrupt, IRQF_SHARED, + "i8042", i8042_platform_device); + if (error) + goto err_free_ports; + } error = aux_enable(); if (error) @@ -1501,8 +1506,17 @@ static int i8042_setup_kbd(void) if (error) return error; - error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, - "i8042", i8042_platform_device); + if (phytium_check_cpu() == true) { + error = phytium_base_ctrl_irq(); + if (error < 0) + goto err_free_port; + + error = devm_request_irq(&i8042_platform_device->dev, error, + i8042_interrupt, IRQF_SHARED, "i8042", i8042_platform_device); + } else { + error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, + "i8042", i8042_platform_device); + } if (error) goto err_free_port; @@ -1619,14 +1633,15 @@ static int __init i8042_init(void) dbg_init(); - err = i8042_platform_init(); - if (err) - return (err == -ENODEV) ? 0 : err; - - err = i8042_controller_check(); - if (err) - goto err_platform_exit; + if (!phytium_check_cpu()) { + err = i8042_platform_init(); + if (err) + return (err == -ENODEV) ? 0 : err; + err = i8042_controller_check(); + if (err) + goto err_platform_exit; + } /* Set this before creating the dev to allow i8042_command to work right away */ i8042_present = true; -- Gitee From 316b59f6dffb8dc400c7ccc59d71df803520a323 Mon Sep 17 00:00:00 2001 From: Li Mingzhe Date: Thu, 20 Feb 2025 11:36:44 +0800 Subject: [PATCH 099/121] devfreq: Add phytium noc devfreq driver. This adds the DEVFREQ driver for Phytium Net On Chip.It adjusts frequency for noc based on load bandwidth obtained from register. Signed-off-by: Li Jiayi Signed-off-by: Li Mingzhe Signed-off-by: Wang Yinfeng Change-Id: Ie83996177f382ab5321d72724c2fcdc255a71af8 --- MAINTAINERS | 1 + drivers/devfreq/Kconfig | 9 + drivers/devfreq/Makefile | 1 + drivers/devfreq/phytium_noc.c | 439 ++++++++++++++++++++++++++++++++++ 4 files changed, 450 insertions(+) create mode 100644 drivers/devfreq/phytium_noc.c diff --git a/MAINTAINERS b/MAINTAINERS index 8d8096d094..7a8918d140 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17468,6 +17468,7 @@ F: drivers/acpi/phytium_base_ctrl.c F: drivers/char/hw_random/phytium-rng.c F: drivers/char/ipmi/bt_bmc_phytium.c F: drivers/char/ipmi/kcs_bmc_phytium.c +F: drivers/devfreq/phytium_noc.c F: drivers/dma/phytium/phytium* F: drivers/edac/phytium_edac.c F: drivers/gpio/gpio-phytium* diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 3c4862a752..858893f41f 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -150,6 +150,15 @@ config ARM_SUN8I_A33_MBUS_DEVFREQ This adds the DEVFREQ driver for the MBUS controller in some Allwinner sun8i (A33 through H3) and sun50i (A64 and H5) SoCs. +config ARM_PHYTIUM_NOC_DEVFREQ + tristate "ARM PHYTIUM NOC DEVFREQ Driver" + depends on ARCH_PHYTIUM || COMPILE_TEST + depends on ACPI + select DEVFREQ_GOV_SIMPLE_ONDEMAND + help + This adds the DEVFREQ driver for Phytium Net On Chip. + It adjusts frequency for noc based on load bandwidth obtained from register. + source "drivers/devfreq/event/Kconfig" endif # PM_DEVFREQ diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index bf40d04928..5d6275c0f8 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o obj-$(CONFIG_ARM_MEDIATEK_CCI_DEVFREQ) += mtk-cci-devfreq.o +obj-$(CONFIG_ARM_PHYTIUM_NOC_DEVFREQ) += phytium_noc.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_SUN8I_A33_MBUS_DEVFREQ) += sun8i-a33-mbus.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o diff --git a/drivers/devfreq/phytium_noc.c b/drivers/devfreq/phytium_noc.c new file mode 100644 index 0000000000..9658d95061 --- /dev/null +++ b/drivers/devfreq/phytium_noc.c @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + *phytium_noc.c - Phytium Processor noc Frequency Driver + * + *Copyright (C) 2024,Phytium Technology Co.,Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MINI_SIZE 0x400 +#define CNT_ENABLE 0x000 +#define WORK_STATE 0X004 +#define CLR_EN 0X010 +#define SNAPSHOT_EN 0X014 +#define INT_CTRL_CLR 0x024 +#define WR_NOLAST_HANDSHARK_NUM 0x44 + +#define DEBUG +#define DEVICE_TYPE 7 + +#define NOCFREQ_DRIVER_VERSION "1.0.0" + +struct phytium_nocfreq { + struct device *dev; + + struct devfreq *devfreq; + struct devfreq_dev_profile profile; + struct devfreq_simple_ondemand_data ondemand_data; + + void __iomem *reg_noc; + struct mutex lock; + + unsigned long rate, target_rate; + unsigned int freq_count; + unsigned long freq_table[]; +}; + +static u32 phytium_nocfreq_get_peak_bw(struct phytium_nocfreq *priv) +{ + /*Returns the peak number of dmu read/write commands on the axi bus.*/ + unsigned long peak_bw, bw_0, bw_1, bw_2, bw_3; + + bw_0 = readl_relaxed(priv->reg_noc + WR_NOLAST_HANDSHARK_NUM); + bw_1 = readl_relaxed(priv->reg_noc + MINI_SIZE*1 + WR_NOLAST_HANDSHARK_NUM); + bw_2 = readl_relaxed(priv->reg_noc + MINI_SIZE*2 + WR_NOLAST_HANDSHARK_NUM); + bw_3 = readl_relaxed(priv->reg_noc + MINI_SIZE*3 + WR_NOLAST_HANDSHARK_NUM); + + peak_bw = bw_0; + if (bw_1 > peak_bw) + peak_bw = bw_1; + if (bw_2 > peak_bw) + peak_bw = bw_2; + if (bw_3 > peak_bw) + peak_bw = bw_3; + + return peak_bw; +} + +static void phytium_nocfreq_restart_handshark_counters(struct phytium_nocfreq *priv) +{ + + /*clear interrupt*/ + + writel_relaxed(0x80000000, priv->reg_noc + INT_CTRL_CLR); + writel_relaxed(0x80000000, priv->reg_noc + MINI_SIZE*1 + INT_CTRL_CLR); + writel_relaxed(0x80000000, priv->reg_noc + MINI_SIZE*2 + INT_CTRL_CLR); + writel_relaxed(0x80000000, priv->reg_noc + MINI_SIZE*3 + INT_CTRL_CLR); + + /*clear counters*/ + writel_relaxed(0x1, priv->reg_noc + CLR_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*1 + CLR_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*2 + CLR_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*3 + CLR_EN); +} + + +static int phytium_noc_set_freq(struct device *dev, unsigned long freq) +{ + struct phytium_nocfreq *priv = dev_get_drvdata(dev); + acpi_handle handle = ACPI_HANDLE(dev); + union acpi_object args[4]; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_status status; + unsigned long long ret; + + args[0].type = ACPI_TYPE_INTEGER; + args[0].integer.value = DEVICE_TYPE; + args[1].type = ACPI_TYPE_INTEGER; + args[1].integer.value = freq; + args[2].type = ACPI_TYPE_INTEGER; + args[2].integer.value = 0; + args[3].type = ACPI_TYPE_INTEGER; + args[3].integer.value = 0; + + mutex_lock(&priv->lock); + status = acpi_evaluate_integer(handle, "PSCF", &arg_list, &ret); + mutex_unlock(&priv->lock); + + if (ACPI_FAILURE(status)) { + dev_err(dev, "No PSCF method\n"); + return -EIO; + } + + if (ret) { + dev_err(dev, "Failed to set the freq to %lu\n", freq); + return -EIO; + } + dev_dbg(dev, "set target_freq = %lu khz\n", freq); + return 0; +} + +static int phytium_noc_target(struct device *dev, unsigned long *freq, u32 flags) +{ + struct phytium_nocfreq *priv = dev_get_drvdata(dev); + unsigned long old_freq = priv->rate; + unsigned long target_rate; + struct dev_pm_opp *opp; + int ret; + + opp = devfreq_recommended_opp(dev, freq, flags); + if (IS_ERR(opp)) + return PTR_ERR(opp); + + target_rate = dev_pm_opp_get_freq(opp); + dev_pm_opp_put(opp); + + if (target_rate == old_freq) + return 0; + /* + * Read back the clk rate to verify switch was correct and so that + * we can report it on all error paths. + */ + ret = phytium_noc_set_freq(dev, target_rate); + + if (ret) { + dev_warn(dev, "failed to set noc frequency: %d\n", ret); + *freq = old_freq; + } + priv->rate = target_rate; + return ret; + +} + +static int phytium_noc_get_cur_freq(struct device *dev, unsigned long *freq) +{ + struct phytium_nocfreq *priv = dev_get_drvdata(dev); + acpi_handle handle = ACPI_HANDLE(dev); + union acpi_object args[3]; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_status status; + unsigned long long ret; + + args[0].type = ACPI_TYPE_INTEGER; + args[0].integer.value = DEVICE_TYPE; + args[1].type = ACPI_TYPE_INTEGER; + args[1].integer.value = 0; + args[2].type = ACPI_TYPE_INTEGER; + args[2].integer.value = 0; + + mutex_lock(&priv->lock); + status = acpi_evaluate_integer(handle, "PGCF", &arg_list, &ret); + mutex_unlock(&priv->lock); + if (ACPI_FAILURE(status)) { + dev_err(dev, "No PGCF method\n"); + return -EIO; + } + + if (ret < 0) { + dev_err(dev, "Failed to get the freq\n"); + return -EIO; + } + *freq = ret; + + return 0; +} + +static int phytium_noc_get_freq_info(struct device *dev, u32 flags) +{ + struct phytium_nocfreq *priv = dev_get_drvdata(dev); + + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object args[3], *package, *element; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_status status; + int i; + + args[0].type = ACPI_TYPE_INTEGER; + args[0].integer.value = flags; + args[1].type = ACPI_TYPE_INTEGER; + args[1].integer.value = 0; + args[2].type = ACPI_TYPE_INTEGER; + args[2].integer.value = 0; + + status = acpi_evaluate_object(handle, "PGCL", &arg_list, &buffer); + if (ACPI_FAILURE(status)) { + dev_err(dev, "No PGCL method\n"); + return -EIO; + } + if (!buffer.length) { + dev_err(dev, "buffer is NULL\n"); + return -EINVAL; + } + + package = buffer.pointer; + + element = &package->package.elements[1]; + priv->freq_count = element->integer.value; + + for (i = 0; i < priv->freq_count; i++) { + element = &package->package.elements[i+2]; + priv->freq_table[i] = element->integer.value; + dev_dbg(dev, "freq_table[%d] = %llu\n", i, element->integer.value); + } + + return 0; + +} + +static int get_freq_count(struct device *dev) +{ + int freq_count = -1; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object args[3], *package, *element; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_status status; + + args[0].type = ACPI_TYPE_INTEGER; + args[0].integer.value = DEVICE_TYPE; + args[1].type = ACPI_TYPE_INTEGER; + args[1].integer.value = 0; + args[2].type = ACPI_TYPE_INTEGER; + args[2].integer.value = 0; + + status = acpi_evaluate_object(handle, "PGCL", &arg_list, &buffer); + if (ACPI_FAILURE(status)) { + dev_err(dev, "No PGCL method\n"); + return -EIO; + } + if (!buffer.length) { + dev_err(dev, "buffer is NULL\n"); + return -EINVAL; + } + + package = buffer.pointer; + + element = &package->package.elements[1]; + freq_count = element->integer.value; + dev_dbg(dev, "freq_count = %d\n", freq_count); + + return freq_count; +} + +static int phytium_noc_get_dev_status(struct device *dev, + struct devfreq_dev_status *stat) +{ + struct phytium_nocfreq *priv = dev_get_drvdata(dev); + unsigned int val; + + writel_relaxed(0x1, priv->reg_noc + SNAPSHOT_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*1 + SNAPSHOT_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*2 + SNAPSHOT_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*3 + SNAPSHOT_EN); + + val = DIV_ROUND_CLOSEST(priv->rate * 100, priv->profile.initial_freq); + stat->busy_time = phytium_nocfreq_get_peak_bw(priv); + stat->total_time = 320000 * val; + stat->current_frequency = priv->rate; + + phytium_nocfreq_restart_handshark_counters(priv); + dev_dbg(dev, "Using %lu/%lu (%lu%%) at %lu KHz\n", + stat->busy_time, stat->total_time, + DIV_ROUND_CLOSEST(stat->busy_time * 100, stat->total_time), + stat->current_frequency); + + return 0; +} + + +static int phytium_nocfreq_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct phytium_nocfreq *priv; + const char *gov = DEVFREQ_GOV_SIMPLE_ONDEMAND; + int i, ret; + unsigned int max_state; + struct resource *mem; + + max_state = get_freq_count(dev); + dev->init_name = "nocfreq"; + + priv = devm_kzalloc(dev, struct_size(priv, freq_table, max_state), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mutex_init(&priv->lock); + platform_set_drvdata(pdev, priv); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(&pdev->dev, "no mem resource"); + return -EINVAL; + } + + priv->reg_noc = devm_ioremap_resource(&pdev->dev, mem); + if (!priv->reg_noc) { + dev_err(dev, "NOC region map failed\n"); + return PTR_ERR(priv->reg_noc); + } + + ret = phytium_noc_get_freq_info(dev, DEVICE_TYPE); + if (ret) { + dev_err(dev, "failed to get noc frequency info\n"); + return -EIO; + } + + priv->profile.initial_freq = priv->freq_table[0]; + priv->profile.polling_ms = 100; + priv->profile.target = phytium_noc_target; + priv->profile.get_cur_freq = phytium_noc_get_cur_freq; + priv->profile.get_dev_status = phytium_noc_get_dev_status; + priv->profile.freq_table = priv->freq_table; + priv->profile.max_state = priv->freq_count; + priv->rate = priv->freq_table[0]; + priv->ondemand_data.upthreshold = 80; + priv->ondemand_data.downdifferential = 10; + priv->profile.max_state = priv->freq_count; + + for (i = 0; i < max_state; ++i) { + ret = dev_pm_opp_add(dev, priv->freq_table[i], 0); + if (ret < 0) { + dev_err(dev, "failed to get OPP table\n"); + goto err; + } + } + priv->devfreq = devm_devfreq_add_device(dev, &priv->profile, + gov, &priv->ondemand_data); + if (IS_ERR(priv->devfreq)) { + ret = PTR_ERR(priv->devfreq); + dev_err(dev, "failed to add devfreq device: %d\n", ret); + goto err; + } + + ret = phytium_noc_set_freq(dev, priv->profile.initial_freq); + if (ret) + dev_warn(dev, "failed to init noc frequency: %d\n", ret); + + writel_relaxed(0x02, priv->reg_noc + WORK_STATE); + writel_relaxed(0x02, priv->reg_noc + MINI_SIZE*1 + WORK_STATE); + writel_relaxed(0x02, priv->reg_noc + MINI_SIZE*2 + WORK_STATE); + writel_relaxed(0x02, priv->reg_noc + MINI_SIZE*3 + WORK_STATE); + + writel_relaxed(0x3f, priv->reg_noc + CNT_ENABLE); + writel_relaxed(0x3f, priv->reg_noc + MINI_SIZE*1 + CNT_ENABLE); + writel_relaxed(0x3f, priv->reg_noc + MINI_SIZE*2 + CNT_ENABLE); + writel_relaxed(0x3f, priv->reg_noc + MINI_SIZE*3 + CNT_ENABLE); + return 0; + +err: + dev_pm_opp_of_remove_table(dev); + kfree(priv); + return ret; +} + +static int phytium_nocfreq_remove(struct platform_device *pdev) +{ + struct phytium_nocfreq *priv = platform_get_drvdata(pdev); + unsigned long initial_freq = priv->profile.initial_freq; + struct device *dev = &pdev->dev; + int ret; + + writel_relaxed(0x0, priv->reg_noc + CNT_ENABLE); + writel_relaxed(0x0, priv->reg_noc + MINI_SIZE*1 + CNT_ENABLE); + writel_relaxed(0x0, priv->reg_noc + MINI_SIZE*2 + CNT_ENABLE); + writel_relaxed(0x0, priv->reg_noc + MINI_SIZE*3 + CNT_ENABLE); + + writel_relaxed(0x1, priv->reg_noc + CLR_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*1 + CLR_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*2 + CLR_EN); + writel_relaxed(0x1, priv->reg_noc + MINI_SIZE*3 + CLR_EN); + + ret = phytium_noc_set_freq(dev, initial_freq); + if (ret) + dev_warn(dev, "failed to restore NOC frequency: %d\n", ret); + + iounmap(priv->reg_noc); + + if (!priv->devfreq) + return 0; + + dev_pm_opp_remove_all_dynamic(dev); + kfree(priv); + + return 0; +} + +static const struct acpi_device_id phytium_noc_acpi_ids[] = { + {"PHYT0047"}, + {}, +}; + +MODULE_DEVICE_TABLE(acpi, phytium_noc_acpi_ids); + +static struct platform_driver phytium_nocfreq_driver = { + .probe = phytium_nocfreq_probe, + .remove = phytium_nocfreq_remove, + .driver = { + .name = "phytium_nocfreq", + .acpi_match_table = ACPI_PTR(phytium_noc_acpi_ids), + .suppress_bind_attrs = true, + }, +}; +module_platform_driver(phytium_nocfreq_driver); + +MODULE_DESCRIPTION("Phytium NOC Controller frequency driver"); +MODULE_AUTHOR("Li Jiayi "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(NOCFREQ_DRIVER_VERSION); -- Gitee From 17f4d0f55ac396d39b0948ee72a23c11e10d006f Mon Sep 17 00:00:00 2001 From: Li Mingzhe Date: Thu, 20 Feb 2025 11:36:44 +0800 Subject: [PATCH 100/121] devfreq: Add phytium dmu devfreq driver This adds the DEVFREQ driver for Phytium DDR Memory Unit.It adjusts frequency for dmu based on load bandwidth obtained from register. Signed-off-by: Li Jiayi Signed-off-by: Li Mingzhe Signed-off-by: Wang Yinfeng Change-Id: I2d867ea3fcfb9d66dad0824e36cb5964b6c0f058 --- MAINTAINERS | 1 + drivers/devfreq/Kconfig | 9 + drivers/devfreq/Makefile | 1 + drivers/devfreq/phytium_dmu.c | 373 ++++++++++++++++++++++++++++++++++ 4 files changed, 384 insertions(+) create mode 100644 drivers/devfreq/phytium_dmu.c diff --git a/MAINTAINERS b/MAINTAINERS index 7a8918d140..edc6fc3c5f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17468,6 +17468,7 @@ F: drivers/acpi/phytium_base_ctrl.c F: drivers/char/hw_random/phytium-rng.c F: drivers/char/ipmi/bt_bmc_phytium.c F: drivers/char/ipmi/kcs_bmc_phytium.c +F: drivers/devfreq/phytium_dmu.c F: drivers/devfreq/phytium_noc.c F: drivers/dma/phytium/phytium* F: drivers/edac/phytium_edac.c diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 858893f41f..c90e8fa9d7 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -159,6 +159,15 @@ config ARM_PHYTIUM_NOC_DEVFREQ This adds the DEVFREQ driver for Phytium Net On Chip. It adjusts frequency for noc based on load bandwidth obtained from register. +config ARM_PHYTIUM_DMU_DEVFREQ + tristate "ARM PHYTIUM DMU DEVFREQ Driver" + depends on ARCH_PHYTIUM || COMPILE_TEST + depends on ACPI + select DEVFREQ_GOV_SIMPLE_ONDEMAND + help + This adds the DEVFREQ driver for Phytium DDR Memory Unit. + It adjusts frequency for dmu based on load bandwidth obtained from register. + source "drivers/devfreq/event/Kconfig" endif # PM_DEVFREQ diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index 5d6275c0f8..c57455f9b4 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o obj-$(CONFIG_ARM_MEDIATEK_CCI_DEVFREQ) += mtk-cci-devfreq.o +obj-$(CONFIG_ARM_PHYTIUM_DMU_DEVFREQ) += phytium_dmu.o obj-$(CONFIG_ARM_PHYTIUM_NOC_DEVFREQ) += phytium_noc.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_SUN8I_A33_MBUS_DEVFREQ) += sun8i-a33-mbus.o diff --git a/drivers/devfreq/phytium_dmu.c b/drivers/devfreq/phytium_dmu.c new file mode 100644 index 0000000000..1fc23b4869 --- /dev/null +++ b/drivers/devfreq/phytium_dmu.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + *phytium_dmu.c - Phytium Processor dmu Frequency Driver + * + *Copyright (C) 2024,Phytium Technology Co.,Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +#define DEVICE_TYPE 9 //DMU ID + +#define UPDATE_INTERVAL_MS 10 + +#define DMUFREQ_DRIVER_VERSION "1.0.0" + +struct phytium_dmufreq { + struct device *dev; + + struct devfreq *devfreq; + struct devfreq_dev_profile profile; + struct devfreq_simple_ondemand_data ondemand_data; + + unsigned long rate, target_rate; + unsigned long bandwidth; + + struct timer_list sampling; + struct work_struct work; + + unsigned int freq_count; + unsigned long freq_table[]; +}; + +static ktime_t stop; + +static int phytium_dmu_set_freq(struct device *dev, unsigned long freq) +{ + acpi_handle handle = ACPI_HANDLE(dev); + union acpi_object args[4]; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_status status; + unsigned long long ret; + + args[0].type = ACPI_TYPE_INTEGER; + args[0].integer.value = DEVICE_TYPE; + args[1].type = ACPI_TYPE_INTEGER; + args[1].integer.value = freq; + args[2].type = ACPI_TYPE_INTEGER; + args[2].integer.value = 0; + args[3].type = ACPI_TYPE_INTEGER; + args[3].integer.value = 0; + + status = acpi_evaluate_integer(handle, "PSCF", &arg_list, &ret); + if (ACPI_FAILURE(status)) { + dev_err(dev, "No PSCF method\n"); + return -EIO; + } + + return 0; +} + +static int phytium_dmu_target(struct device *dev, unsigned long *freq, u32 flags) +{ + struct phytium_dmufreq *priv = dev_get_drvdata(dev); + unsigned long old_freq = priv->rate; + unsigned long target_rate; + struct dev_pm_opp *opp; + int ret; + + opp = devfreq_recommended_opp(dev, freq, flags); + if (IS_ERR(opp)) + return PTR_ERR(opp); + + target_rate = dev_pm_opp_get_freq(opp); + + dev_pm_opp_put(opp); + + if (target_rate == old_freq) + return 0; + + dev_dbg(dev, "target_rate = %lu\n", target_rate); + /* + * Read back the clk rate to verify switch was correct and so that + * we can report it on all error paths. + */ + ret = phytium_dmu_set_freq(dev, target_rate); + if (ret) { + dev_warn(dev, "failed to set DRAM frequency: %lu\n", target_rate); + return ret; + } + priv->rate = target_rate; + + return ret; + +} + +static int phytium_dmu_get_cur_freq(struct device *dev, unsigned long *freq) +{ + struct phytium_dmufreq *priv = dev_get_drvdata(dev); + + *freq = priv->rate; + + return 0; +} + +static int phytium_read_perf_counter(struct device *dev) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *package, *elements; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_status status; + + status = acpi_evaluate_object(handle, "PDMU", NULL, &buffer); + if (ACPI_FAILURE(status)) { + dev_err(dev, "No PDMU method\n"); + return -EIO; + } + + package = buffer.pointer; + + elements = package->package.elements; + + return elements[0].integer.value + elements[1].integer.value; +} + +static void sampling_timer_callback(struct timer_list *t) +{ + struct phytium_dmufreq *priv = from_timer(priv, t, sampling); + + schedule_work(&priv->work); +} + +static void sampling_work_handle(struct work_struct *work) +{ + struct phytium_dmufreq *priv = container_of(work, struct phytium_dmufreq, work); + struct device *dev = priv->dev; + static unsigned long load_counter; + static int count; + unsigned long current_load; + + current_load = phytium_read_perf_counter(dev); + + load_counter += current_load; + count += 1; + + if (ktime_after(ktime_get(), stop)) { + priv->bandwidth = (load_counter / count) / 2; + load_counter = 0; + count = 0; + stop = ktime_add_ms(ktime_get(), priv->profile.polling_ms); + mod_timer(&priv->sampling, jiffies + msecs_to_jiffies(UPDATE_INTERVAL_MS)); + } else + mod_timer(&priv->sampling, jiffies + msecs_to_jiffies(UPDATE_INTERVAL_MS)); +} + +static int phytium_dmu_get_dev_status(struct device *dev, + struct devfreq_dev_status *stat) +{ + struct phytium_dmufreq *priv = dev_get_drvdata(dev); + + stat->busy_time = priv->bandwidth; + stat->total_time = (75000000 * priv->rate) / priv->freq_table[0]; + dev_dbg(dev, "busy_time = %lu, total_time = %lu\n", + stat->busy_time, stat->total_time); + + stat->current_frequency = priv->rate; + + return 0; +} + +static int phytium_dmu_get_freq_info(struct device *dev) +{ + struct phytium_dmufreq *priv = dev_get_drvdata(dev); + + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object args[3], *package, *element; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_status status; + int i; + + args[0].type = ACPI_TYPE_INTEGER; + args[0].integer.value = DEVICE_TYPE; + args[1].type = ACPI_TYPE_INTEGER; + args[1].integer.value = 0; + args[2].type = ACPI_TYPE_INTEGER; + args[2].integer.value = 0; + + status = acpi_evaluate_object(handle, "PGCL", &arg_list, &buffer); + if (ACPI_FAILURE(status)) { + dev_err(dev, "No PGCL method\n"); + return -EIO; + } + + package = buffer.pointer; + + element = &package->package.elements[1]; + priv->freq_count = element->integer.value; + + for (i = 0; i < priv->freq_count; i++) { + element = &package->package.elements[i+2]; + priv->freq_table[i] = element->integer.value; + dev_dbg(dev, "freq_table[%d] = %llu\n", i, element->integer.value); + } + + return 0; + +} + +static int get_freq_count(struct device *dev) +{ + int freq_count = -1; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object args[3], *package, *element; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_status status; + + args[0].type = ACPI_TYPE_INTEGER; + args[0].integer.value = DEVICE_TYPE; + args[1].type = ACPI_TYPE_INTEGER; + args[1].integer.value = 0; + args[2].type = ACPI_TYPE_INTEGER; + args[2].integer.value = 0; + + status = acpi_evaluate_object(handle, "PGCL", &arg_list, &buffer); + if (ACPI_FAILURE(status)) { + dev_err(dev, "No PGCL method, status = %d\n", status); + return -EIO; + } + + package = buffer.pointer; + + element = &package->package.elements[1]; + freq_count = element->integer.value; + dev_dbg(dev, "freq_count = %d\n", freq_count); + + return freq_count; +} + +static int phytium_dmufreq_probe(struct platform_device *pdev) +{ + struct phytium_dmufreq *priv; + struct device *dev = &pdev->dev; + const char *gov = DEVFREQ_GOV_SIMPLE_ONDEMAND; + int i, ret; + unsigned int max_state = get_freq_count(dev); + + if (max_state <= 0) + return max_state; + + dev->init_name = "dmufreq"; + + priv = kzalloc(sizeof(struct phytium_dmufreq) + + max_state * sizeof(unsigned long), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + ret = phytium_dmu_get_freq_info(dev); + if (ret) { + dev_err(dev, "failed to get ddr frequency info\n"); + return -EIO; + } + + priv->profile.initial_freq = priv->freq_table[0]; + priv->profile.polling_ms = 100; + priv->profile.timer = DEVFREQ_TIMER_DELAYED; + priv->profile.target = phytium_dmu_target; + priv->profile.get_cur_freq = phytium_dmu_get_cur_freq; + priv->profile.get_dev_status = phytium_dmu_get_dev_status; + priv->profile.freq_table = priv->freq_table; + priv->rate = priv->profile.initial_freq; + priv->profile.max_state = priv->freq_count; + priv->ondemand_data.upthreshold = 80; + priv->ondemand_data.downdifferential = 10; + + for (i = 0; i < max_state; ++i) { + ret = dev_pm_opp_add(dev, priv->freq_table[i], 0); + if (ret < 0) { + dev_err(dev, "failed to get OPP table\n"); + goto err; + } + } + + priv->devfreq = devm_devfreq_add_device(dev, &priv->profile, + gov, &priv->ondemand_data); + if (IS_ERR(priv->devfreq)) { + ret = PTR_ERR(priv->devfreq); + dev_err(dev, "failed to add devfreq device: %d\n", ret); + goto err; + } + + INIT_WORK(&priv->work, sampling_work_handle); + timer_setup(&priv->sampling, sampling_timer_callback, 0); + stop = ktime_add_ms(ktime_get(), priv->profile.polling_ms); + mod_timer(&priv->sampling, jiffies + msecs_to_jiffies(UPDATE_INTERVAL_MS)); + + priv->dev = dev; + + return 0; + +err: + dev_pm_opp_of_remove_table(dev); + kfree(priv); + return ret; +} + +static int phytium_dmufreq_remove(struct platform_device *pdev) +{ + struct phytium_dmufreq *priv = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + + if (!priv->devfreq) + return 0; + flush_work(&priv->work); + del_timer_sync(&priv->sampling); + dev_pm_opp_remove_all_dynamic(dev); + + kfree(priv); + + return 0; +} + +#ifdef CONFIG_ACPI +static const struct acpi_device_id phytium_dmufreq_acpi_ids[] = { + {"PHYT0063"}, + {}, +}; + +MODULE_DEVICE_TABLE(acpi, phytium_dmufreq_acpi_ids); +#else +#define phytium_dmu_acpi_ids NULL +#endif + +static struct platform_driver phytium_dmufreq_driver = { + .probe = phytium_dmufreq_probe, + .remove = phytium_dmufreq_remove, + .driver = { + .name = "phytium_dmufreq", + .acpi_match_table = ACPI_PTR(phytium_dmufreq_acpi_ids), + .suppress_bind_attrs = true, + }, +}; +module_platform_driver(phytium_dmufreq_driver); + +MODULE_DESCRIPTION("Phytium DDR Memory Unit frequency driver"); +MODULE_AUTHOR("Li Jiayi "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DMUFREQ_DRIVER_VERSION); -- Gitee From 7745dac4ea406298b0f711e1b84de25c0d568f51 Mon Sep 17 00:00:00 2001 From: Li Jiayi Date: Wed, 4 Dec 2024 09:00:16 +0800 Subject: [PATCH 101/121] cpufreq: phytium: Add Phytium P-state driver This patch enables phytium to support the hardware and software frequency adjustment according to the mode of passive or active. Signed-off-by: Li Jiayi Signed-off-by: Wang Yinfeng Change-Id: Ib7453d85bbc43c91ffd5088b1e1b100d814b64e5 cpufreq: phytium: update copyright Signed-off-by: liutianyu1250 --- MAINTAINERS | 1 + drivers/cpufreq/Kconfig.arm | 22 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/phytium_pstate.c | 994 +++++++++++++++++++++++++++++++ 4 files changed, 1018 insertions(+) create mode 100644 drivers/cpufreq/phytium_pstate.c diff --git a/MAINTAINERS b/MAINTAINERS index edc6fc3c5f..f92fd53bf3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17468,6 +17468,7 @@ F: drivers/acpi/phytium_base_ctrl.c F: drivers/char/hw_random/phytium-rng.c F: drivers/char/ipmi/bt_bmc_phytium.c F: drivers/char/ipmi/kcs_bmc_phytium.c +F: drivers/cpufreq/phytium_pstate.c F: drivers/devfreq/phytium_dmu.c F: drivers/devfreq/phytium_noc.c F: drivers/dma/phytium/phytium* diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index c5cecbd89b..0274a0e1a1 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -159,6 +159,28 @@ config ARM_OMAP2PLUS_CPUFREQ depends on ARCH_OMAP2PLUS default ARCH_OMAP2PLUS +config ARM_PHYTIUM_PSTATE + bool "Phytium P-state driver" + depends on ACPI_PROCESSOR + select ACPI_CPPC_LIB + default m + help + This adds the P-state driver for Phytium SoCs. + +config PHYT_PSTATE_DEFAULT_MODE + int "Phytium Processor P-state default mode" + depends on ARM_PHYTIUM_PSTATE + default 1 if ARM_PHYTIUM_PSTATE + range 1 3 + help + Select the default mode the phytium-pstate driver will use on + supported hardware. + The value set has the following meanings: + 1 -> Disabled + 2 -> Passive + 3 -> Active (EPP) + + config ARM_QCOM_CPUFREQ_NVMEM tristate "Qualcomm nvmem based CPUFreq" depends on ARCH_QCOM diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index ef85107749..14b280ce27 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_ARM_MEDIATEK_CPUFREQ) += mediatek-cpufreq.o obj-$(CONFIG_ARM_MEDIATEK_CPUFREQ_HW) += mediatek-cpufreq-hw.o obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o +obj-$(CONFIG_ARM_PHYTIUM_PSTATE) += phytium_pstate.o obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o diff --git a/drivers/cpufreq/phytium_pstate.c b/drivers/cpufreq/phytium_pstate.c new file mode 100644 index 0000000000..f937ac56af --- /dev/null +++ b/drivers/cpufreq/phytium_pstate.c @@ -0,0 +1,994 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * phytium_pstate.c - Phytium Processor P-state Frequency Driver + * + * Copyright (C) 2024,Phytium Technology Co.,Ltd. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define KHZ_PER_MHZ 1000 +#define REFERENCE_PERF 50 + +/* + * Available EPP Performance Levels. From large to small, + * the lower the power consumption. + */ +#define PHYT_CPPC_EPP_PERFORMANCE 0x00 +#define PHYT_CPPC_EPP_BALANCE_PERFORMANCE 0x40 +#define PHYT_CPPC_EPP_BALANCE_POWERSAVE 0x80 +#define PHYT_CPPC_EPP_POWERSAVE 0xc0 + +#define PHYT_PSTATE_TRANSITION_LATENCY 20000 +#define PHYT_PSTATE_TRANSITION_DELAY 1000 + +/* AMU Register Encoding. */ +#define PHYT_SYS_AMEVCNTR0_EL0(op2) sys_reg(3, 3, 15, 9, (op2)) +#define PHYT_SYS_AMEVCNTR0_CORE_EL0 PHYT_SYS_AMEVCNTR0_EL0(0) +#define PHYT_SYS_AMEVCNTR0_CONST_EL0 PHYT_SYS_AMEVCNTR0_EL0(1) + +#define read_corecnt() read_sysreg_s(PHYT_SYS_AMEVCNTR0_CORE_EL0) +#define read_constcnt() read_sysreg_s(PHYT_SYS_AMEVCNTR0_CONST_EL0) + +struct cppc_req_cached { + u32 max_perf_cached; + u32 min_perf_cached; + u32 desired_perf_cached; + u32 epp_cached; +}; + +struct phyt_cpudata { + int cpu; + u32 policy; + bool boost_supported; + + /* EPP feature related attributes */ + s16 epp_policy; + + struct cppc_req_cached req_cached; + bool suspended; + + /* CPC related data structure */ + struct cppc_perf_caps perf_caps; + struct cppc_perf_ctrls perf_ctrls; + struct cppc_perf_fb_ctrs perf_fb_ctrs; +}; + +/* + * enum phyt_pstate_mode - driver working mode of phytium pstate + */ +enum phyt_pstate_mode { + PHYT_PSTATE_UNDEFINED = 0, + PHYT_PSTATE_DISABLE, + PHYT_PSTATE_PASSIVE, + PHYT_PSTATE_ACTIVE, + PHYT_PSTATE_MAX, +}; + +static const char * const phyt_pstate_mode_string[] = { + [PHYT_PSTATE_UNDEFINED] = "undefined", + [PHYT_PSTATE_DISABLE] = "disable", + [PHYT_PSTATE_PASSIVE] = "passive", + [PHYT_PSTATE_ACTIVE] = "active", + NULL, +}; + +static struct cpufreq_driver *current_pstate_driver; +static struct cpufreq_driver phyt_pstate_driver; +static struct cpufreq_driver phyt_cpufreq_driver; +static int driver_state = PHYT_PSTATE_UNDEFINED; + +/* + * Phytium Energy Preference Performance (EPP) + * display strings corresponding to EPP index in the + * energy_perf_strings[] + * index String + *------------------------------------- + * 0 performance + * 1 balance_performance + * 2 balance_power + * 3 power + */ +enum energy_perf_value_index { + EPP_INDEX_PERFORMANCE = 0, + EPP_INDEX_BALANCE_PERFORMANCE, + EPP_INDEX_BALANCE_POWERSAVE, + EPP_INDEX_POWERSAVE, +}; + +static const char * const energy_perf_strings[] = { + [EPP_INDEX_PERFORMANCE] = "performance", + [EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance", + [EPP_INDEX_BALANCE_POWERSAVE] = "balance_power", + [EPP_INDEX_POWERSAVE] = "power", + NULL +}; + +static unsigned int epp_values[] = { + [EPP_INDEX_PERFORMANCE] = PHYT_CPPC_EPP_PERFORMANCE, + [EPP_INDEX_BALANCE_PERFORMANCE] = PHYT_CPPC_EPP_BALANCE_PERFORMANCE, + [EPP_INDEX_BALANCE_POWERSAVE] = PHYT_CPPC_EPP_BALANCE_POWERSAVE, + [EPP_INDEX_POWERSAVE] = PHYT_CPPC_EPP_POWERSAVE, +}; + +typedef int (*cppc_mode_transition_fn)(int); + +static inline int get_mode_idx_from_str(const char *str, size_t size) +{ + int i; + + for (i = 0; i < PHYT_PSTATE_MAX; i++) { + if (!strncmp(str, phyt_pstate_mode_string[i], size)) + return i; + } + return -EINVAL; +} + +static DEFINE_MUTEX(phyt_pstate_limits_lock); +static DEFINE_MUTEX(phyt_pstate_driver_lock); + +static s16 phyt_pstate_get_epp(struct phyt_cpudata *cpudata) +{ + u64 epp; + int ret; + + + ret = cppc_get_epp_perf(cpudata->cpu, &epp); + if (ret < 0) { + pr_debug("Could not retrieve energy perf value (%d)\n", ret); + return -EIO; + } + + return (s16)(epp & 0xff); +} + +static int phyt_pstate_get_energy_pref_index(struct phyt_cpudata *cpudata) +{ + s16 epp; + int index = -EINVAL; + + epp = phyt_pstate_get_epp(cpudata); + if (epp < 0) + return epp; + + switch (epp) { + case PHYT_CPPC_EPP_PERFORMANCE: + index = EPP_INDEX_PERFORMANCE; + break; + case PHYT_CPPC_EPP_BALANCE_PERFORMANCE: + index = EPP_INDEX_BALANCE_PERFORMANCE; + break; + case PHYT_CPPC_EPP_BALANCE_POWERSAVE: + index = EPP_INDEX_BALANCE_POWERSAVE; + break; + case PHYT_CPPC_EPP_POWERSAVE: + index = EPP_INDEX_POWERSAVE; + break; + default: + break; + } + + return index; +} + +static int phyt_pstate_set_epp(struct phyt_cpudata *cpudata, u32 epp) +{ + int ret; + struct cppc_perf_ctrls perf_ctrls; + struct cppc_req_cached req_epp_cached = cpudata->req_cached; + + perf_ctrls.energy_perf = epp; + ret = cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1); + if (ret) { + pr_debug("failed to set energy perf value (%d)\n", ret); + return ret; + } + req_epp_cached.epp_cached = epp; + + return ret; +} + +static int phyt_pstate_set_energy_pref_index(struct phyt_cpudata *cpudata, + int pref_index) +{ + int epp = -EINVAL; + int ret; + + if (!pref_index) { + pr_debug("EPP pref_index is invalid\n"); + return -EINVAL; + } + + if (epp == -EINVAL) + epp = epp_values[pref_index]; + + if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) { + pr_debug("EPP cannot be set under performance policy\n"); + return -EBUSY; + } + + ret = phyt_pstate_set_epp(cpudata, epp); + + return ret; +} + +unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf) +{ + s64 retval, offset = 0; + u64 mul, div; + + mul = caps->nominal_freq - caps->lowest_freq; + mul *= KHZ_PER_MHZ; + div = caps->nominal_perf - caps->lowest_perf; + offset = caps->nominal_freq * KHZ_PER_MHZ - + div64_u64(caps->nominal_perf * mul, div); + + retval = offset + div64_u64(perf * mul, div); + if (retval >= 0) + return retval; + return 0; +} + +unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq) +{ + s64 retval, offset = 0; + u64 mul, div; + + mul = caps->nominal_perf - caps->lowest_perf; + div = caps->nominal_freq - caps->lowest_freq; + /* + * We don't need to convert to kHz for computing offset and can + * directly use nominal_freq and lowest_freq as the div64_u64 + * will remove the frequency unit. + */ + offset = caps->nominal_perf - + div64_u64(caps->nominal_freq * mul, div); + /* But we need it for computing the perf level. */ + div *= KHZ_PER_MHZ; + + retval = offset + div64_u64(freq * mul, div); + if (retval >= 0) + return retval; + return 0; +} + +static int phyt_pstate_init_perf(struct phyt_cpudata *cpudata) +{ + int ret; + + ret = cppc_get_perf_caps(cpudata->cpu, &cpudata->perf_caps); + if (ret) + return ret; + + ret = cppc_get_auto_sel_caps(cpudata->cpu, &cpudata->perf_caps); + if (ret) { + pr_warn("failed to get auto_sel, ret: %d\n", ret); + return 0; + } + + ret = cppc_set_auto_sel(cpudata->cpu, + (driver_state == PHYT_PSTATE_PASSIVE) ? 0 : 1); + if (ret) + pr_warn("failed to set auto_sel, ret: %d\n", ret); + + return ret; +} + +static int phyt_cpufreq_verify(struct cpufreq_policy_data *policy) +{ + cpufreq_verify_within_cpu_limits(policy); + + return 0; +} + +static int phyt_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + unsigned int cpu = policy->cpu; + struct cpufreq_freqs freqs; + u32 desired_perf; + int ret = 0; + + desired_perf = cppc_khz_to_perf(&cpudata->perf_caps, target_freq); + /* Return if it is exactly the same perf. */ + if (desired_perf == cpudata->perf_ctrls.desired_perf) + return ret; + + cpudata->perf_ctrls.desired_perf = desired_perf; + freqs.old = policy->cur; + freqs.new = target_freq; + + cpufreq_freq_transition_begin(policy, &freqs); + ret = cppc_set_perf(cpu, &cpudata->perf_ctrls); + cpufreq_freq_transition_end(policy, &freqs, ret != 0); + + if (ret) + pr_debug("Failed to set target on CPU:%d. ret:%d\n", + cpu, ret); + + pr_debug("Set target on CPU:%d, target:%u\n", cpu, target_freq); + return ret; +} + +static int phyt_cpufreq_set_boost(struct cpufreq_policy *policy, int state) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + int ret; + + if (!cpudata->boost_supported) { + pr_err("Boost mode is not supported by this processor or SBIOS\n"); + return -EINVAL; + } + + if (state) + policy->cpuinfo.max_freq = cppc_perf_to_khz(&cpudata->perf_caps, + cpudata->perf_caps.highest_perf); + else + policy->cpuinfo.max_freq = cppc_perf_to_khz(&cpudata->perf_caps, + cpudata->perf_caps.nominal_perf); + + policy->max = policy->cpuinfo.max_freq; + + ret = freq_qos_update_request(policy->max_freq_req, policy->max); + if (ret < 0) + return ret; + + return 0; +} + +static void phyt_pstate_boost_init(struct phyt_cpudata *cpudata) +{ + u32 highest_perf, nominal_perf; + + highest_perf = cpudata->perf_caps.highest_perf; + nominal_perf = cpudata->perf_caps.nominal_perf; + + if (highest_perf <= nominal_perf) + return; + + cpudata->boost_supported = true; + current_pstate_driver->boost_enabled = false; +} + +static int phyt_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + struct device *dev; + struct phyt_cpudata *cpudata; + struct cppc_perf_caps *caps; + int ret; + + dev = get_cpu_device(policy->cpu); + if (!dev) + return -ENODEV; + + cpudata = kzalloc(sizeof(*cpudata), GFP_KERNEL); + if (!cpudata) + return -ENOMEM; + + cpudata->cpu = policy->cpu; + ret = phyt_pstate_init_perf(cpudata); + if (ret) + goto err; + + caps = &cpudata->perf_caps; + + policy->cpuinfo.transition_latency = PHYT_PSTATE_TRANSITION_LATENCY; + policy->transition_delay_us = PHYT_PSTATE_TRANSITION_DELAY; + policy->min = cppc_perf_to_khz(caps, caps->lowest_perf); + policy->max = cppc_perf_to_khz(caps, caps->nominal_perf); + policy->cpuinfo.min_freq = policy->min; + policy->cpuinfo.max_freq = policy->max; + policy->fast_switch_possible = false; + policy->driver_data = cpudata; + + /* It will be updated by governor */ + policy->cur = policy->cpuinfo.max_freq; + + phyt_pstate_boost_init(cpudata); + + return 0; +err: + kfree(cpudata); + return ret; +} + +static int phyt_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + + kfree(cpudata); + + return 0; +} + +/* Sysfs attributes */ + +static ssize_t show_energy_performance_available_preferences( + struct cpufreq_policy *policy, char *buf) +{ + int i = 0; + int offset = 0; + struct phyt_cpudata *cpudata = policy->driver_data; + + if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) + return sysfs_emit_at(buf, offset, "%s\n", + energy_perf_strings[EPP_INDEX_PERFORMANCE]); + + while (energy_perf_strings[i] != NULL) + offset += sysfs_emit_at(buf, offset, "%s ", energy_perf_strings[i++]); + + offset += sysfs_emit_at(buf, offset, "\n"); + + return offset; +} + +static ssize_t store_energy_performance_preference( + struct cpufreq_policy *policy, const char *buf, size_t count) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + char str_preference[21]; + ssize_t ret; + + ret = sscanf(buf, "%20s", str_preference); + if (ret != 1) + return -EINVAL; + + ret = match_string(energy_perf_strings, -1, str_preference); + if (ret < 0) + return -EINVAL; + + mutex_lock(&phyt_pstate_limits_lock); + ret = phyt_pstate_set_energy_pref_index(cpudata, ret); + mutex_unlock(&phyt_pstate_limits_lock); + + return ret ?: count; +} + +static ssize_t show_energy_performance_preference( + struct cpufreq_policy *policy, char *buf) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + int preference; + + preference = phyt_pstate_get_energy_pref_index(cpudata); + if (preference < 0) + return preference; + + return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]); +} + +static void phyt_pstate_driver_cleanup(void) +{ + int cpu; + + for_each_present_cpu(cpu) + cppc_set_auto_sel(cpu, 0); + + driver_state = PHYT_PSTATE_DISABLE; + current_pstate_driver = NULL; +} + +static int phyt_pstate_register_driver(int mode) +{ + int ret; + + if (mode == PHYT_PSTATE_PASSIVE) + current_pstate_driver = &phyt_cpufreq_driver; + else if (mode == PHYT_PSTATE_ACTIVE) + current_pstate_driver = &phyt_pstate_driver; + else + return -EINVAL; + + driver_state = mode; + ret = cpufreq_register_driver(current_pstate_driver); + if (ret) { + phyt_pstate_driver_cleanup(); + return ret; + } + return 0; +} + +static int phyt_pstate_unregister_driver(int dummy) +{ + cpufreq_unregister_driver(current_pstate_driver); + phyt_pstate_driver_cleanup(); + + return 0; +} + +static int phyt_pstate_change_driver_mode(int mode) +{ + int ret; + + driver_state = mode; + + ret = phyt_pstate_unregister_driver(0); + if (ret) + return ret; + + ret = phyt_pstate_register_driver(mode); + if (ret) + return ret; + + return 0; +} + +static cppc_mode_transition_fn mode_state_machine[PHYT_PSTATE_MAX][PHYT_PSTATE_MAX] = { + [PHYT_PSTATE_DISABLE] = { + [PHYT_PSTATE_DISABLE] = NULL, + [PHYT_PSTATE_PASSIVE] = phyt_pstate_register_driver, + [PHYT_PSTATE_ACTIVE] = phyt_pstate_register_driver, + }, + [PHYT_PSTATE_PASSIVE] = { + [PHYT_PSTATE_DISABLE] = phyt_pstate_unregister_driver, + [PHYT_PSTATE_PASSIVE] = NULL, + [PHYT_PSTATE_ACTIVE] = phyt_pstate_change_driver_mode, + }, + [PHYT_PSTATE_ACTIVE] = { + [PHYT_PSTATE_DISABLE] = phyt_pstate_unregister_driver, + [PHYT_PSTATE_PASSIVE] = phyt_pstate_change_driver_mode, + [PHYT_PSTATE_ACTIVE] = NULL, + } +}; + +static ssize_t phyt_pstate_show_status(char *buf) +{ + if (!current_pstate_driver) + return sysfs_emit(buf, "disable\n"); + + return sysfs_emit(buf, "%s\n", phyt_pstate_mode_string[driver_state]); +} + +static int phyt_pstate_update_status(const char *buf, size_t size) +{ + int mode_idx; + + if (size > strlen("passive") || size < strlen("active")) + return -EINVAL; + + mode_idx = get_mode_idx_from_str(buf, size); + + if (mode_idx < 0 || mode_idx >= PHYT_PSTATE_MAX) + return -EINVAL; + + if (mode_state_machine[driver_state][mode_idx]) + return mode_state_machine[driver_state][mode_idx](mode_idx); + + return 0; +} + +static ssize_t status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret; + + mutex_lock(&phyt_pstate_driver_lock); + ret = phyt_pstate_show_status(buf); + mutex_unlock(&phyt_pstate_driver_lock); + + return ret; +} + +static ssize_t status_store(struct device *a, struct device_attribute *b, + const char *buf, size_t count) +{ + char *p = memchr(buf, '\n', count); + int ret; + + mutex_lock(&phyt_pstate_driver_lock); + ret = phyt_pstate_update_status(buf, p ? p - buf : count); + mutex_unlock(&phyt_pstate_driver_lock); + + return ret < 0 ? ret : count; +} + +cpufreq_freq_attr_rw(energy_performance_preference); +cpufreq_freq_attr_ro(energy_performance_available_preferences); +static DEVICE_ATTR_RW(status); + +static struct freq_attr *phyt_cpufreq_attr[] = { + NULL, +}; + +static struct freq_attr *phyt_pstate_attr[] = { + &energy_performance_preference, + &energy_performance_available_preferences, + NULL, +}; + +static struct attribute *pstate_global_attributes[] = { + &dev_attr_status.attr, + NULL +}; + +static const struct attribute_group phyt_pstate_global_attr_group = { + .name = "phyt_pstate", + .attrs = pstate_global_attributes, +}; + +static int phyt_pstate_cpu_init(struct cpufreq_policy *policy) +{ + struct phyt_cpudata *cpudata; + struct device *dev; + struct cppc_perf_caps *caps; + struct cppc_perf_ctrls perf_ctrls; + int ret; + + dev = get_cpu_device(policy->cpu); + if (!dev) + return -ENODEV; + + cpudata = kzalloc(sizeof(*cpudata), GFP_KERNEL); + if (!cpudata) + return -ENOMEM; + + cpudata->cpu = policy->cpu; + ret = phyt_pstate_init_perf(cpudata); + if (ret) + goto err; + + cpudata->epp_policy = 0; + cpudata->req_cached.epp_cached = phyt_pstate_get_epp(cpudata); + + caps = &cpudata->perf_caps; + + policy->cpuinfo.transition_latency = PHYT_PSTATE_TRANSITION_LATENCY; + policy->transition_delay_us = PHYT_PSTATE_TRANSITION_DELAY; + policy->min = cppc_perf_to_khz(caps, caps->lowest_perf); + policy->max = cppc_perf_to_khz(caps, caps->nominal_perf); + policy->cpuinfo.min_freq = policy->min; + policy->cpuinfo.max_freq = policy->max; + policy->fast_switch_possible = false; + policy->driver_data = cpudata; + policy->policy = CPUFREQ_POLICY_POWERSAVE; + + /* It will be updated by governor */ + policy->cur = policy->cpuinfo.max_freq; + + perf_ctrls.max_perf = caps->nominal_perf; + perf_ctrls.min_perf = caps->lowest_perf; + ret = cppc_set_perf(cpudata->cpu, &perf_ctrls); + if (ret) + pr_debug("Failed to limit freq on CPU:%d. ret:%d\n", + cpudata->cpu, ret); + + phyt_pstate_boost_init(cpudata); + + return 0; +err: + kfree(cpudata); + return ret; +} + +static int phyt_pstate_cpu_exit(struct cpufreq_policy *policy) +{ + pr_debug("CPU %d exiting\n", policy->cpu); + return 0; +} + +static void phyt_pstate_update_limit(struct cpufreq_policy *policy) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + struct cppc_perf_ctrls perf_ctrls; + struct cppc_req_cached req_epp_cached = cpudata->req_cached; + + u32 min_perf, max_perf; + s16 epp; + + max_perf = cppc_khz_to_perf(&cpudata->perf_caps, policy->max); + min_perf = cppc_khz_to_perf(&cpudata->perf_caps, policy->min); + + if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) { + min_perf = max_perf; + policy->min = policy->max; + } + + perf_ctrls.max_perf = max_perf; + perf_ctrls.min_perf = min_perf; + perf_ctrls.desired_perf = 0; + cppc_set_perf(cpudata->cpu, &perf_ctrls); + + req_epp_cached.max_perf_cached = max_perf; + req_epp_cached.min_perf_cached = min_perf; + req_epp_cached.desired_perf_cached = 0; + + cpudata->epp_policy = cpudata->policy; + + /* Get epp value */ + epp = phyt_pstate_get_epp(cpudata); + if (epp < 0) + return; + + if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) + epp = 0; + + req_epp_cached.epp_cached = epp; + phyt_pstate_set_epp(cpudata, epp); +} + +static int phyt_pstate_set_policy(struct cpufreq_policy *policy) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + + if (!policy->cpuinfo.max_freq) + return -ENODEV; + + cpudata->policy = policy->policy; + + phyt_pstate_update_limit(policy); + + return 0; +} + +static void update_cpu_perf(void *val) +{ + u64 prev_core_cnt, prev_const_cnt, core_cnt, const_cnt; + u64 delta_core_cnt, delta_const_cnt; + u64 perf; + + prev_core_cnt = read_corecnt(); + prev_const_cnt = read_constcnt(); + udelay(2); + core_cnt = read_corecnt(); + const_cnt = read_constcnt(); + + delta_core_cnt = core_cnt - prev_core_cnt; + delta_const_cnt = const_cnt - prev_const_cnt; + + /* + * delta_core_cnt + * perf = ----------------- * reference_perf + * delta_const_cnt + */ + perf = div64_u64(100 * delta_core_cnt, delta_const_cnt); + perf = div64_u64(REFERENCE_PERF * perf, 100); + + *(u64 *)val = perf; +} + +static inline int read_counters_on_cpu(int cpu, smp_call_func_t func, u64 *val) +{ + if (WARN_ON_ONCE(irqs_disabled())) + return -EPERM; + + smp_call_function_single(cpu, func, val, 1); + return 0; +} + +static unsigned int phyt_pstate_get_rate(unsigned int cpu) +{ + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + struct phyt_cpudata *cpudata = policy->driver_data; + u64 scale, cur_freq; + + read_counters_on_cpu(cpu, update_cpu_perf, &scale); + + cur_freq = cppc_perf_to_khz(&cpudata->perf_caps, scale); + + cpufreq_cpu_put(policy); + return cur_freq; +} + +static void phyt_pstate_epp_reenable(struct phyt_cpudata *cpudata) +{ + struct cppc_perf_ctrls perf_ctrls; + struct cppc_req_cached req_epp_cached = cpudata->req_cached; + u64 max_perf, min_perf; + + max_perf = req_epp_cached.max_perf_cached; + min_perf = req_epp_cached.min_perf_cached; + + /* Set the maximum and minimum perf level to the cached value. */ + perf_ctrls.max_perf = max_perf; + perf_ctrls.min_perf = min_perf; + perf_ctrls.desired_perf = 0; + cppc_set_perf(cpudata->cpu, &perf_ctrls); + + /* Re-enable auto_sel and write epp levels cached before suspend. */ + perf_ctrls.energy_perf = req_epp_cached.epp_cached; + cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1); +} + +static int phyt_pstate_cpu_online(struct cpufreq_policy *policy) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + + pr_debug("Phyt CPU Core %d going online\n", cpudata->cpu); + + if (driver_state == PHYT_PSTATE_ACTIVE) + phyt_pstate_epp_reenable(cpudata); + + cpudata->suspended = false; + return 0; +} + +static int phyt_pstate_cpu_offline(struct cpufreq_policy *policy) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + + pr_debug("Phyt CPU Core %d going offline\n", cpudata->cpu); + + if (cpudata->suspended) + return 0; + + return 0; +} + +static int phyt_pstate_verify_policy(struct cpufreq_policy_data *policy) +{ + cpufreq_verify_within_cpu_limits(policy); + + return 0; +} + +static int phyt_pstate_suspend(struct cpufreq_policy *policy) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + + cpudata->suspended = true; + + return 0; +} + +static int phyt_pstate_resume(struct cpufreq_policy *policy) +{ + struct phyt_cpudata *cpudata = policy->driver_data; + int ret; + + if (cpudata->suspended) { + if (driver_state == PHYT_PSTATE_ACTIVE) { + mutex_lock(&phyt_pstate_limits_lock); + /* enable phyt pstate from suspend state*/ + phyt_pstate_epp_reenable(cpudata); + mutex_unlock(&phyt_pstate_limits_lock); + } else { + cpudata->perf_ctrls.desired_perf = policy->cur; + ret = cppc_set_perf(policy->cpu, &cpudata->perf_ctrls); + } + cpudata->suspended = false; + } + + return 0; +} + +static struct cpufreq_driver phyt_pstate_driver = { + .flags = CPUFREQ_CONST_LOOPS, + .verify = phyt_pstate_verify_policy, + .setpolicy = phyt_pstate_set_policy, + .get = phyt_pstate_get_rate, + .init = phyt_pstate_cpu_init, + .exit = phyt_pstate_cpu_exit, + .offline = phyt_pstate_cpu_offline, + .online = phyt_pstate_cpu_online, + .suspend = phyt_pstate_suspend, + .resume = phyt_pstate_resume, + .set_boost = phyt_cpufreq_set_boost, + .name = "phyt-pstate", + .attr = phyt_pstate_attr, +}; + +static struct cpufreq_driver phyt_cpufreq_driver = { + .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS, + .verify = phyt_cpufreq_verify, + .target = phyt_cpufreq_target, + .get = phyt_pstate_get_rate, + .init = phyt_cpufreq_cpu_init, + .exit = phyt_cpufreq_cpu_exit, + .suspend = phyt_pstate_suspend, + .resume = phyt_pstate_resume, + .set_boost = phyt_cpufreq_set_boost, + .name = "phyt-cpufreq", + .attr = phyt_cpufreq_attr, +}; + +static int __init phyt_pstate_set_driver(int mode_idx) +{ + if (mode_idx >= PHYT_PSTATE_DISABLE && mode_idx < PHYT_PSTATE_MAX) { + driver_state = mode_idx; + if (driver_state == PHYT_PSTATE_DISABLE) + pr_info("driver is explicitly disabled\n"); + + if (driver_state == PHYT_PSTATE_ACTIVE) + current_pstate_driver = &phyt_pstate_driver; + + if (driver_state == PHYT_PSTATE_PASSIVE) + current_pstate_driver = &phyt_cpufreq_driver; + + return 0; + } + + return -EINVAL; +} + +static int __init phyt_pstate_init(void) +{ + struct device *dev_root; + int ret; + + if (!acpi_cpc_valid()) { + pr_warn_once("_CPC_method is not available\n"); + return -ENODEV; + } + + /* don't keep reloading if cpufreq_driver exists */ + if (cpufreq_get_current_driver()) + return -EEXIST; + + switch (driver_state) { + case PHYT_PSTATE_UNDEFINED: + ret = phyt_pstate_set_driver(CONFIG_PHYT_PSTATE_DEFAULT_MODE); + if (ret) + return ret; + break; + case PHYT_PSTATE_DISABLE: + return -ENODEV; + case PHYT_PSTATE_PASSIVE: + case PHYT_PSTATE_ACTIVE: + break; + default: + return -EINVAL; + } + + ret = cpufreq_register_driver(current_pstate_driver); + if (ret) + pr_err("failed to register with return %d\n", ret); + + dev_root = bus_get_dev_root(&cpu_subsys); + if (dev_root) { + ret = sysfs_create_group(&dev_root->kobj, + &phyt_pstate_global_attr_group); + put_device(dev_root); + if (ret) { + pr_err("sysfs export failed %d\n", ret); + goto global_attr_free; + } + } + + return ret; + +global_attr_free: + cpufreq_unregister_driver(current_pstate_driver); + return ret; +} +device_initcall(phyt_pstate_init); + +static int __init phyt_pstate_param(char *str) +{ + size_t size; + int mode_idx; + + if (!str) + return -EINVAL; + + size = strlen(str); + mode_idx = get_mode_idx_from_str(str, size); + + return phyt_pstate_set_driver(mode_idx); +} +early_param("phyt_pstate", phyt_pstate_param); + +MODULE_AUTHOR("Li Jiayi "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Phytium Processor P-state Frequency Driver"); -- Gitee From 9cd7b7cdadd6e3d7d7def7d9fb92ad2bfdae5ee7 Mon Sep 17 00:00:00 2001 From: Li Jiayi Date: Mon, 4 Nov 2024 17:25:17 +0800 Subject: [PATCH 102/121] thermal: boost: phytium: Automatic enable/disable of BOOST feature This patch provides auto disable/enable operation for boost. When the device temperature rises above 75% of the smallest trip point, the boost is disabled. In that moment thermal monitor workqueue will monitors if the device cools down. When the device temperature drops below 75% of the smallest trip point, the boost is enabled again. Mainline: NA Signed-off-by: Li Jiayi Signed-off-by: Li Mingzhe Signed-off-by: Wang Yinfeng Change-Id: I52ec7cc4b2d3daad35c1835909e6be3cb8f1ae22 --- drivers/cpufreq/cpufreq.c | 12 ++++++-- drivers/thermal/thermal_core.c | 54 +++++++++++++++++++++++++++++++++- include/linux/cpufreq.h | 1 + include/linux/thermal.h | 2 ++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index df445b44e9..344fabe63e 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -86,7 +86,7 @@ static void cpufreq_governor_limits(struct cpufreq_policy *policy); static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_governor *new_gov, unsigned int new_pol); -static bool cpufreq_boost_supported(void); +bool cpufreq_boost_supported(void); /* * Two notifier lists: the "policy" list is involved in the @@ -1224,7 +1224,6 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy) cmp = &policy->kobj_unregister; up_write(&policy->rwsem); kobject_put(kobj); - /* * We need to make sure that the underlying kobj is * actually not referenced anymore by anybody before we @@ -2794,10 +2793,14 @@ int cpufreq_boost_trigger_state(int state) return ret; } -static bool cpufreq_boost_supported(void) +bool cpufreq_boost_supported(void) { + if (!cpufreq_driver) + return -EINVAL; + return cpufreq_driver->set_boost; } +EXPORT_SYMBOL_GPL(cpufreq_boost_supported); static int create_boost_sysfs_file(void) { @@ -2834,6 +2837,9 @@ EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support); int cpufreq_boost_enabled(void) { + if (!cpufreq_driver) + return -EINVAL; + return cpufreq_driver->boost_enabled; } EXPORT_SYMBOL_GPL(cpufreq_boost_enabled); diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d7ac7eef68..4aa2ad4105 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -18,9 +18,10 @@ #include #include #include +#include #include #include - +#include #define CREATE_TRACE_POINTS #include "thermal_trace.h" @@ -341,6 +342,49 @@ static void handle_critical_trips(struct thermal_zone_device *tz, tz->ops->critical(tz); } +static int thermal_boost_enable(struct thermal_zone_device *tz) +{ + enum thermal_trend trend = get_tz_trend(tz, 0); + struct thermal_trip trip; + + if (!tz->overheated) + return -EPERM; + if (trend == THERMAL_TREND_RAISING) + return -EBUSY; + + __thermal_zone_get_trip(tz, 0, &trip); + + if ((tz->temperature + (trip.temperature >> 2)) < trip.temperature) { + mutex_lock(&tz->lock); + tz->overheated = false; + if (tz->boost_polling) { + tz->boost_polling = false; + thermal_zone_device_set_polling(tz, 0); + } + mutex_unlock(&tz->lock); + cpufreq_boost_trigger_state(1); + return 0; + } + return -EBUSY; +} + +static void thermal_boost_disable(struct thermal_zone_device *tz) +{ + cpufreq_boost_trigger_state(0); + + /* + * If no workqueue for monitoring is running - start one with + * 1000 ms monitoring period + * If workqueue already running - do not change its period and only + * test if target CPU has cooled down + */ + if (tz->mode != THERMAL_DEVICE_ENABLED) { + tz->boost_polling = true; + thermal_zone_device_set_polling(tz, 1000); + } + tz->overheated = true; +} + static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id) { struct thermal_trip trip; @@ -420,6 +464,11 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, update_temperature(tz); + if (cpufreq_boost_supported() && cpufreq_boost_enabled()) + if ((tz->temperature + (tz->trips[0].temperature >> 2)) + >= tz->trips[0].temperature) + thermal_boost_disable(tz); + __thermal_zone_set_trips(tz); tz->notify_event = event; @@ -526,6 +575,9 @@ static void thermal_zone_device_check(struct work_struct *work) struct thermal_zone_device *tz = container_of(work, struct thermal_zone_device, poll_queue.work); + if (cpufreq_boost_supported()) + if (!thermal_boost_enable(tz)) + return; thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); } diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 9ca4211c06..0393a2f2ba 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -797,6 +797,7 @@ ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); #ifdef CONFIG_CPU_FREQ int cpufreq_boost_trigger_state(int state); int cpufreq_boost_enabled(void); +bool cpufreq_boost_supported(void); int cpufreq_enable_boost_support(void); bool policy_has_boost_freq(struct cpufreq_policy *policy); diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 2e9d18ba46..155f023b6c 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -176,6 +176,8 @@ struct thermal_zone_device { int prev_low_trip; int prev_high_trip; atomic_t need_update; + bool overheated; + bool boost_polling; struct thermal_zone_device_ops *ops; struct thermal_zone_params *tzp; struct thermal_governor *governor; -- Gitee From 1cf2f2aedc207d0da1a54097f0c5724e9a530375 Mon Sep 17 00:00:00 2001 From: Li Mingzhe Date: Tue, 14 Jan 2025 15:49:34 +0800 Subject: [PATCH 103/121] cpufreq: Phytium: Bugfix the NULL pointer of boost in high temperature Fix that when the temperature control module determines whether boost is supported or not in a high temperature environment and boost is not enabled, the error code will be returned because the cpufreq_driver module is not initialized, resulting in entering the cpufreq module and writing a value to it, and a null pointer error will be reported. Mainline: NA Signed-off-by: Li Mingzhe Signed-off-by: Wang Yinfeng Change-Id: I99c422a1dfbad1d791cc20012f2590c96f54d90a --- drivers/cpufreq/cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 344fabe63e..ad4b7bf331 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2796,7 +2796,7 @@ int cpufreq_boost_trigger_state(int state) bool cpufreq_boost_supported(void) { if (!cpufreq_driver) - return -EINVAL; + return 0; return cpufreq_driver->set_boost; } @@ -2838,7 +2838,7 @@ EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support); int cpufreq_boost_enabled(void) { if (!cpufreq_driver) - return -EINVAL; + return 0; return cpufreq_driver->boost_enabled; } -- Gitee From f6d211b84077fcca015fd09621ef386fc1b4e713 Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Fri, 7 Feb 2025 17:39:27 +0800 Subject: [PATCH 104/121] cpufreq: phytium: Fix Phytium P-state driver build fail in v6.6.63 After v6.6.58, cpufreq/cppc already export cppc_perf_to_khz and cppc_khz_to_perf, no need add in phytium pstate driver. Signed-off-by: liutianyu1250 --- drivers/cpufreq/phytium_pstate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cpufreq/phytium_pstate.c b/drivers/cpufreq/phytium_pstate.c index f937ac56af..54a6a9731b 100644 --- a/drivers/cpufreq/phytium_pstate.c +++ b/drivers/cpufreq/phytium_pstate.c @@ -232,6 +232,8 @@ static int phyt_pstate_set_energy_pref_index(struct phyt_cpudata *cpudata, return ret; } +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,58)// in v6.6.58, cppc_acpi already export these API below unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf) { s64 retval, offset = 0; @@ -271,6 +273,7 @@ unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq) return retval; return 0; } +#endif static int phyt_pstate_init_perf(struct phyt_cpudata *cpudata) { -- Gitee From a640be3df04f6c3454e114f2eee014d1f7078c46 Mon Sep 17 00:00:00 2001 From: luochunsheng Date: Wed, 30 Oct 2024 09:22:15 +0800 Subject: [PATCH 105/121] iommu: smmuv3: Support bypass single device Add smmu.bypassdev cmdline to allow SMMU bypass streams for some specific devices. Mainline: NA Signed-off-by: luochunsheng Signed-off-by: Yang Yingliang Signed-off-by: Wang Yinfeng Change-Id: Id1030811abf120f40a0f9f0f0ba2c93f460e9969 --- drivers/iommu/Kconfig | 6 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 122 ++++++++++++++++++++ drivers/iommu/iommu.c | 16 +++ include/linux/iommu.h | 6 + 4 files changed, 150 insertions(+) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index d57c5adf93..237557f925 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -461,6 +461,12 @@ config QCOM_IOMMU help Support for IOMMU on certain Qualcomm SoCs. +config SMMU_BYPASS_DEV + bool "SMMU bypass streams for some specific devices" + help + according smmu.bypassdev cmdline, SMMU performs attribute + transformation only,with no address translation. + config HYPERV_IOMMU bool "Hyper-V IRQ Handling" depends on HYPERV && X86 diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index b02ea0fe0f..847510eb38 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -41,6 +41,42 @@ module_param(disable_msipolling, bool, 0444); MODULE_PARM_DESC(disable_msipolling, "Disable MSI-based polling for CMD_SYNC completion."); +#ifdef CONFIG_SMMU_BYPASS_DEV +struct smmu_bypass_device { + unsigned short vendor; + unsigned short device; +}; +#define MAX_CMDLINE_SMMU_BYPASS_DEV 16 + +static struct smmu_bypass_device smmu_bypass_devices[MAX_CMDLINE_SMMU_BYPASS_DEV]; +static int smmu_bypass_devices_num; + +static int __init arm_smmu_bypass_dev_setup(char *str) +{ + unsigned short vendor; + unsigned short device; + int ret; + + if (!str) + return -EINVAL; + + ret = sscanf(str, "%hx:%hx", &vendor, &device); + if (ret != 2) + return -EINVAL; + + if (smmu_bypass_devices_num >= MAX_CMDLINE_SMMU_BYPASS_DEV) + return -ERANGE; + + smmu_bypass_devices[smmu_bypass_devices_num].vendor = vendor; + smmu_bypass_devices[smmu_bypass_devices_num].device = device; + smmu_bypass_devices_num++; + + return 0; +} + +__setup("smmu.bypassdev=", arm_smmu_bypass_dev_setup); +#endif + enum arm_smmu_msi_index { EVTQ_MSI_INDEX, GERROR_MSI_INDEX, @@ -2859,6 +2895,30 @@ static void arm_smmu_remove_dev_pasid(struct device *dev, ioasid_t pasid) arm_smmu_sva_remove_dev_pasid(domain, dev, pasid); } +#ifdef CONFIG_SMMU_BYPASS_DEV +static int arm_smmu_device_domain_type(struct device *dev, unsigned int *type) +{ + int i; + struct pci_dev *pdev; + + if (!dev_is_pci(dev)) + return -ERANGE; + + pdev = to_pci_dev(dev); + for (i = 0; i < smmu_bypass_devices_num; i++) { + if ((smmu_bypass_devices[i].vendor == pdev->vendor) + && (smmu_bypass_devices[i].device == pdev->device)) { + dev_info(dev, "device 0x%x:0x%x uses identity mapping.", + pdev->vendor, pdev->device); + *type = IOMMU_DOMAIN_IDENTITY; + return 0; + } + } + + return -ERANGE; +} +#endif + static struct iommu_ops arm_smmu_ops = { .capable = arm_smmu_capable, .domain_alloc = arm_smmu_domain_alloc, @@ -2874,6 +2934,9 @@ static struct iommu_ops arm_smmu_ops = { .def_domain_type = arm_smmu_def_domain_type, .pgsize_bitmap = -1UL, /* Restricted during device attach */ .owner = THIS_MODULE, +#ifdef CONFIG_SMMU_BYPASS_DEV + .device_domain_type = arm_smmu_device_domain_type, +#endif .default_domain_ops = &(const struct iommu_domain_ops) { .attach_dev = arm_smmu_attach_dev, .map_pages = arm_smmu_map_pages, @@ -3003,12 +3066,59 @@ static int arm_smmu_init_l1_strtab(struct arm_smmu_device *smmu) return 0; } +#ifdef CONFIG_SMMU_BYPASS_DEV +static void arm_smmu_install_bypass_ste_for_dev(struct arm_smmu_device *smmu, + u32 sid) +{ + u64 val; + __le64 *step = arm_smmu_get_step_for_sid(smmu, sid); + + if (!step) + return; + + val = STRTAB_STE_0_V; + val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS); + step[0] = cpu_to_le64(val); + step[1] = cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG, + STRTAB_STE_1_SHCFG_INCOMING)); + step[2] = 0; +} + +static int arm_smmu_prepare_init_l2_strtab(struct device *dev, void *data) +{ + u32 sid; + int ret; + unsigned int type; + struct pci_dev *pdev; + struct arm_smmu_device *smmu = (struct arm_smmu_device *)data; + + if (arm_smmu_device_domain_type(dev, &type)) + return 0; + + pdev = to_pci_dev(dev); + sid = PCI_DEVID(pdev->bus->number, pdev->devfn); + if (!arm_smmu_sid_in_range(smmu, sid)) + return -ERANGE; + + ret = arm_smmu_init_l2_strtab(smmu, sid); + if (ret) + return ret; + + arm_smmu_install_bypass_ste_for_dev(smmu, sid); + + return 0; +} +#endif + static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu) { void *strtab; u64 reg; u32 size, l1size; struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; +#ifdef CONFIG_SMMU_BYPASS_DEV + int ret; +#endif /* Calculate the L1 size, capped to the SIDSIZE. */ size = STRTAB_L1_SZ_SHIFT - (ilog2(STRTAB_L1_DESC_DWORDS) + 3); @@ -3038,7 +3148,19 @@ static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu) reg |= FIELD_PREP(STRTAB_BASE_CFG_SPLIT, STRTAB_SPLIT); cfg->strtab_base_cfg = reg; +#ifdef CONFIG_SMMU_BYPASS_DEV + ret = arm_smmu_init_l1_strtab(smmu); + if (ret) + return ret; + + if (smmu_bypass_devices_num) { + ret = bus_for_each_dev(&pci_bus_type, NULL, (void *)smmu, + arm_smmu_prepare_init_l2_strtab); + } + return ret; +#else return arm_smmu_init_l1_strtab(smmu); +#endif } static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index a998f13adf..1ea52c6ac2 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1773,14 +1773,30 @@ iommu_group_alloc_default_domain(struct iommu_group *group, int req_type) list_first_entry(&group->devices, struct group_device, list) ->dev->bus; struct iommu_domain *dom; +#ifdef CONFIG_SMMU_BYPASS_DEV + struct device *dev = + list_first_entry(&group->devices, struct group_device, list)->dev; + const struct iommu_ops *ops = dev_iommu_ops(dev); + unsigned int type = iommu_def_domain_type; +#endif lockdep_assert_held(&group->mutex); if (req_type) return __iommu_group_alloc_default_domain(bus, group, req_type); +#ifdef CONFIG_SMMU_BYPASS_DEV + /* direct allocate required default domain type for some specific devices. */ + if (ops->device_domain_type != NULL) { + if (ops->device_domain_type(dev, &type)) + type = iommu_def_domain_type; + } + + dom = __iommu_group_alloc_default_domain(bus, group, type); +#else /* The driver gave no guidance on what type to use, try the default */ dom = __iommu_group_alloc_default_domain(bus, group, iommu_def_domain_type); +#endif if (dom) return dom; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index b6ef263e85..7c6e71c470 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -294,6 +294,12 @@ struct iommu_ops { const struct iommu_domain_ops *default_domain_ops; unsigned long pgsize_bitmap; struct module *owner; + +#ifdef CONFIG_SMMU_BYPASS_DEV +#ifndef __GENKSYMS__ + int (*device_domain_type)(struct device *dev, unsigned int *type); +#endif +#endif }; /** -- Gitee From e5b8b3719803546d1924c090f4e3535c693efe07 Mon Sep 17 00:00:00 2001 From: Li Yuze Date: Tue, 8 Oct 2024 11:15:54 +0800 Subject: [PATCH 106/121] ec: phytium: Add support for phytium EC driver This patch provides EC driver support for phytium platforms. Mainline: NA Signed-off-by: Li Yuze Signed-off-by: Wang Yinfeng Change-Id: I97775ce2baaa5bfe993e4ce89594074ab380693e --- drivers/acpi/ec.c | 66 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 115994dfef..e5d77ee100 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -31,6 +31,9 @@ #include #include "internal.h" +#ifdef CONFIG_ARCH_PHYTIUM +#include "phytium_base_ctrl.h" +#endif #define ACPI_EC_CLASS "embedded_controller" #define ACPI_EC_DEVICE_NAME "Embedded Controller" @@ -273,7 +276,12 @@ static bool acpi_ec_flushed(struct acpi_ec *ec) static inline u8 acpi_ec_read_status(struct acpi_ec *ec) { - u8 x = inb(ec->command_addr); + u8 x; + + if (phytium_check_cpu() == true) + x = base_ctrl_readb(ec->command_addr); + else + x = inb(ec->command_addr); ec_dbg_raw("EC_SC(R) = 0x%2.2x " "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d", @@ -288,7 +296,12 @@ static inline u8 acpi_ec_read_status(struct acpi_ec *ec) static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { - u8 x = inb(ec->data_addr); + u8 x; + + if (phytium_check_cpu() == true) + x = base_ctrl_readb(ec->data_addr); + else + x = inb(ec->data_addr); ec->timestamp = jiffies; ec_dbg_raw("EC_DATA(R) = 0x%2.2x", x); @@ -298,14 +311,24 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec) static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) { ec_dbg_raw("EC_SC(W) = 0x%2.2x", command); - outb(command, ec->command_addr); + + if (phytium_check_cpu() == true) + base_ctrl_writeb(ec->command_addr, command); + else + outb(command, ec->command_addr); + ec->timestamp = jiffies; } static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) { ec_dbg_raw("EC_DATA(W) = 0x%2.2x", data); - outb(data, ec->data_addr); + + if (phytium_check_cpu() == true) + base_ctrl_writeb(ec->data_addr, data); + else + outb(data, ec->data_addr); + ec->timestamp = jiffies; } @@ -371,6 +394,17 @@ static inline void acpi_ec_disable_gpe(struct acpi_ec *ec, bool close) } } +#ifdef CONFIG_ARCH_PHYTIUM +static void hwreduce_acpi_enable(struct acpi_ec *ec) +{ + base_ctrl_writeb(ec->command_addr, 0x86); +} +static void hwreduce_acpi_disable(struct acpi_ec *ec) +{ + base_ctrl_writeb(ec->command_addr, 0x87); +} +#endif + /* -------------------------------------------------------------------------- * Transaction Management * -------------------------------------------------------------------------- */ @@ -415,9 +449,12 @@ static void acpi_ec_unmask_events(struct acpi_ec *ec) clear_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags); if (ec->gpe >= 0) acpi_ec_enable_gpe(ec, false); - else - enable_irq(ec->irq); - + else { + if (!phytium_check_cpu()) + enable_irq(ec->irq); + else if ((irq_to_desc(ec->irq))->depth > 0) + enable_irq(ec->irq); + } ec_dbg_drv("Polling disabled"); } } @@ -496,6 +533,10 @@ static inline void __acpi_ec_enable_event(struct acpi_ec *ec) * Unconditionally invoke this once after enabling the event * handling mechanism to detect the pending events. */ +#ifdef CONFIG_ARCH_PHYTIUM + if (phytium_check_cpu()) + hwreduce_acpi_enable(ec); +#endif advance_transaction(ec, false); } @@ -503,6 +544,11 @@ static inline void __acpi_ec_disable_event(struct acpi_ec *ec) { if (test_and_clear_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) ec_log_drv("event blocked"); + +#ifdef CONFIG_ARCH_PHYTIUM + if (phytium_check_cpu()) + hwreduce_acpi_disable(ec); +#endif } /* @@ -2117,6 +2163,10 @@ static int acpi_ec_resume(struct device *dev) struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev)); +#ifdef CONFIG_ARCH_PHYTIUM + if (phytium_check_cpu()) + hwreduce_acpi_enable(ec); +#endif acpi_ec_enable_event(ec); return 0; } @@ -2130,7 +2180,7 @@ EXPORT_SYMBOL_GPL(acpi_ec_mark_gpe_for_wake); void acpi_ec_set_gpe_wake_mask(u8 action) { - if (pm_suspend_no_platform() && first_ec && !ec_no_wakeup) + if (!phytium_check_cpu() && pm_suspend_no_platform() && first_ec && !ec_no_wakeup) acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); } -- Gitee From 0b7f97ed1ebb54a43b5a5007d8fe0fe71993b3b9 Mon Sep 17 00:00:00 2001 From: Wu Jinyong Date: Fri, 13 Dec 2024 15:10:13 +0800 Subject: [PATCH 107/121] can: phytium: Modify the sampling points of the register The calculation formula for can sampling points is (ponits = (SS + PTS + PBS1) / (SS + PTS + PBS1 + PBS2)), In the registers, the values of PBS1 and PBS2 are stored reversed,so the result of points is wrong. This patch fixes this bug. Mainline: Open-Source Signed-off-by: Wu Jinyong Signed-off-by: Wang Yinfeng Change-Id: Iaf5d8cf6fcbdd43bd05186bd17e4eecd9693e123 --- drivers/net/can/phytium/phytium_can.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/phytium/phytium_can.c b/drivers/net/can/phytium/phytium_can.c index 52564c4aaa..8f7cf64a9c 100644 --- a/drivers/net/can/phytium/phytium_can.c +++ b/drivers/net/can/phytium/phytium_can.c @@ -814,18 +814,18 @@ static int phytium_can_set_bittiming(struct net_device *dev) /* Setting Time Segment 1 in BTR Register */ btr |= (bt->prop_seg - 1) << 2; - btr |= (bt->phase_seg1 - 1) << 5; + btr |= (bt->phase_seg1 - 1) << 8; /* Setting Time Segment 2 in BTR Register */ - btr |= (bt->phase_seg2 - 1) << 8; + btr |= (bt->phase_seg2 - 1) << 5; /* Setting Synchronous jump width in BTR Register */ btr |= (bt->sjw - 1); dbtr = (dbt->brp - 1) << 16; dbtr |= (dbt->prop_seg - 1) << 2; - dbtr |= (dbt->phase_seg1 - 1) << 5; - dbtr |= (dbt->phase_seg2 - 1) << 8; + dbtr |= (dbt->phase_seg1 - 1) << 8; + dbtr |= (dbt->phase_seg2 - 1) << 5; dbtr |= (dbt->sjw - 1); if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) { -- Gitee From f5d6a48560a05d03e2f176a37872b2ec550f01b8 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Mon, 2 Dec 2024 15:01:59 +0800 Subject: [PATCH 108/121] sched/topology: Remove the EM_MAX_COMPLEXITY limit The Energy Aware Scheduler (EAS) estimates the energy consumption of placing a task on different CPUs. The goal is to minimize this energy consumption. Estimating the energy of different task placements is increasingly complex with the size of the platform. To avoid having a slow wake-up path, EAS is only enabled if this complexity is low enough. The current complexity limit was set in: commit b68a4c0dba3b ("sched/topology: Disable EAS on inappropriate platforms") ... based on the first implementation of EAS, which was re-computing the power of the whole platform for each task placement scenario, see: commit 390031e4c309 ("sched/fair: Introduce an energy estimation helper function") ... but the complexity of EAS was reduced in: commit eb92692b2544 ("sched/fair: Speed-up energy-aware wake-ups") ... and find_energy_efficient_cpu() (feec) algorithm was updated in: commit 3e8c6c9aac42 ("sched/fair: Remove task_util from effective utilization in feec()") find_energy_efficient_cpu() (feec) is now doing: feec() \_ for_each_pd(pd) [0] // get max_spare_cap_cpu and compute_prev_delta \_ for_each_cpu(pd) [1] \_ eenv_pd_busy_time(pd) [2] \_ for_each_cpu(pd) // compute_energy(pd) without the task \_ eenv_pd_max_util(pd, -1) [3.0] \_ for_each_cpu(pd) \_ em_cpu_energy(pd, -1) \_ for_each_ps(pd) // compute_energy(pd) with the task on prev_cpu \_ eenv_pd_max_util(pd, prev_cpu) [3.1] \_ for_each_cpu(pd) \_ em_cpu_energy(pd, prev_cpu) \_ for_each_ps(pd) // compute_energy(pd) with the task on max_spare_cap_cpu \_ eenv_pd_max_util(pd, max_spare_cap_cpu) [3.2] \_ for_each_cpu(pd) \_ em_cpu_energy(pd, max_spare_cap_cpu) \_ for_each_ps(pd) [3.1] happens only once since prev_cpu is unique. With the same definitions for nr_pd, nr_cpus and nr_ps, the complexity is of: nr_pd * (2 * [nr_cpus in pd] + 2 * ([nr_cpus in pd] + [nr_ps in pd])) + ([nr_cpus in pd] + [nr_ps in pd]) [0] * ( [1] + [2] + [3.0] + [3.2] ) + [3.1] = nr_pd * (4 * [nr_cpus in pd] + 2 * [nr_ps in pd]) + [nr_cpus in prev pd] + nr_ps The complexity limit was set to 2048 in: commit b68a4c0dba3b ("sched/topology: Disable EAS on inappropriate platforms") ... to make "EAS usable up to 16 CPUs with per-CPU DVFS and less than 8 performance states each". For the same platform, the complexity would actually be of: 16 * (4 + 2 * 7) + 1 + 7 = 296 Since the EAS complexity was greatly reduced since the limit was introduced, bigger platforms can handle EAS. For instance, a platform with 112 CPUs with 7 performance states each would not reach it: 112 * (4 + 2 * 7) + 1 + 7 = 2024 To reflect this improvement in the underlying EAS code, remove the EAS complexity check. Note that a limit on the number of CPUs still holds against EM_MAX_NUM_CPUS to avoid overflows during the energy estimation. [ mingo: Updates to the changelog. ] Mainline: NA Signed-off-by: Pierre Gondois Signed-off-by: Ingo Molnar Reviewed-by: Lukasz Luba Reviewed-by: Dietmar Eggemann Link: https://lore.kernel.org/r/20231009060037.170765-2-sshegde@linux.vnet.ibm.com Signed-off-by: Li Mingzhe Change-Id: If33b2a395d8ddeca0b88f20b69630d52c75f7b16 --- Documentation/scheduler/sched-energy.rst | 30 ++---------------- kernel/sched/topology.c | 39 ++---------------------- 2 files changed, 6 insertions(+), 63 deletions(-) diff --git a/Documentation/scheduler/sched-energy.rst b/Documentation/scheduler/sched-energy.rst index fc853c8cc3..e3bc17afa7 100644 --- a/Documentation/scheduler/sched-energy.rst +++ b/Documentation/scheduler/sched-energy.rst @@ -359,33 +359,9 @@ in milli-Watts or in an 'abstract scale'. 6.3 - Energy Model complexity ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The task wake-up path is very latency-sensitive. When the EM of a platform is -too complex (too many CPUs, too many performance domains, too many performance -states, ...), the cost of using it in the wake-up path can become prohibitive. -The energy-aware wake-up algorithm has a complexity of: - - C = Nd * (Nc + Ns) - -with: Nd the number of performance domains; Nc the number of CPUs; and Ns the -total number of OPPs (ex: for two perf. domains with 4 OPPs each, Ns = 8). - -A complexity check is performed at the root domain level, when scheduling -domains are built. EAS will not start on a root domain if its C happens to be -higher than the completely arbitrary EM_MAX_COMPLEXITY threshold (2048 at the -time of writing). - -If you really want to use EAS but the complexity of your platform's Energy -Model is too high to be used with a single root domain, you're left with only -two possible options: - - 1. split your system into separate, smaller, root domains using exclusive - cpusets and enable EAS locally on each of them. This option has the - benefit to work out of the box but the drawback of preventing load - balance between root domains, which can result in an unbalanced system - overall; - 2. submit patches to reduce the complexity of the EAS wake-up algorithm, - hence enabling it to cope with larger EMs in reasonable time. - +EAS does not impose any complexity limit on the number of PDs/OPPs/CPUs but +restricts the number of CPUs to EM_MAX_NUM_CPUS to prevent overflows during +the energy estimation. 6.4 - Schedutil governor ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 3a13cecf17..1b05b652f5 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -348,32 +348,13 @@ static void sched_energy_set(bool has_eas) * 1. an Energy Model (EM) is available; * 2. the SD_ASYM_CPUCAPACITY flag is set in the sched_domain hierarchy. * 3. no SMT is detected. - * 4. the EM complexity is low enough to keep scheduling overheads low; - * 5. schedutil is driving the frequency of all CPUs of the rd; - * 6. frequency invariance support is present; - * - * The complexity of the Energy Model is defined as: - * - * C = nr_pd * (nr_cpus + nr_ps) - * - * with parameters defined as: - * - nr_pd: the number of performance domains - * - nr_cpus: the number of CPUs - * - nr_ps: the sum of the number of performance states of all performance - * domains (for example, on a system with 2 performance domains, - * with 10 performance states each, nr_ps = 2 * 10 = 20). - * - * It is generally not a good idea to use such a model in the wake-up path on - * very complex platforms because of the associated scheduling overheads. The - * arbitrary constraint below prevents that. It makes EAS usable up to 16 CPUs - * with per-CPU DVFS and less than 8 performance states each, for example. + * 4. schedutil is driving the frequency of all CPUs of the rd; + * 5. frequency invariance support is present; */ -#define EM_MAX_COMPLEXITY 2048 - extern struct cpufreq_governor schedutil_gov; static bool build_perf_domains(const struct cpumask *cpu_map) { - int i, nr_pd = 0, nr_ps = 0, nr_cpus = cpumask_weight(cpu_map); + int i; struct perf_domain *pd = NULL, *tmp; int cpu = cpumask_first(cpu_map); struct root_domain *rd = cpu_rq(cpu)->rd; @@ -431,20 +412,6 @@ static bool build_perf_domains(const struct cpumask *cpu_map) goto free; tmp->next = pd; pd = tmp; - - /* - * Count performance domains and performance states for the - * complexity check. - */ - nr_pd++; - nr_ps += em_pd_nr_perf_states(pd->em_pd); - } - - /* Bail out if the Energy Model complexity is too high. */ - if (nr_pd * (nr_ps + nr_cpus) > EM_MAX_COMPLEXITY) { - WARN(1, "rd %*pbl: Failed to start EAS, EM complexity is too high\n", - cpumask_pr_args(cpu_map)); - goto free; } perf_domain_debug(cpu_map, pd); -- Gitee From c4cee41a7a061ac25a67dfe78e688a5ec4ffb634 Mon Sep 17 00:00:00 2001 From: Li Mingzhe Date: Fri, 16 Aug 2024 15:59:37 +0800 Subject: [PATCH 109/121] ice: Fix unaligned access in ice driver The new_rcp->recipe_bitmap was written as if it were an aligned bitmap. It is an 8-byte array, but aligned only to 4-byte. Use put_unaligned to set its value insstead. Additionally, values in ice command are typically in little-endian, so use the *_le64 conversion. Mainline: NA Signed-off-by: Li Mingzhe Signed-off-by: Li wencheng Signed-off-by: Wang Yinfeng Change-Id: Ie1c1c4f123e476fb84fc608823d2f7471e3c72a8 --- drivers/net/ethernet/intel/ice/ice_lag.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index 4e675c7c19..b460ea4f5f 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -1806,9 +1806,7 @@ static int ice_create_lag_recipe(struct ice_hw *hw, u16 *rid, new_rcp->content.act_ctrl_fwd_priority = prio; new_rcp->content.rid = *rid | ICE_AQ_RECIPE_ID_IS_ROOT; new_rcp->recipe_indx = *rid; - bitmap_zero((unsigned long *)new_rcp->recipe_bitmap, - ICE_MAX_NUM_RECIPES); - set_bit(*rid, (unsigned long *)new_rcp->recipe_bitmap); + put_unaligned_le64(BIT_ULL(*rid), new_rcp->recipe_bitmap); err = ice_aq_add_recipe(hw, new_rcp, 1, NULL); if (err) -- Gitee From 4373344b1cff0b86e781ea2ce6bf0491a4aa8874 Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Fri, 7 Feb 2025 17:20:22 +0800 Subject: [PATCH 110/121] arm64: dts: fix pe220x build warning fix reg property has invalid length in snoop Signed-off-by: liutianyu1250 --- arch/arm64/boot/dts/phytium/pe220x.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/phytium/pe220x.dtsi b/arch/arm64/boot/dts/phytium/pe220x.dtsi index 92d7b70b61..40d952a1a4 100644 --- a/arch/arm64/boot/dts/phytium/pe220x.dtsi +++ b/arch/arm64/boot/dts/phytium/pe220x.dtsi @@ -280,7 +280,7 @@ ddma1: dma-controller@28004000 { snoop: snoop@28010000 { compatible = "phytium,snoop-ctrl"; - reg = <0x0 0x28010000 0x1000>; + reg = <0x0 0x28010000 0x0 0x1000>; interrupts = ; snoop-ports = <0x80>; }; -- Gitee From 97823a3148f19eef6e5baf31e3411da854e9737a Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Sat, 8 Feb 2025 15:44:34 +0800 Subject: [PATCH 111/121] phytium: base_ctrl: remove no use initcall Platfrom driver can't register in early_initcall, because early_initcall will be called before smp boot up, at this time, platform bus is not init yet. Signed-off-by: liutianyu1250 --- drivers/acpi/phytium_base_ctrl.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/acpi/phytium_base_ctrl.c b/drivers/acpi/phytium_base_ctrl.c index 5ebfd0794a..94bb4c78b3 100644 --- a/drivers/acpi/phytium_base_ctrl.c +++ b/drivers/acpi/phytium_base_ctrl.c @@ -192,18 +192,6 @@ static struct platform_driver phytium_base_ctrl_driver = { module_platform_driver(phytium_base_ctrl_driver); -static int __init phytium_base_ctrl_init(void) -{ - platform_driver_register(&phytium_base_ctrl_driver); - return 0; -} - -static void __exit phytium_base_ctrl_exit(void) -{ - platform_driver_unregister(&phytium_base_ctrl_driver); -} - -early_initcall(phytium_base_ctrl_init); MODULE_AUTHOR("Li Yuze "); MODULE_DESCRIPTION("Phytium base_ctrl driver"); MODULE_LICENSE("GPL"); -- Gitee From c1bdf718558e8cbf765a96bdad55a9741040ce6b Mon Sep 17 00:00:00 2001 From: huxianghua Date: Tue, 6 Aug 2024 20:13:09 +0800 Subject: [PATCH 112/121] drivers/perf:phytium: Add version information to Phytium SoC PCIE PMU. Add version information to the driver for Phytium SoC PCIE PMU to facilitate management. Mainline: NA Signed-off-by: Hu Xianghua Signed-off-by: Wang Yinfeng Change-Id: Iab08b835a710a35669ffd7b4e620e022a4ddfc1a --- drivers/perf/phytium/phytium_pcie_pmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/perf/phytium/phytium_pcie_pmu.c b/drivers/perf/phytium/phytium_pcie_pmu.c index e1dfbf11e6..9b73aded43 100644 --- a/drivers/perf/phytium/phytium_pcie_pmu.c +++ b/drivers/perf/phytium/phytium_pcie_pmu.c @@ -30,6 +30,8 @@ #undef pr_fmt #define pr_fmt(fmt) "phytium_pcie_pmu: " fmt +#define PCIE_PERF_DRIVER_VERSION "1.2.1" + #define PHYTIUM_PCIE_MAX_COUNTERS 18 #define PCIE_START_TIMER 0x000 @@ -896,4 +898,5 @@ module_exit(phytium_pcie_pmu_module_exit); MODULE_DESCRIPTION("Phytium PCIe PMU driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(PCIE_PERF_DRIVER_VERSION); MODULE_AUTHOR("Hu Xianghua "); -- Gitee From 2e716fd9154d21417e9a4e94ef1ceceae8c99778 Mon Sep 17 00:00:00 2001 From: huxianghua Date: Tue, 6 Aug 2024 20:11:25 +0800 Subject: [PATCH 113/121] drivers/perf:phytium: Add version information to Phytium SoC DDR PMU. Add version information to the driver for Phytium SoC DDR PMU to facilitate management. Mainline: NA Signed-off-by: Hu Xianghua Signed-off-by: Wang Yinfeng Change-Id: I99a3c070efa02459cf23c331f4c37674a4d8984b --- drivers/perf/phytium/phytium_ddr_pmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/perf/phytium/phytium_ddr_pmu.c b/drivers/perf/phytium/phytium_ddr_pmu.c index a31bf29c87..13b91b95d4 100644 --- a/drivers/perf/phytium/phytium_ddr_pmu.c +++ b/drivers/perf/phytium/phytium_ddr_pmu.c @@ -30,6 +30,8 @@ #undef pr_fmt #define pr_fmt(fmt) "phytium_ddr_pmu: " fmt +#define DDR_PERF_DRIVER_VERSION "1.2.1" + #define PHYTIUM_DDR_MAX_COUNTERS 8 #define DDR_START_TIMER 0x000 @@ -750,4 +752,5 @@ module_exit(phytium_ddr_pmu_module_exit); MODULE_DESCRIPTION("Phytium DDR PMU driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DDR_PERF_DRIVER_VERSION); MODULE_AUTHOR("Hu Xianghua "); -- Gitee From ecc61859cd1909d38c932844f9a36515dc39fcd6 Mon Sep 17 00:00:00 2001 From: Tan Rui Date: Wed, 4 Dec 2024 10:06:39 +0800 Subject: [PATCH 114/121] drivers/perf:phytium: Added some functional improvements for PCIe PMU. e.g.. 1. Remove support for timer parameter. 2. Add the operation of resetting pmu before driver installion. 3. Modified the method of setting ctrler parameters for PCIe PMU. 4. Add support for new phytium SoC. Mainline: NA Signed-off-by: Tan Rui Change-Id: I5660c70c98797b2bf5733810a45cafac047f959c --- drivers/perf/phytium/phytium_pcie_pmu.c | 407 ++++++++++++++---------- 1 file changed, 238 insertions(+), 169 deletions(-) diff --git a/drivers/perf/phytium/phytium_pcie_pmu.c b/drivers/perf/phytium/phytium_pcie_pmu.c index 9b73aded43..20cf9458a6 100644 --- a/drivers/perf/phytium/phytium_pcie_pmu.c +++ b/drivers/perf/phytium/phytium_pcie_pmu.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -30,52 +31,71 @@ #undef pr_fmt #define pr_fmt(fmt) "phytium_pcie_pmu: " fmt -#define PCIE_PERF_DRIVER_VERSION "1.2.1" - #define PHYTIUM_PCIE_MAX_COUNTERS 18 - -#define PCIE_START_TIMER 0x000 -#define PCIE_STOP_TIMER 0x004 -#define PCIE_CLEAR_EVENT 0x008 -#define PCIE_SET_TIMER_L 0x00c -#define PCIE_SET_TIMER_H 0x010 -#define PCIE_TRIG_MODE 0x014 - -#define PCIE_NOW_STATE 0x0e0 -#define PCIE_EVENT_CYCLES 0x0e4 -#define PCIE_TPOINT_END_L 0x0e4 -#define PCIE_TPOINT_END_H 0x0e8 -#define PCIE_STATE_STOP 0x0ec - -#define PCIE_EVENT_AW 0x100 -#define PCIE_EVENT_W_LAST 0x104 -#define PCIE_EVENT_B 0x108 -#define PCIE_EVENT_AR 0x10c -#define PCIE_EVENT_R_LAST 0x110 -#define PCIE_EVENT_R_FULL 0x114 -#define PCIE_EVENT_R_ERR 0x118 -#define PCIE_EVENT_W_ERR 0x11c -#define PCIE_EVENT_DELAY_RD 0x120 -#define PCIE_EVENT_DELAY_WR 0x124 -#define PCIE_EVENT_RD_MAX 0x128 -#define PCIE_EVENT_RD_MIN 0x12c -#define PCIE_EVENT_WR_MAX 0x130 -#define PCIE_EVENT_WR_MIN 0x134 - -#define PCIE_EVENT_W_DATA 0x200 -#define PCIE_W_DATA_BASE 0x200 - -#define PCIE_EVENT_RDELAY_TIME 0x300 -#define PCIE_RDELAY_TIME_BASE 0x300 - -#define PCIE_EVENT_WDELAY_TIME 0x700 -#define PCIE_WDELAY_TIME_BASE 0x700 - -#define PCIE_CLK_FRE 0xe00 -#define PCIE_DATA_WIDTH 0xe04 +#define PCIE_PERF_DRIVER_VERSION "1.3.0" + +#define PCIE_START_TIMER 0x000 +#define PCIE_STOP_TIMER 0x004 +#define PCIE_CLEAR_EVENT 0x008 + +#define PCIE_EVENT_CYCLES 0x0e4 +#define PCIE_TPOINT_END_L 0x0e4 +#define PCIE_TPOINT_END_H 0x0e8 +#define PCIE_STATE_STOP 0x0ec + +#define PCIE_EVENT_AW 0x100 +#define PCIE_EVENT_W_LAST 0x104 +#define PCIE_EVENT_B 0x108 +#define PCIE_EVENT_AR 0x10c +#define PCIE_EVENT_R_LAST 0x110 +#define PCIE_EVENT_R_FULL 0x114 +#define PCIE_EVENT_R_ERR 0x118 +#define PCIE_EVENT_W_ERR 0x11c +#define PCIE_EVENT_DELAY_RD 0x120 +#define PCIE_EVENT_DELAY_WR 0x124 +#define PCIE_EVENT_RD_MAX 0x128 +#define PCIE_EVENT_RD_MIN 0x12c +#define PCIE_EVENT_WR_MAX 0x130 +#define PCIE_EVENT_WR_MIN 0x134 + +#define PCIE_EVENT_W_DATA 0x200 +#define PCIE_W_DATA_BASE 0x200 + +#define PCIE_EVENT_RDELAY_TIME 0x300 +#define PCIE_RDELAY_TIME_BASE 0x300 + +#define PCIE_EVENT_WDELAY_TIME 0x700 +#define PCIE_WDELAY_TIME_BASE 0x700 + +#define PCIE_DATA_WIDTH 0xe04 + +#define SYS_AIDR_EL1 sys_reg(3, 1, 0, 0, 7) +#define SOC_ID_PS230XX 0x8 +#define SOC_ID_PS240XX 0x6 +#define MIDR_PSXX 0x700f8620 #define to_phytium_pcie_pmu(p) (container_of(p, struct phytium_pcie_pmu, pmu)) +enum { + PS230XX = 0x1, + PS240XX = 0x2, +}; + +static inline int phytium_socs_type(void) +{ + unsigned int soc_id, cpu_id; + + soc_id = read_sysreg_s(SYS_AIDR_EL1); + cpu_id = read_cpuid_id(); + + if ((soc_id == SOC_ID_PS230XX) && (cpu_id == MIDR_PSXX)) + return PS230XX; + else if ((soc_id == SOC_ID_PS240XX) && (cpu_id == MIDR_PSXX)) + return PS240XX; + else + return 0; +} + static int phytium_pcie_pmu_hp_state; struct phytium_pcie_pmu_hwevents { @@ -86,18 +106,21 @@ struct phytium_pcie_pmu_hwevents { struct phytium_pcie_pmu { struct device *dev; void __iomem *base; - void __iomem *csr_base; + void __iomem *cfg_base; void __iomem *irq_reg; struct pmu pmu; struct phytium_pcie_pmu_hwevents pmu_events; u32 die_id; + u32 pcie_id; u32 pmu_id; int on_cpu; int irq; + int irq_bit; struct hlist_node node; int ctrler_id; int real_ctrler; u32 clk_bits; + u32 soc_version; }; #define GET_PCIE_EVENTID(hwc) (hwc->config_base & 0x1F) @@ -160,7 +183,6 @@ static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, static struct attribute *phytium_pcie_pmu_format_attr[] = { PHYTIUM_PCIE_PMU_FORMAT_ATTR(event, "config:0-4"), PHYTIUM_PCIE_PMU_FORMAT_ATTR(ctrler, "config:8-10"), - PHYTIUM_PCIE_PMU_FORMAT_ATTR(timer, "config1:0-31"), NULL, }; @@ -219,11 +241,6 @@ static u32 phytium_pcie_pmu_get_event_ctrler(struct perf_event *event) return FIELD_GET(GENMASK(10, 8), event->attr.config); } -static u32 phytium_pcie_pmu_get_event_timer(struct perf_event *event) -{ - return FIELD_GET(GENMASK(31, 0), event->attr.config1); -} - static u64 phytium_pcie_pmu_read_counter(struct phytium_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) { @@ -233,12 +250,16 @@ static u64 phytium_pcie_pmu_read_counter(struct phytium_pcie_pmu *pcie_pmu, u64 val64 = 0; int i; u32 counter_offset = pcie_counter_reg_offset[idx]; + u32 rdelay_num = 127; if (!EVENT_VALID(idx)) { dev_err(pcie_pmu->dev, "Unsupported event index:%d!\n", idx); return 0; } + if (pcie_pmu->soc_version == PS240XX && pcie_pmu->pmu_id == 3) + rdelay_num = 63; + switch (idx) { case 0: cycle_l = readl(pcie_pmu->base + counter_offset); @@ -253,7 +274,7 @@ static u64 phytium_pcie_pmu_read_counter(struct phytium_pcie_pmu *pcie_pmu, } break; case 16: - for (i = 0; i <= 127; i = i + 2) { + for (i = 0; i <= rdelay_num; i = i + 2) { rdelay_l = readl(pcie_pmu->base + counter_offset + 4 * i); rdelay_h = readl(pcie_pmu->base + counter_offset + @@ -281,38 +302,40 @@ static void phytium_pcie_pmu_enable_clk(struct phytium_pcie_pmu *pcie_pmu) { u32 val; - val = readl(pcie_pmu->csr_base); + val = readl(pcie_pmu->cfg_base); val |= (pcie_pmu->clk_bits); - writel(val, pcie_pmu->csr_base); + writel(val, pcie_pmu->cfg_base); } static void phytium_pcie_pmu_disable_clk(struct phytium_pcie_pmu *pcie_pmu) { u32 val; - val = readl(pcie_pmu->csr_base); + val = readl(pcie_pmu->cfg_base); val &= ~(pcie_pmu->clk_bits); - writel(val, pcie_pmu->csr_base); + writel(val, pcie_pmu->cfg_base); } static void phytium_pcie_pmu_select_ctrler(struct phytium_pcie_pmu *pcie_pmu) { - u32 val, offset = 0; + u32 val, offset; + u32 mask = 0xfffffffc; - if (pcie_pmu->pmu_id != 2) - offset = 0xc; - - val = readl(pcie_pmu->csr_base + offset); - - if (pcie_pmu->pmu_id == 2) { - val &= 0xffffffcf; - val |= pcie_pmu->real_ctrler; + if (pcie_pmu->soc_version == PS230XX) { + if (pcie_pmu->pmu_id == 2) { + mask = 0xffffffcf; + offset = 0x0; + } else + offset = 0xc; } else { - val &= 0xfffffffc; - val |= pcie_pmu->real_ctrler; + offset = 0x170; } - writel(val, pcie_pmu->csr_base + offset); + val = readl(pcie_pmu->cfg_base + offset); + val &= mask; + val |= pcie_pmu->real_ctrler; + writel(val, pcie_pmu->cfg_base + offset); + } static void @@ -333,29 +356,6 @@ phytium_pcie_pmu_stop_all_counters(struct phytium_pcie_pmu *pcie_pmu) writel(0x1, pcie_pmu->base + PCIE_STOP_TIMER); } -static void phytium_pcie_pmu_set_timer(struct phytium_pcie_pmu *pcie_pmu, - u32 th_val) -{ - u32 val; - - val = readl(pcie_pmu->base + PCIE_SET_TIMER_L); - val = readl(pcie_pmu->base + PCIE_SET_TIMER_H); - - writel(th_val, pcie_pmu->base + PCIE_SET_TIMER_L); - writel(0, pcie_pmu->base + PCIE_SET_TIMER_H); -} - -static void phytium_pcie_pmu_reset_timer(struct phytium_pcie_pmu *pcie_pmu) -{ - u32 val; - - val = readl(pcie_pmu->base + PCIE_SET_TIMER_L); - val = readl(pcie_pmu->base + PCIE_SET_TIMER_H); - - writel(0xFFFFFFFF, pcie_pmu->base + PCIE_SET_TIMER_L); - writel(0xFFFFFFFF, pcie_pmu->base + PCIE_SET_TIMER_H); -} - static unsigned long phytium_pcie_pmu_get_stop_state(struct phytium_pcie_pmu *pcie_pmu) { @@ -405,7 +405,7 @@ int phytium_pcie_pmu_event_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; struct phytium_pcie_pmu *pcie_pmu; - u32 event_ctrler, event_timer; + u32 event_ctrler; if (event->attr.type != event->pmu->type) return -ENOENT; @@ -426,57 +426,83 @@ int phytium_pcie_pmu_event_init(struct perf_event *event) if (pcie_pmu->on_cpu == -1) return -EINVAL; - event_timer = phytium_pcie_pmu_get_event_timer(event); - if (event_timer != 0) - phytium_pcie_pmu_set_timer(pcie_pmu, event_timer); - - event_ctrler = phytium_pcie_pmu_get_event_ctrler(event); - switch (pcie_pmu->pmu_id) { - case 0: - if (event_ctrler != 0) { - dev_warn(pcie_pmu->dev, - "Wrong ctrler id(%d) for pcie-pmu0!\n", - event_ctrler); - return -EINVAL; + if (pcie_pmu->soc_version == PS240XX) { + event_ctrler = phytium_pcie_pmu_get_event_ctrler(event); + if (pcie_pmu->pmu_id == 2) { + if (event_ctrler == 0) + event_ctrler = 2; + else if ((event_ctrler < 2) || (event_ctrler > 3)) { + dev_warn(pcie_pmu->dev, "Wrong ctrler id(%d) for pcie-pmu2!\n", + event_ctrler); + return -EINVAL; + } + if (pcie_pmu->ctrler_id != event_ctrler) { + pcie_pmu->ctrler_id = event_ctrler; + pcie_pmu->real_ctrler = pcie_pmu->ctrler_id; + phytium_pcie_pmu_select_ctrler(pcie_pmu); + } + } else { + if (event_ctrler != 0) { + dev_warn(pcie_pmu->dev, "Don't need to set ctrler id(%d) for pcie-pmu%d!\n", + event_ctrler, pcie_pmu->pmu_id); + return -EINVAL; + } + pcie_pmu->ctrler_id = pcie_pmu->pmu_id; + pcie_pmu->real_ctrler = pcie_pmu->ctrler_id; } - break; - case 1: - if ((event_ctrler < 1) || (event_ctrler > 3)) { - dev_warn(pcie_pmu->dev, - "Wrong ctrler id(%d) for pcie-pmu1!\n", - event_ctrler); + } else { + event_ctrler = phytium_pcie_pmu_get_event_ctrler(event); + switch (pcie_pmu->pmu_id) { + case 0: + if (event_ctrler != 0) { + dev_warn(pcie_pmu->dev, + "Wrong ctrler id(%d) for pcie-pmu0!\n", + event_ctrler); + return -EINVAL; + } + break; + case 1: + if (event_ctrler == 0) + event_ctrler = 1; + else if ((event_ctrler < 1) || (event_ctrler > 3)) { + dev_warn(pcie_pmu->dev, + "Wrong ctrler id(%d) for pcie-pmu1!\n", + event_ctrler); + return -EINVAL; + } + break; + case 2: + if (event_ctrler == 0) + event_ctrler = 4; + else if ((event_ctrler < 4) || (event_ctrler > 7)) { + dev_warn(pcie_pmu->dev, + "Wrong ctrler id(%d) for pcie-pmu2!\n", + event_ctrler); + return -EINVAL; + } + break; + default: + dev_err(pcie_pmu->dev, "Unsupported pmu id:%d!\n", + pcie_pmu->pmu_id); return -EINVAL; } - break; - case 2: - if ((event_ctrler < 4) || (event_ctrler > 7)) { - dev_warn(pcie_pmu->dev, - "Wrong ctrler id(%d) for pcie-pmu2!\n", - event_ctrler); + + pcie_pmu->ctrler_id = event_ctrler; + switch (pcie_pmu->pmu_id) { + case 0: + case 1: + pcie_pmu->real_ctrler = pcie_pmu->ctrler_id; + break; + case 2: + pcie_pmu->real_ctrler = (pcie_pmu->ctrler_id - 4) * 16; + break; + default: + dev_err(pcie_pmu->dev, "Unsupported pmu id:%d!\n", + pcie_pmu->pmu_id); return -EINVAL; } - break; - default: - dev_err(pcie_pmu->dev, "Unsupported pmu id:%d!\n", - pcie_pmu->pmu_id); - return -EINVAL; - } - - pcie_pmu->ctrler_id = event_ctrler; - switch (pcie_pmu->pmu_id) { - case 0: - case 1: - pcie_pmu->real_ctrler = pcie_pmu->ctrler_id; - break; - case 2: - pcie_pmu->real_ctrler = (pcie_pmu->ctrler_id - 4) * 16; - break; - default: - dev_err(pcie_pmu->dev, "Unsupported pmu id:%d!\n", - pcie_pmu->pmu_id); - return -EINVAL; + phytium_pcie_pmu_select_ctrler(pcie_pmu); } - phytium_pcie_pmu_select_ctrler(pcie_pmu); hwc->idx = -1; hwc->config_base = event->attr.config; @@ -536,17 +562,12 @@ void phytium_pcie_pmu_event_del(struct perf_event *event, int flags) struct phytium_pcie_pmu *pcie_pmu = to_phytium_pcie_pmu(event->pmu); struct hw_perf_event *hwc = &event->hw; unsigned long val; - u32 event_timer; phytium_pcie_pmu_event_stop(event, PERF_EF_UPDATE); val = phytium_pcie_pmu_get_irq_flag(pcie_pmu); val = phytium_pcie_pmu_get_stop_state(pcie_pmu); phytium_pcie_pmu_unmark_event(pcie_pmu, hwc->idx); - event_timer = phytium_pcie_pmu_get_event_timer(event); - if (event_timer != 0) - phytium_pcie_pmu_reset_timer(pcie_pmu); - perf_event_update_userpage(event); pcie_pmu->pmu_events.hw_events[hwc->idx] = NULL; } @@ -573,6 +594,12 @@ void phytium_pcie_pmu_disable(struct pmu *pmu) phytium_pcie_pmu_stop_all_counters(pcie_pmu); } +void phytium_pcie_pmu_reset(struct phytium_pcie_pmu *pcie_pmu) +{ + phytium_pcie_pmu_disable_clk(pcie_pmu); + phytium_pcie_pmu_clear_all_counters(pcie_pmu); +} + static const struct acpi_device_id phytium_pcie_pmu_acpi_match[] = { { "PHYT0044", @@ -592,7 +619,7 @@ static irqreturn_t phytium_pcie_pmu_overflow_handler(int irq, void *dev_id) overflown = phytium_pcie_pmu_get_irq_flag(pcie_pmu); - if (!test_bit(pcie_pmu->pmu_id + 4, &overflown)) + if (!test_bit(pcie_pmu->irq_bit, &overflown)) return IRQ_NONE; stop_state = phytium_pcie_pmu_get_stop_state(pcie_pmu); @@ -605,7 +632,8 @@ static irqreturn_t phytium_pcie_pmu_overflow_handler(int irq, void *dev_id) phytium_pcie_pmu_event_update(event); } phytium_pcie_pmu_clear_all_counters(pcie_pmu); - phytium_pcie_pmu_start_all_counters(pcie_pmu); + if ((stop_state & 0x10) == 0) + phytium_pcie_pmu_start_all_counters(pcie_pmu); return IRQ_HANDLED; } @@ -641,9 +669,14 @@ static int phytium_pcie_pmu_init_irq(struct phytium_pcie_pmu *pcie_pmu, } static int phytium_pcie_pmu_init_data(struct platform_device *pdev, - struct phytium_pcie_pmu *pcie_pmu) + struct phytium_pcie_pmu *pcie_pmu) { struct resource *res, *clkres, *irqres; + pcie_pmu->soc_version = phytium_socs_type(); + if (pcie_pmu->soc_version == 0) { + dev_err(&pdev->dev, "The PCIe PMU driver can't be installed in this SoC.\n"); + return -EINVAL; + } if (device_property_read_u32(&pdev->dev, "phytium,die-id", &pcie_pmu->die_id)) { @@ -657,20 +690,46 @@ static int phytium_pcie_pmu_init_data(struct platform_device *pdev, return -EINVAL; } - switch (pcie_pmu->pmu_id) { - case 0: - pcie_pmu->clk_bits = 0x1; - break; - case 1: - pcie_pmu->clk_bits = 0xe; - break; - case 2: - pcie_pmu->clk_bits = 0xf; - break; - default: - dev_err(&pdev->dev, "Unsupported pmu id:%d!\n", - pcie_pmu->pmu_id); - break; + if (pcie_pmu->soc_version == PS230XX) { + switch (pcie_pmu->pmu_id) { + case 0: + pcie_pmu->clk_bits = 0x1; + break; + case 1: + pcie_pmu->clk_bits = 0xe; + break; + case 2: + pcie_pmu->clk_bits = 0xf; + break; + default: + dev_err(&pdev->dev, "Unsupported pmu id:%d!\n", pcie_pmu->pmu_id); + break; + } + + pcie_pmu->irq_bit = pcie_pmu->pmu_id + 4; + } else { + if (device_property_read_u32(&pdev->dev, "phytium,pcie-id", &pcie_pmu->pcie_id)) { + dev_err(&pdev->dev, "Can not read phytium,pcie-id!\n"); + return -EINVAL; + } + + switch (pcie_pmu->pmu_id) { + case 0: + case 3: + pcie_pmu->clk_bits = 0x1; + break; + case 1: + pcie_pmu->clk_bits = 0x2; + break; + case 2: + pcie_pmu->clk_bits = 0xc; + break; + default: + dev_err(&pdev->dev, "Unsupported pmu id:%d!\n", pcie_pmu->pmu_id); + break; + } + + pcie_pmu->irq_bit = pcie_pmu->pcie_id * 4 + pcie_pmu->pmu_id + 16; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -686,12 +745,12 @@ static int phytium_pcie_pmu_init_data(struct platform_device *pdev, return -EINVAL; } - pcie_pmu->csr_base = + pcie_pmu->cfg_base = devm_ioremap(&pdev->dev, clkres->start, resource_size(clkres)); - if (IS_ERR(pcie_pmu->csr_base)) { + if (IS_ERR(pcie_pmu->cfg_base)) { dev_err(&pdev->dev, "ioremap failed for pcie_pmu csr resource\n"); - return PTR_ERR(pcie_pmu->csr_base); + return PTR_ERR(pcie_pmu->cfg_base); } irqres = platform_get_resource(pdev, IORESOURCE_MEM, 2); @@ -709,11 +768,13 @@ static int phytium_pcie_pmu_init_data(struct platform_device *pdev, return PTR_ERR(pcie_pmu->irq_reg); } + phytium_pcie_pmu_reset(pcie_pmu); + return 0; } static int phytium_pcie_pmu_dev_probe(struct platform_device *pdev, - struct phytium_pcie_pmu *pcie_pmu) + struct phytium_pcie_pmu *pcie_pmu) { int ret; @@ -754,8 +815,12 @@ static int phytium_pcie_pmu_probe(struct platform_device *pdev) return ret; } - name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "phyt%u_pcie_pmu%u", - pcie_pmu->die_id, pcie_pmu->pmu_id); + if (pcie_pmu->soc_version == PS230XX) + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "phyt%u_pcie_pmu%u", + pcie_pmu->die_id, pcie_pmu->pmu_id); + else + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "phyt%u_pcie%u_pmu%u", + pcie_pmu->die_id, pcie_pmu->pcie_id, pcie_pmu->pmu_id); pcie_pmu->pmu = (struct pmu){ .name = name, .module = THIS_MODULE, @@ -769,7 +834,6 @@ static int phytium_pcie_pmu_probe(struct platform_device *pdev) .stop = phytium_pcie_pmu_event_stop, .read = phytium_pcie_pmu_event_update, .attr_groups = phytium_pcie_pmu_attr_groups, - .capabilities = PERF_PMU_CAP_NO_EXCLUDE, }; ret = perf_pmu_register(&pcie_pmu->pmu, name, -1); @@ -782,9 +846,12 @@ static int phytium_pcie_pmu_probe(struct platform_device *pdev) phytium_pcie_pmu_enable_clk(pcie_pmu); - pr_info("Phytium PCIe PMU: "); - pr_info("die_id = %d pmu_id = %d.\n", pcie_pmu->die_id, - pcie_pmu->pmu_id); + if (pcie_pmu->soc_version == PS230XX) + pr_info("die%d_pcie_pmu%d on cpu%d.\n", + pcie_pmu->die_id, pcie_pmu->pmu_id, pcie_pmu->on_cpu); + else + pr_info("die%d_pcie%d_pmu%d on cpu%d.\n", + pcie_pmu->die_id, pcie_pmu->pcie_id, pcie_pmu->pmu_id, pcie_pmu->on_cpu); return ret; } @@ -826,6 +893,7 @@ int phytium_pcie_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) pcie_pmu->on_cpu = cpu; WARN_ON(irq_set_affinity_hint(pcie_pmu->irq, cpumask_of(cpu))); } + return 0; } @@ -872,8 +940,8 @@ static int __init phytium_pcie_pmu_module_init(void) phytium_pcie_pmu_hp_state = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, - "perf/phytium/pciepmu:online", - phytium_pcie_pmu_online_cpu, phytium_pcie_pmu_offline_cpu); + "perf/phytium/pciepmu:online", phytium_pcie_pmu_online_cpu, + phytium_pcie_pmu_offline_cpu); if (phytium_pcie_pmu_hp_state < 0) { pr_err("PCIE PMU: setup hotplug, ret = %d\n", phytium_pcie_pmu_hp_state); @@ -900,3 +968,4 @@ MODULE_DESCRIPTION("Phytium PCIe PMU driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(PCIE_PERF_DRIVER_VERSION); MODULE_AUTHOR("Hu Xianghua "); +MODULE_AUTHOR("Tan Rui "); -- Gitee From 77f3361bb93c9093bb586c5b654f59b8c1d6f971 Mon Sep 17 00:00:00 2001 From: Wang Yinfeng Date: Fri, 6 Dec 2024 08:49:02 +0800 Subject: [PATCH 115/121] drivers/perf:phytium: Added some functional improvements for DDR PMU. e.g.. 1. Remove support for timer parameter. 2. Add the operation of resetting pmu before driver installion. 3. Add support for new phytium SoC. Mainline: NA Signed-off-by: Tan Rui Signed-off-by: Wang Yinfeng > Change-Id: I70d6388c5244f1e5730917f87ee0628235453ddf --- drivers/perf/phytium/phytium_ddr_pmu.c | 203 ++++++++++++++----------- 1 file changed, 110 insertions(+), 93 deletions(-) diff --git a/drivers/perf/phytium/phytium_ddr_pmu.c b/drivers/perf/phytium/phytium_ddr_pmu.c index 13b91b95d4..37ea145872 100644 --- a/drivers/perf/phytium/phytium_ddr_pmu.c +++ b/drivers/perf/phytium/phytium_ddr_pmu.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -30,31 +31,56 @@ #undef pr_fmt #define pr_fmt(fmt) "phytium_ddr_pmu: " fmt -#define DDR_PERF_DRIVER_VERSION "1.2.1" #define PHYTIUM_DDR_MAX_COUNTERS 8 +#define DDR_PERF_DRIVER_VERSION "1.3.0" + +#define DDR_START_TIMER 0x000 +#define DDR_STOP_TIMER 0x004 +#define DDR_CLEAR_EVENT 0x008 +#define DDR_SET_TIMER_L 0x00c +#define DDR_SET_TIMER_H 0x010 +#define DDR_TRIG_MODE 0x014 +#define DDR_NOW_STATE 0x0e0 +#define DDR_EVENT_CYCLES 0x0e4 +#define DDR_TPOINT_END_L 0x0e4 +#define DDR_TPOINT_END_H 0x0e8 +#define DDR_STATE_STOP 0x0ec +#define DDR_EVENT_RXREQ 0x100 +#define DDR_EVENT_RXDAT 0x104 +#define DDR_EVENT_TXDAT 0x108 +#define DDR_EVENT_RXREQ_RNS 0x10c +#define DDR_EVENT_RXREQ_WNSP 0x110 +#define DDR_EVENT_RXREQ_WNSF 0x114 +#define DDR_EVENT_BANDWIDTH 0x200 +#define DDR_W_DATA_BASE 0x200 +#define DDR_CLK_FRE 0xe00 +#define DDR_DATA_WIDTH 0xe04 + +#define SOC_ID_PS230XX 0x8 +#define SOC_ID_PS240XX 0x6 +#define MIDR_PSXX 0x700F8620 + +enum { + PS230XX = 0x01, + PS240XX = 0x02, +}; + +static inline int phytium_socs_type(void) +{ + unsigned int soc_id; + unsigned int midr; -#define DDR_START_TIMER 0x000 -#define DDR_STOP_TIMER 0x004 -#define DDR_CLEAR_EVENT 0x008 -#define DDR_SET_TIMER_L 0x00c -#define DDR_SET_TIMER_H 0x010 -#define DDR_TRIG_MODE 0x014 -#define DDR_NOW_STATE 0x0e0 -#define DDR_EVENT_CYCLES 0x0e4 -#define DDR_TPOINT_END_L 0x0e4 -#define DDR_TPOINT_END_H 0x0e8 -#define DDR_STATE_STOP 0x0ec -#define DDR_EVENT_RXREQ 0x100 -#define DDR_EVENT_RXDAT 0x104 -#define DDR_EVENT_TXDAT 0x108 -#define DDR_EVENT_RXREQ_RNS 0x10c -#define DDR_EVENT_RXREQ_WNSP 0x110 -#define DDR_EVENT_RXREQ_WNSF 0x114 -#define DDR_EVENT_BANDWIDTH 0x200 -#define DDR_W_DATA_BASE 0x200 -#define DDR_CLK_FRE 0xe00 -#define DDR_DATA_WIDTH 0xe04 + soc_id = read_sysreg_s(SYS_AIDR_EL1); + midr = read_cpuid_id(); + + if ((soc_id == SOC_ID_PS230XX) && (midr == MIDR_PSXX)) + return PS230XX; + if ((soc_id == SOC_ID_PS240XX) && (midr == MIDR_PSXX)) + return PS240XX; + else + return 0; +} #define to_phytium_ddr_pmu(p) (container_of(p, struct phytium_ddr_pmu, pmu)) @@ -68,15 +94,17 @@ struct phytium_ddr_pmu_hwevents { struct phytium_ddr_pmu { struct device *dev; void __iomem *base; - void __iomem *csr_base; + void __iomem *cfg_base; + void __iomem *irq_reg; struct pmu pmu; struct phytium_ddr_pmu_hwevents pmu_events; u32 die_id; u32 ddr_id; u32 pmu_id; - int bit_idx; + int irq_bit; int on_cpu; int irq; + int soc_version; struct hlist_node node; }; @@ -120,22 +148,21 @@ static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, return cpumap_print_to_pagebuf(true, buf, cpumask_of(ddr_pmu->on_cpu)); } -#define PHYTIUM_PMU_ATTR(_name, _func, _config) \ - (&((struct dev_ext_attribute[]){ \ +#define PHYTIUM_PMU_ATTR(_name, _func, _config) \ + (&((struct dev_ext_attribute[]){ \ { __ATTR(_name, 0444, _func, NULL), (void *)_config } })[0] \ .attr.attr) -#define PHYTIUM_DDR_PMU_FORMAT_ATTR(_name, _config) \ +#define PHYTIUM_DDR_PMU_FORMAT_ATTR(_name, _config) \ PHYTIUM_PMU_ATTR(_name, phytium_ddr_pmu_format_sysfs_show, \ (void *)_config) -#define PHYTIUM_DDR_PMU_EVENT_ATTR(_name, _config) \ +#define PHYTIUM_DDR_PMU_EVENT_ATTR(_name, _config) \ PHYTIUM_PMU_ATTR(_name, phytium_ddr_pmu_event_sysfs_show, \ (unsigned long)_config) static struct attribute *phytium_ddr_pmu_format_attr[] = { PHYTIUM_DDR_PMU_FORMAT_ATTR(event, "config:0-2"), - PHYTIUM_DDR_PMU_FORMAT_ATTR(timer, "config1:0-31"), NULL, }; @@ -179,11 +206,6 @@ static const struct attribute_group *phytium_ddr_pmu_attr_groups[] = { NULL, }; -static u32 phytium_ddr_pmu_get_event_timer(struct perf_event *event) -{ - return FIELD_GET(GENMASK(31, 0), event->attr.config1); -} - static u64 phytium_ddr_pmu_read_counter(struct phytium_ddr_pmu *ddr_pmu, struct hw_perf_event *hwc) { @@ -223,18 +245,18 @@ static void phytium_ddr_pmu_enable_clk(struct phytium_ddr_pmu *ddr_pmu) { u32 val; - val = readl(ddr_pmu->csr_base); + val = readl(ddr_pmu->cfg_base); val |= 0xF; - writel(val, ddr_pmu->csr_base); + writel(val, ddr_pmu->cfg_base); } static void phytium_ddr_pmu_disable_clk(struct phytium_ddr_pmu *ddr_pmu) { u32 val; - val = readl(ddr_pmu->csr_base); + val = readl(ddr_pmu->cfg_base); val &= ~(0xF); - writel(val, ddr_pmu->csr_base); + writel(val, ddr_pmu->cfg_base); } static void phytium_ddr_pmu_clear_all_counters(struct phytium_ddr_pmu *ddr_pmu) @@ -252,29 +274,6 @@ static void phytium_ddr_pmu_stop_all_counters(struct phytium_ddr_pmu *ddr_pmu) writel(0x1, ddr_pmu->base + DDR_STOP_TIMER); } -static void phytium_ddr_pmu_set_timer(struct phytium_ddr_pmu *ddr_pmu, - u32 th_val) -{ - u32 val; - - val = readl(ddr_pmu->base + DDR_SET_TIMER_L); - val = readl(ddr_pmu->base + DDR_SET_TIMER_H); - - writel(th_val, ddr_pmu->base + DDR_SET_TIMER_L); - writel(0, ddr_pmu->base + DDR_SET_TIMER_H); -} - -static void phytium_ddr_pmu_reset_timer(struct phytium_ddr_pmu *ddr_pmu) -{ - u32 val; - - val = readl(ddr_pmu->base + DDR_SET_TIMER_L); - val = readl(ddr_pmu->base + DDR_SET_TIMER_H); - - writel(0xFFFFFFFF, ddr_pmu->base + DDR_SET_TIMER_L); - writel(0xFFFFFFFF, ddr_pmu->base + DDR_SET_TIMER_H); -} - static unsigned long phytium_ddr_pmu_get_stop_state(struct phytium_ddr_pmu *ddr_pmu) { @@ -289,7 +288,7 @@ phytium_ddr_pmu_get_irq_flag(struct phytium_ddr_pmu *ddr_pmu) { unsigned long val; - val = (unsigned long)readl(ddr_pmu->csr_base + 4); + val = (unsigned long)readl(ddr_pmu->irq_reg); return val; } @@ -324,7 +323,6 @@ int phytium_ddr_pmu_event_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; struct phytium_ddr_pmu *ddr_pmu; - u32 event_timer; if (event->attr.type != event->pmu->type) return -ENOENT; @@ -345,10 +343,6 @@ int phytium_ddr_pmu_event_init(struct perf_event *event) if (ddr_pmu->on_cpu == -1) return -EINVAL; - event_timer = phytium_ddr_pmu_get_event_timer(event); - if (event_timer != 0) - phytium_ddr_pmu_set_timer(ddr_pmu, event_timer); - hwc->idx = -1; hwc->config_base = event->attr.config; @@ -408,16 +402,12 @@ void phytium_ddr_pmu_event_del(struct perf_event *event, int flags) struct phytium_ddr_pmu *ddr_pmu = to_phytium_ddr_pmu(event->pmu); struct hw_perf_event *hwc = &event->hw; unsigned long val; - u32 event_timer; phytium_ddr_pmu_event_stop(event, PERF_EF_UPDATE); val = phytium_ddr_pmu_get_irq_flag(ddr_pmu); val = phytium_ddr_pmu_get_stop_state(ddr_pmu); phytium_ddr_pmu_unmark_event(ddr_pmu, hwc->idx); - event_timer = phytium_ddr_pmu_get_event_timer(event); - if (event_timer != 0) - phytium_ddr_pmu_reset_timer(ddr_pmu); perf_event_update_userpage(event); ddr_pmu->pmu_events.hw_events[hwc->idx] = NULL; @@ -445,6 +435,12 @@ void phytium_ddr_pmu_disable(struct pmu *pmu) phytium_ddr_pmu_stop_all_counters(ddr_pmu); } +void phytium_ddr_pmu_reset(struct phytium_ddr_pmu *ddr_pmu) +{ + phytium_ddr_pmu_disable_clk(ddr_pmu); + phytium_ddr_pmu_clear_all_counters(ddr_pmu); +} + static const struct acpi_device_id phytium_ddr_pmu_acpi_match[] = { { "PHYT0043", @@ -458,14 +454,13 @@ static irqreturn_t phytium_ddr_pmu_overflow_handler(int irq, void *dev_id) struct phytium_ddr_pmu *ddr_pmu = dev_id; struct perf_event *event; unsigned long overflown, stop_state; - int idx; unsigned long *used_mask = ddr_pmu->pmu_events.used_mask; - + int idx; int event_added = bitmap_weight(used_mask, PHYTIUM_DDR_MAX_COUNTERS); overflown = phytium_ddr_pmu_get_irq_flag(ddr_pmu); - if (!test_bit(ddr_pmu->bit_idx, &overflown)) + if (!test_bit(ddr_pmu->irq_bit, &overflown)) return IRQ_NONE; stop_state = phytium_ddr_pmu_get_stop_state(ddr_pmu); @@ -477,8 +472,10 @@ static irqreturn_t phytium_ddr_pmu_overflow_handler(int irq, void *dev_id) continue; phytium_ddr_pmu_event_update(event); } + phytium_ddr_pmu_clear_all_counters(ddr_pmu); - phytium_ddr_pmu_start_all_counters(ddr_pmu); + if ((stop_state & 0x10) == 0) + phytium_ddr_pmu_start_all_counters(ddr_pmu); return IRQ_HANDLED; } @@ -518,7 +515,15 @@ static int phytium_ddr_pmu_init_irq(struct phytium_ddr_pmu *ddr_pmu, static int phytium_ddr_pmu_init_data(struct platform_device *pdev, struct phytium_ddr_pmu *ddr_pmu) { - struct resource *res, *clkres; + struct resource *res, *clkres, *irqres; + + ddr_pmu->soc_version = phytium_socs_type(); + + + if ((ddr_pmu->soc_version != PS230XX) || (ddr_pmu->soc_version != PS240XX)) { + dev_err(&pdev->dev, "The DDR PMU driver can't be installed in this SoC.\n"); + return -EINVAL; + } if (device_property_read_u32(&pdev->dev, "phytium,die-id", &ddr_pmu->die_id)) { @@ -538,7 +543,7 @@ static int phytium_ddr_pmu_init_data(struct platform_device *pdev, return -EINVAL; } - ddr_pmu->bit_idx = ddr_pmu->ddr_id * 2 + ddr_pmu->pmu_id; + ddr_pmu->irq_bit = ddr_pmu->ddr_id * 2 + ddr_pmu->pmu_id; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ddr_pmu->base = devm_ioremap_resource(&pdev->dev, res); @@ -554,15 +559,29 @@ static int phytium_ddr_pmu_init_data(struct platform_device *pdev, dev_err(&pdev->dev, "failed for get ddr_pmu clk resource.\n"); return -EINVAL; } + ddr_pmu->cfg_base = devm_ioremap(&pdev->dev, clkres->start, resource_size(clkres)); + if (IS_ERR(ddr_pmu->cfg_base)) { + dev_err(&pdev->dev, "ioremap failed for ddr_pmu clk resource\n"); + return PTR_ERR(ddr_pmu->cfg_base); + } - ddr_pmu->csr_base = - devm_ioremap(&pdev->dev, clkres->start, resource_size(clkres)); - if (IS_ERR(ddr_pmu->csr_base)) { - dev_err(&pdev->dev, - "ioremap failed for ddr_pmu csr resource\n"); - return PTR_ERR(ddr_pmu->csr_base); + if (ddr_pmu->soc_version == PS240XX) { + irqres = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (!irqres) { + dev_err(&pdev->dev, "failed for get ddr_pmu irq resource.\n"); + return -EINVAL; + } + ddr_pmu->irq_reg = devm_ioremap(&pdev->dev, irqres->start, resource_size(irqres)); + if (IS_ERR(ddr_pmu->irq_reg)) { + dev_err(&pdev->dev, "ioremap failed for ddr_pmu irq resource\n"); + return PTR_ERR(ddr_pmu->irq_reg); + } + } else { + ddr_pmu->irq_reg = ddr_pmu->cfg_base + 0x4; } + phytium_ddr_pmu_reset(ddr_pmu); + return 0; } @@ -601,8 +620,8 @@ static int phytium_ddr_pmu_probe(struct platform_device *pdev) if (ret) return ret; - ret = cpuhp_state_add_instance( - phytium_ddr_pmu_hp_state, &ddr_pmu->node); + ret = cpuhp_state_add_instance(phytium_ddr_pmu_hp_state, + &ddr_pmu->node); if (ret) { dev_err(&pdev->dev, "Error %d registering hotplug;\n", ret); return ret; @@ -624,22 +643,19 @@ static int phytium_ddr_pmu_probe(struct platform_device *pdev) .stop = phytium_ddr_pmu_event_stop, .read = phytium_ddr_pmu_event_update, .attr_groups = phytium_ddr_pmu_attr_groups, - .capabilities = PERF_PMU_CAP_NO_EXCLUDE, }; ret = perf_pmu_register(&ddr_pmu->pmu, name, -1); if (ret) { dev_err(ddr_pmu->dev, "DDR PMU register failed!\n"); - cpuhp_state_remove_instance_nocalls( - phytium_ddr_pmu_hp_state, + cpuhp_state_remove_instance_nocalls(phytium_ddr_pmu_hp_state, &ddr_pmu->node); } phytium_ddr_pmu_enable_clk(ddr_pmu); - pr_info("Phytium DDR PMU: "); - pr_info(" die_id = %d ddr_id = %d pmu_id = %d.\n", ddr_pmu->die_id, - ddr_pmu->ddr_id, ddr_pmu->pmu_id); + pr_info("die%d_ddr%d_pmu%d on cpu%d.\n", ddr_pmu->die_id, + ddr_pmu->ddr_id, ddr_pmu->pmu_id, ddr_pmu->on_cpu); return ret; } @@ -651,8 +667,8 @@ static int phytium_ddr_pmu_remove(struct platform_device *pdev) phytium_ddr_pmu_disable_clk(ddr_pmu); perf_pmu_unregister(&ddr_pmu->pmu); - cpuhp_state_remove_instance_nocalls( - phytium_ddr_pmu_hp_state, &ddr_pmu->node); + cpuhp_state_remove_instance_nocalls(phytium_ddr_pmu_hp_state, + &ddr_pmu->node); return 0; } @@ -754,3 +770,4 @@ MODULE_DESCRIPTION("Phytium DDR PMU driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DDR_PERF_DRIVER_VERSION); MODULE_AUTHOR("Hu Xianghua "); +MODULE_AUTHOR("Tan Rui "); -- Gitee From 0b6ab33005651b77eeac7c35dd4b2f6428aced9b Mon Sep 17 00:00:00 2001 From: Tan Rui Date: Thu, 26 Dec 2024 09:47:28 +0800 Subject: [PATCH 116/121] drivers/perf: phytium: Adjust operations of DDR PMU clock Remove clock related operations for PS240XX platforms. Mainline: NA Signed-off-by: Tan Rui Signed-off-by: Wang Yinfeng Change-Id: I4a72fb7b3412d72210e12f3eb4b175d2b6ad2f70 --- drivers/perf/phytium/phytium_ddr_pmu.c | 56 ++++++++++++++------------ 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/drivers/perf/phytium/phytium_ddr_pmu.c b/drivers/perf/phytium/phytium_ddr_pmu.c index 37ea145872..8fd6f997c4 100644 --- a/drivers/perf/phytium/phytium_ddr_pmu.c +++ b/drivers/perf/phytium/phytium_ddr_pmu.c @@ -57,10 +57,14 @@ #define DDR_CLK_FRE 0xe00 #define DDR_DATA_WIDTH 0xe04 +#define DDR_PMU_OFL_STOP_TYPE_VAL 0x10 + #define SOC_ID_PS230XX 0x8 #define SOC_ID_PS240XX 0x6 #define MIDR_PSXX 0x700F8620 +#define to_phytium_ddr_pmu(p) (container_of(p, struct phytium_ddr_pmu, pmu)) + enum { PS230XX = 0x01, PS240XX = 0x02, @@ -68,22 +72,19 @@ enum { static inline int phytium_socs_type(void) { - unsigned int soc_id; - unsigned int midr; + unsigned int soc_id, cpu_id; soc_id = read_sysreg_s(SYS_AIDR_EL1); - midr = read_cpuid_id(); + cpu_id = read_cpuid_id(); - if ((soc_id == SOC_ID_PS230XX) && (midr == MIDR_PSXX)) + if ((soc_id == SOC_ID_PS230XX) && (cpu_id == MIDR_PSXX)) return PS230XX; - if ((soc_id == SOC_ID_PS240XX) && (midr == MIDR_PSXX)) + else if ((soc_id == SOC_ID_PS240XX) && (cpu_id == MIDR_PSXX)) return PS240XX; else return 0; } -#define to_phytium_ddr_pmu(p) (container_of(p, struct phytium_ddr_pmu, pmu)) - static int phytium_ddr_pmu_hp_state; struct phytium_ddr_pmu_hwevents { @@ -117,20 +118,20 @@ static const u32 ddr_counter_reg_offset[] = { DDR_EVENT_RXREQ_WNSF, DDR_EVENT_BANDWIDTH }; + ssize_t phytium_ddr_pmu_format_sysfs_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct dev_ext_attribute *eattr; eattr = container_of(attr, struct dev_ext_attribute, attr); - return sprintf(buf, "%s\n", (char *)eattr->var); } ssize_t phytium_ddr_pmu_event_sysfs_show(struct device *dev, - struct device_attribute *attr, - char *page) + struct device_attribute *attr, + char *page) { struct dev_ext_attribute *eattr; @@ -140,7 +141,7 @@ ssize_t phytium_ddr_pmu_event_sysfs_show(struct device *dev, } static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct phytium_ddr_pmu *ddr_pmu = to_phytium_ddr_pmu(dev_get_drvdata(dev)); @@ -149,17 +150,17 @@ static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, } #define PHYTIUM_PMU_ATTR(_name, _func, _config) \ - (&((struct dev_ext_attribute[]){ \ - { __ATTR(_name, 0444, _func, NULL), (void *)_config } })[0] \ - .attr.attr) + (&((struct dev_ext_attribute[]){ \ + { __ATTR(_name, 0444, _func, NULL), (void *)_config } })[0] \ + .attr.attr) #define PHYTIUM_DDR_PMU_FORMAT_ATTR(_name, _config) \ - PHYTIUM_PMU_ATTR(_name, phytium_ddr_pmu_format_sysfs_show, \ - (void *)_config) + PHYTIUM_PMU_ATTR(_name, phytium_ddr_pmu_format_sysfs_show, \ + (void *)_config) #define PHYTIUM_DDR_PMU_EVENT_ATTR(_name, _config) \ - PHYTIUM_PMU_ATTR(_name, phytium_ddr_pmu_event_sysfs_show, \ - (unsigned long)_config) + PHYTIUM_PMU_ATTR(_name, phytium_ddr_pmu_event_sysfs_show, \ + (unsigned long)_config) static struct attribute *phytium_ddr_pmu_format_attr[] = { PHYTIUM_DDR_PMU_FORMAT_ATTR(event, "config:0-2"), @@ -245,6 +246,9 @@ static void phytium_ddr_pmu_enable_clk(struct phytium_ddr_pmu *ddr_pmu) { u32 val; + if (ddr_pmu->soc_version == PS240XX) + return; + val = readl(ddr_pmu->cfg_base); val |= 0xF; writel(val, ddr_pmu->cfg_base); @@ -254,6 +258,9 @@ static void phytium_ddr_pmu_disable_clk(struct phytium_ddr_pmu *ddr_pmu) { u32 val; + if (ddr_pmu->soc_version == PS240XX) + return; + val = readl(ddr_pmu->cfg_base); val &= ~(0xF); writel(val, ddr_pmu->cfg_base); @@ -408,7 +415,6 @@ void phytium_ddr_pmu_event_del(struct perf_event *event, int flags) val = phytium_ddr_pmu_get_stop_state(ddr_pmu); phytium_ddr_pmu_unmark_event(ddr_pmu, hwc->idx); - perf_event_update_userpage(event); ddr_pmu->pmu_events.hw_events[hwc->idx] = NULL; } @@ -474,7 +480,7 @@ static irqreturn_t phytium_ddr_pmu_overflow_handler(int irq, void *dev_id) } phytium_ddr_pmu_clear_all_counters(ddr_pmu); - if ((stop_state & 0x10) == 0) + if ((stop_state & DDR_PMU_OFL_STOP_TYPE_VAL) == 0) phytium_ddr_pmu_start_all_counters(ddr_pmu); return IRQ_HANDLED; @@ -518,10 +524,8 @@ static int phytium_ddr_pmu_init_data(struct platform_device *pdev, struct resource *res, *clkres, *irqres; ddr_pmu->soc_version = phytium_socs_type(); - - - if ((ddr_pmu->soc_version != PS230XX) || (ddr_pmu->soc_version != PS240XX)) { - dev_err(&pdev->dev, "The DDR PMU driver can't be installed in this SoC.\n"); + if (ddr_pmu->soc_version == 0) { + dev_err(&pdev->dev, "The DDR PMU driver can't be installed in this SoC!\n"); return -EINVAL; } -- Gitee From 00ef74b0d5bbb696119e0e2f23531a0a3d1db4e7 Mon Sep 17 00:00:00 2001 From: Tan Rui Date: Thu, 26 Dec 2024 10:21:44 +0800 Subject: [PATCH 117/121] drivers/perf: phytium: Add Interrupt Status Macro for PCIe PMU Add a macro of interrupt status information for PCIe PMU driver. Mainline: NA Signed-off-by: Tan Rui Signed-off-by: Wang Yinfeng Change-Id: Iab719e1fd14c271b6f5eac25935c58caf06b9c0d --- drivers/perf/phytium/phytium_pcie_pmu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/perf/phytium/phytium_pcie_pmu.c b/drivers/perf/phytium/phytium_pcie_pmu.c index 20cf9458a6..80a931e4e4 100644 --- a/drivers/perf/phytium/phytium_pcie_pmu.c +++ b/drivers/perf/phytium/phytium_pcie_pmu.c @@ -69,6 +69,8 @@ #define PCIE_DATA_WIDTH 0xe04 +#define PCIE_PMU_OFL_STOP_TYPE_VAL 0x10 + #define SYS_AIDR_EL1 sys_reg(3, 1, 0, 0, 7) #define SOC_ID_PS230XX 0x8 #define SOC_ID_PS240XX 0x6 @@ -632,7 +634,7 @@ static irqreturn_t phytium_pcie_pmu_overflow_handler(int irq, void *dev_id) phytium_pcie_pmu_event_update(event); } phytium_pcie_pmu_clear_all_counters(pcie_pmu); - if ((stop_state & 0x10) == 0) + if ((stop_state & PCIE_PMU_OFL_STOP_TYPE_VAL) == 0) phytium_pcie_pmu_start_all_counters(pcie_pmu); return IRQ_HANDLED; -- Gitee From abd8eb240f08835e03fe98f3111dd2c198d00e20 Mon Sep 17 00:00:00 2001 From: liutianyu1250 Date: Sat, 8 Feb 2025 15:47:24 +0800 Subject: [PATCH 118/121] arm64: phytium_config: select new phytium driver Signed-off-by: liutianyu1250 --- arch/arm64/configs/phytium_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/phytium_defconfig b/arch/arm64/configs/phytium_defconfig index 8dddafbf05..3cb88a2efe 100644 --- a/arch/arm64/configs/phytium_defconfig +++ b/arch/arm64/configs/phytium_defconfig @@ -381,6 +381,7 @@ CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_PHYTIUM_PCI=y CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y CONFIG_SERIAL_FSL_LPUART=y @@ -836,6 +837,8 @@ CONFIG_DEVFREQ_GOV_PERFORMANCE=y CONFIG_DEVFREQ_GOV_POWERSAVE=y CONFIG_DEVFREQ_GOV_USERSPACE=y CONFIG_DEVFREQ_GOV_PASSIVE=m +CONFIG_ARM_PHYTIUM_NOC_DEVFREQ=y +CONFIG_ARM_PHYTIUM_DMU_DEVFREQ=y CONFIG_EXTCON_PTN5150=m CONFIG_EXTCON_USB_GPIO=y CONFIG_EXTCON_USBC_CROS_EC=y -- Gitee From 32c3ebb20de9f8538720885b55793a8c9ce93061 Mon Sep 17 00:00:00 2001 From: zuoqian Date: Wed, 26 Feb 2025 02:38:44 +0000 Subject: [PATCH 119/121] net: phy: phy_device: fix PHY WOL enabled, PM failed to suspend If the PHY of the mido bus is enabled with Wake-on-LAN (WOL), we cannot suspend the PHY. Although the WOL status has been checked in phy_suspend(), returning -EBUSY(-16) would cause the Power Management (PM) to fail to suspend. Since phy_suspend() is an exported symbol (EXPORT_SYMBOL), timely error reporting is needed. Therefore, an additional check is performed here. If the PHY of the mido bus is enabled with WOL, we skip calling phy_suspend() to avoid PM failure. From the following logs, it has been observed that the phydev->attached_dev is NULL, phydev is "stmmac-0:01", it not attached, but it will affect suspend and resume.The actually attached "stmmac-0:00" will not dpm_run_callback(): mdio_bus_phy_suspend(). init log: [ 5.932502] YT8521 Gigabit Ethernet stmmac-0:00: attached PHY driver (mii_bus:phy_addr=stmmac-0:00, irq=POLL) [ 5.932512] YT8521 Gigabit Ethernet stmmac-0:01: attached PHY driver (mii_bus:phy_addr=stmmac-0:01, irq=POLL) [ 24.566289] YT8521 Gigabit Ethernet stmmac-0:00: yt8521_read_status, link down, media: UTP suspend log: [ 322.631362] OOM killer disabled. [ 322.631364] Freezing remaining freezable tasks [ 322.632536] Freezing remaining freezable tasks completed (elapsed 0.001 seconds) [ 322.632540] printk: Suspending console(s) (use no_console_suspend to debug) [ 322.633052] YT8521 Gigabit Ethernet stmmac-0:01: PM: dpm_run_callback(): mdio_bus_phy_suspend+0x0/0x110 [libphy] returns -16 [ 322.633071] YT8521 Gigabit Ethernet stmmac-0:01: PM: failed to suspend: error -16 [ 322.669699] PM: Some devices failed to suspend, or early wake event detected [ 322.669949] OOM killer enabled. [ 322.669951] Restarting tasks ... done. [ 322.671008] random: crng reseeded on system resumption [ 322.671014] PM: suspend exit Add a function that phylib can inquire of the driver whether WoL has been enabled at the PHY. Signed-off-by: Russell King (Oracle) Signed-off-by: Youwan Wang Reviewed-by: Wojciech Drewek Link: https://patch.msgid.link/20240731091537.771391-1-youwan@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy_device.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index ec2a3d16b1..312fb7728e 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -268,6 +268,15 @@ static struct phy_driver genphy_driver; static LIST_HEAD(phy_fixup_list); static DEFINE_MUTEX(phy_fixup_lock); +static bool phy_drv_wol_enabled(struct phy_device *phydev) +{ + struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; + + phy_ethtool_get_wol(phydev, &wol); + + return wol.wolopts != 0; +} + static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) { struct device_driver *drv = phydev->mdio.dev.driver; @@ -277,6 +286,12 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) if (!drv || !phydrv->suspend) return false; + /* If the PHY on the mido bus is not attached but has WOL enabled + * we cannot suspend the PHY. + */ + if (!netdev && phy_drv_wol_enabled(phydev)) + return false; + /* PHY not attached? May suspend if the PHY has not already been * suspended as part of a prior call to phy_disconnect() -> * phy_detach() -> phy_suspend() because the parent netdev might be the @@ -1860,7 +1875,6 @@ EXPORT_SYMBOL(phy_detach); int phy_suspend(struct phy_device *phydev) { - struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; struct net_device *netdev = phydev->attached_dev; struct phy_driver *phydrv = phydev->drv; int ret; @@ -1868,8 +1882,8 @@ int phy_suspend(struct phy_device *phydev) if (phydev->suspended) return 0; - phy_ethtool_get_wol(phydev, &wol); - phydev->wol_enabled = wol.wolopts || (netdev && netdev->wol_enabled); + phydev->wol_enabled = phy_drv_wol_enabled(phydev) || + (netdev && netdev->wol_enabled); /* If the device has WOL enabled, we cannot suspend the PHY */ if (phydev->wol_enabled && !(phydrv->flags & PHY_ALWAYS_CALL_SUSPEND)) return -EBUSY; -- Gitee From 98c9f77e608579c85080570858a83b2eb8e3f307 Mon Sep 17 00:00:00 2001 From: zuoqian Date: Wed, 26 Feb 2025 03:50:13 +0000 Subject: [PATCH 120/121] net: phytmac: Manage WOL on MAC if PHY supports WOL Signed-off-by: zuoqian --- drivers/net/ethernet/phytium/phytmac_ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/phytium/phytmac_ethtool.c b/drivers/net/ethernet/phytium/phytmac_ethtool.c index 306a9934de..8bba0af005 100644 --- a/drivers/net/ethernet/phytium/phytmac_ethtool.c +++ b/drivers/net/ethernet/phytium/phytmac_ethtool.c @@ -116,7 +116,8 @@ static int phytmac_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) ret = phylink_ethtool_set_wol(pdata->phylink, wol); - if (!ret || ret != -EOPNOTSUPP) + /* Don't manage WoL on MAC, if PHY set_wol() fails */ + if (ret && ret != -EOPNOTSUPP) return ret; pdata->wol = 0; -- Gitee From 88f00b76168d9ba6ee37c0286d5c750a4c6ab806 Mon Sep 17 00:00:00 2001 From: zuoqian Date: Thu, 27 Feb 2025 05:44:58 +0000 Subject: [PATCH 121/121] net/phytmac: Bugfix set WOL failed issue Before configuring WOL, we need to obtain the packet types that WOL supports. Mainline: NA Signed-off-by: Li Wencheng Signed-off-by: Wang Yinfeng --- drivers/net/ethernet/phytium/phytmac_ethtool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/phytium/phytmac_ethtool.c b/drivers/net/ethernet/phytium/phytmac_ethtool.c index 8bba0af005..e1698fa10b 100644 --- a/drivers/net/ethernet/phytium/phytmac_ethtool.c +++ b/drivers/net/ethernet/phytium/phytmac_ethtool.c @@ -89,23 +89,23 @@ static void phytmac_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol { struct phytmac *pdata = netdev_priv(ndev); + wol->wolopts = 0; phylink_ethtool_get_wol(pdata->phylink, wol); + wol->supported = WAKE_MAGIC | WAKE_ARP | + WAKE_UCAST | WAKE_MCAST; + if (pdata->wol & PHYTMAC_WAKE_MAGIC) { wol->wolopts |= WAKE_MAGIC; - wol->supported |= WAKE_MAGIC; } if (pdata->wol & PHYTMAC_WAKE_ARP) { wol->wolopts |= WAKE_ARP; - wol->supported |= WAKE_ARP; } if (pdata->wol & PHYTMAC_WAKE_UCAST) { wol->wolopts |= WAKE_UCAST; - wol->supported |= WAKE_UCAST; } if (pdata->wol & PHYTMAC_WAKE_MCAST) { wol->wolopts |= WAKE_MCAST; - wol->supported |= WAKE_MCAST; } } -- Gitee