From 7f7d9e1e02f0e18275449489425058b639c970dc Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Tue, 11 Aug 2020 11:17:27 +0100 Subject: [PATCH 001/131] memory: samsung: exynos5422-dmc: Additional locking for 'curr_rate' The 'curr_rate' is protected by local 'dmc->lock' in various places, but not in a function exynos5_dmc_get_status(). The lock protects frequency (and voltage) change process and the corresponding value stored in 'curr_rate'. Add the locking mechanism to protect the 'curr_rate' reading also in the exynos5_dmc_get_status(). Suggested-by: Krzysztof Kozlowski Signed-off-by: Lukasz Luba Link: https://lore.kernel.org/r/20200811101727.3976-1-lukasz.luba@arm.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/samsung/exynos5422-dmc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c index b9c7956e5031..952bc61e68f4 100644 --- a/drivers/memory/samsung/exynos5422-dmc.c +++ b/drivers/memory/samsung/exynos5422-dmc.c @@ -908,7 +908,10 @@ static int exynos5_dmc_get_status(struct device *dev, int ret; if (dmc->in_irq_mode) { + mutex_lock(&dmc->lock); stat->current_frequency = dmc->curr_rate; + mutex_unlock(&dmc->lock); + stat->busy_time = dmc->load; stat->total_time = dmc->total; } else { From 911c94dac9525f4824661592611f169713d74d5f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 20:08:57 +0200 Subject: [PATCH 002/131] memory: samsung: exynos5422-dmc: Document mutex scope Document scope of the mutex used by driver. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Lukasz Luba Link: https://lore.kernel.org/r/20200724180857.22119-1-krzk@kernel.org --- drivers/memory/samsung/exynos5422-dmc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c index 952bc61e68f4..0045fa536b2b 100644 --- a/drivers/memory/samsung/exynos5422-dmc.c +++ b/drivers/memory/samsung/exynos5422-dmc.c @@ -119,6 +119,7 @@ struct exynos5_dmc { void __iomem *base_drexi0; void __iomem *base_drexi1; struct regmap *clk_regmap; + /* Protects curr_rate and frequency/voltage setting section */ struct mutex lock; unsigned long curr_rate; unsigned long curr_volt; From c9864df48d2e03e9205fce51c133caeed0296b1f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 27 Nov 2017 12:55:36 -0800 Subject: [PATCH 003/131] bus: brcmstb_gisb: Shorten prints Do not print the full function name (brcmstb_gisb_arb_decode_addr) which is quite long, and reduces our chances to printing a full line, instead just use "GISB: " as a prefix for these prints. Signed-off-by: Florian Fainelli --- drivers/bus/brcmstb_gisb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index ec1004c858b8..7579439971e3 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -210,8 +210,8 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev, m_name = m_fmt; } - pr_crit("%s: %s at 0x%llx [%c %s], core: %s\n", - __func__, reason, arb_addr, + pr_crit("GISB: %s at 0x%llx [%c %s], core: %s\n", + reason, arb_addr, cap_status & ARB_ERR_CAP_STATUS_WRITE ? 'W' : 'R', cap_status & ARB_ERR_CAP_STATUS_TIMEOUT ? "timeout" : "", m_name); From 9eda7c1f6fb45f590cc96bc8352a028ceed47fcc Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 30 Mar 2020 21:13:28 -0700 Subject: [PATCH 004/131] soc: bcm: brcmstb: biuctrl: Enable Read-ahead cache Brahma-B53 and Cortex-A72 CPUs integrated on Broadcom STB SoCs feature a read-ahead cache that performs cache line size adaptation between the bus interface unit and the memory controller. On 32-bit ARM kernels we have to resort to a full featured read-ahead cache driver under arch/arm/mm/cache-b15-rac.c (CONFIG_CACHE_B15_RAC) because there are still cache maintenance operations by set/ways/index that cannot be transparently handled by the ARM Coherency Extension that the read-ahead cache interfaces to. The 64-bit ARM kernel however has long deprecated all of those, so this is simply a one time configuration. Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/biuctrl.c | 87 +++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c index 61731e01f94b..95602ece51d4 100644 --- a/drivers/soc/bcm/brcmstb/biuctrl.c +++ b/drivers/soc/bcm/brcmstb/biuctrl.c @@ -13,6 +13,20 @@ #include #include +#define RACENPREF_MASK 0x3 +#define RACPREFINST_SHIFT 0 +#define RACENINST_SHIFT 2 +#define RACPREFDATA_SHIFT 4 +#define RACENDATA_SHIFT 6 +#define RAC_CPU_SHIFT 8 +#define RACCFG_MASK 0xff + +/* Bitmask to enable instruction and data prefetching with a 256-bytes stride */ +#define RAC_DATA_INST_EN_MASK (1 << RACPREFINST_SHIFT | \ + RACENPREF_MASK << RACENINST_SHIFT | \ + 1 << RACPREFDATA_SHIFT | \ + RACENPREF_MASK << RACENDATA_SHIFT) + #define CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000 #define CPU_CREDIT_REG_MCPx_READ_CRED_MASK 0xf #define CPU_CREDIT_REG_MCPx_WRITE_CRED_MASK 0xf @@ -31,11 +45,20 @@ static void __iomem *cpubiuctrl_base; static bool mcp_wr_pairing_en; static const int *cpubiuctrl_regs; +enum cpubiuctrl_regs { + CPU_CREDIT_REG = 0, + CPU_MCP_FLOW_REG, + CPU_WRITEBACK_CTRL_REG, + RAC_CONFIG0_REG, + NUM_CPU_BIUCTRL_REGS, +}; + static inline u32 cbc_readl(int reg) { int offset = cpubiuctrl_regs[reg]; - if (offset == -1) + if (offset == -1 || + (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg == RAC_CONFIG0_REG)) return (u32)-1; return readl_relaxed(cpubiuctrl_base + offset); @@ -45,22 +68,18 @@ static inline void cbc_writel(u32 val, int reg) { int offset = cpubiuctrl_regs[reg]; - if (offset == -1) + if (offset == -1 || + (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg == RAC_CONFIG0_REG)) return; writel(val, cpubiuctrl_base + offset); } -enum cpubiuctrl_regs { - CPU_CREDIT_REG = 0, - CPU_MCP_FLOW_REG, - CPU_WRITEBACK_CTRL_REG -}; - static const int b15_cpubiuctrl_regs[] = { [CPU_CREDIT_REG] = 0x184, [CPU_MCP_FLOW_REG] = -1, [CPU_WRITEBACK_CTRL_REG] = -1, + [RAC_CONFIG0_REG] = -1, }; /* Odd cases, e.g: 7260A0 */ @@ -68,22 +87,23 @@ static const int b53_cpubiuctrl_no_wb_regs[] = { [CPU_CREDIT_REG] = 0x0b0, [CPU_MCP_FLOW_REG] = 0x0b4, [CPU_WRITEBACK_CTRL_REG] = -1, + [RAC_CONFIG0_REG] = 0x78, }; static const int b53_cpubiuctrl_regs[] = { [CPU_CREDIT_REG] = 0x0b0, [CPU_MCP_FLOW_REG] = 0x0b4, [CPU_WRITEBACK_CTRL_REG] = 0x22c, + [RAC_CONFIG0_REG] = 0x78, }; static const int a72_cpubiuctrl_regs[] = { [CPU_CREDIT_REG] = 0x18, [CPU_MCP_FLOW_REG] = 0x1c, [CPU_WRITEBACK_CTRL_REG] = 0x20, + [RAC_CONFIG0_REG] = 0x08, }; -#define NUM_CPU_BIUCTRL_REGS 3 - static int __init mcp_write_pairing_set(void) { u32 creds = 0; @@ -117,6 +137,52 @@ static const u32 a72_b53_mach_compat[] = { 0x7278, }; +/* The read-ahead cache present in the Brahma-B53 CPU is a special piece of + * hardware after the integrated L2 cache of the B53 CPU complex whose purpose + * is to prefetch instruction and/or data with a line size of either 64 bytes + * or 256 bytes. The rationale is that the data-bus of the CPU interface is + * optimized for 256-byte transactions, and enabling the read-ahead cache + * provides a significant performance boost (typically twice the performance + * for a memcpy benchmark application). + * + * The read-ahead cache is transparent for Virtual Address cache maintenance + * operations: IC IVAU, DC IVAC, DC CVAC, DC CVAU and DC CIVAC. So no special + * handling is needed for the DMA API above and beyond what is included in the + * arm64 implementation. + * + * In addition, since the Point of Unification is typically between L1 and L2 + * for the Brahma-B53 processor no special read-ahead cache handling is needed + * for the IC IALLU and IC IALLUIS cache maintenance operations. + * + * However, it is not possible to specify the cache level (L3) for the cache + * maintenance instructions operating by set/way to operate on the read-ahead + * cache. The read-ahead cache will maintain coherency when inner cache lines + * are cleaned by set/way, but if it is necessary to invalidate inner cache + * lines by set/way to maintain coherency with system masters operating on + * shared memory that does not have hardware support for coherency, then it + * will also be necessary to explicitly invalidate the read-ahead cache. + */ +static void __init a72_b53_rac_enable_all(struct device_node *np) +{ + unsigned int cpu; + u32 enable = 0; + + if (IS_ENABLED(CONFIG_CACHE_B15_RAC)) + return; + + if (WARN(num_possible_cpus() > 4, "RAC only supports 4 CPUs\n")) + return; + + for_each_possible_cpu(cpu) + enable |= RAC_DATA_INST_EN_MASK << (cpu * RAC_CPU_SHIFT); + + cbc_writel(enable, RAC_CONFIG0_REG); + + pr_info("%pOF: Broadcom %s read-ahead cache\n", + np, cpubiuctrl_regs == a72_cpubiuctrl_regs ? + "Cortex-A72" : "Brahma-B53"); +} + static void __init mcp_a72_b53_set(void) { unsigned int i; @@ -262,6 +328,7 @@ static int __init brcmstb_biuctrl_init(void) return ret; } + a72_b53_rac_enable_all(np); mcp_a72_b53_set(); #ifdef CONFIG_PM_SLEEP register_syscore_ops(&brcmstb_cpu_credit_syscore_ops); From 7c12a14802a2a5d7fd43fd11db45567bfb5e17b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:32 +0200 Subject: [PATCH 005/131] dt-bindings: soc: brcm: add BCM63xx power domain binding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6318, BCM6328, BCM6362 and BCM63268 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- .../bindings/power/brcm,bcm63xx-power.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/brcm,bcm63xx-power.yaml diff --git a/Documentation/devicetree/bindings/power/brcm,bcm63xx-power.yaml b/Documentation/devicetree/bindings/power/brcm,bcm63xx-power.yaml new file mode 100644 index 000000000000..63b15ac6dde4 --- /dev/null +++ b/Documentation/devicetree/bindings/power/brcm,bcm63xx-power.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/power/brcm,bcm63xx-power.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: BCM63xx power domain driver + +maintainers: + - Álvaro Fernández Rojas + +description: | + BCM6318, BCM6328, BCM6362 and BCM63268 SoCs have a power domain controller + to enable/disable certain components in order to save power. + +properties: + compatible: + items: + - enum: + - brcm,bcm6318-power-controller + - brcm,bcm6328-power-controller + - brcm,bcm6362-power-controller + - brcm,bcm63268-power-controller + + reg: + maxItems: 1 + + "#power-domain-cells": + const: 1 + +required: + - compatible + - reg + - "#power-domain-cells" + +additionalProperties: false + +examples: + - | + periph_pwr: power-controller@10001848 { + compatible = "brcm,bcm6328-power-controller"; + reg = <0x10001848 0x4>; + #power-domain-cells = <1>; + }; From 5292481134b2c4d64e1279158917dc9b53713721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:33 +0200 Subject: [PATCH 006/131] MIPS: BMIPS: add BCM6328 power domain definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6328 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- include/dt-bindings/soc/bcm6328-pm.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 include/dt-bindings/soc/bcm6328-pm.h diff --git a/include/dt-bindings/soc/bcm6328-pm.h b/include/dt-bindings/soc/bcm6328-pm.h new file mode 100644 index 000000000000..557e1a69b7f7 --- /dev/null +++ b/include/dt-bindings/soc/bcm6328-pm.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_BMIPS_BCM6328_PM_H +#define __DT_BINDINGS_BMIPS_BCM6328_PM_H + +#define BCM6328_POWER_DOMAIN_ADSL2_MIPS 0 +#define BCM6328_POWER_DOMAIN_ADSL2_PHY 1 +#define BCM6328_POWER_DOMAIN_ADSL2_AFE 2 +#define BCM6328_POWER_DOMAIN_SAR 3 +#define BCM6328_POWER_DOMAIN_PCM 4 +#define BCM6328_POWER_DOMAIN_USBD 5 +#define BCM6328_POWER_DOMAIN_USBH 6 +#define BCM6328_POWER_DOMAIN_PCIE 7 +#define BCM6328_POWER_DOMAIN_ROBOSW 8 +#define BCM6328_POWER_DOMAIN_EPHY 9 + +#endif /* __DT_BINDINGS_BMIPS_BCM6328_PM_H */ From 9f9fd9766a288e259ad7cefbf3e45e1ec117b50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:34 +0200 Subject: [PATCH 007/131] MIPS: BMIPS: add BCM6362 power domain definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6362 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- include/dt-bindings/soc/bcm6362-pm.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 include/dt-bindings/soc/bcm6362-pm.h diff --git a/include/dt-bindings/soc/bcm6362-pm.h b/include/dt-bindings/soc/bcm6362-pm.h new file mode 100644 index 000000000000..d087ba63c7a1 --- /dev/null +++ b/include/dt-bindings/soc/bcm6362-pm.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_BMIPS_BCM6362_PM_H +#define __DT_BINDINGS_BMIPS_BCM6362_PM_H + +#define BCM6362_POWER_DOMAIN_SAR 0 +#define BCM6362_POWER_DOMAIN_IPSEC 1 +#define BCM6362_POWER_DOMAIN_MIPS 2 +#define BCM6362_POWER_DOMAIN_DECT 3 +#define BCM6362_POWER_DOMAIN_USBH 4 +#define BCM6362_POWER_DOMAIN_USBD 5 +#define BCM6362_POWER_DOMAIN_ROBOSW 6 +#define BCM6362_POWER_DOMAIN_PCM 7 +#define BCM6362_POWER_DOMAIN_PERIPH 8 +#define BCM6362_POWER_DOMAIN_ADSL_PHY 9 +#define BCM6362_POWER_DOMAIN_GMII_PADS 10 +#define BCM6362_POWER_DOMAIN_FAP 11 +#define BCM6362_POWER_DOMAIN_PCIE 12 +#define BCM6362_POWER_DOMAIN_WLAN_PADS 13 + +#endif /* __DT_BINDINGS_BMIPS_BCM6362_PM_H */ From 5a3be0d0ccfb21d1223f77746d260450d94df9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:35 +0200 Subject: [PATCH 008/131] MIPS: BMIPS: add BCM63268 power domain definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM63268 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- include/dt-bindings/soc/bcm63268-pm.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 include/dt-bindings/soc/bcm63268-pm.h diff --git a/include/dt-bindings/soc/bcm63268-pm.h b/include/dt-bindings/soc/bcm63268-pm.h new file mode 100644 index 000000000000..84ded53a732f --- /dev/null +++ b/include/dt-bindings/soc/bcm63268-pm.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_BMIPS_BCM63268_PM_H +#define __DT_BINDINGS_BMIPS_BCM63268_PM_H + +#define BCM63268_POWER_DOMAIN_SAR 0 +#define BCM63268_POWER_DOMAIN_IPSEC 1 +#define BCM63268_POWER_DOMAIN_MIPS 2 +#define BCM63268_POWER_DOMAIN_DECT 3 +#define BCM63268_POWER_DOMAIN_USBH 4 +#define BCM63268_POWER_DOMAIN_USBD 5 +#define BCM63268_POWER_DOMAIN_ROBOSW 6 +#define BCM63268_POWER_DOMAIN_PCM 7 +#define BCM63268_POWER_DOMAIN_PERIPH 8 +#define BCM63268_POWER_DOMAIN_VDSL_PHY 9 +#define BCM63268_POWER_DOMAIN_VDSL_MIPS 10 +#define BCM63268_POWER_DOMAIN_FAP 11 +#define BCM63268_POWER_DOMAIN_PCIE 12 +#define BCM63268_POWER_DOMAIN_WLAN_PADS 13 + +#endif /* __DT_BINDINGS_BMIPS_BCM63268_PM_H */ From 8bf86a155688f3acbc5919cdf58c59378d62a663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:36 +0200 Subject: [PATCH 009/131] MIPS: BMIPS: add BCM6318 power domain definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6318 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Florian Fainelli --- include/dt-bindings/soc/bcm6318-pm.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 include/dt-bindings/soc/bcm6318-pm.h diff --git a/include/dt-bindings/soc/bcm6318-pm.h b/include/dt-bindings/soc/bcm6318-pm.h new file mode 100644 index 000000000000..05931dce8333 --- /dev/null +++ b/include/dt-bindings/soc/bcm6318-pm.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_BMIPS_BCM6318_PM_H +#define __DT_BINDINGS_BMIPS_BCM6318_PM_H + +#define BCM6318_POWER_DOMAIN_PCIE 0 +#define BCM6318_POWER_DOMAIN_USB 1 +#define BCM6318_POWER_DOMAIN_EPHY0 2 +#define BCM6318_POWER_DOMAIN_EPHY1 3 +#define BCM6318_POWER_DOMAIN_EPHY2 4 +#define BCM6318_POWER_DOMAIN_EPHY3 5 +#define BCM6318_POWER_DOMAIN_LDO2P5 6 +#define BCM6318_POWER_DOMAIN_LDO2P9 7 +#define BCM6318_POWER_DOMAIN_SW1P0 8 +#define BCM6318_POWER_DOMAIN_PAD 9 + +#endif /* __DT_BINDINGS_BMIPS_BCM6318_PM_H */ From 6c41106f177e1e3e198604f42adedc8be97c482a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:37 +0200 Subject: [PATCH 010/131] soc: bcm: add BCM63xx power domain driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6318, BCM6328, BCM6362 and BCM63268 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Signed-off-by: Florian Fainelli --- MAINTAINERS | 1 + drivers/soc/bcm/Kconfig | 10 + drivers/soc/bcm/Makefile | 1 + drivers/soc/bcm/bcm63xx/Kconfig | 12 + drivers/soc/bcm/bcm63xx/Makefile | 2 + drivers/soc/bcm/bcm63xx/bcm63xx-power.c | 378 ++++++++++++++++++++++++ 6 files changed, 404 insertions(+) create mode 100644 drivers/soc/bcm/bcm63xx/Kconfig create mode 100644 drivers/soc/bcm/bcm63xx/Makefile create mode 100644 drivers/soc/bcm/bcm63xx/bcm63xx-power.c diff --git a/MAINTAINERS b/MAINTAINERS index deaafb617361..c742864ab699 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3491,6 +3491,7 @@ F: arch/mips/bmips/* F: arch/mips/boot/dts/brcm/bcm*.dts* F: arch/mips/include/asm/mach-bmips/* F: arch/mips/kernel/*bmips* +F: drivers/soc/bcm/bcm63xx F: drivers/irqchip/irq-bcm63* F: drivers/irqchip/irq-bcm7* F: drivers/irqchip/irq-brcmstb* diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig index 648e32693b7e..24f92a6e882a 100644 --- a/drivers/soc/bcm/Kconfig +++ b/drivers/soc/bcm/Kconfig @@ -22,6 +22,15 @@ config RASPBERRYPI_POWER This enables support for the RPi power domains which can be enabled or disabled via the RPi firmware. +config SOC_BCM63XX + bool "Broadcom 63xx SoC drivers" + depends on BMIPS_GENERIC || COMPILE_TEST + help + Enables drivers for the Broadcom 63xx series of chips. + Drivers can be enabled individually within this menu. + + If unsure, say N. + config SOC_BRCMSTB bool "Broadcom STB SoC drivers" depends on ARM || ARM64 || BMIPS_GENERIC || COMPILE_TEST @@ -33,6 +42,7 @@ config SOC_BRCMSTB If unsure, say N. +source "drivers/soc/bcm/bcm63xx/Kconfig" source "drivers/soc/bcm/brcmstb/Kconfig" endmenu diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile index d92268a829a9..7bc90e0bd773 100644 --- a/drivers/soc/bcm/Makefile +++ b/drivers/soc/bcm/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o +obj-$(CONFIG_SOC_BCM63XX) += bcm63xx/ obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ diff --git a/drivers/soc/bcm/bcm63xx/Kconfig b/drivers/soc/bcm/bcm63xx/Kconfig new file mode 100644 index 000000000000..16f648a6c70a --- /dev/null +++ b/drivers/soc/bcm/bcm63xx/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +if SOC_BCM63XX + +config BCM63XX_POWER + bool "BCM63xx power domain driver" + depends on BMIPS_GENERIC || (COMPILE_TEST && OF) + select PM_GENERIC_DOMAINS if PM + help + This enables support for the BCM63xx power domains controller on + BCM6318, BCM6328, BCM6362 and BCM63268 SoCs. + +endif # SOC_BCM63XX diff --git a/drivers/soc/bcm/bcm63xx/Makefile b/drivers/soc/bcm/bcm63xx/Makefile new file mode 100644 index 000000000000..0710d5e018cc --- /dev/null +++ b/drivers/soc/bcm/bcm63xx/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o diff --git a/drivers/soc/bcm/bcm63xx/bcm63xx-power.c b/drivers/soc/bcm/bcm63xx/bcm63xx-power.c new file mode 100644 index 000000000000..515fe182dc34 --- /dev/null +++ b/drivers/soc/bcm/bcm63xx/bcm63xx-power.c @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * BCM63xx Power Domain Controller Driver + * + * Copyright (C) 2020 Álvaro Fernández Rojas + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bcm63xx_power_dev { + struct generic_pm_domain genpd; + struct bcm63xx_power *power; + uint32_t mask; +}; + +struct bcm63xx_power { + void __iomem *base; + spinlock_t lock; + struct bcm63xx_power_dev *dev; + struct genpd_onecell_data genpd_data; + struct generic_pm_domain **genpd; +}; + +struct bcm63xx_power_data { + const char * const name; + uint8_t bit; + unsigned int flags; +}; + +static int bcm63xx_power_get_state(struct bcm63xx_power_dev *pmd, bool *is_on) +{ + struct bcm63xx_power *power = pmd->power; + + if (!pmd->mask) { + *is_on = false; + return -EINVAL; + } + + *is_on = !(__raw_readl(power->base) & pmd->mask); + + return 0; +} + +static int bcm63xx_power_set_state(struct bcm63xx_power_dev *pmd, bool on) +{ + struct bcm63xx_power *power = pmd->power; + unsigned long flags; + uint32_t val; + + if (!pmd->mask) + return -EINVAL; + + spin_lock_irqsave(&power->lock, flags); + val = __raw_readl(power->base); + if (on) + val &= ~pmd->mask; + else + val |= pmd->mask; + __raw_writel(val, power->base); + spin_unlock_irqrestore(&power->lock, flags); + + return 0; +} + +static int bcm63xx_power_on(struct generic_pm_domain *genpd) +{ + struct bcm63xx_power_dev *pmd = container_of(genpd, + struct bcm63xx_power_dev, genpd); + + return bcm63xx_power_set_state(pmd, true); +} + +static int bcm63xx_power_off(struct generic_pm_domain *genpd) +{ + struct bcm63xx_power_dev *pmd = container_of(genpd, + struct bcm63xx_power_dev, genpd); + + return bcm63xx_power_set_state(pmd, false); +} + +static int bcm63xx_power_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct resource *res; + const struct bcm63xx_power_data *entry, *table; + struct bcm63xx_power *power; + unsigned int ndom; + uint8_t max_bit = 0; + int ret; + + power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL); + if (!power) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + power->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(power->base)) + return PTR_ERR(power->base); + + table = of_device_get_match_data(dev); + if (!table) + return -EINVAL; + + power->genpd_data.num_domains = 0; + ndom = 0; + for (entry = table; entry->name; entry++) { + max_bit = max(max_bit, entry->bit); + ndom++; + } + + if (!ndom) + return -ENODEV; + + power->genpd_data.num_domains = max_bit + 1; + + power->dev = devm_kcalloc(dev, power->genpd_data.num_domains, + sizeof(struct bcm63xx_power_dev), + GFP_KERNEL); + if (!power->dev) + return -ENOMEM; + + power->genpd = devm_kcalloc(dev, power->genpd_data.num_domains, + sizeof(struct generic_pm_domain *), + GFP_KERNEL); + if (!power->genpd) + return -ENOMEM; + + power->genpd_data.domains = power->genpd; + + ndom = 0; + for (entry = table; entry->name; entry++) { + struct bcm63xx_power_dev *pmd = &power->dev[ndom]; + bool is_on; + + pmd->power = power; + pmd->mask = BIT(entry->bit); + pmd->genpd.name = entry->name; + pmd->genpd.flags = entry->flags; + + ret = bcm63xx_power_get_state(pmd, &is_on); + if (ret) + dev_warn(dev, "unable to get current state for %s\n", + pmd->genpd.name); + + pmd->genpd.power_on = bcm63xx_power_on; + pmd->genpd.power_off = bcm63xx_power_off; + + pm_genpd_init(&pmd->genpd, NULL, !is_on); + power->genpd[entry->bit] = &pmd->genpd; + + ndom++; + } + + spin_lock_init(&power->lock); + + ret = of_genpd_add_provider_onecell(np, &power->genpd_data); + if (ret) { + dev_err(dev, "failed to register genpd driver: %d\n", ret); + return ret; + } + + dev_info(dev, "registered %u power domains\n", ndom); + + return 0; +} + +static const struct bcm63xx_power_data bcm6318_power_domains[] = { + { + .name = "pcie", + .bit = BCM6318_POWER_DOMAIN_PCIE, + }, { + .name = "usb", + .bit = BCM6318_POWER_DOMAIN_USB, + }, { + .name = "ephy0", + .bit = BCM6318_POWER_DOMAIN_EPHY0, + }, { + .name = "ephy1", + .bit = BCM6318_POWER_DOMAIN_EPHY1, + }, { + .name = "ephy2", + .bit = BCM6318_POWER_DOMAIN_EPHY2, + }, { + .name = "ephy3", + .bit = BCM6318_POWER_DOMAIN_EPHY3, + }, { + .name = "ldo2p5", + .bit = BCM6318_POWER_DOMAIN_LDO2P5, + .flags = GENPD_FLAG_ALWAYS_ON, + }, { + .name = "ldo2p9", + .bit = BCM6318_POWER_DOMAIN_LDO2P9, + .flags = GENPD_FLAG_ALWAYS_ON, + }, { + .name = "sw1p0", + .bit = BCM6318_POWER_DOMAIN_SW1P0, + .flags = GENPD_FLAG_ALWAYS_ON, + }, { + .name = "pad", + .bit = BCM6318_POWER_DOMAIN_PAD, + .flags = GENPD_FLAG_ALWAYS_ON, + }, { + /* sentinel */ + }, +}; + +static const struct bcm63xx_power_data bcm6328_power_domains[] = { + { + .name = "adsl2-mips", + .bit = BCM6328_POWER_DOMAIN_ADSL2_MIPS, + }, { + .name = "adsl2-phy", + .bit = BCM6328_POWER_DOMAIN_ADSL2_PHY, + }, { + .name = "adsl2-afe", + .bit = BCM6328_POWER_DOMAIN_ADSL2_AFE, + }, { + .name = "sar", + .bit = BCM6328_POWER_DOMAIN_SAR, + }, { + .name = "pcm", + .bit = BCM6328_POWER_DOMAIN_PCM, + }, { + .name = "usbd", + .bit = BCM6328_POWER_DOMAIN_USBD, + }, { + .name = "usbh", + .bit = BCM6328_POWER_DOMAIN_USBH, + }, { + .name = "pcie", + .bit = BCM6328_POWER_DOMAIN_PCIE, + }, { + .name = "robosw", + .bit = BCM6328_POWER_DOMAIN_ROBOSW, + }, { + .name = "ephy", + .bit = BCM6328_POWER_DOMAIN_EPHY, + }, { + /* sentinel */ + }, +}; + +static const struct bcm63xx_power_data bcm6362_power_domains[] = { + { + .name = "sar", + .bit = BCM6362_POWER_DOMAIN_SAR, + }, { + .name = "ipsec", + .bit = BCM6362_POWER_DOMAIN_IPSEC, + }, { + .name = "mips", + .bit = BCM6362_POWER_DOMAIN_MIPS, + .flags = GENPD_FLAG_ALWAYS_ON, + }, { + .name = "dect", + .bit = BCM6362_POWER_DOMAIN_DECT, + }, { + .name = "usbh", + .bit = BCM6362_POWER_DOMAIN_USBH, + }, { + .name = "usbd", + .bit = BCM6362_POWER_DOMAIN_USBD, + }, { + .name = "robosw", + .bit = BCM6362_POWER_DOMAIN_ROBOSW, + }, { + .name = "pcm", + .bit = BCM6362_POWER_DOMAIN_PCM, + }, { + .name = "periph", + .bit = BCM6362_POWER_DOMAIN_PERIPH, + .flags = GENPD_FLAG_ALWAYS_ON, + }, { + .name = "adsl-phy", + .bit = BCM6362_POWER_DOMAIN_ADSL_PHY, + }, { + .name = "gmii-pads", + .bit = BCM6362_POWER_DOMAIN_GMII_PADS, + }, { + .name = "fap", + .bit = BCM6362_POWER_DOMAIN_FAP, + }, { + .name = "pcie", + .bit = BCM6362_POWER_DOMAIN_PCIE, + }, { + .name = "wlan-pads", + .bit = BCM6362_POWER_DOMAIN_WLAN_PADS, + }, { + /* sentinel */ + }, +}; + +static const struct bcm63xx_power_data bcm63268_power_domains[] = { + { + .name = "sar", + .bit = BCM63268_POWER_DOMAIN_SAR, + }, { + .name = "ipsec", + .bit = BCM63268_POWER_DOMAIN_IPSEC, + }, { + .name = "mips", + .bit = BCM63268_POWER_DOMAIN_MIPS, + .flags = GENPD_FLAG_ALWAYS_ON, + }, { + .name = "dect", + .bit = BCM63268_POWER_DOMAIN_DECT, + }, { + .name = "usbh", + .bit = BCM63268_POWER_DOMAIN_USBH, + }, { + .name = "usbd", + .bit = BCM63268_POWER_DOMAIN_USBD, + }, { + .name = "robosw", + .bit = BCM63268_POWER_DOMAIN_ROBOSW, + }, { + .name = "pcm", + .bit = BCM63268_POWER_DOMAIN_PCM, + }, { + .name = "periph", + .bit = BCM63268_POWER_DOMAIN_PERIPH, + .flags = GENPD_FLAG_ALWAYS_ON, + }, { + .name = "vdsl-phy", + .bit = BCM63268_POWER_DOMAIN_VDSL_PHY, + }, { + .name = "vdsl-mips", + .bit = BCM63268_POWER_DOMAIN_VDSL_MIPS, + }, { + .name = "fap", + .bit = BCM63268_POWER_DOMAIN_FAP, + }, { + .name = "pcie", + .bit = BCM63268_POWER_DOMAIN_PCIE, + }, { + .name = "wlan-pads", + .bit = BCM63268_POWER_DOMAIN_WLAN_PADS, + }, { + /* sentinel */ + }, +}; + +static const struct of_device_id bcm63xx_power_of_match[] = { + { + .compatible = "brcm,bcm6318-power-controller", + .data = &bcm6318_power_domains, + }, { + .compatible = "brcm,bcm6328-power-controller", + .data = &bcm6328_power_domains, + }, { + .compatible = "brcm,bcm6362-power-controller", + .data = &bcm6362_power_domains, + }, { + .compatible = "brcm,bcm63268-power-controller", + .data = &bcm63268_power_domains, + }, { + /* sentinel */ + } +}; + +static struct platform_driver bcm63xx_power_driver = { + .driver = { + .name = "bcm63xx-power-controller", + .of_match_table = bcm63xx_power_of_match, + }, + .probe = bcm63xx_power_probe, +}; +builtin_platform_driver(bcm63xx_power_driver); From 60515712abee9e424dc3e5aab04f34eaab4efffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:38 +0200 Subject: [PATCH 011/131] MIPS: BMIPS: dts: add BCM6328 power domain support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6328 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Acked-by: Florian Fainelli Acked-by: Thomas Bogendoerfer Signed-off-by: Florian Fainelli --- arch/mips/boot/dts/brcm/bcm6328.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/boot/dts/brcm/bcm6328.dtsi b/arch/mips/boot/dts/brcm/bcm6328.dtsi index af860d06def6..1f9edd710392 100644 --- a/arch/mips/boot/dts/brcm/bcm6328.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6328.dtsi @@ -110,6 +110,12 @@ leds0: led-controller@10000800 { status = "disabled"; }; + periph_pwr: power-controller@10001848 { + compatible = "brcm,bcm6328-power-controller"; + reg = <0x10001848 0x4>; + #power-domain-cells = <1>; + }; + ehci: usb@10002500 { compatible = "brcm,bcm6328-ehci", "generic-ehci"; reg = <0x10002500 0x100>; From 07fcf7772f57016bc2c0af9558619bb732ce1b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:39 +0200 Subject: [PATCH 012/131] MIPS: BMIPS: dts: add BCM6362 power domain support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM6362 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Acked-by: Florian Fainelli Acked-by: Thomas Bogendoerfer Signed-off-by: Florian Fainelli --- arch/mips/boot/dts/brcm/bcm6362.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/boot/dts/brcm/bcm6362.dtsi b/arch/mips/boot/dts/brcm/bcm6362.dtsi index 8ae6981735b8..c98f9111e3c8 100644 --- a/arch/mips/boot/dts/brcm/bcm6362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6362.dtsi @@ -108,6 +108,12 @@ uart1: serial@10000120 { status = "disabled"; }; + periph_pwr: power-controller@10001848 { + compatible = "brcm,bcm6362-power-controller"; + reg = <0x10001848 0x4>; + #power-domain-cells = <1>; + }; + leds0: led-controller@10001900 { #address-cells = <1>; #size-cells = <0>; From f4d1afc0a454ff8a7d45a2b98de05f6fcbfb2650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sat, 13 Jun 2020 10:21:40 +0200 Subject: [PATCH 013/131] MIPS: BMIPS: dts: add BCM63268 power domain support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BCM63268 SoCs have a power domain controller to enable/disable certain components in order to save power. Signed-off-by: Álvaro Fernández Rojas Acked-by: Florian Fainelli Acked-by: Thomas Bogendoerfer Signed-off-by: Florian Fainelli --- arch/mips/boot/dts/brcm/bcm63268.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/boot/dts/brcm/bcm63268.dtsi b/arch/mips/boot/dts/brcm/bcm63268.dtsi index beec24145af7..5acb49b61867 100644 --- a/arch/mips/boot/dts/brcm/bcm63268.dtsi +++ b/arch/mips/boot/dts/brcm/bcm63268.dtsi @@ -117,6 +117,12 @@ leds0: led-controller@10001900 { status = "disabled"; }; + periph_pwr: power-controller@1000184c { + compatible = "brcm,bcm6328-power-controller"; + reg = <0x1000184c 0x4>; + #power-domain-cells = <1>; + }; + ehci: usb@10002500 { compatible = "brcm,bcm63268-ehci", "generic-ehci"; reg = <0x10002500 0x100>; From 8e9ffd5ed368c267edaf4e585e7d3813cc76cf7c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 09:40:10 +0200 Subject: [PATCH 014/131] memory: omap-gpmc: remove unneeded asm/mach-types.h inclusion The driver does not use macros from asm/mach-types.h (neither MACH_TYPE nor machine_is_xxx()). Removal of this include allows compile testing on non-ARM architectures which lack this header. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724074038.5597-2-krzk@kernel.org --- drivers/memory/omap-gpmc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index f512cbc7a36c..06685ba290f1 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -33,8 +33,6 @@ #include -#include - #define DEVICE_NAME "omap-gpmc" /* GPMC register offsets */ From ddbfbcba4933b50680ae0b6a789e3bbce3f356a4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 09:40:11 +0200 Subject: [PATCH 015/131] memory: omap-gpmc: remove unused file-scope phys_base and mem_size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The file-scope variables phys_base and mem_size are assigned in gpmc_probe() but never read. This fixes build error when compile testing on x86_64 architecture: drivers/memory/omap-gpmc.c:246:24: error: conflicting types for ‘phys_base’ static resource_size_t phys_base, mem_size; In file included from arch/x86/include/asm/page.h:12:0, from arch/x86/include/asm/thread_info.h:12, from include/linux/thread_info.h:38, from arch/x86/include/asm/preempt.h:7, from include/linux/preempt.h:78, from include/linux/spinlock.h:51, from include/linux/irq.h:14, from drivers/memory/omap-gpmc.c:12: arch/x86/include/asm/page_64.h:12:22: note: previous declaration of ‘phys_base’ was here extern unsigned long phys_base; Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724074038.5597-3-krzk@kernel.org --- drivers/memory/omap-gpmc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 06685ba290f1..324870d51dbc 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -243,7 +243,6 @@ static DEFINE_SPINLOCK(gpmc_mem_lock); /* Define chip-selects as reserved by default until probe completes */ static unsigned int gpmc_cs_num = GPMC_CS_NUM; static unsigned int gpmc_nr_waitpins; -static resource_size_t phys_base, mem_size; static unsigned int gpmc_capability; static void __iomem *gpmc_base; @@ -2349,9 +2348,6 @@ static int gpmc_probe(struct platform_device *pdev) if (res == NULL) return -ENOENT; - phys_base = res->start; - mem_size = resource_size(res); - gpmc_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(gpmc_base)) return PTR_ERR(gpmc_base); From d25112aa34d007deaef3f2b373ab98ab1a7fc92d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 09:40:29 +0200 Subject: [PATCH 016/131] memory: omap-gpmc: return meaningful error codes in gpmc_cs_set_timings() The callers of gpmc_cs_set_timings() expect to receive -ERRNO on errors and they pass further what they have received. However gpmc_cs_set_timings() was returning -1 (equal to -EPERM) which does not make sense in this context. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724074038.5597-21-krzk@kernel.org --- drivers/memory/omap-gpmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 324870d51dbc..792cdf048881 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -635,7 +635,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int max #define GPMC_SET_ONE_CD_MAX(reg, st, end, max, field, cd) \ if (set_gpmc_timing_reg(cs, (reg), (st), (end), (max), \ t->field, (cd), #field) < 0) \ - return -1 + return -ENXIO #define GPMC_SET_ONE(reg, st, end, field) \ GPMC_SET_ONE_CD_MAX(reg, st, end, 0, field, GPMC_CD_FCLK) @@ -703,7 +703,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, div = gpmc_calc_divider(t->sync_clk); if (div < 0) - return div; + return -EINVAL; /* * See if we need to change the divider for waitmonitoringtime. @@ -727,7 +727,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, __func__, t->wait_monitoring ); - return -1; + return -ENXIO; } } From 1724f1b6963a412d42696dd0d3c172fe983d1353 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 09:40:30 +0200 Subject: [PATCH 017/131] memory: omap-gpmc: remove GPMC_SET_ONE_CD_MAX macro for safety The GPMC_SET_ONE_CD_MAX macro uses return statement and variable 'cs' coming from called scope. This is not a good practice. Also checkpatch complained: WARNING: Macros with flow control statements should be avoided ERROR: Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects Since GPMC_SET_ONE_CD_MAX macro just calls one function, it can be open coded. The difference with original code is that function will exit on error not after every register set, but after a group of sets. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724074038.5597-22-krzk@kernel.org --- drivers/memory/omap-gpmc.c | 131 +++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 41 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 792cdf048881..2ef2a7a8ed51 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -632,14 +632,6 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int max return 0; } -#define GPMC_SET_ONE_CD_MAX(reg, st, end, max, field, cd) \ - if (set_gpmc_timing_reg(cs, (reg), (st), (end), (max), \ - t->field, (cd), #field) < 0) \ - return -ENXIO - -#define GPMC_SET_ONE(reg, st, end, field) \ - GPMC_SET_ONE_CD_MAX(reg, st, end, 0, field, GPMC_CD_FCLK) - /** * gpmc_calc_waitmonitoring_divider - calculate proper GPMCFCLKDIVIDER based on WAITMONITORINGTIME * WAITMONITORINGTIME will be _at least_ as long as desired, i.e. @@ -698,7 +690,7 @@ int gpmc_calc_divider(unsigned int sync_clk) int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, const struct gpmc_settings *s) { - int div; + int div, ret; u32 l; div = gpmc_calc_divider(t->sync_clk); @@ -731,53 +723,110 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t, } } - GPMC_SET_ONE(GPMC_CS_CONFIG2, 0, 3, cs_on); - GPMC_SET_ONE(GPMC_CS_CONFIG2, 8, 12, cs_rd_off); - GPMC_SET_ONE(GPMC_CS_CONFIG2, 16, 20, cs_wr_off); + ret = 0; + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 0, 3, 0, t->cs_on, + GPMC_CD_FCLK, "cs_on"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 8, 12, 0, t->cs_rd_off, + GPMC_CD_FCLK, "cs_rd_off"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 16, 20, 0, t->cs_wr_off, + GPMC_CD_FCLK, "cs_wr_off"); + if (ret) + return -ENXIO; + + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 0, 3, 0, t->adv_on, + GPMC_CD_FCLK, "adv_on"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 8, 12, 0, t->adv_rd_off, + GPMC_CD_FCLK, "adv_rd_off"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 16, 20, 0, t->adv_wr_off, + GPMC_CD_FCLK, "adv_wr_off"); + if (ret) + return -ENXIO; - GPMC_SET_ONE(GPMC_CS_CONFIG3, 0, 3, adv_on); - GPMC_SET_ONE(GPMC_CS_CONFIG3, 8, 12, adv_rd_off); - GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off); if (gpmc_capability & GPMC_HAS_MUX_AAD) { - GPMC_SET_ONE(GPMC_CS_CONFIG3, 4, 6, adv_aad_mux_on); - GPMC_SET_ONE(GPMC_CS_CONFIG3, 24, 26, adv_aad_mux_rd_off); - GPMC_SET_ONE(GPMC_CS_CONFIG3, 28, 30, adv_aad_mux_wr_off); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 4, 6, 0, + t->adv_aad_mux_on, GPMC_CD_FCLK, + "adv_aad_mux_on"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 24, 26, 0, + t->adv_aad_mux_rd_off, GPMC_CD_FCLK, + "adv_aad_mux_rd_off"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 28, 30, 0, + t->adv_aad_mux_wr_off, GPMC_CD_FCLK, + "adv_aad_mux_wr_off"); + if (ret) + return -ENXIO; } - GPMC_SET_ONE(GPMC_CS_CONFIG4, 0, 3, oe_on); - GPMC_SET_ONE(GPMC_CS_CONFIG4, 8, 12, oe_off); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 0, 3, 0, t->oe_on, + GPMC_CD_FCLK, "oe_on"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 8, 12, 0, t->oe_off, + GPMC_CD_FCLK, "oe_off"); if (gpmc_capability & GPMC_HAS_MUX_AAD) { - GPMC_SET_ONE(GPMC_CS_CONFIG4, 4, 6, oe_aad_mux_on); - GPMC_SET_ONE(GPMC_CS_CONFIG4, 13, 15, oe_aad_mux_off); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 4, 6, 0, + t->oe_aad_mux_on, GPMC_CD_FCLK, + "oe_aad_mux_on"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 13, 15, 0, + t->oe_aad_mux_off, GPMC_CD_FCLK, + "oe_aad_mux_off"); } - GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on); - GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 16, 19, 0, t->we_on, + GPMC_CD_FCLK, "we_on"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 24, 28, 0, t->we_off, + GPMC_CD_FCLK, "we_off"); + if (ret) + return -ENXIO; - GPMC_SET_ONE(GPMC_CS_CONFIG5, 0, 4, rd_cycle); - GPMC_SET_ONE(GPMC_CS_CONFIG5, 8, 12, wr_cycle); - GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 0, 4, 0, t->rd_cycle, + GPMC_CD_FCLK, "rd_cycle"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 8, 12, 0, t->wr_cycle, + GPMC_CD_FCLK, "wr_cycle"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 16, 20, 0, t->access, + GPMC_CD_FCLK, "access"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 24, 27, 0, + t->page_burst_access, GPMC_CD_FCLK, + "page_burst_access"); + if (ret) + return -ENXIO; - GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 0, 3, 0, + t->bus_turnaround, GPMC_CD_FCLK, + "bus_turnaround"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 8, 11, 0, + t->cycle2cycle_delay, GPMC_CD_FCLK, + "cycle2cycle_delay"); + if (ret) + return -ENXIO; - GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround); - GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay); - - if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) - GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); - if (gpmc_capability & GPMC_HAS_WR_ACCESS) - GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access); + if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) { + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 16, 19, 0, + t->wr_data_mux_bus, GPMC_CD_FCLK, + "wr_data_mux_bus"); + if (ret) + return -ENXIO; + } + if (gpmc_capability & GPMC_HAS_WR_ACCESS) { + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 24, 28, 0, + t->wr_access, GPMC_CD_FCLK, + "wr_access"); + if (ret) + return -ENXIO; + } l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); l &= ~0x03; l |= (div - 1); gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); - GPMC_SET_ONE_CD_MAX(GPMC_CS_CONFIG1, 18, 19, - GPMC_CONFIG1_WAITMONITORINGTIME_MAX, - wait_monitoring, GPMC_CD_CLK); - GPMC_SET_ONE_CD_MAX(GPMC_CS_CONFIG1, 25, 26, - GPMC_CONFIG1_CLKACTIVATIONTIME_MAX, - clk_activation, GPMC_CD_FCLK); + ret = 0; + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG1, 18, 19, + GPMC_CONFIG1_WAITMONITORINGTIME_MAX, + t->wait_monitoring, GPMC_CD_CLK, + "wait_monitoring"); + ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG1, 25, 26, + GPMC_CONFIG1_CLKACTIVATIONTIME_MAX, + t->clk_activation, GPMC_CD_FCLK, + "clk_activation"); + if (ret) + return -ENXIO; #ifdef CONFIG_OMAP_GPMC_DEBUG pr_info("GPMC CS%d CLK period is %lu ns (div %d)\n", From 07b6cc4540d3f3f198b62efd73a43806f031b2d6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 20:23:20 +0200 Subject: [PATCH 018/131] memory: omap-gpmc: use WARN() instead of BUG() on wrong free Since driver tracks reserved memory, freeing a non-reserved GPMC should not be fatal and crash the system. Printing a warning is friendlier. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724182328.3348-9-krzk@kernel.org --- drivers/memory/omap-gpmc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 2ef2a7a8ed51..76a9c700cbd5 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -1072,8 +1072,7 @@ void gpmc_cs_free(int cs) spin_lock(&gpmc_mem_lock); if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) { - printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); - BUG(); + WARN(1, "Trying to free non-reserved GPMC CS%d\n", cs); spin_unlock(&gpmc_mem_lock); return; } From dc1a9283f16a5c5c08a3d3b473e43a826ec3a177 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 20:23:22 +0200 Subject: [PATCH 019/131] memory: omap-gpmc: consistently use !res for NULL checks The driver already uses 'if (!res)' pattern in the probe function so be consistent. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724182328.3348-11-krzk@kernel.org --- drivers/memory/omap-gpmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 76a9c700cbd5..ce0e7e2d7cff 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -2393,7 +2393,7 @@ static int gpmc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpmc); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) + if (!res) return -ENOENT; gpmc_base = devm_ioremap_resource(&pdev->dev, res); From 3cd7040762a4727894f5f4bbb25550dc6f557ea7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 09:40:25 +0200 Subject: [PATCH 020/131] memory: renesas-rpc-if: simplify with PTR_ERR_OR_ZERO Use PTR_ERR_OR_ZERO to make the code a little bit simpler. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724074038.5597-17-krzk@kernel.org --- drivers/memory/renesas-rpc-if.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 88f51ec8f1d1..f2a33a1af836 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -199,10 +199,8 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev) rpc->dirmap = NULL; rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (IS_ERR(rpc->rstc)) - return PTR_ERR(rpc->rstc); - return 0; + return PTR_ERR_OR_ZERO(rpc->rstc); } EXPORT_SYMBOL(rpcif_sw_init); From 4a661364e6ff2901b29107cb8b9e57828418c887 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 09:40:33 +0200 Subject: [PATCH 021/131] memory: tegra: tegra210-emc: fix indentation Use tabs instead of spaces for indentation. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724074038.5597-25-krzk@kernel.org --- drivers/memory/tegra/tegra210-emc-cc-r21021.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c index ff55a17896fa..d60bdea3af3f 100644 --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c @@ -1044,7 +1044,7 @@ static void tegra210_emc_r21021_set_clock(struct tegra210_emc *emc, u32 clksrc) !opt_cc_short_zcal && opt_short_zcal) { value = (value & ~(EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK << EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_SHIFT)) | - ((zq_wait_long & EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK) << + ((zq_wait_long & EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK) << EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT); } else if (offset == EMC_ZCAL_INTERVAL && opt_zcal_en_cc) { value = 0; /* EMC_ZCAL_INTERVAL reset value. */ From 904ffa81b709f79b906077e72f4656bdb9930340 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 19:40:16 +0200 Subject: [PATCH 022/131] memory: brcmstb_dpfe: add separate entry for compile test Add separate entry for Broadcom STB DPFE driver, enabled by default on ARCH_BRCMSTB. This allows compile testing. Signed-off-by: Krzysztof Kozlowski Acked-by: Florian Fainelli --- drivers/memory/Kconfig | 12 ++++++++++++ drivers/memory/Makefile | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 2c79e95dd486..74432801f8fa 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -52,6 +52,18 @@ config ATMEL_EBI tree is used. This bus supports NANDs, external ethernet controller, SRAMs, ATA devices, etc. +config BRCMSTB_DPFE + bool "Broadcom STB DPFE driver" if COMPILE_TEST + default y if ARCH_BRCMSTB + depends on ARCH_BRCMSTB || COMPILE_TEST + help + This driver provides access to the DPFE interface of Broadcom + STB SoCs. The firmware running on the DCPU inside the DDR PHY can + provide current information about the system's RAM, for instance + the DRAM refresh rate. This can be used as an indirect indicator + for the DRAM's temperature. Slower refresh rate means cooler RAM, + higher refresh rate means hotter RAM. + config BT1_L2_CTL bool "Baikal-T1 CM2 L2-RAM Cache Control Block" depends on MIPS_BAIKAL_T1 || COMPILE_TEST diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index b4533ffff2bc..e71cf7b99641 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -10,7 +10,7 @@ endif obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o -obj-$(CONFIG_ARCH_BRCMSTB) += brcmstb_dpfe.o +obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o obj-$(CONFIG_TI_AEMIF) += ti-aemif.o obj-$(CONFIG_TI_EMIF) += emif.o From ea0c0ad6b6eb36726088991d97a55b99cae456d0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Jul 2020 09:40:15 +0200 Subject: [PATCH 023/131] memory: Enable compile testing for most of the drivers Most of the memory controller drivers do not depend on architecture specific code so can be compile tested to increase build coverage. When compile tested, do not enable them by default. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200724074038.5597-7-krzk@kernel.org --- drivers/memory/Kconfig | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 74432801f8fa..8072204bc21a 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -32,8 +32,9 @@ config ARM_PL172_MPMC config ATMEL_SDRAMC bool "Atmel (Multi-port DDR-)SDRAM Controller" - default y - depends on ARCH_AT91 && OF + default y if ARCH_AT91 + depends on ARCH_AT91 || COMPILE_TEST + depends on OF help This driver is for Atmel SDRAM Controller or Atmel Multi-port DDR-SDRAM Controller available on Atmel AT91SAM9 and SAMA5 SoCs. @@ -42,8 +43,9 @@ config ATMEL_SDRAMC config ATMEL_EBI bool "Atmel EBI driver" - default y - depends on ARCH_AT91 && OF + default y if ARCH_AT91 + depends on ARCH_AT91 || COMPILE_TEST + depends on OF select MFD_SYSCON select MFD_ATMEL_SMC help @@ -77,7 +79,8 @@ config BT1_L2_CTL config TI_AEMIF tristate "Texas Instruments AEMIF driver" - depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF + depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST + depends on OF help This driver is for the AEMIF module available in Texas Instruments SoCs. AEMIF stands for Asynchronous External Memory Interface and @@ -88,7 +91,7 @@ config TI_AEMIF config TI_EMIF tristate "Texas Instruments EMIF driver" - depends on ARCH_OMAP2PLUS + depends on ARCH_OMAP2PLUS || COMPILE_TEST select DDR help This driver is for the EMIF module available in Texas Instruments @@ -100,7 +103,7 @@ config TI_EMIF temperature changes config OMAP_GPMC - bool + bool "Texas Instruments OMAP SoC GPMC driver" if COMPILE_TEST select GPIOLIB help This driver is for the General Purpose Memory Controller (GPMC) @@ -124,7 +127,8 @@ config OMAP_GPMC_DEBUG config TI_EMIF_SRAM tristate "Texas Instruments EMIF SRAM driver" - depends on (SOC_AM33XX || SOC_AM43XX) && SRAM + depends on SOC_AM33XX || SOC_AM43XX || (ARM && COMPILE_TEST) + depends on SRAM help This driver is for the EMIF module available on Texas Instruments AM33XX and AM43XX SoCs and is required for PM. Certain parts of @@ -134,8 +138,9 @@ config TI_EMIF_SRAM config MVEBU_DEVBUS bool "Marvell EBU Device Bus Controller" - default y - depends on PLAT_ORION && OF + default y if PLAT_ORION + depends on PLAT_ORION || COMPILE_TEST + depends on OF help This driver is for the Device Bus controller available in some Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and @@ -144,7 +149,7 @@ config MVEBU_DEVBUS config FSL_CORENET_CF tristate "Freescale CoreNet Error Reporting" - depends on FSL_SOC_BOOKE + depends on FSL_SOC_BOOKE || COMPILE_TEST help Say Y for reporting of errors from the Freescale CoreNet Coherency Fabric. Errors reported include accesses to @@ -153,7 +158,7 @@ config FSL_CORENET_CF represents a coherency violation. config FSL_IFC - bool + bool "Freescale IFC driver" if COMPILE_TEST depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A || COMPILE_TEST depends on HAS_IOMEM @@ -167,7 +172,7 @@ config JZ4780_NEMC memory devices such as NAND and SRAM. config MTK_SMI - bool + bool "Mediatek SoC Memory Controller driver" if COMPILE_TEST depends on ARCH_MEDIATEK || COMPILE_TEST help This driver is for the Memory Controller module in MediaTek SoCs, @@ -176,7 +181,7 @@ config MTK_SMI config DA8XX_DDRCTL bool "Texas Instruments da8xx DDR2/mDDR driver" - depends on ARCH_DAVINCI_DA8XX + depends on ARCH_DAVINCI_DA8XX || COMPILE_TEST help This driver is for the DDR2/mDDR Memory Controller present on Texas Instruments da8xx SoCs. It's used to tweak various memory @@ -184,16 +189,16 @@ config DA8XX_DDRCTL config PL353_SMC tristate "ARM PL35X Static Memory Controller(SMC) driver" - default y + default y if ARM depends on ARM - depends on ARM_AMBA + depends on ARM_AMBA || COMPILE_TEST help This driver is for the ARM PL351/PL353 Static Memory Controller(SMC) module. config RENESAS_RPCIF tristate "Renesas RPC-IF driver" - depends on ARCH_RENESAS + depends on ARCH_RENESAS || COMPILE_TEST select REGMAP_MMIO help This supports Renesas R-Car Gen3 RPC-IF which provides either SPI From 296050a04c9e4e4017638599de8ef0c3cce375b3 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Tue, 18 Aug 2020 02:51:21 -0700 Subject: [PATCH 024/131] memory: tegra: Correct shift value of apew According to Tegra X1 (Tegra210) TRM, the APEW field is between [23:16] so the shift bit for apew should be 16 accordingly. Signed-off-by: Nicolin Chen Link: https://lore.kernel.org/r/20200818095121.13645-1-nicoleotsuka@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index cc0482434c75..3bdd7811efef 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c @@ -842,7 +842,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = { }, .la = { .reg = 0x3dc, - .shift = 0, + .shift = 16, .mask = 0xff, .def = 0x80, }, From 4da1edcf8f226d53c02c6b0e3077d581115b30d0 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Thu, 20 Aug 2020 18:21:18 +0100 Subject: [PATCH 025/131] memory: brcmstb_dpfe: Fix memory leak In brcmstb_dpfe_download_firmware(), memory is allocated to variable fw by firmware_request_nowarn(), but never released. Fix up to release fw on all return paths. Cc: Fixes: 2f330caff577 ("memory: brcmstb: Add driver for DPFE") Signed-off-by: Alex Dewar Acked-by: Markus Mayer Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20200820172118.781324-1-alex.dewar90@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/brcmstb_dpfe.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index 60e8633b1175..e08528b12cbd 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c @@ -647,8 +647,10 @@ static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv) return (ret == -ENOENT) ? -EPROBE_DEFER : ret; ret = __verify_firmware(&init, fw); - if (ret) - return -EFAULT; + if (ret) { + ret = -EFAULT; + goto release_fw; + } __disable_dcpu(priv); @@ -667,18 +669,20 @@ static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv) ret = __write_firmware(priv->dmem, dmem, dmem_size, is_big_endian); if (ret) - return ret; + goto release_fw; ret = __write_firmware(priv->imem, imem, imem_size, is_big_endian); if (ret) - return ret; + goto release_fw; ret = __verify_fw_checksum(&init, priv, header, init.chksum); if (ret) - return ret; + goto release_fw; __enable_dcpu(priv); - return 0; +release_fw: + release_firmware(fw); + return ret; } static ssize_t generic_show(unsigned int command, u32 response[], From ba171d3f0850003216fd1a85190d17b1feddb961 Mon Sep 17 00:00:00 2001 From: Cedric Neveux Date: Mon, 4 Mar 2019 08:54:23 +0100 Subject: [PATCH 026/131] driver: tee: Handle NULL pointer indication from client TEE Client introduce a new capability "TEE_GEN_CAP_MEMREF_NULL" to handle the support of the shared memory buffer with a NULL pointer. This capability depends on TEE Capabilities and driver support. Driver and TEE exchange capabilities at driver initialization. Signed-off-by: Michael Whitfield Signed-off-by: Cedric Neveux Reviewed-by: Joakim Bech Tested-by: Joakim Bech (QEMU) Signed-off-by: Jens Wiklander --- drivers/tee/optee/core.c | 7 ++++++ drivers/tee/optee/optee_smc.h | 3 +++ drivers/tee/tee_core.c | 47 ++++++++++++++++++++++------------- include/linux/tee_drv.h | 3 +++ include/uapi/linux/tee.h | 13 ++++++++++ 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index b373b1b08b6d..cf4718c6d35d 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -216,6 +216,8 @@ static void optee_get_version(struct tee_device *teedev, if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) v.gen_caps |= TEE_GEN_CAP_REG_MEM; + if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) + v.gen_caps |= TEE_GEN_CAP_MEMREF_NULL; *vers = v; } @@ -262,6 +264,11 @@ static int optee_open(struct tee_context *ctx) mutex_init(&ctxdata->mutex); INIT_LIST_HEAD(&ctxdata->sess_list); + if (optee->sec_caps & OPTEE_SMC_SEC_CAP_MEMREF_NULL) + ctx->cap_memref_null = true; + else + ctx->cap_memref_null = false; + ctx->data = ctxdata; return 0; } diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h index c72122d9c997..777ad54d4c2c 100644 --- a/drivers/tee/optee/optee_smc.h +++ b/drivers/tee/optee/optee_smc.h @@ -215,6 +215,9 @@ struct optee_smc_get_shm_config_result { */ #define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2) +/* Secure world supports Shared Memory with a NULL buffer reference */ +#define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4) + #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 64637e09a095..ce0f0309b6ac 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -383,25 +383,38 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params, case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: /* - * If we fail to get a pointer to a shared memory - * object (and increase the ref count) from an - * identifier we return an error. All pointers that - * has been added in params have an increased ref - * count. It's the callers responibility to do - * tee_shm_put() on all resolved pointers. + * If a NULL pointer is passed to a TA in the TEE, + * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL + * indicating a NULL memory reference. */ - shm = tee_shm_get_from_id(ctx, ip.c); - if (IS_ERR(shm)) - return PTR_ERR(shm); + if (ip.c != TEE_MEMREF_NULL) { + /* + * If we fail to get a pointer to a shared + * memory object (and increase the ref count) + * from an identifier we return an error. All + * pointers that has been added in params have + * an increased ref count. It's the callers + * responibility to do tee_shm_put() on all + * resolved pointers. + */ + shm = tee_shm_get_from_id(ctx, ip.c); + if (IS_ERR(shm)) + return PTR_ERR(shm); - /* - * Ensure offset + size does not overflow offset - * and does not overflow the size of the referred - * shared memory object. - */ - if ((ip.a + ip.b) < ip.a || - (ip.a + ip.b) > shm->size) { - tee_shm_put(shm); + /* + * Ensure offset + size does not overflow + * offset and does not overflow the size of + * the referred shared memory object. + */ + if ((ip.a + ip.b) < ip.a || + (ip.a + ip.b) > shm->size) { + tee_shm_put(shm); + return -EINVAL; + } + } else if (ctx->cap_memref_null) { + /* Pass NULL pointer to OP-TEE */ + shm = NULL; + } else { return -EINVAL; } diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index d074302989dd..cdd049a724b1 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -47,6 +47,8 @@ struct tee_shm_pool; * and just return with an error code. It is needed for requests * that arises from TEE based kernel drivers that should be * non-blocking in nature. + * @cap_memref_null: flag indicating if the TEE Client support shared + * memory buffer with a NULL pointer. */ struct tee_context { struct tee_device *teedev; @@ -54,6 +56,7 @@ struct tee_context { struct kref refcount; bool releasing; bool supp_nowait; + bool cap_memref_null; }; struct tee_param_memref { diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index b619f37ee03e..d67cadf221fc 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -51,6 +51,9 @@ #define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */ #define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ #define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */ +#define TEE_GEN_CAP_MEMREF_NULL (1 << 3)/* NULL MemRef support */ + +#define TEE_MEMREF_NULL (__u64)(-1) /* NULL MemRef Buffer */ /* * TEE Implementation ID @@ -200,6 +203,16 @@ struct tee_ioctl_buf_data { * a part of a shared memory by specifying an offset (@a) and size (@b) of * the object. To supply the entire shared memory object set the offset * (@a) to 0 and size (@b) to the previously returned size of the object. + * + * A client may need to present a NULL pointer in the argument + * passed to a trusted application in the TEE. + * This is also a requirement in GlobalPlatform Client API v1.0c + * (section 3.2.5 memory references), which can be found at + * http://www.globalplatform.org/specificationsdevice.asp + * + * If a NULL pointer is passed to a TA in the TEE, the (@c) + * IOCTL parameters value must be set to TEE_MEMREF_NULL indicating a NULL + * memory reference. */ struct tee_ioctl_param { __u64 attr; From c05210ab975771e161427eb47696b869d820bdaf Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Fri, 14 Aug 2020 13:12:21 +0200 Subject: [PATCH 027/131] drivers: optee: allow op-tee to access devices on the i2c bus Some secure elements like NXP's SE050 sit on I2C buses. For OP-TEE to control this type of cryptographic devices it needs coordinated access to the bus, so collisions and RUNTIME_PM dont get in the way. This trampoline driver allow OP-TEE to access them. Signed-off-by: Jorge Ramirez-Ortiz Signed-off-by: Jens Wiklander --- drivers/tee/optee/optee_msg.h | 21 +++++++ drivers/tee/optee/optee_private.h | 1 + drivers/tee/optee/rpc.c | 95 +++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h index 795bc19ae17a..7b2d919da2ac 100644 --- a/drivers/tee/optee/optee_msg.h +++ b/drivers/tee/optee/optee_msg.h @@ -419,4 +419,25 @@ struct optee_msg_arg { */ #define OPTEE_MSG_RPC_CMD_SHM_FREE 7 +/* + * Access a device on an i2c bus + * + * [in] param[0].u.value.a mode: RD(0), WR(1) + * [in] param[0].u.value.b i2c adapter + * [in] param[0].u.value.c i2c chip + * + * [in] param[1].u.value.a i2c control flags + * + * [in/out] memref[2] buffer to exchange the transfer data + * with the secure world + * + * [out] param[3].u.value.a bytes transferred by the driver + */ +#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER 21 +/* I2C master transfer modes */ +#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD 0 +#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR 1 +/* I2C master control flags */ +#define OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT BIT(0) + #endif /* _OPTEE_MSG_H */ diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 8b71839a357e..e25b216a14ef 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -17,6 +17,7 @@ /* Some Global Platform error codes used in this driver */ #define TEEC_SUCCESS 0x00000000 #define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 +#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A #define TEEC_ERROR_COMMUNICATION 0xFFFF000E #define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C #define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010 diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index b4ade54d1f28..64a206c56264 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include "optee_private.h" @@ -49,6 +50,97 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg) arg->ret = TEEC_ERROR_BAD_PARAMETERS; } +#if IS_ENABLED(CONFIG_I2C) +static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, + struct optee_msg_arg *arg) +{ + struct i2c_client client = { 0 }; + struct tee_param *params; + size_t i; + int ret = -EOPNOTSUPP; + u8 attr[] = { + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT, + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT, + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT, + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT, + }; + + if (arg->num_params != ARRAY_SIZE(attr)) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + return; + } + + params = kmalloc_array(arg->num_params, sizeof(struct tee_param), + GFP_KERNEL); + if (!params) { + arg->ret = TEEC_ERROR_OUT_OF_MEMORY; + return; + } + + if (optee_from_msg_param(params, arg->num_params, arg->params)) + goto bad; + + for (i = 0; i < arg->num_params; i++) { + if (params[i].attr != attr[i]) + goto bad; + } + + client.adapter = i2c_get_adapter(params[0].u.value.b); + if (!client.adapter) + goto bad; + + if (params[1].u.value.a & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT) { + if (!i2c_check_functionality(client.adapter, + I2C_FUNC_10BIT_ADDR)) { + i2c_put_adapter(client.adapter); + goto bad; + } + + client.flags = I2C_CLIENT_TEN; + } + + client.addr = params[0].u.value.c; + snprintf(client.name, I2C_NAME_SIZE, "i2c%d", client.adapter->nr); + + switch (params[0].u.value.a) { + case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD: + ret = i2c_master_recv(&client, params[2].u.memref.shm->kaddr, + params[2].u.memref.size); + break; + case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR: + ret = i2c_master_send(&client, params[2].u.memref.shm->kaddr, + params[2].u.memref.size); + break; + default: + i2c_put_adapter(client.adapter); + goto bad; + } + + if (ret < 0) { + arg->ret = TEEC_ERROR_COMMUNICATION; + } else { + params[3].u.value.a = ret; + if (optee_to_msg_param(arg->params, arg->num_params, params)) + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + else + arg->ret = TEEC_SUCCESS; + } + + i2c_put_adapter(client.adapter); + kfree(params); + return; +bad: + kfree(params); + arg->ret = TEEC_ERROR_BAD_PARAMETERS; +} +#else +static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, + struct optee_msg_arg *arg) +{ + arg->ret = TEEC_ERROR_NOT_SUPPORTED; +} +#endif + static struct wq_entry *wq_entry_get(struct optee_wait_queue *wq, u32 key) { struct wq_entry *w; @@ -382,6 +474,9 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, case OPTEE_MSG_RPC_CMD_SHM_FREE: handle_rpc_func_cmd_shm_free(ctx, arg); break; + case OPTEE_MSG_RPC_CMD_I2C_TRANSFER: + handle_rpc_func_cmd_i2c_transfer(ctx, arg); + break; default: handle_rpc_supp_cmd(ctx, arg); } From b663b798d04fb73f1ad4d54c46582d2fde7a76d6 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 11 Aug 2020 11:04:42 +0800 Subject: [PATCH 028/131] soc: imx: gpcv2: Use dev_err_probe() to simplify error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev_err_probe() can reduce code size, uniform error handling and record the defer probe reason etc., use it to simplify the code. Signed-off-by: Anson Huang Reviewed-by: Guido Günther Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 6cf8a7a412bd..db7e7fc321b1 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -487,22 +487,17 @@ static int imx_pgc_domain_probe(struct platform_device *pdev) domain->regulator = devm_regulator_get_optional(domain->dev, "power"); if (IS_ERR(domain->regulator)) { - if (PTR_ERR(domain->regulator) != -ENODEV) { - if (PTR_ERR(domain->regulator) != -EPROBE_DEFER) - dev_err(domain->dev, "Failed to get domain's regulator\n"); - return PTR_ERR(domain->regulator); - } + if (PTR_ERR(domain->regulator) != -ENODEV) + return dev_err_probe(domain->dev, PTR_ERR(domain->regulator), + "Failed to get domain's regulator\n"); } else if (domain->voltage) { regulator_set_voltage(domain->regulator, domain->voltage, domain->voltage); } ret = imx_pgc_get_clocks(domain); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(domain->dev, "Failed to get domain's clocks\n"); - return ret; - } + if (ret) + return dev_err_probe(domain->dev, ret, "Failed to get domain's clocks\n"); ret = pm_genpd_init(&domain->genpd, NULL, true); if (ret) { From f42ae4bbf94c15aa720afb9d176ecbfe140d792e Mon Sep 17 00:00:00 2001 From: Markus Mayer Date: Sat, 22 Aug 2020 13:50:00 -0700 Subject: [PATCH 029/131] memory: brcmstb_dpfe: fix array index out of bounds We would overrun the error_text array if we hit a TIMEOUT condition, because we were using the error code "ETIMEDOUT" (which is 110) as an array index. We fix the problem by correcting the array index and by providing a function to retrieve error messages rather than accessing the array directly. The function includes a bounds check that prevents the array from being overrun. Link: https://lore.kernel.org/linux-arm-kernel/38d00022-730c-948a-917c-d86382df8cb9@canonical.com/ Link: https://lore.kernel.org/r/20200822205000.15841-1-mmayer@broadcom.com Fixes: 2f330caff577 ("memory: brcmstb: Add driver for DPFE") Reported-by: Colin Ian King Signed-off-by: Markus Mayer Acked-by: Florian Fainelli Signed-off-by: Krzysztof Kozlowski --- drivers/memory/brcmstb_dpfe.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index e08528b12cbd..dcf50bb8dd69 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c @@ -188,11 +188,6 @@ struct brcmstb_dpfe_priv { struct mutex lock; }; -static const char * const error_text[] = { - "Success", "Header code incorrect", "Unknown command or argument", - "Incorrect checksum", "Malformed command", "Timed out", -}; - /* * Forward declaration of our sysfs attribute functions, so we can declare the * attribute data structures early. @@ -307,6 +302,20 @@ static const struct dpfe_api dpfe_api_v3 = { }, }; +static const char *get_error_text(unsigned int i) +{ + static const char * const error_text[] = { + "Success", "Header code incorrect", + "Unknown command or argument", "Incorrect checksum", + "Malformed command", "Timed out", "Unknown error", + }; + + if (unlikely(i >= ARRAY_SIZE(error_text))) + i = ARRAY_SIZE(error_text) - 1; + + return error_text[i]; +} + static bool is_dcpu_enabled(struct brcmstb_dpfe_priv *priv) { u32 val; @@ -445,7 +454,7 @@ static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd, } if (resp != 0) { mutex_unlock(&priv->lock); - return -ETIMEDOUT; + return -ffs(DCPU_RET_ERR_TIMEDOUT); } /* Compute checksum over the message */ @@ -695,7 +704,7 @@ static ssize_t generic_show(unsigned int command, u32 response[], ret = __send_command(priv, command, response); if (ret < 0) - return sprintf(buf, "ERROR: %s\n", error_text[-ret]); + return sprintf(buf, "ERROR: %s\n", get_error_text(-ret)); return 0; } From 4300cd6374a5192a2c8122a4a48ed647bdcb0214 Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Mon, 24 Aug 2020 14:11:25 -0700 Subject: [PATCH 030/131] tee: convert get_user_pages() --> pin_user_pages() This code was using get_user_pages*(), in a "Case 2" scenario (DMA/RDMA), using the categorization from [1]. That means that it's time to convert the get_user_pages*() + put_page() calls to pin_user_pages*() + unpin_user_pages() calls. Factor out a new, small release_registered_pages() function, in order to consolidate the logic for discerning between TEE_SHM_USER_MAPPED and TEE_SHM_KERNEL_MAPPED pages. This also absorbs the kfree() call that is also required there. There is some helpful background in [2]: basically, this is a small part of fixing a long-standing disconnect between pinning pages, and file systems' use of those pages. [1] Documentation/core-api/pin_user_pages.rst [2] "Explicit pinning of user-space pages": https://lwn.net/Articles/807108/ Cc: Jens Wiklander Cc: Sumit Semwal Cc: tee-dev@lists.linaro.org Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Signed-off-by: John Hubbard Signed-off-by: Jens Wiklander --- drivers/tee/tee_shm.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 827ac3d0fea9..00472f5ce22e 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -12,6 +12,22 @@ #include #include "tee_private.h" +static void release_registered_pages(struct tee_shm *shm) +{ + if (shm->pages) { + if (shm->flags & TEE_SHM_USER_MAPPED) { + unpin_user_pages(shm->pages, shm->num_pages); + } else { + size_t n; + + for (n = 0; n < shm->num_pages; n++) + put_page(shm->pages[n]); + } + + kfree(shm->pages); + } +} + static void tee_shm_release(struct tee_shm *shm) { struct tee_device *teedev = shm->ctx->teedev; @@ -32,17 +48,13 @@ static void tee_shm_release(struct tee_shm *shm) poolm->ops->free(poolm, shm); } else if (shm->flags & TEE_SHM_REGISTER) { - size_t n; int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm); if (rc) dev_err(teedev->dev.parent, "unregister shm %p failed: %d", shm, rc); - for (n = 0; n < shm->num_pages; n++) - put_page(shm->pages[n]); - - kfree(shm->pages); + release_registered_pages(shm); } teedev_ctx_put(shm->ctx); @@ -228,7 +240,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, } if (flags & TEE_SHM_USER_MAPPED) { - rc = get_user_pages_fast(start, num_pages, FOLL_WRITE, + rc = pin_user_pages_fast(start, num_pages, FOLL_WRITE, shm->pages); } else { struct kvec *kiov; @@ -292,18 +304,12 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, return shm; err: if (shm) { - size_t n; - if (shm->id >= 0) { mutex_lock(&teedev->mutex); idr_remove(&teedev->idr, shm->id); mutex_unlock(&teedev->mutex); } - if (shm->pages) { - for (n = 0; n < shm->num_pages; n++) - put_page(shm->pages[n]); - kfree(shm->pages); - } + release_registered_pages(shm); } kfree(shm); teedev_ctx_put(ctx); From 928bfbc6c76ca7bad7cf8d52b4b0b1802325f2b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Aug 2020 13:50:55 +0900 Subject: [PATCH 031/131] soc: renesas: Use menu for Renesas SoC Renesas related SoC settings are located on TOP level menu, thus it is very verbose. This patch groups Renesas related settings into "Renesas SoC driver support" menu. And it aligns config menu names. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k0xxho7t.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 30984659df90..265a59345909 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -config SOC_RENESAS +menuconfig SOC_RENESAS bool "Renesas SoC driver support" if COMPILE_TEST && !ARCH_RENESAS default y if ARCH_RENESAS select SOC_BUS From 4c54228ac8fd55044195825873c50a524131fa53 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Aug 2020 13:47:07 +0300 Subject: [PATCH 032/131] memory: omap-gpmc: Fix a couple off by ones These comparisons should be >= instead of > to prevent reading one element beyond the end of the gpmc_cs[] array. Fixes: cdd6928c589a ("ARM: OMAP2+: Add device-tree support for NOR flash") Fixes: f37e4580c409 ("ARM: OMAP2: Dynamic allocator for GPMC memory space") Signed-off-by: Dan Carpenter Acked-by: Roger Quadros Link: https://lore.kernel.org/r/20200825104707.GB278587@mwanda Signed-off-by: Krzysztof Kozlowski --- drivers/memory/omap-gpmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index ce0e7e2d7cff..2cd7ddf128ec 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -990,7 +990,7 @@ static int gpmc_cs_remap(int cs, u32 base) int ret; u32 old_base, size; - if (cs > gpmc_cs_num) { + if (cs >= gpmc_cs_num) { pr_err("%s: requested chip-select is disabled\n", __func__); return -ENODEV; } @@ -1025,7 +1025,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) struct resource *res = &gpmc->mem; int r = -1; - if (cs > gpmc_cs_num) { + if (cs >= gpmc_cs_num) { pr_err("%s: requested chip-select is disabled\n", __func__); return -ENODEV; } From 13d029ee51da365aa9c859db0c7395129252bde8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 27 Aug 2020 20:53:16 +0800 Subject: [PATCH 033/131] memory: omap-gpmc: Fix build error without CONFIG_OF If CONFIG_OF is n, gcc fails: drivers/memory/omap-gpmc.o: In function `gpmc_omap_onenand_set_timings': omap-gpmc.c:(.text+0x2a88): undefined reference to `gpmc_read_settings_dt' Add gpmc_read_settings_dt() helper function, which zero the gpmc_settings so the caller doesn't proceed with random/invalid settings. Fixes: a758f50f10cf ("mtd: onenand: omap2: Configure driver from DT") Signed-off-by: YueHaibing Acked-by: Roger Quadros Link: https://lore.kernel.org/r/20200827125316.20780-1-yuehaibing@huawei.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/omap-gpmc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 2cd7ddf128ec..8932c5b266e4 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -2311,6 +2311,10 @@ static void gpmc_probe_dt_children(struct platform_device *pdev) } } #else +void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p) +{ + memset(p, 0, sizeof(*p)); +} static int gpmc_probe_dt(struct platform_device *pdev) { return 0; From fd22781648080cc400772b3c68aa6b059d2d5420 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 26 Aug 2020 14:37:59 +0300 Subject: [PATCH 034/131] memory: emif: Remove bogus debugfs error handling Callers are generally not supposed to check the return values from debugfs functions. Debugfs functions never return NULL so this error handling will never trigger. (Historically debugfs functions used to return a mix of NULL and error pointers but it was eventually deemed too complicated for something which wasn't intended to be used in normal situations). Delete all the error handling. Signed-off-by: Dan Carpenter Acked-by: Santosh Shilimkar Link: https://lore.kernel.org/r/20200826113759.GF393664@mwanda Signed-off-by: Krzysztof Kozlowski --- drivers/memory/emif.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index bb6a71d26798..5c4d8319c9cf 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -163,35 +163,12 @@ static const struct file_operations emif_mr4_fops = { static int __init_or_module emif_debugfs_init(struct emif_data *emif) { - struct dentry *dentry; - int ret; - - dentry = debugfs_create_dir(dev_name(emif->dev), NULL); - if (!dentry) { - ret = -ENOMEM; - goto err0; - } - emif->debugfs_root = dentry; - - dentry = debugfs_create_file("regcache_dump", S_IRUGO, - emif->debugfs_root, emif, &emif_regdump_fops); - if (!dentry) { - ret = -ENOMEM; - goto err1; - } - - dentry = debugfs_create_file("mr4", S_IRUGO, - emif->debugfs_root, emif, &emif_mr4_fops); - if (!dentry) { - ret = -ENOMEM; - goto err1; - } - + emif->debugfs_root = debugfs_create_dir(dev_name(emif->dev), NULL); + debugfs_create_file("regcache_dump", S_IRUGO, emif->debugfs_root, emif, + &emif_regdump_fops); + debugfs_create_file("mr4", S_IRUGO, emif->debugfs_root, emif, + &emif_mr4_fops); return 0; -err1: - debugfs_remove_recursive(emif->debugfs_root); -err0: - return ret; } static void __exit emif_debugfs_exit(struct emif_data *emif) From 464d9b349be634bd12978f2554b2b0198e56399d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Aug 2020 11:22:06 +0900 Subject: [PATCH 035/131] soc: renesas: Align driver description titles Now, Renesas SoC drivers are under menu, but current descriptions are not aligned. This patch aligns them. - Emma Mobile EV2 - RZ/A1H (R7S72100) ... - R-Car H2 (R8A77900) ... - Renesas R-Car H3 ES1.x SoC Platform ... - R-Car H2 System Controller support - R-Car M2-W/N System Controller support - R-Car V2H System Controller support - R-Car E2 System Controller support - R-Car H3 System Controller support - R-Car M3-W System Controller support - R-Car M3-W+ System Controller support - R-Car M3-N System Controller support + SoC Platform support for Emma Mobile EV2 + SoC Platform support for RZ/A1H+ ... + SoC Platform support for R-Car H2 ... + SoC Platform support for R-Car H3 ES1.x ... + System Controller support for R-Car H2 + System Controller support for R-Car M2-W/N + System Controller support for R-Car V2H + System Controller support for R-Car E2 + System Controller support for R-Car H3 + System Controller support for R-Car M3-W + System Controller support for R-Car M3-W+ + System Controller support for R-Car M3-N Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87zh6kyedc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 112 ++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 265a59345909..7d63a13e5b78 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -49,12 +49,12 @@ if ARM && ARCH_RENESAS #comment "Renesas ARM SoCs System Type" config ARCH_EMEV2 - bool "Emma Mobile EV2" + bool "SoC Platform support for Emma Mobile EV2" select HAVE_ARM_SCU if SMP select SYS_SUPPORTS_EM_STI config ARCH_R7S72100 - bool "RZ/A1H (R7S72100)" + bool "SoC Platform support for RZ/A1H" select ARM_ERRATA_754322 select PM select PM_GENERIC_DOMAINS @@ -63,14 +63,14 @@ config ARCH_R7S72100 select SYS_SUPPORTS_SH_MTU2 config ARCH_R7S9210 - bool "RZ/A2 (R7S9210)" + bool "SoC Platform support for RZ/A2" select PM select PM_GENERIC_DOMAINS select RENESAS_OSTM select RENESAS_RZA1_IRQC config ARCH_R8A73A4 - bool "R-Mobile APE6 (R8A73A40)" + bool "SoC Platform support for R-Mobile APE6" select ARCH_RMOBILE select ARM_ERRATA_798181 if SMP select ARM_ERRATA_814220 @@ -78,49 +78,49 @@ config ARCH_R8A73A4 select RENESAS_IRQC config ARCH_R8A7740 - bool "R-Mobile A1 (R8A77400)" + bool "SoC Platform support for R-Mobile A1" select ARCH_RMOBILE select ARM_ERRATA_754322 select RENESAS_INTC_IRQPIN config ARCH_R8A7742 - bool "RZ/G1H (R8A77420)" + bool "SoC Platform support for RZ/G1H" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select ARM_ERRATA_814220 select SYSC_R8A7742 config ARCH_R8A7743 - bool "RZ/G1M (R8A77430)" + bool "SoC Platform support for RZ/G1M" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select SYSC_R8A7743 config ARCH_R8A7744 - bool "RZ/G1N (R8A77440)" + bool "SoC Platform support for RZ/G1N" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select SYSC_R8A7743 config ARCH_R8A7745 - bool "RZ/G1E (R8A77450)" + bool "SoC Platform support for RZ/G1E" select ARCH_RCAR_GEN2 select ARM_ERRATA_814220 select SYSC_R8A7745 config ARCH_R8A77470 - bool "RZ/G1C (R8A77470)" + bool "SoC Platform support for RZ/G1C" select ARCH_RCAR_GEN2 select ARM_ERRATA_814220 select SYSC_R8A77470 config ARCH_R8A7778 - bool "R-Car M1A (R8A77781)" + bool "SoC Platform support for R-Car M1A" select ARCH_RCAR_GEN1 select ARM_ERRATA_754322 config ARCH_R8A7779 - bool "R-Car H1 (R8A77790)" + bool "SoC Platform support for R-Car H1" select ARCH_RCAR_GEN1 select ARM_ERRATA_754322 select ARM_GLOBAL_TIMER @@ -129,7 +129,7 @@ config ARCH_R8A7779 select SYSC_R8A7779 config ARCH_R8A7790 - bool "R-Car H2 (R8A77900)" + bool "SoC Platform support for R-Car H2" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select ARM_ERRATA_814220 @@ -137,38 +137,38 @@ config ARCH_R8A7790 select SYSC_R8A7790 config ARCH_R8A7791 - bool "R-Car M2-W (R8A77910)" + bool "SoC Platform support for R-Car M2-W" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select I2C select SYSC_R8A7791 config ARCH_R8A7792 - bool "R-Car V2H (R8A77920)" + bool "SoC Platform support for R-Car V2H" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select SYSC_R8A7792 config ARCH_R8A7793 - bool "R-Car M2-N (R8A7793)" + bool "SoC Platform support for R-Car M2-N" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select I2C select SYSC_R8A7791 config ARCH_R8A7794 - bool "R-Car E2 (R8A77940)" + bool "SoC Platform support for R-Car E2" select ARCH_RCAR_GEN2 select ARM_ERRATA_814220 select SYSC_R8A7794 config ARCH_R9A06G032 - bool "RZ/N1D (R9A06G032)" + bool "SoC Platform support for RZ/N1D" select ARCH_RZN1 select ARM_ERRATA_814220 config ARCH_SH73A0 - bool "SH-Mobile AG5 (R8A73A00)" + bool "SoC Platform support for SH-Mobile AG5" select ARCH_RMOBILE select ARM_ERRATA_754322 select ARM_GLOBAL_TIMER @@ -181,42 +181,42 @@ endif # ARM if ARM64 config ARCH_R8A774A1 - bool "Renesas RZ/G2M SoC Platform" + bool "SoC Platform support for RZ/G2M" select ARCH_RCAR_GEN3 select SYSC_R8A774A1 help This enables support for the Renesas RZ/G2M SoC. config ARCH_R8A774B1 - bool "Renesas RZ/G2N SoC Platform" + bool "SoC Platform support for RZ/G2N" select ARCH_RCAR_GEN3 select SYSC_R8A774B1 help This enables support for the Renesas RZ/G2N SoC. config ARCH_R8A774C0 - bool "Renesas RZ/G2E SoC Platform" + bool "SoC Platform support for RZ/G2E" select ARCH_RCAR_GEN3 select SYSC_R8A774C0 help This enables support for the Renesas RZ/G2E SoC. config ARCH_R8A774E1 - bool "Renesas RZ/G2H SoC Platform" + bool "SoC Platform support for RZ/G2H" select ARCH_RCAR_GEN3 select SYSC_R8A774E1 help This enables support for the Renesas RZ/G2H SoC. config ARCH_R8A77950 - bool "Renesas R-Car H3 ES1.x SoC Platform" + bool "SoC Platform support for R-Car H3 ES1.x" select ARCH_RCAR_GEN3 select SYSC_R8A7795 help This enables support for the Renesas R-Car H3 SoC (revision 1.x). config ARCH_R8A77951 - bool "Renesas R-Car H3 ES2.0+ SoC Platform" + bool "SoC Platform support for R-Car H3 ES2.0+" select ARCH_RCAR_GEN3 select SYSC_R8A7795 help @@ -224,49 +224,49 @@ config ARCH_R8A77951 later). config ARCH_R8A77960 - bool "Renesas R-Car M3-W SoC Platform" + bool "SoC Platform support for R-Car M3-W" select ARCH_RCAR_GEN3 select SYSC_R8A77960 help This enables support for the Renesas R-Car M3-W SoC. config ARCH_R8A77961 - bool "Renesas R-Car M3-W+ SoC Platform" + bool "SoC Platform support for R-Car M3-W+" select ARCH_RCAR_GEN3 select SYSC_R8A77961 help This enables support for the Renesas R-Car M3-W+ SoC. config ARCH_R8A77965 - bool "Renesas R-Car M3-N SoC Platform" + bool "SoC Platform support for R-Car M3-N" select ARCH_RCAR_GEN3 select SYSC_R8A77965 help This enables support for the Renesas R-Car M3-N SoC. config ARCH_R8A77970 - bool "Renesas R-Car V3M SoC Platform" + bool "SoC Platform support for R-Car V3M" select ARCH_RCAR_GEN3 select SYSC_R8A77970 help This enables support for the Renesas R-Car V3M SoC. config ARCH_R8A77980 - bool "Renesas R-Car V3H SoC Platform" + bool "SoC Platform support for R-Car V3H" select ARCH_RCAR_GEN3 select SYSC_R8A77980 help This enables support for the Renesas R-Car V3H SoC. config ARCH_R8A77990 - bool "Renesas R-Car E3 SoC Platform" + bool "SoC Platform support for R-Car E3" select ARCH_RCAR_GEN3 select SYSC_R8A77990 help This enables support for the Renesas R-Car E3 SoC. config ARCH_R8A77995 - bool "Renesas R-Car D3 SoC Platform" + bool "SoC Platform support for R-Car D3" select ARCH_RCAR_GEN3 select SYSC_R8A77995 help @@ -276,97 +276,97 @@ endif # ARM64 # SoC config SYSC_R8A7742 - bool "RZ/G1H System Controller support" if COMPILE_TEST + bool "System Controller support for RZ/G1H" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7743 - bool "RZ/G1M System Controller support" if COMPILE_TEST + bool "System Controller support for RZ/G1M" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7745 - bool "RZ/G1E System Controller support" if COMPILE_TEST + bool "System Controller support for RZ/G1E" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77470 - bool "RZ/G1C System Controller support" if COMPILE_TEST + bool "System Controller support for RZ/G1C" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A774A1 - bool "RZ/G2M System Controller support" if COMPILE_TEST + bool "System Controller support for RZ/G2M" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A774B1 - bool "RZ/G2N System Controller support" if COMPILE_TEST + bool "System Controller support for RZ/G2N" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A774C0 - bool "RZ/G2E System Controller support" if COMPILE_TEST + bool "System Controller support for RZ/G2E" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A774E1 - bool "RZ/G2H System Controller support" if COMPILE_TEST + bool "System Controller support for RZ/G2H" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7779 - bool "R-Car H1 System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car H1" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7790 - bool "R-Car H2 System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car H2" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7791 - bool "R-Car M2-W/N System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car M2-W/N" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7792 - bool "R-Car V2H System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car V2H" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7794 - bool "R-Car E2 System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car E2" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7795 - bool "R-Car H3 System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car H3" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77960 - bool "R-Car M3-W System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car M3-W" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77961 - bool "R-Car M3-W+ System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car M3-W+" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77965 - bool "R-Car M3-N System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car M3-N" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77970 - bool "R-Car V3M System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car V3M" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77980 - bool "R-Car V3H System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car V3H" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77990 - bool "R-Car E3 System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car E3" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77995 - bool "R-Car D3 System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car D3" if COMPILE_TEST select SYSC_RCAR # Family config RST_RCAR - bool "R-Car Reset Controller support" if COMPILE_TEST + bool "Reset Controller support for R-Car" if COMPILE_TEST config SYSC_RCAR - bool "R-Car System Controller support" if COMPILE_TEST + bool "System Controller support for R-Car" if COMPILE_TEST config SYSC_RMOBILE - bool "R-Mobile System Controller support" if COMPILE_TEST + bool "System Controller support for R-Mobile" if COMPILE_TEST endif # SOC_RENESAS From 539f8fc253ece5501fdea1a6aa227d0618374111 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 31 Aug 2020 18:11:02 +0200 Subject: [PATCH 036/131] drivers: optee: fix i2c build issue When the optee driver is compiled into the kernel while the i2c core is configured as a module, the i2c symbols are not available. This commit addresses the situation by disabling the i2c support for this use case while allowing it in all other scenarios: i2c=y, optee=y i2c=m, optee=m i2c=y, optee=m i2c=m, optee=y (not supported) Fixes: c05210ab9757 ("drivers: optee: allow op-tee to access devices on the i2c bus") Reported-by: kernel test robot Signed-off-by: Jorge Ramirez-Ortiz Signed-off-by: Jens Wiklander --- drivers/tee/optee/rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index 64a206c56264..1e3614e4798f 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -50,7 +50,7 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg) arg->ret = TEEC_ERROR_BAD_PARAMETERS; } -#if IS_ENABLED(CONFIG_I2C) +#if IS_REACHABLE(CONFIG_I2C) static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, struct optee_msg_arg *arg) { From bb0ebc7d39647c2e5062fb112d90f41fc2113aae Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 22 Aug 2020 18:32:16 +0200 Subject: [PATCH 037/131] memory: samsung: exynos5422-dmc: rename timing register fields variables The driver has file-scope arrays defining fields of timing registers (e.g. struct timing_reg timing_row) and actual values for these registers per each OPP in state container (struct exynos5_dmc.timing_row). The meanings of these are different so use different names to avoid confusion. Signed-off-by: Krzysztof Kozlowski Acked-by: Lukasz Luba Link: https://lore.kernel.org/r/20200822163218.21857-1-krzk@kernel.org --- drivers/memory/samsung/exynos5422-dmc.c | 49 +++++++++++++------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c index 0045fa536b2b..31864ce59b25 100644 --- a/drivers/memory/samsung/exynos5422-dmc.c +++ b/drivers/memory/samsung/exynos5422-dmc.c @@ -170,7 +170,7 @@ struct timing_reg { unsigned int val; }; -static const struct timing_reg timing_row[] = { +static const struct timing_reg timing_row_reg_fields[] = { TIMING_FIELD("tRFC", 24, 31), TIMING_FIELD("tRRD", 20, 23), TIMING_FIELD("tRP", 16, 19), @@ -179,7 +179,7 @@ static const struct timing_reg timing_row[] = { TIMING_FIELD("tRAS", 0, 5), }; -static const struct timing_reg timing_data[] = { +static const struct timing_reg timing_data_reg_fields[] = { TIMING_FIELD("tWTR", 28, 31), TIMING_FIELD("tWR", 24, 27), TIMING_FIELD("tRTP", 20, 23), @@ -190,7 +190,7 @@ static const struct timing_reg timing_data[] = { TIMING_FIELD("RL", 0, 3), }; -static const struct timing_reg timing_power[] = { +static const struct timing_reg timing_power_reg_fields[] = { TIMING_FIELD("tFAW", 26, 31), TIMING_FIELD("tXSR", 16, 25), TIMING_FIELD("tXP", 8, 15), @@ -198,8 +198,9 @@ static const struct timing_reg timing_power[] = { TIMING_FIELD("tMRD", 0, 3), }; -#define TIMING_COUNT (ARRAY_SIZE(timing_row) + ARRAY_SIZE(timing_data) + \ - ARRAY_SIZE(timing_power)) +#define TIMING_COUNT (ARRAY_SIZE(timing_row_reg_fields) + \ + ARRAY_SIZE(timing_data_reg_fields) + \ + ARRAY_SIZE(timing_power_reg_fields)) static int exynos5_counters_set_event(struct exynos5_dmc *dmc) { @@ -1022,117 +1023,117 @@ static int create_timings_aligned(struct exynos5_dmc *dmc, u32 *reg_timing_row, val = dmc->timings->tRFC / clk_period_ps; val += dmc->timings->tRFC % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tRFC); - reg = &timing_row[0]; + reg = &timing_row_reg_fields[0]; *reg_timing_row |= TIMING_VAL2REG(reg, val); val = dmc->timings->tRRD / clk_period_ps; val += dmc->timings->tRRD % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tRRD); - reg = &timing_row[1]; + reg = &timing_row_reg_fields[1]; *reg_timing_row |= TIMING_VAL2REG(reg, val); val = dmc->timings->tRPab / clk_period_ps; val += dmc->timings->tRPab % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tRPab); - reg = &timing_row[2]; + reg = &timing_row_reg_fields[2]; *reg_timing_row |= TIMING_VAL2REG(reg, val); val = dmc->timings->tRCD / clk_period_ps; val += dmc->timings->tRCD % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tRCD); - reg = &timing_row[3]; + reg = &timing_row_reg_fields[3]; *reg_timing_row |= TIMING_VAL2REG(reg, val); val = dmc->timings->tRC / clk_period_ps; val += dmc->timings->tRC % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tRC); - reg = &timing_row[4]; + reg = &timing_row_reg_fields[4]; *reg_timing_row |= TIMING_VAL2REG(reg, val); val = dmc->timings->tRAS / clk_period_ps; val += dmc->timings->tRAS % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tRAS); - reg = &timing_row[5]; + reg = &timing_row_reg_fields[5]; *reg_timing_row |= TIMING_VAL2REG(reg, val); /* data related timings */ val = dmc->timings->tWTR / clk_period_ps; val += dmc->timings->tWTR % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tWTR); - reg = &timing_data[0]; + reg = &timing_data_reg_fields[0]; *reg_timing_data |= TIMING_VAL2REG(reg, val); val = dmc->timings->tWR / clk_period_ps; val += dmc->timings->tWR % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tWR); - reg = &timing_data[1]; + reg = &timing_data_reg_fields[1]; *reg_timing_data |= TIMING_VAL2REG(reg, val); val = dmc->timings->tRTP / clk_period_ps; val += dmc->timings->tRTP % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tRTP); - reg = &timing_data[2]; + reg = &timing_data_reg_fields[2]; *reg_timing_data |= TIMING_VAL2REG(reg, val); val = dmc->timings->tW2W_C2C / clk_period_ps; val += dmc->timings->tW2W_C2C % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tW2W_C2C); - reg = &timing_data[3]; + reg = &timing_data_reg_fields[3]; *reg_timing_data |= TIMING_VAL2REG(reg, val); val = dmc->timings->tR2R_C2C / clk_period_ps; val += dmc->timings->tR2R_C2C % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tR2R_C2C); - reg = &timing_data[4]; + reg = &timing_data_reg_fields[4]; *reg_timing_data |= TIMING_VAL2REG(reg, val); val = dmc->timings->tWL / clk_period_ps; val += dmc->timings->tWL % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tWL); - reg = &timing_data[5]; + reg = &timing_data_reg_fields[5]; *reg_timing_data |= TIMING_VAL2REG(reg, val); val = dmc->timings->tDQSCK / clk_period_ps; val += dmc->timings->tDQSCK % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tDQSCK); - reg = &timing_data[6]; + reg = &timing_data_reg_fields[6]; *reg_timing_data |= TIMING_VAL2REG(reg, val); val = dmc->timings->tRL / clk_period_ps; val += dmc->timings->tRL % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tRL); - reg = &timing_data[7]; + reg = &timing_data_reg_fields[7]; *reg_timing_data |= TIMING_VAL2REG(reg, val); /* power related timings */ val = dmc->timings->tFAW / clk_period_ps; val += dmc->timings->tFAW % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tFAW); - reg = &timing_power[0]; + reg = &timing_power_reg_fields[0]; *reg_timing_power |= TIMING_VAL2REG(reg, val); val = dmc->timings->tXSR / clk_period_ps; val += dmc->timings->tXSR % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tXSR); - reg = &timing_power[1]; + reg = &timing_power_reg_fields[1]; *reg_timing_power |= TIMING_VAL2REG(reg, val); val = dmc->timings->tXP / clk_period_ps; val += dmc->timings->tXP % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tXP); - reg = &timing_power[2]; + reg = &timing_power_reg_fields[2]; *reg_timing_power |= TIMING_VAL2REG(reg, val); val = dmc->timings->tCKE / clk_period_ps; val += dmc->timings->tCKE % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tCKE); - reg = &timing_power[3]; + reg = &timing_power_reg_fields[3]; *reg_timing_power |= TIMING_VAL2REG(reg, val); val = dmc->timings->tMRD / clk_period_ps; val += dmc->timings->tMRD % clk_period_ps ? 1 : 0; val = max(val, dmc->min_tck->tMRD); - reg = &timing_power[4]; + reg = &timing_power_reg_fields[4]; *reg_timing_power |= TIMING_VAL2REG(reg, val); return 0; From 1415fa0dca591b547465bd6bee9cd940920df6e9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 22 Aug 2020 18:32:17 +0200 Subject: [PATCH 038/131] memory: samsung: exynos5422-dmc: remove unused exynos5_dmc members The struct exynos5_dmc members bypass_rate, mx_mspll_ccore_phy, mout_mx_mspll_ccore_phy and opp_bypass are not actually used. Apparently there was a plan to store the OPP for the bypass mode in opp_bypass member, but driver fails to do it and instead always sets target voltage during bypass mode. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200822163218.21857-2-krzk@kernel.org --- drivers/memory/samsung/exynos5422-dmc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c index 31864ce59b25..df02afa8aa90 100644 --- a/drivers/memory/samsung/exynos5422-dmc.c +++ b/drivers/memory/samsung/exynos5422-dmc.c @@ -123,9 +123,7 @@ struct exynos5_dmc { struct mutex lock; unsigned long curr_rate; unsigned long curr_volt; - unsigned long bypass_rate; struct dmc_opp_table *opp; - struct dmc_opp_table opp_bypass; int opp_count; u32 timings_arr_size; u32 *timing_row; @@ -143,8 +141,6 @@ struct exynos5_dmc { struct clk *mout_bpll; struct clk *mout_mclk_cdrex; struct clk *mout_mx_mspll_ccore; - struct clk *mx_mspll_ccore_phy; - struct clk *mout_mx_mspll_ccore_phy; struct devfreq_event_dev **counter; int num_counters; u64 last_overflow_ts[2]; @@ -455,9 +451,6 @@ static int exynos5_dmc_align_bypass_voltage(struct exynos5_dmc *dmc, unsigned long target_volt) { int ret = 0; - unsigned long bypass_volt = dmc->opp_bypass.volt_uv; - - target_volt = max(bypass_volt, target_volt); if (dmc->curr_volt >= target_volt) return 0; @@ -1268,8 +1261,6 @@ static int exynos5_dmc_init_clks(struct exynos5_dmc *dmc) clk_set_parent(dmc->mout_mx_mspll_ccore, dmc->mout_spll); - dmc->bypass_rate = clk_get_rate(dmc->mout_mx_mspll_ccore); - clk_prepare_enable(dmc->fout_bpll); clk_prepare_enable(dmc->mout_bpll); From 4c2af5ddf84b45720102cd6348105a288417a214 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 22 Aug 2020 18:32:18 +0200 Subject: [PATCH 039/131] memory: samsung: exynos5422-dmc: add missing and fix kerneldoc Add missing kerneldoc to struct exynos5_dmc and correct the existing kerneldoc in other places to fix W=1 warnings like: drivers/memory/samsung/exynos5422-dmc.c:107: warning: Function parameter or member 'freq_hz' not described in 'dmc_opp_table' drivers/memory/samsung/exynos5422-dmc.c:154: warning: Function parameter or member 'dev' not described in 'exynos5_dmc' drivers/memory/samsung/exynos5422-dmc.c:357: warning: Excess function parameter 'param' description in 'exynos5_set_bypass_dram_timings' drivers/memory/samsung/exynos5422-dmc.c:630: warning: Function parameter or member 'flags' not described in 'exynos5_dmc_get_volt_freq' drivers/memory/samsung/exynos5422-dmc.c:962: warning: cannot understand function prototype: 'struct devfreq_dev_profile exynos5_dmc_df_profile = ' drivers/memory/samsung/exynos5422-dmc.c:1011: warning: Function parameter or member 'reg_timing_row' not described in 'create_timings_aligned' drivers/memory/samsung/exynos5422-dmc.c:1011: warning: Excess function parameter 'idx' description in 'create_timings_aligned' drivers/memory/samsung/exynos5422-dmc.c:1345: warning: Excess function parameter 'set' description in 'exynos5_dmc_set_pause_on_switching' Signed-off-by: Krzysztof Kozlowski Acked-by: Lukasz Luba Link: https://lore.kernel.org/r/20200822163218.21857-3-krzk@kernel.org --- drivers/memory/samsung/exynos5422-dmc.c | 46 ++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c index df02afa8aa90..4961a565c462 100644 --- a/drivers/memory/samsung/exynos5422-dmc.c +++ b/drivers/memory/samsung/exynos5422-dmc.c @@ -98,6 +98,8 @@ MODULE_PARM_DESC(irqmode, "Enable IRQ mode (0=off [default], 1=on)"); /** * struct dmc_opp_table - Operating level desciption + * @freq_hz: target frequency in Hz + * @volt_uv: target voltage in uV * * Covers frequency and voltage settings of the DMC operating mode. */ @@ -108,6 +110,41 @@ struct dmc_opp_table { /** * struct exynos5_dmc - main structure describing DMC device + * @dev: DMC device + * @df: devfreq device structure returned by devfreq framework + * @gov_data: configuration of devfreq governor + * @base_drexi0: DREX0 registers mapping + * @base_drexi1: DREX1 registers mapping + * @clk_regmap: regmap for clock controller registers + * @lock: protects curr_rate and frequency/voltage setting section + * @curr_rate: current frequency + * @curr_volt: current voltage + * @opp: OPP table + * @opp_count: number of 'opp' elements + * @timings_arr_size: number of 'timings' elements + * @timing_row: values for timing row register, for each OPP + * @timing_data: values for timing data register, for each OPP + * @timing_power: balues for timing power register, for each OPP + * @timings: DDR memory timings, from device tree + * @min_tck: DDR memory minimum timing values, from device tree + * @bypass_timing_row: value for timing row register for bypass timings + * @bypass_timing_data: value for timing data register for bypass timings + * @bypass_timing_power: value for timing power register for bypass + * timings + * @vdd_mif: Memory interface regulator + * @fout_spll: clock: SPLL + * @fout_bpll: clock: BPLL + * @mout_spll: clock: mux SPLL + * @mout_bpll: clock: mux BPLL + * @mout_mclk_cdrex: clock: mux mclk_cdrex + * @mout_mx_mspll_ccore: clock: mux mx_mspll_ccore + * @counter: devfreq events + * @num_counters: number of 'counter' elements + * @last_overflow_ts: time (in ns) of last overflow of each DREX + * @load: utilization in percents + * @total: total time between devfreq events + * @in_irq_mode: whether running in interrupt mode (true) + * or polling (false) * * The main structure for the Dynamic Memory Controller which covers clocks, * memory regions, HW information, parameters and current operating mode. @@ -344,7 +381,6 @@ static int exynos5_init_freq_table(struct exynos5_dmc *dmc, /** * exynos5_set_bypass_dram_timings() - Low-level changes of the DRAM timings * @dmc: device for which the new settings is going to be applied - * @param: DRAM parameters which passes timing data * * Low-level function for changing timings for DRAM memory clocking from * 'bypass' clock source (fixed frequency @400MHz). @@ -612,6 +648,7 @@ exynos5_dmc_change_freq_and_volt(struct exynos5_dmc *dmc, * requested * @target_volt: returned voltage which corresponds to the returned * frequency + * @flags: devfreq flags provided for this frequency change request * * Function gets requested frequency and checks OPP framework for needed * frequency and voltage. It populates the values 'target_rate' and @@ -948,7 +985,7 @@ static int exynos5_dmc_get_cur_freq(struct device *dev, unsigned long *freq) return 0; } -/** +/* * exynos5_dmc_df_profile - Devfreq governor's profile structure * * It provides to the devfreq framework needed functions and polling period. @@ -991,7 +1028,9 @@ exynos5_dmc_align_init_freq(struct exynos5_dmc *dmc, /** * create_timings_aligned() - Create register values and align with standard * @dmc: device for which the frequency is going to be set - * @idx: speed bin in the OPP table + * @reg_timing_row: array to fill with values for timing row register + * @reg_timing_data: array to fill with values for timing data register + * @reg_timing_power: array to fill with values for timing power register * @clk_period_ps: the period of the clock, known as tCK * * The function calculates timings and creates a register value ready for @@ -1326,7 +1365,6 @@ static int exynos5_performance_counters_init(struct exynos5_dmc *dmc) /** * exynos5_dmc_set_pause_on_switching() - Controls a pause feature in DMC * @dmc: device which is used for changing this feature - * @set: a boolean state passing enable/disable request * * There is a need of pausing DREX DMC when divider or MUX in clock tree * changes its configuration. In such situation access to the memory is blocked From 74ca0d837b99b0ca6e66861a64a6456beaa10298 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Aug 2020 17:37:46 +0200 Subject: [PATCH 040/131] memory: brcmstb_dpfe: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Acked-by: Florian Fainelli Acked-by: Markus Mayer Link: https://lore.kernel.org/r/20200828153747.22358-1-krzk@kernel.org --- drivers/memory/brcmstb_dpfe.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c index dcf50bb8dd69..f43ba69fbb3e 100644 --- a/drivers/memory/brcmstb_dpfe.c +++ b/drivers/memory/brcmstb_dpfe.c @@ -901,11 +901,8 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev) } ret = brcmstb_dpfe_download_firmware(priv); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Couldn't download firmware -- %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Couldn't download firmware\n"); ret = sysfs_create_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs); if (!ret) From 25f2f5e5910fa5e805cb1232237291f2ac4e9eb0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Aug 2020 17:37:47 +0200 Subject: [PATCH 041/131] memory: tegra186-emc: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200828153747.22358-2-krzk@kernel.org --- drivers/memory/tegra/tegra186-emc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c index 8478f59db432..fa8af17b0e2d 100644 --- a/drivers/memory/tegra/tegra186-emc.c +++ b/drivers/memory/tegra/tegra186-emc.c @@ -172,14 +172,8 @@ static int tegra186_emc_probe(struct platform_device *pdev) return -ENOMEM; emc->bpmp = tegra_bpmp_get(&pdev->dev); - if (IS_ERR(emc->bpmp)) { - err = PTR_ERR(emc->bpmp); - - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get BPMP: %d\n", err); - - return err; - } + if (IS_ERR(emc->bpmp)) + return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp), "failed to get BPMP\n"); emc->clk = devm_clk_get(&pdev->dev, "emc"); if (IS_ERR(emc->clk)) { From ea90f66f2a8629dde07328df0b8314aae5e54a47 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 1 Sep 2020 17:32:48 +0200 Subject: [PATCH 042/131] memory: tegra: Remove GPU from DRM IOMMU group Commit 63a613fdb16c ("memory: tegra: Add gr2d and gr3d to DRM IOMMU group") added the GPU to the DRM IOMMU group, which doesn't make any sense. This causes problems when Nouveau tries to attach to the SMMU and causes it to fall back to using the DMA API. Remove the GPU from the DRM groups to restore the old behaviour. The GPU should always have its own IOMMU domain to make sure it can map buffers into contiguous chunks (for big page support) without getting in the way of mappings from the DRM group. Cc: Fixes: 63a613fdb16c ("memory: tegra: Add gr2d and gr3d to DRM IOMMU group") Reported-by: Matias Zuniga Signed-off-by: Thierry Reding Reviewed-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20200901153248.1831263-1-thierry.reding@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra124.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 493b5dc3a4b3..0cede24479bf 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -957,7 +957,6 @@ static const struct tegra_smmu_swgroup tegra124_swgroups[] = { static const unsigned int tegra124_group_drm[] = { TEGRA_SWGROUP_DC, TEGRA_SWGROUP_DCB, - TEGRA_SWGROUP_GPU, TEGRA_SWGROUP_VIC, }; From 6cf238d4e21bc21bc18d126358dd617b2c991d66 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 1 Sep 2020 19:28:32 +0800 Subject: [PATCH 043/131] memory: omap-gpmc: Fix -Wunused-function warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_OF is not set, make W=1 warns: drivers/memory/omap-gpmc.c:987:12: warning: ‘gpmc_cs_remap’ defined but not used [-Wunused-function] drivers/memory/omap-gpmc.c:926:20: warning: ‘gpmc_cs_get_name’ defined but not used [-Wunused-function] drivers/memory/omap-gpmc.c:919:13: warning: ‘gpmc_cs_set_name’ defined but not used [-Wunused-function] Move them to #ifdef CONFIG_OF block to fix this. Signed-off-by: YueHaibing Acked-by: Roger Quadros Link: https://lore.kernel.org/r/20200901112832.3084-1-yuehaibing%40huawei.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/omap-gpmc.c | 114 ++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 8932c5b266e4..bd989b8614b2 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -917,20 +917,6 @@ static bool gpmc_cs_reserved(int cs) return gpmc->flags & GPMC_CS_RESERVED; } -static void gpmc_cs_set_name(int cs, const char *name) -{ - struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; - - gpmc->name = name; -} - -static const char *gpmc_cs_get_name(int cs) -{ - struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; - - return gpmc->name; -} - static unsigned long gpmc_mem_align(unsigned long size) { int order; @@ -976,49 +962,6 @@ static int gpmc_cs_delete_mem(int cs) return r; } -/** - * gpmc_cs_remap - remaps a chip-select physical base address - * @cs: chip-select to remap - * @base: physical base address to re-map chip-select to - * - * Re-maps a chip-select to a new physical base address specified by - * "base". Returns 0 on success and appropriate negative error code - * on failure. - */ -static int gpmc_cs_remap(int cs, u32 base) -{ - int ret; - u32 old_base, size; - - if (cs >= gpmc_cs_num) { - pr_err("%s: requested chip-select is disabled\n", __func__); - return -ENODEV; - } - - /* - * Make sure we ignore any device offsets from the GPMC partition - * allocated for the chip select and that the new base confirms - * to the GPMC 16MB minimum granularity. - */ - base &= ~(SZ_16M - 1); - - gpmc_cs_get_memconf(cs, &old_base, &size); - if (base == old_base) - return 0; - - ret = gpmc_cs_delete_mem(cs); - if (ret < 0) - return ret; - - ret = gpmc_cs_insert_mem(cs, base, size); - if (ret < 0) - return ret; - - ret = gpmc_cs_set_memconf(cs, base, size); - - return ret; -} - int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) { struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; @@ -1942,6 +1885,63 @@ static const struct of_device_id gpmc_dt_ids[] = { { } }; +static void gpmc_cs_set_name(int cs, const char *name) +{ + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + + gpmc->name = name; +} + +static const char *gpmc_cs_get_name(int cs) +{ + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + + return gpmc->name; +} + +/** + * gpmc_cs_remap - remaps a chip-select physical base address + * @cs: chip-select to remap + * @base: physical base address to re-map chip-select to + * + * Re-maps a chip-select to a new physical base address specified by + * "base". Returns 0 on success and appropriate negative error code + * on failure. + */ +static int gpmc_cs_remap(int cs, u32 base) +{ + int ret; + u32 old_base, size; + + if (cs >= gpmc_cs_num) { + pr_err("%s: requested chip-select is disabled\n", __func__); + return -ENODEV; + } + + /* + * Make sure we ignore any device offsets from the GPMC partition + * allocated for the chip select and that the new base confirms + * to the GPMC 16MB minimum granularity. + */ + base &= ~(SZ_16M - 1); + + gpmc_cs_get_memconf(cs, &old_base, &size); + if (base == old_base) + return 0; + + ret = gpmc_cs_delete_mem(cs); + if (ret < 0) + return ret; + + ret = gpmc_cs_insert_mem(cs, base, size); + if (ret < 0) + return ret; + + ret = gpmc_cs_set_memconf(cs, base, size); + + return ret; +} + /** * gpmc_read_settings_dt - read gpmc settings from device-tree * @np: pointer to device-tree node for a gpmc child device From dd85345abca60a8916617e8d75c0f9ce334336dd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 27 Aug 2020 09:33:15 +0200 Subject: [PATCH 044/131] memory: fsl-corenet-cf: Fix handling of platform_get_irq() error platform_get_irq() returns -ERRNO on error. In such case comparison to 0 would pass the check. Fixes: 54afbec0d57f ("memory: Freescale CoreNet Coherency Fabric error reporting driver") Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200827073315.29351-1-krzk@kernel.org --- drivers/memory/fsl-corenet-cf.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/memory/fsl-corenet-cf.c b/drivers/memory/fsl-corenet-cf.c index 0b0ed72016da..0309bd5a1800 100644 --- a/drivers/memory/fsl-corenet-cf.c +++ b/drivers/memory/fsl-corenet-cf.c @@ -211,10 +211,8 @@ static int ccf_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, ccf); irq = platform_get_irq(pdev, 0); - if (!irq) { - dev_err(&pdev->dev, "%s: no irq\n", __func__); - return -ENXIO; - } + if (irq < 0) + return irq; ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf); if (ret) { From 5dfd145aada85d37638e820775e457a78d70a7e0 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Feb 2020 16:14:11 -0800 Subject: [PATCH 045/131] soc: bcm: brcmstb: biuctrl: Tune MCP settings for 72164 72164 uses a Brahma-B53 CPU and its Bus Interface Unit, tune it according to the existing values we have. Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/biuctrl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c index 95602ece51d4..a4b01894a9ad 100644 --- a/drivers/soc/bcm/brcmstb/biuctrl.c +++ b/drivers/soc/bcm/brcmstb/biuctrl.c @@ -130,6 +130,7 @@ static int __init mcp_write_pairing_set(void) static const u32 a72_b53_mach_compat[] = { 0x7211, 0x7216, + 0x72164, 0x7255, 0x7260, 0x7268, From 4029f3b419dad519fcb0b7233cc24ae242d33651 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 28 Feb 2020 11:32:26 -0800 Subject: [PATCH 046/131] soc: bcm: brcmstb: biuctrl: Tune MCP settings for 72165 72165 uses a Brahma-B53 CPU and its Bus Interface Unit, tune it according to the existing values we have. Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/biuctrl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c index a4b01894a9ad..d448a89ceb27 100644 --- a/drivers/soc/bcm/brcmstb/biuctrl.c +++ b/drivers/soc/bcm/brcmstb/biuctrl.c @@ -131,6 +131,7 @@ static const u32 a72_b53_mach_compat[] = { 0x7211, 0x7216, 0x72164, + 0x72165, 0x7255, 0x7260, 0x7268, From 091353c88b3b4358aa5a0ec07bf53a2f2ac77206 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 25 Oct 2019 11:18:06 -0700 Subject: [PATCH 047/131] soc: bcm: brcmstb: biuctrl: Change RAC prefetch distance from +/-1 to +/- 2 Change the RAC prefetch distance from +/- 1 to +/- 2 for Cortex-A72 CPUs since this provides an average of a 3.8% performance increase for synthetic memcpy benchmarks. Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/biuctrl.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c index d448a89ceb27..28f69cc0df51 100644 --- a/drivers/soc/bcm/brcmstb/biuctrl.c +++ b/drivers/soc/bcm/brcmstb/biuctrl.c @@ -20,6 +20,8 @@ #define RACENDATA_SHIFT 6 #define RAC_CPU_SHIFT 8 #define RACCFG_MASK 0xff +#define DPREF_LINE_2_SHIFT 24 +#define DPREF_LINE_2_MASK 0xff /* Bitmask to enable instruction and data prefetching with a 256-bytes stride */ #define RAC_DATA_INST_EN_MASK (1 << RACPREFINST_SHIFT | \ @@ -50,6 +52,7 @@ enum cpubiuctrl_regs { CPU_MCP_FLOW_REG, CPU_WRITEBACK_CTRL_REG, RAC_CONFIG0_REG, + RAC_CONFIG1_REG, NUM_CPU_BIUCTRL_REGS, }; @@ -58,7 +61,7 @@ static inline u32 cbc_readl(int reg) int offset = cpubiuctrl_regs[reg]; if (offset == -1 || - (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg == RAC_CONFIG0_REG)) + (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg >= RAC_CONFIG0_REG)) return (u32)-1; return readl_relaxed(cpubiuctrl_base + offset); @@ -69,7 +72,7 @@ static inline void cbc_writel(u32 val, int reg) int offset = cpubiuctrl_regs[reg]; if (offset == -1 || - (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg == RAC_CONFIG0_REG)) + (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg >= RAC_CONFIG0_REG)) return; writel(val, cpubiuctrl_base + offset); @@ -80,6 +83,7 @@ static const int b15_cpubiuctrl_regs[] = { [CPU_MCP_FLOW_REG] = -1, [CPU_WRITEBACK_CTRL_REG] = -1, [RAC_CONFIG0_REG] = -1, + [RAC_CONFIG1_REG] = -1, }; /* Odd cases, e.g: 7260A0 */ @@ -88,6 +92,7 @@ static const int b53_cpubiuctrl_no_wb_regs[] = { [CPU_MCP_FLOW_REG] = 0x0b4, [CPU_WRITEBACK_CTRL_REG] = -1, [RAC_CONFIG0_REG] = 0x78, + [RAC_CONFIG1_REG] = 0x7c, }; static const int b53_cpubiuctrl_regs[] = { @@ -95,6 +100,7 @@ static const int b53_cpubiuctrl_regs[] = { [CPU_MCP_FLOW_REG] = 0x0b4, [CPU_WRITEBACK_CTRL_REG] = 0x22c, [RAC_CONFIG0_REG] = 0x78, + [RAC_CONFIG1_REG] = 0x7c, }; static const int a72_cpubiuctrl_regs[] = { @@ -102,6 +108,7 @@ static const int a72_cpubiuctrl_regs[] = { [CPU_MCP_FLOW_REG] = 0x1c, [CPU_WRITEBACK_CTRL_REG] = 0x20, [RAC_CONFIG0_REG] = 0x08, + [RAC_CONFIG1_REG] = 0x0c, }; static int __init mcp_write_pairing_set(void) @@ -167,7 +174,7 @@ static const u32 a72_b53_mach_compat[] = { static void __init a72_b53_rac_enable_all(struct device_node *np) { unsigned int cpu; - u32 enable = 0; + u32 enable = 0, pref_dist; if (IS_ENABLED(CONFIG_CACHE_B15_RAC)) return; @@ -175,10 +182,15 @@ static void __init a72_b53_rac_enable_all(struct device_node *np) if (WARN(num_possible_cpus() > 4, "RAC only supports 4 CPUs\n")) return; - for_each_possible_cpu(cpu) + pref_dist = cbc_readl(RAC_CONFIG1_REG); + for_each_possible_cpu(cpu) { enable |= RAC_DATA_INST_EN_MASK << (cpu * RAC_CPU_SHIFT); + if (cpubiuctrl_regs == a72_cpubiuctrl_regs) + pref_dist |= 1 << (cpu + DPREF_LINE_2_SHIFT); + } cbc_writel(enable, RAC_CONFIG0_REG); + cbc_writel(pref_dist, RAC_CONFIG1_REG); pr_info("%pOF: Broadcom %s read-ahead cache\n", np, cpubiuctrl_regs == a72_cpubiuctrl_regs ? From 10e7dd54cdaa00be8deb11a8cdb90faa804bdb19 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 25 Oct 2019 11:34:58 -0700 Subject: [PATCH 048/131] soc: bcm: brcmstb: biuctrl: Change RAC data line prefetching after 4 consecutive lines Change the RACPREFDATA(x) setting to prefetch the next 256-byte line after 4 consecutive lines have been used, instead of after 2 consecutive lines. This does improve the synthetic memcpy benchmark by an additional +0.5% on top of the previous change for Cortex-A72 CPUs. Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/biuctrl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c index 28f69cc0df51..7f8dc302ae6e 100644 --- a/drivers/soc/bcm/brcmstb/biuctrl.c +++ b/drivers/soc/bcm/brcmstb/biuctrl.c @@ -174,7 +174,7 @@ static const u32 a72_b53_mach_compat[] = { static void __init a72_b53_rac_enable_all(struct device_node *np) { unsigned int cpu; - u32 enable = 0, pref_dist; + u32 enable = 0, pref_dist, shift; if (IS_ENABLED(CONFIG_CACHE_B15_RAC)) return; @@ -184,9 +184,13 @@ static void __init a72_b53_rac_enable_all(struct device_node *np) pref_dist = cbc_readl(RAC_CONFIG1_REG); for_each_possible_cpu(cpu) { + shift = cpu * RAC_CPU_SHIFT + RACPREFDATA_SHIFT; enable |= RAC_DATA_INST_EN_MASK << (cpu * RAC_CPU_SHIFT); - if (cpubiuctrl_regs == a72_cpubiuctrl_regs) + if (cpubiuctrl_regs == a72_cpubiuctrl_regs) { + enable &= ~(RACENPREF_MASK << shift); + enable |= 3 << shift; pref_dist |= 1 << (cpu + DPREF_LINE_2_SHIFT); + } } cbc_writel(enable, RAC_CONFIG0_REG); From 541b6e6ee7a475538c5d6b0b6ad74752d10e3064 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 17 Apr 2020 17:11:46 -0700 Subject: [PATCH 049/131] dt-bindings: bus: Document breakpoint interrupt for gisb-arb The GISB arbiter can have a third and optional interrupt to handle GISB breakpoints. Signed-off-by: Florian Fainelli --- Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt b/Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt index 729def62f0c5..10f6d0a8159d 100644 --- a/Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt +++ b/Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt @@ -10,7 +10,8 @@ Required properties: "brcm,bcm7038-gisb-arb" for 130nm chips - reg: specifies the base physical address and size of the registers - interrupts: specifies the two interrupts (timeout and TEA) to be used from - the parent interrupt controller + the parent interrupt controller. A third optional interrupt may be specified + for breakpoints. Optional properties: From fb8a0b80c4bb4d474218d515cca0ec9b9028c6b4 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 17 Apr 2020 17:21:32 -0700 Subject: [PATCH 050/131] bus: brcmstb_gisb: Add support for breakpoint interrupts GISB breakpoint interrupts can be raised when a breakpoint has been enabled to match a specific master and/or GISB register address. Being able to print a message, similar to those done during target abort or timeout greatly helps debug systems. Signed-off-by: Florian Fainelli --- drivers/bus/brcmstb_gisb.c | 96 +++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index 7579439971e3..7355fa2cb439 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -30,8 +30,22 @@ #define ARB_ERR_CAP_STATUS_WRITE (1 << 1) #define ARB_ERR_CAP_STATUS_VALID (1 << 0) +#define ARB_BP_CAP_CLEAR (1 << 0) +#define ARB_BP_CAP_STATUS_PROT_SHIFT 14 +#define ARB_BP_CAP_STATUS_TYPE (1 << 13) +#define ARB_BP_CAP_STATUS_RSP_SHIFT 10 +#define ARB_BP_CAP_STATUS_MASK GENMASK(1, 0) +#define ARB_BP_CAP_STATUS_BS_SHIFT 2 +#define ARB_BP_CAP_STATUS_WRITE (1 << 1) +#define ARB_BP_CAP_STATUS_VALID (1 << 0) + enum { ARB_TIMER, + ARB_BP_CAP_CLR, + ARB_BP_CAP_HI_ADDR, + ARB_BP_CAP_ADDR, + ARB_BP_CAP_STATUS, + ARB_BP_CAP_MASTER, ARB_ERR_CAP_CLR, ARB_ERR_CAP_HI_ADDR, ARB_ERR_CAP_ADDR, @@ -41,6 +55,11 @@ enum { static const int gisb_offsets_bcm7038[] = { [ARB_TIMER] = 0x00c, + [ARB_BP_CAP_CLR] = 0x014, + [ARB_BP_CAP_HI_ADDR] = -1, + [ARB_BP_CAP_ADDR] = 0x0b8, + [ARB_BP_CAP_STATUS] = 0x0c0, + [ARB_BP_CAP_MASTER] = -1, [ARB_ERR_CAP_CLR] = 0x0c4, [ARB_ERR_CAP_HI_ADDR] = -1, [ARB_ERR_CAP_ADDR] = 0x0c8, @@ -50,6 +69,11 @@ static const int gisb_offsets_bcm7038[] = { static const int gisb_offsets_bcm7278[] = { [ARB_TIMER] = 0x008, + [ARB_BP_CAP_CLR] = 0x01c, + [ARB_BP_CAP_HI_ADDR] = -1, + [ARB_BP_CAP_ADDR] = 0x220, + [ARB_BP_CAP_STATUS] = 0x230, + [ARB_BP_CAP_MASTER] = 0x234, [ARB_ERR_CAP_CLR] = 0x7f8, [ARB_ERR_CAP_HI_ADDR] = -1, [ARB_ERR_CAP_ADDR] = 0x7e0, @@ -59,6 +83,11 @@ static const int gisb_offsets_bcm7278[] = { static const int gisb_offsets_bcm7400[] = { [ARB_TIMER] = 0x00c, + [ARB_BP_CAP_CLR] = 0x014, + [ARB_BP_CAP_HI_ADDR] = -1, + [ARB_BP_CAP_ADDR] = 0x0b8, + [ARB_BP_CAP_STATUS] = 0x0c0, + [ARB_BP_CAP_MASTER] = 0x0c4, [ARB_ERR_CAP_CLR] = 0x0c8, [ARB_ERR_CAP_HI_ADDR] = -1, [ARB_ERR_CAP_ADDR] = 0x0cc, @@ -68,6 +97,11 @@ static const int gisb_offsets_bcm7400[] = { static const int gisb_offsets_bcm7435[] = { [ARB_TIMER] = 0x00c, + [ARB_BP_CAP_CLR] = 0x014, + [ARB_BP_CAP_HI_ADDR] = -1, + [ARB_BP_CAP_ADDR] = 0x158, + [ARB_BP_CAP_STATUS] = 0x160, + [ARB_BP_CAP_MASTER] = 0x164, [ARB_ERR_CAP_CLR] = 0x168, [ARB_ERR_CAP_HI_ADDR] = -1, [ARB_ERR_CAP_ADDR] = 0x16c, @@ -77,6 +111,11 @@ static const int gisb_offsets_bcm7435[] = { static const int gisb_offsets_bcm7445[] = { [ARB_TIMER] = 0x008, + [ARB_BP_CAP_CLR] = 0x010, + [ARB_BP_CAP_HI_ADDR] = -1, + [ARB_BP_CAP_ADDR] = 0x1d8, + [ARB_BP_CAP_STATUS] = 0x1e0, + [ARB_BP_CAP_MASTER] = 0x1e4, [ARB_ERR_CAP_CLR] = 0x7e4, [ARB_ERR_CAP_HI_ADDR] = 0x7e8, [ARB_ERR_CAP_ADDR] = 0x7ec, @@ -125,6 +164,16 @@ static u64 gisb_read_address(struct brcmstb_gisb_arb_device *gdev) return value; } +static u64 gisb_read_bp_address(struct brcmstb_gisb_arb_device *gdev) +{ + u64 value; + + value = gisb_read(gdev, ARB_BP_CAP_ADDR); + value |= (u64)gisb_read(gdev, ARB_BP_CAP_HI_ADDR) << 32; + + return value; +} + static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg) { int offset = gdev->gisb_offsets[reg]; @@ -259,6 +308,41 @@ static irqreturn_t brcmstb_gisb_tea_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t brcmstb_gisb_bp_handler(int irq, void *dev_id) +{ + struct brcmstb_gisb_arb_device *gdev = dev_id; + const char *m_name; + u32 bp_status; + u64 arb_addr; + u32 master; + char m_fmt[11]; + + bp_status = gisb_read(gdev, ARB_BP_CAP_STATUS); + + /* Invalid captured address, bail out */ + if (!(bp_status & ARB_BP_CAP_STATUS_VALID)) + return IRQ_HANDLED; + + /* Read the address and master */ + arb_addr = gisb_read_bp_address(gdev); + master = gisb_read(gdev, ARB_BP_CAP_MASTER); + + m_name = brcmstb_gisb_master_to_str(gdev, master); + if (!m_name) { + snprintf(m_fmt, sizeof(m_fmt), "0x%08x", master); + m_name = m_fmt; + } + + pr_crit("GISB: breakpoint at 0x%llx [%c], core: %s\n", + arb_addr, bp_status & ARB_BP_CAP_STATUS_WRITE ? 'W' : 'R', + m_name); + + /* clear the GISB error */ + gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR); + + return IRQ_HANDLED; +} + /* * Dump out gisb errors on die or panic. */ @@ -317,13 +401,14 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev) struct brcmstb_gisb_arb_device *gdev; const struct of_device_id *of_id; struct resource *r; - int err, timeout_irq, tea_irq; + int err, timeout_irq, tea_irq, bp_irq; unsigned int num_masters, j = 0; int i, first, last; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); timeout_irq = platform_get_irq(pdev, 0); tea_irq = platform_get_irq(pdev, 1); + bp_irq = platform_get_irq(pdev, 2); gdev = devm_kzalloc(&pdev->dev, sizeof(*gdev), GFP_KERNEL); if (!gdev) @@ -356,6 +441,15 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev) if (err < 0) return err; + /* Interrupt is optional */ + if (bp_irq > 0) { + err = devm_request_irq(&pdev->dev, bp_irq, + brcmstb_gisb_bp_handler, 0, pdev->name, + gdev); + if (err < 0) + return err; + } + /* If we do not have a valid mask, assume all masters are enabled */ if (of_property_read_u32(dn, "brcm,gisb-arb-master-mask", &gdev->valid_mask)) From 69ecb3230b007384726d36499f4bdea98109d3d7 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Mon, 7 Sep 2020 01:04:50 +0200 Subject: [PATCH 051/131] cpufreq: arm_scmi: Constify scmi_perf_ops pointers The perf_ops are not modified through this pointer. Make them const to indicate that. This is in preparation to make the scmi-ops pointers in scmi_handle const. Link: https://lore.kernel.org/r/20200906230452.33410-2-rikard.falkeborn@gmail.com Acked-by: Viresh Kumar Signed-off-by: Rikard Falkeborn Signed-off-by: Sudeep Holla --- drivers/cpufreq/scmi-cpufreq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index fb42e3390377..46b268095421 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c @@ -29,7 +29,7 @@ static const struct scmi_handle *handle; static unsigned int scmi_cpufreq_get_rate(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); - struct scmi_perf_ops *perf_ops = handle->perf_ops; + const struct scmi_perf_ops *perf_ops = handle->perf_ops; struct scmi_data *priv = policy->driver_data; unsigned long rate; int ret; @@ -50,7 +50,7 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { int ret; struct scmi_data *priv = policy->driver_data; - struct scmi_perf_ops *perf_ops = handle->perf_ops; + const struct scmi_perf_ops *perf_ops = handle->perf_ops; u64 freq = policy->freq_table[index].frequency; ret = perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false); @@ -64,7 +64,7 @@ static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy, unsigned int target_freq) { struct scmi_data *priv = policy->driver_data; - struct scmi_perf_ops *perf_ops = handle->perf_ops; + const struct scmi_perf_ops *perf_ops = handle->perf_ops; if (!perf_ops->freq_set(handle, priv->domain_id, target_freq * 1000, true)) { From 82894c1d397f16c2208a35dbb1310559f31980bb Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Mon, 7 Sep 2020 01:04:51 +0200 Subject: [PATCH 052/131] firmware: arm_scmi: Constify ops pointers in scmi_handle These are never modified, so make them const to allow drivers to make them const. Link: https://lore.kernel.org/r/20200906230452.33410-3-rikard.falkeborn@gmail.com Signed-off-by: Rikard Falkeborn Signed-off-by: Sudeep Holla --- include/linux/scmi_protocol.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 7e5dd7d1e221..05570afc7f74 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -279,12 +279,12 @@ struct scmi_notify_ops { struct scmi_handle { struct device *dev; struct scmi_revision_info *version; - struct scmi_perf_ops *perf_ops; - struct scmi_clk_ops *clk_ops; - struct scmi_power_ops *power_ops; - struct scmi_sensor_ops *sensor_ops; - struct scmi_reset_ops *reset_ops; - struct scmi_notify_ops *notify_ops; + const struct scmi_perf_ops *perf_ops; + const struct scmi_clk_ops *clk_ops; + const struct scmi_power_ops *power_ops; + const struct scmi_sensor_ops *sensor_ops; + const struct scmi_reset_ops *reset_ops; + const struct scmi_notify_ops *notify_ops; /* for protocol internal use */ void *perf_priv; void *clk_priv; From 3de7b83017bd93d521dc29f475f4c8fc5d61e518 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Mon, 7 Sep 2020 01:04:52 +0200 Subject: [PATCH 053/131] firmware: arm_scmi: Constify static scmi-ops These are never modified, so make them const to allow the compiler to put them in read-only memory. Link: https://lore.kernel.org/r/20200906230452.33410-4-rikard.falkeborn@gmail.com Signed-off-by: Rikard Falkeborn Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/clock.c | 2 +- drivers/firmware/arm_scmi/common.h | 2 +- drivers/firmware/arm_scmi/mailbox.c | 2 +- drivers/firmware/arm_scmi/notify.c | 2 +- drivers/firmware/arm_scmi/perf.c | 2 +- drivers/firmware/arm_scmi/power.c | 2 +- drivers/firmware/arm_scmi/reset.c | 2 +- drivers/firmware/arm_scmi/sensors.c | 2 +- drivers/firmware/arm_scmi/smc.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 75e39882746e..a3b90be28009 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -318,7 +318,7 @@ scmi_clock_info_get(const struct scmi_handle *handle, u32 clk_id) return clk; } -static struct scmi_clk_ops clk_ops = { +static const struct scmi_clk_ops clk_ops = { .count_get = scmi_clock_count_get, .info_get = scmi_clock_info_get, .rate_get = scmi_clock_rate_get, diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index c113e578cc6c..233700a42bff 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -210,7 +210,7 @@ struct scmi_transport_ops { * @max_msg_size: Maximum size of data per message that can be handled. */ struct scmi_desc { - struct scmi_transport_ops *ops; + const struct scmi_transport_ops *ops; int max_rx_timeout_ms; int max_msg; int max_msg_size; diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index 6998dc86b5ce..cc2de207fe10 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -181,7 +181,7 @@ mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) return shmem_poll_done(smbox->shmem, xfer); } -static struct scmi_transport_ops scmi_mailbox_ops = { +static const struct scmi_transport_ops scmi_mailbox_ops = { .chan_available = mailbox_chan_available, .chan_setup = mailbox_chan_setup, .chan_free = mailbox_chan_free, diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index 4731daaacd19..2754f9d01636 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -1421,7 +1421,7 @@ static void scmi_protocols_late_init(struct work_struct *work) * notify_ops are attached to the handle so that can be accessed * directly from an scmi_driver to register its own notifiers. */ -static struct scmi_notify_ops notify_ops = { +static const struct scmi_notify_ops notify_ops = { .register_event_notifier = scmi_register_notifier, .unregister_event_notifier = scmi_unregister_notifier, }; diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 3e1e87012c95..a3e7b1bfab00 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -748,7 +748,7 @@ static bool scmi_fast_switch_possible(const struct scmi_handle *handle, return dom->fc_info && dom->fc_info->level_set_addr; } -static struct scmi_perf_ops perf_ops = { +static const struct scmi_perf_ops perf_ops = { .limits_set = scmi_perf_limits_set, .limits_get = scmi_perf_limits_get, .level_set = scmi_perf_level_set, diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 46f213644c49..32bcf5821ea9 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -184,7 +184,7 @@ static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain) return dom->name; } -static struct scmi_power_ops power_ops = { +static const struct scmi_power_ops power_ops = { .num_domains_get = scmi_power_num_domains_get, .name_get = scmi_power_name_get, .state_set = scmi_power_state_set, diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index 3691bafca057..4e2dc5fc43d9 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -194,7 +194,7 @@ scmi_reset_domain_deassert(const struct scmi_handle *handle, u32 domain) return scmi_domain_reset(handle, domain, 0, ARCH_COLD_RESET); } -static struct scmi_reset_ops reset_ops = { +static const struct scmi_reset_ops reset_ops = { .num_domains_get = scmi_reset_num_domains_get, .name_get = scmi_reset_name_get, .latency_get = scmi_reset_latency_get, diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 1af0ad362e82..7d83680198de 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -275,7 +275,7 @@ static int scmi_sensor_count_get(const struct scmi_handle *handle) return si->num_sensors; } -static struct scmi_sensor_ops sensor_ops = { +static const struct scmi_sensor_ops sensor_ops = { .count_get = scmi_sensor_count_get, .info_get = scmi_sensor_info_get, .trip_point_config = scmi_sensor_trip_point_config, diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c index a1537d123e38..1a03c3ec0230 100644 --- a/drivers/firmware/arm_scmi/smc.c +++ b/drivers/firmware/arm_scmi/smc.c @@ -137,7 +137,7 @@ smc_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) return shmem_poll_done(scmi_info->shmem, xfer); } -static struct scmi_transport_ops scmi_smc_ops = { +static const struct scmi_transport_ops scmi_smc_ops = { .chan_available = smc_chan_available, .chan_setup = smc_chan_setup, .chan_free = smc_chan_free, From a8803055127afb87640974adedac60435592b86d Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 7 Sep 2020 18:46:55 +0100 Subject: [PATCH 054/131] firmware: arm_scmi: Add system power protocol support Add bare protocol support for SCMI system power protocol as needed by an OSPM agent: basic initialization and SYSTEM_POWER_STATE_NOTIFIER core notification support. No event-handling logic is attached to such notification.. Link: https://lore.kernel.org/r/20200907174657.32466-2-cristian.marussi@arm.com Signed-off-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/Makefile | 2 +- drivers/firmware/arm_scmi/system.c | 136 +++++++++++++++++++++++++++++ include/linux/scmi_protocol.h | 18 ++++ 3 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/system.c diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 6f9cbc4aef22..643f2320f976 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -5,5 +5,5 @@ scmi-driver-y = driver.o notify.o scmi-transport-y = shmem.o scmi-transport-$(CONFIG_MAILBOX) += mailbox.o scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o -scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o +scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c new file mode 100644 index 000000000000..aa1e74f066a0 --- /dev/null +++ b/drivers/firmware/arm_scmi/system.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Management Interface (SCMI) System Power Protocol + * + * Copyright (C) 2020 ARM Ltd. + */ + +#define pr_fmt(fmt) "SCMI Notifications SYSTEM - " fmt + +#include + +#include "common.h" +#include "notify.h" + +#define SCMI_SYSTEM_NUM_SOURCES 1 + +enum scmi_system_protocol_cmd { + SYSTEM_POWER_STATE_NOTIFY = 0x5, +}; + +struct scmi_system_power_state_notify { + __le32 notify_enable; +}; + +struct scmi_system_power_state_notifier_payld { + __le32 agent_id; + __le32 flags; + __le32 system_state; +}; + +struct scmi_system_info { + u32 version; +}; + +static int scmi_system_request_notify(const struct scmi_handle *handle, + bool enable) +{ + int ret; + struct scmi_xfer *t; + struct scmi_system_power_state_notify *notify; + + ret = scmi_xfer_get_init(handle, SYSTEM_POWER_STATE_NOTIFY, + SCMI_PROTOCOL_SYSTEM, sizeof(*notify), 0, &t); + if (ret) + return ret; + + notify = t->tx.buf; + notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; + + ret = scmi_do_xfer(handle, t); + + scmi_xfer_put(handle, t); + return ret; +} + +static int scmi_system_set_notify_enabled(const struct scmi_handle *handle, + u8 evt_id, u32 src_id, bool enable) +{ + int ret; + + ret = scmi_system_request_notify(handle, enable); + if (ret) + pr_debug("FAIL_ENABLE - evt[%X] - ret:%d\n", evt_id, ret); + + return ret; +} + +static void *scmi_system_fill_custom_report(const struct scmi_handle *handle, + u8 evt_id, ktime_t timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + const struct scmi_system_power_state_notifier_payld *p = payld; + struct scmi_system_power_state_notifier_report *r = report; + + if (evt_id != SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER || + sizeof(*p) != payld_sz) + return NULL; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->flags = le32_to_cpu(p->flags); + r->system_state = le32_to_cpu(p->system_state); + *src_id = 0; + + return r; +} + +static const struct scmi_event system_events[] = { + { + .id = SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER, + .max_payld_sz = + sizeof(struct scmi_system_power_state_notifier_payld), + .max_report_sz = + sizeof(struct scmi_system_power_state_notifier_report), + }, +}; + +static const struct scmi_event_ops system_event_ops = { + .set_notify_enabled = scmi_system_set_notify_enabled, + .fill_custom_report = scmi_system_fill_custom_report, +}; + +static int scmi_system_protocol_init(struct scmi_handle *handle) +{ + u32 version; + struct scmi_system_info *pinfo; + + scmi_version_get(handle, SCMI_PROTOCOL_SYSTEM, &version); + + dev_dbg(handle->dev, "System Power Version %d.%d\n", + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); + + pinfo = devm_kzalloc(handle->dev, sizeof(*pinfo), GFP_KERNEL); + if (!pinfo) + return -ENOMEM; + + scmi_register_protocol_events(handle, + SCMI_PROTOCOL_SYSTEM, SCMI_PROTO_QUEUE_SZ, + &system_event_ops, + system_events, + ARRAY_SIZE(system_events), + SCMI_SYSTEM_NUM_SOURCES); + + pinfo->version = version; + handle->system_priv = pinfo; + + return 0; +} + +static int __init scmi_system_init(void) +{ + return scmi_protocol_register(SCMI_PROTOCOL_SYSTEM, + &scmi_system_protocol_init); +} +subsys_initcall(scmi_system_init); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 05570afc7f74..4b10093ad671 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -292,6 +292,7 @@ struct scmi_handle { void *sensor_priv; void *reset_priv; void *notify_priv; + void *system_priv; }; enum scmi_std_protocol { @@ -304,6 +305,15 @@ enum scmi_std_protocol { SCMI_PROTOCOL_RESET = 0x16, }; +enum scmi_system_events { + SCMI_SYSTEM_SHUTDOWN, + SCMI_SYSTEM_COLDRESET, + SCMI_SYSTEM_WARMRESET, + SCMI_SYSTEM_POWERUP, + SCMI_SYSTEM_SUSPEND, + SCMI_SYSTEM_MAX +}; + struct scmi_device { u32 id; u8 protocol_id; @@ -378,6 +388,7 @@ enum scmi_notification_events { SCMI_EVENT_SENSOR_TRIP_POINT_EVENT = 0x0, SCMI_EVENT_RESET_ISSUED = 0x0, SCMI_EVENT_BASE_ERROR_EVENT = 0x0, + SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER = 0x0, }; struct scmi_power_state_changed_report { @@ -387,6 +398,13 @@ struct scmi_power_state_changed_report { unsigned int power_state; }; +struct scmi_system_power_state_notifier_report { + ktime_t timestamp; + unsigned int agent_id; + unsigned int flags; + unsigned int system_state; +}; + struct scmi_perf_limits_report { ktime_t timestamp; unsigned int agent_id; From 481f6ccf399b4e3c8ff6d2cc2b7b1a384d86b2ad Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 7 Sep 2020 18:46:56 +0100 Subject: [PATCH 055/131] firmware: arm_scmi: Add SCMI device for system power protocol Add SCMI device for system power protocol by just adding the name "syspower" to the list of supported core protocol devices. Link: https://lore.kernel.org/r/20200907174657.32466-3-cristian.marussi@arm.com Signed-off-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 03ec74242c14..dbec34423f72 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -730,6 +730,7 @@ struct scmi_prot_devnames { static struct scmi_prot_devnames devnames[] = { { SCMI_PROTOCOL_POWER, { "genpd" },}, + { SCMI_PROTOCOL_SYSTEM, { "syspower" },}, { SCMI_PROTOCOL_PERF, { "cpufreq" },}, { SCMI_PROTOCOL_CLOCK, { "clocks" },}, { SCMI_PROTOCOL_SENSOR, { "hwmon" },}, From 8014c4781b4661370ec8bbd345c3a32565a80bba Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 3 Sep 2020 10:15:42 +0800 Subject: [PATCH 056/131] memory: tegra: Delete duplicated argument to '|' in function tegra210_emc_r21021_periodic_compensation In function tegra210_emc_r21021_periodic_compensation when calculate emc_cfg EMC_CFG_DRAM_CLKSTOP_PD is duplicated. Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20200903021542.315195-1-yebin10@huawei.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra210-emc-cc-r21021.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c index d60bdea3af3f..0ebfa8eccf0c 100644 --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c @@ -501,7 +501,6 @@ static u32 tegra210_emc_r21021_periodic_compensation(struct tegra210_emc *emc) emc_cfg_o = emc_readl(emc, EMC_CFG); emc_cfg = emc_cfg_o & ~(EMC_CFG_DYN_SELF_REF | EMC_CFG_DRAM_ACPD | - EMC_CFG_DRAM_CLKSTOP_PD | EMC_CFG_DRAM_CLKSTOP_PD); From 6ed6c558234f0b6c22e47a3c2feddce3d02324dd Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 8 Sep 2020 12:26:11 +0100 Subject: [PATCH 057/131] firmware: arm_scmi: Fix NULL pointer dereference in mailbox_chan_free scmi_mailbox is obtained from cinfo->transport_info and the first call to mailbox_chan_free frees the channel and sets cinfo->transport_info to NULL. Care is taken to check for non NULL smbox->chan but smbox can itself be NULL. Fix it by checking for it without which, kernel crashes with below NULL pointer dereference and eventually kernel panic. Unable to handle kernel NULL pointer dereference at virtual address 0000000000000038 Modules linked in: scmi_module(-) Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform, BIOS EDK II Sep 2 2020 pstate: 80000005 (Nzcv daif -PAN -UAO BTYPE=--) pc : mailbox_chan_free+0x2c/0x70 [scmi_module] lr : idr_for_each+0x6c/0xf8 Call trace: mailbox_chan_free+0x2c/0x70 [scmi_module] idr_for_each+0x6c/0xf8 scmi_remove+0xa8/0xf0 [scmi_module] platform_drv_remove+0x34/0x58 device_release_driver_internal+0x118/0x1f0 driver_detach+0x58/0xe8 bus_remove_driver+0x64/0xe0 driver_unregister+0x38/0x68 platform_driver_unregister+0x1c/0x28 scmi_driver_exit+0x38/0x44 [scmi_module] ---[ end trace 17bde19f50436de9 ]--- Kernel panic - not syncing: Fatal exception SMP: stopping secondary CPUs Kernel Offset: 0x1d0000 from 0xffff800010000000 PHYS_OFFSET: 0x80000000 CPU features: 0x0240022,25806004 Memory Limit: none ---[ end Kernel panic - not syncing: Fatal exception ]--- Link: https://lore.kernel.org/r/20200908112611.31515-1-sudeep.holla@arm.com Fixes: 5c8a47a5a91d ("firmware: arm_scmi: Make scmi core independent of the transport type") Cc: Cristian Marussi Cc: Viresh Kumar Tested-by: Cristian Marussi Reviewed-by: Cristian Marussi Reviewed-by: Viresh Kumar Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/mailbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index cc2de207fe10..4626404be541 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -110,7 +110,7 @@ static int mailbox_chan_free(int id, void *p, void *data) struct scmi_chan_info *cinfo = p; struct scmi_mailbox *smbox = cinfo->transport_info; - if (!IS_ERR(smbox->chan)) { + if (smbox && !IS_ERR(smbox->chan)) { mbox_free_channel(smbox->chan); cinfo->transport_info = NULL; smbox->chan = NULL; From 83ab016dfac377d1edc3698fb5179196f4f71f02 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Sun, 6 Sep 2020 20:09:37 +0200 Subject: [PATCH 058/131] dt-bindings: memory: mediatek: Add binding for MT8167 SMI Add device tree bindings documentation for MT8167 SMI. Signed-off-by: Fabien Parent Link: https://lore.kernel.org/r/20200906180938.1117526-1-fparent@baylibre.com Signed-off-by: Krzysztof Kozlowski --- .../bindings/memory-controllers/mediatek,smi-common.txt | 3 ++- .../bindings/memory-controllers/mediatek,smi-larb.txt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt index b64573680b42..dbafffe3f41e 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt @@ -5,7 +5,7 @@ The hardware block diagram please check bindings/iommu/mediatek,iommu.txt Mediatek SMI have two generations of HW architecture, here is the list which generation the SoCs use: generation 1: mt2701 and mt7623. -generation 2: mt2712, mt6779, mt8173 and mt8183. +generation 2: mt2712, mt6779, mt8167, mt8173 and mt8183. There's slight differences between the two SMI, for generation 2, the register which control the iommu port is at each larb's register base. But @@ -20,6 +20,7 @@ Required properties: "mediatek,mt2712-smi-common" "mediatek,mt6779-smi-common" "mediatek,mt7623-smi-common", "mediatek,mt2701-smi-common" + "mediatek,mt8167-smi-common" "mediatek,mt8173-smi-common" "mediatek,mt8183-smi-common" - reg : the register and size of the SMI block. diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt index 8f19dfe7d80e..0c5de12b5496 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt @@ -8,6 +8,7 @@ Required properties: "mediatek,mt2712-smi-larb" "mediatek,mt6779-smi-larb" "mediatek,mt7623-smi-larb", "mediatek,mt2701-smi-larb" + "mediatek,mt8167-smi-larb" "mediatek,mt8173-smi-larb" "mediatek,mt8183-smi-larb" - reg : the register and size of this local arbiter. @@ -22,7 +23,7 @@ Required properties: - "gals": the clock for GALS(Global Async Local Sync). Here is the list which has this GALS: mt8183. -Required property for mt2701, mt2712, mt6779 and mt7623: +Required property for mt2701, mt2712, mt6779, mt7623 and mt8167: - mediatek,larb-id :the hardware id of this larb. Example: From a8529f3b1cd89b8c650b5bfa1903f18460b57faf Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Sun, 6 Sep 2020 20:09:38 +0200 Subject: [PATCH 059/131] memory: mtk-smi: add support for MT8167 Add support for the SMI IP on MT8167 Signed-off-by: Fabien Parent Link: https://lore.kernel.org/r/20200906180938.1117526-2-fparent@baylibre.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index c21262502581..691e4c344cf8 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -19,6 +19,9 @@ /* mt8173 */ #define SMI_LARB_MMU_EN 0xf00 +/* mt8167 */ +#define MT8167_SMI_LARB_MMU_EN 0xfc0 + /* mt2701 */ #define REG_SMI_SECUR_CON_BASE 0x5c0 @@ -179,6 +182,13 @@ static void mtk_smi_larb_config_port_mt8173(struct device *dev) writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN); } +static void mtk_smi_larb_config_port_mt8167(struct device *dev) +{ + struct mtk_smi_larb *larb = dev_get_drvdata(dev); + + writel(*larb->mmu, larb->base + MT8167_SMI_LARB_MMU_EN); +} + static void mtk_smi_larb_config_port_gen1(struct device *dev) { struct mtk_smi_larb *larb = dev_get_drvdata(dev); @@ -226,6 +236,11 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = { .config_port = mtk_smi_larb_config_port_mt8173, }; +static const struct mtk_smi_larb_gen mtk_smi_larb_mt8167 = { + /* mt8167 do not need the port in larb */ + .config_port = mtk_smi_larb_config_port_mt8167, +}; + static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = { .port_in_larb = { LARB0_PORT_OFFSET, LARB1_PORT_OFFSET, @@ -254,6 +269,10 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = { }; static const struct of_device_id mtk_smi_larb_of_ids[] = { + { + .compatible = "mediatek,mt8167-smi-larb", + .data = &mtk_smi_larb_mt8167 + }, { .compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173 @@ -418,6 +437,10 @@ static const struct of_device_id mtk_smi_common_of_ids[] = { .compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2, }, + { + .compatible = "mediatek,mt8167-smi-common", + .data = &mtk_smi_common_gen2, + }, { .compatible = "mediatek,mt2701-smi-common", .data = &mtk_smi_common_gen1, From 8fae675850900e2032075b67f498cfe586fa23ad Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 7 Sep 2020 08:51:10 +0900 Subject: [PATCH 060/131] soc: renesas: Use ARM32/ARM64 for menu description For easy understanding of architecture and alphabetical merging, this patch uses ARM32/ARM64 for description. This prepares for sorting the menu. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bliiv54u.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 64 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 7d63a13e5b78..04d3b2ab1e22 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -49,12 +49,12 @@ if ARM && ARCH_RENESAS #comment "Renesas ARM SoCs System Type" config ARCH_EMEV2 - bool "SoC Platform support for Emma Mobile EV2" + bool "ARM32 Platform support for Emma Mobile EV2" select HAVE_ARM_SCU if SMP select SYS_SUPPORTS_EM_STI config ARCH_R7S72100 - bool "SoC Platform support for RZ/A1H" + bool "ARM32 Platform support for RZ/A1H" select ARM_ERRATA_754322 select PM select PM_GENERIC_DOMAINS @@ -63,14 +63,14 @@ config ARCH_R7S72100 select SYS_SUPPORTS_SH_MTU2 config ARCH_R7S9210 - bool "SoC Platform support for RZ/A2" + bool "ARM32 Platform support for RZ/A2" select PM select PM_GENERIC_DOMAINS select RENESAS_OSTM select RENESAS_RZA1_IRQC config ARCH_R8A73A4 - bool "SoC Platform support for R-Mobile APE6" + bool "ARM32 Platform support for R-Mobile APE6" select ARCH_RMOBILE select ARM_ERRATA_798181 if SMP select ARM_ERRATA_814220 @@ -78,49 +78,49 @@ config ARCH_R8A73A4 select RENESAS_IRQC config ARCH_R8A7740 - bool "SoC Platform support for R-Mobile A1" + bool "ARM32 Platform support for R-Mobile A1" select ARCH_RMOBILE select ARM_ERRATA_754322 select RENESAS_INTC_IRQPIN config ARCH_R8A7742 - bool "SoC Platform support for RZ/G1H" + bool "ARM32 Platform support for RZ/G1H" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select ARM_ERRATA_814220 select SYSC_R8A7742 config ARCH_R8A7743 - bool "SoC Platform support for RZ/G1M" + bool "ARM32 Platform support for RZ/G1M" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select SYSC_R8A7743 config ARCH_R8A7744 - bool "SoC Platform support for RZ/G1N" + bool "ARM32 Platform support for RZ/G1N" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select SYSC_R8A7743 config ARCH_R8A7745 - bool "SoC Platform support for RZ/G1E" + bool "ARM32 Platform support for RZ/G1E" select ARCH_RCAR_GEN2 select ARM_ERRATA_814220 select SYSC_R8A7745 config ARCH_R8A77470 - bool "SoC Platform support for RZ/G1C" + bool "ARM32 Platform support for RZ/G1C" select ARCH_RCAR_GEN2 select ARM_ERRATA_814220 select SYSC_R8A77470 config ARCH_R8A7778 - bool "SoC Platform support for R-Car M1A" + bool "ARM32 Platform support for R-Car M1A" select ARCH_RCAR_GEN1 select ARM_ERRATA_754322 config ARCH_R8A7779 - bool "SoC Platform support for R-Car H1" + bool "ARM32 Platform support for R-Car H1" select ARCH_RCAR_GEN1 select ARM_ERRATA_754322 select ARM_GLOBAL_TIMER @@ -129,7 +129,7 @@ config ARCH_R8A7779 select SYSC_R8A7779 config ARCH_R8A7790 - bool "SoC Platform support for R-Car H2" + bool "ARM32 Platform support for R-Car H2" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select ARM_ERRATA_814220 @@ -137,38 +137,38 @@ config ARCH_R8A7790 select SYSC_R8A7790 config ARCH_R8A7791 - bool "SoC Platform support for R-Car M2-W" + bool "ARM32 Platform support for R-Car M2-W" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select I2C select SYSC_R8A7791 config ARCH_R8A7792 - bool "SoC Platform support for R-Car V2H" + bool "ARM32 Platform support for R-Car V2H" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select SYSC_R8A7792 config ARCH_R8A7793 - bool "SoC Platform support for R-Car M2-N" + bool "ARM32 Platform support for R-Car M2-N" select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP select I2C select SYSC_R8A7791 config ARCH_R8A7794 - bool "SoC Platform support for R-Car E2" + bool "ARM32 Platform support for R-Car E2" select ARCH_RCAR_GEN2 select ARM_ERRATA_814220 select SYSC_R8A7794 config ARCH_R9A06G032 - bool "SoC Platform support for RZ/N1D" + bool "ARM32 Platform support for RZ/N1D" select ARCH_RZN1 select ARM_ERRATA_814220 config ARCH_SH73A0 - bool "SoC Platform support for SH-Mobile AG5" + bool "ARM32 Platform support for SH-Mobile AG5" select ARCH_RMOBILE select ARM_ERRATA_754322 select ARM_GLOBAL_TIMER @@ -181,42 +181,42 @@ endif # ARM if ARM64 config ARCH_R8A774A1 - bool "SoC Platform support for RZ/G2M" + bool "ARM64 Platform support for RZ/G2M" select ARCH_RCAR_GEN3 select SYSC_R8A774A1 help This enables support for the Renesas RZ/G2M SoC. config ARCH_R8A774B1 - bool "SoC Platform support for RZ/G2N" + bool "ARM64 Platform support for RZ/G2N" select ARCH_RCAR_GEN3 select SYSC_R8A774B1 help This enables support for the Renesas RZ/G2N SoC. config ARCH_R8A774C0 - bool "SoC Platform support for RZ/G2E" + bool "ARM64 Platform support for RZ/G2E" select ARCH_RCAR_GEN3 select SYSC_R8A774C0 help This enables support for the Renesas RZ/G2E SoC. config ARCH_R8A774E1 - bool "SoC Platform support for RZ/G2H" + bool "ARM64 Platform support for RZ/G2H" select ARCH_RCAR_GEN3 select SYSC_R8A774E1 help This enables support for the Renesas RZ/G2H SoC. config ARCH_R8A77950 - bool "SoC Platform support for R-Car H3 ES1.x" + bool "ARM64 Platform support for R-Car H3 ES1.x" select ARCH_RCAR_GEN3 select SYSC_R8A7795 help This enables support for the Renesas R-Car H3 SoC (revision 1.x). config ARCH_R8A77951 - bool "SoC Platform support for R-Car H3 ES2.0+" + bool "ARM64 Platform support for R-Car H3 ES2.0+" select ARCH_RCAR_GEN3 select SYSC_R8A7795 help @@ -224,49 +224,49 @@ config ARCH_R8A77951 later). config ARCH_R8A77960 - bool "SoC Platform support for R-Car M3-W" + bool "ARM64 Platform support for R-Car M3-W" select ARCH_RCAR_GEN3 select SYSC_R8A77960 help This enables support for the Renesas R-Car M3-W SoC. config ARCH_R8A77961 - bool "SoC Platform support for R-Car M3-W+" + bool "ARM64 Platform support for R-Car M3-W+" select ARCH_RCAR_GEN3 select SYSC_R8A77961 help This enables support for the Renesas R-Car M3-W+ SoC. config ARCH_R8A77965 - bool "SoC Platform support for R-Car M3-N" + bool "ARM64 Platform support for R-Car M3-N" select ARCH_RCAR_GEN3 select SYSC_R8A77965 help This enables support for the Renesas R-Car M3-N SoC. config ARCH_R8A77970 - bool "SoC Platform support for R-Car V3M" + bool "ARM64 Platform support for R-Car V3M" select ARCH_RCAR_GEN3 select SYSC_R8A77970 help This enables support for the Renesas R-Car V3M SoC. config ARCH_R8A77980 - bool "SoC Platform support for R-Car V3H" + bool "ARM64 Platform support for R-Car V3H" select ARCH_RCAR_GEN3 select SYSC_R8A77980 help This enables support for the Renesas R-Car V3H SoC. config ARCH_R8A77990 - bool "SoC Platform support for R-Car E3" + bool "ARM64 Platform support for R-Car E3" select ARCH_RCAR_GEN3 select SYSC_R8A77990 help This enables support for the Renesas R-Car E3 SoC. config ARCH_R8A77995 - bool "SoC Platform support for R-Car D3" + bool "ARM64 Platform support for R-Car D3" select ARCH_RCAR_GEN3 select SYSC_R8A77995 help From 6d5aded8d57fc0323ee61fec7a3318d8222e85ed Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 7 Sep 2020 08:51:15 +0900 Subject: [PATCH 061/131] soc: renesas: Sort driver description title This patch sorts each driver by description title in alphabetical order. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a6y2v54o.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 328 ++++++++++++++++++------------------ 1 file changed, 163 insertions(+), 165 deletions(-) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 04d3b2ab1e22..9954acdd7945 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -53,6 +53,68 @@ config ARCH_EMEV2 select HAVE_ARM_SCU if SMP select SYS_SUPPORTS_EM_STI +config ARCH_R8A7794 + bool "ARM32 Platform support for R-Car E2" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_814220 + select SYSC_R8A7794 + +config ARCH_R8A7779 + bool "ARM32 Platform support for R-Car H1" + select ARCH_RCAR_GEN1 + select ARM_ERRATA_754322 + select ARM_GLOBAL_TIMER + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + select SYSC_R8A7779 + +config ARCH_R8A7790 + bool "ARM32 Platform support for R-Car H2" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select ARM_ERRATA_814220 + select I2C + select SYSC_R8A7790 + +config ARCH_R8A7778 + bool "ARM32 Platform support for R-Car M1A" + select ARCH_RCAR_GEN1 + select ARM_ERRATA_754322 + +config ARCH_R8A7793 + bool "ARM32 Platform support for R-Car M2-N" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select I2C + select SYSC_R8A7791 + +config ARCH_R8A7791 + bool "ARM32 Platform support for R-Car M2-W" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select I2C + select SYSC_R8A7791 + +config ARCH_R8A7792 + bool "ARM32 Platform support for R-Car V2H" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select SYSC_R8A7792 + +config ARCH_R8A7740 + bool "ARM32 Platform support for R-Mobile A1" + select ARCH_RMOBILE + select ARM_ERRATA_754322 + select RENESAS_INTC_IRQPIN + +config ARCH_R8A73A4 + bool "ARM32 Platform support for R-Mobile APE6" + select ARCH_RMOBILE + select ARM_ERRATA_798181 if SMP + select ARM_ERRATA_814220 + select HAVE_ARM_ARCH_TIMER + select RENESAS_IRQC + config ARCH_R7S72100 bool "ARM32 Platform support for RZ/A1H" select ARM_ERRATA_754322 @@ -69,19 +131,17 @@ config ARCH_R7S9210 select RENESAS_OSTM select RENESAS_RZA1_IRQC -config ARCH_R8A73A4 - bool "ARM32 Platform support for R-Mobile APE6" - select ARCH_RMOBILE - select ARM_ERRATA_798181 if SMP +config ARCH_R8A77470 + bool "ARM32 Platform support for RZ/G1C" + select ARCH_RCAR_GEN2 select ARM_ERRATA_814220 - select HAVE_ARM_ARCH_TIMER - select RENESAS_IRQC + select SYSC_R8A77470 -config ARCH_R8A7740 - bool "ARM32 Platform support for R-Mobile A1" - select ARCH_RMOBILE - select ARM_ERRATA_754322 - select RENESAS_INTC_IRQPIN +config ARCH_R8A7745 + bool "ARM32 Platform support for RZ/G1E" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_814220 + select SYSC_R8A7745 config ARCH_R8A7742 bool "ARM32 Platform support for RZ/G1H" @@ -102,66 +162,6 @@ config ARCH_R8A7744 select ARM_ERRATA_798181 if SMP select SYSC_R8A7743 -config ARCH_R8A7745 - bool "ARM32 Platform support for RZ/G1E" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_814220 - select SYSC_R8A7745 - -config ARCH_R8A77470 - bool "ARM32 Platform support for RZ/G1C" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_814220 - select SYSC_R8A77470 - -config ARCH_R8A7778 - bool "ARM32 Platform support for R-Car M1A" - select ARCH_RCAR_GEN1 - select ARM_ERRATA_754322 - -config ARCH_R8A7779 - bool "ARM32 Platform support for R-Car H1" - select ARCH_RCAR_GEN1 - select ARM_ERRATA_754322 - select ARM_GLOBAL_TIMER - select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if SMP - select SYSC_R8A7779 - -config ARCH_R8A7790 - bool "ARM32 Platform support for R-Car H2" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - select ARM_ERRATA_814220 - select I2C - select SYSC_R8A7790 - -config ARCH_R8A7791 - bool "ARM32 Platform support for R-Car M2-W" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - select I2C - select SYSC_R8A7791 - -config ARCH_R8A7792 - bool "ARM32 Platform support for R-Car V2H" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - select SYSC_R8A7792 - -config ARCH_R8A7793 - bool "ARM32 Platform support for R-Car M2-N" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - select I2C - select SYSC_R8A7791 - -config ARCH_R8A7794 - bool "ARM32 Platform support for R-Car E2" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_814220 - select SYSC_R8A7794 - config ARCH_R9A06G032 bool "ARM32 Platform support for RZ/N1D" select ARCH_RZN1 @@ -180,33 +180,19 @@ endif # ARM if ARM64 -config ARCH_R8A774A1 - bool "ARM64 Platform support for RZ/G2M" +config ARCH_R8A77995 + bool "ARM64 Platform support for R-Car D3" select ARCH_RCAR_GEN3 - select SYSC_R8A774A1 + select SYSC_R8A77995 help - This enables support for the Renesas RZ/G2M SoC. + This enables support for the Renesas R-Car D3 SoC. -config ARCH_R8A774B1 - bool "ARM64 Platform support for RZ/G2N" +config ARCH_R8A77990 + bool "ARM64 Platform support for R-Car E3" select ARCH_RCAR_GEN3 - select SYSC_R8A774B1 + select SYSC_R8A77990 help - This enables support for the Renesas RZ/G2N SoC. - -config ARCH_R8A774C0 - bool "ARM64 Platform support for RZ/G2E" - select ARCH_RCAR_GEN3 - select SYSC_R8A774C0 - help - This enables support for the Renesas RZ/G2E SoC. - -config ARCH_R8A774E1 - bool "ARM64 Platform support for RZ/G2H" - select ARCH_RCAR_GEN3 - select SYSC_R8A774E1 - help - This enables support for the Renesas RZ/G2H SoC. + This enables support for the Renesas R-Car E3 SoC. config ARCH_R8A77950 bool "ARM64 Platform support for R-Car H3 ES1.x" @@ -223,6 +209,13 @@ config ARCH_R8A77951 This enables support for the Renesas R-Car H3 SoC (revisions 2.0 and later). +config ARCH_R8A77965 + bool "ARM64 Platform support for R-Car M3-N" + select ARCH_RCAR_GEN3 + select SYSC_R8A77965 + help + This enables support for the Renesas R-Car M3-N SoC. + config ARCH_R8A77960 bool "ARM64 Platform support for R-Car M3-W" select ARCH_RCAR_GEN3 @@ -237,12 +230,12 @@ config ARCH_R8A77961 help This enables support for the Renesas R-Car M3-W+ SoC. -config ARCH_R8A77965 - bool "ARM64 Platform support for R-Car M3-N" +config ARCH_R8A77980 + bool "ARM64 Platform support for R-Car V3H" select ARCH_RCAR_GEN3 - select SYSC_R8A77965 + select SYSC_R8A77980 help - This enables support for the Renesas R-Car M3-N SoC. + This enables support for the Renesas R-Car V3H SoC. config ARCH_R8A77970 bool "ARM64 Platform support for R-Car V3M" @@ -251,60 +244,52 @@ config ARCH_R8A77970 help This enables support for the Renesas R-Car V3M SoC. -config ARCH_R8A77980 - bool "ARM64 Platform support for R-Car V3H" +config ARCH_R8A774C0 + bool "ARM64 Platform support for RZ/G2E" select ARCH_RCAR_GEN3 - select SYSC_R8A77980 + select SYSC_R8A774C0 help - This enables support for the Renesas R-Car V3H SoC. + This enables support for the Renesas RZ/G2E SoC. -config ARCH_R8A77990 - bool "ARM64 Platform support for R-Car E3" +config ARCH_R8A774E1 + bool "ARM64 Platform support for RZ/G2H" select ARCH_RCAR_GEN3 - select SYSC_R8A77990 + select SYSC_R8A774E1 help - This enables support for the Renesas R-Car E3 SoC. + This enables support for the Renesas RZ/G2H SoC. -config ARCH_R8A77995 - bool "ARM64 Platform support for R-Car D3" +config ARCH_R8A774A1 + bool "ARM64 Platform support for RZ/G2M" select ARCH_RCAR_GEN3 - select SYSC_R8A77995 + select SYSC_R8A774A1 help - This enables support for the Renesas R-Car D3 SoC. + This enables support for the Renesas RZ/G2M SoC. + +config ARCH_R8A774B1 + bool "ARM64 Platform support for RZ/G2N" + select ARCH_RCAR_GEN3 + select SYSC_R8A774B1 + help + This enables support for the Renesas RZ/G2N SoC. endif # ARM64 -# SoC -config SYSC_R8A7742 - bool "System Controller support for RZ/G1H" if COMPILE_TEST +config RST_RCAR + bool "Reset Controller support for R-Car" if COMPILE_TEST + +config SYSC_RCAR + bool "System Controller support for R-Car" if COMPILE_TEST + +config SYSC_R8A77995 + bool "System Controller support for R-Car D3" if COMPILE_TEST select SYSC_RCAR -config SYSC_R8A7743 - bool "System Controller support for RZ/G1M" if COMPILE_TEST +config SYSC_R8A7794 + bool "System Controller support for R-Car E2" if COMPILE_TEST select SYSC_RCAR -config SYSC_R8A7745 - bool "System Controller support for RZ/G1E" if COMPILE_TEST - select SYSC_RCAR - -config SYSC_R8A77470 - bool "System Controller support for RZ/G1C" if COMPILE_TEST - select SYSC_RCAR - -config SYSC_R8A774A1 - bool "System Controller support for RZ/G2M" if COMPILE_TEST - select SYSC_RCAR - -config SYSC_R8A774B1 - bool "System Controller support for RZ/G2N" if COMPILE_TEST - select SYSC_RCAR - -config SYSC_R8A774C0 - bool "System Controller support for RZ/G2E" if COMPILE_TEST - select SYSC_RCAR - -config SYSC_R8A774E1 - bool "System Controller support for RZ/G2H" if COMPILE_TEST +config SYSC_R8A77990 + bool "System Controller support for R-Car E3" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A7779 @@ -315,20 +300,16 @@ config SYSC_R8A7790 bool "System Controller support for R-Car H2" if COMPILE_TEST select SYSC_RCAR +config SYSC_R8A7795 + bool "System Controller support for R-Car H3" if COMPILE_TEST + select SYSC_RCAR + config SYSC_R8A7791 bool "System Controller support for R-Car M2-W/N" if COMPILE_TEST select SYSC_RCAR -config SYSC_R8A7792 - bool "System Controller support for R-Car V2H" if COMPILE_TEST - select SYSC_RCAR - -config SYSC_R8A7794 - bool "System Controller support for R-Car E2" if COMPILE_TEST - select SYSC_RCAR - -config SYSC_R8A7795 - bool "System Controller support for R-Car H3" if COMPILE_TEST +config SYSC_R8A77965 + bool "System Controller support for R-Car M3-N" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77960 @@ -339,34 +320,51 @@ config SYSC_R8A77961 bool "System Controller support for R-Car M3-W+" if COMPILE_TEST select SYSC_RCAR -config SYSC_R8A77965 - bool "System Controller support for R-Car M3-N" if COMPILE_TEST - select SYSC_RCAR - -config SYSC_R8A77970 - bool "System Controller support for R-Car V3M" if COMPILE_TEST +config SYSC_R8A7792 + bool "System Controller support for R-Car V2H" if COMPILE_TEST select SYSC_RCAR config SYSC_R8A77980 bool "System Controller support for R-Car V3H" if COMPILE_TEST select SYSC_RCAR -config SYSC_R8A77990 - bool "System Controller support for R-Car E3" if COMPILE_TEST +config SYSC_R8A77970 + bool "System Controller support for R-Car V3M" if COMPILE_TEST select SYSC_RCAR -config SYSC_R8A77995 - bool "System Controller support for R-Car D3" if COMPILE_TEST - select SYSC_RCAR - -# Family -config RST_RCAR - bool "Reset Controller support for R-Car" if COMPILE_TEST - -config SYSC_RCAR - bool "System Controller support for R-Car" if COMPILE_TEST - config SYSC_RMOBILE bool "System Controller support for R-Mobile" if COMPILE_TEST +config SYSC_R8A77470 + bool "System Controller support for RZ/G1C" if COMPILE_TEST + select SYSC_RCAR + +config SYSC_R8A7745 + bool "System Controller support for RZ/G1E" if COMPILE_TEST + select SYSC_RCAR + +config SYSC_R8A7742 + bool "System Controller support for RZ/G1H" if COMPILE_TEST + select SYSC_RCAR + +config SYSC_R8A7743 + bool "System Controller support for RZ/G1M" if COMPILE_TEST + select SYSC_RCAR + +config SYSC_R8A774C0 + bool "System Controller support for RZ/G2E" if COMPILE_TEST + select SYSC_RCAR + +config SYSC_R8A774E1 + bool "System Controller support for RZ/G2H" if COMPILE_TEST + select SYSC_RCAR + +config SYSC_R8A774A1 + bool "System Controller support for RZ/G2M" if COMPILE_TEST + select SYSC_RCAR + +config SYSC_R8A774B1 + bool "System Controller support for RZ/G2N" if COMPILE_TEST + select SYSC_RCAR + endif # SOC_RENESAS From 090e87e7fbe3b13f14f0fd648aceac9c28d42c18 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 7 Sep 2020 18:19:45 +0900 Subject: [PATCH 062/131] soc: renesas: Identify R-Car V3U Add support for identifying the R-Car V3U (R8A779A0) SoC. Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/1599470390-29719-10-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 6 ++++++ drivers/soc/renesas/renesas-soc.c | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 9954acdd7945..6efa9d0b67d9 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -244,6 +244,12 @@ config ARCH_R8A77970 help This enables support for the Renesas R-Car V3M SoC. +config ARCH_R8A779A0 + bool "ARM64 Platform support for R-Car V3U" + select ARCH_RCAR_GEN3 + help + This enables support for the Renesas R-Car V3U SoC. + config ARCH_R8A774C0 bool "ARM64 Platform support for RZ/G2E" select ARCH_RCAR_GEN3 diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index f815a6a8b88b..0f8eff4a641a 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -200,6 +200,11 @@ static const struct renesas_soc soc_rcar_d3 __initconst __maybe_unused = { .id = 0x58, }; +static const struct renesas_soc soc_rcar_v3u __initconst __maybe_unused = { + .family = &fam_rcar_gen3, + .id = 0x59, +}; + static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = { .family = &fam_shmobile, .id = 0x37, @@ -291,6 +296,9 @@ static const struct of_device_id renesas_socs[] __initconst = { #ifdef CONFIG_ARCH_R8A77995 { .compatible = "renesas,r8a77995", .data = &soc_rcar_d3 }, #endif +#ifdef CONFIG_ARCH_R8A779A0 + { .compatible = "renesas,r8a779a0", .data = &soc_rcar_v3u }, +#endif #ifdef CONFIG_ARCH_SH73A0 { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, #endif From 8e9529f5cde7c99a0c528d96c600b5affad71908 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 7 Sep 2020 18:19:47 +0900 Subject: [PATCH 063/131] soc: renesas: rcar-rst: Add support for R-Car V3U Add support for R-Car V3U (R8A779A0) to the R-Car RST driver. Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/1599470390-29719-12-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/rcar-rst.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c index a932015ce9c1..8a1e402ea799 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c @@ -37,6 +37,10 @@ static const struct rst_config rcar_rst_gen3 __initconst = { .modemr = 0x60, }; +static const struct rst_config rcar_rst_r8a779a0 __initconst = { + .modemr = 0x00, /* MODEMR0 and it has CPG related bits */ +}; + static const struct of_device_id rcar_rst_matches[] __initconst = { /* RZ/G1 is handled like R-Car Gen2 */ { .compatible = "renesas,r8a7742-rst", .data = &rcar_rst_gen2 }, @@ -67,6 +71,8 @@ static const struct of_device_id rcar_rst_matches[] __initconst = { { .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 }, + /* R-Car V3U */ + { .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_r8a779a0 }, { /* sentinel */ } }; From 7303fbd2f07e529becfe6c22bd95978009f7bda3 Mon Sep 17 00:00:00 2001 From: Kathiravan T Date: Mon, 17 Aug 2020 12:00:30 +0530 Subject: [PATCH 064/131] soc: qcom: socinfo: add soc id for IPQ6018 Add the SoC ID for IPQ6018 variant. Signed-off-by: Kathiravan T Link: https://lore.kernel.org/r/1597645830-30409-1-git-send-email-kathirav@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index e19102f46302..2b28667e1c66 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -223,6 +223,7 @@ static const struct soc_id soc_id[] = { { 321, "SDM845" }, { 341, "SDA845" }, { 356, "SM8250" }, + { 402, "IPQ6018" }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) From cb8aed7b92f3cf74007a07c17bb08e6488661ae9 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 13 Aug 2020 08:03:52 -0700 Subject: [PATCH 065/131] soc: qcom: socinfo: add SC7180 entry to soc_id array Add an entry for SC7180 SoC. Reviewed-by: Sai Prakash Ranjan Reviewed-by: Stephen Boyd Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200813080345.1.I85bb28f9ea3fa3bf797ecaf0a5218ced4cfaa6e2@changeid Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 2b28667e1c66..1fbdea81e1f1 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -224,6 +224,7 @@ static const struct soc_id soc_id[] = { { 341, "SDA845" }, { 356, "SM8250" }, { 402, "IPQ6018" }, + { 425, "SC7180" }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) From 0feea33d79825d05b5ede30947db4df34722b463 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Wed, 22 Jul 2020 15:01:20 -0700 Subject: [PATCH 066/131] soc: qcom-geni-se: Don't use relaxed writes when writing commands Writing the command is the final step in kicking off a transfer. Let's use writel() to ensure that any other memory accesses are done before the command kicks off. It's expected that this is mostly relevant if we're in DMA mode but since it doesn't appear to regress performance in a measurable way [1] even in PIO mode and it's easier to reason about then let's just always use it. NOTE: this patch came about due to code inspection. No actual problems were observed that this patch fixes. [1] Tested by timing "flashrom -p ec" on a Chromebook which stresses GENI SPI a lot. Reviewed-by: Mukesh Kumar Savaliya Reviewed-by: Akash Asthana Reviewed-by: Stephen Boyd Suggested-by: Stephen Boyd Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200722150113.1.Ia50ab5cb8a6d3a73d302e6bdc25542d48ffd27f4@changeid Signed-off-by: Bjorn Andersson --- include/linux/qcom-geni-se.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index 8f385fbe5a0e..ae4a8a766b69 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -296,7 +296,7 @@ static inline void geni_se_setup_m_cmd(struct geni_se *se, u32 cmd, u32 params) u32 m_cmd; m_cmd = (cmd << M_OPCODE_SHFT) | (params & M_PARAMS_MSK); - writel_relaxed(m_cmd, se->base + SE_GENI_M_CMD0); + writel(m_cmd, se->base + SE_GENI_M_CMD0); } /** @@ -316,7 +316,7 @@ static inline void geni_se_setup_s_cmd(struct geni_se *se, u32 cmd, u32 params) s_cmd &= ~(S_OPCODE_MSK | S_PARAMS_MSK); s_cmd |= (cmd << S_OPCODE_SHFT); s_cmd |= (params & S_PARAMS_MSK); - writel_relaxed(s_cmd, se->base + SE_GENI_S_CMD0); + writel(s_cmd, se->base + SE_GENI_S_CMD0); } /** From 2bc20f3c8487bd5bc4dd9ad2c06d2ba05fd4e838 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 24 Jul 2020 14:17:11 -0700 Subject: [PATCH 067/131] soc: qcom: rpmh-rsc: Sleep waiting for tcs slots to be free The busy loop in rpmh_rsc_send_data() is written with the assumption that the udelay will be preempted by the tcs_tx_done() irq handler when the TCS slots are all full. This doesn't hold true when the calling thread is an irqthread and the tcs_tx_done() irq is also an irqthread. That's because kernel irqthreads are SCHED_FIFO and thus need to voluntarily give up priority by calling into the scheduler so that other threads can run. I see RCU stalls when I boot with irqthreads on the kernel commandline because the modem remoteproc driver is trying to send an rpmh async message from an irqthread that needs to give up the CPU for the rpmh irqthread to run and clear out tcs slots. rcu: INFO: rcu_preempt self-detected stall on CPU rcu: 0-....: (1 GPs behind) idle=402/1/0x4000000000000002 softirq=2108/2109 fqs=4920 (t=21016 jiffies g=2933 q=590) Task dump for CPU 0: irq/11-smp2p R running task 0 148 2 0x00000028 Call trace: dump_backtrace+0x0/0x154 show_stack+0x20/0x2c sched_show_task+0xfc/0x108 dump_cpu_task+0x44/0x50 rcu_dump_cpu_stacks+0xa4/0xf8 rcu_sched_clock_irq+0x7dc/0xaa8 update_process_times+0x30/0x54 tick_sched_handle+0x50/0x64 tick_sched_timer+0x4c/0x8c __hrtimer_run_queues+0x21c/0x36c hrtimer_interrupt+0xf0/0x22c arch_timer_handler_phys+0x40/0x50 handle_percpu_devid_irq+0x114/0x25c __handle_domain_irq+0x84/0xc4 gic_handle_irq+0xd0/0x178 el1_irq+0xbc/0x180 save_return_addr+0x18/0x28 return_address+0x54/0x88 preempt_count_sub+0x40/0x88 _raw_spin_unlock_irqrestore+0x4c/0x6c ___ratelimit+0xd0/0x128 rpmh_rsc_send_data+0x24c/0x378 __rpmh_write+0x1b0/0x208 rpmh_write_async+0x90/0xbc rpmhpd_send_corner+0x60/0x8c rpmhpd_aggregate_corner+0x8c/0x124 rpmhpd_set_performance_state+0x8c/0xbc _genpd_set_performance_state+0xdc/0x1b8 dev_pm_genpd_set_performance_state+0xb8/0xf8 q6v5_pds_disable+0x34/0x60 [qcom_q6v5_mss] qcom_msa_handover+0x38/0x44 [qcom_q6v5_mss] q6v5_handover_interrupt+0x24/0x3c [qcom_q6v5] handle_nested_irq+0xd0/0x138 qcom_smp2p_intr+0x188/0x200 irq_thread_fn+0x2c/0x70 irq_thread+0xfc/0x14c kthread+0x11c/0x12c ret_from_fork+0x10/0x18 This busy loop naturally lends itself to using a wait queue so that each thread that tries to send a message will sleep waiting on the waitqueue and only be woken up when a free slot is available. This should make things more predictable too because the scheduler will be able to sleep tasks that are waiting on a free tcs instead of the busy loop we currently have today. Reviewed-by: Maulik Shah Reviewed-by: Douglas Anderson Tested-by: Stanimir Varbanov Cc: Douglas Anderson Cc: Maulik Shah Cc: Lina Iyer Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20200724211711.810009-1-sboyd@kernel.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-internal.h | 4 ++ drivers/soc/qcom/rpmh-rsc.c | 117 +++++++++++++++---------------- 2 files changed, 59 insertions(+), 62 deletions(-) diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h index ef60e790a750..344ba687c13b 100644 --- a/drivers/soc/qcom/rpmh-internal.h +++ b/drivers/soc/qcom/rpmh-internal.h @@ -8,6 +8,7 @@ #define __RPM_INTERNAL_H__ #include +#include #include #define TCS_TYPE_NR 4 @@ -106,6 +107,8 @@ struct rpmh_ctrlr { * @lock: Synchronize state of the controller. If RPMH's cache * lock will also be held, the order is: drv->lock then * cache_lock. + * @tcs_wait: Wait queue used to wait for @tcs_in_use to free up a + * slot * @client: Handle to the DRV's client. */ struct rsc_drv { @@ -118,6 +121,7 @@ struct rsc_drv { struct tcs_group tcs[TCS_TYPE_NR]; DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR); spinlock_t lock; + wait_queue_head_t tcs_wait; struct rpmh_ctrlr client; }; diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index ae6675782581..a297911afe57 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -453,6 +454,7 @@ static irqreturn_t tcs_tx_done(int irq, void *p) if (!drv->tcs[ACTIVE_TCS].num_tcs) enable_tcs_irq(drv, i, false); spin_unlock(&drv->lock); + wake_up(&drv->tcs_wait); if (req) rpmh_tx_done(req, err); } @@ -571,43 +573,74 @@ static int find_free_tcs(struct tcs_group *tcs) } /** - * tcs_write() - Store messages into a TCS right now, or return -EBUSY. + * claim_tcs_for_req() - Claim a tcs in the given tcs_group; only for active. * @drv: The controller. + * @tcs: The tcs_group used for ACTIVE_ONLY transfers. * @msg: The data to be sent. * - * Grabs a TCS for ACTIVE_ONLY transfers and writes the messages to it. + * Claims a tcs in the given tcs_group while making sure that no existing cmd + * is in flight that would conflict with the one in @msg. * - * If there are no free TCSes for ACTIVE_ONLY transfers or if a command for - * the same address is already transferring returns -EBUSY which means the - * client should retry shortly. + * Context: Must be called with the drv->lock held since that protects + * tcs_in_use. * - * Return: 0 on success, -EBUSY if client should retry, or an error. - * Client should have interrupts enabled for a bit before retrying. + * Return: The id of the claimed tcs or -EBUSY if a matching msg is in flight + * or the tcs_group is full. */ -static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg) +static int claim_tcs_for_req(struct rsc_drv *drv, struct tcs_group *tcs, + const struct tcs_request *msg) { - struct tcs_group *tcs; - int tcs_id; - unsigned long flags; int ret; - tcs = get_tcs_for_msg(drv, msg); - if (IS_ERR(tcs)) - return PTR_ERR(tcs); - - spin_lock_irqsave(&drv->lock, flags); /* * The h/w does not like if we send a request to the same address, * when one is already in-flight or being processed. */ ret = check_for_req_inflight(drv, tcs, msg); if (ret) - goto unlock; + return ret; - ret = find_free_tcs(tcs); - if (ret < 0) - goto unlock; - tcs_id = ret; + return find_free_tcs(tcs); +} + +/** + * rpmh_rsc_send_data() - Write / trigger active-only message. + * @drv: The controller. + * @msg: The data to be sent. + * + * NOTES: + * - This is only used for "ACTIVE_ONLY" since the limitations of this + * function don't make sense for sleep/wake cases. + * - To do the transfer, we will grab a whole TCS for ourselves--we don't + * try to share. If there are none available we'll wait indefinitely + * for a free one. + * - This function will not wait for the commands to be finished, only for + * data to be programmed into the RPMh. See rpmh_tx_done() which will + * be called when the transfer is fully complete. + * - This function must be called with interrupts enabled. If the hardware + * is busy doing someone else's transfer we need that transfer to fully + * finish so that we can have the hardware, and to fully finish it needs + * the interrupt handler to run. If the interrupts is set to run on the + * active CPU this can never happen if interrupts are disabled. + * + * Return: 0 on success, -EINVAL on error. + */ +int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) +{ + struct tcs_group *tcs; + int tcs_id; + unsigned long flags; + + tcs = get_tcs_for_msg(drv, msg); + if (IS_ERR(tcs)) + return PTR_ERR(tcs); + + spin_lock_irqsave(&drv->lock, flags); + + /* Wait forever for a free tcs. It better be there eventually! */ + wait_event_lock_irq(drv->tcs_wait, + (tcs_id = claim_tcs_for_req(drv, tcs, msg)) >= 0, + drv->lock); tcs->req[tcs_id - tcs->offset] = msg; set_bit(tcs_id, drv->tcs_in_use); @@ -635,47 +668,6 @@ static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg) __tcs_set_trigger(drv, tcs_id, true); return 0; -unlock: - spin_unlock_irqrestore(&drv->lock, flags); - return ret; -} - -/** - * rpmh_rsc_send_data() - Write / trigger active-only message. - * @drv: The controller. - * @msg: The data to be sent. - * - * NOTES: - * - This is only used for "ACTIVE_ONLY" since the limitations of this - * function don't make sense for sleep/wake cases. - * - To do the transfer, we will grab a whole TCS for ourselves--we don't - * try to share. If there are none available we'll wait indefinitely - * for a free one. - * - This function will not wait for the commands to be finished, only for - * data to be programmed into the RPMh. See rpmh_tx_done() which will - * be called when the transfer is fully complete. - * - This function must be called with interrupts enabled. If the hardware - * is busy doing someone else's transfer we need that transfer to fully - * finish so that we can have the hardware, and to fully finish it needs - * the interrupt handler to run. If the interrupts is set to run on the - * active CPU this can never happen if interrupts are disabled. - * - * Return: 0 on success, -EINVAL on error. - */ -int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) -{ - int ret; - - do { - ret = tcs_write(drv, msg); - if (ret == -EBUSY) { - pr_info_ratelimited("TCS Busy, retrying RPMH message send: addr=%#x\n", - msg->cmds[0].addr); - udelay(10); - } - } while (ret == -EBUSY); - - return ret; } /** @@ -983,6 +975,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev) return ret; spin_lock_init(&drv->lock); + init_waitqueue_head(&drv->tcs_wait); bitmap_zero(drv->tcs_in_use, MAX_TCS_NR); irq = platform_get_irq(pdev, drv->id); From 1893a2d5264e2004722afecfcea1859f38b3ed82 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Thu, 10 Sep 2020 22:05:46 +0800 Subject: [PATCH 068/131] soc: sunxi: sram: remove unneeded semicolon Eliminate the following coccicheck warning: drivers/soc/sunxi/sunxi_sram.c:197:2-3: Unneeded semicolon Reported-by: Hulk Robot Signed-off-by: Jason Yan Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20200910140546.1191280-1-yanaijie@huawei.com --- drivers/soc/sunxi/sunxi_sram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 1b0d50f36349..d4c7bd59429e 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -194,7 +194,7 @@ static const struct sunxi_sram_data *sunxi_sram_of_parse(struct device_node *nod if (!data) { ret = -EINVAL; goto err; - }; + } for (func = data->func; func->func; func++) { if (val == func->val) { From 95e7be062aea6d2e09116cd4d28957d310c04781 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 11 Sep 2020 21:29:56 -0700 Subject: [PATCH 069/131] soc: ti: k3: ringacc: add am65x sr2.0 support The AM65x SR2.0 Ringacc has fixed errata i2023 "RINGACC, UDMA: RINGACC and UDMA Ring State Interoperability Issue after Channel Teardown". This errata also fixed for J271E SoC. Use SOC bus data for K3 SoC identification and enable i2023 errate w/a only for the AM65x SR1.0. This also makes obsolete "ti,dma-ring-reset-quirk" DT property. Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/k3-ringacc.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c index 6dcc21dde0cb..1147dc4c1d59 100644 --- a/drivers/soc/ti/k3-ringacc.c +++ b/drivers/soc/ti/k3-ringacc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,15 @@ struct k3_ringacc { const struct k3_ringacc_ops *ops; }; +/** + * struct k3_ringacc - Rings accelerator SoC data + * + * @dma_ring_reset_quirk: DMA reset w/a enable + */ +struct k3_ringacc_soc_data { + unsigned dma_ring_reset_quirk:1; +}; + static long k3_ringacc_ring_get_fifo_pos(struct k3_ring *ring) { return K3_RINGACC_FIFO_WINDOW_SIZE_BYTES - @@ -1051,9 +1061,6 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc) return ret; } - ringacc->dma_ring_reset_quirk = - of_property_read_bool(node, "ti,dma-ring-reset-quirk"); - ringacc->tisci = ti_sci_get_by_phandle(node, "ti,sci"); if (IS_ERR(ringacc->tisci)) { ret = PTR_ERR(ringacc->tisci); @@ -1084,9 +1091,22 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc) ringacc->rm_gp_range); } +static const struct k3_ringacc_soc_data k3_ringacc_soc_data_sr1 = { + .dma_ring_reset_quirk = 1, +}; + +static const struct soc_device_attribute k3_ringacc_socinfo[] = { + { .family = "AM65X", + .revision = "SR1.0", + .data = &k3_ringacc_soc_data_sr1 + }, + {/* sentinel */} +}; + static int k3_ringacc_init(struct platform_device *pdev, struct k3_ringacc *ringacc) { + const struct soc_device_attribute *soc; void __iomem *base_fifo, *base_rt; struct device *dev = &pdev->dev; struct resource *res; @@ -1103,6 +1123,13 @@ static int k3_ringacc_init(struct platform_device *pdev, if (ret) return ret; + soc = soc_device_match(k3_ringacc_socinfo); + if (soc && soc->data) { + const struct k3_ringacc_soc_data *soc_data = soc->data; + + ringacc->dma_ring_reset_quirk = soc_data->dma_ring_reset_quirk; + } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rt"); base_rt = devm_ioremap_resource(dev, res); if (IS_ERR(base_rt)) From aee123f48f387ea62002cddb46c7cb04c96628df Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 11 Sep 2020 21:30:23 -0700 Subject: [PATCH 070/131] bindings: soc: ti: soc: ringacc: remove ti,dma-ring-reset-quirk Remove "ti,dma-ring-reset-quirk" DT property as proper w/a handling is implemented now in Ringacc driver using SoC info. Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml b/Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml index ae33fc957141..c3c595e235a8 100644 --- a/Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml +++ b/Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml @@ -62,11 +62,6 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 description: TI-SCI device id of the ring accelerator - ti,dma-ring-reset-quirk: - $ref: /schemas/types.yaml#definitions/flag - description: | - enable ringacc/udma ring state interoperability issue software w/a - required: - compatible - reg @@ -94,7 +89,6 @@ examples: reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target"; ti,num-rings = <818>; ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */ - ti,dma-ring-reset-quirk; ti,sci = <&dmsc>; ti,sci-dev-id = <187>; msi-parent = <&inta_main_udmass>; From bd691ce0ba9d610018072723307f5983f94f5322 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Fri, 11 Sep 2020 21:41:17 -0700 Subject: [PATCH 071/131] dt-bindings: soc: ti: Add TI PRUSS bindings This patch adds the bindings for the Programmable Real-Time Unit and Industrial Communication Subsystem (PRU-ICSS) present on various TI SoCs. The IP is present on multiple TI SoC architecture families including the OMAP architecture SoCs such as AM33xx, AM437x and AM57xx; and on a Keystone 2 architecture based 66AK2G SoC. It is also present on the Davinci based OMAPL138 SoCs and K3 architecture based AM65x and J721E SoCs as well. The IP has a number of sub-modules some of which are represented as their own devices. This binding covers only the top-level sub-system devices, and some sub-modules like MDIO, MII_RT (Ethernet MII_RT module with MII ports) and IEP (Industrial Ethernet Peripheral). The remaining sub-modules bindings shall be defined in the respective driver subsystem bindings folders. Couple of full examples have also been added demonstrating the devices on AM335x and AM437x SoCs. Reviewed-by: Rob Herring Signed-off-by: Suman Anna Signed-off-by: Roger Quadros Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- .../devicetree/bindings/soc/ti/ti,pruss.yaml | 320 ++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml diff --git a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml new file mode 100644 index 000000000000..482beefaac1f --- /dev/null +++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml @@ -0,0 +1,320 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/ti/ti,pruss.yaml +$schema: http://devicetree.org/meta-schemas/core.yaml + +title: |+ + TI Programmable Real-Time Unit and Industrial Communication Subsystem + +maintainers: + - Suman Anna + +description: |+ + + The Programmable Real-Time Unit and Industrial Communication Subsystem + (PRU-ICSS a.k.a. PRUSS) is present on various TI SoCs such as AM335x, AM437x, + Keystone 66AK2G, OMAP-L138/DA850 etc. A PRUSS consists of dual 32-bit RISC + cores (Programmable Real-Time Units, or PRUs), shared RAM, data and + instruction RAMs, some internal peripheral modules to facilitate industrial + communication, and an interrupt controller. + + The programmable nature of the PRUs provide flexibility to implement custom + peripheral interfaces, fast real-time responses, or specialized data handling. + The common peripheral modules include the following, + - an Ethernet MII_RT module with two MII ports + - an MDIO port to control external Ethernet PHYs + - an Industrial Ethernet Peripheral (IEP) to manage/generate Industrial + Ethernet functions + - an Enhanced Capture Module (eCAP) + - an Industrial Ethernet Timer with 7/9 capture and 16 compare events + - a 16550-compatible UART to support PROFIBUS + - Enhanced GPIO with async capture and serial support + + A PRU-ICSS subsystem can have up to three shared data memories. A PRU core + acts on a primary Data RAM (there are usually 2 Data RAMs) at its address + 0x0, but also has access to a secondary Data RAM (primary to the other PRU + core) at its address 0x2000. A shared Data RAM, if present, can be accessed + by both the PRU cores. The Interrupt Controller (INTC) and a CFG module are + common to both the PRU cores. Each PRU core also has a private instruction + RAM, and specific register spaces for Control and Debug functionalities. + + Various sub-modules within a PRU-ICSS subsystem are represented as individual + nodes and are defined using a parent-child hierarchy depending on their + integration within the IP and the SoC. These nodes are described in the + following sections. + + + PRU-ICSS Node + ============== + Each PRU-ICSS instance is represented as its own node with the individual PRU + processor cores, the memories node, an INTC node and an MDIO node represented + as child nodes within this PRUSS node. This node shall be a child of the + corresponding interconnect bus nodes or target-module nodes. + + See ../../mfd/syscon.yaml for generic SysCon binding details. + + +properties: + $nodename: + pattern: "^(pruss|icssg)@[0-9a-f]+$" + + compatible: + enum: + - ti,am3356-pruss # for AM335x SoC family + - ti,am4376-pruss0 # for AM437x SoC family and PRUSS unit 0 + - ti,am4376-pruss1 # for AM437x SoC family and PRUSS unit 1 + - ti,am5728-pruss # for AM57xx SoC family + - ti,k2g-pruss # for 66AK2G SoC family + - ti,am654-icssg # for K3 AM65x SoC family + - ti,j721e-icssg # for K3 J721E SoC family + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: + maxItems: 1 + + power-domains: + description: | + This property is as per sci-pm-domain.txt. + +patternProperties: + + memories@[a-f0-9]+$: + description: | + The various Data RAMs within a single PRU-ICSS unit are represented as a + single node with the name 'memories'. + + type: object + + properties: + reg: + minItems: 2 # On AM437x one of two PRUSS units don't contain Shared RAM. + maxItems: 3 + items: + - description: Address and size of the Data RAM0. + - description: Address and size of the Data RAM1. + - description: | + Address and size of the Shared Data RAM. Note that on AM437x one + of two PRUSS units don't contain Shared RAM, while the second one + has it. + + reg-names: + minItems: 2 + maxItems: 3 + items: + - const: dram0 + - const: dram1 + - const: shrdram2 + + required: + - reg + - reg-names + + additionalProperties: false + + cfg@[a-f0-9]+$: + description: | + PRU-ICSS configuration space. CFG sub-module represented as a SysCon. + + type: object + + properties: + compatible: + items: + - const: ti,pruss-cfg + - const: syscon + + reg: + maxItems: 1 + + additionalProperties: false + + iep@[a-f0-9]+$: + description: | + Industrial Ethernet Peripheral to manage/generate Industrial Ethernet + functions such as time stamping. Each PRUSS has either 1 IEP (on AM335x, + AM437x, AM57xx & 66AK2G SoCs) or 2 IEPs (on K3 AM65x & J721E SoCs ). IEP + is used for creating PTP clocks and generating PPS signals. + + type: object + + mii-rt@[a-f0-9]+$: + description: | + Real-Time Ethernet to support multiple industrial communication protocols. + MII-RT sub-module represented as a SysCon. + + type: object + + properties: + compatible: + items: + - const: ti,pruss-mii + - const: syscon + + reg: + maxItems: 1 + + additionalProperties: false + + mii-g-rt@[a-f0-9]+$: + description: | + The Real-time Media Independent Interface to support multiple industrial + communication protocols (G stands for Gigabit). MII-G-RT sub-module + represented as a SysCon. + + type: object + + properties: + compatible: + items: + - const: ti,pruss-mii-g + - const: syscon + + reg: + maxItems: 1 + + additionalProperties: false + + interrupt-controller@[a-f0-9]+$: + description: | + PRUSS INTC Node. Each PRUSS has a single interrupt controller instance + that is common to all the PRU cores. This should be represented as an + interrupt-controller node. + + type: object + + mdio@[a-f0-9]+$: + description: | + MDIO Node. Each PRUSS has an MDIO module that can be used to control + external PHYs. The MDIO module used within the PRU-ICSS is an instance of + the MDIO Controller used in TI Davinci SoCs. + + allOf: + - $ref: /schemas/net/ti,davinci-mdio.yaml# + + type: object + + "^(pru|rtu|txpru)@[0-9a-f]+$": + description: | + PRU Node. Each PRUSS has dual PRU cores, each represented as a RemoteProc + device through a PRU child node each. Each node can optionally be rendered + inactive by using the standard DT string property, "status". The ICSSG IP + present on K3 SoCs have additional auxiliary PRU cores with slightly + different IP integration. + + type: object + +required: + - compatible + - reg + - ranges + +additionalProperties: false + +# Due to inability of correctly verifying sub-nodes with an @address through +# the "required" list, the required sub-nodes below are commented out for now. + +#required: +# - memories +# - interrupt-controller +# - pru + +if: + properties: + compatible: + contains: + enum: + - ti,k2g-pruss + - ti,am654-icssg + - ti,j721e-icssg +then: + required: + - power-domains + +examples: + - | + + /* Example 1 AM33xx PRU-ICSS */ + pruss: pruss@0 { + compatible = "ti,am3356-pruss"; + reg = <0x0 0x80000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pruss_mem: memories@0 { + reg = <0x0 0x2000>, + <0x2000 0x2000>, + <0x10000 0x3000>; + reg-names = "dram0", "dram1", "shrdram2"; + }; + + pruss_cfg: cfg@26000 { + compatible = "ti,pruss-cfg", "syscon"; + reg = <0x26000 0x2000>; + }; + + pruss_mii_rt: mii-rt@32000 { + compatible = "ti,pruss-mii", "syscon"; + reg = <0x32000 0x58>; + }; + + pruss_mdio: mdio@32400 { + compatible = "ti,davinci_mdio"; + reg = <0x32400 0x90>; + clocks = <&dpll_core_m4_ck>; + clock-names = "fck"; + bus_freq = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + - | + + /* Example 2 AM43xx PRU-ICSS with PRUSS1 node */ + #include + pruss1: pruss@0 { + compatible = "ti,am4376-pruss1"; + reg = <0x0 0x40000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pruss1_mem: memories@0 { + reg = <0x0 0x2000>, + <0x2000 0x2000>, + <0x10000 0x8000>; + reg-names = "dram0", "dram1", "shrdram2"; + }; + + pruss1_cfg: cfg@26000 { + compatible = "ti,pruss-cfg", "syscon"; + reg = <0x26000 0x2000>; + }; + + pruss1_mii_rt: mii-rt@32000 { + compatible = "ti,pruss-mii", "syscon"; + reg = <0x32000 0x58>; + }; + + pruss1_mdio: mdio@32400 { + compatible = "ti,davinci_mdio"; + reg = <0x32400 0x90>; + clocks = <&dpll_core_m4_ck>; + clock-names = "fck"; + bus_freq = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + +... From dc1129564a0147feb459159fd220ae22357e2eb6 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:34 -0700 Subject: [PATCH 072/131] soc: ti: pruss: Add a platform driver for PRUSS in TI SoCs The Programmable Real-Time Unit - Industrial Communication Subsystem (PRU-ICSS) is present on various TI SoCs such as AM335x or AM437x or the Keystone 66AK2G. Each SoC can have one or more PRUSS instances that may or may not be identical. For example, AM335x SoCs have a single PRUSS, while AM437x has two PRUSS instances PRUSS1 and PRUSS0, with the PRUSS0 being a cut-down version of the PRUSS1. The PRUSS consists of dual 32-bit RISC cores called the Programmable Real-Time Units (PRUs), some shared, data and instruction memories, some internal peripheral modules, and an interrupt controller. The programmable nature of the PRUs provide flexibility to implement custom peripheral interfaces, fast real-time responses, or specialized data handling. The PRU-ICSS functionality is achieved through three different platform drivers addressing a specific portion of the PRUSS. Some sub-modules of the PRU-ICSS IP reuse some of the existing drivers (like davinci mdio driver or the generic syscon driver). This design provides flexibility in representing the different modules of PRUSS accordingly, and at the same time allowing the PRUSS driver to add some instance specific configuration within an SoC. The PRUSS platform driver deals with the overall PRUSS and is used for managing the subsystem level resources like various memories and the CFG module. It is responsible for the creation and deletion of the platform devices for the child PRU devices and other child devices (like Interrupt Controller, MDIO node and some syscon nodes) so that they can be managed by specific platform drivers. The PRUSS interrupt controller is managed by an irqchip driver, while the individual PRU RISC cores are managed by a PRU remoteproc driver. The driver currently supports the AM335x SoC, and support for other TI SoCs will be added in subsequent patches. Signed-off-by: Suman Anna Signed-off-by: Andrew F. Davis Signed-off-by: Tero Kristo Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 11 +++ drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 147 +++++++++++++++++++++++++++++++++++ include/linux/pruss_driver.h | 48 ++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/linux/pruss_driver.h diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index e192fb788836..b934bc341d26 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -101,6 +101,17 @@ config TI_K3_SOCINFO platforms to provide information about the SoC family and variant to user space. +config TI_PRUSS + tristate "TI PRU-ICSS Subsystem Platform drivers" + depends on SOC_AM33XX + select MFD_SYSCON + help + TI PRU-ICSS Subsystem platform specific support. + + Say Y or M here to support the Programmable Realtime Unit (PRU) + processors on various TI SoCs. It's safe to say N here if you're + not interested in the PRU or if you are unsure. + endif # SOC_TI config TI_SCI_INTA_MSI_DOMAIN diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index 1110e5c98685..18129aa557df 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o obj-$(CONFIG_TI_K3_RINGACC) += k3-ringacc.o obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o +obj-$(CONFIG_TI_PRUSS) += pruss.o diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c new file mode 100644 index 000000000000..c071bb2e1c33 --- /dev/null +++ b/drivers/soc/ti/pruss.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PRU-ICSS platform driver for various TI SoCs + * + * Copyright (C) 2014-2020 Texas Instruments Incorporated - http://www.ti.com/ + * Author(s): + * Suman Anna + * Andrew F. Davis + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int pruss_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev_of_node(dev); + struct device_node *child; + struct pruss *pruss; + struct resource res; + int ret, i, index; + const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" }; + + ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(dev, "failed to set the DMA coherent mask"); + return ret; + } + + pruss = devm_kzalloc(dev, sizeof(*pruss), GFP_KERNEL); + if (!pruss) + return -ENOMEM; + + pruss->dev = dev; + + child = of_get_child_by_name(np, "memories"); + if (!child) { + dev_err(dev, "%pOF is missing its 'memories' node\n", child); + return -ENODEV; + } + + for (i = 0; i < ARRAY_SIZE(mem_names); i++) { + index = of_property_match_string(child, "reg-names", + mem_names[i]); + if (index < 0) { + of_node_put(child); + return index; + } + + if (of_address_to_resource(child, index, &res)) { + of_node_put(child); + return -EINVAL; + } + + pruss->mem_regions[i].va = devm_ioremap(dev, res.start, + resource_size(&res)); + if (!pruss->mem_regions[i].va) { + dev_err(dev, "failed to parse and map memory resource %d %s\n", + i, mem_names[i]); + of_node_put(child); + return -ENOMEM; + } + pruss->mem_regions[i].pa = res.start; + pruss->mem_regions[i].size = resource_size(&res); + + dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n", + mem_names[i], &pruss->mem_regions[i].pa, + pruss->mem_regions[i].size, pruss->mem_regions[i].va); + } + of_node_put(child); + + platform_set_drvdata(pdev, pruss); + + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "couldn't enable module\n"); + pm_runtime_put_noidle(dev); + goto rpm_disable; + } + + child = of_get_child_by_name(np, "cfg"); + if (!child) { + dev_err(dev, "%pOF is missing its 'cfg' node\n", child); + ret = -ENODEV; + goto rpm_put; + } + + pruss->cfg_regmap = syscon_node_to_regmap(child); + of_node_put(child); + if (IS_ERR(pruss->cfg_regmap)) { + ret = -ENODEV; + goto rpm_put; + } + + ret = devm_of_platform_populate(dev); + if (ret) { + dev_err(dev, "failed to register child devices\n"); + goto rpm_put; + } + + return 0; + +rpm_put: + pm_runtime_put_sync(dev); +rpm_disable: + pm_runtime_disable(dev); + return ret; +} + +static int pruss_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + devm_of_platform_depopulate(dev); + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + + return 0; +} + +static const struct of_device_id pruss_of_match[] = { + { .compatible = "ti,am3356-pruss" }, + {}, +}; +MODULE_DEVICE_TABLE(of, pruss_of_match); + +static struct platform_driver pruss_driver = { + .driver = { + .name = "pruss", + .of_match_table = pruss_of_match, + }, + .probe = pruss_probe, + .remove = pruss_remove, +}; +module_platform_driver(pruss_driver); + +MODULE_AUTHOR("Suman Anna "); +MODULE_DESCRIPTION("PRU-ICSS Subsystem Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h new file mode 100644 index 000000000000..0701fe1953dd --- /dev/null +++ b/include/linux/pruss_driver.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * PRU-ICSS sub-system specific definitions + * + * Copyright (C) 2014-2020 Texas Instruments Incorporated - http://www.ti.com/ + * Suman Anna + */ + +#ifndef _PRUSS_DRIVER_H_ +#define _PRUSS_DRIVER_H_ + +#include + +/* + * enum pruss_mem - PRUSS memory range identifiers + */ +enum pruss_mem { + PRUSS_MEM_DRAM0 = 0, + PRUSS_MEM_DRAM1, + PRUSS_MEM_SHRD_RAM2, + PRUSS_MEM_MAX, +}; + +/** + * struct pruss_mem_region - PRUSS memory region structure + * @va: kernel virtual address of the PRUSS memory region + * @pa: physical (bus) address of the PRUSS memory region + * @size: size of the PRUSS memory region + */ +struct pruss_mem_region { + void __iomem *va; + phys_addr_t pa; + size_t size; +}; + +/** + * struct pruss - PRUSS parent structure + * @dev: pruss device pointer + * @cfg_regmap: regmap for config region + * @mem_regions: data for each of the PRUSS memory regions + */ +struct pruss { + struct device *dev; + struct regmap *cfg_regmap; + struct pruss_mem_region mem_regions[PRUSS_MEM_MAX]; +}; + +#endif /* _PRUSS_DRIVER_H_ */ From 78251639d376a4ea1a795a4f3dcd985fcdf9aed3 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:35 -0700 Subject: [PATCH 073/131] soc: ti: pruss: Add support for PRU-ICSSs on AM437x SoCs The AM437x SoCs have two different PRU-ICSS subsystems: PRU-ICSS1 and a smaller PRU-ICSS0. Enhance the PRUSS platform driver to support both the PRU-ICSS sub-systems on these SoCs. The PRU-ICSS1 on AM437x is very similar to the PRU-ICSS on AM33xx except for few minor differences - increased Instruction RAM, increased Shared Data RAM2, and 1 less interrupt (PRUSS host interrupt 7 which is redirected to the other PRUSS) towards the MPU INTC. The PRU-ICSS0 is a cut-down version of the IP, with less DRAM per PRU, no Shared DRAM etc. It also does not have direct access to L3 bus regions, there is a single interface to L3 for both PRUSS0 and PRUSS1, and it would have to go through the PRUSS1's interface. The PRUSS_SYSCFG register is reserved on PRUSS0, so any external access requires the programming the corresponding PRUSS_SYSCFG register in PRUSS1. It does have its own dedicated I/O lines though. Note that this instance does not support any PRU Ethernet related use cases. The adaptation uses SoC-specific compatibles in the driver and uses a newly introduced pruss_match_private_data structure and the pruss_get_private_data() function to retrieve a PRUSS instance specific data using a device-name based lookup logic. The reset and the L3 external access are managed by the parent interconnect ti-sysc bus driver so that PRUSS1 and PRUSS0 can be independently supported. Signed-off-by: Suman Anna Signed-off-by: Andrew F. Davis Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 2 +- drivers/soc/ti/pruss.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index b934bc341d26..40d6a222275f 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -103,7 +103,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX + depends on SOC_AM33XX || SOC_AM43XX select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index c071bb2e1c33..04938ba6b150 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -17,6 +17,14 @@ #include #include +/** + * struct pruss_private_data - PRUSS driver private data + * @has_no_sharedram: flag to indicate the absence of PRUSS Shared Data RAM + */ +struct pruss_private_data { + bool has_no_sharedram; +}; + static int pruss_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -25,8 +33,15 @@ static int pruss_probe(struct platform_device *pdev) struct pruss *pruss; struct resource res; int ret, i, index; + const struct pruss_private_data *data; const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" }; + data = of_device_get_match_data(&pdev->dev); + if (IS_ERR(data)) { + dev_err(dev, "missing private data\n"); + return -ENODEV; + } + ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); if (ret) { dev_err(dev, "failed to set the DMA coherent mask"); @@ -45,7 +60,14 @@ static int pruss_probe(struct platform_device *pdev) return -ENODEV; } - for (i = 0; i < ARRAY_SIZE(mem_names); i++) { + for (i = 0; i < PRUSS_MEM_MAX; i++) { + /* + * On AM437x one of two PRUSS units don't contain Shared RAM, + * skip it + */ + if (data && data->has_no_sharedram && i == PRUSS_MEM_SHRD_RAM2) + continue; + index = of_property_match_string(child, "reg-names", mem_names[i]); if (index < 0) { @@ -126,8 +148,19 @@ static int pruss_remove(struct platform_device *pdev) return 0; } +/* instance-specific driver private data */ +static const struct pruss_private_data am437x_pruss1_data = { + .has_no_sharedram = false, +}; + +static const struct pruss_private_data am437x_pruss0_data = { + .has_no_sharedram = true, +}; + static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am3356-pruss" }, + { .compatible = "ti,am4376-pruss0", .data = &am437x_pruss0_data, }, + { .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From ae19b8a145252d35d4d31d53799f823fe3e2ccbf Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:35 -0700 Subject: [PATCH 074/131] soc: ti: pruss: Add support for PRU-ICSS subsystems on AM57xx SoCs The AM57xx family of SoCs supports two PRU-ICSS instances, each of which has two PRU processor cores. The two PRU-ICSS instances are identical to each other, and are very similar to the PRU-ICSS1 of AM33xx/AM43xx except for a few minor differences like the RAM sizes and the number of interrupts coming into the MPU INTC. They do not have a programmable module reset line unlike those present on AM33xx/AM43xx SoCs. The modules are reset just like any other IP with the SoC's global cold/warm resets. Each PRU-ICSS's INTC is also preceded by a Crossbar that enables multiple external events to be routed to a specific number of input interrupt events. Any interrupt event directed towards PRUSS needs this crossbar to be setup properly on the firmware side. The existing PRUSS platform driver has been enhanced to support these AM57xx PRU-ICSS instances through new AM57xx specific compatible for properly probing and booting all the different PRU cores in each PRU-ICSS processor subsystem. A build dependency with SOC_DRA7XX is also added to enable the driver to be built in AM57xx-only configuration (there is no separate Kconfig option for AM57xx vs DRA7xx). Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 2 +- drivers/soc/ti/pruss.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 40d6a222275f..99dbc14e0d3e 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -103,7 +103,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX || SOC_AM43XX + depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 04938ba6b150..5df4caa4bcf4 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -161,6 +161,7 @@ static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am3356-pruss" }, { .compatible = "ti,am4376-pruss0", .data = &am437x_pruss0_data, }, { .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, }, + { .compatible = "ti,am5728-pruss" }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From 3227c8daac3c34bcb7cef374c57c83844851c31e Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:36 -0700 Subject: [PATCH 075/131] soc: ti: pruss: Add support for PRU-ICSS subsystems on 66AK2G SoC The 66AK2G SoC supports two PRU-ICSS instances, named PRUSS0 and PRUSS1, each of which has two PRU processor cores. The two PRU-ICSS instances are identical to each other with few minor SoC integration differences, and are very similar to the PRU-ICSS1 of AM57xx/AM43xx. The Shared Data RAM size is larger and the number of interrupts coming into MPU INTC is like the instances on AM437x. There are also few other differences attributing to integration in Keystone architecture (like no SYSCFG register or PRCM handshake protocols). Other IP level differences include different constant table, differences in system event interrupt input sources etc. They also do not have a programmable module reset line like those present on AM33xx/AM43xx SoCs. The modules are reset just like any other IP with the SoC's global cold/warm resets. The existing PRUSS platform driver has been enhanced to support these 66AK2G PRU-ICSS instances through new 66AK2G specific compatible for properly probing and booting all the different PRU cores in each PRU-ICSS processor subsystem. A build dependency with ARCH_KEYSTONE is added to enable the driver to be built in K2G-only configuration. Signed-off-by: Andrew F. Davis Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 2 +- drivers/soc/ti/pruss.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 99dbc14e0d3e..c29034321b50 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -103,7 +103,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX + depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 5df4caa4bcf4..d5f128ec1e31 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -162,6 +162,7 @@ static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am4376-pruss0", .data = &am437x_pruss0_data, }, { .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, }, { .compatible = "ti,am5728-pruss" }, + { .compatible = "ti,k2g-pruss" }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From 6530cd9b201db9a2f78c53a76b2dff4a5bf072fa Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:36 -0700 Subject: [PATCH 076/131] soc: ti: pruss: Enable support for ICSSG subsystems on K3 AM65x SoCs The K3 AM65x family of SoCs have the next generation of the PRU-ICSS processor subsystem capable of supporting Gigabit Ethernet, and is commonly referred to as ICSSG. These SoCs contain typically three ICSSG instances named ICSSG0, ICSSG1 and ICSSG2. The three ICSSGs are identical to each other for the most part with minor SoC integration differences and capabilities. The ICSSG2 supports slightly enhanced features like SGMII mode Ethernet, while the ICSS0 and ICSSG1 instances are limited to MII mode only. The ICSSGs on K3 AM65x SoCs are in general super-sets of the PRUSS on the AM57xx/66AK2G SoCs. They include two additional auxiliary PRU cores called RTUs and few other additional sub-modules. The interrupt integration is also different on the K3 AM65x SoCs and are propagated through various SoC-level Interrupt Router and Interrupt Aggregator blocks. Other IP level differences include different constant tables, differences in system event interrupt input sources etc. They also do not have a programmable module reset line like those present on AM33xx/AM43xx SoCs. The modules are reset just like any other IP with the SoC's global cold/warm resets. The existing pruss platform driver has been updated to support these new ICSSG instances through new AM65x specific compatibles. A build dependency with ARCH_K3 is added to enable building all the existing PRUSS platform drivers for this ARMv8 platform. Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 2 +- drivers/soc/ti/pruss.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index c29034321b50..f5b82ffa637b 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -103,7 +103,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE + depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index d5f128ec1e31..ccc9783c123a 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -163,6 +163,7 @@ static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, }, { .compatible = "ti,am5728-pruss" }, { .compatible = "ti,k2g-pruss" }, + { .compatible = "ti,am654-icssg" }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From 557003a98fb89e4841a8d9522c023ada145056d2 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:37 -0700 Subject: [PATCH 077/131] soc: ti: pruss: Enable support for ICSSG subsystems on K3 J721E SoCs The K3 J721E family of SoCs have a revised version of the PRU-ICSS (ICSSG) processor subsystem present on K3 AM65x SoCs. These SoCs contain typically two ICSSG instances named ICSSG0 and ICSSG1. The two ICSSGs are identical to each other for the most part with minor SoC integration differences and capabilities. The ICSSG1 supports slightly enhanced features like SGMII mode Ethernet, while the ICSSG0 instance is limited to MII mode only. There is no change in the Interrupt Controller w.r.t AM65x. All other integration aspects are very similar to the ICSSGs on AM65x SoCs. The existing pruss platform driver has been updated to support these new ICSSG instances through new J721E specific compatibles. Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/pruss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index ccc9783c123a..37df543998ef 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -164,6 +164,7 @@ static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am5728-pruss" }, { .compatible = "ti,k2g-pruss" }, { .compatible = "ti,am654-icssg" }, + { .compatible = "ti,j721e-icssg" }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From efa5c01cd7ee20421a92ffe9b4aae7dfed385eeb Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 11 Sep 2020 21:47:08 -0700 Subject: [PATCH 078/131] soc: ti: ti_sci_pm_domains: switch to use multiple genpds instead of one Current implementation of the genpd support over TI SCI uses a single genpd across the whole SoC, and attaches multiple devices to this. This solution has its drawbacks, like it is currently impossible to attach more than one power domain to a device; the core genpd implementation requires one genpd per power-domain entry in DT for a single device. Also, some devices like USB apparently require their own genpd during probe time, the current shared approach in use does not work at all. Switch the implementation over to use a single genpd per power domain entry in DT. The domains are registered with the onecell approach, but we also add our own xlate service due to recent introduction of the extended flag for TI SCI PM domains; genpd core xlate service requires a single cell per powerdomain, but we are using two cells. Signed-off-by: Tero Kristo Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/ti_sci_pm_domains.c | 251 ++++++++++++++--------------- 1 file changed, 121 insertions(+), 130 deletions(-) diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c index 8c2a2f23982c..af2126d2b2ff 100644 --- a/drivers/soc/ti/ti_sci_pm_domains.c +++ b/drivers/soc/ti/ti_sci_pm_domains.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -18,150 +17,95 @@ #include /** - * struct ti_sci_genpd_dev_data: holds data needed for every device attached - * to this genpd - * @idx: index of the device that identifies it with the system - * control processor. - * @exclusive: Permissions for exclusive request or shared request of the - * device. + * struct ti_sci_genpd_provider: holds common TI SCI genpd provider data + * @ti_sci: handle to TI SCI protocol driver that provides ops to + * communicate with system control processor. + * @dev: pointer to dev for the driver for devm allocs + * @pd_list: list of all the power domains on the device + * @data: onecell data for genpd core */ -struct ti_sci_genpd_dev_data { - int idx; - u8 exclusive; +struct ti_sci_genpd_provider { + const struct ti_sci_handle *ti_sci; + struct device *dev; + struct list_head pd_list; + struct genpd_onecell_data data; }; /** * struct ti_sci_pm_domain: TI specific data needed for power domain - * @ti_sci: handle to TI SCI protocol driver that provides ops to - * communicate with system control processor. - * @dev: pointer to dev for the driver for devm allocs + * @idx: index of the device that identifies it with the system + * control processor. + * @exclusive: Permissions for exclusive request or shared request of the + * device. * @pd: generic_pm_domain for use with the genpd framework + * @node: link for the genpd list + * @parent: link to the parent TI SCI genpd provider */ struct ti_sci_pm_domain { - const struct ti_sci_handle *ti_sci; - struct device *dev; + int idx; + u8 exclusive; struct generic_pm_domain pd; + struct list_head node; + struct ti_sci_genpd_provider *parent; }; #define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd) -/** - * ti_sci_dev_id(): get prepopulated ti_sci id from struct dev - * @dev: pointer to device associated with this genpd - * - * Returns device_id stored from ti,sci_id property +/* + * ti_sci_pd_power_off(): genpd power down hook + * @domain: pointer to the powerdomain to power off */ -static int ti_sci_dev_id(struct device *dev) +static int ti_sci_pd_power_off(struct generic_pm_domain *domain) { - struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev); - struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data; + struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain); + const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; - return sci_dev_data->idx; + return ti_sci->ops.dev_ops.put_device(ti_sci, pd->idx); } -static u8 is_ti_sci_dev_exclusive(struct device *dev) -{ - struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev); - struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data; - - return sci_dev_data->exclusive; -} - -/** - * ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle - * @dev: pointer to device associated with this genpd - * - * Returns ti_sci_handle to be used to communicate with system - * control processor. +/* + * ti_sci_pd_power_on(): genpd power up hook + * @domain: pointer to the powerdomain to power on */ -static const struct ti_sci_handle *ti_sci_dev_to_sci_handle(struct device *dev) +static int ti_sci_pd_power_on(struct generic_pm_domain *domain) { - struct generic_pm_domain *pd = pd_to_genpd(dev->pm_domain); - struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(pd); + struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain); + const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; - return ti_sci_genpd->ti_sci; -} - -/** - * ti_sci_dev_start(): genpd device start hook called to turn device on - * @dev: pointer to device associated with this genpd to be powered on - */ -static int ti_sci_dev_start(struct device *dev) -{ - const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev); - int idx = ti_sci_dev_id(dev); - - if (is_ti_sci_dev_exclusive(dev)) - return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci, idx); + if (pd->exclusive) + return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci, + pd->idx); else - return ti_sci->ops.dev_ops.get_device(ti_sci, idx); + return ti_sci->ops.dev_ops.get_device(ti_sci, pd->idx); } -/** - * ti_sci_dev_stop(): genpd device stop hook called to turn device off - * @dev: pointer to device associated with this genpd to be powered off +/* + * ti_sci_pd_xlate(): translation service for TI SCI genpds + * @genpdspec: DT identification data for the genpd + * @data: genpd core data for all the powerdomains on the device */ -static int ti_sci_dev_stop(struct device *dev) +static struct generic_pm_domain *ti_sci_pd_xlate( + struct of_phandle_args *genpdspec, + void *data) { - const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev); - int idx = ti_sci_dev_id(dev); + struct genpd_onecell_data *genpd_data = data; + unsigned int idx = genpdspec->args[0]; - return ti_sci->ops.dev_ops.put_device(ti_sci, idx); -} + if (genpdspec->args_count < 2) + return ERR_PTR(-EINVAL); -static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - struct device_node *np = dev->of_node; - struct of_phandle_args pd_args; - struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(domain); - const struct ti_sci_handle *ti_sci = ti_sci_genpd->ti_sci; - struct ti_sci_genpd_dev_data *sci_dev_data; - struct generic_pm_domain_data *genpd_data; - int idx, ret = 0; + if (idx >= genpd_data->num_domains) { + pr_err("%s: invalid domain index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } - ret = of_parse_phandle_with_args(np, "power-domains", - "#power-domain-cells", 0, &pd_args); - if (ret < 0) - return ret; + if (!genpd_data->domains[idx]) + return ERR_PTR(-ENOENT); - if (pd_args.args_count != 1 && pd_args.args_count != 2) - return -EINVAL; + genpd_to_ti_sci_pd(genpd_data->domains[idx])->exclusive = + genpdspec->args[1]; - idx = pd_args.args[0]; - - /* - * Check the validity of the requested idx, if the index is not valid - * the PMMC will return a NAK here and we will not allocate it. - */ - ret = ti_sci->ops.dev_ops.is_valid(ti_sci, idx); - if (ret) - return -EINVAL; - - sci_dev_data = kzalloc(sizeof(*sci_dev_data), GFP_KERNEL); - if (!sci_dev_data) - return -ENOMEM; - - sci_dev_data->idx = idx; - /* Enable the exclusive permissions by default */ - sci_dev_data->exclusive = TI_SCI_PD_EXCLUSIVE; - if (pd_args.args_count == 2) - sci_dev_data->exclusive = pd_args.args[1] & 0x1; - - genpd_data = dev_gpd_data(dev); - genpd_data->data = sci_dev_data; - - return 0; -} - -static void ti_sci_pd_detach_dev(struct generic_pm_domain *domain, - struct device *dev) -{ - struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev); - struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data; - - kfree(sci_dev_data); - genpd_data->data = NULL; + return genpd_data->domains[idx]; } static const struct of_device_id ti_sci_pm_domain_matches[] = { @@ -173,33 +117,80 @@ MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches); static int ti_sci_pm_domain_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct ti_sci_pm_domain *ti_sci_pd; + struct ti_sci_genpd_provider *pd_provider; + struct ti_sci_pm_domain *pd; + struct device_node *np = NULL; + struct of_phandle_args args; int ret; + u32 max_id = 0; + int index; - ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL); - if (!ti_sci_pd) + pd_provider = devm_kzalloc(dev, sizeof(*pd_provider), GFP_KERNEL); + if (!pd_provider) return -ENOMEM; - ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev); - if (IS_ERR(ti_sci_pd->ti_sci)) - return PTR_ERR(ti_sci_pd->ti_sci); + pd_provider->ti_sci = devm_ti_sci_get_handle(dev); + if (IS_ERR(pd_provider->ti_sci)) + return PTR_ERR(pd_provider->ti_sci); - ti_sci_pd->dev = dev; + pd_provider->dev = dev; - ti_sci_pd->pd.name = "ti_sci_pd"; + INIT_LIST_HEAD(&pd_provider->pd_list); - ti_sci_pd->pd.attach_dev = ti_sci_pd_attach_dev; - ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev; + /* Find highest device ID used for power domains */ + while (1) { + np = of_find_node_with_property(np, "power-domains"); + if (!np) + break; - ti_sci_pd->pd.dev_ops.start = ti_sci_dev_start; - ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop; + index = 0; - pm_genpd_init(&ti_sci_pd->pd, NULL, true); + while (1) { + ret = of_parse_phandle_with_args(np, "power-domains", + "#power-domain-cells", + index, &args); + if (ret) + break; - ret = of_genpd_add_provider_simple(np, &ti_sci_pd->pd); + if (args.args_count >= 1 && args.np == dev->of_node) { + if (args.args[0] > max_id) + max_id = args.args[0]; - return ret; + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) + return -ENOMEM; + + pd->pd.name = devm_kasprintf(dev, GFP_KERNEL, + "pd:%d", + args.args[0]); + if (!pd->pd.name) + return -ENOMEM; + + pd->pd.power_off = ti_sci_pd_power_off; + pd->pd.power_on = ti_sci_pd_power_on; + pd->idx = args.args[0]; + pd->parent = pd_provider; + + pm_genpd_init(&pd->pd, NULL, true); + + list_add(&pd->node, &pd_provider->pd_list); + } + index++; + } + } + + pd_provider->data.domains = + devm_kcalloc(dev, max_id + 1, + sizeof(*pd_provider->data.domains), + GFP_KERNEL); + + pd_provider->data.num_domains = max_id + 1; + pd_provider->data.xlate = ti_sci_pd_xlate; + + list_for_each_entry(pd, &pd_provider->pd_list, node) + pd_provider->data.domains[pd->idx] = &pd->pd; + + return of_genpd_add_provider_onecell(dev->of_node, &pd_provider->data); } static struct platform_driver ti_sci_pm_domains_driver = { From 71b610825f4b2130901c7b6fbf4063f03350bcb9 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 11 Sep 2020 21:47:08 -0700 Subject: [PATCH 079/131] firmware: ti_sci: allow frequency change for disabled clocks by default If a clock is disabled, its frequency should be allowed to change as it is no longer in use. Add a flag towards this to the firmware clock API handler routines. Acked-by: Nishanth Menon Tested-by: Tomi Valkeinen Signed-off-by: Tero Kristo Signed-off-by: Santosh Shilimkar --- drivers/firmware/ti_sci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 53cee17d0115..39890665a975 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -1124,7 +1124,8 @@ static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id, static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle, u32 dev_id, u32 clk_id) { - return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, + return ti_sci_set_clock_state(handle, dev_id, clk_id, + MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, MSG_CLOCK_SW_STATE_UNREQ); } @@ -1143,7 +1144,8 @@ static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle, static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle, u32 dev_id, u32 clk_id) { - return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, + return ti_sci_set_clock_state(handle, dev_id, clk_id, + MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, MSG_CLOCK_SW_STATE_AUTO); } From 25bafac9408f67873f03909401deecfb16974d84 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Fri, 11 Sep 2020 21:47:09 -0700 Subject: [PATCH 080/131] dt-bindings: soc: ti: Update TI PRUSS bindings regarding clock-muxes ICSS/ICSSG modules have an IEP clock mux that allow selection of internal IEP clock from 2 clock sources. ICSSG module has a CORE clock mux that allows selection of internal CORE clock from 2 clock sources. Add binding information for these 2 clock muxes. Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- .../devicetree/bindings/soc/ti/ti,pruss.yaml | 121 +++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml index 482beefaac1f..cf7dc83f724f 100644 --- a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml +++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml @@ -132,10 +132,99 @@ patternProperties: - const: ti,pruss-cfg - const: syscon + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + reg: maxItems: 1 - additionalProperties: false + ranges: + maxItems: 1 + + clocks: + type: object + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + patternProperties: + coreclk-mux@[a-f0-9]+$: + description: | + This is applicable only for ICSSG (K3 SoCs). The ICSSG modules + core clock can be set to one of the 2 sources: ICSSG_CORE_CLK or + ICSSG_ICLK. This node models this clock mux and should have the + name "coreclk-mux". + + type: object + + properties: + '#clock-cells': + const: 0 + + clocks: + items: + - description: ICSSG_CORE Clock + - description: ICSSG_ICLK Clock + + assigned-clocks: + maxItems: 1 + + assigned-clock-parents: + maxItems: 1 + description: | + Standard assigned-clocks-parents definition used for selecting + mux parent (one of the mux input). + + reg: + maxItems: 1 + + required: + - clocks + + additionalProperties: false + + iepclk-mux@[a-f0-9]+$: + description: | + The IEP module can get its clock from 2 sources: ICSSG_IEP_CLK or + CORE_CLK (OCP_CLK in older SoCs). This node models this clock + mux and should have the name "iepclk-mux". + + type: object + + properties: + '#clock-cells': + const: 0 + + clocks: + items: + - description: ICSSG_IEP Clock + - description: Core Clock (OCP Clock in older SoCs) + + assigned-clocks: + maxItems: 1 + + assigned-clock-parents: + maxItems: 1 + description: | + Standard assigned-clocks-parents definition used for selecting + mux parent (one of the mux input). + + reg: + maxItems: 1 + + required: + - clocks + + additionalProperties: false + + additionalProperties: false iep@[a-f0-9]+$: description: | @@ -259,7 +348,22 @@ examples: pruss_cfg: cfg@26000 { compatible = "ti,pruss-cfg", "syscon"; + #address-cells = <1>; + #size-cells = <1>; reg = <0x26000 0x2000>; + ranges = <0x00 0x26000 0x2000>; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + pruss_iepclk_mux: iepclk-mux@30 { + reg = <0x30>; + #clock-cells = <0>; + clocks = <&l3_gclk>, /* icss_iep */ + <&pruss_ocp_gclk>; /* icss_ocp */ + }; + }; }; pruss_mii_rt: mii-rt@32000 { @@ -298,7 +402,22 @@ examples: pruss1_cfg: cfg@26000 { compatible = "ti,pruss-cfg", "syscon"; + #address-cells = <1>; + #size-cells = <1>; reg = <0x26000 0x2000>; + ranges = <0x00 0x26000 0x2000>; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + pruss1_iepclk_mux: iepclk-mux@30 { + reg = <0x30>; + #clock-cells = <0>; + clocks = <&sysclk_div>, /* icss_iep */ + <&pruss_ocp_gclk>; /* icss_ocp */ + }; + }; }; pruss1_mii_rt: mii-rt@32000 { From ba59c9b43c86b2c2396acac94e41d946cbaec9fe Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Fri, 11 Sep 2020 21:47:10 -0700 Subject: [PATCH 081/131] soc: ti: pruss: support CORECLK_MUX and IEPCLK_MUX The IEPCLK_MUX is present on all SoCs whereas the CORECLK_MUX is present only on AM65x SoCs and J721E. Add support for both these CLK muxes. This allows the clock rates and clock parents for these to be controlled through DT leveraging the clk infrastructure for configuring the default parents and rates. Signed-off-by: Roger Quadros Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/pruss.c | 184 +++++++++++++++++++++++++++++++++-- include/linux/pruss_driver.h | 6 ++ 2 files changed, 183 insertions(+), 7 deletions(-) diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 37df543998ef..cc0b4ad7a3d3 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -8,6 +8,7 @@ * Andrew F. Davis */ +#include #include #include #include @@ -16,13 +17,150 @@ #include #include #include +#include +#include /** * struct pruss_private_data - PRUSS driver private data * @has_no_sharedram: flag to indicate the absence of PRUSS Shared Data RAM + * @has_core_mux_clock: flag to indicate the presence of PRUSS core clock */ struct pruss_private_data { bool has_no_sharedram; + bool has_core_mux_clock; +}; + +static void pruss_of_free_clk_provider(void *data) +{ + struct device_node *clk_mux_np = data; + + of_clk_del_provider(clk_mux_np); + of_node_put(clk_mux_np); +} + +static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux, + char *mux_name, struct device_node *clks_np) +{ + struct device_node *clk_mux_np; + struct device *dev = pruss->dev; + char *clk_mux_name; + unsigned int num_parents; + const char **parent_names; + void __iomem *reg; + u32 reg_offset; + int ret; + + clk_mux_np = of_get_child_by_name(clks_np, mux_name); + if (!clk_mux_np) { + dev_err(dev, "%pOF is missing its '%s' node\n", clks_np, + mux_name); + return -ENODEV; + } + + num_parents = of_clk_get_parent_count(clk_mux_np); + if (num_parents < 1) { + dev_err(dev, "mux-clock %pOF must have parents\n", clk_mux_np); + ret = -EINVAL; + goto put_clk_mux_np; + } + + parent_names = devm_kcalloc(dev, sizeof(*parent_names), num_parents, + GFP_KERNEL); + if (!parent_names) { + ret = -ENOMEM; + goto put_clk_mux_np; + } + + of_clk_parent_fill(clk_mux_np, parent_names, num_parents); + + clk_mux_name = devm_kasprintf(dev, GFP_KERNEL, "%s.%pOFn", + dev_name(dev), clk_mux_np); + if (!clk_mux_name) { + ret = -ENOMEM; + goto put_clk_mux_np; + } + + ret = of_property_read_u32(clk_mux_np, "reg", ®_offset); + if (ret) + goto put_clk_mux_np; + + reg = pruss->cfg_base + reg_offset; + + clk_mux = clk_register_mux(NULL, clk_mux_name, parent_names, + num_parents, 0, reg, 0, 1, 0, NULL); + if (IS_ERR(clk_mux)) { + ret = PTR_ERR(clk_mux); + goto put_clk_mux_np; + } + + ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux, + clk_mux); + if (ret) { + dev_err(dev, "failed to add clkmux unregister action %d", ret); + goto put_clk_mux_np; + } + + ret = of_clk_add_provider(clk_mux_np, of_clk_src_simple_get, clk_mux); + if (ret) + goto put_clk_mux_np; + + ret = devm_add_action_or_reset(dev, pruss_of_free_clk_provider, + clk_mux_np); + if (ret) { + dev_err(dev, "failed to add clkmux free action %d", ret); + goto put_clk_mux_np; + } + + return 0; + +put_clk_mux_np: + of_node_put(clk_mux_np); + return ret; +} + +static int pruss_clk_init(struct pruss *pruss, struct device_node *cfg_node) +{ + const struct pruss_private_data *data; + struct device_node *clks_np; + struct device *dev = pruss->dev; + int ret = 0; + + data = of_device_get_match_data(dev); + if (IS_ERR(data)) + return -ENODEV; + + clks_np = of_get_child_by_name(cfg_node, "clocks"); + if (!clks_np) { + dev_err(dev, "%pOF is missing its 'clocks' node\n", clks_np); + return -ENODEV; + } + + if (data && data->has_core_mux_clock) { + ret = pruss_clk_mux_setup(pruss, pruss->core_clk_mux, + "coreclk-mux", clks_np); + if (ret) { + dev_err(dev, "failed to setup coreclk-mux\n"); + goto put_clks_node; + } + } + + ret = pruss_clk_mux_setup(pruss, pruss->iep_clk_mux, "iepclk-mux", + clks_np); + if (ret) { + dev_err(dev, "failed to setup iepclk-mux\n"); + goto put_clks_node; + } + +put_clks_node: + of_node_put(clks_np); + + return ret; +} + +static struct regmap_config regmap_conf = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, }; static int pruss_probe(struct platform_device *pdev) @@ -114,21 +252,49 @@ static int pruss_probe(struct platform_device *pdev) goto rpm_put; } - pruss->cfg_regmap = syscon_node_to_regmap(child); - of_node_put(child); + if (of_address_to_resource(child, 0, &res)) { + ret = -ENOMEM; + goto node_put; + } + + pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res)); + if (!pruss->cfg_base) { + ret = -ENOMEM; + goto node_put; + } + + regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child, + (u64)res.start); + regmap_conf.max_register = resource_size(&res) - 4; + + pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base, + ®map_conf); + kfree(regmap_conf.name); if (IS_ERR(pruss->cfg_regmap)) { - ret = -ENODEV; - goto rpm_put; + dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n", + PTR_ERR(pruss->cfg_regmap)); + ret = PTR_ERR(pruss->cfg_regmap); + goto node_put; + } + + ret = pruss_clk_init(pruss, child); + if (ret) { + dev_err(dev, "failed to setup coreclk-mux\n"); + goto node_put; } ret = devm_of_platform_populate(dev); if (ret) { dev_err(dev, "failed to register child devices\n"); - goto rpm_put; + goto node_put; } + of_node_put(child); + return 0; +node_put: + of_node_put(child); rpm_put: pm_runtime_put_sync(dev); rpm_disable: @@ -157,14 +323,18 @@ static const struct pruss_private_data am437x_pruss0_data = { .has_no_sharedram = true, }; +static const struct pruss_private_data am65x_j721e_pruss_data = { + .has_core_mux_clock = true, +}; + static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am3356-pruss" }, { .compatible = "ti,am4376-pruss0", .data = &am437x_pruss0_data, }, { .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, }, { .compatible = "ti,am5728-pruss" }, { .compatible = "ti,k2g-pruss" }, - { .compatible = "ti,am654-icssg" }, - { .compatible = "ti,j721e-icssg" }, + { .compatible = "ti,am654-icssg", .data = &am65x_j721e_pruss_data, }, + { .compatible = "ti,j721e-icssg", .data = &am65x_j721e_pruss_data, }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h index 0701fe1953dd..ecfded30ed05 100644 --- a/include/linux/pruss_driver.h +++ b/include/linux/pruss_driver.h @@ -36,13 +36,19 @@ struct pruss_mem_region { /** * struct pruss - PRUSS parent structure * @dev: pruss device pointer + * @cfg_base: base iomap for CFG region * @cfg_regmap: regmap for config region * @mem_regions: data for each of the PRUSS memory regions + * @core_clk_mux: clk handle for PRUSS CORE_CLK_MUX + * @iep_clk_mux: clk handle for PRUSS IEP_CLK_MUX */ struct pruss { struct device *dev; + void __iomem *cfg_base; struct regmap *cfg_regmap; struct pruss_mem_region mem_regions[PRUSS_MEM_MAX]; + struct clk *core_clk_mux; + struct clk *iep_clk_mux; }; #endif /* _PRUSS_DRIVER_H_ */ From 4f02044123b23660cee9d9dbea74383a58eb46b5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Sep 2020 21:47:39 -0700 Subject: [PATCH 082/131] soc: ti: k3-socinfo: Add entry for J7200 Update K3 chipinfo driver to support new TI J7200 SoC. It's JTAG PARTNO is 0xBB6D. Reviewed-by: Lokesh Vutla Reviewed-by: Grygorii Strashko Signed-off-by: Peter Ujfalusi Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/k3-socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c index af0ba5288e58..bbbc2d2b7091 100644 --- a/drivers/soc/ti/k3-socinfo.c +++ b/drivers/soc/ti/k3-socinfo.c @@ -39,6 +39,7 @@ static const struct k3_soc_id { } k3_soc_ids[] = { { 0xBB5A, "AM65X" }, { 0xBB64, "J721E" }, + { 0xBB6D, "J7200" }, }; static int From 6259c8441c4de3f1727a0db61465a8dc8f340c05 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Sep 2020 21:47:39 -0700 Subject: [PATCH 083/131] dmaengine: ti: k3-udma-glue: Fix parameters for rx ring pair request The original commit mixed up the forward and completion ring IDs for the rx flow configuration. Acked-by: Vinod Koul Reviewed-by: Grygorii Strashko Fixes: 4927b1ab2047 ("dmaengine: ti: k3-udma: Switch to k3_ringacc_request_rings_pair") Signed-off-by: Peter Ujfalusi Signed-off-by: Santosh Shilimkar --- drivers/dma/ti/k3-udma-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c index 3a5d33ea5ebe..12da38a92218 100644 --- a/drivers/dma/ti/k3-udma-glue.c +++ b/drivers/dma/ti/k3-udma-glue.c @@ -579,8 +579,8 @@ static int k3_udma_glue_cfg_rx_flow(struct k3_udma_glue_rx_channel *rx_chn, /* request and cfg rings */ ret = k3_ringacc_request_rings_pair(rx_chn->common.ringacc, - flow_cfg->ring_rxq_id, flow_cfg->ring_rxfdq0_id, + flow_cfg->ring_rxq_id, &flow->ringrxfdq, &flow->ringrx); if (ret) { From e2314cf5af30d5e87cbf89fdef1a0fe4efee4552 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 8 Sep 2020 18:07:01 +0800 Subject: [PATCH 084/131] firmware: imx: scu-pd: ignore power domain not owned Should not register power domain that not owned by current partition. Alought power domains will not be registered when power on failure, we have to let CPU waste more cycles. Whether power on or owned check, both need communicate with SCU, but with owned check, we no need to run more code path to save CPU cycles. Signed-off-by: Peng Fan Reviewed-by: Leonard Crestez Signed-off-by: Shawn Guo --- drivers/firmware/imx/scu-pd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index af3d6d9ead28..946eea292b52 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -256,6 +257,9 @@ imx_scu_add_pm_domain(struct device *dev, int idx, struct imx_sc_pm_domain *sc_pd; int ret; + if (!imx_sc_rm_is_resource_owned(pm_ipc_handle, pd_ranges->rsrc + idx)) + return NULL; + sc_pd = devm_kzalloc(dev, sizeof(*sc_pd), GFP_KERNEL); if (!sc_pd) return ERR_PTR(-ENOMEM); From 6825f17c950ca5691a057fa71bb1b649b7434014 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 23 Jun 2020 15:33:57 +0100 Subject: [PATCH 085/131] firmware: smccc: Export both smccc functions We need to export both arm_smccc_1_1_get_conduit and arm_smccc_get_version to allow several modules make use of them. Arm FFA, Arm SCMI and PTP drivers are few drivers that are planning to use these functions. Let us export them in preparation to add support for SCMI as module. Link: https://lore.kernel.org/r/20200907195046.56615-2-sudeep.holla@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/smccc/smccc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c index 4e80921ee212..00c88b809c0c 100644 --- a/drivers/firmware/smccc/smccc.c +++ b/drivers/firmware/smccc/smccc.c @@ -24,8 +24,10 @@ enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void) return smccc_conduit; } +EXPORT_SYMBOL_GPL(arm_smccc_1_1_get_conduit); u32 arm_smccc_get_version(void) { return smccc_version; } +EXPORT_SYMBOL_GPL(arm_smccc_get_version); From 5a2f0a0bdf201e2183904b6217f9c74774c961a8 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 7 Sep 2020 12:00:04 +0100 Subject: [PATCH 086/131] firmware: arm_scmi: Move scmi bus init and exit calls into the driver In preparation to enable building scmi as a single module, let us move the scmi bus {de-,}initialisation call into the driver. The main reason for this is to keep it simple instead of maintaining it as separate modules and dealing with all possible initcall races and deferred probe handling. We can move it as separate modules if needed in future. Link: https://lore.kernel.org/r/20200907195046.56615-3-sudeep.holla@arm.com Tested-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/bus.c | 6 ++---- drivers/firmware/arm_scmi/common.h | 3 +++ drivers/firmware/arm_scmi/driver.c | 16 +++++++++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index db55c43a2cbd..1377ec76a45d 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -230,7 +230,7 @@ static void scmi_devices_unregister(void) bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister); } -static int __init scmi_bus_init(void) +int __init scmi_bus_init(void) { int retval; @@ -240,12 +240,10 @@ static int __init scmi_bus_init(void) return retval; } -subsys_initcall(scmi_bus_init); -static void __exit scmi_bus_exit(void) +void __exit scmi_bus_exit(void) { scmi_devices_unregister(); bus_unregister(&scmi_bus_type); ida_destroy(&scmi_bus_id); } -module_exit(scmi_bus_exit); diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 233700a42bff..a940c6cf1e51 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -156,6 +156,9 @@ void scmi_setup_protocol_implemented(const struct scmi_handle *handle, int scmi_base_protocol_init(struct scmi_handle *h); +int __init scmi_bus_init(void); +void __exit scmi_bus_exit(void); + /* SCMI Transport */ /** * struct scmi_chan_info - Structure representing a SCMI channel information diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index dbec34423f72..8f60c6a97cc3 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -929,7 +929,21 @@ static struct platform_driver scmi_driver = { .remove = scmi_remove, }; -module_platform_driver(scmi_driver); +static int __init scmi_driver_init(void) +{ + scmi_bus_init(); + + return platform_driver_register(&scmi_driver); +} +module_init(scmi_driver_init); + +static void __exit scmi_driver_exit(void) +{ + scmi_bus_exit(); + + platform_driver_unregister(&scmi_driver); +} +module_exit(scmi_driver_exit); MODULE_ALIAS("platform: arm-scmi"); MODULE_AUTHOR("Sudeep Holla "); From 1eaf18e35a783a007ef03e09f1dfc3de81eace7c Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 7 Sep 2020 12:06:01 +0100 Subject: [PATCH 087/131] firmware: arm_scmi: Move scmi protocols registration into the driver In preparation to enable building SCMI as a single module, let us move the SCMI protocol registration call into the driver. This enables us to also add unregistration of the SCMI protocols. The main reason for this is to keep it simple instead of maintaining it as separate modules and dealing with all possible initcall races and deferred probe handling. We can move it as separate modules if needed in future. Link: https://lore.kernel.org/r/20200907195046.56615-4-sudeep.holla@arm.com Tested-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/clock.c | 7 +------ drivers/firmware/arm_scmi/common.h | 21 +++++++++++++++++++++ drivers/firmware/arm_scmi/driver.c | 16 +++++++++++++++- drivers/firmware/arm_scmi/perf.c | 7 +------ drivers/firmware/arm_scmi/power.c | 7 +------ drivers/firmware/arm_scmi/reset.c | 7 +------ drivers/firmware/arm_scmi/sensors.c | 7 +------ drivers/firmware/arm_scmi/system.c | 7 +------ 8 files changed, 42 insertions(+), 37 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index a3b90be28009..c1cfe3ee3d55 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -364,9 +364,4 @@ static int scmi_clock_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_clock_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_CLOCK, - &scmi_clock_protocol_init); -} -subsys_initcall(scmi_clock_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_CLOCK, clock) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index a940c6cf1e51..37fb583f1bf5 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -159,6 +159,27 @@ int scmi_base_protocol_init(struct scmi_handle *h); int __init scmi_bus_init(void); void __exit scmi_bus_exit(void); +#define DECLARE_SCMI_REGISTER_UNREGISTER(func) \ + int __init scmi_##func##_register(void); \ + void __exit scmi_##func##_unregister(void) +DECLARE_SCMI_REGISTER_UNREGISTER(clock); +DECLARE_SCMI_REGISTER_UNREGISTER(perf); +DECLARE_SCMI_REGISTER_UNREGISTER(power); +DECLARE_SCMI_REGISTER_UNREGISTER(reset); +DECLARE_SCMI_REGISTER_UNREGISTER(sensors); +DECLARE_SCMI_REGISTER_UNREGISTER(system); + +#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(id, name) \ +int __init scmi_##name##_register(void) \ +{ \ + return scmi_protocol_register((id), &scmi_##name##_protocol_init); \ +} \ +\ +void __exit scmi_##name##_unregister(void) \ +{ \ + scmi_protocol_unregister((id)); \ +} + /* SCMI Transport */ /** * struct scmi_chan_info - Structure representing a SCMI channel information diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 8f60c6a97cc3..c5dea87edf8f 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -933,14 +933,28 @@ static int __init scmi_driver_init(void) { scmi_bus_init(); + scmi_clock_register(); + scmi_perf_register(); + scmi_power_register(); + scmi_reset_register(); + scmi_sensors_register(); + scmi_system_register(); + return platform_driver_register(&scmi_driver); } -module_init(scmi_driver_init); +subsys_initcall(scmi_driver_init); static void __exit scmi_driver_exit(void) { scmi_bus_exit(); + scmi_clock_unregister(); + scmi_perf_unregister(); + scmi_power_unregister(); + scmi_reset_unregister(); + scmi_sensors_unregister(); + scmi_system_unregister(); + platform_driver_unregister(&scmi_driver); } module_exit(scmi_driver_exit); diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index a3e7b1bfab00..ed475b40bd08 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -890,9 +890,4 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_perf_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_PERF, - &scmi_perf_protocol_init); -} -subsys_initcall(scmi_perf_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_PERF, perf) diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 32bcf5821ea9..1f37258e9bee 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -301,9 +301,4 @@ static int scmi_power_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_power_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_POWER, - &scmi_power_protocol_init); -} -subsys_initcall(scmi_power_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_POWER, power) diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index 4e2dc5fc43d9..f063cfe17e02 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -313,9 +313,4 @@ static int scmi_reset_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_reset_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_RESET, - &scmi_reset_protocol_init); -} -subsys_initcall(scmi_reset_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_RESET, reset) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 7d83680198de..9703cf6356a0 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -365,9 +365,4 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_sensors_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_SENSOR, - &scmi_sensors_protocol_init); -} -subsys_initcall(scmi_sensors_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SENSOR, sensors) diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c index aa1e74f066a0..283e12d5f24b 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -128,9 +128,4 @@ static int scmi_system_protocol_init(struct scmi_handle *handle) return 0; } -static int __init scmi_system_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_SYSTEM, - &scmi_system_protocol_init); -} -subsys_initcall(scmi_system_init); +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SYSTEM, system) From 66d90f6ecee755e9c19a119c9255e80091165498 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 7 Sep 2020 12:09:23 +0100 Subject: [PATCH 088/131] firmware: arm_scmi: Enable building as a single module Now, with all the plumbing in place to enable building scmi as a module instead of built-in modules, let us enable the same. Link: https://lore.kernel.org/r/20200907195046.56615-5-sudeep.holla@arm.com Tested-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/Kconfig | 2 +- drivers/firmware/Makefile | 2 +- drivers/firmware/arm_scmi/Makefile | 4 +++- include/linux/scmi_protocol.h | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index fbd785dd0513..afdbebba628a 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -7,7 +7,7 @@ menu "Firmware Drivers" config ARM_SCMI_PROTOCOL - bool "ARM System Control and Management Interface (SCMI) Message Protocol" + tristate "ARM System Control and Management Interface (SCMI) Message Protocol" depends on ARM || ARM64 || COMPILE_TEST depends on MAILBOX help diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 99510be9f5ed..5e013b6a3692 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o -obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/ +obj-y += arm_scmi/ obj-y += broadcom/ obj-y += meson/ obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 643f2320f976..bc0d54f8e861 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -1,9 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o scmi-bus-y = bus.o scmi-driver-y = driver.o notify.o scmi-transport-y = shmem.o scmi-transport-$(CONFIG_MAILBOX) += mailbox.o scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o +scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \ + $(scmi-transport-y) +obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 4b10093ad671..9cd312a1ff92 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -345,7 +345,7 @@ struct scmi_driver { #define to_scmi_driver(d) container_of(d, struct scmi_driver, driver) -#ifdef CONFIG_ARM_SCMI_PROTOCOL +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL) int scmi_driver_register(struct scmi_driver *driver, struct module *owner, const char *mod_name); void scmi_driver_unregister(struct scmi_driver *driver); From a32a43e00e6888c45ad93d989b225494bf21495d Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 2 Jun 2020 22:12:29 +0200 Subject: [PATCH 089/131] soc: qcom: socinfo: Add msm8992/4 and apq8094 SoC IDs Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20200602201229.322578-1-konradybcio@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 1fbdea81e1f1..0102bf254a9e 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -194,6 +194,7 @@ static const struct soc_id soc_id[] = { { 186, "MSM8674" }, { 194, "MSM8974PRO" }, { 206, "MSM8916" }, + { 207, "MSM8994" }, { 208, "APQ8074-AA" }, { 209, "APQ8074-AB" }, { 210, "APQ8074PRO" }, @@ -214,6 +215,8 @@ static const struct soc_id soc_id[] = { { 248, "MSM8216" }, { 249, "MSM8116" }, { 250, "MSM8616" }, + { 251, "MSM8992" }, + { 253, "APQ8094" }, { 291, "APQ8096" }, { 305, "MSM8996SG" }, { 310, "MSM8996AU" }, From ba34f977c333f96c8acd37ec30e232220399f5a5 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Tue, 15 Sep 2020 21:12:32 +0530 Subject: [PATCH 090/131] soc: qcom: apr: Fixup the error displayed on lookup failure APR client incorrectly prints out "ret" variable on pdr_add_lookup failure, it should be printing the error value returned by the lookup instead. Fixes: 8347356626028 ("soc: qcom: apr: Add avs/audio tracking functionality") Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20200915154232.27523-1-sibis@codeaurora.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/apr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index 1f35b097c635..7abfc8c4fdc7 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -328,7 +328,7 @@ static int of_apr_add_pd_lookups(struct device *dev) pds = pdr_add_lookup(apr->pdr, service_name, service_path); if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) { - dev_err(dev, "pdr add lookup failed: %d\n", ret); + dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds)); return PTR_ERR(pds); } } From 1b4298f000064cc20540a565d249914c60597550 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 11 Sep 2020 16:43:52 +0900 Subject: [PATCH 091/131] soc: renesas: r8a779a0-sysc: Add r8a779a0 support Add support for R-Car V3U (R8A779A0) SoC power areas and register access, because register specification differs from R-Car Gen2/3. Inspired by patches in the BSP by Tho Vu. Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/1599810232-29035-5-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 4 + drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/r8a779a0-sysc.c | 448 ++++++++++++++++++++++++++++ 3 files changed, 453 insertions(+) create mode 100644 drivers/soc/renesas/r8a779a0-sysc.c diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 6efa9d0b67d9..b70bbc38efc6 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -247,6 +247,7 @@ config ARCH_R8A77970 config ARCH_R8A779A0 bool "ARM64 Platform support for R-Car V3U" select ARCH_RCAR_GEN3 + select SYSC_R8A779A0 help This enables support for the Renesas R-Car V3U SoC. @@ -338,6 +339,9 @@ config SYSC_R8A77970 bool "System Controller support for R-Car V3M" if COMPILE_TEST select SYSC_RCAR +config SYSC_R8A779A0 + bool "System Controller support for R-Car V3U" if COMPILE_TEST + config SYSC_RMOBILE bool "System Controller support for R-Mobile" if COMPILE_TEST diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 10a399fc486a..9b29bed2a597 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o obj-$(CONFIG_SYSC_R8A77990) += r8a77990-sysc.o obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o +obj-$(CONFIG_SYSC_R8A779A0) += r8a779a0-sysc.o ifdef CONFIG_SMP obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o endif diff --git a/drivers/soc/renesas/r8a779a0-sysc.c b/drivers/soc/renesas/r8a779a0-sysc.c new file mode 100644 index 000000000000..d464ffa1be33 --- /dev/null +++ b/drivers/soc/renesas/r8a779a0-sysc.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas R-Car V3U System Controller + * + * Copyright (C) 2020 Renesas Electronics Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Power Domain flags + */ +#define PD_CPU BIT(0) /* Area contains main CPU core */ +#define PD_SCU BIT(1) /* Area contains SCU and L2 cache */ +#define PD_NO_CR BIT(2) /* Area lacks PWR{ON,OFF}CR registers */ + +#define PD_CPU_NOCR PD_CPU | PD_NO_CR /* CPU area lacks CR */ +#define PD_ALWAYS_ON PD_NO_CR /* Always-on area */ + +/* + * Description of a Power Area + */ +struct r8a779a0_sysc_area { + const char *name; + u8 pdr; /* PDRn */ + int parent; /* -1 if none */ + unsigned int flags; /* See PD_* */ +}; + +/* + * SoC-specific Power Area Description + */ +struct r8a779a0_sysc_info { + const struct r8a779a0_sysc_area *areas; + unsigned int num_areas; +}; + +static struct r8a779a0_sysc_area r8a779a0_areas[] __initdata = { + { "always-on", R8A779A0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "a3e0", R8A779A0_PD_A3E0, R8A779A0_PD_ALWAYS_ON, PD_SCU }, + { "a3e1", R8A779A0_PD_A3E1, R8A779A0_PD_ALWAYS_ON, PD_SCU }, + { "a2e0d0", R8A779A0_PD_A2E0D0, R8A779A0_PD_A3E0, PD_SCU }, + { "a2e0d1", R8A779A0_PD_A2E0D1, R8A779A0_PD_A3E0, PD_SCU }, + { "a2e1d0", R8A779A0_PD_A2E1D0, R8A779A0_PD_A3E1, PD_SCU }, + { "a2e1d1", R8A779A0_PD_A2E1D1, R8A779A0_PD_A3E1, PD_SCU }, + { "a1e0d0c0", R8A779A0_PD_A1E0D0C0, R8A779A0_PD_A2E0D0, PD_CPU_NOCR }, + { "a1e0d0c1", R8A779A0_PD_A1E0D0C1, R8A779A0_PD_A2E0D0, PD_CPU_NOCR }, + { "a1e0d1c0", R8A779A0_PD_A1E0D1C0, R8A779A0_PD_A2E0D1, PD_CPU_NOCR }, + { "a1e0d1c1", R8A779A0_PD_A1E0D1C1, R8A779A0_PD_A2E0D1, PD_CPU_NOCR }, + { "a1e1d0c0", R8A779A0_PD_A1E1D0C0, R8A779A0_PD_A2E1D0, PD_CPU_NOCR }, + { "a1e1d0c1", R8A779A0_PD_A1E1D0C1, R8A779A0_PD_A2E1D0, PD_CPU_NOCR }, + { "a1e1d1c0", R8A779A0_PD_A1E1D1C0, R8A779A0_PD_A2E1D1, PD_CPU_NOCR }, + { "a1e1d1c1", R8A779A0_PD_A1E1D1C1, R8A779A0_PD_A2E1D1, PD_CPU_NOCR }, + { "3dg-a", R8A779A0_PD_3DG_A, R8A779A0_PD_ALWAYS_ON }, + { "3dg-b", R8A779A0_PD_3DG_B, R8A779A0_PD_3DG_A }, + { "a3vip0", R8A779A0_PD_A3VIP0, R8A779A0_PD_ALWAYS_ON }, + { "a3vip1", R8A779A0_PD_A3VIP1, R8A779A0_PD_ALWAYS_ON }, + { "a3vip3", R8A779A0_PD_A3VIP3, R8A779A0_PD_ALWAYS_ON }, + { "a3vip2", R8A779A0_PD_A3VIP2, R8A779A0_PD_ALWAYS_ON }, + { "a3isp01", R8A779A0_PD_A3ISP01, R8A779A0_PD_ALWAYS_ON }, + { "a3isp23", R8A779A0_PD_A3ISP23, R8A779A0_PD_ALWAYS_ON }, + { "a3ir", R8A779A0_PD_A3IR, R8A779A0_PD_ALWAYS_ON }, + { "a2cn0", R8A779A0_PD_A2CN0, R8A779A0_PD_A3IR }, + { "a2imp01", R8A779A0_PD_A2IMP01, R8A779A0_PD_A3IR }, + { "a2dp0", R8A779A0_PD_A2DP0, R8A779A0_PD_A3IR }, + { "a2cv0", R8A779A0_PD_A2CV0, R8A779A0_PD_A3IR }, + { "a2cv1", R8A779A0_PD_A2CV1, R8A779A0_PD_A3IR }, + { "a2cv4", R8A779A0_PD_A2CV4, R8A779A0_PD_A3IR }, + { "a2cv6", R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR }, + { "a2cn2", R8A779A0_PD_A2CN2, R8A779A0_PD_A3IR }, + { "a2imp23", R8A779A0_PD_A2IMP23, R8A779A0_PD_A3IR }, + { "a2dp1", R8A779A0_PD_A2DP0, R8A779A0_PD_A3IR }, + { "a2cv2", R8A779A0_PD_A2CV0, R8A779A0_PD_A3IR }, + { "a2cv3", R8A779A0_PD_A2CV1, R8A779A0_PD_A3IR }, + { "a2cv5", R8A779A0_PD_A2CV4, R8A779A0_PD_A3IR }, + { "a2cv7", R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR }, + { "a2cn1", R8A779A0_PD_A2CN1, R8A779A0_PD_A3IR }, + { "a1cnn0", R8A779A0_PD_A1CNN0, R8A779A0_PD_A2CN0 }, + { "a1cnn2", R8A779A0_PD_A1CNN2, R8A779A0_PD_A2CN2 }, + { "a1dsp0", R8A779A0_PD_A1DSP0, R8A779A0_PD_A2CN2 }, + { "a1cnn1", R8A779A0_PD_A1CNN1, R8A779A0_PD_A2CN1 }, + { "a1dsp1", R8A779A0_PD_A1DSP1, R8A779A0_PD_A2CN1 }, +}; + +static const struct r8a779a0_sysc_info r8a779a0_sysc_info __initconst = { + .areas = r8a779a0_areas, + .num_areas = ARRAY_SIZE(r8a779a0_areas), +}; + +/* SYSC Common */ +#define SYSCSR 0x000 /* SYSC Status Register */ +#define SYSCPONSR(x) (0x800 + ((x) * 0x4)) /* Power-ON Status Register 0 */ +#define SYSCPOFFSR(x) (0x808 + ((x) * 0x4)) /* Power-OFF Status Register */ +#define SYSCISCR(x) (0x810 + ((x) * 0x4)) /* Interrupt Status/Clear Register */ +#define SYSCIER(x) (0x820 + ((x) * 0x4)) /* Interrupt Enable Register */ +#define SYSCIMR(x) (0x830 + ((x) * 0x4)) /* Interrupt Mask Register */ + +/* Power Domain Registers */ +#define PDRSR(n) (0x1000 + ((n) * 0x40)) +#define PDRONCR(n) (0x1004 + ((n) * 0x40)) +#define PDROFFCR(n) (0x1008 + ((n) * 0x40)) +#define PDRESR(n) (0x100C + ((n) * 0x40)) + +/* PWRON/PWROFF */ +#define PWRON_PWROFF BIT(0) /* Power-ON/OFF request */ + +/* PDRESR */ +#define PDRESR_ERR BIT(0) + +/* PDRSR */ +#define PDRSR_OFF BIT(0) /* Power-OFF state */ +#define PDRSR_ON BIT(4) /* Power-ON state */ +#define PDRSR_OFF_STATE BIT(8) /* Processing Power-OFF sequence */ +#define PDRSR_ON_STATE BIT(12) /* Processing Power-ON sequence */ + +#define SYSCSR_BUSY GENMASK(1, 0) /* All bit sets is not busy */ + +#define SYSCSR_TIMEOUT 10000 +#define SYSCSR_DELAY_US 10 + +#define PDRESR_RETRIES 1000 +#define PDRESR_DELAY_US 10 + +#define SYSCISR_TIMEOUT 10000 +#define SYSCISR_DELAY_US 10 + +#define NUM_DOMAINS_EACH_REG BITS_PER_TYPE(u32) + +static void __iomem *r8a779a0_sysc_base; +static DEFINE_SPINLOCK(r8a779a0_sysc_lock); /* SMP CPUs + I/O devices */ + +static int r8a779a0_sysc_pwr_on_off(u8 pdr, bool on) +{ + unsigned int reg_offs; + u32 val; + int ret; + + if (on) + reg_offs = PDRONCR(pdr); + else + reg_offs = PDROFFCR(pdr); + + /* Wait until SYSC is ready to accept a power request */ + ret = readl_poll_timeout_atomic(r8a779a0_sysc_base + SYSCSR, val, + (val & SYSCSR_BUSY) == SYSCSR_BUSY, + SYSCSR_DELAY_US, SYSCSR_TIMEOUT); + if (ret < 0) + return -EAGAIN; + + /* Submit power shutoff or power resume request */ + iowrite32(PWRON_PWROFF, r8a779a0_sysc_base + reg_offs); + + return 0; +} + +static int clear_irq_flags(unsigned int reg_idx, unsigned int isr_mask) +{ + u32 val; + int ret; + + iowrite32(isr_mask, r8a779a0_sysc_base + SYSCISCR(reg_idx)); + + ret = readl_poll_timeout_atomic(r8a779a0_sysc_base + SYSCISCR(reg_idx), + val, !(val & isr_mask), + SYSCISR_DELAY_US, SYSCISR_TIMEOUT); + if (ret < 0) { + pr_err("\n %s : Can not clear IRQ flags in SYSCISCR", __func__); + return -EIO; + } + + return 0; +} + +static int r8a779a0_sysc_power(u8 pdr, bool on) +{ + unsigned int isr_mask; + unsigned int reg_idx, bit_idx; + unsigned int status; + unsigned long flags; + int ret = 0; + u32 val; + int k; + + spin_lock_irqsave(&r8a779a0_sysc_lock, flags); + + reg_idx = pdr / NUM_DOMAINS_EACH_REG; + bit_idx = pdr % NUM_DOMAINS_EACH_REG; + + isr_mask = BIT(bit_idx); + + /* + * The interrupt source needs to be enabled, but masked, to prevent the + * CPU from receiving it. + */ + iowrite32(ioread32(r8a779a0_sysc_base + SYSCIER(reg_idx)) | isr_mask, + r8a779a0_sysc_base + SYSCIER(reg_idx)); + iowrite32(ioread32(r8a779a0_sysc_base + SYSCIMR(reg_idx)) | isr_mask, + r8a779a0_sysc_base + SYSCIMR(reg_idx)); + + ret = clear_irq_flags(reg_idx, isr_mask); + if (ret) + goto out; + + /* Submit power shutoff or resume request until it was accepted */ + for (k = 0; k < PDRESR_RETRIES; k++) { + ret = r8a779a0_sysc_pwr_on_off(pdr, on); + if (ret) + goto out; + + status = ioread32(r8a779a0_sysc_base + PDRESR(pdr)); + if (!(status & PDRESR_ERR)) + break; + + udelay(PDRESR_DELAY_US); + } + + if (k == PDRESR_RETRIES) { + ret = -EIO; + goto out; + } + + /* Wait until the power shutoff or resume request has completed * */ + ret = readl_poll_timeout_atomic(r8a779a0_sysc_base + SYSCISCR(reg_idx), + val, (val & isr_mask), + SYSCISR_DELAY_US, SYSCISR_TIMEOUT); + if (ret < 0) { + ret = -EIO; + goto out; + } + + /* Clear interrupt flags */ + ret = clear_irq_flags(reg_idx, isr_mask); + if (ret) + goto out; + + out: + spin_unlock_irqrestore(&r8a779a0_sysc_lock, flags); + + pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", + pdr, ioread32(r8a779a0_sysc_base + SYSCISCR(reg_idx)), ret); + return ret; +} + +static bool r8a779a0_sysc_power_is_off(u8 pdr) +{ + unsigned int st; + + st = ioread32(r8a779a0_sysc_base + PDRSR(pdr)); + + if (st & PDRSR_OFF) + return true; + + return false; +} + +struct r8a779a0_sysc_pd { + struct generic_pm_domain genpd; + u8 pdr; + unsigned int flags; + char name[]; +}; + +static inline struct r8a779a0_sysc_pd *to_r8a779a0_pd(struct generic_pm_domain *d) +{ + return container_of(d, struct r8a779a0_sysc_pd, genpd); +} + +static int r8a779a0_sysc_pd_power_off(struct generic_pm_domain *genpd) +{ + struct r8a779a0_sysc_pd *pd = to_r8a779a0_pd(genpd); + + pr_debug("%s: %s\n", __func__, genpd->name); + return r8a779a0_sysc_power(pd->pdr, false); +} + +static int r8a779a0_sysc_pd_power_on(struct generic_pm_domain *genpd) +{ + struct r8a779a0_sysc_pd *pd = to_r8a779a0_pd(genpd); + + pr_debug("%s: %s\n", __func__, genpd->name); + return r8a779a0_sysc_power(pd->pdr, true); +} + +static int __init r8a779a0_sysc_pd_setup(struct r8a779a0_sysc_pd *pd) +{ + struct generic_pm_domain *genpd = &pd->genpd; + const char *name = pd->genpd.name; + int error; + + if (pd->flags & PD_CPU) { + /* + * This domain contains a CPU core and therefore it should + * only be turned off if the CPU is not in use. + */ + pr_debug("PM domain %s contains %s\n", name, "CPU"); + genpd->flags |= GENPD_FLAG_ALWAYS_ON; + } else if (pd->flags & PD_SCU) { + /* + * This domain contains an SCU and cache-controller, and + * therefore it should only be turned off if the CPU cores are + * not in use. + */ + pr_debug("PM domain %s contains %s\n", name, "SCU"); + genpd->flags |= GENPD_FLAG_ALWAYS_ON; + } else if (pd->flags & PD_NO_CR) { + /* + * This domain cannot be turned off. + */ + genpd->flags |= GENPD_FLAG_ALWAYS_ON; + } + + if (!(pd->flags & (PD_CPU | PD_SCU))) { + /* Enable Clock Domain for I/O devices */ + genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; + genpd->attach_dev = cpg_mssr_attach_dev; + genpd->detach_dev = cpg_mssr_detach_dev; + } + + genpd->power_off = r8a779a0_sysc_pd_power_off; + genpd->power_on = r8a779a0_sysc_pd_power_on; + + if (pd->flags & (PD_CPU | PD_NO_CR)) { + /* Skip CPUs (handled by SMP code) and areas without control */ + pr_debug("%s: Not touching %s\n", __func__, genpd->name); + goto finalize; + } + + if (!r8a779a0_sysc_power_is_off(pd->pdr)) { + pr_debug("%s: %s is already powered\n", __func__, genpd->name); + goto finalize; + } + + r8a779a0_sysc_power(pd->pdr, true); + +finalize: + error = pm_genpd_init(genpd, &simple_qos_governor, false); + if (error) + pr_err("Failed to init PM domain %s: %d\n", name, error); + + return error; +} + +static const struct of_device_id r8a779a0_sysc_matches[] __initconst = { + { .compatible = "renesas,r8a779a0-sysc", .data = &r8a779a0_sysc_info }, + { /* sentinel */ } +}; + +struct r8a779a0_pm_domains { + struct genpd_onecell_data onecell_data; + struct generic_pm_domain *domains[R8A779A0_PD_ALWAYS_ON + 1]; +}; + +static struct genpd_onecell_data *r8a779a0_sysc_onecell_data; + +static int __init r8a779a0_sysc_pd_init(void) +{ + const struct r8a779a0_sysc_info *info; + const struct of_device_id *match; + struct r8a779a0_pm_domains *domains; + struct device_node *np; + void __iomem *base; + unsigned int i; + int error; + + np = of_find_matching_node_and_match(NULL, r8a779a0_sysc_matches, &match); + if (!np) + return -ENODEV; + + info = match->data; + + base = of_iomap(np, 0); + if (!base) { + pr_warn("%pOF: Cannot map regs\n", np); + error = -ENOMEM; + goto out_put; + } + + r8a779a0_sysc_base = base; + + domains = kzalloc(sizeof(*domains), GFP_KERNEL); + if (!domains) { + error = -ENOMEM; + goto out_put; + } + + domains->onecell_data.domains = domains->domains; + domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); + r8a779a0_sysc_onecell_data = &domains->onecell_data; + + for (i = 0; i < info->num_areas; i++) { + const struct r8a779a0_sysc_area *area = &info->areas[i]; + struct r8a779a0_sysc_pd *pd; + + if (!area->name) { + /* Skip NULLified area */ + continue; + } + + pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL); + if (!pd) { + error = -ENOMEM; + goto out_put; + } + + strcpy(pd->name, area->name); + pd->genpd.name = pd->name; + pd->pdr = area->pdr; + pd->flags = area->flags; + + error = r8a779a0_sysc_pd_setup(pd); + if (error) + goto out_put; + + domains->domains[area->pdr] = &pd->genpd; + + if (area->parent < 0) + continue; + + error = pm_genpd_add_subdomain(domains->domains[area->parent], + &pd->genpd); + if (error) { + pr_warn("Failed to add PM subdomain %s to parent %u\n", + area->name, area->parent); + goto out_put; + } + } + + error = of_genpd_add_provider_onecell(np, &domains->onecell_data); + +out_put: + of_node_put(np); + return error; +} +early_initcall(r8a779a0_sysc_pd_init); From 26cb1d2fffb73ed66ba6eb958b070861465e29aa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 11 Sep 2020 16:32:51 +0200 Subject: [PATCH 092/131] memory: omap-gpmc: Fix compile test on SPARC SPARC comes without CONFIG_OF_ADDRESS thus compile testing fails on linking: /usr/bin/sparc64-linux-gnu-ld: drivers/memory/omap-gpmc.o: in function `gpmc_probe_generic_child': omap-gpmc.c:(.text.unlikely+0x14ec): undefined reference to `of_platform_device_create' Fixes: ea0c0ad6b6eb ("memory: Enable compile testing for most of the drivers") Signed-off-by: Krzysztof Kozlowski Acked-by: Roger Quadros Link: https://lore.kernel.org/r/20200911143251.399-1-krzk@kernel.org --- drivers/memory/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 8072204bc21a..00e013b14703 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -104,6 +104,7 @@ config TI_EMIF config OMAP_GPMC bool "Texas Instruments OMAP SoC GPMC driver" if COMPILE_TEST + depends on OF_ADDRESS select GPIOLIB help This driver is for the General Purpose Memory Controller (GPMC) From 2899347249fe7567cb04bb810a85f848fc0ce475 Mon Sep 17 00:00:00 2001 From: Qilong Zhang Date: Wed, 16 Sep 2020 19:15:17 +0800 Subject: [PATCH 093/131] soc: qcom: llcc: use devm_platform_ioremap_resource_byname() Use the devm_platform_ioremap_resource_byname() helper instead of calling platform_get_resource_byname() and devm_ioremap_resource() separately. Signed-off-by: Zhang Qilong Link: https://lore.kernel.org/r/20200916111517.99670-1-zhangqilong3@huawei.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 429b5a60a1ba..70fbe70c6213 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -387,7 +387,6 @@ static int qcom_llcc_remove(struct platform_device *pdev) static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev, const char *name) { - struct resource *res; void __iomem *base; struct regmap_config llcc_regmap_config = { .reg_bits = 32, @@ -396,11 +395,7 @@ static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev, .fast_io = true, }; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (!res) - return ERR_PTR(-ENODEV); - - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource_byname(pdev, name); if (IS_ERR(base)) return ERR_CAST(base); From ab3d8e1baaee4b167cc99120f640ee4de6d05d50 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 1 Sep 2020 11:33:34 +0100 Subject: [PATCH 094/131] tee: replace cdev_add + device_add with cdev_device_add Commit 233ed09d7fda ("chardev: add helper function to register char devs with a struct device") added a helper function 'cdev_device_add'. Make use of cdev_device_add in tee_device_register to replace cdev_add and device_add. Since cdev_device_add takes care of setting the kobj->parent, drop explicit initialisation in tee_device_alloc. Signed-off-by: Sudeep Holla Signed-off-by: Jens Wiklander --- drivers/tee/tee_core.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 64637e09a095..b4a8b362d78f 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -917,7 +917,6 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc, cdev_init(&teedev->cdev, &tee_fops); teedev->cdev.owner = teedesc->owner; - teedev->cdev.kobj.parent = &teedev->dev.kobj; dev_set_drvdata(&teedev->dev, driver_data); device_initialize(&teedev->dev); @@ -985,24 +984,15 @@ int tee_device_register(struct tee_device *teedev) return -EINVAL; } - rc = cdev_add(&teedev->cdev, teedev->dev.devt, 1); + rc = cdev_device_add(&teedev->cdev, &teedev->dev); if (rc) { dev_err(&teedev->dev, - "unable to cdev_add() %s, major %d, minor %d, err=%d\n", + "unable to cdev_device_add() %s, major %d, minor %d, err=%d\n", teedev->name, MAJOR(teedev->dev.devt), MINOR(teedev->dev.devt), rc); return rc; } - rc = device_add(&teedev->dev); - if (rc) { - dev_err(&teedev->dev, - "unable to device_add() %s, major %d, minor %d, err=%d\n", - teedev->name, MAJOR(teedev->dev.devt), - MINOR(teedev->dev.devt), rc); - goto err_device_add; - } - rc = sysfs_create_group(&teedev->dev.kobj, &tee_dev_group); if (rc) { dev_err(&teedev->dev, @@ -1014,9 +1004,7 @@ int tee_device_register(struct tee_device *teedev) return 0; err_sysfs_create_group: - device_del(&teedev->dev); -err_device_add: - cdev_del(&teedev->cdev); + cdev_device_del(&teedev->cdev, &teedev->dev); return rc; } EXPORT_SYMBOL_GPL(tee_device_register); @@ -1062,8 +1050,7 @@ void tee_device_unregister(struct tee_device *teedev) if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) { sysfs_remove_group(&teedev->dev.kobj, &tee_dev_group); - cdev_del(&teedev->cdev); - device_del(&teedev->dev); + cdev_device_del(&teedev->cdev, &teedev->dev); } tee_device_put(teedev); From 8c05f50fe8452f9d3220efad77bef42c7b498193 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 1 Sep 2020 11:33:35 +0100 Subject: [PATCH 095/131] tee: avoid explicit sysfs_create/delete_group by initialising dev->groups If the dev->groups is initialised, the sysfs group is created as part of device_add call. There is no need to call sysfs_create/delete_group explicitly. Signed-off-by: Sudeep Holla Signed-off-by: Jens Wiklander --- drivers/tee/tee_core.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index b4a8b362d78f..f77d64fafead 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -962,9 +962,7 @@ static struct attribute *tee_dev_attrs[] = { NULL }; -static const struct attribute_group tee_dev_group = { - .attrs = tee_dev_attrs, -}; +ATTRIBUTE_GROUPS(tee_dev); /** * tee_device_register() - Registers a TEE device @@ -984,6 +982,8 @@ int tee_device_register(struct tee_device *teedev) return -EINVAL; } + teedev->dev.groups = tee_dev_groups; + rc = cdev_device_add(&teedev->cdev, &teedev->dev); if (rc) { dev_err(&teedev->dev, @@ -993,19 +993,8 @@ int tee_device_register(struct tee_device *teedev) return rc; } - rc = sysfs_create_group(&teedev->dev.kobj, &tee_dev_group); - if (rc) { - dev_err(&teedev->dev, - "failed to create sysfs attributes, err=%d\n", rc); - goto err_sysfs_create_group; - } - teedev->flags |= TEE_DEVICE_FLAG_REGISTERED; return 0; - -err_sysfs_create_group: - cdev_device_del(&teedev->cdev, &teedev->dev); - return rc; } EXPORT_SYMBOL_GPL(tee_device_register); @@ -1048,10 +1037,8 @@ void tee_device_unregister(struct tee_device *teedev) if (!teedev) return; - if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) { - sysfs_remove_group(&teedev->dev.kobj, &tee_dev_group); + if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) cdev_device_del(&teedev->cdev, &teedev->dev); - } tee_device_put(teedev); wait_for_completion(&teedev->c_no_users); From 775edf7856d81fde852968212cd58fc9a3f8cd7d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 17 Sep 2020 12:07:45 +0200 Subject: [PATCH 096/131] soc/tegra: fuse: Extract tegra_get_platform() This function extracts the PRE_SI_PLATFORM field from the HIDREV register and can be used to determine which platform the kernel runs on (silicon, simulation, ...). Note that while only Tegra194 and later define this field, it should be safe to call this on prior generations as well since this field should read as 0, indicating silicon. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra.c | 2 +- drivers/soc/tegra/fuse/tegra-apbmisc.c | 5 +++++ include/soc/tegra/fuse.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index d1f8dd0289e6..7e6b6ee59120 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -336,7 +336,7 @@ static ssize_t platform_show(struct device *dev, struct device_attribute *attr, * platform type is silicon and all other non-zero values indicate * the type of simulation platform is being used. */ - return sprintf(buf, "%d\n", (tegra_read_chipid() >> 20) & 0xf); + return sprintf(buf, "%d\n", tegra_get_platform()); } static DEVICE_ATTR_RO(platform); diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 8e416ad91ee2..92a2d646c183 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -47,6 +47,11 @@ u8 tegra_get_minor_rev(void) return (tegra_read_chipid() >> 16) & 0xf; } +u8 tegra_get_platform(void) +{ + return (tegra_read_chipid() >> 20) & 0xf; +} + u32 tegra_read_straps(void) { WARN(!chipid, "Tegra ABP MISC not yet available\n"); diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index 1097feca41ed..214908fc5581 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -23,6 +23,7 @@ u32 tegra_read_chipid(void); u8 tegra_get_chip_id(void); +u8 tegra_get_platform(void); enum tegra_revision { TEGRA_REVISION_UNKNOWN = 0, From 52e6d399a41da68125ec107f5f5f688a74ab7ac4 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 17 Sep 2020 12:07:46 +0200 Subject: [PATCH 097/131] soc/tegra: fuse: Implement tegra_is_silicon() This function can be used by drivers to determine whether code is running on silicon or on a simulation platform. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/tegra-apbmisc.c | 19 +++++++++++++++++++ include/soc/tegra/fuse.h | 1 + 2 files changed, 20 insertions(+) diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 92a2d646c183..946a2d9ad117 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -52,6 +52,25 @@ u8 tegra_get_platform(void) return (tegra_read_chipid() >> 20) & 0xf; } +bool tegra_is_silicon(void) +{ + switch (tegra_get_chip_id()) { + case TEGRA194: + if (tegra_get_platform() == 0) + return true; + + return false; + } + + /* + * Chips prior to Tegra194 have a different way of determining whether + * they are silicon or not. Since we never supported simulation on the + * older Tegra chips, don't bother extracting the information and just + * report that we're running on silicon. + */ + return true; +} + u32 tegra_read_straps(void) { WARN(!chipid, "Tegra ABP MISC not yet available\n"); diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index 214908fc5581..a9db917a1d06 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -24,6 +24,7 @@ u32 tegra_read_chipid(void); u8 tegra_get_chip_id(void); u8 tegra_get_platform(void); +bool tegra_is_silicon(void); enum tegra_revision { TEGRA_REVISION_UNKNOWN = 0, From 1f44febf71ba3d8a8694669197ec5a384c8d3011 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 17 Sep 2020 12:07:47 +0200 Subject: [PATCH 098/131] soc/tegra: fuse: Add Tegra234 support Add support for FUSE block found on the Tegra234 SoC, which is largely similar to the IP found on previous generations. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra.c | 6 +++++- drivers/soc/tegra/fuse/fuse-tegra30.c | 30 ++++++++++++++++++++++++++ drivers/soc/tegra/fuse/fuse.h | 12 +++++++++-- drivers/soc/tegra/fuse/tegra-apbmisc.c | 1 + include/soc/tegra/fuse.h | 1 + 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 7e6b6ee59120..94b60a692b51 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -49,6 +49,9 @@ static struct tegra_fuse *fuse = &(struct tegra_fuse) { }; static const struct of_device_id tegra_fuse_match[] = { +#ifdef CONFIG_ARCH_TEGRA_234_SOC + { .compatible = "nvidia,tegra234-efuse", .data = &tegra234_fuse_soc }, +#endif #ifdef CONFIG_ARCH_TEGRA_194_SOC { .compatible = "nvidia,tegra194-efuse", .data = &tegra194_fuse_soc }, #endif @@ -326,7 +329,8 @@ const struct attribute_group tegra_soc_attr_group = { .attrs = tegra_soc_attr, }; -#ifdef CONFIG_ARCH_TEGRA_194_SOC +#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \ + IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) static ssize_t platform_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index 85accef41fa1..9ea7f0168457 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -356,3 +356,33 @@ const struct tegra_fuse_soc tegra194_fuse_soc = { .soc_attr_group = &tegra194_soc_attr_group, }; #endif + +#if defined(CONFIG_ARCH_TEGRA_234_SOC) +static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = { + { + .nvmem_name = "fuse", + .cell_name = "xusb-pad-calibration", + .dev_id = "3520000.padctl", + .con_id = "calibration", + }, { + .nvmem_name = "fuse", + .cell_name = "xusb-pad-calibration-ext", + .dev_id = "3520000.padctl", + .con_id = "calibration-ext", + }, +}; + +static const struct tegra_fuse_info tegra234_fuse_info = { + .read = tegra30_fuse_read, + .size = 0x300, + .spare = 0x280, +}; + +const struct tegra_fuse_soc tegra234_fuse_soc = { + .init = tegra30_fuse_init, + .info = &tegra234_fuse_info, + .lookups = tegra234_fuse_lookups, + .num_lookups = ARRAY_SIZE(tegra234_fuse_lookups), + .soc_attr_group = &tegra194_soc_attr_group, +}; +#endif diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h index 9d4fc315a007..e057a58e2060 100644 --- a/drivers/soc/tegra/fuse/fuse.h +++ b/drivers/soc/tegra/fuse/fuse.h @@ -115,9 +115,17 @@ extern const struct tegra_fuse_soc tegra210_fuse_soc; extern const struct tegra_fuse_soc tegra186_fuse_soc; #endif -#ifdef CONFIG_ARCH_TEGRA_194_SOC -extern const struct tegra_fuse_soc tegra194_fuse_soc; +#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \ + IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) extern const struct attribute_group tegra194_soc_attr_group; #endif +#ifdef CONFIG_ARCH_TEGRA_194_SOC +extern const struct tegra_fuse_soc tegra194_fuse_soc; +#endif + +#ifdef CONFIG_ARCH_TEGRA_234_SOC +extern const struct tegra_fuse_soc tegra234_fuse_soc; +#endif + #endif diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 946a2d9ad117..0e4eb2656f44 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -56,6 +56,7 @@ bool tegra_is_silicon(void) { switch (tegra_get_chip_id()) { case TEGRA194: + case TEGRA234: if (tegra_get_platform() == 0) return true; diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index a9db917a1d06..c702bd2911bc 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -14,6 +14,7 @@ #define TEGRA210 0x21 #define TEGRA186 0x18 #define TEGRA194 0x19 +#define TEGRA234 0x23 #define TEGRA_FUSE_SKU_CALIB_0 0xf0 #define TEGRA30_FUSE_SATA_CALIB 0x124 From 03d285230708c6d851c8c570778b748449c5b852 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 17 Sep 2020 12:07:48 +0200 Subject: [PATCH 099/131] soc/tegra: misc: Add Tegra234 support The MISC block is largely similar to that found on earlier chips, but not completely compatible. Allow binding to the instantiation found on Tegra234. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/tegra-apbmisc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 0e4eb2656f44..cee207d10024 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -95,6 +95,7 @@ static const struct of_device_id apbmisc_match[] __initconst = { { .compatible = "nvidia,tegra20-apbmisc", }, { .compatible = "nvidia,tegra186-misc", }, { .compatible = "nvidia,tegra194-misc", }, + { .compatible = "nvidia,tegra234-misc", }, {}, }; From f98485e4edbbbe5a691e87447a21bff0bbac574d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 17 Sep 2020 12:07:49 +0200 Subject: [PATCH 100/131] soc/tegra: pmc: Reorder reset sources/levels definitions Move the definitions of reset sources and levels into a more natural location. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 78 ++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 42cf37a0556b..3255eaf159f0 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -336,45 +336,6 @@ struct tegra_pmc_soc { bool has_blink_output; }; -static const char * const tegra186_reset_sources[] = { - "SYS_RESET", - "AOWDT", - "MCCPLEXWDT", - "BPMPWDT", - "SCEWDT", - "SPEWDT", - "APEWDT", - "BCCPLEXWDT", - "SENSOR", - "AOTAG", - "VFSENSOR", - "SWREST", - "SC7", - "HSM", - "CORESIGHT" -}; - -static const char * const tegra186_reset_levels[] = { - "L0", "L1", "L2", "WARM" -}; - -static const char * const tegra30_reset_sources[] = { - "POWER_ON_RESET", - "WATCHDOG", - "SENSOR", - "SW_MAIN", - "LP0" -}; - -static const char * const tegra210_reset_sources[] = { - "POWER_ON_RESET", - "WATCHDOG", - "SENSOR", - "SW_MAIN", - "LP0", - "AOTAG" -}; - /** * struct tegra_pmc - NVIDIA Tegra PMC * @dev: pointer to PMC device structure @@ -2784,6 +2745,14 @@ static const u8 tegra30_cpu_powergates[] = { TEGRA_POWERGATE_CPU3, }; +static const char * const tegra30_reset_sources[] = { + "POWER_ON_RESET", + "WATCHDOG", + "SENSOR", + "SW_MAIN", + "LP0" +}; + static const struct tegra_pmc_soc tegra30_pmc_soc = { .num_powergates = ARRAY_SIZE(tegra30_powergates), .powergates = tegra30_powergates, @@ -3061,6 +3030,15 @@ static const struct pinctrl_pin_desc tegra210_pin_descs[] = { TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) }; +static const char * const tegra210_reset_sources[] = { + "POWER_ON_RESET", + "WATCHDOG", + "SENSOR", + "SW_MAIN", + "LP0", + "AOTAG" +}; + static const struct tegra_wake_event tegra210_wake_events[] = { TEGRA_WAKE_IRQ("rtc", 16, 2), TEGRA_WAKE_IRQ("pmu", 51, 86), @@ -3193,6 +3171,28 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, iounmap(wake); } +static const char * const tegra186_reset_sources[] = { + "SYS_RESET", + "AOWDT", + "MCCPLEXWDT", + "BPMPWDT", + "SCEWDT", + "SPEWDT", + "APEWDT", + "BCCPLEXWDT", + "SENSOR", + "AOTAG", + "VFSENSOR", + "SWREST", + "SC7", + "HSM", + "CORESIGHT" +}; + +static const char * const tegra186_reset_levels[] = { + "L0", "L1", "L2", "WARM" +}; + static const struct tegra_wake_event tegra186_wake_events[] = { TEGRA_WAKE_IRQ("pmu", 24, 209), TEGRA_WAKE_GPIO("power", 29, 1, TEGRA186_AON_GPIO(FF, 0)), From 34e214a99689054e666cd4149500a37fa0c5ac98 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 17 Sep 2020 12:07:50 +0200 Subject: [PATCH 101/131] soc/tegra: pmc: Add Tegra234 support The PMC block is largely similar to that found on earlier chips, but not completely compatible. Allow binding to the instantiation found on Tegra234. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 3255eaf159f0..9ed0c3b04c0a 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -3362,7 +3362,75 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = { .has_blink_output = false, }; +static const struct tegra_pmc_regs tegra234_pmc_regs = { + .scratch0 = 0x2000, + .dpd_req = 0, + .dpd_status = 0, + .dpd2_req = 0, + .dpd2_status = 0, + .rst_status = 0x70, + .rst_source_shift = 0x2, + .rst_source_mask = 0xfc, + .rst_level_shift = 0x0, + .rst_level_mask = 0x3, +}; + +static const char * const tegra234_reset_sources[] = { + "SYS_RESET_N", + "AOWDT", + "BCCPLEXWDT", + "BPMPWDT", + "SCEWDT", + "SPEWDT", + "APEWDT", + "LCCPLEXWDT", + "SENSOR", + "AOTAG", + "VFSENSOR", + "MAINSWRST", + "SC7", + "HSM", + "CSITE", + "RCEWDT", + "PVA0WDT", + "PVA1WDT", + "L1A_ASYNC", + "BPMPBOOT", + "FUSECRC", +}; + +static const struct tegra_pmc_soc tegra234_pmc_soc = { + .num_powergates = 0, + .powergates = NULL, + .num_cpu_powergates = 0, + .cpu_powergates = NULL, + .has_tsense_reset = false, + .has_gpu_clamps = false, + .needs_mbist_war = false, + .has_impl_33v_pwr = true, + .maybe_tz_only = false, + .num_io_pads = 0, + .io_pads = NULL, + .num_pin_descs = 0, + .pin_descs = NULL, + .regs = &tegra234_pmc_regs, + .init = NULL, + .setup_irq_polarity = tegra186_pmc_setup_irq_polarity, + .irq_set_wake = tegra186_pmc_irq_set_wake, + .irq_set_type = tegra186_pmc_irq_set_type, + .reset_sources = tegra234_reset_sources, + .num_reset_sources = ARRAY_SIZE(tegra234_reset_sources), + .reset_levels = tegra186_reset_levels, + .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels), + .num_wake_events = 0, + .wake_events = NULL, + .pmc_clks_data = NULL, + .num_pmc_clks = 0, + .has_blink_output = false, +}; + static const struct of_device_id tegra_pmc_match[] = { + { .compatible = "nvidia,tegra234-pmc", .data = &tegra234_pmc_soc }, { .compatible = "nvidia,tegra194-pmc", .data = &tegra194_pmc_soc }, { .compatible = "nvidia,tegra186-pmc", .data = &tegra186_pmc_soc }, { .compatible = "nvidia,tegra210-pmc", .data = &tegra210_pmc_soc }, From 0ebdf11699d0491c0a1eee5bb5d920f4f36810ba Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 17 Sep 2020 12:07:51 +0200 Subject: [PATCH 102/131] firmware: tegra: Enable BPMP support on Tegra234 Enable support for the BPMP on Tegra234 to avoid relying on Tegra194 being enabled to pull in the needed OF device ID table entry. On simulation platforms the BPMP hasn't booted up yet by the time we probe the BPMP driver and the BPMP hasn't had a chance to mark the doorbell as ringable by the CCPLEX. This corresponding check in the BPMP driver will therefore fail. Work around this by disabling the check on simulation platforms. Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp.c | 3 ++- drivers/mailbox/tegra-hsp.c | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 4d93d8925e14..0742a90cb844 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -856,7 +856,8 @@ static const struct tegra_bpmp_soc tegra210_soc = { static const struct of_device_id tegra_bpmp_match[] = { #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \ - IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) + IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \ + IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC) { .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc }, #endif #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c index 834b35dc3b13..e07091d71986 100644 --- a/drivers/mailbox/tegra-hsp.c +++ b/drivers/mailbox/tegra-hsp.c @@ -13,6 +13,8 @@ #include #include +#include + #include #include "mailbox.h" @@ -322,7 +324,12 @@ static int tegra_hsp_doorbell_startup(struct mbox_chan *chan) if (!ccplex) return -ENODEV; - if (!tegra_hsp_doorbell_can_ring(db)) + /* + * On simulation platforms the BPMP hasn't had a chance yet to mark + * the doorbell as ringable by the CCPLEX, so we want to skip extra + * checks here. + */ + if (tegra_is_silicon() && !tegra_hsp_doorbell_can_ring(db)) return -ENODEV; spin_lock_irqsave(&hsp->lock, flags); From 97de44c5ecd413d3da3d4ace74272a1ad6a409ca Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 17 Sep 2020 08:47:01 +0200 Subject: [PATCH 103/131] dt-bindings: power: amlogic, meson-ee-pwrc: add Amlogic AXG power controller bindings This add the bindings of the Power Controller found in the Amlogic AXG SoCs. Signed-off-by: Neil Armstrong Signed-off-by: Kevin Hilman Reviewed-by: Rob Herring Acked-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20200917064702.1459-2-narmstrong@baylibre.com --- .../bindings/power/amlogic,meson-ee-pwrc.yaml | 23 +++++++++++++++++-- include/dt-bindings/power/meson-axg-power.h | 14 +++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/power/meson-axg-power.h diff --git a/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml b/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml index 4f524f822e84..d30f85cc395e 100644 --- a/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml +++ b/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml @@ -27,6 +27,7 @@ properties: - amlogic,meson8b-pwrc - amlogic,meson8m2-pwrc - amlogic,meson-gxbb-pwrc + - amlogic,meson-axg-pwrc - amlogic,meson-g12a-pwrc - amlogic,meson-sm1-pwrc @@ -42,11 +43,11 @@ properties: - const: vapb resets: - minItems: 11 + minItems: 5 maxItems: 12 reset-names: - minItems: 11 + minItems: 5 maxItems: 12 "#power-domain-cells": @@ -107,6 +108,24 @@ allOf: - resets - reset-names + - if: + properties: + compatible: + enum: + - amlogic,meson-axg-pwrc + then: + properties: + reset-names: + items: + - const: viu + - const: venc + - const: vcbus + - const: vencl + - const: vid_lock + required: + - resets + - reset-names + - if: properties: compatible: diff --git a/include/dt-bindings/power/meson-axg-power.h b/include/dt-bindings/power/meson-axg-power.h new file mode 100644 index 000000000000..e5243884b249 --- /dev/null +++ b/include/dt-bindings/power/meson-axg-power.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (c) 2020 BayLibre, SAS + * Author: Neil Armstrong + */ + +#ifndef _DT_BINDINGS_MESON_AXG_POWER_H +#define _DT_BINDINGS_MESON_AXG_POWER_H + +#define PWRC_AXG_VPU_ID 0 +#define PWRC_AXG_ETHERNET_MEM_ID 1 +#define PWRC_AXG_AUDIO_ID 2 + +#endif From 525054782a74d28503c3f585e00d9860d67d7ad1 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 17 Sep 2020 08:47:02 +0200 Subject: [PATCH 104/131] soc: amlogic: meson-ee-pwrc: add support for the Meson AXG SoCs The Power Controller in the Amlogic AXG SoCs is similar to the GXL one but with less VPU memory domains to enable and a supplementary Audio memory power domain. Signed-off-by: Neil Armstrong Signed-off-by: Kevin Hilman Acked-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20200917064702.1459-3-narmstrong@baylibre.com --- drivers/soc/amlogic/meson-ee-pwrc.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c index 43665b77aa9e..9fd97ad02806 100644 --- a/drivers/soc/amlogic/meson-ee-pwrc.c +++ b/drivers/soc/amlogic/meson-ee-pwrc.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,11 @@ static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19); { __reg, BIT(14) }, \ { __reg, BIT(15) } +static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_vpu[] = { + VPU_MEMPD(HHI_VPU_MEM_PD_REG0), + VPU_HHI_MEMPD(HHI_MEM_PD_REG0), +}; + static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = { VPU_MEMPD(HHI_VPU_MEM_PD_REG0), VPU_MEMPD(HHI_VPU_MEM_PD_REG1), @@ -190,6 +196,10 @@ static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = { { HHI_MEM_PD_REG0, GENMASK(25, 18) }, }; +static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_audio[] = { + { HHI_MEM_PD_REG0, GENMASK(5, 4) }, +}; + static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = { { HHI_MEM_PD_REG0, GENMASK(5, 4) }, { HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) }, @@ -231,6 +241,13 @@ static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = { static bool pwrc_ee_get_power(struct meson_ee_pwrc_domain *pwrc_domain); +static struct meson_ee_pwrc_domain_desc axg_pwrc_domains[] = { + [PWRC_AXG_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, axg_pwrc_mem_vpu, + pwrc_ee_get_power, 5, 2), + [PWRC_AXG_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth), + [PWRC_AXG_AUDIO_ID] = MEM_PD("AUDIO", axg_pwrc_mem_audio), +}; + static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = { [PWRC_G12A_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu, pwrc_ee_get_power, 11, 2), @@ -529,6 +546,11 @@ static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = { .domains = g12a_pwrc_domains, }; +static struct meson_ee_pwrc_domain_data meson_ee_axg_pwrc_data = { + .count = ARRAY_SIZE(axg_pwrc_domains), + .domains = axg_pwrc_domains, +}; + static struct meson_ee_pwrc_domain_data meson_ee_gxbb_pwrc_data = { .count = ARRAY_SIZE(gxbb_pwrc_domains), .domains = gxbb_pwrc_domains, @@ -562,6 +584,10 @@ static const struct of_device_id meson_ee_pwrc_match_table[] = { .compatible = "amlogic,meson8m2-pwrc", .data = &meson_ee_m8b_pwrc_data, }, + { + .compatible = "amlogic,meson-axg-pwrc", + .data = &meson_ee_axg_pwrc_data, + }, { .compatible = "amlogic,meson-gxbb-pwrc", .data = &meson_ee_gxbb_pwrc_data, From 67a344e889669690906324f09ffd07fb02a76889 Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Thu, 17 Sep 2020 20:51:14 +0800 Subject: [PATCH 105/131] memory: tegra: Convert to DEFINE_SHOW_ATTRIBUTE Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Qinglang Miao Link: https://lore.kernel.org/r/20200917125114.103598-1-miaoqinglang@huawei.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra124-emc.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index ba5cb1f4dfc2..76ace42a688a 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -1060,19 +1060,7 @@ static int tegra_emc_debug_available_rates_show(struct seq_file *s, return 0; } -static int tegra_emc_debug_available_rates_open(struct inode *inode, - struct file *file) -{ - return single_open(file, tegra_emc_debug_available_rates_show, - inode->i_private); -} - -static const struct file_operations tegra_emc_debug_available_rates_fops = { - .open = tegra_emc_debug_available_rates_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(tegra_emc_debug_available_rates); static int tegra_emc_debug_min_rate_get(void *data, u64 *rate) { From 94ca85733699e09c691e63c5bc2475f92f9dd52a Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Thu, 17 Sep 2020 20:51:13 +0800 Subject: [PATCH 106/131] memory: emif: Convert to DEFINE_SHOW_ATTRIBUTE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Along with this change, we get additionally: .owner = THIS_MODULE, .llseek = seq_lseek, 1. The llseek method is used to change the current read/write position in a file which can be ignored if you don't use it. 2. The owner is not even a method. Instead, it is a pointer to the module that “owns” this structure; it is used by the kernel to maintain the module's usage count which can be ignored. Signed-off-by: Qinglang Miao Link: https://lore.kernel.org/r/20200917125113.103550-1-miaoqinglang@huawei.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/emif.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 5c4d8319c9cf..ddb1879f07d3 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -131,16 +131,7 @@ static int emif_regdump_show(struct seq_file *s, void *unused) return 0; } -static int emif_regdump_open(struct inode *inode, struct file *file) -{ - return single_open(file, emif_regdump_show, inode->i_private); -} - -static const struct file_operations emif_regdump_fops = { - .open = emif_regdump_open, - .read = seq_read, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(emif_regdump); static int emif_mr4_show(struct seq_file *s, void *unused) { @@ -150,16 +141,7 @@ static int emif_mr4_show(struct seq_file *s, void *unused) return 0; } -static int emif_mr4_open(struct inode *inode, struct file *file) -{ - return single_open(file, emif_mr4_show, inode->i_private); -} - -static const struct file_operations emif_mr4_fops = { - .open = emif_mr4_open, - .read = seq_read, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(emif_mr4); static int __init_or_module emif_debugfs_init(struct emif_data *emif) { From 74e0e43a09cea3189c12ad6a5444d313f45664ac Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Sun, 20 Sep 2020 19:30:30 -0700 Subject: [PATCH 107/131] soc: ti: Convert to DEFINE_SHOW_ATTRIBUTE Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Qinglang Miao Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/knav_dma.c | 16 +++------------- drivers/soc/ti/knav_qmss_queue.c | 14 ++------------ 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index 6285cd8efb21..8c863ecb1c60 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -355,7 +355,7 @@ static void dma_debug_show_devices(struct seq_file *s, } } -static int dma_debug_show(struct seq_file *s, void *v) +static int knav_dma_debug_show(struct seq_file *s, void *v) { struct knav_dma_device *dma; @@ -370,17 +370,7 @@ static int dma_debug_show(struct seq_file *s, void *v) return 0; } -static int knav_dma_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, dma_debug_show, NULL); -} - -static const struct file_operations knav_dma_debug_ops = { - .open = knav_dma_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(knav_dma_debug); static int of_channel_match_helper(struct device_node *np, const char *name, const char **dma_instance) @@ -778,7 +768,7 @@ static int knav_dma_probe(struct platform_device *pdev) } debugfs_create_file("knav_dma", S_IFREG | S_IRUGO, NULL, NULL, - &knav_dma_debug_ops); + &knav_dma_debug_fops); device_ready = true; return ret; diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index aa071d96ef36..a460f201bf8e 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -478,17 +478,7 @@ static int knav_queue_debug_show(struct seq_file *s, void *v) return 0; } -static int knav_queue_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, knav_queue_debug_show, NULL); -} - -static const struct file_operations knav_queue_debug_ops = { - .open = knav_queue_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(knav_queue_debug); static inline int knav_queue_pdsp_wait(u32 * __iomem addr, unsigned timeout, u32 flags) @@ -1878,7 +1868,7 @@ static int knav_queue_probe(struct platform_device *pdev) } debugfs_create_file("qmss", S_IFREG | S_IRUGO, NULL, NULL, - &knav_queue_debug_ops); + &knav_queue_debug_fops); device_ready = true; return 0; From dcca7a97c6bfff2a7a18b928a0b9bf215cc8f4f5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 20 Sep 2020 19:32:38 -0700 Subject: [PATCH 108/131] Add missing '#' to fix schema errors: $id: 'http://devicetree.org/schemas/soc/ti/ti,pruss.yaml' does not match 'http://devicetree.org/schemas/.*\\.yaml#' $schema: 'http://devicetree.org/meta-schemas/core.yaml' is not one of ['http://devicetree.org/meta-schemas/core.yaml#', 'http://devicetree.org/meta-schemas/base.yaml#'] Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml: ignoring, error in schema: $id Fixes: bd691ce0ba9d ("dt-bindings: soc: ti: Add TI PRUSS bindings") Acked-by: Suman Anna Signed-off-by: Krzysztof Kozlowski Signed-off-by: Santosh Shilimkar --- Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml index cf7dc83f724f..037c51b2f972 100644 --- a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml +++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/soc/ti/ti,pruss.yaml -$schema: http://devicetree.org/meta-schemas/core.yaml +$id: http://devicetree.org/schemas/soc/ti/ti,pruss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: |+ TI Programmable Real-Time Unit and Industrial Communication Subsystem From 1fe44191f361a88b0f9600a5bbc8ebf7ede642ce Mon Sep 17 00:00:00 2001 From: Li Yang Date: Tue, 22 Sep 2020 17:38:21 -0500 Subject: [PATCH 109/131] soc: fsl: qman: fix -Wpacked-not-aligned warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes compile warnings from the -Wpacked-not-aligned option. In file included from ../drivers/crypto/caam/qi.c:12: ../include/soc/fsl/qman.h:259:1: warning: alignment 1 of ‘struct qm_dqrr_entry’ is less than 8 [-Wpacked-not-aligned] } __packed; ^ ../include/soc/fsl/qman.h:292:2: warning: alignment 1 of ‘struct ’ is less than 8 [-Wpacked-not-aligned] } __packed ern; ^ Reported-by: Herbert Xu Signed-off-by: Li Yang --- include/soc/fsl/qman.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/soc/fsl/qman.h b/include/soc/fsl/qman.h index cfe00e08e85b..9f484113cfda 100644 --- a/include/soc/fsl/qman.h +++ b/include/soc/fsl/qman.h @@ -256,7 +256,7 @@ struct qm_dqrr_entry { __be32 context_b; struct qm_fd fd; u8 __reserved4[32]; -} __packed; +} __packed __aligned(64); #define QM_DQRR_VERB_VBIT 0x80 #define QM_DQRR_VERB_MASK 0x7f /* where the verb contains; */ #define QM_DQRR_VERB_FRAME_DEQUEUE 0x60 /* "this format" */ @@ -289,7 +289,7 @@ union qm_mr_entry { __be32 tag; struct qm_fd fd; u8 __reserved1[32]; - } __packed ern; + } __packed __aligned(64) ern; struct { u8 verb; u8 fqs; /* Frame Queue Status */ From 750cf40c0f7088f36a8a5d102e0488b1ac47faf5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 20 Sep 2020 22:26:25 +0200 Subject: [PATCH 110/131] soc: fsl: qbman: Fix return value on success On error the function was meant to return -ERRNO. This also fixes compile warning: drivers/soc/fsl/qbman/bman.c:640:6: warning: variable 'err' set but not used [-Wunused-but-set-variable] Fixes: 0505d00c8dba ("soc/fsl/qbman: Cleanup buffer pools if BMan was initialized prior to bootup") Signed-off-by: Krzysztof Kozlowski Signed-off-by: Li Yang --- drivers/soc/fsl/qbman/bman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qbman/bman.c b/drivers/soc/fsl/qbman/bman.c index f4fb527d8301..c5dd026fe889 100644 --- a/drivers/soc/fsl/qbman/bman.c +++ b/drivers/soc/fsl/qbman/bman.c @@ -660,7 +660,7 @@ int bm_shutdown_pool(u32 bpid) } done: put_affine_portal(); - return 0; + return err; } struct gen_pool *bm_bpalloc; From 72f7fe2d6a2637c98ada42812ebfa0dcad0b0737 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Thu, 10 Sep 2020 22:04:15 +0800 Subject: [PATCH 111/131] soc: fsl: dpio: remove set but not used 'addr_cena' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This addresses the following gcc warning with "make W=1": drivers/soc/fsl/dpio/qbman-portal.c: In function ‘qbman_swp_enqueue_multiple_direct’: drivers/soc/fsl/dpio/qbman-portal.c:650:11: warning: variable ‘addr_cena’ set but not used [-Wunused-but-set-variable] 650 | uint64_t addr_cena; | ^~~~~~~~~ Reported-by: Hulk Robot Signed-off-by: Jason Yan Reported-by: kernel test robot Reviewed-by: Krzysztof Kozlowski Signed-off-by: Li Yang --- drivers/soc/fsl/dpio/qbman-portal.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c index 0ab85bfb116f..659b4a570d5b 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.c +++ b/drivers/soc/fsl/dpio/qbman-portal.c @@ -647,7 +647,6 @@ int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s, const uint32_t *cl = (uint32_t *)d; uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask; int i, num_enqueued = 0; - uint64_t addr_cena; spin_lock(&s->access_spinlock); half_mask = (s->eqcr.pi_ci_mask>>1); @@ -701,7 +700,6 @@ int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s, /* Flush all the cacheline without load/store in between */ eqcr_pi = s->eqcr.pi; - addr_cena = (size_t)s->addr_cena; for (i = 0; i < num_enqueued; i++) eqcr_pi++; s->eqcr.pi = eqcr_pi & full_mask; From 5ed2da99e3fcf3eee32a050fd31eb62d49575533 Mon Sep 17 00:00:00 2001 From: Liu Shixin Date: Mon, 14 Sep 2020 12:17:52 +0800 Subject: [PATCH 112/131] soc: fsl: qman: convert to use be32_add_cpu() Signed-off-by: Liu Shixin Signed-off-by: Li Yang --- drivers/soc/fsl/qbman/qman_test_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qbman/qman_test_api.c b/drivers/soc/fsl/qbman/qman_test_api.c index 2895d062cf51..7066b2f1467c 100644 --- a/drivers/soc/fsl/qbman/qman_test_api.c +++ b/drivers/soc/fsl/qbman/qman_test_api.c @@ -86,7 +86,7 @@ static void fd_inc(struct qm_fd *fd) len--; qm_fd_set_param(fd, fmt, off, len); - fd->cmd = cpu_to_be32(be32_to_cpu(fd->cmd) + 1); + be32_add_cpu(&fd->cmd, 1); } /* The only part of the 'fd' we can't memcmp() is the ppid */ From d97b957e32b1e7527a9b6652fa6e795f2861df7d Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Tue, 4 Aug 2020 21:56:44 +0800 Subject: [PATCH 113/131] soc: fsl: qe: Remove unnessesary check in ucc_set_tdm_rxtx_clk Fix smatch warning: drivers/soc/fsl/qe/ucc.c:526 ucc_set_tdm_rxtx_clk() warn: unsigned 'tdm_num' is never less than zero. 'tdm_num' is u32 type, never less than zero. Signed-off-by: Wang Hai Signed-off-by: Li Yang --- drivers/soc/fsl/qe/ucc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qe/ucc.c b/drivers/soc/fsl/qe/ucc.c index cac0fb7693a0..21dbcd787cd5 100644 --- a/drivers/soc/fsl/qe/ucc.c +++ b/drivers/soc/fsl/qe/ucc.c @@ -523,7 +523,7 @@ int ucc_set_tdm_rxtx_clk(u32 tdm_num, enum qe_clock clock, qe_mux_reg = &qe_immr->qmx; - if (tdm_num > 7 || tdm_num < 0) + if (tdm_num > 7) return -EINVAL; /* The communications direction must be RX or TX */ From a442abbbe186e14128d18bc3e42fb0fbf1a62210 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 20 Jul 2020 22:21:59 +0800 Subject: [PATCH 114/131] reset: imx7: Support module build Use module_platform_driver(), add module device table, author, description and license to support module build, and CONFIG_RESET_IMX7 is changed to default 'y' ONLY for i.MX7D, other platforms need to select it in defconfig. Signed-off-by: Anson Huang Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 5 +++-- drivers/reset/reset-imx7.c | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index d9efbfd29646..19f9773133dd 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -65,9 +65,10 @@ config RESET_HSDK This enables the reset controller driver for HSDK board. config RESET_IMX7 - bool "i.MX7/8 Reset Driver" if COMPILE_TEST + tristate "i.MX7/8 Reset Driver" depends on HAS_IOMEM - default SOC_IMX7D || (ARM64 && ARCH_MXC) + depends on SOC_IMX7D || (ARM64 && ARCH_MXC) || COMPILE_TEST + default y if SOC_IMX7D select MFD_SYSCON help This enables the reset controller driver for i.MX7 SoCs. diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c index d170fe663210..9832033a702a 100644 --- a/drivers/reset/reset-imx7.c +++ b/drivers/reset/reset-imx7.c @@ -8,7 +8,7 @@ */ #include -#include +#include #include #include #include @@ -386,6 +386,7 @@ static const struct of_device_id imx7_reset_dt_ids[] = { { .compatible = "fsl,imx8mp-src", .data = &variant_imx8mp }, { /* sentinel */ }, }; +MODULE_DEVICE_TABLE(of, imx7_reset_dt_ids); static struct platform_driver imx7_reset_driver = { .probe = imx7_reset_probe, @@ -394,4 +395,8 @@ static struct platform_driver imx7_reset_driver = { .of_match_table = imx7_reset_dt_ids, }, }; -builtin_platform_driver(imx7_reset_driver); +module_platform_driver(imx7_reset_driver); + +MODULE_AUTHOR("Andrey Smirnov "); +MODULE_DESCRIPTION("NXP i.MX7 reset driver"); +MODULE_LICENSE("GPL v2"); From a297104aceeb312600b0efaf8a281ad0f17167d2 Mon Sep 17 00:00:00 2001 From: Sai Krishna Potthuri Date: Wed, 22 Jul 2020 12:46:04 +0530 Subject: [PATCH 115/131] dt-bindings: reset: Updated binding for Versal reset driver Added documentation and Versal reset indices to describe about Versal reset driver bindings. In Versal all reset indices includes Class, SubClass, Type, Index information whereas class refers to clock, reset, power etc., Underlying firmware in Versal have such classification and expects the ID to be this way. [13:0] - Index bits [19:14] - Type bits [25:20] - SubClass bits [31:26] - Class bits. Signed-off-by: Sai Krishna Potthuri Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- .../bindings/reset/xlnx,zynqmp-reset.txt | 11 +- .../dt-bindings/reset/xlnx-versal-resets.h | 105 ++++++++++++++++++ 2 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 include/dt-bindings/reset/xlnx-versal-resets.h diff --git a/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt b/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt index 27a45fe5ecf1..ed836868dbf1 100644 --- a/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt +++ b/Documentation/devicetree/bindings/reset/xlnx,zynqmp-reset.txt @@ -1,7 +1,7 @@ -------------------------------------------------------------------------- - = Zynq UltraScale+ MPSoC reset driver binding = + = Zynq UltraScale+ MPSoC and Versal reset driver binding = -------------------------------------------------------------------------- -The Zynq UltraScale+ MPSoC has several different resets. +The Zynq UltraScale+ MPSoC and Versal has several different resets. See Chapter 36 of the Zynq UltraScale+ MPSoC TRM (UG) for more information about zynqmp resets. @@ -10,7 +10,8 @@ Please also refer to reset.txt in this directory for common reset controller binding usage. Required Properties: -- compatible: "xlnx,zynqmp-reset" +- compatible: "xlnx,zynqmp-reset" for Zynq UltraScale+ MPSoC platform + "xlnx,versal-reset" for Versal platform - #reset-cells: Specifies the number of cells needed to encode reset line, should be 1 @@ -37,8 +38,10 @@ Device nodes that need access to reset lines should specify them as a reset phandle in their corresponding node as specified in reset.txt. -For list of all valid reset indicies see +For list of all valid reset indices for Zynq UltraScale+ MPSoC see +For list of all valid reset indices for Versal see + Example: diff --git a/include/dt-bindings/reset/xlnx-versal-resets.h b/include/dt-bindings/reset/xlnx-versal-resets.h new file mode 100644 index 000000000000..895424e9b0e5 --- /dev/null +++ b/include/dt-bindings/reset/xlnx-versal-resets.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Xilinx, Inc. + */ + +#ifndef _DT_BINDINGS_VERSAL_RESETS_H +#define _DT_BINDINGS_VERSAL_RESETS_H + +#define VERSAL_RST_PMC_POR (0xc30c001U) +#define VERSAL_RST_PMC (0xc410002U) +#define VERSAL_RST_PS_POR (0xc30c003U) +#define VERSAL_RST_PL_POR (0xc30c004U) +#define VERSAL_RST_NOC_POR (0xc30c005U) +#define VERSAL_RST_FPD_POR (0xc30c006U) +#define VERSAL_RST_ACPU_0_POR (0xc30c007U) +#define VERSAL_RST_ACPU_1_POR (0xc30c008U) +#define VERSAL_RST_OCM2_POR (0xc30c009U) +#define VERSAL_RST_PS_SRST (0xc41000aU) +#define VERSAL_RST_PL_SRST (0xc41000bU) +#define VERSAL_RST_NOC (0xc41000cU) +#define VERSAL_RST_NPI (0xc41000dU) +#define VERSAL_RST_SYS_RST_1 (0xc41000eU) +#define VERSAL_RST_SYS_RST_2 (0xc41000fU) +#define VERSAL_RST_SYS_RST_3 (0xc410010U) +#define VERSAL_RST_FPD (0xc410011U) +#define VERSAL_RST_PL0 (0xc410012U) +#define VERSAL_RST_PL1 (0xc410013U) +#define VERSAL_RST_PL2 (0xc410014U) +#define VERSAL_RST_PL3 (0xc410015U) +#define VERSAL_RST_APU (0xc410016U) +#define VERSAL_RST_ACPU_0 (0xc410017U) +#define VERSAL_RST_ACPU_1 (0xc410018U) +#define VERSAL_RST_ACPU_L2 (0xc410019U) +#define VERSAL_RST_ACPU_GIC (0xc41001aU) +#define VERSAL_RST_RPU_ISLAND (0xc41001bU) +#define VERSAL_RST_RPU_AMBA (0xc41001cU) +#define VERSAL_RST_R5_0 (0xc41001dU) +#define VERSAL_RST_R5_1 (0xc41001eU) +#define VERSAL_RST_SYSMON_PMC_SEQ_RST (0xc41001fU) +#define VERSAL_RST_SYSMON_PMC_CFG_RST (0xc410020U) +#define VERSAL_RST_SYSMON_FPD_CFG_RST (0xc410021U) +#define VERSAL_RST_SYSMON_FPD_SEQ_RST (0xc410022U) +#define VERSAL_RST_SYSMON_LPD (0xc410023U) +#define VERSAL_RST_PDMA_RST1 (0xc410024U) +#define VERSAL_RST_PDMA_RST0 (0xc410025U) +#define VERSAL_RST_ADMA (0xc410026U) +#define VERSAL_RST_TIMESTAMP (0xc410027U) +#define VERSAL_RST_OCM (0xc410028U) +#define VERSAL_RST_OCM2_RST (0xc410029U) +#define VERSAL_RST_IPI (0xc41002aU) +#define VERSAL_RST_SBI (0xc41002bU) +#define VERSAL_RST_LPD (0xc41002cU) +#define VERSAL_RST_QSPI (0xc10402dU) +#define VERSAL_RST_OSPI (0xc10402eU) +#define VERSAL_RST_SDIO_0 (0xc10402fU) +#define VERSAL_RST_SDIO_1 (0xc104030U) +#define VERSAL_RST_I2C_PMC (0xc104031U) +#define VERSAL_RST_GPIO_PMC (0xc104032U) +#define VERSAL_RST_GEM_0 (0xc104033U) +#define VERSAL_RST_GEM_1 (0xc104034U) +#define VERSAL_RST_SPARE (0xc104035U) +#define VERSAL_RST_USB_0 (0xc104036U) +#define VERSAL_RST_UART_0 (0xc104037U) +#define VERSAL_RST_UART_1 (0xc104038U) +#define VERSAL_RST_SPI_0 (0xc104039U) +#define VERSAL_RST_SPI_1 (0xc10403aU) +#define VERSAL_RST_CAN_FD_0 (0xc10403bU) +#define VERSAL_RST_CAN_FD_1 (0xc10403cU) +#define VERSAL_RST_I2C_0 (0xc10403dU) +#define VERSAL_RST_I2C_1 (0xc10403eU) +#define VERSAL_RST_GPIO_LPD (0xc10403fU) +#define VERSAL_RST_TTC_0 (0xc104040U) +#define VERSAL_RST_TTC_1 (0xc104041U) +#define VERSAL_RST_TTC_2 (0xc104042U) +#define VERSAL_RST_TTC_3 (0xc104043U) +#define VERSAL_RST_SWDT_FPD (0xc104044U) +#define VERSAL_RST_SWDT_LPD (0xc104045U) +#define VERSAL_RST_USB (0xc104046U) +#define VERSAL_RST_DPC (0xc208047U) +#define VERSAL_RST_PMCDBG (0xc208048U) +#define VERSAL_RST_DBG_TRACE (0xc208049U) +#define VERSAL_RST_DBG_FPD (0xc20804aU) +#define VERSAL_RST_DBG_TSTMP (0xc20804bU) +#define VERSAL_RST_RPU0_DBG (0xc20804cU) +#define VERSAL_RST_RPU1_DBG (0xc20804dU) +#define VERSAL_RST_HSDP (0xc20804eU) +#define VERSAL_RST_DBG_LPD (0xc20804fU) +#define VERSAL_RST_CPM_POR (0xc30c050U) +#define VERSAL_RST_CPM (0xc410051U) +#define VERSAL_RST_CPMDBG (0xc208052U) +#define VERSAL_RST_PCIE_CFG (0xc410053U) +#define VERSAL_RST_PCIE_CORE0 (0xc410054U) +#define VERSAL_RST_PCIE_CORE1 (0xc410055U) +#define VERSAL_RST_PCIE_DMA (0xc410056U) +#define VERSAL_RST_CMN (0xc410057U) +#define VERSAL_RST_L2_0 (0xc410058U) +#define VERSAL_RST_L2_1 (0xc410059U) +#define VERSAL_RST_ADDR_REMAP (0xc41005aU) +#define VERSAL_RST_CPI0 (0xc41005bU) +#define VERSAL_RST_CPI1 (0xc41005cU) +#define VERSAL_RST_XRAM (0xc30c05dU) +#define VERSAL_RST_AIE_ARRAY (0xc10405eU) +#define VERSAL_RST_AIE_SHIM (0xc10405fU) + +#endif From 552f388bbe1ffe486f89d8b97cf19e79dbe55b5e Mon Sep 17 00:00:00 2001 From: Sai Krishna Potthuri Date: Wed, 22 Jul 2020 12:46:05 +0530 Subject: [PATCH 116/131] reset: reset-zynqmp: Added support for Versal platform Updated the reset driver to support Versal platform. As part of adding Versal support - Added Versal specific compatible string. - Reset Id and number of resets are different for Versal and ZynqMP, hence taken care of these two based on compatible string. Signed-off-by: Sai Krishna Potthuri Signed-off-by: Philipp Zabel --- drivers/reset/reset-zynqmp.c | 50 +++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c index 373ea8d4f7a1..ebd433fa09dd 100644 --- a/drivers/reset/reset-zynqmp.c +++ b/drivers/reset/reset-zynqmp.c @@ -9,12 +9,20 @@ #include #include #include +#include #define ZYNQMP_NR_RESETS (ZYNQMP_PM_RESET_END - ZYNQMP_PM_RESET_START) #define ZYNQMP_RESET_ID ZYNQMP_PM_RESET_START +#define VERSAL_NR_RESETS 95 + +struct zynqmp_reset_soc_data { + u32 reset_id; + u32 num_resets; +}; struct zynqmp_reset_data { struct reset_controller_dev rcdev; + const struct zynqmp_reset_soc_data *data; }; static inline struct zynqmp_reset_data * @@ -26,23 +34,28 @@ to_zynqmp_reset_data(struct reset_controller_dev *rcdev) static int zynqmp_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) { - return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id, + struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev); + + return zynqmp_pm_reset_assert(priv->data->reset_id + id, PM_RESET_ACTION_ASSERT); } static int zynqmp_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) { - return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id, + struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev); + + return zynqmp_pm_reset_assert(priv->data->reset_id + id, PM_RESET_ACTION_RELEASE); } static int zynqmp_reset_status(struct reset_controller_dev *rcdev, unsigned long id) { + struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev); int val, err; - err = zynqmp_pm_reset_get_status(ZYNQMP_RESET_ID + id, &val); + err = zynqmp_pm_reset_get_status(priv->data->reset_id + id, &val); if (err) return err; @@ -52,10 +65,28 @@ static int zynqmp_reset_status(struct reset_controller_dev *rcdev, static int zynqmp_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) { - return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id, + struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev); + + return zynqmp_pm_reset_assert(priv->data->reset_id + id, PM_RESET_ACTION_PULSE); } +static int zynqmp_reset_of_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + return reset_spec->args[0]; +} + +static const struct zynqmp_reset_soc_data zynqmp_reset_data = { + .reset_id = ZYNQMP_RESET_ID, + .num_resets = ZYNQMP_NR_RESETS, +}; + +static const struct zynqmp_reset_soc_data versal_reset_data = { + .reset_id = 0, + .num_resets = VERSAL_NR_RESETS, +}; + static const struct reset_control_ops zynqmp_reset_ops = { .reset = zynqmp_reset_reset, .assert = zynqmp_reset_assert, @@ -71,18 +102,25 @@ static int zynqmp_reset_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + priv->data = of_device_get_match_data(&pdev->dev); + if (!priv->data) + return -EINVAL; + platform_set_drvdata(pdev, priv); priv->rcdev.ops = &zynqmp_reset_ops; priv->rcdev.owner = THIS_MODULE; priv->rcdev.of_node = pdev->dev.of_node; - priv->rcdev.nr_resets = ZYNQMP_NR_RESETS; + priv->rcdev.nr_resets = priv->data->num_resets; + priv->rcdev.of_reset_n_cells = 1; + priv->rcdev.of_xlate = zynqmp_reset_of_xlate; return devm_reset_controller_register(&pdev->dev, &priv->rcdev); } static const struct of_device_id zynqmp_reset_dt_ids[] = { - { .compatible = "xlnx,zynqmp-reset", }, + { .compatible = "xlnx,zynqmp-reset", .data = &zynqmp_reset_data, }, + { .compatible = "xlnx,versal-reset", .data = &versal_reset_data, }, { /* sentinel */ }, }; From 3315be577411d55df393fc8ab9f7a384cb90835a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 28 Jul 2020 19:10:11 +0200 Subject: [PATCH 117/131] reset: Fix and extend kerneldoc Fix W=1 compile warnings (invalid kerneldoc): drivers/reset/core.c:50: warning: Function parameter or member 'array' not described in 'reset_control' drivers/reset/core.c:50: warning: Function parameter or member 'deassert_count' not described in 'reset_control' Signed-off-by: Krzysztof Kozlowski Signed-off-by: Philipp Zabel --- drivers/reset/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 01c0c7aa835c..a2df88e90011 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -32,7 +32,8 @@ static LIST_HEAD(reset_lookup_list); * @refcnt: Number of gets of this reset_control * @acquired: Only one reset_control may be acquired for a given rcdev and id. * @shared: Is this a shared (1), or an exclusive (0) reset_control? - * @deassert_cnt: Number of times this reset line has been deasserted + * @array: Is this an array of reset controls (1)? + * @deassert_count: Number of times this reset line has been deasserted * @triggered_count: Number of times this reset line has been reset. Currently * only used for shared resets, which means that the value * will be either 0 or 1. From cbc111d1552ee1364a16cfd1162dd9e8f969101e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 30 Jul 2020 14:46:08 +0800 Subject: [PATCH 118/131] dt-bindings: reset: imx8mq: add m4 reset Add the m4 reset used by the remoteproc driver Signed-off-by: Peng Fan Acked-by: Rob Herring Signed-off-by: Philipp Zabel --- include/dt-bindings/reset/imx8mq-reset.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/reset/imx8mq-reset.h b/include/dt-bindings/reset/imx8mq-reset.h index a5b570737582..705870693ec2 100644 --- a/include/dt-bindings/reset/imx8mq-reset.h +++ b/include/dt-bindings/reset/imx8mq-reset.h @@ -58,7 +58,10 @@ #define IMX8MQ_RESET_DDRC2_PRST 47 /* i.MX8MM/i.MX8MN does NOT support */ #define IMX8MQ_RESET_DDRC2_CORE_RESET 48 /* i.MX8MM/i.MX8MN does NOT support */ #define IMX8MQ_RESET_DDRC2_PHY_RESET 49 /* i.MX8MM/i.MX8MN does NOT support */ +#define IMX8MQ_RESET_SW_M4C_RST 50 +#define IMX8MQ_RESET_SW_M4P_RST 51 +#define IMX8MQ_RESET_M4_ENABLE 52 -#define IMX8MQ_RESET_NUM 50 +#define IMX8MQ_RESET_NUM 53 #endif From f008c403270cc2b830868ec0967a3cac7f18a984 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 30 Jul 2020 14:46:09 +0800 Subject: [PATCH 119/131] reset: imx7: add the cm4 reset for i.MX8MQ Add the cm4 reset used by the remoteproc driver Signed-off-by: Peng Fan Signed-off-by: Philipp Zabel --- drivers/reset/reset-imx7.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c index 9832033a702a..b60534a1e0ef 100644 --- a/drivers/reset/reset-imx7.c +++ b/drivers/reset/reset-imx7.c @@ -178,6 +178,9 @@ static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = { [IMX8MQ_RESET_A53_SOC_DBG_RESET] = { SRC_A53RCR0, BIT(20) }, [IMX8MQ_RESET_A53_L2RESET] = { SRC_A53RCR0, BIT(21) }, [IMX8MQ_RESET_SW_NON_SCLR_M4C_RST] = { SRC_M4RCR, BIT(0) }, + [IMX8MQ_RESET_SW_M4C_RST] = { SRC_M4RCR, BIT(1) }, + [IMX8MQ_RESET_SW_M4P_RST] = { SRC_M4RCR, BIT(2) }, + [IMX8MQ_RESET_M4_ENABLE] = { SRC_M4RCR, BIT(3) }, [IMX8MQ_RESET_OTG1_PHY_RESET] = { SRC_USBOPHY1_RCR, BIT(0) }, [IMX8MQ_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) }, [IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N] = { SRC_MIPIPHY_RCR, BIT(1) }, @@ -238,6 +241,7 @@ static int imx8mq_reset_set(struct reset_controller_dev *rcdev, case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N: /* fallthrough */ case IMX8MQ_RESET_MIPI_DSI_RESET_N: /* fallthrough */ case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N: /* fallthrough */ + case IMX8MQ_RESET_M4_ENABLE: value = assert ? 0 : bit; break; } From 68a215164e1938490c82eecccb263d30c586b84a Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Mon, 31 Aug 2020 22:38:04 +0200 Subject: [PATCH 120/131] reset: sti: reset-syscfg: fix struct description warnings Fix formating of struct description to avoid warning highlighted by W=1 compilation. Fixes: e5d76075d930 ("drivers: reset: STi SoC system configuration reset controller support") Signed-off-by: Alain Volmat Signed-off-by: Philipp Zabel --- drivers/reset/sti/reset-syscfg.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c index 91215bb88f62..99b63035fe72 100644 --- a/drivers/reset/sti/reset-syscfg.c +++ b/drivers/reset/sti/reset-syscfg.c @@ -17,7 +17,7 @@ #include "reset-syscfg.h" /** - * Reset channel regmap configuration + * struct syscfg_reset_channel - Reset channel regmap configuration * * @reset: regmap field for the channel's reset bit. * @ack: regmap field for the channel's ack bit (optional). @@ -28,8 +28,9 @@ struct syscfg_reset_channel { }; /** - * A reset controller which groups together a set of related reset bits, which - * may be located in different system configuration registers. + * struct syscfg_reset_controller - A reset controller which groups together + * a set of related reset bits, which may be located in different system + * configuration registers. * * @rst: base reset controller structure. * @active_low: are the resets in this controller active low, i.e. clearing From 5aabf1180fa9a8d876debd39a8cfb60b022019bc Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 21 Sep 2020 15:21:35 -0700 Subject: [PATCH 121/131] soc: amlogic: pm-domains: use always-on flag Rather than use a governor to keep these domains always-on, instead use the flag GENPD_FLAG_ALWAYS_ON. This has the same effect, but with much lower overhead since the governor path is not used at all. Signed-off-by: Kevin Hilman Acked-by: Neil Armstrong Signed-off-by: Kevin Hilman Link: https://lore.kernel.org/r/20200921222135.7145-1-khilman@baylibre.com --- drivers/soc/amlogic/meson-ee-pwrc.c | 4 ++-- drivers/soc/amlogic/meson-gx-pwrc-vpu.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c index 9fd97ad02806..5164a4dc2352 100644 --- a/drivers/soc/amlogic/meson-ee-pwrc.c +++ b/drivers/soc/amlogic/meson-ee-pwrc.c @@ -450,8 +450,8 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev, if (ret) return ret; - ret = pm_genpd_init(&dom->base, &pm_domain_always_on_gov, - false); + dom->base.flags = GENPD_FLAG_ALWAYS_ON; + ret = pm_genpd_init(&dom->base, NULL, false); if (ret) return ret; } else { diff --git a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c index 511b6856225d..21b4bc811c00 100644 --- a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c +++ b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c @@ -339,8 +339,8 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev) return ret; } - pm_genpd_init(&vpu_pd->genpd, &pm_domain_always_on_gov, - powered_off); + vpu_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON; + pm_genpd_init(&vpu_pd->genpd, NULL, powered_off); return of_genpd_add_provider_simple(pdev->dev.of_node, &vpu_pd->genpd); From 11b490c6aea9666047d51127a665221102277edb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 29 Jul 2020 09:44:14 +0200 Subject: [PATCH 122/131] soc: mediatek: mtk-infracfg: Fix kerneldoc Fix W=1 compile warnings (invalid kerneldoc): drivers/soc/mediatek/mtk-infracfg.c:34: warning: Function parameter or member 'infracfg' not described in 'mtk_infracfg_set_bus_protection' drivers/soc/mediatek/mtk-infracfg.c:34: warning: Excess function parameter 'regmap' description in 'mtk_infracfg_set_bus_protection' Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200729074415.28393-1-krzk@kernel.org Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-infracfg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c index 341c7ac250e3..4a123796aad3 100644 --- a/drivers/soc/mediatek/mtk-infracfg.c +++ b/drivers/soc/mediatek/mtk-infracfg.c @@ -19,7 +19,7 @@ /** * mtk_infracfg_set_bus_protection - enable bus protection - * @regmap: The infracfg regmap + * @infracfg: The infracfg regmap * @mask: The mask containing the protection bits to be enabled. * @reg_update: The boolean flag determines to set the protection bits * by regmap_update_bits with enable register(PROTECTEN) or @@ -50,7 +50,7 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask, /** * mtk_infracfg_clear_bus_protection - disable bus protection - * @regmap: The infracfg regmap + * @infracfg: The infracfg regmap * @mask: The mask containing the protection bits to be disabled. * @reg_update: The boolean flag determines to clear the protection bits * by regmap_update_bits with enable register(PROTECTEN) or From 2b8cf38343b378ed3717822c46f69cdee607055f Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:06 +0800 Subject: [PATCH 123/131] soc: mediatek: cmdq: add address shift in jump Add address shift when compose jump instruction to compatible with 35bit format. Signed-off-by: Dennis YC Hsieh Reviewed-by: Bibby Hsieh Link: https://lore.kernel.org/r/1594136714-11650-2-git-send-email-dennis-yc.hsieh@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index dc644cfb6419..9faf78fbed3a 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -329,7 +329,8 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt) /* JUMP to end */ inst.op = CMDQ_CODE_JUMP; - inst.value = CMDQ_JUMP_PASS; + inst.value = CMDQ_JUMP_PASS >> + cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan); err = cmdq_pkt_append_command(pkt, inst); return err; From 5f6e560c2dd5be3ae446f20ae97263cbfa309630 Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:07 +0800 Subject: [PATCH 124/131] soc: mediatek: cmdq: add write_s function add write_s function in cmdq helper functions which writes value contains in internal register to address with large dma access support. Signed-off-by: Dennis YC Hsieh Link: https://lore.kernel.org/r/1594136714-11650-3-git-send-email-dennis-yc.hsieh@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 19 +++++++++++++++++++ include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + include/linux/soc/mediatek/mtk-cmdq.h | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 9faf78fbed3a..880349b3f16c 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -18,6 +18,10 @@ struct cmdq_instruction { union { u32 value; u32 mask; + struct { + u16 arg_c; + u16 src_reg; + }; }; union { u16 offset; @@ -223,6 +227,21 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, } EXPORT_SYMBOL(cmdq_pkt_write_mask); +int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, + u16 addr_low, u16 src_reg_idx) +{ + struct cmdq_instruction inst = {}; + + inst.op = CMDQ_CODE_WRITE_S; + inst.src_t = CMDQ_REG_TYPE; + inst.sop = high_addr_reg_idx; + inst.offset = addr_low; + inst.src_reg = src_reg_idx; + + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_write_s); + int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) { struct cmdq_instruction inst = { {0} }; diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index 05eea1aef5aa..1f76cfedb16d 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -60,6 +60,7 @@ enum cmdq_code { CMDQ_CODE_JUMP = 0x10, CMDQ_CODE_WFE = 0x20, CMDQ_CODE_EOC = 0x40, + CMDQ_CODE_WRITE_S = 0x90, CMDQ_CODE_LOGIC = 0xa0, }; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 2249ecaf77e4..9b0c57a0063d 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -12,6 +12,8 @@ #include #define CMDQ_NO_TIMEOUT 0xffffffffu +#define CMDQ_ADDR_HIGH(addr) ((u32)(((addr) >> 16) & GENMASK(31, 0))) +#define CMDQ_ADDR_LOW(addr) ((u16)(addr) | BIT(1)) struct cmdq_pkt; @@ -102,6 +104,23 @@ int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value, u32 mask); +/** + * cmdq_pkt_write_s() - append write_s command to the CMDQ packet + * @pkt: the CMDQ packet + * @high_addr_reg_idx: internal register ID which contains high address of pa + * @addr_low: low address of pa + * @src_reg_idx: the CMDQ internal register ID which cache source value + * + * Return: 0 for success; else the error code is returned + * + * Support write value to physical address without subsys. Use CMDQ_ADDR_HIGH() + * to get high address and call cmdq_pkt_assign() to assign value into internal + * reg. Also use CMDQ_ADDR_LOW() to get low address for addr_low parameter when + * call to this function. + */ +int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, + u16 addr_low, u16 src_reg_idx); + /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet * @pkt: the CMDQ packet From 11c7842d41c82eb3551a0606ccba89ac33318b62 Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:08 +0800 Subject: [PATCH 125/131] soc: mediatek: cmdq: add write_s_mask function add write_s_mask function in cmdq helper functions which writes value contains in internal register to address with mask and large dma access support. Signed-off-by: Dennis YC Hsieh Link: https://lore.kernel.org/r/1594136714-11650-4-git-send-email-dennis-yc.hsieh@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 23 +++++++++++++++++++++++ include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + include/linux/soc/mediatek/mtk-cmdq.h | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 880349b3f16c..550e9e7e3ff2 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -242,6 +242,29 @@ int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, } EXPORT_SYMBOL(cmdq_pkt_write_s); +int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, + u16 addr_low, u16 src_reg_idx, u32 mask) +{ + struct cmdq_instruction inst = {}; + int err; + + inst.op = CMDQ_CODE_MASK; + inst.mask = ~mask; + err = cmdq_pkt_append_command(pkt, inst); + if (err < 0) + return err; + + inst.mask = 0; + inst.op = CMDQ_CODE_WRITE_S_MASK; + inst.src_t = CMDQ_REG_TYPE; + inst.sop = high_addr_reg_idx; + inst.offset = addr_low; + inst.src_reg = src_reg_idx; + + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_write_s_mask); + int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) { struct cmdq_instruction inst = { {0} }; diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index 1f76cfedb16d..90d1d8e64412 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -61,6 +61,7 @@ enum cmdq_code { CMDQ_CODE_WFE = 0x20, CMDQ_CODE_EOC = 0x40, CMDQ_CODE_WRITE_S = 0x90, + CMDQ_CODE_WRITE_S_MASK = 0x91, CMDQ_CODE_LOGIC = 0xa0, }; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 9b0c57a0063d..53230341bf94 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -121,6 +121,24 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, u16 src_reg_idx); +/** + * cmdq_pkt_write_s_mask() - append write_s with mask command to the CMDQ packet + * @pkt: the CMDQ packet + * @high_addr_reg_idx: internal register ID which contains high address of pa + * @addr_low: low address of pa + * @src_reg_idx: the CMDQ internal register ID which cache source value + * @mask: the specified target address mask, use U32_MAX if no need + * + * Return: 0 for success; else the error code is returned + * + * Support write value to physical address without subsys. Use CMDQ_ADDR_HIGH() + * to get high address and call cmdq_pkt_assign() to assign value into internal + * reg. Also use CMDQ_ADDR_LOW() to get low address for addr_low parameter when + * call to this function. + */ +int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, + u16 addr_low, u16 src_reg_idx, u32 mask); + /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet * @pkt: the CMDQ packet From d3b04aab06fbc33ddea15725f3ff1667c9717929 Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:09 +0800 Subject: [PATCH 126/131] soc: mediatek: cmdq: add read_s function Add read_s function in cmdq helper functions which support read value from register or dma physical address into gce internal register. Signed-off-by: Dennis YC Hsieh Link: https://lore.kernel.org/r/1594136714-11650-5-git-send-email-dennis-yc.hsieh@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 15 +++++++++++++++ include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + include/linux/soc/mediatek/mtk-cmdq.h | 12 ++++++++++++ 3 files changed, 28 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 550e9e7e3ff2..ed9f5e63c195 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -227,6 +227,21 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, } EXPORT_SYMBOL(cmdq_pkt_write_mask); +int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, + u16 reg_idx) +{ + struct cmdq_instruction inst = {}; + + inst.op = CMDQ_CODE_READ_S; + inst.dst_t = CMDQ_REG_TYPE; + inst.sop = high_addr_reg_idx; + inst.reg_dst = reg_idx; + inst.src_reg = addr_low; + + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_read_s); + int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, u16 src_reg_idx) { diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index 90d1d8e64412..efbd8a9eb2d1 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -60,6 +60,7 @@ enum cmdq_code { CMDQ_CODE_JUMP = 0x10, CMDQ_CODE_WFE = 0x20, CMDQ_CODE_EOC = 0x40, + CMDQ_CODE_READ_S = 0x80, CMDQ_CODE_WRITE_S = 0x90, CMDQ_CODE_WRITE_S_MASK = 0x91, CMDQ_CODE_LOGIC = 0xa0, diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 53230341bf94..cd7ec714344e 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -104,6 +104,18 @@ int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value, u32 mask); +/* + * cmdq_pkt_read_s() - append read_s command to the CMDQ packet + * @pkt: the CMDQ packet + * @high_addr_reg_idx: internal register ID which contains high address of pa + * @addr_low: low address of pa + * @reg_idx: the CMDQ internal register ID to cache read data + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, + u16 reg_idx); + /** * cmdq_pkt_write_s() - append write_s command to the CMDQ packet * @pkt: the CMDQ packet From 1af43fce813ebd74c76d080beb261603bd0853e1 Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:10 +0800 Subject: [PATCH 127/131] soc: mediatek: cmdq: add write_s value function add write_s function in cmdq helper functions which writes a constant value to address with large dma access support. Signed-off-by: Dennis YC Hsieh Link: https://lore.kernel.org/r/1594136714-11650-6-git-send-email-dennis-yc.hsieh@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 14 ++++++++++++++ include/linux/soc/mediatek/mtk-cmdq.h | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index ed9f5e63c195..4e86b65815fc 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -280,6 +280,20 @@ int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, } EXPORT_SYMBOL(cmdq_pkt_write_s_mask); +int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, + u16 addr_low, u32 value) +{ + struct cmdq_instruction inst = {}; + + inst.op = CMDQ_CODE_WRITE_S; + inst.sop = high_addr_reg_idx; + inst.offset = addr_low; + inst.value = value; + + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_write_s_value); + int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) { struct cmdq_instruction inst = { {0} }; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index cd7ec714344e..ae73e10da274 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -151,6 +151,19 @@ int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, u16 src_reg_idx, u32 mask); +/** + * cmdq_pkt_write_s_value() - append write_s command to the CMDQ packet which + * write value to a physical address + * @pkt: the CMDQ packet + * @high_addr_reg_idx: internal register ID which contains high address of pa + * @addr_low: low address of pa + * @value: the specified target value + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, + u16 addr_low, u32 value); + /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet * @pkt: the CMDQ packet From 88a2ffc48d5bc85119ef7961df12369dcd53b4d2 Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:11 +0800 Subject: [PATCH 128/131] soc: mediatek: cmdq: add write_s_mask value function add write_s_mask_value function in cmdq helper functions which writes a constant value to address with mask and large dma access support. Signed-off-by: Dennis YC Hsieh Link: https://lore.kernel.org/r/1594136714-11650-7-git-send-email-dennis-yc.hsieh@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 21 +++++++++++++++++++++ include/linux/soc/mediatek/mtk-cmdq.h | 15 +++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 4e86b65815fc..b6e25f216605 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -294,6 +294,27 @@ int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, } EXPORT_SYMBOL(cmdq_pkt_write_s_value); +int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, + u16 addr_low, u32 value, u32 mask) +{ + struct cmdq_instruction inst = {}; + int err; + + inst.op = CMDQ_CODE_MASK; + inst.mask = ~mask; + err = cmdq_pkt_append_command(pkt, inst); + if (err < 0) + return err; + + inst.op = CMDQ_CODE_WRITE_S_MASK; + inst.sop = high_addr_reg_idx; + inst.offset = addr_low; + inst.value = value; + + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value); + int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) { struct cmdq_instruction inst = { {0} }; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index ae73e10da274..d9390d76ee14 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -164,6 +164,21 @@ int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, u16 addr_low, u32 value); +/** + * cmdq_pkt_write_s_mask_value() - append write_s command with mask to the CMDQ + * packet which write value to a physical + * address + * @pkt: the CMDQ packet + * @high_addr_reg_idx: internal register ID which contains high address of pa + * @addr_low: low address of pa + * @value: the specified target value + * @mask: the specified target mask + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, + u16 addr_low, u32 value, u32 mask); + /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet * @pkt: the CMDQ packet From 946f1792d3d7942acfbc6afa9a733f608f4622d6 Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:12 +0800 Subject: [PATCH 129/131] soc: mediatek: cmdq: add jump function Add jump function so that client can jump to any address which contains instruction. Signed-off-by: Dennis YC Hsieh Link: https://lore.kernel.org/r/1594136714-11650-8-git-send-email-dennis-yc.hsieh@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-cmdq-helper.c | 13 +++++++++++++ include/linux/soc/mediatek/mtk-cmdq.h | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index b6e25f216605..d55dc3296105 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -13,6 +13,7 @@ #define CMDQ_POLL_ENABLE_MASK BIT(0) #define CMDQ_EOC_IRQ_EN BIT(0) #define CMDQ_REG_TYPE 1 +#define CMDQ_JUMP_RELATIVE 1 struct cmdq_instruction { union { @@ -407,6 +408,18 @@ int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) } EXPORT_SYMBOL(cmdq_pkt_assign); +int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr) +{ + struct cmdq_instruction inst = {}; + + inst.op = CMDQ_CODE_JUMP; + inst.offset = CMDQ_JUMP_RELATIVE; + inst.value = addr >> + cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan); + return cmdq_pkt_append_command(pkt, inst); +} +EXPORT_SYMBOL(cmdq_pkt_jump); + int cmdq_pkt_finalize(struct cmdq_pkt *pkt) { struct cmdq_instruction inst = { {0} }; diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index d9390d76ee14..34354e952f60 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -252,6 +252,17 @@ int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, */ int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value); +/** + * cmdq_pkt_jump() - Append jump command to the CMDQ packet, ask GCE + * to execute an instruction that change current thread PC to + * a physical address which should contains more instruction. + * @pkt: the CMDQ packet + * @addr: physical address of target instruction buffer + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr); + /** * cmdq_pkt_finalize() - Append EOC and jump command to pkt. * @pkt: the CMDQ packet From 23c22299cd290409c6b78f57c42b64f8dfb6dd92 Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:13 +0800 Subject: [PATCH 130/131] soc: mediatek: cmdq: add clear option in cmdq_pkt_wfe api Add clear parameter to let client decide if event should be clear to 0 after GCE receive it. Signed-off-by: Dennis YC Hsieh Acked-by: Chun-Kuang Hu Link: https://lore.kernel.org/r/1594136714-11650-9-git-send-email-dennis-yc.hsieh@mediatek.com [mb: fix commit message] Signed-off-by: Matthias Brugger --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 2 +- drivers/soc/mediatek/mtk-cmdq-helper.c | 5 +++-- include/linux/mailbox/mtk-cmdq-mailbox.h | 3 +-- include/linux/soc/mediatek/mtk-cmdq.h | 5 +++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 3fc5511330b9..2a332e297ebf 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -481,7 +481,7 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc) mbox_flush(mtk_crtc->cmdq_client->chan, 2000); cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE); cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); - cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event); + cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, true); mtk_crtc_ddp_config(crtc, cmdq_handle); cmdq_pkt_finalize(cmdq_handle); cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle); diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index d55dc3296105..505651b0d715 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -316,15 +316,16 @@ int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, } EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value); -int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear) { struct cmdq_instruction inst = { {0} }; + u32 clear_option = clear ? CMDQ_WFE_UPDATE : 0; if (event >= CMDQ_MAX_EVENT) return -EINVAL; inst.op = CMDQ_CODE_WFE; - inst.value = CMDQ_WFE_OPTION; + inst.value = CMDQ_WFE_OPTION | clear_option; inst.event = event; return cmdq_pkt_append_command(pkt, inst); diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index efbd8a9eb2d1..d5a983d65f05 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -28,8 +28,7 @@ * bit 16-27: update value * bit 31: 1 - update, 0 - no update */ -#define CMDQ_WFE_OPTION (CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | \ - CMDQ_WFE_WAIT_VALUE) +#define CMDQ_WFE_OPTION (CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE) /** cmdq event maximum */ #define CMDQ_MAX_EVENT 0x3ff diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 34354e952f60..960704d75994 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -182,11 +182,12 @@ int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet * @pkt: the CMDQ packet - * @event: the desired event type to "wait and CLEAR" + * @event: the desired event type to wait + * @clear: clear event or not after event arrive * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event); +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear); /** * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet From bee1abc9cc021f50b90f22a589d9ddc816a80db0 Mon Sep 17 00:00:00 2001 From: Dennis YC Hsieh Date: Tue, 7 Jul 2020 23:45:14 +0800 Subject: [PATCH 131/131] drm/mediatek: reduce clear event No need to clear event again since event always clear before wait. This fix depend on patch: "soc: mediatek: cmdq: add clear option in cmdq_pkt_wfe api" Fixes: 2f965be7f9008 ("drm/mediatek: apply CMDQ control flow") Signed-off-by: Dennis YC Hsieh Reviewed-by: Bibby Hsieh Acked-by: Chun-Kuang Hu Link: https://lore.kernel.org/r/1594136714-11650-10-git-send-email-dennis-yc.hsieh@mediatek.com Signed-off-by: Matthias Brugger --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 2a332e297ebf..bd16874bf2dd 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -481,7 +481,7 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc) mbox_flush(mtk_crtc->cmdq_client->chan, 2000); cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE); cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); - cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, true); + cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); mtk_crtc_ddp_config(crtc, cmdq_handle); cmdq_pkt_finalize(cmdq_handle); cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle);