From 41a21e578da4986685f013d45454a12457f01180 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 18 Jul 2022 20:28:24 +0100 Subject: soc: renesas: Kconfig: Enable IRQC driver for RZ/G2L SoC Select RENESAS_RZG2L_IRQC config option if ARCH_RZG2L is enabled so that IRQC driver is enabled on RZ/G2L (and alike) SoC's. Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20220718192824.7246-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index c50a6ce1b99d..390f52109cb7 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -44,6 +44,7 @@ config ARCH_RZG2L bool select PM select PM_GENERIC_DOMAINS + select RENESAS_RZG2L_IRQC config ARCH_RZN1 bool -- cgit v1.2.3 From 751c3e19d0a354eebd5efad40003a22585ffd0bf Mon Sep 17 00:00:00 2001 From: "Guilherme G. Piccoli" Date: Tue, 19 Jul 2022 16:53:17 -0300 Subject: soc: bcm: brcmstb: Document panic notifier action and remove useless header The panic notifier of this driver is very simple code-wise, just a memory write to a special position with some numeric code. But this is not clear from the semantic point-of-view, and there is no public documentation about that either. After discussing this in the mailing-lists [0] and having Florian explained it very well, document that in the code for the future generations asking the same questions. Also, while at it, remove a useless header. [0] https://lore.kernel.org/lkml/781cafb0-8d06-8b56-907a-5175c2da196a@gmail.com Cc: Brian Norris Cc: Doug Berger Cc: Justin Chen Cc: Lee Jones Cc: Markus Mayer Acked-by: Florian Fainelli Signed-off-by: Guilherme G. Piccoli Link: https://lore.kernel.org/r/20220719195325.402745-5-gpiccoli@igalia.com Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/pm/pm-arm.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/bcm/brcmstb/pm/pm-arm.c b/drivers/soc/bcm/brcmstb/pm/pm-arm.c index d6b30d521307..7643c9ade888 100644 --- a/drivers/soc/bcm/brcmstb/pm/pm-arm.c +++ b/drivers/soc/bcm/brcmstb/pm/pm-arm.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -664,7 +663,20 @@ static void __iomem *brcmstb_ioremap_match(const struct of_device_id *matches, return of_io_request_and_map(dn, index, dn->full_name); } - +/* + * The AON is a small domain in the SoC that can retain its state across + * various system wide sleep states and specific reset conditions; the + * AON DATA RAM is a small RAM of a few words (< 1KB) which can store + * persistent information across such events. + * + * The purpose of the below panic notifier is to help with notifying + * the bootloader that a panic occurred and so that it should try its + * best to preserve the DRAM contents holding that buffer for recovery + * by the kernel as opposed to wiping out DRAM clean again. + * + * Reference: comment from Florian Fainelli, at + * https://lore.kernel.org/lkml/781cafb0-8d06-8b56-907a-5175c2da196a@gmail.com + */ static int brcmstb_pm_panic_notify(struct notifier_block *nb, unsigned long action, void *data) { -- cgit v1.2.3 From 7bb49d774f481fdd7bd053e034e4d206770fda04 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Wed, 3 Aug 2022 10:54:52 -0700 Subject: arm64: bcmbca: Make BCM4908 drivers depend on ARCH_BCMBCA With Broadcom Broadband arch ARCH_BCMBCA supported in the kernel, this patch series migrate the ARCH_BCM4908 symbol to ARCH_BCMBCA. Hence replace ARCH_BCM4908 with ARCH_BCMBCA in subsystem Kconfig files. Signed-off-by: William Zhang Acked-by: Guenter Roeck (for watchdog) Acked-by: Bjorn Helgaas (for drivers/pci) Acked-by: Wolfram Sang (for i2c) Acked-by: Philipp Zabel (for reset) Link: https://lore.kernel.org/r/20220803175455.47638-7-william.zhang@broadcom.com Signed-off-by: Florian Fainelli --- drivers/i2c/busses/Kconfig | 4 ++-- drivers/mtd/parsers/Kconfig | 6 +++--- drivers/net/ethernet/broadcom/Kconfig | 4 ++-- drivers/pci/controller/Kconfig | 2 +- drivers/phy/broadcom/Kconfig | 4 ++-- drivers/pinctrl/bcm/Kconfig | 4 ++-- drivers/reset/Kconfig | 2 +- drivers/soc/bcm/bcm63xx/Kconfig | 4 ++-- drivers/tty/serial/Kconfig | 4 ++-- drivers/watchdog/Kconfig | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 7284206b278b..0c48d8a9f44a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -488,8 +488,8 @@ config I2C_BCM_KONA config I2C_BRCMSTB tristate "BRCM Settop/DSL I2C controller" - depends on ARCH_BCM2835 || ARCH_BCM4908 || ARCH_BCMBCA || \ - ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST + depends on ARCH_BCM2835 || ARCH_BCMBCA || ARCH_BRCMSTB || \ + BMIPS_GENERIC || COMPILE_TEST default y help If you say yes to this option, support will be included for the diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index b43df73927a0..d6db655a1d24 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -69,8 +69,8 @@ config MTD_OF_PARTS config MTD_OF_PARTS_BCM4908 bool "BCM4908 partitioning support" - depends on MTD_OF_PARTS && (ARCH_BCM4908 || COMPILE_TEST) - default ARCH_BCM4908 + depends on MTD_OF_PARTS && (ARCH_BCMBCA || COMPILE_TEST) + default ARCH_BCMBCA help This provides partitions parser for BCM4908 family devices that can have multiple "firmware" partitions. It takes care of @@ -78,7 +78,7 @@ config MTD_OF_PARTS_BCM4908 config MTD_OF_PARTS_LINKSYS_NS bool "Linksys Northstar partitioning support" - depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCM4908 || COMPILE_TEST) + depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCMBCA || COMPILE_TEST) default ARCH_BCM_5301X help This provides partitions parser for Linksys devices based on Broadcom diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 56e0fb07aec7..f4e1ca68d831 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -53,8 +53,8 @@ config B44_PCI config BCM4908_ENET tristate "Broadcom BCM4908 internal mac support" - depends on ARCH_BCM4908 || COMPILE_TEST - default y if ARCH_BCM4908 + depends on ARCH_BCMBCA || COMPILE_TEST + default y if ARCH_BCMBCA help This driver supports Ethernet controller integrated into Broadcom BCM4908 family SoCs. diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index d1c5fcf00a8a..bfd9bac37e24 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -274,7 +274,7 @@ config VMD config PCIE_BRCMSTB tristate "Broadcom Brcmstb PCIe host controller" - depends on ARCH_BRCMSTB || ARCH_BCM2835 || ARCH_BCM4908 || \ + depends on ARCH_BRCMSTB || ARCH_BCM2835 || ARCH_BCMBCA || \ BMIPS_GENERIC || COMPILE_TEST depends on OF depends on PCI_MSI_IRQ_DOMAIN diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig index 93a6a8ee4716..1d89a2fd9b79 100644 --- a/drivers/phy/broadcom/Kconfig +++ b/drivers/phy/broadcom/Kconfig @@ -93,11 +93,11 @@ config PHY_BRCM_SATA config PHY_BRCM_USB tristate "Broadcom STB USB PHY driver" - depends on ARCH_BCM4908 || ARCH_BRCMSTB || COMPILE_TEST + depends on ARCH_BCMBCA || ARCH_BRCMSTB || COMPILE_TEST depends on OF select GENERIC_PHY select SOC_BRCMSTB if ARCH_BRCMSTB - default ARCH_BCM4908 || ARCH_BRCMSTB + default ARCH_BCMBCA || ARCH_BRCMSTB help Enable this to support the Broadcom STB USB PHY. This driver is required by the USB XHCI, EHCI and OHCI diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig index 8f4d89806fcb..35b51ce4298e 100644 --- a/drivers/pinctrl/bcm/Kconfig +++ b/drivers/pinctrl/bcm/Kconfig @@ -31,13 +31,13 @@ config PINCTRL_BCM2835 config PINCTRL_BCM4908 tristate "Broadcom BCM4908 pinmux driver" - depends on OF && (ARCH_BCM4908 || COMPILE_TEST) + depends on OF && (ARCH_BCMBCA || COMPILE_TEST) select PINMUX select PINCONF select GENERIC_PINCONF select GENERIC_PINCTRL_GROUPS select GENERIC_PINMUX_FUNCTIONS - default ARCH_BCM4908 + default ARCH_BCMBCA help Driver for BCM4908 family SoCs with integrated pin controller. diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 806773e88832..2a8238eb8794 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -201,7 +201,7 @@ config RESET_SCMI config RESET_SIMPLE bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT - default ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC + default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC depends on HAS_IOMEM help This enables a simple reset controller driver for reset lines that diff --git a/drivers/soc/bcm/bcm63xx/Kconfig b/drivers/soc/bcm/bcm63xx/Kconfig index 9e501c8ac5ce..355c34482076 100644 --- a/drivers/soc/bcm/bcm63xx/Kconfig +++ b/drivers/soc/bcm/bcm63xx/Kconfig @@ -13,8 +13,8 @@ endif # SOC_BCM63XX config BCM_PMB bool "Broadcom PMB (Power Management Bus) driver" - depends on ARCH_BCM4908 || (COMPILE_TEST && OF) - default ARCH_BCM4908 + depends on ARCH_BCMBCA || (COMPILE_TEST && OF) + default ARCH_BCMBCA select PM_GENERIC_DOMAINS if PM help This enables support for the Broadcom's PMB (Power Management Bus) that diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 877173907c53..ba4b63fd511e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1083,8 +1083,8 @@ config SERIAL_TIMBERDALE config SERIAL_BCM63XX tristate "Broadcom BCM63xx/BCM33xx UART support" select SERIAL_CORE - depends on ARCH_BCM4908 || ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC || COMPILE_TEST - default ARCH_BCM4908 || ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC + depends on ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC || COMPILE_TEST + default ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC help This enables the driver for the onchip UART core found on the following chipsets: diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 9295492d24f7..688922fc4edb 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1799,7 +1799,7 @@ config BCM7038_WDT tristate "BCM63xx/BCM7038 Watchdog" select WATCHDOG_CORE depends on HAS_IOMEM - depends on ARCH_BCM4908 || ARCH_BRCMSTB || BMIPS_GENERIC || BCM63XX || COMPILE_TEST + depends on ARCH_BCMBCA || ARCH_BRCMSTB || BMIPS_GENERIC || BCM63XX || COMPILE_TEST help Watchdog driver for the built-in hardware in Broadcom 7038 and later SoCs used in set-top boxes. BCM7038 was made public -- cgit v1.2.3 From 1b37236de8c1ac56969efd130bb38edf8ac4b7f6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Jul 2022 10:08:03 +0200 Subject: soc: renesas: Identify R-Car H3Ne-1.7G Add support for identifying the R-Car H3Ne-1.7G (R8A779MB) SoC. As this is a different grading of the already supported R-Car H3-N ES3.0 (R8A77951) SoC, support for it is enabled through the existing ARCH_R8A77951 configuration symbol. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/8670482178567897571edc0dfc60017453544071.1656072871.git.geert+renesas@glider.be --- drivers/soc/renesas/renesas-soc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index d171f1b635c7..6fa7f43f6f3b 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -320,6 +320,7 @@ static const struct of_device_id renesas_socs[] __initconst = { { .compatible = "renesas,r8a779m0", .data = &soc_rcar_h3 }, { .compatible = "renesas,r8a779m1", .data = &soc_rcar_h3 }, { .compatible = "renesas,r8a779m8", .data = &soc_rcar_h3 }, + { .compatible = "renesas,r8a779mb", .data = &soc_rcar_h3 }, #endif #ifdef CONFIG_ARCH_R8A77960 { .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w }, -- cgit v1.2.3 From ebd0e06f3063cc2e3a689112904b29720579c6d2 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 22 Jul 2022 15:15:06 +0100 Subject: soc: renesas: Identify RZ/Five SoC Add support for identifying the (R9A07G043) RZ/Five SoC. Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20220722141506.20171-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/soc/renesas/Kconfig | 10 ++++++++++ drivers/soc/renesas/renesas-soc.c | 13 +++++++++++++ 2 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 390f52109cb7..f95a1337450d 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -333,6 +333,16 @@ config ARCH_R9A09G011 endif # ARM64 +if RISCV + +config ARCH_R9A07G043 + bool "RISC-V Platform support for RZ/Five" + select ARCH_RZG2L + help + This enables support for the Renesas RZ/Five SoC. + +endif # RISCV + config RST_RCAR bool "Reset Controller support for R-Car" if COMPILE_TEST diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 6fa7f43f6f3b..621ceaa047d4 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -50,6 +50,10 @@ static const struct renesas_family fam_rza2 __initconst __maybe_unused = { .name = "RZ/A2", }; +static const struct renesas_family fam_rzfive __initconst __maybe_unused = { + .name = "RZ/Five", +}; + static const struct renesas_family fam_rzg1 __initconst __maybe_unused = { .name = "RZ/G1", .reg = 0xff000044, /* PRR (Product Register) */ @@ -102,6 +106,11 @@ static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = { .id = 0x40, }; +static const struct renesas_soc soc_rz_five __initconst __maybe_unused = { + .family = &fam_rzfive, + .id = 0x847c447, +}; + static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = { .family = &fam_rzg1, .id = 0x45, @@ -359,8 +368,12 @@ static const struct of_device_id renesas_socs[] __initconst = { { .compatible = "renesas,r8a779g0", .data = &soc_rcar_v4h }, #endif #if defined(CONFIG_ARCH_R9A07G043) +#ifdef CONFIG_RISCV + { .compatible = "renesas,r9a07g043", .data = &soc_rz_five }, +#else { .compatible = "renesas,r9a07g043", .data = &soc_rz_g2ul }, #endif +#endif #if defined(CONFIG_ARCH_R9A07G044) { .compatible = "renesas,r9a07g044", .data = &soc_rz_g2l }, #endif -- cgit v1.2.3 From 61b3c876c1cbdb1efd1f52a1f348580e6e14efb6 Mon Sep 17 00:00:00 2001 From: Liang He Date: Sat, 16 Jul 2022 11:13:24 +0800 Subject: memory: pl353-smc: Fix refcount leak bug in pl353_smc_probe() The break of for_each_available_child_of_node() needs a corresponding of_node_put() when the reference 'child' is not used anymore. Here we do not need to call of_node_put() in fail path as '!match' means no break. While the of_platform_device_create() will created a new reference by 'child' but it has considered the refcounting. Fixes: fee10bd22678 ("memory: pl353: Add driver for arm pl353 static memory controller") Signed-off-by: Liang He Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220716031324.447680-1-windhl@126.com --- drivers/memory/pl353-smc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/memory/pl353-smc.c b/drivers/memory/pl353-smc.c index f84b98278745..d39ee7d06665 100644 --- a/drivers/memory/pl353-smc.c +++ b/drivers/memory/pl353-smc.c @@ -122,6 +122,7 @@ static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id) } of_platform_device_create(child, NULL, &adev->dev); + of_node_put(child); return 0; -- cgit v1.2.3 From 8e4787582d92494188c094f0fa7d2f03c73ed509 Mon Sep 17 00:00:00 2001 From: Debarati Biswas Date: Wed, 13 Jul 2022 09:03:55 -0400 Subject: memory: dfl-emif: Update the dfl emif driver support revision 1 The next generation (revision 1) of the DFL EMIF feature device requires support for more than 4 memory banks. It does not support the selective clearing of memory banks. A capability register replaces the previous control register, and contains a bitmask to indicate the presence of each memory bank. This bitmask aligns with the previous control register bitmask that served the same purpose. The control and capability registers are treated like a C Union structure in order to support both the new and old revisions of the EMIF device. Signed-off-by: Debarati Biswas Signed-off-by: Russ Weight Signed-off-by: Tianfei Zhang Reviewed-by: Matthew Gerlach Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220713130355.196115-1-tianfei.zhang@intel.com --- drivers/memory/dfl-emif.c | 62 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/memory/dfl-emif.c b/drivers/memory/dfl-emif.c index 3f719816771d..da06cd30a016 100644 --- a/drivers/memory/dfl-emif.c +++ b/drivers/memory/dfl-emif.c @@ -24,11 +24,24 @@ #define EMIF_STAT_CLEAR_BUSY_SFT 16 #define EMIF_CTRL 0x10 #define EMIF_CTRL_CLEAR_EN_SFT 0 -#define EMIF_CTRL_CLEAR_EN_MSK GENMASK_ULL(3, 0) +#define EMIF_CTRL_CLEAR_EN_MSK GENMASK_ULL(7, 0) #define EMIF_POLL_INVL 10000 /* us */ #define EMIF_POLL_TIMEOUT 5000000 /* us */ +/* + * The Capability Register replaces the Control Register (at the same + * offset) for EMIF feature revisions > 0. The bitmask that indicates + * the presence of memory channels exists in both the Capability Register + * and Control Register definitions. These can be thought of as a C union. + * The Capability Register definitions are used to check for the existence + * of a memory channel, and the Control Register definitions are used for + * managing the memory-clear functionality in revision 0. + */ +#define EMIF_CAPABILITY_BASE 0x10 +#define EMIF_CAPABILITY_CHN_MSK_V0 GENMASK_ULL(3, 0) +#define EMIF_CAPABILITY_CHN_MSK GENMASK_ULL(7, 0) + struct dfl_emif { struct device *dev; void __iomem *base; @@ -106,16 +119,30 @@ emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 0); emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 1); emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 2); emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 3); +emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 4); +emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 5); +emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 6); +emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 7); emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 0); emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 1); emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 2); emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 3); +emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 4); +emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 5); +emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 6); +emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 7); + emif_clear_attr(0); emif_clear_attr(1); emif_clear_attr(2); emif_clear_attr(3); +emif_clear_attr(4); +emif_clear_attr(5); +emif_clear_attr(6); +emif_clear_attr(7); + static struct attribute *dfl_emif_attrs[] = { &emif_attr_inf0_init_done.attr.attr, @@ -134,6 +161,22 @@ static struct attribute *dfl_emif_attrs[] = { &emif_attr_inf3_cal_fail.attr.attr, &emif_attr_inf3_clear.attr.attr, + &emif_attr_inf4_init_done.attr.attr, + &emif_attr_inf4_cal_fail.attr.attr, + &emif_attr_inf4_clear.attr.attr, + + &emif_attr_inf5_init_done.attr.attr, + &emif_attr_inf5_cal_fail.attr.attr, + &emif_attr_inf5_clear.attr.attr, + + &emif_attr_inf6_init_done.attr.attr, + &emif_attr_inf6_cal_fail.attr.attr, + &emif_attr_inf6_clear.attr.attr, + + &emif_attr_inf7_init_done.attr.attr, + &emif_attr_inf7_cal_fail.attr.attr, + &emif_attr_inf7_clear.attr.attr, + NULL, }; @@ -143,15 +186,24 @@ static umode_t dfl_emif_visible(struct kobject *kobj, struct dfl_emif *de = dev_get_drvdata(kobj_to_dev(kobj)); struct emif_attr *eattr = container_of(attr, struct emif_attr, attr.attr); + struct dfl_device *ddev = to_dfl_dev(de->dev); u64 val; /* - * This device supports upto 4 memory interfaces, but not all + * This device supports up to 8 memory interfaces, but not all * interfaces are used on different platforms. The read out value of - * CLEAN_EN field (which is a bitmap) could tell how many interfaces - * are available. + * CAPABILITY_CHN_MSK field (which is a bitmap) indicates which + * interfaces are available. */ - val = FIELD_GET(EMIF_CTRL_CLEAR_EN_MSK, readq(de->base + EMIF_CTRL)); + if (ddev->revision > 0 && strstr(attr->name, "_clear")) + return 0; + + if (ddev->revision == 0) + val = FIELD_GET(EMIF_CAPABILITY_CHN_MSK_V0, + readq(de->base + EMIF_CAPABILITY_BASE)); + else + val = FIELD_GET(EMIF_CAPABILITY_CHN_MSK, + readq(de->base + EMIF_CAPABILITY_BASE)); return (val & BIT_ULL(eattr->index)) ? attr->mode : 0; } -- cgit v1.2.3 From 05215fb32010d4afb68fbdbb4d237df6e2d4567b Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 19 Jul 2022 16:56:39 +0800 Subject: memory: of: Fix refcount leak bug in of_get_ddr_timings() We should add the of_node_put() when breaking out of for_each_child_of_node() as it will automatically increase and decrease the refcount. Fixes: e6b42eb6a66c ("memory: emif: add device tree support to emif driver") Signed-off-by: Liang He Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220719085640.1210583-1-windhl@126.com --- drivers/memory/of_memory.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c index dbdf87bc0b78..8e2ef4bf6b17 100644 --- a/drivers/memory/of_memory.c +++ b/drivers/memory/of_memory.c @@ -134,6 +134,7 @@ const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr, for_each_child_of_node(np_ddr, np_tim) { if (of_device_is_compatible(np_tim, tim_compat)) { if (of_do_get_timings(np_tim, &timings[i])) { + of_node_put(np_tim); devm_kfree(dev, timings); goto default_timings; } -- cgit v1.2.3 From 48af14fb0eaa63d9aa68f59fb0b205ec55a95636 Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 19 Jul 2022 16:56:40 +0800 Subject: memory: of: Fix refcount leak bug in of_lpddr3_get_ddr_timings() We should add the of_node_put() when breaking out of for_each_child_of_node() as it will automatically increase and decrease the refcount. Fixes: 976897dd96db ("memory: Extend of_memory with LPDDR3 support") Signed-off-by: Liang He Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220719085640.1210583-2-windhl@126.com --- drivers/memory/of_memory.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c index 8e2ef4bf6b17..fcd20d85d385 100644 --- a/drivers/memory/of_memory.c +++ b/drivers/memory/of_memory.c @@ -285,6 +285,7 @@ const struct lpddr3_timings if (of_device_is_compatible(np_tim, tim_compat)) { if (of_lpddr3_do_get_timings(np_tim, &timings[i])) { devm_kfree(dev, timings); + of_node_put(np_tim); goto default_timings; } i++; -- cgit v1.2.3 From a4be90ff7a7d22a5a781ed2bb3c2d4b2f535a515 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 12 Aug 2022 15:25:33 -0700 Subject: memory: brcmstb_memc: Add Broadcom STB memory controller driver Add support for configuring the Self Refresh Power Down (SRPD) inactivity timeout on Broadcom STB chips. This is used to conserve power when the DRAM activity is reduced. Signed-off-by: Florian Fainelli Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220812222533.2428033-4-f.fainelli@gmail.com --- drivers/memory/Kconfig | 9 ++ drivers/memory/Makefile | 1 + drivers/memory/brcmstb_memc.c | 301 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 311 insertions(+) create mode 100644 drivers/memory/brcmstb_memc.c (limited to 'drivers') diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index ac1a411648d8..fac290e48e0b 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -66,6 +66,15 @@ config BRCMSTB_DPFE for the DRAM's temperature. Slower refresh rate means cooler RAM, higher refresh rate means hotter RAM. +config BRCMSTB_MEMC + tristate "Broadcom STB MEMC driver" + default ARCH_BRCMSTB + depends on ARCH_BRCMSTB || COMPILE_TEST + help + This driver provides a way to configure the Broadcom STB memory + controller and specifically control the Self Refresh Power Down + (SRPD) inactivity timeout. + 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 bc7663ed1c25..e148f636c082 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o +obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o obj-$(CONFIG_TI_AEMIF) += ti-aemif.o obj-$(CONFIG_TI_EMIF) += emif.o diff --git a/drivers/memory/brcmstb_memc.c b/drivers/memory/brcmstb_memc.c new file mode 100644 index 000000000000..233a53f5bce1 --- /dev/null +++ b/drivers/memory/brcmstb_memc.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * DDR Self-Refresh Power Down (SRPD) support for Broadcom STB SoCs + * + */ + +#include +#include +#include +#include +#include +#include + +#define REG_MEMC_CNTRLR_CONFIG 0x00 +#define CNTRLR_CONFIG_LPDDR4_SHIFT 5 +#define CNTRLR_CONFIG_MASK 0xf +#define REG_MEMC_SRPD_CFG_21 0x20 +#define REG_MEMC_SRPD_CFG_20 0x34 +#define REG_MEMC_SRPD_CFG_1x 0x3c +#define INACT_COUNT_SHIFT 0 +#define INACT_COUNT_MASK 0xffff +#define SRPD_EN_SHIFT 16 + +struct brcmstb_memc_data { + u32 srpd_offset; +}; + +struct brcmstb_memc { + struct device *dev; + void __iomem *ddr_ctrl; + unsigned int timeout_cycles; + u32 frequency; + u32 srpd_offset; +}; + +static int brcmstb_memc_uses_lpddr4(struct brcmstb_memc *memc) +{ + void __iomem *config = memc->ddr_ctrl + REG_MEMC_CNTRLR_CONFIG; + u32 reg; + + reg = readl_relaxed(config) & CNTRLR_CONFIG_MASK; + + return reg == CNTRLR_CONFIG_LPDDR4_SHIFT; +} + +static int brcmstb_memc_srpd_config(struct brcmstb_memc *memc, + unsigned int cycles) +{ + void __iomem *cfg = memc->ddr_ctrl + memc->srpd_offset; + u32 val; + + /* Max timeout supported in HW */ + if (cycles > INACT_COUNT_MASK) + return -EINVAL; + + memc->timeout_cycles = cycles; + + val = (cycles << INACT_COUNT_SHIFT) & INACT_COUNT_MASK; + if (cycles) + val |= BIT(SRPD_EN_SHIFT); + + writel_relaxed(val, cfg); + /* Ensure the write is committed to the controller */ + (void)readl_relaxed(cfg); + + return 0; +} + +static ssize_t frequency_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct brcmstb_memc *memc = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", memc->frequency); +} + +static ssize_t srpd_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct brcmstb_memc *memc = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", memc->timeout_cycles); +} + +static ssize_t srpd_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct brcmstb_memc *memc = dev_get_drvdata(dev); + unsigned int val; + int ret; + + /* + * Cannot change the inactivity timeout on LPDDR4 chips because the + * dynamic tuning process will also get affected by the inactivity + * timeout, thus making it non functional. + */ + if (brcmstb_memc_uses_lpddr4(memc)) + return -EOPNOTSUPP; + + ret = kstrtouint(buf, 10, &val); + if (ret < 0) + return ret; + + ret = brcmstb_memc_srpd_config(memc, val); + if (ret) + return ret; + + return count; +} + +static DEVICE_ATTR_RO(frequency); +static DEVICE_ATTR_RW(srpd); + +static struct attribute *dev_attrs[] = { + &dev_attr_frequency.attr, + &dev_attr_srpd.attr, + NULL, +}; + +static struct attribute_group dev_attr_group = { + .attrs = dev_attrs, +}; + +static const struct of_device_id brcmstb_memc_of_match[]; + +static int brcmstb_memc_probe(struct platform_device *pdev) +{ + const struct brcmstb_memc_data *memc_data; + const struct of_device_id *of_id; + struct device *dev = &pdev->dev; + struct brcmstb_memc *memc; + int ret; + + memc = devm_kzalloc(dev, sizeof(*memc), GFP_KERNEL); + if (!memc) + return -ENOMEM; + + dev_set_drvdata(dev, memc); + + of_id = of_match_device(brcmstb_memc_of_match, dev); + memc_data = of_id->data; + memc->srpd_offset = memc_data->srpd_offset; + + memc->ddr_ctrl = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(memc->ddr_ctrl)) + return PTR_ERR(memc->ddr_ctrl); + + of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &memc->frequency); + + ret = sysfs_create_group(&dev->kobj, &dev_attr_group); + if (ret) + return ret; + + return 0; +} + +static int brcmstb_memc_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + sysfs_remove_group(&dev->kobj, &dev_attr_group); + + return 0; +} + +enum brcmstb_memc_hwtype { + BRCMSTB_MEMC_V21, + BRCMSTB_MEMC_V20, + BRCMSTB_MEMC_V1X, +}; + +static const struct brcmstb_memc_data brcmstb_memc_versions[] = { + { .srpd_offset = REG_MEMC_SRPD_CFG_21 }, + { .srpd_offset = REG_MEMC_SRPD_CFG_20 }, + { .srpd_offset = REG_MEMC_SRPD_CFG_1x }, +}; + +static const struct of_device_id brcmstb_memc_of_match[] = { + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.1.x", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V1X] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.0", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V20] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.5", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.6", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.7", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.8", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-c.1.0", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-c.1.1", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-c.1.2", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-c.1.3", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + { + .compatible = "brcm,brcmstb-memc-ddr-rev-c.1.4", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21] + }, + /* default to the original offset */ + { + .compatible = "brcm,brcmstb-memc-ddr", + .data = &brcmstb_memc_versions[BRCMSTB_MEMC_V1X] + }, + {} +}; + +static int brcmstb_memc_suspend(struct device *dev) +{ + struct brcmstb_memc *memc = dev_get_drvdata(dev); + void __iomem *cfg = memc->ddr_ctrl + memc->srpd_offset; + u32 val; + + if (memc->timeout_cycles == 0) + return 0; + + /* + * Disable SRPD prior to suspending the system since that can + * cause issues with other memory clients managed by the ARM + * trusted firmware to access memory. + */ + val = readl_relaxed(cfg); + val &= ~BIT(SRPD_EN_SHIFT); + writel_relaxed(val, cfg); + /* Ensure the write is committed to the controller */ + (void)readl_relaxed(cfg); + + return 0; +} + +static int brcmstb_memc_resume(struct device *dev) +{ + struct brcmstb_memc *memc = dev_get_drvdata(dev); + + if (memc->timeout_cycles == 0) + return 0; + + return brcmstb_memc_srpd_config(memc, memc->timeout_cycles); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(brcmstb_memc_pm_ops, brcmstb_memc_suspend, + brcmstb_memc_resume); + +static struct platform_driver brcmstb_memc_driver = { + .probe = brcmstb_memc_probe, + .remove = brcmstb_memc_remove, + .driver = { + .name = "brcmstb_memc", + .of_match_table = brcmstb_memc_of_match, + .pm = pm_ptr(&brcmstb_memc_pm_ops), + }, +}; +module_platform_driver(brcmstb_memc_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("DDR SRPD driver for Broadcom STB chips"); -- cgit v1.2.3 From 6356c7bb5383c1e65cd718d94392fdc8cfa79fc8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Jul 2022 13:37:39 +0200 Subject: soc: qcom: icc-bwmon: re-use IRQ enable/clear define The interrupt enable, status and clear registers have the same layout, so BWMON_GLOBAL_IRQ_ENABLE_ENABLE define can be used also for clearing IRQ, instead of hard-coded value. Cc: Rajendra Nayak Cc: Sibi Sankar Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sibi Sankar Tested-by: Steev Klimaszewski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220728113748.170548-3-krzysztof.kozlowski@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 7f8aca533cd3..c2df038a2fbc 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -162,7 +162,8 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon) * interrupt is cleared. */ writel(BWMON_IRQ_ENABLE_MASK, bwmon->base + BWMON_IRQ_CLEAR); - writel(BIT(0), bwmon->base + BWMON_GLOBAL_IRQ_CLEAR); + writel(BWMON_GLOBAL_IRQ_ENABLE_ENABLE, + bwmon->base + BWMON_GLOBAL_IRQ_CLEAR); } static void bwmon_disable(struct icc_bwmon *bwmon) -- cgit v1.2.3 From 2b5d8b02f5acdf5f4b2ef42ec0a082b7e1fb7eac Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Jul 2022 13:37:40 +0200 Subject: soc: qcom: icc-bwmon: drop unused registers BWMON_GLOBAL_IRQ_STATUS and BWMON_ZONE_COUNT defines are not used. Cc: Rajendra Nayak Cc: Sibi Sankar Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sibi Sankar Tested-by: Steev Klimaszewski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220728113748.170548-4-krzysztof.kozlowski@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index c2df038a2fbc..680a3b97ef2c 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -31,7 +31,6 @@ /* Internal sampling clock frequency */ #define HW_TIMER_HZ 19200000 -#define BWMON_GLOBAL_IRQ_STATUS 0x0 #define BWMON_GLOBAL_IRQ_CLEAR 0x8 #define BWMON_GLOBAL_IRQ_ENABLE 0xc #define BWMON_GLOBAL_IRQ_ENABLE_ENABLE BIT(0) @@ -105,7 +104,6 @@ /* BWMONv4 count registers use count unit of 64 kB */ #define BWMON_COUNT_UNIT_KB 64 -#define BWMON_ZONE_COUNT 0x2d8 #define BWMON_ZONE_MAX(zone) (0x2e0 + 4 * (zone)) struct icc_bwmon_data { -- cgit v1.2.3 From 1dd5246ea6ba66b3e926eb13528fdfaf63211c65 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Jul 2022 13:37:41 +0200 Subject: soc: qcom: icc-bwmon: store reference to variant data in container Instead of copying pieces of variant-specific data (struct icc_bwmon_data) into the state container (struct icc_bwmon), just store a pointer to it. This simplifies a bit the code and allows later to grow easily the variant-specific data for new BWMON v5. Cc: Rajendra Nayak Cc: Sibi Sankar Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sibi Sankar Tested-by: Steev Klimaszewski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220728113748.170548-5-krzysztof.kozlowski@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 680a3b97ef2c..90c0494de43b 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -117,11 +117,10 @@ struct icc_bwmon_data { struct icc_bwmon { struct device *dev; + const struct icc_bwmon_data *data; void __iomem *base; int irq; - unsigned int default_lowbw_kbps; - unsigned int sample_ms; unsigned int max_bw_kbps; unsigned int min_bw_kbps; unsigned int target_kbps; @@ -198,20 +197,20 @@ static void bwmon_set_threshold(struct icc_bwmon *bwmon, unsigned int reg, { unsigned int thres; - thres = mult_frac(bwmon_kbps_to_count(kbps), bwmon->sample_ms, + thres = mult_frac(bwmon_kbps_to_count(kbps), bwmon->data->sample_ms, MSEC_PER_SEC); writel_relaxed(thres, bwmon->base + reg); } -static void bwmon_start(struct icc_bwmon *bwmon, - const struct icc_bwmon_data *data) +static void bwmon_start(struct icc_bwmon *bwmon) { + const struct icc_bwmon_data *data = bwmon->data; unsigned int thres_count; int window; bwmon_clear_counters(bwmon); - window = mult_frac(bwmon->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC); + window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC); /* Maximum sampling window: 0xfffff */ writel_relaxed(window, bwmon->base + BWMON_SAMPLE_WINDOW); @@ -266,7 +265,7 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id) */ max = readl(bwmon->base + BWMON_ZONE_MAX(zone)) + 1; max *= BWMON_COUNT_UNIT_KB; - bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->sample_ms); + bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms); return IRQ_WAKE_THREAD; } @@ -328,14 +327,13 @@ static int bwmon_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct dev_pm_opp *opp; struct icc_bwmon *bwmon; - const struct icc_bwmon_data *data; int ret; bwmon = devm_kzalloc(dev, sizeof(*bwmon), GFP_KERNEL); if (!bwmon) return -ENOMEM; - data = of_device_get_match_data(dev); + bwmon->data = of_device_get_match_data(dev); bwmon->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bwmon->base)) { @@ -361,8 +359,6 @@ static int bwmon_probe(struct platform_device *pdev) if (IS_ERR(opp)) return dev_err_probe(dev, ret, "failed to find min peak bandwidth\n"); - bwmon->sample_ms = data->sample_ms; - bwmon->default_lowbw_kbps = data->default_lowbw_kbps; bwmon->dev = dev; bwmon_disable(bwmon); @@ -373,7 +369,7 @@ static int bwmon_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "failed to request IRQ\n"); platform_set_drvdata(pdev, bwmon); - bwmon_start(bwmon, data); + bwmon_start(bwmon); return 0; } -- cgit v1.2.3 From 956deab551b099b52c99f956539a3c8a1c3c34e6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Jul 2022 13:37:42 +0200 Subject: soc: qcom: icc-bwmon: clear all registers on init The hardware programming guide recommends to clear all registers on first initialization, through separate field in BWMON_CLEAR register. This makes sense in general but especially if driver is rebound to avoid spurious/early interrupts. Cc: Rajendra Nayak Cc: Sibi Sankar Signed-off-by: Krzysztof Kozlowski Tested-by: Steev Klimaszewski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220728113748.170548-6-krzysztof.kozlowski@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 90c0494de43b..da2b68394730 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -50,6 +50,7 @@ #define BWMON_CLEAR 0x2a4 #define BWMON_CLEAR_CLEAR BIT(0) +#define BWMON_CLEAR_CLEAR_ALL BIT(1) #define BWMON_SAMPLE_WINDOW 0x2a8 #define BWMON_THRESHOLD_HIGH 0x2ac @@ -127,8 +128,12 @@ struct icc_bwmon { unsigned int current_kbps; }; -static void bwmon_clear_counters(struct icc_bwmon *bwmon) +static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all) { + unsigned int val = BWMON_CLEAR_CLEAR; + + if (clear_all) + val |= BWMON_CLEAR_CLEAR_ALL; /* * Clear counters. The order and barriers are * important. Quoting downstream Qualcomm msm-4.9 tree: @@ -137,7 +142,7 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon) * region. So, we need to make sure the counter clear is completed * before we try to clear the IRQ or do any other counter operations. */ - writel(BWMON_CLEAR_CLEAR, bwmon->base + BWMON_CLEAR); + writel(val, bwmon->base + BWMON_CLEAR); } static void bwmon_clear_irq(struct icc_bwmon *bwmon) @@ -208,7 +213,7 @@ static void bwmon_start(struct icc_bwmon *bwmon) unsigned int thres_count; int window; - bwmon_clear_counters(bwmon); + bwmon_clear_counters(bwmon, true); window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC); /* Maximum sampling window: 0xfffff */ @@ -304,7 +309,7 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id) bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH, up_kbps); bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED, down_kbps); /* Write barriers in bwmon_clear_counters() */ - bwmon_clear_counters(bwmon); + bwmon_clear_counters(bwmon, false); bwmon_clear_irq(bwmon); bwmon_enable(bwmon, irq_enable); -- cgit v1.2.3 From 650db9fa2c540b860fce547514e305fbee01aa2d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Jul 2022 13:37:43 +0200 Subject: soc: qcom: icc-bwmon: store count unit per variant Versions v4 and v5 of BWMON on SDM845 use different unit count, so allow easier variant customization by storing its value in struct icc_bwmon_data. Cc: Rajendra Nayak Cc: Sibi Sankar Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sibi Sankar Tested-by: Steev Klimaszewski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220728113748.170548-7-krzysztof.kozlowski@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index da2b68394730..f356a968598c 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -103,12 +103,11 @@ #define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT 0xff #define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT 0xff -/* BWMONv4 count registers use count unit of 64 kB */ -#define BWMON_COUNT_UNIT_KB 64 #define BWMON_ZONE_MAX(zone) (0x2e0 + 4 * (zone)) struct icc_bwmon_data { unsigned int sample_ms; + unsigned int count_unit_kb; /* kbytes */ unsigned int default_highbw_kbps; unsigned int default_medbw_kbps; unsigned int default_lowbw_kbps; @@ -192,9 +191,10 @@ static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable) writel(BWMON_ENABLE_ENABLE, bwmon->base + BWMON_ENABLE); } -static unsigned int bwmon_kbps_to_count(unsigned int kbps) +static unsigned int bwmon_kbps_to_count(struct icc_bwmon *bwmon, + unsigned int kbps) { - return kbps / BWMON_COUNT_UNIT_KB; + return kbps / bwmon->data->count_unit_kb; } static void bwmon_set_threshold(struct icc_bwmon *bwmon, unsigned int reg, @@ -202,8 +202,8 @@ static void bwmon_set_threshold(struct icc_bwmon *bwmon, unsigned int reg, { unsigned int thres; - thres = mult_frac(bwmon_kbps_to_count(kbps), bwmon->data->sample_ms, - MSEC_PER_SEC); + thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps), + bwmon->data->sample_ms, MSEC_PER_SEC); writel_relaxed(thres, bwmon->base + reg); } @@ -269,7 +269,7 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id) * downstream) always increments the max bytes count by one. */ max = readl(bwmon->base + BWMON_ZONE_MAX(zone)) + 1; - max *= BWMON_COUNT_UNIT_KB; + max *= bwmon->data->count_unit_kb; bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms); return IRQ_WAKE_THREAD; @@ -391,6 +391,7 @@ static int bwmon_remove(struct platform_device *pdev) /* BWMON v4 */ static const struct icc_bwmon_data msm8998_bwmon_data = { .sample_ms = 4, + .count_unit_kb = 64, .default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */ .default_medbw_kbps = 512 * 1024, /* 512 MBps */ .default_lowbw_kbps = 0, -- cgit v1.2.3 From ec63dcd3c863bf966b7a222b1a6465b4a55a30b1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Jul 2022 13:37:44 +0200 Subject: soc: qcom: icc-bwmon: use regmap and prepare for BWMON v5 Refactor the code to prepare it for supporting BWMON v5 which comes with different register layout by: 1. Adding use of MMIO regmap and regmap fields which allows to keep one code logic with different register maps. 2. The "clear" type registers do not allow reading, therefore regmap requires using cache with default values. 3. regmap has an effect of introducing barriers after each readl/writel, which should negligible effect as only few writes were relaxed. 4. Additionally usage of regmap fields removes need of shifting the register values. 5. Add "V4" prefix to names of all defines with register addresses (so BWMON_V4_xxx) to differentiate it from V5. The actual register values are shared so keep their naming. 6. While changing the defines, pad register addresses to three digits for readability. Cc: Rajendra Nayak Cc: Sibi Sankar Signed-off-by: Krzysztof Kozlowski Tested-by: Steev Klimaszewski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220728113748.170548-8-krzysztof.kozlowski@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 294 ++++++++++++++++++++++++++++++++----------- 1 file changed, 220 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index f356a968598c..3350ff77dc45 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -5,6 +5,8 @@ * Author: Krzysztof Kozlowski , based on * previous work of Thara Gopinath and msm-4.9 downstream sources. */ + +#include #include #include #include @@ -13,6 +15,7 @@ #include #include #include +#include #include /* @@ -31,33 +34,33 @@ /* Internal sampling clock frequency */ #define HW_TIMER_HZ 19200000 -#define BWMON_GLOBAL_IRQ_CLEAR 0x8 -#define BWMON_GLOBAL_IRQ_ENABLE 0xc -#define BWMON_GLOBAL_IRQ_ENABLE_ENABLE BIT(0) - -#define BWMON_IRQ_STATUS 0x100 -#define BWMON_IRQ_STATUS_ZONE_SHIFT 4 -#define BWMON_IRQ_CLEAR 0x108 -#define BWMON_IRQ_ENABLE 0x10c -#define BWMON_IRQ_ENABLE_ZONE1_SHIFT 5 -#define BWMON_IRQ_ENABLE_ZONE2_SHIFT 6 -#define BWMON_IRQ_ENABLE_ZONE3_SHIFT 7 -#define BWMON_IRQ_ENABLE_MASK (BIT(BWMON_IRQ_ENABLE_ZONE1_SHIFT) | \ - BIT(BWMON_IRQ_ENABLE_ZONE3_SHIFT)) - -#define BWMON_ENABLE 0x2a0 +#define BWMON_V4_GLOBAL_IRQ_CLEAR 0x008 +#define BWMON_V4_GLOBAL_IRQ_ENABLE 0x00c +/* + * All values here and further are matching regmap fields, so without absolute + * register offsets. + */ +#define BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE BIT(0) + +#define BWMON_V4_IRQ_STATUS 0x100 +#define BWMON_V4_IRQ_CLEAR 0x108 + +#define BWMON_V4_IRQ_ENABLE 0x10c +#define BWMON_IRQ_ENABLE_MASK (BIT(1) | BIT(3)) + +#define BWMON_V4_ENABLE 0x2a0 #define BWMON_ENABLE_ENABLE BIT(0) -#define BWMON_CLEAR 0x2a4 +#define BWMON_V4_CLEAR 0x2a4 #define BWMON_CLEAR_CLEAR BIT(0) #define BWMON_CLEAR_CLEAR_ALL BIT(1) -#define BWMON_SAMPLE_WINDOW 0x2a8 -#define BWMON_THRESHOLD_HIGH 0x2ac -#define BWMON_THRESHOLD_MED 0x2b0 -#define BWMON_THRESHOLD_LOW 0x2b4 +#define BWMON_V4_SAMPLE_WINDOW 0x2a8 +#define BWMON_V4_THRESHOLD_HIGH 0x2ac +#define BWMON_V4_THRESHOLD_MED 0x2b0 +#define BWMON_V4_THRESHOLD_LOW 0x2b4 -#define BWMON_ZONE_ACTIONS 0x2b8 +#define BWMON_V4_ZONE_ACTIONS 0x2b8 /* * Actions to perform on some zone 'z' when current zone hits the threshold: * Increment counter of zone 'z' @@ -83,27 +86,47 @@ BWMON_ZONE_ACTIONS_CLEAR(2) | \ BWMON_ZONE_ACTIONS_CLEAR(1) | \ BWMON_ZONE_ACTIONS_CLEAR(0)) -/* Value for BWMON_ZONE_ACTIONS */ -#define BWMON_ZONE_ACTIONS_DEFAULT (BWMON_ZONE_ACTIONS_ZONE0 | \ - BWMON_ZONE_ACTIONS_ZONE1 << 8 | \ - BWMON_ZONE_ACTIONS_ZONE2 << 16 | \ - BWMON_ZONE_ACTIONS_ZONE3 << 24) /* - * There is no clear documentation/explanation of BWMON_THRESHOLD_COUNT + * There is no clear documentation/explanation of BWMON_V4_THRESHOLD_COUNT * register. Based on observations, this is number of times one threshold has to * be reached, to trigger interrupt in given zone. * * 0xff are maximum values meant to ignore the zones 0 and 2. */ -#define BWMON_THRESHOLD_COUNT 0x2bc -#define BWMON_THRESHOLD_COUNT_ZONE1_SHIFT 8 -#define BWMON_THRESHOLD_COUNT_ZONE2_SHIFT 16 -#define BWMON_THRESHOLD_COUNT_ZONE3_SHIFT 24 +#define BWMON_V4_THRESHOLD_COUNT 0x2bc #define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT 0xff #define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT 0xff -#define BWMON_ZONE_MAX(zone) (0x2e0 + 4 * (zone)) +#define BWMON_V4_ZONE_MAX(zone) (0x2e0 + 4 * (zone)) + +enum bwmon_fields { + F_GLOBAL_IRQ_CLEAR, + F_GLOBAL_IRQ_ENABLE, + F_IRQ_STATUS, + F_IRQ_CLEAR, + F_IRQ_ENABLE, + F_ENABLE, + F_CLEAR, + F_SAMPLE_WINDOW, + F_THRESHOLD_HIGH, + F_THRESHOLD_MED, + F_THRESHOLD_LOW, + F_ZONE_ACTIONS_ZONE0, + F_ZONE_ACTIONS_ZONE1, + F_ZONE_ACTIONS_ZONE2, + F_ZONE_ACTIONS_ZONE3, + F_THRESHOLD_COUNT_ZONE0, + F_THRESHOLD_COUNT_ZONE1, + F_THRESHOLD_COUNT_ZONE2, + F_THRESHOLD_COUNT_ZONE3, + F_ZONE0_MAX, + F_ZONE1_MAX, + F_ZONE2_MAX, + F_ZONE3_MAX, + + F_NUM_FIELDS +}; struct icc_bwmon_data { unsigned int sample_ms; @@ -113,20 +136,104 @@ struct icc_bwmon_data { unsigned int default_lowbw_kbps; u8 zone1_thres_count; u8 zone3_thres_count; + + const struct regmap_config *regmap_cfg; + const struct reg_field *regmap_fields; }; struct icc_bwmon { struct device *dev; const struct icc_bwmon_data *data; - void __iomem *base; int irq; + struct regmap *regmap; + struct regmap_field *regs[F_NUM_FIELDS]; + unsigned int max_bw_kbps; unsigned int min_bw_kbps; unsigned int target_kbps; unsigned int current_kbps; }; +/* BWMON v4 */ +static const struct reg_field msm8998_bwmon_reg_fields[] = { + [F_GLOBAL_IRQ_CLEAR] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR, 0, 0), + [F_GLOBAL_IRQ_ENABLE] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE, 0, 0), + [F_IRQ_STATUS] = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7), + [F_IRQ_CLEAR] = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7), + [F_IRQ_ENABLE] = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7), + /* F_ENABLE covers entire register to disable other features */ + [F_ENABLE] = REG_FIELD(BWMON_V4_ENABLE, 0, 31), + [F_CLEAR] = REG_FIELD(BWMON_V4_CLEAR, 0, 1), + [F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V4_SAMPLE_WINDOW, 0, 23), + [F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V4_THRESHOLD_HIGH, 0, 11), + [F_THRESHOLD_MED] = REG_FIELD(BWMON_V4_THRESHOLD_MED, 0, 11), + [F_THRESHOLD_LOW] = REG_FIELD(BWMON_V4_THRESHOLD_LOW, 0, 11), + [F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 0, 7), + [F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 8, 15), + [F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 16, 23), + [F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 24, 31), + [F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 0, 7), + [F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 8, 15), + [F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 16, 23), + [F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 24, 31), + [F_ZONE0_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(0), 0, 11), + [F_ZONE1_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(1), 0, 11), + [F_ZONE2_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(2), 0, 11), + [F_ZONE3_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(3), 0, 11), +}; + +static const struct regmap_range msm8998_bwmon_reg_noread_ranges[] = { + regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR, BWMON_V4_GLOBAL_IRQ_CLEAR), + regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR), + regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR), +}; + +static const struct regmap_access_table msm8998_bwmon_reg_read_table = { + .no_ranges = msm8998_bwmon_reg_noread_ranges, + .n_no_ranges = ARRAY_SIZE(msm8998_bwmon_reg_noread_ranges), +}; + +static const struct regmap_range msm8998_bwmon_reg_volatile_ranges[] = { + regmap_reg_range(BWMON_V4_IRQ_STATUS, BWMON_V4_IRQ_STATUS), + regmap_reg_range(BWMON_V4_ZONE_MAX(0), BWMON_V4_ZONE_MAX(3)), +}; + +static const struct regmap_access_table msm8998_bwmon_reg_volatile_table = { + .yes_ranges = msm8998_bwmon_reg_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(msm8998_bwmon_reg_volatile_ranges), +}; + +/* + * Fill the cache for non-readable registers only as rest does not really + * matter and can be read from the device. + */ +static const struct reg_default msm8998_bwmon_reg_defaults[] = { + { BWMON_V4_GLOBAL_IRQ_CLEAR, 0x0 }, + { BWMON_V4_IRQ_CLEAR, 0x0 }, + { BWMON_V4_CLEAR, 0x0 }, +}; + +static const struct regmap_config msm8998_bwmon_regmap_cfg = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + /* + * No concurrent access expected - driver has one interrupt handler, + * regmap is not shared, no driver or user-space API. + */ + .disable_locking = true, + .rd_table = &msm8998_bwmon_reg_read_table, + .volatile_table = &msm8998_bwmon_reg_volatile_table, + .reg_defaults = msm8998_bwmon_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(msm8998_bwmon_reg_defaults), + /* + * Cache is necessary for using regmap fields with non-readable + * registers. + */ + .cache_type = REGCACHE_RBTREE, +}; + static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all) { unsigned int val = BWMON_CLEAR_CLEAR; @@ -141,7 +248,7 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all) * region. So, we need to make sure the counter clear is completed * before we try to clear the IRQ or do any other counter operations. */ - writel(val, bwmon->base + BWMON_CLEAR); + regmap_field_force_write(bwmon->regs[F_CLEAR], val); } static void bwmon_clear_irq(struct icc_bwmon *bwmon) @@ -162,33 +269,33 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon) * clearing here so that local writes don't happen before the * interrupt is cleared. */ - writel(BWMON_IRQ_ENABLE_MASK, bwmon->base + BWMON_IRQ_CLEAR); - writel(BWMON_GLOBAL_IRQ_ENABLE_ENABLE, - bwmon->base + BWMON_GLOBAL_IRQ_CLEAR); + regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], BWMON_IRQ_ENABLE_MASK); + regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR], + BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE); } static void bwmon_disable(struct icc_bwmon *bwmon) { /* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */ - writel(0x0, bwmon->base + BWMON_GLOBAL_IRQ_ENABLE); - writel(0x0, bwmon->base + BWMON_IRQ_ENABLE); + regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0); + regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0); /* * Disable bwmon. Must happen before bwmon_clear_irq() to avoid spurious * IRQ. */ - writel(0x0, bwmon->base + BWMON_ENABLE); + regmap_field_write(bwmon->regs[F_ENABLE], 0x0); } static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable) { /* Enable interrupts */ - writel(BWMON_GLOBAL_IRQ_ENABLE_ENABLE, - bwmon->base + BWMON_GLOBAL_IRQ_ENABLE); - writel(irq_enable, bwmon->base + BWMON_IRQ_ENABLE); + regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], + BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE); + regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable); /* Enable bwmon */ - writel(BWMON_ENABLE_ENABLE, bwmon->base + BWMON_ENABLE); + regmap_field_write(bwmon->regs[F_ENABLE], BWMON_ENABLE_ENABLE); } static unsigned int bwmon_kbps_to_count(struct icc_bwmon *bwmon, @@ -197,43 +304,51 @@ static unsigned int bwmon_kbps_to_count(struct icc_bwmon *bwmon, return kbps / bwmon->data->count_unit_kb; } -static void bwmon_set_threshold(struct icc_bwmon *bwmon, unsigned int reg, - unsigned int kbps) +static void bwmon_set_threshold(struct icc_bwmon *bwmon, + struct regmap_field *reg, unsigned int kbps) { unsigned int thres; thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps), bwmon->data->sample_ms, MSEC_PER_SEC); - writel_relaxed(thres, bwmon->base + reg); + regmap_field_write(reg, thres); } static void bwmon_start(struct icc_bwmon *bwmon) { const struct icc_bwmon_data *data = bwmon->data; - unsigned int thres_count; int window; bwmon_clear_counters(bwmon, true); window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC); /* Maximum sampling window: 0xfffff */ - writel_relaxed(window, bwmon->base + BWMON_SAMPLE_WINDOW); + regmap_field_write(bwmon->regs[F_SAMPLE_WINDOW], window); - bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH, + bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH], data->default_highbw_kbps); - bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED, + bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED], data->default_medbw_kbps); - bwmon_set_threshold(bwmon, BWMON_THRESHOLD_LOW, + bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_LOW], data->default_lowbw_kbps); - thres_count = data->zone3_thres_count << BWMON_THRESHOLD_COUNT_ZONE3_SHIFT | - BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT << BWMON_THRESHOLD_COUNT_ZONE2_SHIFT | - data->zone1_thres_count << BWMON_THRESHOLD_COUNT_ZONE1_SHIFT | - BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT; - writel_relaxed(thres_count, bwmon->base + BWMON_THRESHOLD_COUNT); - writel_relaxed(BWMON_ZONE_ACTIONS_DEFAULT, - bwmon->base + BWMON_ZONE_ACTIONS); - /* Write barriers in bwmon_clear_irq() */ + regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE0], + BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT); + regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE1], + data->zone1_thres_count); + regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE2], + BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT); + regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE3], + data->zone3_thres_count); + + regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE0], + BWMON_ZONE_ACTIONS_ZONE0); + regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE1], + BWMON_ZONE_ACTIONS_ZONE1); + regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE2], + BWMON_ZONE_ACTIONS_ZONE2); + regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE3], + BWMON_ZONE_ACTIONS_ZONE3); bwmon_clear_irq(bwmon); bwmon_enable(bwmon, BWMON_IRQ_ENABLE_MASK); @@ -245,7 +360,9 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id) unsigned int status, max; int zone; - status = readl(bwmon->base + BWMON_IRQ_STATUS); + if (regmap_field_read(bwmon->regs[F_IRQ_STATUS], &status)) + return IRQ_NONE; + status &= BWMON_IRQ_ENABLE_MASK; if (!status) { /* @@ -262,13 +379,16 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id) bwmon_disable(bwmon); - zone = get_bitmask_order(status >> BWMON_IRQ_STATUS_ZONE_SHIFT) - 1; + zone = get_bitmask_order(status) - 1; /* * Zone max bytes count register returns count units within sampling * window. Downstream kernel for BWMONv4 (called BWMON type 2 in * downstream) always increments the max bytes count by one. */ - max = readl(bwmon->base + BWMON_ZONE_MAX(zone)) + 1; + if (regmap_field_read(bwmon->regs[F_ZONE0_MAX + zone], &max)) + return IRQ_NONE; + + max += 1; max *= bwmon->data->count_unit_kb; bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms); @@ -300,15 +420,16 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id) up_kbps = bwmon->target_kbps + 1; if (bwmon->target_kbps >= bwmon->max_bw_kbps) - irq_enable = BIT(BWMON_IRQ_ENABLE_ZONE1_SHIFT); + irq_enable = BIT(1); else if (bwmon->target_kbps <= bwmon->min_bw_kbps) - irq_enable = BIT(BWMON_IRQ_ENABLE_ZONE3_SHIFT); + irq_enable = BIT(3); else irq_enable = BWMON_IRQ_ENABLE_MASK; - bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH, up_kbps); - bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED, down_kbps); - /* Write barriers in bwmon_clear_counters() */ + bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH], + up_kbps); + bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED], + down_kbps); bwmon_clear_counters(bwmon, false); bwmon_clear_irq(bwmon); bwmon_enable(bwmon, irq_enable); @@ -327,6 +448,32 @@ out: return IRQ_HANDLED; } +static int bwmon_init_regmap(struct platform_device *pdev, + struct icc_bwmon *bwmon) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "failed to map bwmon registers\n"); + + map = devm_regmap_init_mmio(dev, base, bwmon->data->regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "failed to initialize regmap\n"); + + BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS); + ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs, + bwmon->data->regmap_fields, + F_NUM_FIELDS); + + return ret; +} + static int bwmon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -340,11 +487,9 @@ static int bwmon_probe(struct platform_device *pdev) bwmon->data = of_device_get_match_data(dev); - bwmon->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(bwmon->base)) { - dev_err(dev, "failed to map bwmon registers\n"); - return PTR_ERR(bwmon->base); - } + ret = bwmon_init_regmap(pdev, bwmon); + if (ret) + return ret; bwmon->irq = platform_get_irq(pdev, 0); if (bwmon->irq < 0) @@ -388,7 +533,6 @@ static int bwmon_remove(struct platform_device *pdev) return 0; } -/* BWMON v4 */ static const struct icc_bwmon_data msm8998_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, @@ -397,6 +541,8 @@ static const struct icc_bwmon_data msm8998_bwmon_data = { .default_lowbw_kbps = 0, .zone1_thres_count = 16, .zone3_thres_count = 1, + .regmap_fields = msm8998_bwmon_reg_fields, + .regmap_cfg = &msm8998_bwmon_regmap_cfg, }; static const struct of_device_id bwmon_of_match[] = { -- cgit v1.2.3 From e6f34184dd012c627e402182688d459d482c8544 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Jul 2022 13:37:45 +0200 Subject: soc: qcom: icc-bwmon: add per-variant quirks BWMON v5 lacks global interrupt registers. Other BWMON versions differ as well, so add quirks for easier customization of code flow. Cc: Rajendra Nayak Cc: Sibi Sankar Signed-off-by: Krzysztof Kozlowski Tested-by: Steev Klimaszewski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220728113748.170548-9-krzysztof.kozlowski@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 3350ff77dc45..d22b865a902b 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -100,6 +100,9 @@ #define BWMON_V4_ZONE_MAX(zone) (0x2e0 + 4 * (zone)) +/* Quirks for specific BWMON types */ +#define BWMON_HAS_GLOBAL_IRQ BIT(0) + enum bwmon_fields { F_GLOBAL_IRQ_CLEAR, F_GLOBAL_IRQ_ENABLE, @@ -136,6 +139,7 @@ struct icc_bwmon_data { unsigned int default_lowbw_kbps; u8 zone1_thres_count; u8 zone3_thres_count; + unsigned int quirks; const struct regmap_config *regmap_cfg; const struct reg_field *regmap_fields; @@ -270,14 +274,16 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon) * interrupt is cleared. */ regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], BWMON_IRQ_ENABLE_MASK); - regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR], - BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE); + if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ) + regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR], + BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE); } static void bwmon_disable(struct icc_bwmon *bwmon) { /* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */ - regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0); + if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ) + regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0); regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0); /* @@ -290,8 +296,9 @@ static void bwmon_disable(struct icc_bwmon *bwmon) static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable) { /* Enable interrupts */ - regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], - BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE); + if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ) + regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], + BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE); regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable); /* Enable bwmon */ @@ -541,6 +548,7 @@ static const struct icc_bwmon_data msm8998_bwmon_data = { .default_lowbw_kbps = 0, .zone1_thres_count = 16, .zone3_thres_count = 1, + .quirks = BWMON_HAS_GLOBAL_IRQ, .regmap_fields = msm8998_bwmon_reg_fields, .regmap_cfg = &msm8998_bwmon_regmap_cfg, }; -- cgit v1.2.3 From 14af4ce084b5fb86f7a01167f54ec8517966b804 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 28 Jul 2022 13:37:46 +0200 Subject: soc: qcom: icc-bwmon: add support for SDM845 LLCC BWMON The SDM845 comes with few instances of Bandwidth Monitor. The already supported one monitors traffic between CPU and Last Level Cache Controller (LLCC) and in downstream sources is called BWMON v4 (or v4 of register layout). SDM845 also has also BWMON instance measuring traffic between LLCC and memory with different register layout: called v5. Add support for this "LLCC" BWMON. Differences against existing v4 one: 1. No global interrupts. 2. Different register layout. 3. Different shift of interrupt fields. 4. Smaller sampling window. Cc: Rajendra Nayak Cc: Sibi Sankar Signed-off-by: Krzysztof Kozlowski Tested-by: Steev Klimaszewski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220728113748.170548-10-krzysztof.kozlowski@linaro.org --- drivers/soc/qcom/icc-bwmon.c | 113 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index d22b865a902b..47c2c3e7bb3f 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -47,20 +47,31 @@ #define BWMON_V4_IRQ_ENABLE 0x10c #define BWMON_IRQ_ENABLE_MASK (BIT(1) | BIT(3)) +#define BWMON_V5_IRQ_STATUS 0x000 +#define BWMON_V5_IRQ_CLEAR 0x008 +#define BWMON_V5_IRQ_ENABLE 0x00c #define BWMON_V4_ENABLE 0x2a0 +#define BWMON_V5_ENABLE 0x010 #define BWMON_ENABLE_ENABLE BIT(0) #define BWMON_V4_CLEAR 0x2a4 +#define BWMON_V5_CLEAR 0x014 #define BWMON_CLEAR_CLEAR BIT(0) #define BWMON_CLEAR_CLEAR_ALL BIT(1) #define BWMON_V4_SAMPLE_WINDOW 0x2a8 +#define BWMON_V5_SAMPLE_WINDOW 0x020 + #define BWMON_V4_THRESHOLD_HIGH 0x2ac #define BWMON_V4_THRESHOLD_MED 0x2b0 #define BWMON_V4_THRESHOLD_LOW 0x2b4 +#define BWMON_V5_THRESHOLD_HIGH 0x024 +#define BWMON_V5_THRESHOLD_MED 0x028 +#define BWMON_V5_THRESHOLD_LOW 0x02c #define BWMON_V4_ZONE_ACTIONS 0x2b8 +#define BWMON_V5_ZONE_ACTIONS 0x030 /* * Actions to perform on some zone 'z' when current zone hits the threshold: * Increment counter of zone 'z' @@ -95,10 +106,12 @@ * 0xff are maximum values meant to ignore the zones 0 and 2. */ #define BWMON_V4_THRESHOLD_COUNT 0x2bc +#define BWMON_V5_THRESHOLD_COUNT 0x034 #define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT 0xff #define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT 0xff #define BWMON_V4_ZONE_MAX(zone) (0x2e0 + 4 * (zone)) +#define BWMON_V5_ZONE_MAX(zone) (0x044 + 4 * (zone)) /* Quirks for specific BWMON types */ #define BWMON_HAS_GLOBAL_IRQ BIT(0) @@ -238,6 +251,83 @@ static const struct regmap_config msm8998_bwmon_regmap_cfg = { .cache_type = REGCACHE_RBTREE, }; +/* BWMON v5 */ +static const struct reg_field sdm845_llcc_bwmon_reg_fields[] = { + [F_GLOBAL_IRQ_CLEAR] = {}, + [F_GLOBAL_IRQ_ENABLE] = {}, + [F_IRQ_STATUS] = REG_FIELD(BWMON_V5_IRQ_STATUS, 0, 3), + [F_IRQ_CLEAR] = REG_FIELD(BWMON_V5_IRQ_CLEAR, 0, 3), + [F_IRQ_ENABLE] = REG_FIELD(BWMON_V5_IRQ_ENABLE, 0, 3), + /* F_ENABLE covers entire register to disable other features */ + [F_ENABLE] = REG_FIELD(BWMON_V5_ENABLE, 0, 31), + [F_CLEAR] = REG_FIELD(BWMON_V5_CLEAR, 0, 1), + [F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V5_SAMPLE_WINDOW, 0, 19), + [F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V5_THRESHOLD_HIGH, 0, 11), + [F_THRESHOLD_MED] = REG_FIELD(BWMON_V5_THRESHOLD_MED, 0, 11), + [F_THRESHOLD_LOW] = REG_FIELD(BWMON_V5_THRESHOLD_LOW, 0, 11), + [F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 0, 7), + [F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 8, 15), + [F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 16, 23), + [F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 24, 31), + [F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 0, 7), + [F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 8, 15), + [F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 16, 23), + [F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 24, 31), + [F_ZONE0_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(0), 0, 11), + [F_ZONE1_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(1), 0, 11), + [F_ZONE2_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(2), 0, 11), + [F_ZONE3_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(3), 0, 11), +}; + +static const struct regmap_range sdm845_llcc_bwmon_reg_noread_ranges[] = { + regmap_reg_range(BWMON_V5_IRQ_CLEAR, BWMON_V5_IRQ_CLEAR), + regmap_reg_range(BWMON_V5_CLEAR, BWMON_V5_CLEAR), +}; + +static const struct regmap_access_table sdm845_llcc_bwmon_reg_read_table = { + .no_ranges = sdm845_llcc_bwmon_reg_noread_ranges, + .n_no_ranges = ARRAY_SIZE(sdm845_llcc_bwmon_reg_noread_ranges), +}; + +static const struct regmap_range sdm845_llcc_bwmon_reg_volatile_ranges[] = { + regmap_reg_range(BWMON_V5_IRQ_STATUS, BWMON_V5_IRQ_STATUS), + regmap_reg_range(BWMON_V5_ZONE_MAX(0), BWMON_V5_ZONE_MAX(3)), +}; + +static const struct regmap_access_table sdm845_llcc_bwmon_reg_volatile_table = { + .yes_ranges = sdm845_llcc_bwmon_reg_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(sdm845_llcc_bwmon_reg_volatile_ranges), +}; + +/* + * Fill the cache for non-readable registers only as rest does not really + * matter and can be read from the device. + */ +static const struct reg_default sdm845_llcc_bwmon_reg_defaults[] = { + { BWMON_V5_IRQ_CLEAR, 0x0 }, + { BWMON_V5_CLEAR, 0x0 }, +}; + +static const struct regmap_config sdm845_llcc_bwmon_regmap_cfg = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + /* + * No concurrent access expected - driver has one interrupt handler, + * regmap is not shared, no driver or user-space API. + */ + .disable_locking = true, + .rd_table = &sdm845_llcc_bwmon_reg_read_table, + .volatile_table = &sdm845_llcc_bwmon_reg_volatile_table, + .reg_defaults = sdm845_llcc_bwmon_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(sdm845_llcc_bwmon_reg_defaults), + /* + * Cache is necessary for using regmap fields with non-readable + * registers. + */ + .cache_type = REGCACHE_RBTREE, +}; + static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all) { unsigned int val = BWMON_CLEAR_CLEAR; @@ -329,7 +419,7 @@ static void bwmon_start(struct icc_bwmon *bwmon) bwmon_clear_counters(bwmon, true); window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC); - /* Maximum sampling window: 0xfffff */ + /* Maximum sampling window: 0xffffff for v4 and 0xfffff for v5 */ regmap_field_write(bwmon->regs[F_SAMPLE_WINDOW], window); bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH], @@ -474,6 +564,7 @@ static int bwmon_init_regmap(struct platform_device *pdev, "failed to initialize regmap\n"); BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS); + BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS); ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs, bwmon->data->regmap_fields, F_NUM_FIELDS); @@ -553,8 +644,26 @@ static const struct icc_bwmon_data msm8998_bwmon_data = { .regmap_cfg = &msm8998_bwmon_regmap_cfg, }; +static const struct icc_bwmon_data sdm845_llcc_bwmon_data = { + .sample_ms = 4, + .count_unit_kb = 1024, + .default_highbw_kbps = 800 * 1024, /* 800 MBps */ + .default_medbw_kbps = 256 * 1024, /* 256 MBps */ + .default_lowbw_kbps = 0, + .zone1_thres_count = 16, + .zone3_thres_count = 1, + .regmap_fields = sdm845_llcc_bwmon_reg_fields, + .regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg, +}; + static const struct of_device_id bwmon_of_match[] = { - { .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data }, + { + .compatible = "qcom,msm8998-bwmon", + .data = &msm8998_bwmon_data + }, { + .compatible = "qcom,sdm845-llcc-bwmon", + .data = &sdm845_llcc_bwmon_data + }, {} }; MODULE_DEVICE_TABLE(of, bwmon_of_match); -- cgit v1.2.3 From af8f6f39b8afd772fda4f8e61823ef8c021bf382 Mon Sep 17 00:00:00 2001 From: Liang He Date: Thu, 21 Jul 2022 21:52:16 +0800 Subject: soc: qcom: smsm: Fix refcount leak bugs in qcom_smsm_probe() There are two refcount leak bugs in qcom_smsm_probe(): (1) The 'local_node' is escaped out from for_each_child_of_node() as the break of iteration, we should call of_node_put() for it in error path or when it is not used anymore. (2) The 'node' is escaped out from for_each_available_child_of_node() as the 'goto', we should call of_node_put() for it in goto target. Fixes: c97c4090ff72 ("soc: qcom: smsm: Add driver for Qualcomm SMSM") Signed-off-by: Liang He Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220721135217.1301039-1-windhl@126.com --- drivers/soc/qcom/smsm.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index 9df9bba242f3..3e8994d6110e 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -526,7 +526,7 @@ static int qcom_smsm_probe(struct platform_device *pdev) for (id = 0; id < smsm->num_hosts; id++) { ret = smsm_parse_ipc(smsm, id); if (ret < 0) - return ret; + goto out_put; } /* Acquire the main SMSM state vector */ @@ -534,13 +534,14 @@ static int qcom_smsm_probe(struct platform_device *pdev) smsm->num_entries * sizeof(u32)); if (ret < 0 && ret != -EEXIST) { dev_err(&pdev->dev, "unable to allocate shared state entry\n"); - return ret; + goto out_put; } states = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL); if (IS_ERR(states)) { dev_err(&pdev->dev, "Unable to acquire shared state entry\n"); - return PTR_ERR(states); + ret = PTR_ERR(states); + goto out_put; } /* Acquire the list of interrupt mask vectors */ @@ -548,13 +549,14 @@ static int qcom_smsm_probe(struct platform_device *pdev) ret = qcom_smem_alloc(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, size); if (ret < 0 && ret != -EEXIST) { dev_err(&pdev->dev, "unable to allocate smsm interrupt mask\n"); - return ret; + goto out_put; } intr_mask = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL); if (IS_ERR(intr_mask)) { dev_err(&pdev->dev, "unable to acquire shared memory interrupt mask\n"); - return PTR_ERR(intr_mask); + ret = PTR_ERR(intr_mask); + goto out_put; } /* Setup the reference to the local state bits */ @@ -565,7 +567,8 @@ static int qcom_smsm_probe(struct platform_device *pdev) smsm->state = qcom_smem_state_register(local_node, &smsm_state_ops, smsm); if (IS_ERR(smsm->state)) { dev_err(smsm->dev, "failed to register qcom_smem_state\n"); - return PTR_ERR(smsm->state); + ret = PTR_ERR(smsm->state); + goto out_put; } /* Register handlers for remote processor entries of interest. */ @@ -595,16 +598,19 @@ static int qcom_smsm_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, smsm); + of_node_put(local_node); return 0; unwind_interfaces: + of_node_put(node); for (id = 0; id < smsm->num_entries; id++) if (smsm->entries[id].domain) irq_domain_remove(smsm->entries[id].domain); qcom_smem_state_unregister(smsm->state); - +out_put: + of_node_put(local_node); return ret; } -- cgit v1.2.3 From 90681f53b9381c23ff7762a3b13826d620c272de Mon Sep 17 00:00:00 2001 From: Liang He Date: Thu, 21 Jul 2022 21:52:17 +0800 Subject: soc: qcom: smem_state: Add refcounting for the 'state->of_node' In qcom_smem_state_register() and qcom_smem_state_release(), we should better use of_node_get() and of_node_put() for the reference creation and destruction of 'device_node'. Fixes: 9460ae2ff308 ("soc: qcom: Introduce common SMEM state machine code") Signed-off-by: Liang He Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220721135217.1301039-2-windhl@126.com --- drivers/soc/qcom/smem_state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/smem_state.c b/drivers/soc/qcom/smem_state.c index 31faf4aa868e..e848cc9a3cf8 100644 --- a/drivers/soc/qcom/smem_state.c +++ b/drivers/soc/qcom/smem_state.c @@ -136,6 +136,7 @@ static void qcom_smem_state_release(struct kref *ref) struct qcom_smem_state *state = container_of(ref, struct qcom_smem_state, refcount); list_del(&state->list); + of_node_put(state->of_node); kfree(state); } @@ -205,7 +206,7 @@ struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node, kref_init(&state->refcount); - state->of_node = of_node; + state->of_node = of_node_get(of_node); state->ops = *ops; state->priv = priv; -- cgit v1.2.3 From fd40048901d20b81ab84fb151b16f82afca57d56 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 23 Jul 2022 12:02:24 +0200 Subject: soc: qcom: socinfo: Add an ID for SM6375 Add an ID for SM6375, also known as BLAIR. Signed-off-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220723100225.92053-1-konrad.dybcio@somainline.org --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 4554fb8655d3..fdaa56d3b79a 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -334,6 +334,7 @@ static const struct soc_id soc_id[] = { { 482, "SM8450" }, { 487, "SC7280" }, { 495, "SC7180P" }, + { 507, "SM6375" }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) -- cgit v1.2.3 From 5257841aaa8c6c39df7cfac30d72783a1c57563a Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 23 Jul 2022 12:02:25 +0200 Subject: soc: qcom: socinfo: Add PM6125 ID PM6125 has the ID 45. Add it. Signed-off-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220723100225.92053-2-konrad.dybcio@somainline.org --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index fdaa56d3b79a..aa37e1bad095 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -104,6 +104,7 @@ static const char *const pmic_models[] = { [36] = "PM8009", [38] = "PM8150C", [41] = "SMB2351", + [45] = "PM6125", [47] = "PMK8350", [48] = "PM8350", [49] = "PM8350C", -- cgit v1.2.3 From 2778caedb5667239823a29148dfc48b26a8b3c2a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 30 Jul 2022 14:48:33 +0200 Subject: soc: mediatek: Let PMIC Wrapper and SCPSYS depend on OF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the following configuration options: CONFIG_OF is not set CONFIG_MTK_PMIC_WRAP=y CONFIG_MTK_SCPSYS=y we get the following build warnings: CC drivers/soc/mediatek/mtk-pmic-wrap.o drivers/soc/mediatek/mtk-pmic-wrap.c:2138:34: warning: ‘of_pwrap_match_tbl’ defined but not used [-Wunused-const-variable=] drivers/soc/mediatek/mtk-pmic-wrap.c:1953:34: warning: ‘of_slave_match_tbl’ defined but not used [-Wunused-const-variable=] CC drivers/soc/mediatek/mtk-scpsys.o drivers/soc/mediatek/mtk-scpsys.c:1084:34: warning: ‘of_scpsys_match_tbl’ defined but not used [-Wunused-const-variable=] Looking at the code, both drivers can only bind to OF-defined device nodes, so these drivers are useless without OF and should therefore depend on it. Also drop of_match_ptr() from both drivers. We already know what it will resolve to, so we might as well save cpp some work. Developers or QA teams who wish to test-build the code can still do so by enabling CONFIG_OF, which is available on all architectures and has no dependencies. Signed-off-by: Jean Delvare Reported-by: kernel test robot Link: https://lore.kernel.org/all/202207240252.ZY5hSCNB-lkp@intel.com/ Cc: Matthias Brugger Cc: Chenglin Xu Link: https://lore.kernel.org/r/20220730144833.0a0d9825@endymion.delvare Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/Kconfig | 2 ++ drivers/soc/mediatek/mtk-pmic-wrap.c | 2 +- drivers/soc/mediatek/mtk-scpsys.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index 3c3eedea35f7..73e63920b1b9 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -37,6 +37,7 @@ config MTK_INFRACFG config MTK_PMIC_WRAP tristate "MediaTek PMIC Wrapper Support" depends on RESET_CONTROLLER + depends on OF select REGMAP help Say yes here to add support for MediaTek PMIC Wrapper found @@ -46,6 +47,7 @@ config MTK_PMIC_WRAP config MTK_SCPSYS bool "MediaTek SCPSYS Support" default ARCH_MEDIATEK + depends on OF select REGMAP select MTK_INFRACFG select PM_GENERIC_DOMAINS if PM diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index d8cb0f833645..eb82ae06697f 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -2316,7 +2316,7 @@ err_out1: static struct platform_driver pwrap_drv = { .driver = { .name = "mt-pmic-pwrap", - .of_match_table = of_match_ptr(of_pwrap_match_tbl), + .of_match_table = of_pwrap_match_tbl, }, .probe = pwrap_probe, }; diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index ca75b14931ec..7a668888111c 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -1141,7 +1141,7 @@ static struct platform_driver scpsys_drv = { .name = "mtk-scpsys", .suppress_bind_attrs = true, .owner = THIS_MODULE, - .of_match_table = of_match_ptr(of_scpsys_match_tbl), + .of_match_table = of_scpsys_match_tbl, }, }; builtin_platform_driver(scpsys_drv); -- cgit v1.2.3 From 2efddd28a2c7ba0fd07720918e7929ffda5101eb Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 26 Jul 2022 16:16:49 +0200 Subject: soc: mediatek: mtk-svs: Switch to platform_get_irq() Instead of using irq_of_parse_and_map() to retrieve the interrupt from devicetree, switch to platform_get_irq() instead: this function will conveniently also write an error message in case the irq is not found. Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220726141653.177948-3-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-svs.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index dee8664a12fd..aace9c3cb38b 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -2306,8 +2306,7 @@ static struct svs_platform *svs_platform_probe(struct platform_device *pdev) static int svs_probe(struct platform_device *pdev) { struct svs_platform *svsp; - unsigned int svsp_irq; - int ret; + int svsp_irq, ret; svsp = svs_platform_probe(pdev); if (IS_ERR(svsp)) @@ -2325,7 +2324,12 @@ static int svs_probe(struct platform_device *pdev) goto svs_probe_free_resource; } - svsp_irq = irq_of_parse_and_map(svsp->dev->of_node, 0); + svsp_irq = platform_get_irq(pdev, 0); + if (svsp_irq < 0) { + ret = svsp_irq; + goto svs_probe_free_resource; + } + ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr, svsp->irqflags | IRQF_ONESHOT, svsp->name, svsp); -- cgit v1.2.3 From 93cd9b3e60b62dbf399b88603fbc18256d45db6c Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 26 Jul 2022 16:16:50 +0200 Subject: soc: mediatek: mtk-svs: Remove hardcoded irqflags The interrupt flags are specified in devicetree: forcing them into the driver is suboptimal and not very useful. Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220726141653.177948-4-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-svs.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index aace9c3cb38b..46cb31255f29 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -262,7 +262,6 @@ static const u32 svs_regs_v2[] = { * @rst: svs platform reset control * @efuse_parsing: svs platform efuse parsing function pointer * @probe: svs platform probe function pointer - * @irqflags: svs platform irq settings flags * @efuse_max: total number of svs efuse * @tefuse_max: total number of thermal efuse * @regs: svs platform registers map @@ -280,7 +279,6 @@ struct svs_platform { struct reset_control *rst; bool (*efuse_parsing)(struct svs_platform *svsp); int (*probe)(struct svs_platform *svsp); - unsigned long irqflags; size_t efuse_max; size_t tefuse_max; const u32 *regs; @@ -294,7 +292,6 @@ struct svs_platform_data { struct svs_bank *banks; bool (*efuse_parsing)(struct svs_platform *svsp); int (*probe)(struct svs_platform *svsp); - unsigned long irqflags; const u32 *regs; u32 bank_max; }; @@ -2244,7 +2241,6 @@ static const struct svs_platform_data svs_mt8192_platform_data = { .banks = svs_mt8192_banks, .efuse_parsing = svs_mt8192_efuse_parsing, .probe = svs_mt8192_platform_probe, - .irqflags = IRQF_TRIGGER_HIGH, .regs = svs_regs_v2, .bank_max = ARRAY_SIZE(svs_mt8192_banks), }; @@ -2254,7 +2250,6 @@ static const struct svs_platform_data svs_mt8183_platform_data = { .banks = svs_mt8183_banks, .efuse_parsing = svs_mt8183_efuse_parsing, .probe = svs_mt8183_platform_probe, - .irqflags = IRQF_TRIGGER_LOW, .regs = svs_regs_v2, .bank_max = ARRAY_SIZE(svs_mt8183_banks), }; @@ -2292,7 +2287,6 @@ static struct svs_platform *svs_platform_probe(struct platform_device *pdev) svsp->banks = svsp_data->banks; svsp->efuse_parsing = svsp_data->efuse_parsing; svsp->probe = svsp_data->probe; - svsp->irqflags = svsp_data->irqflags; svsp->regs = svsp_data->regs; svsp->bank_max = svsp_data->bank_max; @@ -2331,8 +2325,7 @@ static int svs_probe(struct platform_device *pdev) } ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr, - svsp->irqflags | IRQF_ONESHOT, - svsp->name, svsp); + IRQF_ONESHOT, svsp->name, svsp); if (ret) { dev_err(svsp->dev, "register irq(%d) failed: %d\n", svsp_irq, ret); -- cgit v1.2.3 From 1cd80c06784dd55dca97ce10c5f97bcaa3a417ef Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 26 Jul 2022 16:16:51 +0200 Subject: soc: mediatek: mtk-svs: Drop of_match_ptr() for of_match_table If CONFIG_OF is not set, we get a -Wunused-const-variable: dropping of_match_ptr() solves that issue. Fixes: 681a02e95000 ("soc: mediatek: SVS: introduce MTK SVS engine") Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220726141653.177948-5-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-svs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index 46cb31255f29..dde95aa160e9 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -2389,7 +2389,7 @@ static struct platform_driver svs_driver = { .driver = { .name = "mtk-svs", .pm = &svs_pm_ops, - .of_match_table = of_match_ptr(svs_of_match), + .of_match_table = svs_of_match, }, }; -- cgit v1.2.3 From 02aace9be3cf393eed8bf36cc1edee6818fb5e1d Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 26 Jul 2022 16:16:52 +0200 Subject: soc: mediatek: mtk-svs: Use devm variant for dev_pm_opp_of_add_table() In error cases, this driver never calls dev_pm_opp_of_remove_table(): instead of doing that, simple switch to a devm variant, which will automagically do that for us. Fixes: 681a02e95000 ("soc: mediatek: SVS: introduce MTK SVS engine") Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220726141653.177948-6-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-svs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index dde95aa160e9..d96b9d3f3a83 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -1586,7 +1586,7 @@ static int svs_bank_resource_setup(struct svs_platform *svsp) dev_set_drvdata(svsb->dev, svsp); - ret = dev_pm_opp_of_add_table(svsb->opp_dev); + ret = devm_pm_opp_of_add_table(svsb->opp_dev); if (ret) { dev_err(svsb->dev, "add opp table fail: %d\n", ret); return ret; -- cgit v1.2.3 From 43819e3853306625275f1ada7416453117a9aabf Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 25 Aug 2022 14:46:15 -0400 Subject: soc: mediatek: mtk-svs: Commonize t-calibration-data fuse array read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commonize the repeating pattern for reading the "t-calibration-data" efuse data in a new function svs_thermal_efuse_get_data(), reducing the size of this driver. No functional changes. Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Nícolas F. R. A. Prado Link: https://lore.kernel.org/r/20220825184616.2118870-2-nfraprado@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-svs.c | 69 ++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index d96b9d3f3a83..63253e22abdd 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -1641,11 +1641,36 @@ static int svs_bank_resource_setup(struct svs_platform *svsp) return 0; } +static int svs_thermal_efuse_get_data(struct svs_platform *svsp) +{ + struct nvmem_cell *cell; + + /* Thermal efuse parsing */ + cell = nvmem_cell_get(svsp->dev, "t-calibration-data"); + if (IS_ERR_OR_NULL(cell)) { + dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n", PTR_ERR(cell)); + return PTR_ERR(cell); + } + + svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max); + if (IS_ERR(svsp->tefuse)) { + dev_err(svsp->dev, "cannot read thermal efuse: %ld\n", + PTR_ERR(svsp->tefuse)); + nvmem_cell_put(cell); + return PTR_ERR(svsp->tefuse); + } + + svsp->tefuse_max /= sizeof(u32); + nvmem_cell_put(cell); + + return 0; +} + static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp) { struct svs_bank *svsb; - struct nvmem_cell *cell; u32 idx, i, vmin, golden_temp; + int ret; for (i = 0; i < svsp->efuse_max; i++) if (svsp->efuse[i]) @@ -1683,24 +1708,9 @@ static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp) svsb->vmax += svsb->dvt_fixed; } - /* Thermal efuse parsing */ - cell = nvmem_cell_get(svsp->dev, "t-calibration-data"); - if (IS_ERR_OR_NULL(cell)) { - dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n", - PTR_ERR(cell)); - return false; - } - - svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max); - if (IS_ERR(svsp->tefuse)) { - dev_err(svsp->dev, "cannot read thermal efuse: %ld\n", - PTR_ERR(svsp->tefuse)); - nvmem_cell_put(cell); + ret = svs_thermal_efuse_get_data(svsp); + if (ret) return false; - } - - svsp->tefuse_max /= sizeof(u32); - nvmem_cell_put(cell); for (i = 0; i < svsp->tefuse_max; i++) if (svsp->tefuse[i] != 0) @@ -1723,11 +1733,11 @@ static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp) static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp) { struct svs_bank *svsb; - struct nvmem_cell *cell; int format[6], x_roomt[6], o_vtsmcu[5], o_vtsabb, tb_roomt = 0; int adc_ge_t, adc_oe_t, ge, oe, gain, degc_cali, adc_cali_en_t; int o_slope, o_slope_sign, ts_id; u32 idx, i, ft_pgm, mts, temp0, temp1, temp2; + int ret; for (i = 0; i < svsp->efuse_max; i++) if (svsp->efuse[i]) @@ -1803,24 +1813,9 @@ static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp) } } - /* Get thermal efuse by nvmem */ - cell = nvmem_cell_get(svsp->dev, "t-calibration-data"); - if (IS_ERR(cell)) { - dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n", - PTR_ERR(cell)); - goto remove_mt8183_svsb_mon_mode; - } - - svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max); - if (IS_ERR(svsp->tefuse)) { - dev_err(svsp->dev, "cannot read thermal efuse: %ld\n", - PTR_ERR(svsp->tefuse)); - nvmem_cell_put(cell); - goto remove_mt8183_svsb_mon_mode; - } - - svsp->tefuse_max /= sizeof(u32); - nvmem_cell_put(cell); + ret = svs_thermal_efuse_get_data(svsp); + if (ret) + return false; /* Thermal efuse parsing */ adc_ge_t = (svsp->tefuse[1] >> 22) & GENMASK(9, 0); -- cgit v1.2.3 From a92438c5a30a27b6791da025306a45478a6ac7a4 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 25 Aug 2022 14:46:16 -0400 Subject: soc: mediatek: mtk-svs: Use bitfield access macros where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to enhance readability and safety during registers setup and value retrieval, redefine a few register related macros and convert all open-coded instances of bitfield setting/retrieval to use the FIELD_PREP() and FIELD_GET() macros. While at it, some macros were renamed to further enhance readability. This commit brings no functional changes. Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Nícolas F. R. A. Prado Link: https://lore.kernel.org/r/20220825184616.2118870-3-nfraprado@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-svs.c | 191 +++++++++++++++++++++++++++-------------- 1 file changed, 128 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index 63253e22abdd..da1a3bfc8633 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -53,22 +53,79 @@ #define SVSB_MON_VOLT_IGNORE BIT(16) #define SVSB_REMOVE_DVTFIXED_VOLT BIT(24) -/* svs bank register common configuration */ -#define SVSB_DET_MAX 0xffff +/* svs bank register fields and common configuration */ +#define SVSB_PTPCONFIG_DETMAX GENMASK(15, 0) +#define SVSB_DET_MAX FIELD_PREP(SVSB_PTPCONFIG_DETMAX, 0xffff) #define SVSB_DET_WINDOW 0xa28 -#define SVSB_DTHI 0x1 -#define SVSB_DTLO 0xfe -#define SVSB_EN_INIT01 0x1 -#define SVSB_EN_INIT02 0x5 -#define SVSB_EN_MON 0x2 -#define SVSB_EN_OFF 0x0 -#define SVSB_INTEN_INIT0x 0x00005f01 -#define SVSB_INTEN_MONVOPEN 0x00ff0000 -#define SVSB_INTSTS_CLEAN 0x00ffffff -#define SVSB_INTSTS_COMPLETE 0x1 -#define SVSB_INTSTS_MONVOP 0x00ff0000 + +/* DESCHAR */ +#define SVSB_DESCHAR_FLD_MDES GENMASK(7, 0) +#define SVSB_DESCHAR_FLD_BDES GENMASK(15, 8) + +/* TEMPCHAR */ +#define SVSB_TEMPCHAR_FLD_DVT_FIXED GENMASK(7, 0) +#define SVSB_TEMPCHAR_FLD_MTDES GENMASK(15, 8) +#define SVSB_TEMPCHAR_FLD_VCO GENMASK(23, 16) + +/* DETCHAR */ +#define SVSB_DETCHAR_FLD_DCMDET GENMASK(7, 0) +#define SVSB_DETCHAR_FLD_DCBDET GENMASK(15, 8) + +/* SVSEN (PTPEN) */ +#define SVSB_PTPEN_INIT01 BIT(0) +#define SVSB_PTPEN_MON BIT(1) +#define SVSB_PTPEN_INIT02 (SVSB_PTPEN_INIT01 | BIT(2)) +#define SVSB_PTPEN_OFF 0x0 + +/* FREQPCTS */ +#define SVSB_FREQPCTS_FLD_PCT0_4 GENMASK(7, 0) +#define SVSB_FREQPCTS_FLD_PCT1_5 GENMASK(15, 8) +#define SVSB_FREQPCTS_FLD_PCT2_6 GENMASK(23, 16) +#define SVSB_FREQPCTS_FLD_PCT3_7 GENMASK(31, 24) + +/* INTSTS */ +#define SVSB_INTSTS_VAL_CLEAN 0x00ffffff +#define SVSB_INTSTS_F0_COMPLETE BIT(0) +#define SVSB_INTSTS_FLD_MONVOP GENMASK(23, 16) #define SVSB_RUNCONFIG_DEFAULT 0x80000000 +/* LIMITVALS */ +#define SVSB_LIMITVALS_FLD_DTLO GENMASK(7, 0) +#define SVSB_LIMITVALS_FLD_DTHI GENMASK(15, 8) +#define SVSB_LIMITVALS_FLD_VMIN GENMASK(23, 16) +#define SVSB_LIMITVALS_FLD_VMAX GENMASK(31, 24) +#define SVSB_VAL_DTHI 0x1 +#define SVSB_VAL_DTLO 0xfe + +/* INTEN */ +#define SVSB_INTEN_F0EN BIT(0) +#define SVSB_INTEN_DACK0UPEN BIT(8) +#define SVSB_INTEN_DC0EN BIT(9) +#define SVSB_INTEN_DC1EN BIT(10) +#define SVSB_INTEN_DACK0LOEN BIT(11) +#define SVSB_INTEN_INITPROD_OVF_EN BIT(12) +#define SVSB_INTEN_INITSUM_OVF_EN BIT(14) +#define SVSB_INTEN_MONVOPEN GENMASK(23, 16) +#define SVSB_INTEN_INIT0x (SVSB_INTEN_F0EN | SVSB_INTEN_DACK0UPEN | \ + SVSB_INTEN_DC0EN | SVSB_INTEN_DC1EN | \ + SVSB_INTEN_DACK0LOEN | \ + SVSB_INTEN_INITPROD_OVF_EN | \ + SVSB_INTEN_INITSUM_OVF_EN) + +/* TSCALCS */ +#define SVSB_TSCALCS_FLD_MTS GENMASK(11, 0) +#define SVSB_TSCALCS_FLD_BTS GENMASK(23, 12) + +/* INIT2VALS */ +#define SVSB_INIT2VALS_FLD_DCVOFFSETIN GENMASK(15, 0) +#define SVSB_INIT2VALS_FLD_AGEVOFFSETIN GENMASK(31, 16) + +/* VOPS */ +#define SVSB_VOPS_FLD_VOP0_4 GENMASK(7, 0) +#define SVSB_VOPS_FLD_VOP1_5 GENMASK(15, 8) +#define SVSB_VOPS_FLD_VOP2_6 GENMASK(23, 16) +#define SVSB_VOPS_FLD_VOP3_7 GENMASK(31, 24) + /* svs bank related setting */ #define BITS8 8 #define MAX_OPP_ENTRIES 16 @@ -665,8 +722,8 @@ static ssize_t svs_enable_debug_write(struct file *filp, svsp->pbank = svsb; svsb->mode_support = SVSB_MODE_ALL_DISABLE; svs_switch_bank(svsp); - svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN); - svs_writel_relaxed(svsp, SVSB_INTSTS_CLEAN, INTSTS); + svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); + svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS); spin_unlock_irqrestore(&svs_lock, flags); svsb->phase = SVSB_PHASE_ERROR; @@ -827,7 +884,7 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) } else if (svsb->type == SVSB_LOW) { /* volt[turn_pt] + volt[j] ~ volt[opp_count - 1] */ j = svsb->opp_count - 7; - svsb->volt[turn_pt] = vop30 & GENMASK(7, 0); + svsb->volt[turn_pt] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30); shift_byte++; for (i = j; i < svsb->opp_count; i++) { b_sft = BITS8 * (shift_byte % REG_BYTES); @@ -849,7 +906,7 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) if (svsb->type == SVSB_HIGH) { /* volt[0] + volt[j] ~ volt[turn_pt - 1] */ j = turn_pt - 7; - svsb->volt[0] = vop30 & GENMASK(7, 0); + svsb->volt[0] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30); shift_byte++; for (i = j; i < turn_pt; i++) { b_sft = BITS8 * (shift_byte % REG_BYTES); @@ -980,16 +1037,16 @@ static void svs_get_bank_volts_v2(struct svs_platform *svsp) u32 temp, i; temp = svs_readl_relaxed(svsp, VOP74); - svsb->volt[14] = (temp >> 24) & GENMASK(7, 0); - svsb->volt[12] = (temp >> 16) & GENMASK(7, 0); - svsb->volt[10] = (temp >> 8) & GENMASK(7, 0); - svsb->volt[8] = (temp & GENMASK(7, 0)); + svsb->volt[14] = FIELD_GET(SVSB_VOPS_FLD_VOP3_7, temp); + svsb->volt[12] = FIELD_GET(SVSB_VOPS_FLD_VOP2_6, temp); + svsb->volt[10] = FIELD_GET(SVSB_VOPS_FLD_VOP1_5, temp); + svsb->volt[8] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, temp); temp = svs_readl_relaxed(svsp, VOP30); - svsb->volt[6] = (temp >> 24) & GENMASK(7, 0); - svsb->volt[4] = (temp >> 16) & GENMASK(7, 0); - svsb->volt[2] = (temp >> 8) & GENMASK(7, 0); - svsb->volt[0] = (temp & GENMASK(7, 0)); + svsb->volt[6] = FIELD_GET(SVSB_VOPS_FLD_VOP3_7, temp); + svsb->volt[4] = FIELD_GET(SVSB_VOPS_FLD_VOP2_6, temp); + svsb->volt[2] = FIELD_GET(SVSB_VOPS_FLD_VOP1_5, temp); + svsb->volt[0] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, temp); for (i = 0; i <= 12; i += 2) svsb->volt[i + 1] = interpolate(svsb->freq_pct[i], @@ -1011,20 +1068,20 @@ static void svs_get_bank_volts_v2(struct svs_platform *svsp) static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp) { struct svs_bank *svsb = svsp->pbank; + u32 freqpct74_val, freqpct30_val; + + freqpct74_val = FIELD_PREP(SVSB_FREQPCTS_FLD_PCT0_4, svsb->freq_pct[8]) | + FIELD_PREP(SVSB_FREQPCTS_FLD_PCT1_5, svsb->freq_pct[10]) | + FIELD_PREP(SVSB_FREQPCTS_FLD_PCT2_6, svsb->freq_pct[12]) | + FIELD_PREP(SVSB_FREQPCTS_FLD_PCT3_7, svsb->freq_pct[14]); + + freqpct30_val = FIELD_PREP(SVSB_FREQPCTS_FLD_PCT0_4, svsb->freq_pct[0]) | + FIELD_PREP(SVSB_FREQPCTS_FLD_PCT1_5, svsb->freq_pct[2]) | + FIELD_PREP(SVSB_FREQPCTS_FLD_PCT2_6, svsb->freq_pct[4]) | + FIELD_PREP(SVSB_FREQPCTS_FLD_PCT3_7, svsb->freq_pct[6]); - svs_writel_relaxed(svsp, - (svsb->freq_pct[14] << 24) | - (svsb->freq_pct[12] << 16) | - (svsb->freq_pct[10] << 8) | - svsb->freq_pct[8], - FREQPCT74); - - svs_writel_relaxed(svsp, - (svsb->freq_pct[6] << 24) | - (svsb->freq_pct[4] << 16) | - (svsb->freq_pct[2] << 8) | - svsb->freq_pct[0], - FREQPCT30); + svs_writel_relaxed(svsp, freqpct74_val, FREQPCT74); + svs_writel_relaxed(svsp, freqpct30_val, FREQPCT30); } static void svs_set_bank_phase(struct svs_platform *svsp, @@ -1035,13 +1092,17 @@ static void svs_set_bank_phase(struct svs_platform *svsp, svs_switch_bank(svsp); - des_char = (svsb->bdes << 8) | svsb->mdes; + des_char = FIELD_PREP(SVSB_DESCHAR_FLD_BDES, svsb->bdes) | + FIELD_PREP(SVSB_DESCHAR_FLD_MDES, svsb->mdes); svs_writel_relaxed(svsp, des_char, DESCHAR); - temp_char = (svsb->vco << 16) | (svsb->mtdes << 8) | svsb->dvt_fixed; + temp_char = FIELD_PREP(SVSB_TEMPCHAR_FLD_VCO, svsb->vco) | + FIELD_PREP(SVSB_TEMPCHAR_FLD_MTDES, svsb->mtdes) | + FIELD_PREP(SVSB_TEMPCHAR_FLD_DVT_FIXED, svsb->dvt_fixed); svs_writel_relaxed(svsp, temp_char, TEMPCHAR); - det_char = (svsb->dcbdet << 8) | svsb->dcmdet; + det_char = FIELD_PREP(SVSB_DETCHAR_FLD_DCBDET, svsb->dcbdet) | + FIELD_PREP(SVSB_DETCHAR_FLD_DCMDET, svsb->dcmdet); svs_writel_relaxed(svsp, det_char, DETCHAR); svs_writel_relaxed(svsp, svsb->dc_config, DCCONFIG); @@ -1050,33 +1111,37 @@ static void svs_set_bank_phase(struct svs_platform *svsp, svsb->set_freq_pct(svsp); - limit_vals = (svsb->vmax << 24) | (svsb->vmin << 16) | - (SVSB_DTHI << 8) | SVSB_DTLO; + limit_vals = FIELD_PREP(SVSB_LIMITVALS_FLD_DTLO, SVSB_VAL_DTLO) | + FIELD_PREP(SVSB_LIMITVALS_FLD_DTHI, SVSB_VAL_DTHI) | + FIELD_PREP(SVSB_LIMITVALS_FLD_VMIN, svsb->vmin) | + FIELD_PREP(SVSB_LIMITVALS_FLD_VMAX, svsb->vmax); svs_writel_relaxed(svsp, limit_vals, LIMITVALS); svs_writel_relaxed(svsp, SVSB_DET_WINDOW, DETWINDOW); svs_writel_relaxed(svsp, SVSB_DET_MAX, CONFIG); svs_writel_relaxed(svsp, svsb->chk_shift, CHKSHIFT); svs_writel_relaxed(svsp, svsb->ctl0, CTL0); - svs_writel_relaxed(svsp, SVSB_INTSTS_CLEAN, INTSTS); + svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS); switch (target_phase) { case SVSB_PHASE_INIT01: svs_writel_relaxed(svsp, svsb->vboot, VBOOT); svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN); - svs_writel_relaxed(svsp, SVSB_EN_INIT01, SVSEN); + svs_writel_relaxed(svsp, SVSB_PTPEN_INIT01, SVSEN); break; case SVSB_PHASE_INIT02: + init2vals = FIELD_PREP(SVSB_INIT2VALS_FLD_AGEVOFFSETIN, svsb->age_voffset_in) | + FIELD_PREP(SVSB_INIT2VALS_FLD_DCVOFFSETIN, svsb->dc_voffset_in); svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN); - init2vals = (svsb->age_voffset_in << 16) | svsb->dc_voffset_in; svs_writel_relaxed(svsp, init2vals, INIT2VALS); - svs_writel_relaxed(svsp, SVSB_EN_INIT02, SVSEN); + svs_writel_relaxed(svsp, SVSB_PTPEN_INIT02, SVSEN); break; case SVSB_PHASE_MON: - ts_calcs = (svsb->bts << 12) | svsb->mts; + ts_calcs = FIELD_PREP(SVSB_TSCALCS_FLD_BTS, svsb->bts) | + FIELD_PREP(SVSB_TSCALCS_FLD_MTS, svsb->mts); svs_writel_relaxed(svsp, ts_calcs, TSCALCS); svs_writel_relaxed(svsp, SVSB_INTEN_MONVOPEN, INTEN); - svs_writel_relaxed(svsp, SVSB_EN_MON, SVSEN); + svs_writel_relaxed(svsp, SVSB_PTPEN_MON, SVSEN); break; default: dev_err(svsb->dev, "requested unknown target phase: %u\n", @@ -1112,8 +1177,8 @@ static inline void svs_error_isr_handler(struct svs_platform *svsp) svs_save_bank_register_data(svsp, SVSB_PHASE_ERROR); svsb->phase = SVSB_PHASE_ERROR; - svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN); - svs_writel_relaxed(svsp, SVSB_INTSTS_CLEAN, INTSTS); + svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); + svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS); } static inline void svs_init01_isr_handler(struct svs_platform *svsp) @@ -1138,8 +1203,8 @@ static inline void svs_init01_isr_handler(struct svs_platform *svsp) svsb->age_voffset_in = svs_readl_relaxed(svsp, AGEVALUES) & GENMASK(15, 0); - svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN); - svs_writel_relaxed(svsp, SVSB_INTSTS_COMPLETE, INTSTS); + svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); + svs_writel_relaxed(svsp, SVSB_INTSTS_F0_COMPLETE, INTSTS); svsb->core_sel &= ~SVSB_DET_CLK_EN; } @@ -1157,8 +1222,8 @@ static inline void svs_init02_isr_handler(struct svs_platform *svsp) svsb->phase = SVSB_PHASE_INIT02; svsb->get_volts(svsp); - svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN); - svs_writel_relaxed(svsp, SVSB_INTSTS_COMPLETE, INTSTS); + svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); + svs_writel_relaxed(svsp, SVSB_INTSTS_F0_COMPLETE, INTSTS); } static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp) @@ -1171,7 +1236,7 @@ static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp) svsb->get_volts(svsp); svsb->temp = svs_readl_relaxed(svsp, TEMP) & GENMASK(7, 0); - svs_writel_relaxed(svsp, SVSB_INTSTS_MONVOP, INTSTS); + svs_writel_relaxed(svsp, SVSB_INTSTS_FLD_MONVOP, INTSTS); } static irqreturn_t svs_isr(int irq, void *data) @@ -1198,13 +1263,13 @@ static irqreturn_t svs_isr(int irq, void *data) int_sts = svs_readl_relaxed(svsp, INTSTS); svs_en = svs_readl_relaxed(svsp, SVSEN); - if (int_sts == SVSB_INTSTS_COMPLETE && - svs_en == SVSB_EN_INIT01) + if (int_sts == SVSB_INTSTS_F0_COMPLETE && + svs_en == SVSB_PTPEN_INIT01) svs_init01_isr_handler(svsp); - else if (int_sts == SVSB_INTSTS_COMPLETE && - svs_en == SVSB_EN_INIT02) + else if (int_sts == SVSB_INTSTS_F0_COMPLETE && + svs_en == SVSB_PTPEN_INIT02) svs_init02_isr_handler(svsp); - else if (int_sts & SVSB_INTSTS_MONVOP) + else if (int_sts & SVSB_INTSTS_FLD_MONVOP) svs_mon_mode_isr_handler(svsp); else svs_error_isr_handler(svsp); @@ -1490,8 +1555,8 @@ static int svs_suspend(struct device *dev) spin_lock_irqsave(&svs_lock, flags); svsp->pbank = svsb; svs_switch_bank(svsp); - svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN); - svs_writel_relaxed(svsp, SVSB_INTSTS_CLEAN, INTSTS); + svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); + svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS); spin_unlock_irqrestore(&svs_lock, flags); svsb->phase = SVSB_PHASE_ERROR; -- cgit v1.2.3 From 0e5732e4d58437feded42fb459384904eb317e91 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 20 Aug 2022 19:32:02 +0800 Subject: soc: qcom: Make QCOM_RPMPD depend on OF WARNING: unmet direct dependencies detected for PM_GENERIC_DOMAINS_OF Depends on [n]: PM_GENERIC_DOMAINS [=y] && OF [=n] Selected by [m]: - QCOM_RPMPD [=m] && PM [=y] && QCOM_SMD_RPM [=m] PM_GENERIC_DOMAINS_OF depends on OF, so QCOM_RPMPD also depends on it. Fixes: 7d0221fb5912 ("soc/qcom: Make QCOM_RPMPD select PM_GENERIC_DOMAINS/_OF") Signed-off-by: YueHaibing Acked-by: Randy Dunlap # build-tested Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220820113202.23940-1-yuehaibing@huawei.com --- drivers/soc/qcom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index e0d7a5459562..024e420f1bb7 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -129,7 +129,7 @@ config QCOM_RPMHPD config QCOM_RPMPD tristate "Qualcomm RPM Power domain driver" - depends on PM + depends on PM && OF depends on QCOM_SMD_RPM select PM_GENERIC_DOMAINS select PM_GENERIC_DOMAINS_OF -- cgit v1.2.3 From 0425c5c6ebb2388074ea18460199547f076cbf60 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Fri, 12 Aug 2022 13:12:38 +0300 Subject: soc: qcom: stats: Add SDM845 stats config and compatible SDM845 is a special case compared to the other platforms that use RPMh stats, since it only has 2 stats (aosd and cxsd), while the others have a 3rd one (ddr). So lets add dedicated stats config and compatible for SDM845 to make the driver aware of this num_records difference. Signed-off-by: Abel Vesa Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220812101240.1869605-2-abel.vesa@linaro.org --- drivers/soc/qcom/qcom_stats.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index d6bfd1bbdc2a..121ea409fafc 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -246,6 +246,14 @@ static const struct stats_config rpm_data_dba0 = { .subsystem_stats_in_smem = false, }; +static const struct stats_config rpmh_data_sdm845 = { + .stats_offset = 0x48, + .num_records = 2, + .appended_stats_avail = false, + .dynamic_offset = false, + .subsystem_stats_in_smem = true, +}; + static const struct stats_config rpmh_data = { .stats_offset = 0x48, .num_records = 3, @@ -261,6 +269,7 @@ static const struct of_device_id qcom_stats_table[] = { { .compatible = "qcom,msm8974-rpm-stats", .data = &rpm_data_dba0 }, { .compatible = "qcom,rpm-stats", .data = &rpm_data }, { .compatible = "qcom,rpmh-stats", .data = &rpmh_data }, + { .compatible = "qcom,sdm845-rpmh-stats", .data = &rpmh_data_sdm845 }, { } }; MODULE_DEVICE_TABLE(of, qcom_stats_table); -- cgit v1.2.3 From 7eb89c17abd2574f627c1277a15f6ff64bec33a4 Mon Sep 17 00:00:00 2001 From: Jinpeng Cui Date: Tue, 23 Aug 2022 13:36:20 +0000 Subject: soc: qcom: icc-bwmon: remove redundant ret variable Return value from devm_regmap_field_bulk_alloc() directly instead of taking this in another redundant variable. Reported-by: Zeal Robot Signed-off-by: Jinpeng Cui Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220823133620.211902-1-cui.jinpeng2@zte.com.cn --- drivers/soc/qcom/icc-bwmon.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 47c2c3e7bb3f..9df47afb0d81 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -551,7 +551,6 @@ static int bwmon_init_regmap(struct platform_device *pdev, struct device *dev = &pdev->dev; void __iomem *base; struct regmap *map; - int ret; base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) @@ -565,11 +564,10 @@ static int bwmon_init_regmap(struct platform_device *pdev, BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS); BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS); - ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs, + + return devm_regmap_field_bulk_alloc(dev, map, bwmon->regs, bwmon->data->regmap_fields, F_NUM_FIELDS); - - return ret; } static int bwmon_probe(struct platform_device *pdev) -- cgit v1.2.3 From ff6d365898d4d31bd557954c7fc53f38977b491c Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Mon, 22 Aug 2022 08:34:35 -0700 Subject: soc: qcom: qmi: use const for struct qmi_elem_info Currently all usage of struct qmi_elem_info, which is used to define the QMI message encoding/decoding rules, does not use const. This prevents clients from registering const arrays. Since these arrays are always pre-defined, they should be const, so add the const qualifier to all places in the QMI interface where struct qmi_elem_info is used. Once this patch is in place, clients can independently update their pre-defined arrays to be const, as demonstrated in the QMI sample code. Signed-off-by: Jeff Johnson Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220822153435.7856-1-quic_jjohnson@quicinc.com --- drivers/soc/qcom/qmi_encdec.c | 50 ++++++++++++++++++++-------------------- drivers/soc/qcom/qmi_interface.c | 12 ++++++---- include/linux/soc/qcom/qmi.h | 20 ++++++++-------- samples/qmi/qmi_sample_client.c | 10 ++++---- 4 files changed, 47 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/qmi_encdec.c b/drivers/soc/qcom/qmi_encdec.c index 328cc8237191..b7158e3c3a0b 100644 --- a/drivers/soc/qcom/qmi_encdec.c +++ b/drivers/soc/qcom/qmi_encdec.c @@ -57,11 +57,11 @@ do { \ #define TLV_TYPE_SIZE sizeof(u8) #define OPTIONAL_TLV_TYPE_START 0x10 -static int qmi_encode(struct qmi_elem_info *ei_array, void *out_buf, +static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf, const void *in_c_struct, u32 out_buf_len, int enc_level); -static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct, +static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct, const void *in_buf, u32 in_buf_len, int dec_level); /** @@ -76,10 +76,10 @@ static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct, * * Return: struct info of the next element that can be encoded. */ -static struct qmi_elem_info *skip_to_next_elem(struct qmi_elem_info *ei_array, - int level) +static const struct qmi_elem_info * +skip_to_next_elem(const struct qmi_elem_info *ei_array, int level) { - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; u8 tlv_type; if (level > 1) { @@ -101,11 +101,11 @@ static struct qmi_elem_info *skip_to_next_elem(struct qmi_elem_info *ei_array, * * Return: Expected minimum length of the QMI message or 0 on error. */ -static int qmi_calc_min_msg_len(struct qmi_elem_info *ei_array, +static int qmi_calc_min_msg_len(const struct qmi_elem_info *ei_array, int level) { int min_msg_len = 0; - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; if (!ei_array) return min_msg_len; @@ -194,13 +194,13 @@ static int qmi_encode_basic_elem(void *buf_dst, const void *buf_src, * Return: The number of bytes of encoded information on success or negative * errno on error. */ -static int qmi_encode_struct_elem(struct qmi_elem_info *ei_array, +static int qmi_encode_struct_elem(const struct qmi_elem_info *ei_array, void *buf_dst, const void *buf_src, u32 elem_len, u32 out_buf_len, int enc_level) { int i, rc, encoded_bytes = 0; - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; for (i = 0; i < elem_len; i++) { rc = qmi_encode(temp_ei->ei_array, buf_dst, buf_src, @@ -233,13 +233,13 @@ static int qmi_encode_struct_elem(struct qmi_elem_info *ei_array, * Return: The number of bytes of encoded information on success or negative * errno on error. */ -static int qmi_encode_string_elem(struct qmi_elem_info *ei_array, +static int qmi_encode_string_elem(const struct qmi_elem_info *ei_array, void *buf_dst, const void *buf_src, u32 out_buf_len, int enc_level) { int rc; int encoded_bytes = 0; - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; u32 string_len = 0; u32 string_len_sz = 0; @@ -289,11 +289,11 @@ static int qmi_encode_string_elem(struct qmi_elem_info *ei_array, * Return: The number of bytes of encoded information on success or negative * errno on error. */ -static int qmi_encode(struct qmi_elem_info *ei_array, void *out_buf, +static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf, const void *in_c_struct, u32 out_buf_len, int enc_level) { - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; u8 opt_flag_value = 0; u32 data_len_value = 0, data_len_sz; u8 *buf_dst = (u8 *)out_buf; @@ -468,13 +468,13 @@ static int qmi_decode_basic_elem(void *buf_dst, const void *buf_src, * Return: The total size of the decoded data elements on success, negative * errno on error. */ -static int qmi_decode_struct_elem(struct qmi_elem_info *ei_array, +static int qmi_decode_struct_elem(const struct qmi_elem_info *ei_array, void *buf_dst, const void *buf_src, u32 elem_len, u32 tlv_len, int dec_level) { int i, rc, decoded_bytes = 0; - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; for (i = 0; i < elem_len && decoded_bytes < tlv_len; i++) { rc = qmi_decode(temp_ei->ei_array, buf_dst, buf_src, @@ -514,7 +514,7 @@ static int qmi_decode_struct_elem(struct qmi_elem_info *ei_array, * Return: The total size of the decoded data elements on success, negative * errno on error. */ -static int qmi_decode_string_elem(struct qmi_elem_info *ei_array, +static int qmi_decode_string_elem(const struct qmi_elem_info *ei_array, void *buf_dst, const void *buf_src, u32 tlv_len, int dec_level) { @@ -522,7 +522,7 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array, int decoded_bytes = 0; u32 string_len = 0; u32 string_len_sz = 0; - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; if (dec_level == 1) { string_len = tlv_len; @@ -564,10 +564,10 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array, * * Return: Pointer to struct info, if found */ -static struct qmi_elem_info *find_ei(struct qmi_elem_info *ei_array, - u32 type) +static const struct qmi_elem_info *find_ei(const struct qmi_elem_info *ei_array, + u32 type) { - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; while (temp_ei->data_type != QMI_EOTI) { if (temp_ei->tlv_type == (u8)type) @@ -590,11 +590,11 @@ static struct qmi_elem_info *find_ei(struct qmi_elem_info *ei_array, * Return: The number of bytes of decoded information on success, negative * errno on error. */ -static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct, +static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct, const void *in_buf, u32 in_buf_len, int dec_level) { - struct qmi_elem_info *temp_ei = ei_array; + const struct qmi_elem_info *temp_ei = ei_array; u8 opt_flag_value = 1; u32 data_len_value = 0, data_len_sz = 0; u8 *buf_dst = out_c_struct; @@ -713,7 +713,7 @@ static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct, * Return: Buffer with encoded message, or negative ERR_PTR() on error */ void *qmi_encode_message(int type, unsigned int msg_id, size_t *len, - unsigned int txn_id, struct qmi_elem_info *ei, + unsigned int txn_id, const struct qmi_elem_info *ei, const void *c_struct) { struct qmi_header *hdr; @@ -767,7 +767,7 @@ EXPORT_SYMBOL(qmi_encode_message); * errno on error. */ int qmi_decode_message(const void *buf, size_t len, - struct qmi_elem_info *ei, void *c_struct) + const struct qmi_elem_info *ei, void *c_struct) { if (!ei) return -EINVAL; @@ -781,7 +781,7 @@ int qmi_decode_message(const void *buf, size_t len, EXPORT_SYMBOL(qmi_decode_message); /* Common header in all QMI responses */ -struct qmi_elem_info qmi_response_type_v01_ei[] = { +const struct qmi_elem_info qmi_response_type_v01_ei[] = { { .data_type = QMI_SIGNED_2_BYTE_ENUM, .elem_len = 1, diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index c8c4c730b135..57052726299d 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -305,7 +305,7 @@ EXPORT_SYMBOL(qmi_add_server); * Return: Transaction id on success, negative errno on failure. */ int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn, - struct qmi_elem_info *ei, void *c_struct) + const struct qmi_elem_info *ei, void *c_struct) { int ret; @@ -736,7 +736,8 @@ EXPORT_SYMBOL(qmi_handle_release); static ssize_t qmi_send_message(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct qmi_txn *txn, int type, int msg_id, size_t len, - struct qmi_elem_info *ei, const void *c_struct) + const struct qmi_elem_info *ei, + const void *c_struct) { struct msghdr msghdr = {}; struct kvec iv; @@ -787,7 +788,7 @@ static ssize_t qmi_send_message(struct qmi_handle *qmi, */ ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct qmi_txn *txn, int msg_id, size_t len, - struct qmi_elem_info *ei, const void *c_struct) + const struct qmi_elem_info *ei, const void *c_struct) { return qmi_send_message(qmi, sq, txn, QMI_REQUEST, msg_id, len, ei, c_struct); @@ -808,7 +809,7 @@ EXPORT_SYMBOL(qmi_send_request); */ ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct qmi_txn *txn, int msg_id, size_t len, - struct qmi_elem_info *ei, const void *c_struct) + const struct qmi_elem_info *ei, const void *c_struct) { return qmi_send_message(qmi, sq, txn, QMI_RESPONSE, msg_id, len, ei, c_struct); @@ -827,7 +828,8 @@ EXPORT_SYMBOL(qmi_send_response); * Return: 0 on success, negative errno on failure. */ ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, - int msg_id, size_t len, struct qmi_elem_info *ei, + int msg_id, size_t len, + const struct qmi_elem_info *ei, const void *c_struct) { struct qmi_txn txn; diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h index b1f80e756d2a..469e02d2aa0d 100644 --- a/include/linux/soc/qcom/qmi.h +++ b/include/linux/soc/qcom/qmi.h @@ -75,7 +75,7 @@ struct qmi_elem_info { enum qmi_array_type array_type; u8 tlv_type; u32 offset; - struct qmi_elem_info *ei_array; + const struct qmi_elem_info *ei_array; }; #define QMI_RESULT_SUCCESS_V01 0 @@ -102,7 +102,7 @@ struct qmi_response_type_v01 { u16 error; }; -extern struct qmi_elem_info qmi_response_type_v01_ei[]; +extern const struct qmi_elem_info qmi_response_type_v01_ei[]; /** * struct qmi_service - context to track lookup-results @@ -173,7 +173,7 @@ struct qmi_txn { struct completion completion; int result; - struct qmi_elem_info *ei; + const struct qmi_elem_info *ei; void *dest; }; @@ -189,7 +189,7 @@ struct qmi_msg_handler { unsigned int type; unsigned int msg_id; - struct qmi_elem_info *ei; + const struct qmi_elem_info *ei; size_t decoded_size; void (*fn)(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, @@ -249,23 +249,23 @@ void qmi_handle_release(struct qmi_handle *qmi); ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct qmi_txn *txn, int msg_id, size_t len, - struct qmi_elem_info *ei, const void *c_struct); + const struct qmi_elem_info *ei, const void *c_struct); ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct qmi_txn *txn, int msg_id, size_t len, - struct qmi_elem_info *ei, const void *c_struct); + const struct qmi_elem_info *ei, const void *c_struct); ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, - int msg_id, size_t len, struct qmi_elem_info *ei, + int msg_id, size_t len, const struct qmi_elem_info *ei, const void *c_struct); void *qmi_encode_message(int type, unsigned int msg_id, size_t *len, - unsigned int txn_id, struct qmi_elem_info *ei, + unsigned int txn_id, const struct qmi_elem_info *ei, const void *c_struct); int qmi_decode_message(const void *buf, size_t len, - struct qmi_elem_info *ei, void *c_struct); + const struct qmi_elem_info *ei, void *c_struct); int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn, - struct qmi_elem_info *ei, void *c_struct); + const struct qmi_elem_info *ei, void *c_struct); int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout); void qmi_txn_cancel(struct qmi_txn *txn); diff --git a/samples/qmi/qmi_sample_client.c b/samples/qmi/qmi_sample_client.c index 78fcedbd25e2..c045e3d24326 100644 --- a/samples/qmi/qmi_sample_client.c +++ b/samples/qmi/qmi_sample_client.c @@ -42,7 +42,7 @@ struct test_name_type_v01 { char name[TEST_MAX_NAME_SIZE_V01]; }; -static struct qmi_elem_info test_name_type_v01_ei[] = { +static const struct qmi_elem_info test_name_type_v01_ei[] = { { .data_type = QMI_DATA_LEN, .elem_len = 1, @@ -71,7 +71,7 @@ struct test_ping_req_msg_v01 { struct test_name_type_v01 client_name; }; -static struct qmi_elem_info test_ping_req_msg_v01_ei[] = { +static const struct qmi_elem_info test_ping_req_msg_v01_ei[] = { { .data_type = QMI_UNSIGNED_1_BYTE, .elem_len = 4, @@ -113,7 +113,7 @@ struct test_ping_resp_msg_v01 { struct test_name_type_v01 service_name; }; -static struct qmi_elem_info test_ping_resp_msg_v01_ei[] = { +static const struct qmi_elem_info test_ping_resp_msg_v01_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, @@ -172,7 +172,7 @@ struct test_data_req_msg_v01 { struct test_name_type_v01 client_name; }; -static struct qmi_elem_info test_data_req_msg_v01_ei[] = { +static const struct qmi_elem_info test_data_req_msg_v01_ei[] = { { .data_type = QMI_DATA_LEN, .elem_len = 1, @@ -224,7 +224,7 @@ struct test_data_resp_msg_v01 { struct test_name_type_v01 service_name; }; -static struct qmi_elem_info test_data_resp_msg_v01_ei[] = { +static const struct qmi_elem_info test_data_resp_msg_v01_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, -- cgit v1.2.3 From 5365cea199c70d6abedc2e1be850c03e990f1829 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 25 Aug 2022 10:08:55 +0530 Subject: soc: qcom: llcc: Rename reg_offset structs to reflect LLCC version The register offsets used by the LLCC block retains its layout for multiple versions. For instance, starting from version v1.0.0 to v2.0.1 the offsets are same. And starting from v2.1.0, the offsets changed. But the current reg_offset naming convention is confusing. So to reflect this change correctly in driver, let's encode the start version from which the offsets got changed in reg_offset struct name. This will be llcc_v1_reg_offset for v1.0.0 and llcc_v2_1_reg_offset for v2.1.0. This will allow multiple SoCs to use the same reg_offset clearly. And in the future if the offsets got changed again, then that specific version could be encoded in the struct name. Suggested-by: Sai Prakash Ranjan Signed-off-by: Manivannan Sadhasivam Reviewed-by: Sai Prakash Ranjan Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220825043859.30066-2-manivannan.sadhasivam@linaro.org --- drivers/soc/qcom/llcc-qcom.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 38d7296315a2..0dc2bb0c23cc 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -296,12 +296,14 @@ static const struct llcc_slice_config sm8450_data[] = { {LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, }; -static const u32 llcc_v1_2_reg_offset[] = { +/* LLCC register offset starting from v1.0.0 */ +static const u32 llcc_v1_reg_offset[] = { [LLCC_COMMON_HW_INFO] = 0x00030000, [LLCC_COMMON_STATUS0] = 0x0003000c, }; -static const u32 llcc_v21_reg_offset[] = { +/* LLCC register offset starting from v2.0.1 */ +static const u32 llcc_v2_1_reg_offset[] = { [LLCC_COMMON_HW_INFO] = 0x00034000, [LLCC_COMMON_STATUS0] = 0x0003400c, }; @@ -310,70 +312,70 @@ static const struct qcom_llcc_config sc7180_cfg = { .sct_data = sc7180_data, .size = ARRAY_SIZE(sc7180_data), .need_llcc_cfg = true, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sc7280_cfg = { .sct_data = sc7280_data, .size = ARRAY_SIZE(sc7280_data), .need_llcc_cfg = true, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sc8180x_cfg = { .sct_data = sc8180x_data, .size = ARRAY_SIZE(sc8180x_data), .need_llcc_cfg = true, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sc8280xp_cfg = { .sct_data = sc8280xp_data, .size = ARRAY_SIZE(sc8280xp_data), .need_llcc_cfg = true, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sdm845_cfg = { .sct_data = sdm845_data, .size = ARRAY_SIZE(sdm845_data), .need_llcc_cfg = false, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sm6350_cfg = { .sct_data = sm6350_data, .size = ARRAY_SIZE(sm6350_data), .need_llcc_cfg = true, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sm8150_cfg = { .sct_data = sm8150_data, .size = ARRAY_SIZE(sm8150_data), .need_llcc_cfg = true, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sm8250_cfg = { .sct_data = sm8250_data, .size = ARRAY_SIZE(sm8250_data), .need_llcc_cfg = true, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sm8350_cfg = { .sct_data = sm8350_data, .size = ARRAY_SIZE(sm8350_data), .need_llcc_cfg = true, - .reg_offset = llcc_v1_2_reg_offset, + .reg_offset = llcc_v1_reg_offset, }; static const struct qcom_llcc_config sm8450_cfg = { .sct_data = sm8450_data, .size = ARRAY_SIZE(sm8450_data), .need_llcc_cfg = true, - .reg_offset = llcc_v21_reg_offset, + .reg_offset = llcc_v2_1_reg_offset, }; static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; -- cgit v1.2.3 From c13d7d261e361dbaf5adbdc216ee4a1204c48001 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 25 Aug 2022 10:08:56 +0530 Subject: soc: qcom: llcc: Pass LLCC version based register offsets to EDAC driver The LLCC EDAC register offsets varies between each SoCs. Until now, the EDAC driver used the hardcoded register offsets. But this caused crash on SM8450 SoC where the register offsets has been changed. So to avoid this crash and also to make it easy to accommodate changes for new SoCs, let's pass the LLCC version specific register offsets to the EDAC driver. Currently, two set of offsets are used. One is starting from LLCC version v1.0.0 used by all SoCs other than SM8450. For SM8450, LLCC version starting from v2.1.0 is used. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Sai Prakash Ranjan Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220825043859.30066-3-manivannan.sadhasivam@linaro.org --- drivers/soc/qcom/llcc-qcom.c | 66 ++++++++++++++++++++++++++++++++++++++ include/linux/soc/qcom/llcc-qcom.h | 30 +++++++++++++++++ 2 files changed, 96 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 0dc2bb0c23cc..8b7e8118f3ce 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -104,6 +104,7 @@ struct qcom_llcc_config { int size; bool need_llcc_cfg; const u32 *reg_offset; + const struct llcc_edac_reg_offset *edac_reg_offset; }; enum llcc_reg_offset { @@ -296,6 +297,60 @@ static const struct llcc_slice_config sm8450_data[] = { {LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, }; +static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = { + .trp_ecc_error_status0 = 0x20344, + .trp_ecc_error_status1 = 0x20348, + .trp_ecc_sb_err_syn0 = 0x2304c, + .trp_ecc_db_err_syn0 = 0x20370, + .trp_ecc_error_cntr_clear = 0x20440, + .trp_interrupt_0_status = 0x20480, + .trp_interrupt_0_clear = 0x20484, + .trp_interrupt_0_enable = 0x20488, + + /* LLCC Common registers */ + .cmn_status0 = 0x3000c, + .cmn_interrupt_0_enable = 0x3001c, + .cmn_interrupt_2_enable = 0x3003c, + + /* LLCC DRP registers */ + .drp_ecc_error_cfg = 0x40000, + .drp_ecc_error_cntr_clear = 0x40004, + .drp_interrupt_status = 0x41000, + .drp_interrupt_clear = 0x41008, + .drp_interrupt_enable = 0x4100c, + .drp_ecc_error_status0 = 0x42044, + .drp_ecc_error_status1 = 0x42048, + .drp_ecc_sb_err_syn0 = 0x4204c, + .drp_ecc_db_err_syn0 = 0x42070, +}; + +static const struct llcc_edac_reg_offset llcc_v2_1_edac_reg_offset = { + .trp_ecc_error_status0 = 0x20344, + .trp_ecc_error_status1 = 0x20348, + .trp_ecc_sb_err_syn0 = 0x2034c, + .trp_ecc_db_err_syn0 = 0x20370, + .trp_ecc_error_cntr_clear = 0x20440, + .trp_interrupt_0_status = 0x20480, + .trp_interrupt_0_clear = 0x20484, + .trp_interrupt_0_enable = 0x20488, + + /* LLCC Common registers */ + .cmn_status0 = 0x3400c, + .cmn_interrupt_0_enable = 0x3401c, + .cmn_interrupt_2_enable = 0x3403c, + + /* LLCC DRP registers */ + .drp_ecc_error_cfg = 0x50000, + .drp_ecc_error_cntr_clear = 0x50004, + .drp_interrupt_status = 0x50020, + .drp_interrupt_clear = 0x50028, + .drp_interrupt_enable = 0x5002c, + .drp_ecc_error_status0 = 0x520f4, + .drp_ecc_error_status1 = 0x520f8, + .drp_ecc_sb_err_syn0 = 0x520fc, + .drp_ecc_db_err_syn0 = 0x52120, +}; + /* LLCC register offset starting from v1.0.0 */ static const u32 llcc_v1_reg_offset[] = { [LLCC_COMMON_HW_INFO] = 0x00030000, @@ -313,6 +368,7 @@ static const struct qcom_llcc_config sc7180_cfg = { .size = ARRAY_SIZE(sc7180_data), .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sc7280_cfg = { @@ -320,6 +376,7 @@ static const struct qcom_llcc_config sc7280_cfg = { .size = ARRAY_SIZE(sc7280_data), .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sc8180x_cfg = { @@ -327,6 +384,7 @@ static const struct qcom_llcc_config sc8180x_cfg = { .size = ARRAY_SIZE(sc8180x_data), .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sc8280xp_cfg = { @@ -334,6 +392,7 @@ static const struct qcom_llcc_config sc8280xp_cfg = { .size = ARRAY_SIZE(sc8280xp_data), .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sdm845_cfg = { @@ -341,6 +400,7 @@ static const struct qcom_llcc_config sdm845_cfg = { .size = ARRAY_SIZE(sdm845_data), .need_llcc_cfg = false, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sm6350_cfg = { @@ -348,6 +408,7 @@ static const struct qcom_llcc_config sm6350_cfg = { .size = ARRAY_SIZE(sm6350_data), .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sm8150_cfg = { @@ -355,6 +416,7 @@ static const struct qcom_llcc_config sm8150_cfg = { .size = ARRAY_SIZE(sm8150_data), .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sm8250_cfg = { @@ -362,6 +424,7 @@ static const struct qcom_llcc_config sm8250_cfg = { .size = ARRAY_SIZE(sm8250_data), .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sm8350_cfg = { @@ -369,6 +432,7 @@ static const struct qcom_llcc_config sm8350_cfg = { .size = ARRAY_SIZE(sm8350_data), .need_llcc_cfg = true, .reg_offset = llcc_v1_reg_offset, + .edac_reg_offset = &llcc_v1_edac_reg_offset, }; static const struct qcom_llcc_config sm8450_cfg = { @@ -376,6 +440,7 @@ static const struct qcom_llcc_config sm8450_cfg = { .size = ARRAY_SIZE(sm8450_data), .need_llcc_cfg = true, .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, }; static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; @@ -776,6 +841,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) drv_data->cfg = llcc_cfg; drv_data->cfg_size = sz; + drv_data->edac_reg_offset = cfg->edac_reg_offset; mutex_init(&drv_data->lock); platform_set_drvdata(pdev, drv_data); diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index 9ed5384c5ca1..bc2fb8343a94 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h @@ -78,11 +78,40 @@ struct llcc_edac_reg_data { u8 ways_shift; }; +struct llcc_edac_reg_offset { + /* LLCC TRP registers */ + u32 trp_ecc_error_status0; + u32 trp_ecc_error_status1; + u32 trp_ecc_sb_err_syn0; + u32 trp_ecc_db_err_syn0; + u32 trp_ecc_error_cntr_clear; + u32 trp_interrupt_0_status; + u32 trp_interrupt_0_clear; + u32 trp_interrupt_0_enable; + + /* LLCC Common registers */ + u32 cmn_status0; + u32 cmn_interrupt_0_enable; + u32 cmn_interrupt_2_enable; + + /* LLCC DRP registers */ + u32 drp_ecc_error_cfg; + u32 drp_ecc_error_cntr_clear; + u32 drp_interrupt_status; + u32 drp_interrupt_clear; + u32 drp_interrupt_enable; + u32 drp_ecc_error_status0; + u32 drp_ecc_error_status1; + u32 drp_ecc_sb_err_syn0; + u32 drp_ecc_db_err_syn0; +}; + /** * struct llcc_drv_data - Data associated with the llcc driver * @regmap: regmap associated with the llcc device * @bcast_regmap: regmap associated with llcc broadcast offset * @cfg: pointer to the data structure for slice configuration + * @edac_reg_offset: Offset of the LLCC EDAC registers * @lock: mutex associated with each slice * @cfg_size: size of the config data table * @max_slices: max slices as read from device tree @@ -96,6 +125,7 @@ struct llcc_drv_data { struct regmap *regmap; struct regmap *bcast_regmap; const struct llcc_slice_config *cfg; + const struct llcc_edac_reg_offset *edac_reg_offset; struct mutex lock; u32 cfg_size; u32 max_slices; -- cgit v1.2.3 From 9d0d887ac7e5a32834cda4f305e1875fccaf67ff Mon Sep 17 00:00:00 2001 From: "Nícolas F. R. A. Prado" Date: Mon, 29 Aug 2022 16:44:39 -0400 Subject: soc: mediatek: mtk-svs: Explicitly include bitfield header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit a92438c5a30a ("soc: mediatek: mtk-svs: Use bitfield access macros where possible") introduced the use of FIELD_GET and FIELD_PREP macros, which are defined in the bitfield header. Add an explicit include for it so we're sure to have the symbols defined independently of the config. Fixes: a92438c5a30a ("soc: mediatek: mtk-svs: Use bitfield access macros where possible") Reported-by: kernel test robot Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220829204439.3748648-1-nfraprado@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-svs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index da1a3bfc8633..0469c9dfeb04 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -3,6 +3,7 @@ * Copyright (C) 2022 MediaTek Inc. */ +#include #include #include #include -- cgit v1.2.3 From 8c1561edc0692fa8e321daf2777c3c32454b5748 Mon Sep 17 00:00:00 2001 From: "Chengci.Xu" Date: Wed, 17 Aug 2022 20:46:06 +0800 Subject: memory: mtk-smi: Add return value for configure port function In MT8188, the register to enable/disable IOMMU can only be configured in secure world by SMC call. We should add a return value for configure port function for preparation because SMC call may return an error result. Signed-off-by: Chengci.Xu Reviewed-by: Yong Wu Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220817124608.10062-3-chengci.xu@mediatek.com --- drivers/memory/mtk-smi.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index d7cb7ead2ac7..7e97406ab4a3 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -127,7 +127,7 @@ struct mtk_smi_common_plat { struct mtk_smi_larb_gen { int port_in_larb[MTK_LARB_NR_MAX + 1]; - void (*config_port)(struct device *dev); + int (*config_port)(struct device *dev); unsigned int larb_direct_to_common_mask; unsigned int flags_general; const u8 (*ostd)[SMI_LARB_PORT_NR_MAX]; @@ -185,7 +185,7 @@ static const struct component_ops mtk_smi_larb_component_ops = { .unbind = mtk_smi_larb_unbind, }; -static void mtk_smi_larb_config_port_gen1(struct device *dev) +static int mtk_smi_larb_config_port_gen1(struct device *dev) { struct mtk_smi_larb *larb = dev_get_drvdata(dev); const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen; @@ -214,23 +214,26 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev) common->smi_ao_base + REG_SMI_SECUR_CON_ADDR(m4u_port_id)); } + return 0; } -static void mtk_smi_larb_config_port_mt8167(struct device *dev) +static int 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); + return 0; } -static void mtk_smi_larb_config_port_mt8173(struct device *dev) +static int mtk_smi_larb_config_port_mt8173(struct device *dev) { struct mtk_smi_larb *larb = dev_get_drvdata(dev); writel(*larb->mmu, larb->base + MT8173_SMI_LARB_MMU_EN); + return 0; } -static void mtk_smi_larb_config_port_gen2_general(struct device *dev) +static int mtk_smi_larb_config_port_gen2_general(struct device *dev) { struct mtk_smi_larb *larb = dev_get_drvdata(dev); u32 reg, flags_general = larb->larb_gen->flags_general; @@ -238,7 +241,7 @@ static void mtk_smi_larb_config_port_gen2_general(struct device *dev) int i; if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask) - return; + return 0; if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_THRT_UPDATE)) { reg = readl_relaxed(larb->base + SMI_LARB_CMD_THRT_CON); @@ -259,6 +262,7 @@ static void mtk_smi_larb_config_port_gen2_general(struct device *dev) reg |= BANK_SEL(larb->bank[i]); writel(reg, larb->base + SMI_LARB_NONSEC_CON(i)); } + return 0; } static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = { @@ -511,9 +515,7 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev) mtk_smi_larb_sleep_ctrl_disable(larb); /* Configure the basic setting for this larb */ - larb_gen->config_port(dev); - - return 0; + return larb_gen->config_port(dev); } static int __maybe_unused mtk_smi_larb_suspend(struct device *dev) -- cgit v1.2.3 From 4e508b259ed02f5fa608cdd83b817a7f49c22271 Mon Sep 17 00:00:00 2001 From: "Chengci.Xu" Date: Wed, 17 Aug 2022 20:46:07 +0800 Subject: memory: mtk-smi: Add enable IOMMU SMC command for MM master For concerns about security, the register to enable/disable IOMMU of SMI LARB should only be configured in secure world. Thus, we add some SMC command for multimedia master to enable/disable MM IOMMU in ATF by setting the register of SMI LARB. This function is prepared for MT8188. Signed-off-by: Chengci.Xu Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220817124608.10062-4-chengci.xu@mediatek.com --- drivers/memory/mtk-smi.c | 18 ++++++++++++++++++ include/linux/soc/mediatek/mtk_sip_svc.h | 3 +++ include/soc/mediatek/smi.h | 5 +++++ 3 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 7e97406ab4a3..73a8a9867082 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -3,6 +3,7 @@ * Copyright (c) 2015-2016 MediaTek Inc. * Author: Yong Wu */ +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +91,7 @@ #define MTK_SMI_FLAG_THRT_UPDATE BIT(0) #define MTK_SMI_FLAG_SW_FLAG BIT(1) #define MTK_SMI_FLAG_SLEEP_CTL BIT(2) +#define MTK_SMI_FLAG_CFG_PORT_SEC_CTL BIT(3) #define MTK_SMI_CAPS(flags, _x) (!!((flags) & (_x))) struct mtk_smi_reg_pair { @@ -238,6 +241,7 @@ static int mtk_smi_larb_config_port_gen2_general(struct device *dev) struct mtk_smi_larb *larb = dev_get_drvdata(dev); u32 reg, flags_general = larb->larb_gen->flags_general; const u8 *larbostd = larb->larb_gen->ostd ? larb->larb_gen->ostd[larb->larbid] : NULL; + struct arm_smccc_res res; int i; if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask) @@ -256,6 +260,20 @@ static int mtk_smi_larb_config_port_gen2_general(struct device *dev) for (i = 0; i < SMI_LARB_PORT_NR_MAX && larbostd && !!larbostd[i]; i++) writel_relaxed(larbostd[i], larb->base + SMI_LARB_OSTDL_PORTx(i)); + /* + * When mmu_en bits are in security world, the bank_sel still is in the + * LARB_NONSEC_CON below. And the mmu_en bits of LARB_NONSEC_CON have no + * effect in this case. + */ + if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_CFG_PORT_SEC_CTL)) { + arm_smccc_smc(MTK_SIP_KERNEL_IOMMU_CONTROL, IOMMU_ATF_CMD_CONFIG_SMI_LARB, + larb->larbid, *larb->mmu, 0, 0, 0, 0, &res); + if (res.a0 != 0) { + dev_err(dev, "Enable iommu fail, ret %ld\n", res.a0); + return -EINVAL; + } + } + for_each_set_bit(i, (unsigned long *)larb->mmu, 32) { reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i)); reg |= F_MMU_EN; diff --git a/include/linux/soc/mediatek/mtk_sip_svc.h b/include/linux/soc/mediatek/mtk_sip_svc.h index 082398e0cfb1..0761128b4354 100644 --- a/include/linux/soc/mediatek/mtk_sip_svc.h +++ b/include/linux/soc/mediatek/mtk_sip_svc.h @@ -22,4 +22,7 @@ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, MTK_SIP_SMC_CONVENTION, \ ARM_SMCCC_OWNER_SIP, fn_id) +/* IOMMU related SMC call */ +#define MTK_SIP_KERNEL_IOMMU_CONTROL MTK_SIP_SMC_CMD(0x514) + #endif diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h index 11f7d6b59642..dfd8efca5e60 100644 --- a/include/soc/mediatek/smi.h +++ b/include/soc/mediatek/smi.h @@ -11,6 +11,11 @@ #if IS_ENABLED(CONFIG_MTK_SMI) +enum iommu_atf_cmd { + IOMMU_ATF_CMD_CONFIG_SMI_LARB, /* For mm master to en/disable iommu */ + IOMMU_ATF_CMD_MAX, +}; + #define MTK_SMI_MMU_EN(port) BIT(port) struct mtk_smi_larb_iommu { -- cgit v1.2.3 From 673e71df5ccfaefeb32bb5b3130a5d397b742194 Mon Sep 17 00:00:00 2001 From: "Chengci.Xu" Date: Wed, 17 Aug 2022 20:46:08 +0800 Subject: memory: mtk-smi: mt8188: Add SMI Support Add mt8188 smi common & larb support Signed-off-by: Chengci.Xu Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Yong Wu Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220817124608.10062-5-chengci.xu@mediatek.com --- drivers/memory/mtk-smi.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'drivers') diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 73a8a9867082..5a9754442bc7 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -283,6 +283,55 @@ static int mtk_smi_larb_config_port_gen2_general(struct device *dev) return 0; } +static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = { + [0] = {0x02, 0x18, 0x22, 0x22, 0x01, 0x02, 0x0a,}, + [1] = {0x12, 0x02, 0x14, 0x14, 0x01, 0x18, 0x0a,}, + [2] = {0x12, 0x12, 0x12, 0x12, 0x0a,}, + [3] = {0x12, 0x12, 0x12, 0x12, 0x28, 0x28, 0x0a,}, + [4] = {0x06, 0x01, 0x17, 0x06, 0x0a, 0x07, 0x07,}, + [5] = {0x02, 0x01, 0x04, 0x02, 0x06, 0x01, 0x06, 0x0a,}, + [6] = {0x06, 0x01, 0x06, 0x0a,}, + [7] = {0x0c, 0x0c, 0x12,}, + [8] = {0x0c, 0x01, 0x0a, 0x05, 0x02, 0x03, 0x01, 0x01, 0x14, 0x14, + 0x0a, 0x14, 0x1e, 0x01, 0x0c, 0x0a, 0x05, 0x02, 0x02, 0x05, + 0x03, 0x01, 0x1e, 0x01, 0x05,}, + [9] = {0x1e, 0x01, 0x0a, 0x0a, 0x01, 0x01, 0x03, 0x1e, 0x1e, 0x10, + 0x07, 0x01, 0x0a, 0x06, 0x03, 0x03, 0x0e, 0x01, 0x04, 0x28,}, + [10] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14, + 0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,}, + [11] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14, + 0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,}, + [12] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14, + 0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,}, + [13] = {0x07, 0x02, 0x04, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x07, 0x02, 0x04, 0x02, 0x05, 0x05,}, + [14] = {0x02, 0x02, 0x0c, 0x0c, 0x0c, 0x0c, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x01, 0x01,}, + [15] = {0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x0c, 0x0c, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, + 0x0c, 0x01, 0x01,}, + [16] = {0x28, 0x28, 0x03, 0x01, 0x01, 0x03, 0x14, 0x14, 0x0a, 0x0d, + 0x03, 0x05, 0x0e, 0x01, 0x01, 0x05, 0x06, 0x0d, 0x01,}, + [17] = {0x28, 0x02, 0x02, 0x12, 0x02, 0x12, 0x10, 0x02, 0x02, 0x0a, + 0x12, 0x02, 0x02, 0x0a, 0x16, 0x02, 0x04,}, + [18] = {0x28, 0x02, 0x02, 0x12, 0x02, 0x12, 0x10, 0x02, 0x02, 0x0a, + 0x12, 0x02, 0x02, 0x0a, 0x16, 0x02, 0x04,}, + [19] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,}, + [20] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,}, + [21] = {0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x01, + 0x01, 0x01, 0x04, 0x0a, 0x06, 0x01, 0x01, 0x01, 0x0a, 0x06, + 0x01, 0x01, 0x05, 0x03, 0x03, 0x04, 0x01,}, + [22] = {0x28, 0x19, 0x0c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, + 0x01,}, + [23] = {0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x18, 0x01, 0x01,}, + [24] = {0x12, 0x06, 0x12, 0x06,}, + [25] = {0x01}, +}; + static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = { [0] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb0 */ [1] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb1 */ @@ -369,6 +418,13 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8186 = { .flags_general = MTK_SMI_FLAG_SLEEP_CTL, }; +static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = { + .config_port = mtk_smi_larb_config_port_gen2_general, + .flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG | + MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CFG_PORT_SEC_CTL, + .ostd = mtk_smi_larb_mt8188_ostd, +}; + static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = { .config_port = mtk_smi_larb_config_port_gen2_general, }; @@ -389,6 +445,7 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = { {.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173}, {.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183}, {.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186}, + {.compatible = "mediatek,mt8188-smi-larb", .data = &mtk_smi_larb_mt8188}, {.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192}, {.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195}, {} @@ -617,6 +674,18 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8186 = { .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(4) | F_MMU1_LARB(7), }; +static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vdo = { + .type = MTK_SMI_GEN2, + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(5) | F_MMU1_LARB(7), + .init = mtk_smi_common_mt8195_init, +}; + +static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = { + .type = MTK_SMI_GEN2, + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(7), + .init = mtk_smi_common_mt8195_init, +}; + static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = { .type = MTK_SMI_GEN2, .has_gals = true, @@ -653,6 +722,8 @@ static const struct of_device_id mtk_smi_common_of_ids[] = { {.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2}, {.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183}, {.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186}, + {.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo}, + {.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp}, {.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192}, {.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo}, {.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp}, -- cgit v1.2.3 From 385ba16dbf9edad0b898d160a40e98e379fc05c5 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 5 Aug 2022 23:46:49 +0200 Subject: soc: mediatek: pm-domains: Simplify some error message dev_err_probe() already prints the error code in a human readable way, so there is no need to duplicate it as a numerical value at the end of the message. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/e6ba80d8e27fdb2b1527c7eae6687e481960c81d.1659735996.git.christophe.jaillet@wanadoo.fr Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pm-domains.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c index 9734f1091c69..09e3c38b8466 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.c +++ b/drivers/soc/mediatek/mtk-pm-domains.c @@ -393,7 +393,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err_probe(scpsys->dev, ret, - "%pOF: failed to get clk at index %d: %d\n", node, i, ret); + "%pOF: failed to get clk at index %d\n", node, i); goto err_put_clocks; } @@ -405,8 +405,8 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err_probe(scpsys->dev, ret, - "%pOF: failed to get clk at index %d: %d\n", node, - i + clk_ind, ret); + "%pOF: failed to get clk at index %d\n", node, + i + clk_ind); goto err_put_subsys_clocks; } -- cgit v1.2.3 From 21370ecddfe1ff6fb826faedb601cfbb7adcf4ff Mon Sep 17 00:00:00 2001 From: Allen-KH Cheng Date: Thu, 1 Sep 2022 01:21:51 +0800 Subject: soc: mediatek: mutex: Add mt8186 mutex mod settings for mdp3 Add mt8186 mutex mod settings for mdp3. Co-developed-by: Xiandong Wang Signed-off-by: Xiandong Wang Signed-off-by: Allen-KH Cheng Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220831172151.10215-3-allen-kh.cheng@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-mutex.c | 28 ++++++++++++++++++++++++++++ include/linux/soc/mediatek/mtk-mutex.h | 2 ++ 2 files changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c index 5ea43de4e410..f95100d4de73 100644 --- a/drivers/soc/mediatek/mtk-mutex.c +++ b/drivers/soc/mediatek/mtk-mutex.c @@ -91,6 +91,15 @@ #define MT8183_MUTEX_MOD_MDP_AAL0 23 #define MT8183_MUTEX_MOD_MDP_CCORR0 24 +#define MT8186_MUTEX_MOD_MDP_RDMA0 0 +#define MT8186_MUTEX_MOD_MDP_AAL0 2 +#define MT8186_MUTEX_MOD_MDP_HDR0 4 +#define MT8186_MUTEX_MOD_MDP_RSZ0 5 +#define MT8186_MUTEX_MOD_MDP_RSZ1 6 +#define MT8186_MUTEX_MOD_MDP_WROT0 7 +#define MT8186_MUTEX_MOD_MDP_TDSHP0 9 +#define MT8186_MUTEX_MOD_MDP_COLOR0 14 + #define MT8173_MUTEX_MOD_DISP_OVL0 11 #define MT8173_MUTEX_MOD_DISP_OVL1 12 #define MT8173_MUTEX_MOD_DISP_RDMA0 13 @@ -324,6 +333,17 @@ static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_RDMA1] = MT8186_MUTEX_MOD_DISP_RDMA1, }; +static const unsigned int mt8186_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = { + [MUTEX_MOD_IDX_MDP_RDMA0] = MT8186_MUTEX_MOD_MDP_RDMA0, + [MUTEX_MOD_IDX_MDP_RSZ0] = MT8186_MUTEX_MOD_MDP_RSZ0, + [MUTEX_MOD_IDX_MDP_RSZ1] = MT8186_MUTEX_MOD_MDP_RSZ1, + [MUTEX_MOD_IDX_MDP_TDSHP0] = MT8186_MUTEX_MOD_MDP_TDSHP0, + [MUTEX_MOD_IDX_MDP_WROT0] = MT8186_MUTEX_MOD_MDP_WROT0, + [MUTEX_MOD_IDX_MDP_HDR0] = MT8186_MUTEX_MOD_MDP_HDR0, + [MUTEX_MOD_IDX_MDP_AAL0] = MT8186_MUTEX_MOD_MDP_AAL0, + [MUTEX_MOD_IDX_MDP_COLOR0] = MT8186_MUTEX_MOD_MDP_COLOR0, +}; + static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0, [DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0, @@ -458,6 +478,12 @@ static const struct mtk_mutex_data mt8183_mutex_driver_data = { .no_clk = true, }; +static const struct mtk_mutex_data mt8186_mdp_mutex_driver_data = { + .mutex_mod_reg = MT8183_MUTEX0_MOD0, + .mutex_sof_reg = MT8183_MUTEX0_SOF0, + .mutex_table_mod = mt8186_mdp_mutex_table_mod, +}; + static const struct mtk_mutex_data mt8186_mutex_driver_data = { .mutex_mod = mt8186_mutex_mod, .mutex_sof = mt8186_mutex_sof, @@ -810,6 +836,8 @@ static const struct of_device_id mutex_driver_dt_match[] = { .data = &mt8183_mutex_driver_data}, { .compatible = "mediatek,mt8186-disp-mutex", .data = &mt8186_mutex_driver_data}, + { .compatible = "mediatek,mt8186-mdp3-mutex", + .data = &mt8186_mdp_mutex_driver_data}, { .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data}, { .compatible = "mediatek,mt8195-disp-mutex", diff --git a/include/linux/soc/mediatek/mtk-mutex.h b/include/linux/soc/mediatek/mtk-mutex.h index a0f4f51a3b45..b335c2837cd8 100644 --- a/include/linux/soc/mediatek/mtk-mutex.h +++ b/include/linux/soc/mediatek/mtk-mutex.h @@ -20,6 +20,8 @@ enum mtk_mutex_mod_index { MUTEX_MOD_IDX_MDP_WDMA, MUTEX_MOD_IDX_MDP_AAL0, MUTEX_MOD_IDX_MDP_CCORR0, + MUTEX_MOD_IDX_MDP_HDR0, + MUTEX_MOD_IDX_MDP_COLOR0, MUTEX_MOD_IDX_MAX /* ALWAYS keep at the end */ }; -- cgit v1.2.3 From 9491cff16a4996aee578adf9f41acfb1bc483df9 Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 26 Jul 2022 15:38:41 +0800 Subject: soc: amlogic: meson-pwrc: Hold reference returned by of_get_parent() We should hold the reference returned by of_get_parent() and use it to call of_node_put() for refcount balance. Signed-off-by: Liang He Reviewed-by: Neil Armstrong Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20220726073841.1320509-1-windhl@126.com --- drivers/soc/amlogic/meson-ee-pwrc.c | 5 ++++- drivers/soc/amlogic/meson-gx-pwrc-vpu.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c index 2be3afe6c2e3..dd5f2a13ceb5 100644 --- a/drivers/soc/amlogic/meson-ee-pwrc.c +++ b/drivers/soc/amlogic/meson-ee-pwrc.c @@ -469,6 +469,7 @@ static int meson_ee_pwrc_probe(struct platform_device *pdev) { const struct meson_ee_pwrc_domain_data *match; struct regmap *regmap_ao, *regmap_hhi; + struct device_node *parent_np; struct meson_ee_pwrc *pwrc; int i, ret; @@ -495,7 +496,9 @@ static int meson_ee_pwrc_probe(struct platform_device *pdev) pwrc->xlate.num_domains = match->count; - regmap_hhi = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node)); + parent_np = of_get_parent(pdev->dev.of_node); + regmap_hhi = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap_hhi)) { dev_err(&pdev->dev, "failed to get HHI regmap\n"); return PTR_ERR(regmap_hhi); diff --git a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c index b4615b288625..312fd9afccb0 100644 --- a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c +++ b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c @@ -273,6 +273,7 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev) const struct meson_gx_pwrc_vpu *vpu_pd_match; struct regmap *regmap_ao, *regmap_hhi; struct meson_gx_pwrc_vpu *vpu_pd; + struct device_node *parent_np; struct reset_control *rstc; struct clk *vpu_clk; struct clk *vapb_clk; @@ -291,7 +292,9 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev) memcpy(vpu_pd, vpu_pd_match, sizeof(*vpu_pd)); - regmap_ao = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node)); + parent_np = of_get_parent(pdev->dev.of_node); + regmap_ao = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap_ao)) { dev_err(&pdev->dev, "failed to get regmap\n"); return PTR_ERR(regmap_ao); -- cgit v1.2.3 From 66296e0a318e12ef1ca04013e1e893539e715c5a Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Thu, 18 Aug 2022 18:11:16 +0530 Subject: soc: rockchip: power-domain: Add RV1126 power domains Add power domains support for RV1126 SoC. Cypto, VO and NPU domains will add it future patches. Signed-off-by: Elaine Zhang Signed-off-by: Jagan Teki Link: https://lore.kernel.org/r/20220818124132.125304-4-jagan@edgeble.ai Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 89795abac951..3aaadab2716e 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -126,6 +127,9 @@ struct rockchip_pmu { #define DOMAIN_PX30(name, pwr, status, req, wakeup) \ DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup) +#define DOMAIN_RV1126(name, pwr, req, idle, wakeup) \ + DOMAIN_M(name, pwr, pwr, req, idle, idle, wakeup) + #define DOMAIN_RK3288(name, pwr, status, req, wakeup) \ DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup) @@ -855,6 +859,16 @@ static const struct rockchip_domain_info px30_pm_domains[] = { [PX30_PD_GPU] = DOMAIN_PX30("gpu", BIT(15), BIT(15), BIT(2), false), }; +static const struct rockchip_domain_info rv1126_pm_domains[] = { + [RV1126_PD_VEPU] = DOMAIN_RV1126("vepu", BIT(2), BIT(9), BIT(9), false), + [RV1126_PD_VI] = DOMAIN_RV1126("vi", BIT(4), BIT(6), BIT(6), false), + [RV1126_PD_ISPP] = DOMAIN_RV1126("ispp", BIT(1), BIT(8), BIT(8), false), + [RV1126_PD_VDPU] = DOMAIN_RV1126("vdpu", BIT(3), BIT(10), BIT(10), false), + [RV1126_PD_NVM] = DOMAIN_RV1126("nvm", BIT(7), BIT(11), BIT(11), false), + [RV1126_PD_SDIO] = DOMAIN_RV1126("sdio", BIT(8), BIT(13), BIT(13), false), + [RV1126_PD_USB] = DOMAIN_RV1126("usb", BIT(9), BIT(15), BIT(15), false), +}; + static const struct rockchip_domain_info rk3036_pm_domains[] = { [RK3036_PD_MSCH] = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true), [RK3036_PD_CORE] = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false), @@ -1128,6 +1142,17 @@ static const struct rockchip_pmu_info rk3568_pmu = { .domain_info = rk3568_pm_domains, }; +static const struct rockchip_pmu_info rv1126_pmu = { + .pwr_offset = 0x110, + .status_offset = 0x108, + .req_offset = 0xc0, + .idle_offset = 0xd8, + .ack_offset = 0xd0, + + .num_domains = ARRAY_SIZE(rv1126_pm_domains), + .domain_info = rv1126_pm_domains, +}; + static const struct of_device_id rockchip_pm_domain_dt_match[] = { { .compatible = "rockchip,px30-power-controller", @@ -1177,6 +1202,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = { .compatible = "rockchip,rk3568-power-controller", .data = (void *)&rk3568_pmu, }, + { + .compatible = "rockchip,rv1126-power-controller", + .data = (void *)&rv1126_pmu, + }, { /* sentinel */ }, }; -- cgit v1.2.3 From 570ed4e5b0d9e784f51a52bede2326391afa8c3f Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 18 Aug 2022 18:11:18 +0530 Subject: soc: rockchip: io-domain: Add RV1126 IO domains Add IO domains support for RV1126 SoC. Cc: Liam Girdwood Cc: Mark Brown Signed-off-by: Jianqun Xu Signed-off-by: Jagan Teki Link: https://lore.kernel.org/r/20220818124132.125304-6-jagan@edgeble.ai Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/io-domain.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c index 9df513d1219b..6619256c2d11 100644 --- a/drivers/soc/rockchip/io-domain.c +++ b/drivers/soc/rockchip/io-domain.c @@ -491,6 +491,22 @@ static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = { }, }; +static const struct rockchip_iodomain_soc_data soc_data_rv1126_pmu = { + .grf_offset = 0x140, + .supply_names = { + NULL, + "vccio1", + "vccio2", + "vccio3", + "vccio4", + "vccio5", + "vccio6", + "vccio7", + "pmuio0", + "pmuio1", + }, +}; + static const struct of_device_id rockchip_iodomain_match[] = { { .compatible = "rockchip,px30-io-voltage-domain", @@ -544,6 +560,10 @@ static const struct of_device_id rockchip_iodomain_match[] = { .compatible = "rockchip,rv1108-pmu-io-voltage-domain", .data = &soc_data_rv1108_pmu }, + { + .compatible = "rockchip,rv1126-pmu-io-voltage-domain", + .data = &soc_data_rv1126_pmu + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, rockchip_iodomain_match); -- cgit v1.2.3 From 1335fc5b24d3fd51bdae0747b153433f2969edfc Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 2 Sep 2022 10:05:09 +0530 Subject: soc: qcom: icc-bwmon: add support for sc7280 LLCC BWMON Add support for sc7280 BWMON instance measuring traffic between LLCC and memory with the v5 register layout. Signed-off-by: Rajendra Nayak Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220902043511.17130-3-quic_rjendra@quicinc.com --- drivers/soc/qcom/icc-bwmon.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 9df47afb0d81..056e630500e0 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -654,6 +654,18 @@ static const struct icc_bwmon_data sdm845_llcc_bwmon_data = { .regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg, }; +static const struct icc_bwmon_data sc7280_llcc_bwmon_data = { + .sample_ms = 4, + .count_unit_kb = 64, + .default_highbw_kbps = 800 * 1024, /* 800 MBps */ + .default_medbw_kbps = 256 * 1024, /* 256 MBps */ + .default_lowbw_kbps = 0, + .zone1_thres_count = 16, + .zone3_thres_count = 1, + .regmap_fields = sdm845_llcc_bwmon_reg_fields, + .regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg, +}; + static const struct of_device_id bwmon_of_match[] = { { .compatible = "qcom,msm8998-bwmon", @@ -661,6 +673,9 @@ static const struct of_device_id bwmon_of_match[] = { }, { .compatible = "qcom,sdm845-llcc-bwmon", .data = &sdm845_llcc_bwmon_data + }, { + .compatible = "qcom,sc7280-llcc-bwmon", + .data = &sc7280_llcc_bwmon_data }, {} }; -- cgit v1.2.3 From cdad59c2d8698505c328c19832fbd2781e79adac Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 2 Sep 2022 10:05:10 +0530 Subject: soc: qcom: icc-bwmon: force clear counter/irq registers In some SoCs we have to force clear the counter/irq clear registers as they are not self clearing after they are written into. sc7280 seems to be one such SoC, handle this with a quirk flag. Signed-off-by: Rajendra Nayak Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220902043511.17130-4-quic_rjendra@quicinc.com --- drivers/soc/qcom/icc-bwmon.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 056e630500e0..d07be3700db6 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -115,6 +115,7 @@ /* Quirks for specific BWMON types */ #define BWMON_HAS_GLOBAL_IRQ BIT(0) +#define BWMON_NEEDS_FORCE_CLEAR BIT(1) enum bwmon_fields { F_GLOBAL_IRQ_CLEAR, @@ -343,6 +344,8 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all) * before we try to clear the IRQ or do any other counter operations. */ regmap_field_force_write(bwmon->regs[F_CLEAR], val); + if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR) + regmap_field_force_write(bwmon->regs[F_CLEAR], 0); } static void bwmon_clear_irq(struct icc_bwmon *bwmon) @@ -364,6 +367,8 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon) * interrupt is cleared. */ regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], BWMON_IRQ_ENABLE_MASK); + if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR) + regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], 0); if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ) regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR], BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE); @@ -662,6 +667,7 @@ static const struct icc_bwmon_data sc7280_llcc_bwmon_data = { .default_lowbw_kbps = 0, .zone1_thres_count = 16, .zone3_thres_count = 1, + .quirks = BWMON_NEEDS_FORCE_CLEAR, .regmap_fields = sdm845_llcc_bwmon_reg_fields, .regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg, }; -- cgit v1.2.3 From 947f11d153f20f87828a15e829d69890db71bcf7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 5 Sep 2022 16:23:02 +0800 Subject: bus: hisi_lpc: Don't dereference fwnode handle Use dev_fwnode() and acpi_fwnode_handle() instead of dereferencing an fwnode handle directly, which is a better coding practice. While at it, reuse fwnode instead of ACPI_COMPANION(). Signed-off-by: Andy Shevchenko Reviewed-by: Rafael J. Wysocki Signed-off-by: John Garry Signed-off-by: Wei Xu --- drivers/bus/hisi_lpc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index 2e564803e786..6d432a07cbba 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -347,7 +347,7 @@ static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev, unsigned long sys_port; resource_size_t len = resource_size(res); - sys_port = logic_pio_trans_hwaddr(&host->fwnode, res->start, len); + sys_port = logic_pio_trans_hwaddr(acpi_fwnode_handle(host), res->start, len); if (sys_port == ~0UL) return -EFAULT; @@ -615,7 +615,6 @@ static void hisi_lpc_acpi_remove(struct device *hostdev) static int hisi_lpc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct acpi_device *acpi_device = ACPI_COMPANION(dev); struct logic_pio_hwaddr *range; struct hisi_lpc_dev *lpcdev; resource_size_t io_end; @@ -637,7 +636,7 @@ static int hisi_lpc_probe(struct platform_device *pdev) if (!range) return -ENOMEM; - range->fwnode = dev->fwnode; + range->fwnode = dev_fwnode(dev); range->flags = LOGIC_PIO_INDIRECT; range->size = PIO_INDIRECT_SIZE; range->hostdata = lpcdev; @@ -651,7 +650,7 @@ static int hisi_lpc_probe(struct platform_device *pdev) } /* register the LPC host PIO resources */ - if (acpi_device) + if (is_acpi_device_node(range->fwnode)) ret = hisi_lpc_acpi_probe(dev); else ret = of_platform_populate(dev->of_node, NULL, NULL, dev); @@ -672,11 +671,10 @@ static int hisi_lpc_probe(struct platform_device *pdev) static int hisi_lpc_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct acpi_device *acpi_device = ACPI_COMPANION(dev); struct hisi_lpc_dev *lpcdev = dev_get_drvdata(dev); struct logic_pio_hwaddr *range = lpcdev->io_host; - if (acpi_device) + if (is_acpi_device_node(range->fwnode)) hisi_lpc_acpi_remove(dev); else of_platform_depopulate(dev); -- cgit v1.2.3 From 23bea44cd00c618dca7877366cf8a5340ac110e9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 5 Sep 2022 16:23:03 +0800 Subject: bus: hisi_lpc: Use devm_platform_ioremap_resource The struct resource is not used for anything else, so we can simplify the code a bit by using the helper function. Signed-off-by: Andy Shevchenko Reviewed-by: Rafael J. Wysocki Signed-off-by: John Garry Signed-off-by: Wei Xu --- drivers/bus/hisi_lpc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index 6d432a07cbba..03d4d96ff794 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -618,7 +618,6 @@ static int hisi_lpc_probe(struct platform_device *pdev) struct logic_pio_hwaddr *range; struct hisi_lpc_dev *lpcdev; resource_size_t io_end; - struct resource *res; int ret; lpcdev = devm_kzalloc(dev, sizeof(*lpcdev), GFP_KERNEL); @@ -627,8 +626,7 @@ static int hisi_lpc_probe(struct platform_device *pdev) spin_lock_init(&lpcdev->cycle_lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - lpcdev->membase = devm_ioremap_resource(dev, res); + lpcdev->membase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(lpcdev->membase)) return PTR_ERR(lpcdev->membase); -- cgit v1.2.3 From 5e3e70b8e1ae98358d1534e27b0a8259ce3efee8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 5 Sep 2022 16:23:04 +0800 Subject: bus: hisi_lpc: Correct error code for timeout The usual error code is -ETIMEDOUT, the currently used -ETIME is specific for timers. Signed-off-by: Andy Shevchenko Reviewed-by: Rafael J. Wysocki Signed-off-by: John Garry Signed-off-by: Wei Xu --- drivers/bus/hisi_lpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index 03d4d96ff794..a6513a571d7b 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -85,7 +85,7 @@ static int wait_lpc_idle(void __iomem *mbase, unsigned int waitcnt) ndelay(LPC_NSEC_PERWAIT); } while (--waitcnt); - return -ETIME; + return -ETIMEDOUT; } /* -- cgit v1.2.3 From e8cd65061fac64d6d0b5c3f5c3059c326b1492f0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 5 Sep 2022 16:23:05 +0800 Subject: bus: hisi_lpc: Don't guard ACPI IDs with ACPI_PTR() The OF ID table is not guarded, and the ACPI table does not needs it either. The IDs do not depend on the configuration. Hence drop ACPI_PTR() from the code and move ID table closer to its user. Signed-off-by: Andy Shevchenko Reviewed-by: Rafael J. Wysocki Signed-off-by: John Garry Signed-off-by: Wei Xu --- drivers/bus/hisi_lpc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index a6513a571d7b..74f4448bff9d 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -589,11 +589,6 @@ static int hisi_lpc_acpi_probe(struct device *hostdev) return ret; } - -static const struct acpi_device_id hisi_lpc_acpi_match[] = { - {"HISI0191"}, - {} -}; #else static int hisi_lpc_acpi_probe(struct device *dev) { @@ -688,11 +683,16 @@ static const struct of_device_id hisi_lpc_of_match[] = { {} }; +static const struct acpi_device_id hisi_lpc_acpi_match[] = { + {"HISI0191"}, + {} +}; + static struct platform_driver hisi_lpc_driver = { .driver = { .name = DRV_NAME, .of_match_table = hisi_lpc_of_match, - .acpi_match_table = ACPI_PTR(hisi_lpc_acpi_match), + .acpi_match_table = hisi_lpc_acpi_match, }, .probe = hisi_lpc_probe, .remove = hisi_lpc_remove, -- cgit v1.2.3 From 4678a2d352e055a186dd02613d54e30785810fb0 Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 5 Sep 2022 16:23:06 +0800 Subject: bus: hisi_lpc: Use platform_device_register_full() The code to create the child platform device is essentially the same as what platform_device_register_full() does, so change over to use that same function to reduce duplication. Signed-off-by: John Garry Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Wei Xu --- drivers/bus/hisi_lpc.c | 68 ++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index 74f4448bff9d..5b65a48f17e7 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -472,9 +472,7 @@ static int hisi_lpc_acpi_clear_enumerated(struct acpi_device *adev, void *not_us struct hisi_lpc_acpi_cell { const char *hid; - const char *name; - void *pdata; - size_t pdata_size; + const struct platform_device_info *pdevinfo; }; static void hisi_lpc_acpi_remove(struct device *hostdev) @@ -505,28 +503,45 @@ static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data) /* ipmi */ { .hid = "IPI0001", - .name = "hisi-lpc-ipmi", + .pdevinfo = (struct platform_device_info []) { + { + .parent = hostdev, + .fwnode = acpi_fwnode_handle(child), + .name = "hisi-lpc-ipmi", + .id = PLATFORM_DEVID_AUTO, + .res = res, + .num_res = num_res, + }, + }, }, /* 8250-compatible uart */ { .hid = "HISI1031", - .name = "serial8250", - .pdata = (struct plat_serial8250_port []) { + .pdevinfo = (struct platform_device_info []) { { - .iobase = res->start, - .uartclk = 1843200, - .iotype = UPIO_PORT, - .flags = UPF_BOOT_AUTOCONF, + .parent = hostdev, + .fwnode = acpi_fwnode_handle(child), + .name = "serial8250", + .id = PLATFORM_DEVID_AUTO, + .res = res, + .num_res = num_res, + .data = (struct plat_serial8250_port []) { + { + .iobase = res->start, + .uartclk = 1843200, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF, + }, + {} + }, + .size_data = 2 * sizeof(struct plat_serial8250_port), }, - {} }, - .pdata_size = 2 * - sizeof(struct plat_serial8250_port), }, {} }; - for (; cell && cell->name; cell++) { + for (; cell && cell->hid; cell++) { if (!strcmp(cell->hid, hid)) { found = true; break; @@ -540,31 +555,12 @@ static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data) return 0; } - pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO); - if (!pdev) - return -ENOMEM; - - pdev->dev.parent = hostdev; - ACPI_COMPANION_SET(&pdev->dev, child); - - ret = platform_device_add_resources(pdev, res, num_res); - if (ret) - goto fail; - - ret = platform_device_add_data(pdev, cell->pdata, cell->pdata_size); - if (ret) - goto fail; - - ret = platform_device_add(pdev); - if (ret) - goto fail; + pdev = platform_device_register_full(cell->pdevinfo); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); acpi_device_set_enumerated(child); return 0; - -fail: - platform_device_put(pdev); - return ret; } /* -- cgit v1.2.3 From d01387fc16421cbbf95d1fda8fe1258195396c64 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:31 +0100 Subject: firmware: arm_ffa: Add pointer to the ffa_dev_ops in struct ffa_dev Currently ffa_dev_ops_get() is the way to fetch the ffa_dev_ops pointer. It checks if the ffa_dev structure pointer is valid before returning the ffa_dev_ops pointer. Instead, the pointer can be made part of the ffa_dev structure and since the core driver is incharge of creating ffa_device for each identified partition, there is no need to check for the validity explicitly if the pointer is embedded in the structure. Add the pointer to the ffa_dev_ops in the ffa_dev structure itself and initialise the same as part of creation of the device. Link: https://lore.kernel.org/r/20220907145240.1683088-2-sudeep.holla@arm.com Reviewed-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/bus.c | 4 +++- drivers/firmware/arm_ffa/driver.c | 2 +- include/linux/arm_ffa.h | 7 +++++-- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index 641a91819088..69328041fbc3 100644 --- a/drivers/firmware/arm_ffa/bus.c +++ b/drivers/firmware/arm_ffa/bus.c @@ -167,7 +167,8 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev) return valid; } -struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id) +struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, + const struct ffa_dev_ops *ops) { int ret; struct device *dev; @@ -183,6 +184,7 @@ struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id) dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id); ffa_dev->vm_id = vm_id; + ffa_dev->ops = ops; uuid_copy(&ffa_dev->uuid, uuid); ret = device_register(&ffa_dev->dev); diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index ec731e9e942b..213665e5ad0e 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -688,7 +688,7 @@ static void ffa_setup_partitions(void) * as part of the discovery API, we need to pass the * discovered UUID here instead. */ - ffa_dev = ffa_device_register(&uuid_null, tpbuf->id); + ffa_dev = ffa_device_register(&uuid_null, tpbuf->id, &ffa_ops); if (!ffa_dev) { pr_err("%s: failed to register partition ID 0x%x\n", __func__, tpbuf->id); diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h index e5c76c1ef9ed..91b47e42b73d 100644 --- a/include/linux/arm_ffa.h +++ b/include/linux/arm_ffa.h @@ -17,6 +17,7 @@ struct ffa_device { bool mode_32bit; uuid_t uuid; struct device dev; + const struct ffa_dev_ops *ops; }; #define to_ffa_dev(d) container_of(d, struct ffa_device, dev) @@ -47,7 +48,8 @@ static inline void *ffa_dev_get_drvdata(struct ffa_device *fdev) } #if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT) -struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id); +struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, + const struct ffa_dev_ops *ops); void ffa_device_unregister(struct ffa_device *ffa_dev); int ffa_driver_register(struct ffa_driver *driver, struct module *owner, const char *mod_name); @@ -57,7 +59,8 @@ const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev); #else static inline -struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id) +struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, + const struct ffa_dev_ops *ops) { return NULL; } -- cgit v1.2.3 From 320c3fa38c514eb71aa188da3495e13da9a30542 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:32 +0100 Subject: tee: optee: Drop ffa_ops in optee_ffa structure using ffa_dev->ops directly Now that the ffa_device structure holds the pointer to ffa_dev_ops, there is no need to obtain the same through ffa_dev_ops_get(). Just use the ffa_dev->ops directly. Since the ffa_device itself carries ffa_dev_ops now, there is no need to keep a copy in optee_ffa structure. Drop ffa_ops in the optee_ffa structure as it is not needed anymore. Link: https://lore.kernel.org/r/20220907145240.1683088-3-sudeep.holla@arm.com Reviewed-by: Jens Wiklander Reviewed-by: Sumit Garg Signed-off-by: Sudeep Holla --- drivers/tee/optee/ffa_abi.c | 15 +++++---------- drivers/tee/optee/optee_private.h | 1 - 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index 7ab31740cff8..3d4079575ccd 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -271,8 +271,8 @@ static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm, unsigned long start) { struct optee *optee = tee_get_drvdata(ctx->teedev); - const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops; struct ffa_device *ffa_dev = optee->ffa.ffa_dev; + const struct ffa_dev_ops *ffa_ops = ffa_dev->ops; struct ffa_mem_region_attributes mem_attr = { .receiver = ffa_dev->vm_id, .attrs = FFA_MEM_RW, @@ -314,8 +314,8 @@ static int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) { struct optee *optee = tee_get_drvdata(ctx->teedev); - const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops; struct ffa_device *ffa_dev = optee->ffa.ffa_dev; + const struct ffa_dev_ops *ffa_ops = ffa_dev->ops; u64 global_handle = shm->sec_world_id; struct ffa_send_direct_data data = { .data0 = OPTEE_FFA_UNREGISTER_SHM, @@ -342,7 +342,7 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm) { struct optee *optee = tee_get_drvdata(ctx->teedev); - const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops; + const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_dev->ops; u64 global_handle = shm->sec_world_id; int rc; @@ -529,8 +529,8 @@ static int optee_ffa_yielding_call(struct tee_context *ctx, struct optee_msg_arg *rpc_arg) { struct optee *optee = tee_get_drvdata(ctx->teedev); - const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops; struct ffa_device *ffa_dev = optee->ffa.ffa_dev; + const struct ffa_dev_ops *ffa_ops = ffa_dev->ops; struct optee_call_waiter w; u32 cmd = data->data0; u32 w4 = data->data1; @@ -793,11 +793,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) u32 sec_caps; int rc; - ffa_ops = ffa_dev_ops_get(ffa_dev); - if (!ffa_ops) { - pr_warn("failed \"method\" init: ffa\n"); - return -ENOENT; - } + ffa_ops = ffa_dev->ops; if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops)) return -EINVAL; @@ -821,7 +817,6 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) optee->ops = &optee_ffa_ops; optee->ffa.ffa_dev = ffa_dev; - optee->ffa.ffa_ops = ffa_ops; optee->rpc_param_count = rpc_param_count; teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool, diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index a33d98d17cfd..04ae58892608 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -111,7 +111,6 @@ struct optee_smc { */ struct optee_ffa { struct ffa_device *ffa_dev; - const struct ffa_dev_ops *ffa_ops; /* Serializes access to @global_ids */ struct mutex mutex; struct rhashtable global_ids; -- cgit v1.2.3 From 55bf84fd0a76894ae29c69b3552e073fa37818be Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:33 +0100 Subject: firmware: arm_ffa: Remove ffa_dev_ops_get() The only user of this exported ffa_dev_ops_get() was OPTEE driver which now uses ffa_dev->ops directly, there are no other users for this. Also, since any ffa driver can use ffa_dev->ops directly, there will be no need for ffa_dev_ops_get(), so just remove ffa_dev_ops_get(). Link: https://lore.kernel.org/r/20220907145240.1683088-4-sudeep.holla@arm.com Reviewed-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 9 --------- include/linux/arm_ffa.h | 6 ------ 2 files changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 213665e5ad0e..04e7cbb1b9aa 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -644,15 +644,6 @@ static const struct ffa_dev_ops ffa_ops = { .memory_lend = ffa_memory_lend, }; -const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev) -{ - if (ffa_device_is_valid(dev)) - return &ffa_ops; - - return NULL; -} -EXPORT_SYMBOL_GPL(ffa_dev_ops_get); - void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid) { int count, idx; diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h index 91b47e42b73d..556f50f27fb1 100644 --- a/include/linux/arm_ffa.h +++ b/include/linux/arm_ffa.h @@ -55,7 +55,6 @@ int ffa_driver_register(struct ffa_driver *driver, struct module *owner, const char *mod_name); void ffa_driver_unregister(struct ffa_driver *driver); bool ffa_device_is_valid(struct ffa_device *ffa_dev); -const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev); #else static inline @@ -79,11 +78,6 @@ static inline void ffa_driver_unregister(struct ffa_driver *driver) {} static inline bool ffa_device_is_valid(struct ffa_device *ffa_dev) { return false; } -static inline -const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev) -{ - return NULL; -} #endif /* CONFIG_ARM_FFA_TRANSPORT */ #define ffa_register(driver) \ -- cgit v1.2.3 From cb1f4c2c15bb708b1ec8c70926c43ab6b6c93ecb Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:34 +0100 Subject: firmware: arm_ffa: Add support for querying FF-A features Add support for FFA_FEATURES to discover properties supported at the FF-A interface. This interface can be used to query: - If an FF-A interface is implemented by the component at the higher EL, - If an implemented FF-A interface also implements any optional features described in its interface definition, and - Any implementation details exported by an implemented FF-A interface as described in its interface definition. Link: https://lore.kernel.org/r/20220907145240.1683088-5-sudeep.holla@arm.com Reviewed-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 04e7cbb1b9aa..81b8d578b6ea 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -571,6 +571,32 @@ static int ffa_memory_reclaim(u64 g_handle, u32 flags) return 0; } +static int ffa_features(u32 func_feat_id, u32 input_props, + u32 *if_props_1, u32 *if_props_2) +{ + ffa_value_t id; + + if (!ARM_SMCCC_IS_FAST_CALL(func_feat_id) && input_props) { + pr_err("%s: Invalid Parameters: %x, %x", __func__, + func_feat_id, input_props); + return ffa_to_linux_errno(FFA_RET_INVALID_PARAMETERS); + } + + invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_FEATURES, .a1 = func_feat_id, .a2 = input_props, + }, &id); + + if (id.a0 == FFA_ERROR) + return ffa_to_linux_errno((int)id.a2); + + if (if_props_1) + *if_props_1 = id.a2; + if (if_props_2) + *if_props_2 = id.a3; + + return 0; +} + static u32 ffa_api_version_get(void) { return drv_info->version; -- cgit v1.2.3 From e57fba9105fac60d81a7ff2ce70d347d7ae95943 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:35 +0100 Subject: firmware: arm_ffa: Use FFA_FEATURES to detect if native versions are supported Currently, the ffa_dev->mode_32bit is use to detect if the native 64-bit or 32-bit versions of FF-A ABI needs to be used. However for the FF-A memory ABIs, it is not dependent on the ffa_device(i.e. the partition) itself, but the partition manager(SPM). So, the FFA_FEATURES can be use to detect if the native 64bit ABIs are supported or not and appropriate calls can be made based on that. Use FFA_FEATURES to detect if native versions of MEM_LEND or MEM_SHARE are implemented and make of the same to use native memory ABIs later on. Link: https://lore.kernel.org/r/20220907145240.1683088-6-sudeep.holla@arm.com Reviewed-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 81b8d578b6ea..37a8ee304508 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -163,6 +163,7 @@ struct ffa_drv_info { struct mutex tx_lock; /* lock to protect Tx buffer */ void *rx_buffer; void *tx_buffer; + bool mem_ops_native; }; static struct ffa_drv_info *drv_info; @@ -597,6 +598,13 @@ static int ffa_features(u32 func_feat_id, u32 input_props, return 0; } +static void ffa_set_up_mem_ops_native_flag(void) +{ + if (!ffa_features(FFA_FN_NATIVE(MEM_LEND), 0, NULL, NULL) || + !ffa_features(FFA_FN_NATIVE(MEM_SHARE), 0, NULL, NULL)) + drv_info->mem_ops_native = true; +} + static u32 ffa_api_version_get(void) { return drv_info->version; @@ -638,10 +646,10 @@ static int ffa_sync_send_receive(struct ffa_device *dev, static int ffa_memory_share(struct ffa_device *dev, struct ffa_mem_ops_args *args) { - if (dev->mode_32bit) - return ffa_memory_ops(FFA_MEM_SHARE, args); + if (drv_info->mem_ops_native) + return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args); - return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args); + return ffa_memory_ops(FFA_MEM_SHARE, args); } static int @@ -654,10 +662,10 @@ ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args) * however on systems without a hypervisor the responsibility * falls to the calling kernel driver to prevent access. */ - if (dev->mode_32bit) - return ffa_memory_ops(FFA_MEM_LEND, args); + if (drv_info->mem_ops_native) + return ffa_memory_ops(FFA_FN_NATIVE(MEM_LEND), args); - return ffa_memory_ops(FFA_FN_NATIVE(MEM_LEND), args); + return ffa_memory_ops(FFA_MEM_LEND, args); } static const struct ffa_dev_ops ffa_ops = { @@ -768,6 +776,8 @@ static int __init ffa_init(void) ffa_setup_partitions(); + ffa_set_up_mem_ops_native_flag(); + return 0; free_pages: if (drv_info->tx_buffer) -- cgit v1.2.3 From 8c3812c8f74f050278d734ec4b90149d84bdbefb Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:36 +0100 Subject: firmware: arm_ffa: Make memory apis ffa_device independent There is a requirement to make memory APIs independent of the ffa_device. One of the use-case is to have a common memory driver that manages the memory for all the ffa_devices. That common memory driver won't be a ffa_driver or won't have any ffa_device associated with it. So having these memory APIs accessible without a ffa_device is needed and should be possible as most of these are handled by the partition manager(SPM or hypervisor). Drop the ffa_device argument to the memory APIs and make them ffa_device independent. Link: https://lore.kernel.org/r/20220907145240.1683088-7-sudeep.holla@arm.com Acked-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 6 ++---- drivers/tee/optee/ffa_abi.c | 2 +- include/linux/arm_ffa.h | 6 ++---- 3 files changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 37a8ee304508..e4fd35773071 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -643,8 +643,7 @@ static int ffa_sync_send_receive(struct ffa_device *dev, dev->mode_32bit, data); } -static int -ffa_memory_share(struct ffa_device *dev, struct ffa_mem_ops_args *args) +static int ffa_memory_share(struct ffa_mem_ops_args *args) { if (drv_info->mem_ops_native) return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args); @@ -652,8 +651,7 @@ ffa_memory_share(struct ffa_device *dev, struct ffa_mem_ops_args *args) return ffa_memory_ops(FFA_MEM_SHARE, args); } -static int -ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args) +static int ffa_memory_lend(struct ffa_mem_ops_args *args) { /* Note that upon a successful MEM_LEND request the caller * must ensure that the memory region specified is not accessed diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index 3d4079575ccd..7257b42d0545 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -294,7 +294,7 @@ static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm, if (rc) return rc; args.sg = sgt.sgl; - rc = ffa_ops->memory_share(ffa_dev, &args); + rc = ffa_ops->memory_share(&args); sg_free_table(&sgt); if (rc) return rc; diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h index 556f50f27fb1..eafab07c9f58 100644 --- a/include/linux/arm_ffa.h +++ b/include/linux/arm_ffa.h @@ -262,10 +262,8 @@ struct ffa_dev_ops { int (*sync_send_receive)(struct ffa_device *dev, struct ffa_send_direct_data *data); int (*memory_reclaim)(u64 g_handle, u32 flags); - int (*memory_share)(struct ffa_device *dev, - struct ffa_mem_ops_args *args); - int (*memory_lend)(struct ffa_device *dev, - struct ffa_mem_ops_args *args); + int (*memory_share)(struct ffa_mem_ops_args *args); + int (*memory_lend)(struct ffa_mem_ops_args *args); }; #endif /* _LINUX_ARM_FFA_H */ -- cgit v1.2.3 From 7aa7a97989557011f762a4b7c2e4e3b061b638e4 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:37 +0100 Subject: firmware: arm_ffa: Rename ffa_dev_ops as ffa_ops Except the message APIs, all other APIs are ffa_device independent and can be used without any associated ffa_device from a non ffa_driver. In order to reflect the same, just rename ffa_dev_ops as ffa_ops to avoid any confusion or to keep it simple. Link: https://lore.kernel.org/r/20220907145240.1683088-8-sudeep.holla@arm.com Suggested-by: Sumit Garg Reviewed-by: Sumit Garg Reviewed-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/bus.c | 2 +- drivers/firmware/arm_ffa/driver.c | 2 +- drivers/tee/optee/ffa_abi.c | 14 +++++++------- include/linux/arm_ffa.h | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index 69328041fbc3..99d439480612 100644 --- a/drivers/firmware/arm_ffa/bus.c +++ b/drivers/firmware/arm_ffa/bus.c @@ -168,7 +168,7 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev) } struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, - const struct ffa_dev_ops *ops) + const struct ffa_ops *ops) { int ret; struct device *dev; diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index e4fd35773071..2532e0f16cc9 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -666,7 +666,7 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args) return ffa_memory_ops(FFA_MEM_LEND, args); } -static const struct ffa_dev_ops ffa_ops = { +static const struct ffa_ops ffa_ops = { .api_version_get = ffa_api_version_get, .partition_info_get = ffa_partition_info_get, .mode_32bit_set = ffa_mode_32bit_set, diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index 7257b42d0545..2ce5b87dfb27 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -272,7 +272,7 @@ static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm, { struct optee *optee = tee_get_drvdata(ctx->teedev); struct ffa_device *ffa_dev = optee->ffa.ffa_dev; - const struct ffa_dev_ops *ffa_ops = ffa_dev->ops; + const struct ffa_ops *ffa_ops = ffa_dev->ops; struct ffa_mem_region_attributes mem_attr = { .receiver = ffa_dev->vm_id, .attrs = FFA_MEM_RW, @@ -315,7 +315,7 @@ static int optee_ffa_shm_unregister(struct tee_context *ctx, { struct optee *optee = tee_get_drvdata(ctx->teedev); struct ffa_device *ffa_dev = optee->ffa.ffa_dev; - const struct ffa_dev_ops *ffa_ops = ffa_dev->ops; + const struct ffa_ops *ffa_ops = ffa_dev->ops; u64 global_handle = shm->sec_world_id; struct ffa_send_direct_data data = { .data0 = OPTEE_FFA_UNREGISTER_SHM, @@ -342,7 +342,7 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm) { struct optee *optee = tee_get_drvdata(ctx->teedev); - const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_dev->ops; + const struct ffa_ops *ffa_ops = optee->ffa.ffa_dev->ops; u64 global_handle = shm->sec_world_id; int rc; @@ -530,7 +530,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx, { struct optee *optee = tee_get_drvdata(ctx->teedev); struct ffa_device *ffa_dev = optee->ffa.ffa_dev; - const struct ffa_dev_ops *ffa_ops = ffa_dev->ops; + const struct ffa_ops *ffa_ops = ffa_dev->ops; struct optee_call_waiter w; u32 cmd = data->data0; u32 w4 = data->data1; @@ -652,7 +652,7 @@ static int optee_ffa_do_call_with_arg(struct tee_context *ctx, */ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev, - const struct ffa_dev_ops *ops) + const struct ffa_ops *ops) { struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION }; int rc; @@ -687,7 +687,7 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev, } static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev, - const struct ffa_dev_ops *ops, + const struct ffa_ops *ops, u32 *sec_caps, unsigned int *rpc_param_count) { @@ -783,7 +783,7 @@ static void optee_ffa_remove(struct ffa_device *ffa_dev) static int optee_ffa_probe(struct ffa_device *ffa_dev) { - const struct ffa_dev_ops *ffa_ops; + const struct ffa_ops *ffa_ops; unsigned int rpc_param_count; struct tee_shm_pool *pool; struct tee_device *teedev; diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h index eafab07c9f58..4c4b06783035 100644 --- a/include/linux/arm_ffa.h +++ b/include/linux/arm_ffa.h @@ -17,7 +17,7 @@ struct ffa_device { bool mode_32bit; uuid_t uuid; struct device dev; - const struct ffa_dev_ops *ops; + const struct ffa_ops *ops; }; #define to_ffa_dev(d) container_of(d, struct ffa_device, dev) @@ -49,7 +49,7 @@ static inline void *ffa_dev_get_drvdata(struct ffa_device *fdev) #if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT) struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, - const struct ffa_dev_ops *ops); + const struct ffa_ops *ops); void ffa_device_unregister(struct ffa_device *ffa_dev); int ffa_driver_register(struct ffa_driver *driver, struct module *owner, const char *mod_name); @@ -59,7 +59,7 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev); #else static inline struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, - const struct ffa_dev_ops *ops) + const struct ffa_ops *ops) { return NULL; } @@ -254,7 +254,7 @@ struct ffa_mem_ops_args { struct ffa_mem_region_attributes *attrs; }; -struct ffa_dev_ops { +struct ffa_ops { u32 (*api_version_get)(void); int (*partition_info_get)(const char *uuid_str, struct ffa_partition_info *buffer); -- cgit v1.2.3 From bb1be749850055d88d839eff0962e5915788f228 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:38 +0100 Subject: firmware: arm_ffa: Add v1.1 get_partition_info support FF-A v1.1 adds support to discovery the UUIDs of the partitions that was missing in v1.0 and which the driver workarounds by using UUIDs supplied by the ffa_drivers. Add the v1.1 get_partition_info support and disable the workaround if the detected FF-A version is greater than v1.0. Link: https://lore.kernel.org/r/20220907145240.1683088-9-sudeep.holla@arm.com Reviewed-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 43 +++++++++++++++++++++++++++++++-------- include/linux/arm_ffa.h | 1 + 2 files changed, 36 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 2532e0f16cc9..42bc22220c69 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -264,18 +264,24 @@ static int ffa_rxtx_unmap(u16 vm_id) return 0; } +#define PARTITION_INFO_GET_RETURN_COUNT_ONLY BIT(0) + /* buffer must be sizeof(struct ffa_partition_info) * num_partitions */ static int __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3, struct ffa_partition_info *buffer, int num_partitions) { - int count; + int idx, count, flags = 0, sz, buf_sz; ffa_value_t partition_info; + if (!buffer || !num_partitions) /* Just get the count for now */ + flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY; + mutex_lock(&drv_info->rx_lock); invoke_ffa_fn((ffa_value_t){ .a0 = FFA_PARTITION_INFO_GET, .a1 = uuid0, .a2 = uuid1, .a3 = uuid2, .a4 = uuid3, + .a5 = flags, }, &partition_info); if (partition_info.a0 == FFA_ERROR) { @@ -285,8 +291,19 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3, count = partition_info.a2; + if (drv_info->version > FFA_VERSION_1_0) { + buf_sz = sz = partition_info.a3; + if (sz > sizeof(*buffer)) + buf_sz = sizeof(*buffer); + } else { + /* FFA_VERSION_1_0 lacks size in the response */ + buf_sz = sz = 8; + } + if (buffer && count <= num_partitions) - memcpy(buffer, drv_info->rx_buffer, sizeof(*buffer) * count); + for (idx = 0; idx < count; idx++) + memcpy(buffer + idx, drv_info->rx_buffer + idx * sz, + buf_sz); ffa_rx_release(); @@ -681,6 +698,14 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid) int count, idx; struct ffa_partition_info *pbuf, *tpbuf; + /* + * FF-A v1.1 provides UUID for each partition as part of the discovery + * API, the discovered UUID must be populated in the device's UUID and + * there is no need to copy the same from the driver table. + */ + if (drv_info->version > FFA_VERSION_1_0) + return; + count = ffa_partition_probe(uuid, &pbuf); if (count <= 0) return; @@ -694,6 +719,7 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid) static void ffa_setup_partitions(void) { int count, idx; + uuid_t uuid; struct ffa_device *ffa_dev; struct ffa_partition_info *pbuf, *tpbuf; @@ -704,14 +730,15 @@ static void ffa_setup_partitions(void) } for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) { - /* Note that the &uuid_null parameter will require + import_uuid(&uuid, (u8 *)tpbuf->uuid); + + /* Note that if the UUID will be uuid_null, that will require * ffa_device_match() to find the UUID of this partition id - * with help of ffa_device_match_uuid(). Once the FF-A spec - * is updated to provide correct UUID here for each partition - * as part of the discovery API, we need to pass the - * discovered UUID here instead. + * with help of ffa_device_match_uuid(). FF-A v1.1 and above + * provides UUID here for each partition as part of the + * discovery API and the same is passed. */ - ffa_dev = ffa_device_register(&uuid_null, tpbuf->id, &ffa_ops); + ffa_dev = ffa_device_register(&uuid, tpbuf->id, &ffa_ops); if (!ffa_dev) { pr_err("%s: failed to register partition ID 0x%x\n", __func__, tpbuf->id); diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h index 4c4b06783035..09567ffd1f49 100644 --- a/include/linux/arm_ffa.h +++ b/include/linux/arm_ffa.h @@ -107,6 +107,7 @@ struct ffa_partition_info { /* partition can send and receive indirect messages. */ #define FFA_PARTITION_INDIRECT_MSG BIT(2) u32 properties; + u32 uuid[4]; }; /* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */ -- cgit v1.2.3 From 106b11b1ccd5a43432d9517f4a26629a1658cfe6 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:39 +0100 Subject: firmware: arm_ffa: Set up 32bit execution mode flag using partiion property FF-A v1.1 adds a flag in the partition properties to indicate if the partition runs in the AArch32 or AArch64 execution state. Use the same to set-up the 32-bit execution flag mode in the ffa_dev automatically if the detected firmware version is above v1.0 and ignore any requests to do the same from the ffa_driver. Link: https://lore.kernel.org/r/20220907145240.1683088-10-sudeep.holla@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 14 +++++++++++++- include/linux/arm_ffa.h | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 42bc22220c69..a530139083c4 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -648,11 +648,19 @@ static int ffa_partition_info_get(const char *uuid_str, return 0; } -static void ffa_mode_32bit_set(struct ffa_device *dev) +static void _ffa_mode_32bit_set(struct ffa_device *dev) { dev->mode_32bit = true; } +static void ffa_mode_32bit_set(struct ffa_device *dev) +{ + if (drv_info->version > FFA_VERSION_1_0) + return; + + _ffa_mode_32bit_set(dev); +} + static int ffa_sync_send_receive(struct ffa_device *dev, struct ffa_send_direct_data *data) { @@ -744,6 +752,10 @@ static void ffa_setup_partitions(void) __func__, tpbuf->id); continue; } + + if (drv_info->version > FFA_VERSION_1_0 && + !(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC)) + _ffa_mode_32bit_set(ffa_dev); } kfree(pbuf); } diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h index 09567ffd1f49..5964b6104996 100644 --- a/include/linux/arm_ffa.h +++ b/include/linux/arm_ffa.h @@ -106,6 +106,8 @@ struct ffa_partition_info { #define FFA_PARTITION_DIRECT_SEND BIT(1) /* partition can send and receive indirect messages. */ #define FFA_PARTITION_INDIRECT_MSG BIT(2) +/* partition runs in the AArch64 execution state. */ +#define FFA_PARTITION_AARCH64_EXEC BIT(8) u32 properties; u32 uuid[4]; }; -- cgit v1.2.3 From 5b0c6328e47dccf552996ca711005ca3f44034e9 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 7 Sep 2022 15:52:40 +0100 Subject: firmware: arm_ffa: Split up ffa_ops into info, message and memory operations In preparation to make memory operations accessible for a non ffa_driver/device, it is better to split the ffa_ops into different categories of operations: info, message and memory. The info and memory are ffa_device independent and can be used without any associated ffa_device from a non ffa_driver. However, we don't export these info and memory APIs yet without the user. The first users of these APIs can export them. Link: https://lore.kernel.org/r/20220907145240.1683088-11-sudeep.holla@arm.com Reviewed-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 16 ++++++++++++++-- drivers/tee/optee/ffa_abi.c | 33 ++++++++++++++++++--------------- include/linux/arm_ffa.h | 14 +++++++++++++- 3 files changed, 45 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index a530139083c4..d5e86ef40b89 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -691,16 +691,28 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args) return ffa_memory_ops(FFA_MEM_LEND, args); } -static const struct ffa_ops ffa_ops = { +static const struct ffa_info_ops ffa_drv_info_ops = { .api_version_get = ffa_api_version_get, .partition_info_get = ffa_partition_info_get, +}; + +static const struct ffa_msg_ops ffa_drv_msg_ops = { .mode_32bit_set = ffa_mode_32bit_set, .sync_send_receive = ffa_sync_send_receive, +}; + +static const struct ffa_mem_ops ffa_drv_mem_ops = { .memory_reclaim = ffa_memory_reclaim, .memory_share = ffa_memory_share, .memory_lend = ffa_memory_lend, }; +static const struct ffa_ops ffa_drv_ops = { + .info_ops = &ffa_drv_info_ops, + .msg_ops = &ffa_drv_msg_ops, + .mem_ops = &ffa_drv_mem_ops, +}; + void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid) { int count, idx; @@ -746,7 +758,7 @@ static void ffa_setup_partitions(void) * provides UUID here for each partition as part of the * discovery API and the same is passed. */ - ffa_dev = ffa_device_register(&uuid, tpbuf->id, &ffa_ops); + ffa_dev = ffa_device_register(&uuid, tpbuf->id, &ffa_drv_ops); if (!ffa_dev) { pr_err("%s: failed to register partition ID 0x%x\n", __func__, tpbuf->id); diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index 2ce5b87dfb27..0828240f27e6 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -272,7 +272,7 @@ static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm, { struct optee *optee = tee_get_drvdata(ctx->teedev); struct ffa_device *ffa_dev = optee->ffa.ffa_dev; - const struct ffa_ops *ffa_ops = ffa_dev->ops; + const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops; struct ffa_mem_region_attributes mem_attr = { .receiver = ffa_dev->vm_id, .attrs = FFA_MEM_RW, @@ -294,14 +294,14 @@ static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm, if (rc) return rc; args.sg = sgt.sgl; - rc = ffa_ops->memory_share(&args); + rc = mem_ops->memory_share(&args); sg_free_table(&sgt); if (rc) return rc; rc = optee_shm_add_ffa_handle(optee, shm, args.g_handle); if (rc) { - ffa_ops->memory_reclaim(args.g_handle, 0); + mem_ops->memory_reclaim(args.g_handle, 0); return rc; } @@ -315,7 +315,8 @@ static int optee_ffa_shm_unregister(struct tee_context *ctx, { struct optee *optee = tee_get_drvdata(ctx->teedev); struct ffa_device *ffa_dev = optee->ffa.ffa_dev; - const struct ffa_ops *ffa_ops = ffa_dev->ops; + const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops; + const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops; u64 global_handle = shm->sec_world_id; struct ffa_send_direct_data data = { .data0 = OPTEE_FFA_UNREGISTER_SHM, @@ -327,11 +328,11 @@ static int optee_ffa_shm_unregister(struct tee_context *ctx, optee_shm_rem_ffa_handle(optee, global_handle); shm->sec_world_id = 0; - rc = ffa_ops->sync_send_receive(ffa_dev, &data); + rc = msg_ops->sync_send_receive(ffa_dev, &data); if (rc) pr_err("Unregister SHM id 0x%llx rc %d\n", global_handle, rc); - rc = ffa_ops->memory_reclaim(global_handle, 0); + rc = mem_ops->memory_reclaim(global_handle, 0); if (rc) pr_err("mem_reclaim: 0x%llx %d", global_handle, rc); @@ -342,7 +343,7 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm) { struct optee *optee = tee_get_drvdata(ctx->teedev); - const struct ffa_ops *ffa_ops = optee->ffa.ffa_dev->ops; + const struct ffa_mem_ops *mem_ops; u64 global_handle = shm->sec_world_id; int rc; @@ -353,7 +354,8 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx, */ optee_shm_rem_ffa_handle(optee, global_handle); - rc = ffa_ops->memory_reclaim(global_handle, 0); + mem_ops = optee->ffa.ffa_dev->ops->mem_ops; + rc = mem_ops->memory_reclaim(global_handle, 0); if (rc) pr_err("mem_reclaim: 0x%llx %d", global_handle, rc); @@ -530,7 +532,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx, { struct optee *optee = tee_get_drvdata(ctx->teedev); struct ffa_device *ffa_dev = optee->ffa.ffa_dev; - const struct ffa_ops *ffa_ops = ffa_dev->ops; + const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops; struct optee_call_waiter w; u32 cmd = data->data0; u32 w4 = data->data1; @@ -541,7 +543,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx, /* Initialize waiter */ optee_cq_wait_init(&optee->call_queue, &w); while (true) { - rc = ffa_ops->sync_send_receive(ffa_dev, data); + rc = msg_ops->sync_send_receive(ffa_dev, data); if (rc) goto done; @@ -576,7 +578,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx, * OP-TEE has returned with a RPC request. * * Note that data->data4 (passed in register w7) is already - * filled in by ffa_ops->sync_send_receive() returning + * filled in by ffa_mem_ops->sync_send_receive() returning * above. */ cond_resched(); @@ -654,12 +656,13 @@ static int optee_ffa_do_call_with_arg(struct tee_context *ctx, static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev, const struct ffa_ops *ops) { + const struct ffa_msg_ops *msg_ops = ops->msg_ops; struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION }; int rc; - ops->mode_32bit_set(ffa_dev); + msg_ops->mode_32bit_set(ffa_dev); - rc = ops->sync_send_receive(ffa_dev, &data); + rc = msg_ops->sync_send_receive(ffa_dev, &data); if (rc) { pr_err("Unexpected error %d\n", rc); return false; @@ -672,7 +675,7 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev, } data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION }; - rc = ops->sync_send_receive(ffa_dev, &data); + rc = msg_ops->sync_send_receive(ffa_dev, &data); if (rc) { pr_err("Unexpected error %d\n", rc); return false; @@ -694,7 +697,7 @@ static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev, struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES }; int rc; - rc = ops->sync_send_receive(ffa_dev, &data); + rc = ops->msg_ops->sync_send_receive(ffa_dev, &data); if (rc) { pr_err("Unexpected error %d", rc); return false; diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h index 5964b6104996..5f02d2e6b9d9 100644 --- a/include/linux/arm_ffa.h +++ b/include/linux/arm_ffa.h @@ -257,16 +257,28 @@ struct ffa_mem_ops_args { struct ffa_mem_region_attributes *attrs; }; -struct ffa_ops { +struct ffa_info_ops { u32 (*api_version_get)(void); int (*partition_info_get)(const char *uuid_str, struct ffa_partition_info *buffer); +}; + +struct ffa_msg_ops { void (*mode_32bit_set)(struct ffa_device *dev); int (*sync_send_receive)(struct ffa_device *dev, struct ffa_send_direct_data *data); +}; + +struct ffa_mem_ops { int (*memory_reclaim)(u64 g_handle, u32 flags); int (*memory_share)(struct ffa_mem_ops_args *args); int (*memory_lend)(struct ffa_mem_ops_args *args); }; +struct ffa_ops { + const struct ffa_info_ops *info_ops; + const struct ffa_msg_ops *msg_ops; + const struct ffa_mem_ops *mem_ops; +}; + #endif /* _LINUX_ARM_FFA_H */ -- cgit v1.2.3 From 47bceb7cda6a78b3735694790e70f5cdc254058e Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Tue, 6 Sep 2022 16:38:24 +0200 Subject: soc: rockchip: power-domain: do not enable domain when adding it It's not need to power on all pd when add pm domain. Instead use PD's real status in pm_genpd_init(). Signed-off-by: Elaine Zhang Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20220906143825.199089-6-sebastian.reichel@collabora.com Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 3aaadab2716e..4e24f40bf467 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -599,14 +599,6 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, } } - error = rockchip_pd_power(pd, true); - if (error) { - dev_err(pmu->dev, - "failed to power on domain '%pOFn': %d\n", - node, error); - goto err_unprepare_clocks; - } - if (pd->info->name) pd->genpd.name = pd->info->name; else @@ -618,7 +610,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, pd->genpd.flags = GENPD_FLAG_PM_CLK; if (pd_info->active_wakeup) pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; - pm_genpd_init(&pd->genpd, NULL, false); + pm_genpd_init(&pd->genpd, NULL, !rockchip_pmu_domain_is_on(pd)); pmu->genpd_data.domains[id] = &pd->genpd; return 0; -- cgit v1.2.3 From 6541b424ce1dda616d3946e839f015c984df7a99 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 6 Sep 2022 16:38:25 +0200 Subject: soc: rockchip: power-domain: add power domain support for rk3588 This driver is modified to support RK3588 SoCs. Signed-off-by: Finley Xiao [port of downstream code incl. merging in fixes] Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20220906143825.199089-7-sebastian.reichel@collabora.com Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 91 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 4e24f40bf467..84bc022f9e5b 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -31,6 +31,7 @@ #include #include #include +#include struct rockchip_domain_info { const char *name; @@ -42,6 +43,9 @@ struct rockchip_domain_info { bool active_wakeup; int pwr_w_mask; int req_w_mask; + int repair_status_mask; + u32 pwr_offset; + u32 req_offset; }; struct rockchip_pmu_info { @@ -50,6 +54,7 @@ struct rockchip_pmu_info { u32 req_offset; u32 idle_offset; u32 ack_offset; + u32 repair_status_offset; u32 core_pwrcnt_offset; u32 gpu_pwrcnt_offset; @@ -114,6 +119,22 @@ struct rockchip_pmu { .active_wakeup = wakeup, \ } +#define DOMAIN_M_O_R(_name, p_offset, pwr, status, r_status, r_offset, req, idle, ack, wakeup) \ +{ \ + .name = _name, \ + .pwr_offset = p_offset, \ + .pwr_w_mask = (pwr) << 16, \ + .pwr_mask = (pwr), \ + .status_mask = (status), \ + .repair_status_mask = (r_status), \ + .req_offset = r_offset, \ + .req_w_mask = (req) << 16, \ + .req_mask = (req), \ + .idle_mask = (idle), \ + .ack_mask = (ack), \ + .active_wakeup = wakeup, \ +} + #define DOMAIN_RK3036(_name, req, ack, idle, wakeup) \ { \ .name = _name, \ @@ -248,6 +269,9 @@ void rockchip_pmu_unblock(void) } EXPORT_SYMBOL_GPL(rockchip_pmu_unblock); +#define DOMAIN_RK3588(name, p_offset, pwr, status, r_status, r_offset, req, idle, wakeup) \ + DOMAIN_M_O_R(name, p_offset, pwr, status, r_status, r_offset, req, idle, idle, wakeup) + static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) { struct rockchip_pmu *pmu = pd->pmu; @@ -272,6 +296,7 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, const struct rockchip_domain_info *pd_info = pd->info; struct generic_pm_domain *genpd = &pd->genpd; struct rockchip_pmu *pmu = pd->pmu; + u32 pd_req_offset = pd_info->req_offset; unsigned int target_ack; unsigned int val; bool is_idle; @@ -280,11 +305,11 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, if (pd_info->req_mask == 0) return 0; else if (pd_info->req_w_mask) - regmap_write(pmu->regmap, pmu->info->req_offset, + regmap_write(pmu->regmap, pmu->info->req_offset + pd_req_offset, idle ? (pd_info->req_mask | pd_info->req_w_mask) : pd_info->req_w_mask); else - regmap_update_bits(pmu->regmap, pmu->info->req_offset, + regmap_update_bits(pmu->regmap, pmu->info->req_offset + pd_req_offset, pd_info->req_mask, idle ? -1U : 0); wmb(); @@ -367,6 +392,12 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd) struct rockchip_pmu *pmu = pd->pmu; unsigned int val; + if (pd->info->repair_status_mask) { + regmap_read(pmu->regmap, pmu->info->repair_status_offset, &val); + /* 1'b1: power on, 1'b0: power off */ + return val & pd->info->repair_status_mask; + } + /* check idle status for idle-only domains */ if (pd->info->status_mask == 0) return !rockchip_pmu_domain_is_idle(pd); @@ -382,16 +413,17 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, { struct rockchip_pmu *pmu = pd->pmu; struct generic_pm_domain *genpd = &pd->genpd; + u32 pd_pwr_offset = pd->info->pwr_offset; bool is_on; if (pd->info->pwr_mask == 0) return; else if (pd->info->pwr_w_mask) - regmap_write(pmu->regmap, pmu->info->pwr_offset, + regmap_write(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset, on ? pd->info->pwr_w_mask : (pd->info->pwr_mask | pd->info->pwr_w_mask)); else - regmap_update_bits(pmu->regmap, pmu->info->pwr_offset, + regmap_update_bits(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset, pd->info->pwr_mask, on ? 0 : -1U); wmb(); @@ -518,6 +550,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, node, id); return -EINVAL; } + /* RK3588 has domains with two parents (RKVDEC0/RKVDEC1) */ + if (pmu->genpd_data.domains[id]) + return 0; pd_info = &pmu->info->domain_info[id]; if (!pd_info) { @@ -988,6 +1023,38 @@ static const struct rockchip_domain_info rk3568_pm_domains[] = { [RK3568_PD_PIPE] = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false), }; +static const struct rockchip_domain_info rk3588_pm_domains[] = { + [RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, BIT(1), 0x0, BIT(0), BIT(0), false), + [RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0, 0x0, 0, 0, false), + [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0, 0x0, 0, 0, false), + [RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, BIT(2), 0x0, BIT(1), BIT(1), false), + [RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, BIT(3), 0x0, BIT(2), BIT(2), false), + [RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, BIT(4), 0x0, BIT(3), BIT(3), false), + [RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, BIT(5), 0x0, BIT(4), BIT(4), false), + [RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, BIT(6), 0x0, BIT(5), BIT(5), false), + [RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, BIT(7), 0x0, BIT(6), BIT(6), false), + [RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, BIT(8), 0x0, BIT(7), BIT(7), false), + [RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, BIT(9), 0x0, BIT(8), BIT(8), false), + [RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, BIT(10), 0x0, 0, 0, false), + [RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, BIT(11), 0x0, BIT(9), BIT(9), false), + [RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, BIT(12), 0x0, BIT(10), BIT(10), false), + [RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, BIT(13), 0x0, 0, 0, false), + [RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, BIT(14), 0x0, BIT(11), BIT(11), false), + [RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, BIT(15), 0x0, BIT(12), BIT(12), false), + [RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false), + [RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, BIT(17), 0x0, BIT(15), BIT(15), false), + [RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, BIT(18), 0x4, BIT(0), BIT(16), false), + [RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, BIT(19), 0x4, BIT(1), BIT(17), false), + [RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, BIT(20), 0x4, BIT(5), BIT(21), false), + [RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, BIT(21), 0x0, 0, 0, false), + [RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, BIT(22), 0x0, 0, 0, true), + [RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0, 0x4, BIT(2), BIT(18), false), + [RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, BIT(23), 0x0, 0, 0, false), + [RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, BIT(24), 0x4, BIT(3), BIT(19), false), + [RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, BIT(25), 0x4, BIT(4), BIT(20), true), + [RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, BIT(26), 0x0, 0, 0, false), +}; + static const struct rockchip_pmu_info px30_pmu = { .pwr_offset = 0x18, .status_offset = 0x20, @@ -1134,6 +1201,18 @@ static const struct rockchip_pmu_info rk3568_pmu = { .domain_info = rk3568_pm_domains, }; +static const struct rockchip_pmu_info rk3588_pmu = { + .pwr_offset = 0x14c, + .status_offset = 0x180, + .req_offset = 0x10c, + .idle_offset = 0x120, + .ack_offset = 0x118, + .repair_status_offset = 0x290, + + .num_domains = ARRAY_SIZE(rk3588_pm_domains), + .domain_info = rk3588_pm_domains, +}; + static const struct rockchip_pmu_info rv1126_pmu = { .pwr_offset = 0x110, .status_offset = 0x108, @@ -1194,6 +1273,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = { .compatible = "rockchip,rk3568-power-controller", .data = (void *)&rk3568_pmu, }, + { + .compatible = "rockchip,rk3588-power-controller", + .data = (void *)&rk3588_pmu, + }, { .compatible = "rockchip,rv1126-power-controller", .data = (void *)&rv1126_pmu, -- cgit v1.2.3 From e66fee7519ad5eb82de2fe03682e056757216a0c Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Sun, 11 Sep 2022 17:29:12 +0800 Subject: firmware: qcom: scm: remove unused __qcom_scm_init declaration __qcom_scm_init has been removed since commit 9a434cee773a ("firmware: qcom_scm: Dynamically support SMCCC and legacy conventions"), so remove it. Signed-off-by: Gaosheng Cui Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220911092912.3219132-1-cuigaosheng1@huawei.com --- drivers/firmware/qcom_scm.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 0d51eef2472f..db3d08a01209 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -129,8 +129,6 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, #define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03 #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02 -extern void __qcom_scm_init(void); - /* common error codes */ #define QCOM_SCM_V2_EBUSY -12 #define QCOM_SCM_ENOMEM -5 -- cgit v1.2.3 From df646a17f103c6f18ab85c5e3773763d18dc528b Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 16 Jul 2022 21:32:01 +0200 Subject: soc: qcom: rpmpd: Add SM6375 support Add support for RPMPDs on SM6375. Signed-off-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220716193201.455728-2-konrad.dybcio@somainline.org --- drivers/soc/qcom/rpmpd.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 5803038c744e..337b1ad1cd3b 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -29,6 +29,7 @@ #define RPMPD_RWLM 0x6d6c7772 #define RPMPD_RWSC 0x63737772 #define RPMPD_RWSM 0x6d737772 +#define RPMPD_RWGX 0x78677772 /* Operation Keys */ #define KEY_CORNER 0x6e726f63 /* corn */ @@ -433,6 +434,26 @@ static const struct rpmpd_desc sm6125_desc = { .max_state = RPM_SMD_LEVEL_BINNING, }; +DEFINE_RPMPD_PAIR(sm6375, vddgx, vddgx_ao, RWGX, LEVEL, 0); +static struct rpmpd *sm6375_rpmpds[] = { + [SM6375_VDDCX] = &sm6125_vddcx, + [SM6375_VDDCX_AO] = &sm6125_vddcx_ao, + [SM6375_VDDCX_VFL] = &sm6125_vddcx_vfl, + [SM6375_VDDMX] = &sm6125_vddmx, + [SM6375_VDDMX_AO] = &sm6125_vddmx_ao, + [SM6375_VDDMX_VFL] = &sm6125_vddmx_vfl, + [SM6375_VDDGX] = &sm6375_vddgx, + [SM6375_VDDGX_AO] = &sm6375_vddgx_ao, + [SM6375_VDD_LPI_CX] = &sm6115_vdd_lpi_cx, + [SM6375_VDD_LPI_MX] = &sm6115_vdd_lpi_mx, +}; + +static const struct rpmpd_desc sm6375_desc = { + .rpmpds = sm6375_rpmpds, + .num_pds = ARRAY_SIZE(sm6375_rpmpds), + .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, +}; + static struct rpmpd *qcm2290_rpmpds[] = { [QCM2290_VDDCX] = &sm6115_vddcx, [QCM2290_VDDCX_AO] = &sm6115_vddcx_ao, @@ -466,6 +487,7 @@ static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc }, { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc }, { .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc }, + { .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc }, { } }; MODULE_DEVICE_TABLE(of, rpmpd_match_table); -- cgit v1.2.3 From 96765cc47546fe6724825600afa8ba170671da61 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 12 May 2022 01:46:43 +0530 Subject: soc/tegra: Set ERD bit to mask inband errors Add a function to set the ERD (Error Response Disable) bit in the MISCREG_CCROC_ERR_CONFIG register from the Control Backbone (CBB) error handler driver. ERD bit allows masking of SError due to inband errors which are caused by illegal register accesses through CBB. When the bit is set, interrupt is used for reporting errors and magic code '0xdead2003' is returned. This change is only required for Tegra194 SoC as the config is moved to CBB register space for future SoC's. Also, remove unmapping the apbmisc_base as it's required to get the base address for accessing the misc register. Signed-off-by: Sumit Gupta Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/tegra-apbmisc.c | 29 +++++++++++++++++++++++++++-- include/soc/tegra/fuse.h | 6 ++++++ 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 590c862538d0..de833f8d2408 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -16,12 +16,16 @@ #define FUSE_SKU_INFO 0x10 +#define ERD_ERR_CONFIG 0x120c +#define ERD_MASK_INBAND_ERR 0x1 + #define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \ (0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \ (0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) +static void __iomem *apbmisc_base; static bool long_ram_code; static u32 strapping; static u32 chipid; @@ -93,6 +97,28 @@ u32 tegra_read_ram_code(void) } EXPORT_SYMBOL_GPL(tegra_read_ram_code); +/* + * The function sets ERD(Error Response Disable) bit. + * This allows to mask inband errors and always send an + * OKAY response from CBB to the master which caused error. + */ +int tegra194_miscreg_mask_serror(void) +{ + if (!apbmisc_base) + return -EPROBE_DEFER; + + if (!of_machine_is_compatible("nvidia,tegra194")) { + WARN(1, "Only supported for Tegra194 devices!\n"); + return -EOPNOTSUPP; + } + + writel_relaxed(ERD_MASK_INBAND_ERR, + apbmisc_base + ERD_ERR_CONFIG); + + return 0; +} +EXPORT_SYMBOL(tegra194_miscreg_mask_serror); + static const struct of_device_id apbmisc_match[] __initconst = { { .compatible = "nvidia,tegra20-apbmisc", }, { .compatible = "nvidia,tegra186-misc", }, @@ -134,7 +160,7 @@ void __init tegra_init_revision(void) void __init tegra_init_apbmisc(void) { - void __iomem *apbmisc_base, *strapping_base; + void __iomem *strapping_base; struct resource apbmisc, straps; struct device_node *np; @@ -196,7 +222,6 @@ void __init tegra_init_apbmisc(void) pr_err("failed to map APBMISC registers\n"); } else { chipid = readl_relaxed(apbmisc_base + 4); - iounmap(apbmisc_base); } strapping_base = ioremap(straps.start, resource_size(&straps)); diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index 67d2bc856fbc..977c334136e9 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -58,6 +58,7 @@ u32 tegra_read_chipid(void); u8 tegra_get_chip_id(void); u8 tegra_get_platform(void); bool tegra_is_silicon(void); +int tegra194_miscreg_mask_serror(void); #else static struct tegra_sku_info tegra_sku_info __maybe_unused; @@ -95,6 +96,11 @@ static inline bool tegra_is_silicon(void) { return false; } + +static inline int tegra194_miscreg_mask_serror(void) +{ + return false; +} #endif struct device *tegra_soc_device_register(void); -- cgit v1.2.3 From e941712cccab8a96f03b5d3274159c1ed338efee Mon Sep 17 00:00:00 2001 From: Liang He Date: Thu, 16 Jun 2022 09:46:36 +0800 Subject: soc/tegra: fuse: Add missing of_node_put() in tegra_init_fuse() In this function, of_find_matching_node() will return a node pointer with refcount incremented. We should use of_node_put() when the "np" pointer is not used anymore. Signed-off-by: Liang He Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index b0a8405dbdb1..6542267a224d 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -568,6 +568,7 @@ static int __init tegra_init_fuse(void) np = of_find_matching_node(NULL, car_match); if (np) { void __iomem *base = of_iomap(np, 0); + of_node_put(np); if (base) { tegra_enable_fuse_clk(base); iounmap(base); -- cgit v1.2.3 From 0a3c2dbec425b82d9af7aeb5dc9b18da398992a7 Mon Sep 17 00:00:00 2001 From: Liang He Date: Wed, 15 Jun 2022 20:32:32 +0800 Subject: soc/tegra: fuse: Add missing of_node_put() In tegra_init_apbmisc(), of_find_matching_node() will return a node pointer with refcount incremented. We should use of_node_put() in each failure path or when it is not used anymore. Signed-off-by: Liang He Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/tegra-apbmisc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 590c862538d0..eea5de3e5fa5 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -182,12 +182,12 @@ void __init tegra_init_apbmisc(void) */ if (of_address_to_resource(np, 0, &apbmisc) < 0) { pr_err("failed to get APBMISC registers\n"); - return; + goto put; } if (of_address_to_resource(np, 1, &straps) < 0) { pr_err("failed to get strapping options registers\n"); - return; + goto put; } } @@ -208,4 +208,7 @@ void __init tegra_init_apbmisc(void) } long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code"); + +put: + of_node_put(np); } -- cgit v1.2.3 From 1623566fc43ecfcbcb5f39aee294262b9b187c9a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 11 Jul 2022 17:40:29 +0200 Subject: soc/tegra: pmc: Remove leading space Remove a leading space from a line that is otherwise indented by tabs. Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 6a4b8f7e7948..0e87fdb90a4a 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -2274,7 +2274,7 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq, /* GPIO hierarchies stop at the PMC level */ if (!err && domain->parent) - err = irq_domain_disconnect_hierarchy(domain->parent, + err = irq_domain_disconnect_hierarchy(domain->parent, virq); break; } -- cgit v1.2.3 From 72ccc1f564918c1087a8e37e82422f79d3255a7b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 11 Jul 2022 17:40:30 +0200 Subject: soc/tegra: pmc: Add support for simple wake events Simple wake events are neither mapped to GIC interrupts nor have an associated GPIO line. They are close to GPIO-backed wake events in that the IRQ hierarchy processing needs to stop at the PMC level, but since there is no dedicated GPIO line for them, let's turn them into a separate type. Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 0e87fdb90a4a..48286bc59f46 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -296,6 +296,17 @@ struct tegra_wake_event { } gpio; }; +#define TEGRA_WAKE_SIMPLE(_name, _id) \ + { \ + .name = _name, \ + .id = _id, \ + .irq = 0, \ + .gpio = { \ + .instance = UINT_MAX, \ + .pin = UINT_MAX, \ + }, \ + } + #define TEGRA_WAKE_IRQ(_name, _id, _irq) \ { \ .name = _name, \ @@ -2239,6 +2250,7 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq, for (i = 0; i < soc->num_wake_events; i++) { const struct tegra_wake_event *event = &soc->wake_events[i]; + /* IRQ and simple wake events */ if (fwspec->param_count == 2) { struct irq_fwspec spec; @@ -2251,6 +2263,12 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq, if (err < 0) break; + /* simple hierarchies stop at the PMC level */ + if (event->irq == 0) { + err = irq_domain_disconnect_hierarchy(domain->parent, virq); + break; + } + spec.fwnode = &pmc->dev->of_node->fwnode; spec.param_count = 3; spec.param[0] = GIC_SPI; @@ -2263,6 +2281,7 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq, break; } + /* GPIO wake events */ if (fwspec->param_count == 3) { if (event->gpio.instance != fwspec->param[0] || event->gpio.pin != fwspec->param[1]) -- cgit v1.2.3 From a28dc5f17da52e4bff08c9deac29f97dd4d3819a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 11 Jul 2022 17:40:31 +0200 Subject: soc/tegra: pmc: Add USB port wake events for Tegra194 Tegra194 supports waking up from suspend when activity is detected on any of the USB ports. Add these wake events so that the system can be woken on such activity. Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 48286bc59f46..03d614acd521 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -3776,6 +3776,13 @@ static const struct tegra_wake_event tegra194_wake_events[] = { TEGRA_WAKE_IRQ("pmu", 24, 209), TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)), TEGRA_WAKE_IRQ("rtc", 73, 10), + TEGRA_WAKE_SIMPLE("usb3-port-0", 76), + TEGRA_WAKE_SIMPLE("usb3-port-1", 77), + TEGRA_WAKE_SIMPLE("usb3-port-2-3", 78), + TEGRA_WAKE_SIMPLE("usb2-port-0", 79), + TEGRA_WAKE_SIMPLE("usb2-port-1", 80), + TEGRA_WAKE_SIMPLE("usb2-port-2", 81), + TEGRA_WAKE_SIMPLE("usb2-port-3", 82), }; static const struct tegra_pmc_soc tegra194_pmc_soc = { -- cgit v1.2.3 From b7134422146692e096e807751656fc58ee1a717d Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 12 May 2022 01:46:47 +0530 Subject: soc/tegra: cbb: Add CBB 1.0 driver for Tegra194 Adding driver to handle errors from Control Backbone (CBB) which are generated due to illegal accesses. CBB 1.0 is used in Tegra194 SoCs. When an error is reported from a NOC within CBB, the driver prints debug information about failed transaction like Error Code, Error Description, Master, Address, AXI ID, Cache, Protection, Security Group etc. It then causes system crash using BUG_ON() or call WARN() based on whether the error type is fatal or not. Signed-off-by: Sumit Gupta Signed-off-by: Thierry Reding --- drivers/soc/tegra/Kconfig | 9 + drivers/soc/tegra/Makefile | 1 + drivers/soc/tegra/cbb/Makefile | 8 + drivers/soc/tegra/cbb/tegra-cbb.c | 190 +++ drivers/soc/tegra/cbb/tegra194-cbb.c | 2364 ++++++++++++++++++++++++++++++++++ include/soc/tegra/tegra-cbb.h | 47 + 6 files changed, 2619 insertions(+) create mode 100644 drivers/soc/tegra/cbb/Makefile create mode 100644 drivers/soc/tegra/cbb/tegra-cbb.c create mode 100644 drivers/soc/tegra/cbb/tegra194-cbb.c create mode 100644 include/soc/tegra/tegra-cbb.h (limited to 'drivers') diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 5725c8ef0406..65283a93e78f 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -162,3 +162,12 @@ config SOC_TEGRA30_VOLTAGE_COUPLER bool "Voltage scaling support for Tegra30 SoCs" depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST depends on REGULATOR + +config SOC_TEGRA_CBB + tristate "Tegra driver to handle error from CBB" + depends on ARCH_TEGRA_194_SOC + default y + help + Support for handling error from Tegra Control Backbone(CBB). + This driver handles the errors from CBB and prints debug + information about the failed transactions. diff --git a/drivers/soc/tegra/Makefile b/drivers/soc/tegra/Makefile index 054e862b63d8..d722f512dc9d 100644 --- a/drivers/soc/tegra/Makefile +++ b/drivers/soc/tegra/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += fuse/ +obj-y += cbb/ obj-y += common.o obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o diff --git a/drivers/soc/tegra/cbb/Makefile b/drivers/soc/tegra/cbb/Makefile new file mode 100644 index 000000000000..711b75610703 --- /dev/null +++ b/drivers/soc/tegra/cbb/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Control Backbone Driver code. +# +ifdef CONFIG_SOC_TEGRA_CBB +obj-y += tegra-cbb.o +obj-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-cbb.o +endif diff --git a/drivers/soc/tegra/cbb/tegra-cbb.c b/drivers/soc/tegra/cbb/tegra-cbb.c new file mode 100644 index 000000000000..d200937353c7 --- /dev/null +++ b/drivers/soc/tegra/cbb/tegra-cbb.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void tegra_cbb_print_err(struct seq_file *file, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + if (file) { + seq_vprintf(file, fmt, args); + } else { + vaf.fmt = fmt; + vaf.va = &args; + pr_crit("%pV", &vaf); + } + + va_end(args); +} + +void tegra_cbb_print_cache(struct seq_file *file, u32 cache) +{ + const char *buff_str, *mod_str, *rd_str, *wr_str; + + buff_str = (cache & BIT(0)) ? "Bufferable " : ""; + mod_str = (cache & BIT(1)) ? "Modifiable " : ""; + rd_str = (cache & BIT(2)) ? "Read-Allocate " : ""; + wr_str = (cache & BIT(3)) ? "Write-Allocate" : ""; + + if (cache == 0x0) + buff_str = "Device Non-Bufferable"; + + tegra_cbb_print_err(file, "\t Cache\t\t\t: 0x%x -- %s%s%s%s\n", + cache, buff_str, mod_str, rd_str, wr_str); +} + +void tegra_cbb_print_prot(struct seq_file *file, u32 prot) +{ + const char *data_str, *secure_str, *priv_str; + + data_str = (prot & 0x4) ? "Instruction" : "Data"; + secure_str = (prot & 0x2) ? "Non-Secure" : "Secure"; + priv_str = (prot & 0x1) ? "Privileged" : "Unprivileged"; + + tegra_cbb_print_err(file, "\t Protection\t\t: 0x%x -- %s, %s, %s Access\n", + prot, priv_str, secure_str, data_str); +} + +static int tegra_cbb_err_show(struct seq_file *file, void *data) +{ + struct tegra_cbb *cbb = file->private; + + return cbb->ops->debugfs_show(cbb, file, data); +} + +static int tegra_cbb_err_open(struct inode *inode, struct file *file) +{ + return single_open(file, tegra_cbb_err_show, inode->i_private); +} + +static const struct file_operations tegra_cbb_err_fops = { + .open = tegra_cbb_err_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + +static int tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb) +{ + static struct dentry *root; + + if (!root) { + root = debugfs_create_file("tegra_cbb_err", 0444, NULL, cbb, &tegra_cbb_err_fops); + if (IS_ERR_OR_NULL(root)) { + pr_err("%s(): could not create debugfs node\n", __func__); + return PTR_ERR(root); + } + } + + return 0; +} + +void tegra_cbb_stall_enable(struct tegra_cbb *cbb) +{ + if (cbb->ops->stall_enable) + cbb->ops->stall_enable(cbb); +} + +void tegra_cbb_fault_enable(struct tegra_cbb *cbb) +{ + if (cbb->ops->fault_enable) + cbb->ops->fault_enable(cbb); +} + +void tegra_cbb_error_clear(struct tegra_cbb *cbb) +{ + if (cbb->ops->error_clear) + cbb->ops->error_clear(cbb); +} + +u32 tegra_cbb_get_status(struct tegra_cbb *cbb) +{ + if (cbb->ops->get_status) + return cbb->ops->get_status(cbb); + + return 0; +} + +int tegra_cbb_get_irq(struct platform_device *pdev, unsigned int *nonsec_irq, + unsigned int *sec_irq) +{ + unsigned int index = 0; + int num_intr = 0, irq; + + num_intr = platform_irq_count(pdev); + if (!num_intr) + return -EINVAL; + + if (num_intr == 2) { + irq = platform_get_irq(pdev, index); + if (irq <= 0) { + dev_err(&pdev->dev, "failed to get non-secure IRQ: %d\n", irq); + return -ENOENT; + } + + *nonsec_irq = irq; + index++; + } + + irq = platform_get_irq(pdev, index); + if (irq <= 0) { + dev_err(&pdev->dev, "failed to get secure IRQ: %d\n", irq); + return -ENOENT; + } + + *sec_irq = irq; + + if (num_intr == 1) + dev_dbg(&pdev->dev, "secure IRQ: %u\n", *sec_irq); + + if (num_intr == 2) + dev_dbg(&pdev->dev, "secure IRQ: %u, non-secure IRQ: %u\n", *sec_irq, *nonsec_irq); + + return 0; +} + +int tegra_cbb_register(struct tegra_cbb *cbb) +{ + int ret; + + if (IS_ENABLED(CONFIG_DEBUG_FS)) { + ret = tegra_cbb_err_debugfs_init(cbb); + if (ret) { + dev_err(cbb->dev, "failed to create debugfs\n"); + return ret; + } + } + + /* register interrupt handler for errors due to different initiators */ + ret = cbb->ops->interrupt_enable(cbb); + if (ret < 0) { + dev_err(cbb->dev, "Failed to register CBB Interrupt ISR"); + return ret; + } + + cbb->ops->error_enable(cbb); + dsb(sy); + + return 0; +} diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c new file mode 100644 index 000000000000..1ae0bd9a1ac1 --- /dev/null +++ b/drivers/soc/tegra/cbb/tegra194-cbb.c @@ -0,0 +1,2364 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved + * + * The driver handles Error's from Control Backbone(CBB) generated due to + * illegal accesses. When an error is reported from a NOC within CBB, + * the driver checks ErrVld status of all three Error Logger's of that NOC. + * It then prints debug information about failed transaction using ErrLog + * registers of error logger which has ErrVld set. Currently, SLV, DEC, + * TMO, SEC, UNS are the codes which are supported by CBB. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ERRLOGGER_0_ID_COREID_0 0x00000000 +#define ERRLOGGER_0_ID_REVISIONID_0 0x00000004 +#define ERRLOGGER_0_FAULTEN_0 0x00000008 +#define ERRLOGGER_0_ERRVLD_0 0x0000000c +#define ERRLOGGER_0_ERRCLR_0 0x00000010 +#define ERRLOGGER_0_ERRLOG0_0 0x00000014 +#define ERRLOGGER_0_ERRLOG1_0 0x00000018 +#define ERRLOGGER_0_RSVD_00_0 0x0000001c +#define ERRLOGGER_0_ERRLOG3_0 0x00000020 +#define ERRLOGGER_0_ERRLOG4_0 0x00000024 +#define ERRLOGGER_0_ERRLOG5_0 0x00000028 +#define ERRLOGGER_0_STALLEN_0 0x00000038 + +#define ERRLOGGER_1_ID_COREID_0 0x00000080 +#define ERRLOGGER_1_ID_REVISIONID_0 0x00000084 +#define ERRLOGGER_1_FAULTEN_0 0x00000088 +#define ERRLOGGER_1_ERRVLD_0 0x0000008c +#define ERRLOGGER_1_ERRCLR_0 0x00000090 +#define ERRLOGGER_1_ERRLOG0_0 0x00000094 +#define ERRLOGGER_1_ERRLOG1_0 0x00000098 +#define ERRLOGGER_1_RSVD_00_0 0x0000009c +#define ERRLOGGER_1_ERRLOG3_0 0x000000a0 +#define ERRLOGGER_1_ERRLOG4_0 0x000000a4 +#define ERRLOGGER_1_ERRLOG5_0 0x000000a8 +#define ERRLOGGER_1_STALLEN_0 0x000000b8 + +#define ERRLOGGER_2_ID_COREID_0 0x00000100 +#define ERRLOGGER_2_ID_REVISIONID_0 0x00000104 +#define ERRLOGGER_2_FAULTEN_0 0x00000108 +#define ERRLOGGER_2_ERRVLD_0 0x0000010c +#define ERRLOGGER_2_ERRCLR_0 0x00000110 +#define ERRLOGGER_2_ERRLOG0_0 0x00000114 +#define ERRLOGGER_2_ERRLOG1_0 0x00000118 +#define ERRLOGGER_2_RSVD_00_0 0x0000011c +#define ERRLOGGER_2_ERRLOG3_0 0x00000120 +#define ERRLOGGER_2_ERRLOG4_0 0x00000124 +#define ERRLOGGER_2_ERRLOG5_0 0x00000128 +#define ERRLOGGER_2_STALLEN_0 0x00000138 + +#define CBB_NOC_INITFLOW GENMASK(23, 20) +#define CBB_NOC_TARGFLOW GENMASK(19, 16) +#define CBB_NOC_TARG_SUBRANGE GENMASK(15, 9) +#define CBB_NOC_SEQID GENMASK(8, 0) + +#define BPMP_NOC_INITFLOW GENMASK(20, 18) +#define BPMP_NOC_TARGFLOW GENMASK(17, 13) +#define BPMP_NOC_TARG_SUBRANGE GENMASK(12, 9) +#define BPMP_NOC_SEQID GENMASK(8, 0) + +#define AON_NOC_INITFLOW GENMASK(22, 21) +#define AON_NOC_TARGFLOW GENMASK(20, 15) +#define AON_NOC_TARG_SUBRANGE GENMASK(14, 9) +#define AON_NOC_SEQID GENMASK(8, 0) + +#define SCE_NOC_INITFLOW GENMASK(21, 19) +#define SCE_NOC_TARGFLOW GENMASK(18, 14) +#define SCE_NOC_TARG_SUBRANGE GENMASK(13, 9) +#define SCE_NOC_SEQID GENMASK(8, 0) + +#define CBB_NOC_AXCACHE GENMASK(3, 0) +#define CBB_NOC_NON_MOD GENMASK(4, 4) +#define CBB_NOC_AXPROT GENMASK(7, 5) +#define CBB_NOC_FALCONSEC GENMASK(9, 8) +#define CBB_NOC_GRPSEC GENMASK(16, 10) +#define CBB_NOC_VQC GENMASK(18, 17) +#define CBB_NOC_MSTR_ID GENMASK(22, 19) +#define CBB_NOC_AXI_ID GENMASK(30, 23) + +#define CLUSTER_NOC_AXCACHE GENMASK(3, 0) +#define CLUSTER_NOC_AXPROT GENMASK(6, 4) +#define CLUSTER_NOC_FALCONSEC GENMASK(8, 7) +#define CLUSTER_NOC_GRPSEC GENMASK(15, 9) +#define CLUSTER_NOC_VQC GENMASK(17, 16) +#define CLUSTER_NOC_MSTR_ID GENMASK(21, 18) + +#define USRBITS_MSTR_ID GENMASK(21, 18) + +#define CBB_ERR_OPC GENMASK(4, 1) +#define CBB_ERR_ERRCODE GENMASK(10, 8) +#define CBB_ERR_LEN1 GENMASK(27, 16) + +#define DMAAPB_X_RAW_INTERRUPT_STATUS 0x2ec + +struct tegra194_cbb_packet_header { + bool lock; // [0] + u8 opc; // [4:1] + u8 errcode; // [10:8]= RD, RDW, RDL, RDX, WR, WRW, WRC, PRE, URG + u16 len1; // [27:16] + bool format; // [31] = 1 -> FlexNoC versions 2.7 & above +}; + +struct tegra194_cbb_aperture { + u8 initflow; + u8 targflow; + u8 targ_subrange; + u8 init_mapping; + u32 init_localaddress; + u8 targ_mapping; + u32 targ_localaddress; + u16 seqid; +}; + +struct tegra194_cbb_userbits { + u8 axcache; + u8 non_mod; + u8 axprot; + u8 falconsec; + u8 grpsec; + u8 vqc; + u8 mstr_id; + u8 axi_id; +}; + +struct tegra194_cbb_noc_data { + const char *name; + bool erd_mask_inband_err; + const char * const *master_id; + unsigned int max_aperture; + const struct tegra194_cbb_aperture *noc_aperture; + const char * const *routeid_initflow; + const char * const *routeid_targflow; + void (*parse_routeid)(struct tegra194_cbb_aperture *info, u64 routeid); + void (*parse_userbits)(struct tegra194_cbb_userbits *usrbits, u32 elog_5); +}; + +struct tegra194_axi2apb_bridge { + struct resource res; + void __iomem *base; +}; + +struct tegra194_cbb { + struct tegra_cbb base; + + const struct tegra194_cbb_noc_data *noc; + struct resource *res; + + void __iomem *regs; + unsigned int num_intr; + unsigned int sec_irq; + unsigned int nonsec_irq; + u32 errlog0; + u32 errlog1; + u32 errlog2; + u32 errlog3; + u32 errlog4; + u32 errlog5; + + struct tegra194_axi2apb_bridge *bridges; + unsigned int num_bridges; +}; + +static inline struct tegra194_cbb *to_tegra194_cbb(struct tegra_cbb *cbb) +{ + return container_of(cbb, struct tegra194_cbb, base); +} + +static LIST_HEAD(cbb_list); +static DEFINE_SPINLOCK(cbb_lock); + +static const char * const tegra194_cbb_trantype[] = { + "RD - Read, Incrementing", + "RDW - Read, Wrap", /* Not Supported */ + "RDX - Exclusive Read", /* Not Supported */ + "RDL - Linked Read", /* Not Supported */ + "WR - Write, Incrementing", + "WRW - Write, Wrap", /* Not Supported */ + "WRC - Exclusive Write", /* Not Supported */ + "PRE - Preamble Sequence for Fixed Accesses" +}; + +static const char * const tegra194_axi2apb_error[] = { + "SFIFONE - Status FIFO Not Empty interrupt", + "SFIFOF - Status FIFO Full interrupt", + "TIM - Timer(Timeout) interrupt", + "SLV - SLVERR interrupt", + "NULL", + "ERBF - Early response buffer Full interrupt", + "NULL", + "RDFIFOF - Read Response FIFO Full interrupt", + "WRFIFOF - Write Response FIFO Full interrupt", + "CH0DFIFOF - Ch0 Data FIFO Full interrupt", + "CH1DFIFOF - Ch1 Data FIFO Full interrupt", + "CH2DFIFOF - Ch2 Data FIFO Full interrupt", + "UAT - Unsupported alignment type error", + "UBS - Unsupported burst size error", + "UBE - Unsupported Byte Enable error", + "UBT - Unsupported burst type error", + "BFS - Block Firewall security error", + "ARFS - Address Range Firewall security error", + "CH0RFIFOF - Ch0 Request FIFO Full interrupt", + "CH1RFIFOF - Ch1 Request FIFO Full interrupt", + "CH2RFIFOF - Ch2 Request FIFO Full interrupt" +}; + +static const char * const tegra194_master_id[] = { + [0x0] = "CCPLEX", + [0x1] = "CCPLEX_DPMU", + [0x2] = "BPMP", + [0x3] = "AON", + [0x4] = "SCE", + [0x5] = "GPCDMA_PERIPHERAL", + [0x6] = "TSECA", + [0x7] = "TSECB", + [0x8] = "JTAGM_DFT", + [0x9] = "CORESIGHT_AXIAP", + [0xa] = "APE", + [0xb] = "PEATR", + [0xc] = "NVDEC", + [0xd] = "RCE", + [0xe] = "NVDEC1" +}; + +static const struct tegra_cbb_error tegra194_cbb_errors[] = { + { + .code = "SLV", + .source = "Target", + .desc = "Target error detected by CBB slave" + }, { + .code = "DEC", + .source = "Initiator NIU", + .desc = "Address decode error" + }, { + .code = "UNS", + .source = "Target NIU", + .desc = "Unsupported request. Not a valid transaction" + }, { + .code = "DISC", /* Not Supported by CBB */ + .source = "Power Disconnect", + .desc = "Disconnected target or domain" + }, { + .code = "SEC", + .source = "Initiator NIU or Firewall", + .desc = "Security violation. Firewall error" + }, { + .code = "HIDE", /* Not Supported by CBB */ + .source = "Firewall", + .desc = "Hidden security violation, reported as OK to initiator" + }, { + .code = "TMO", + .source = "Target NIU", + .desc = "Target time-out error" + }, { + .code = "RSV", + .source = "None", + .desc = "Reserved" + } +}; + +/* + * CBB NOC aperture lookup table as per file "cbb_central_noc_Structure.info". + */ +static const char * const tegra194_cbbcentralnoc_routeid_initflow[] = { + [0x0] = "aon_p2ps/I/aon", + [0x1] = "ape_p2ps/I/ape_p2ps", + [0x2] = "bpmp_p2ps/I/bpmp_p2ps", + [0x3] = "ccroc_p2ps/I/ccroc_p2ps", + [0x4] = "csite_p2ps/I/0", + [0x5] = "gpcdma_mmio_p2ps/I/0", + [0x6] = "jtag_p2ps/I/0", + [0x7] = "nvdec1_p2ps/I/0", + [0x8] = "nvdec_p2ps/I/0", + [0x9] = "rce_p2ps/I/rce_p2ps", + [0xa] = "sce_p2ps/I/sce_p2ps", + [0xb] = "tseca_p2ps/I/0", + [0xc] = "tsecb_p2ps/I/0", + [0xd] = "RESERVED", + [0xe] = "RESERVED", + [0xf] = "RESERVED" +}; + +static const char * const tegra194_cbbcentralnoc_routeid_targflow[] = { + [0x0] = "SVC/T/intreg", + [0x1] = "axis_satellite_axi2apb_p2pm/T/axis_satellite_axi2apb_p2pm", + [0x2] = "axis_satellite_grout/T/axis_satellite_grout", + [0x3] = "cbb_firewall/T/cbb_firewall", + [0x4] = "gpu_p2pm/T/gpu_p2pm", + [0x5] = "host1x_p2pm/T/host1x_p2pm", + [0x6] = "sapb_3_p2pm/T/sapb_3_p2pm", + [0x7] = "smmu0_p2pm/T/smmu0_p2pm", + [0x8] = "smmu1_p2pm/T/smmu1_p2pm", + [0x9] = "smmu2_p2pm/T/smmu2_p2pm", + [0xa] = "stm_p2pm/T/stm_p2pm", + [0xb] = "RESERVED", + [0xc] = "RESERVED", + [0xd] = "RESERVED", + [0xe] = "RESERVED", + [0xf] = "RESERVED" +}; + +/* + * Fields of CBB NOC lookup table: + * Init flow, Targ flow, Targ subrange, Init mapping, Init localAddress, + * Targ mapping, Targ localAddress + * ---------------------------------------------------------------------------- + */ +static const struct tegra194_cbb_aperture tegra194_cbbcentralnoc_apert_lookup[] = { + { 0x0, 0x0, 0x00, 0x0, 0x02300000, 0, 0x00000000 }, + { 0x0, 0x1, 0x00, 0x0, 0x02003000, 0, 0x02003000 }, + { 0x0, 0x1, 0x01, 0x0, 0x02006000, 2, 0x02006000 }, + { 0x0, 0x1, 0x02, 0x0, 0x02016000, 3, 0x02016000 }, + { 0x0, 0x1, 0x03, 0x0, 0x0201d000, 4, 0x0201d000 }, + { 0x0, 0x1, 0x04, 0x0, 0x0202b000, 6, 0x0202b000 }, + { 0x0, 0x1, 0x05, 0x0, 0x02434000, 20, 0x02434000 }, + { 0x0, 0x1, 0x06, 0x0, 0x02436000, 21, 0x02436000 }, + { 0x0, 0x1, 0x07, 0x0, 0x02438000, 22, 0x02438000 }, + { 0x0, 0x1, 0x08, 0x0, 0x02445000, 24, 0x02445000 }, + { 0x0, 0x1, 0x09, 0x0, 0x02446000, 25, 0x02446000 }, + { 0x0, 0x1, 0x0a, 0x0, 0x02004000, 1, 0x02004000 }, + { 0x0, 0x1, 0x0b, 0x0, 0x0201e000, 5, 0x0201e000 }, + { 0x0, 0x1, 0x0c, 0x0, 0x0202c000, 7, 0x0202c000 }, + { 0x0, 0x1, 0x0d, 0x0, 0x02204000, 8, 0x02204000 }, + { 0x0, 0x1, 0x0e, 0x0, 0x02214000, 9, 0x02214000 }, + { 0x0, 0x1, 0x0f, 0x0, 0x02224000, 10, 0x02224000 }, + { 0x0, 0x1, 0x10, 0x0, 0x02234000, 11, 0x02234000 }, + { 0x0, 0x1, 0x11, 0x0, 0x02244000, 12, 0x02244000 }, + { 0x0, 0x1, 0x12, 0x0, 0x02254000, 13, 0x02254000 }, + { 0x0, 0x1, 0x13, 0x0, 0x02264000, 14, 0x02264000 }, + { 0x0, 0x1, 0x14, 0x0, 0x02274000, 15, 0x02274000 }, + { 0x0, 0x1, 0x15, 0x0, 0x02284000, 16, 0x02284000 }, + { 0x0, 0x1, 0x16, 0x0, 0x0243a000, 23, 0x0243a000 }, + { 0x0, 0x1, 0x17, 0x0, 0x02370000, 17, 0x02370000 }, + { 0x0, 0x1, 0x18, 0x0, 0x023d0000, 18, 0x023d0000 }, + { 0x0, 0x1, 0x19, 0x0, 0x023e0000, 19, 0x023e0000 }, + { 0x0, 0x1, 0x1a, 0x0, 0x02450000, 26, 0x02450000 }, + { 0x0, 0x1, 0x1b, 0x0, 0x02460000, 27, 0x02460000 }, + { 0x0, 0x1, 0x1c, 0x0, 0x02490000, 28, 0x02490000 }, + { 0x0, 0x1, 0x1d, 0x0, 0x03130000, 31, 0x03130000 }, + { 0x0, 0x1, 0x1e, 0x0, 0x03160000, 32, 0x03160000 }, + { 0x0, 0x1, 0x1f, 0x0, 0x03270000, 33, 0x03270000 }, + { 0x0, 0x1, 0x20, 0x0, 0x032e0000, 35, 0x032e0000 }, + { 0x0, 0x1, 0x21, 0x0, 0x03300000, 36, 0x03300000 }, + { 0x0, 0x1, 0x22, 0x0, 0x13090000, 40, 0x13090000 }, + { 0x0, 0x1, 0x23, 0x0, 0x20120000, 43, 0x20120000 }, + { 0x0, 0x1, 0x24, 0x0, 0x20170000, 44, 0x20170000 }, + { 0x0, 0x1, 0x25, 0x0, 0x20190000, 45, 0x20190000 }, + { 0x0, 0x1, 0x26, 0x0, 0x201b0000, 46, 0x201b0000 }, + { 0x0, 0x1, 0x27, 0x0, 0x20250000, 47, 0x20250000 }, + { 0x0, 0x1, 0x28, 0x0, 0x20260000, 48, 0x20260000 }, + { 0x0, 0x1, 0x29, 0x0, 0x20420000, 49, 0x20420000 }, + { 0x0, 0x1, 0x2a, 0x0, 0x20460000, 50, 0x20460000 }, + { 0x0, 0x1, 0x2b, 0x0, 0x204f0000, 51, 0x204f0000 }, + { 0x0, 0x1, 0x2c, 0x0, 0x20520000, 52, 0x20520000 }, + { 0x0, 0x1, 0x2d, 0x0, 0x20580000, 53, 0x20580000 }, + { 0x0, 0x1, 0x2e, 0x0, 0x205a0000, 54, 0x205a0000 }, + { 0x0, 0x1, 0x2f, 0x0, 0x205c0000, 55, 0x205c0000 }, + { 0x0, 0x1, 0x30, 0x0, 0x20690000, 56, 0x20690000 }, + { 0x0, 0x1, 0x31, 0x0, 0x20770000, 57, 0x20770000 }, + { 0x0, 0x1, 0x32, 0x0, 0x20790000, 58, 0x20790000 }, + { 0x0, 0x1, 0x33, 0x0, 0x20880000, 59, 0x20880000 }, + { 0x0, 0x1, 0x34, 0x0, 0x20990000, 62, 0x20990000 }, + { 0x0, 0x1, 0x35, 0x0, 0x20e10000, 65, 0x20e10000 }, + { 0x0, 0x1, 0x36, 0x0, 0x20e70000, 66, 0x20e70000 }, + { 0x0, 0x1, 0x37, 0x0, 0x20e80000, 67, 0x20e80000 }, + { 0x0, 0x1, 0x38, 0x0, 0x20f30000, 68, 0x20f30000 }, + { 0x0, 0x1, 0x39, 0x0, 0x20f50000, 69, 0x20f50000 }, + { 0x0, 0x1, 0x3a, 0x0, 0x20fc0000, 70, 0x20fc0000 }, + { 0x0, 0x1, 0x3b, 0x0, 0x21110000, 72, 0x21110000 }, + { 0x0, 0x1, 0x3c, 0x0, 0x21270000, 73, 0x21270000 }, + { 0x0, 0x1, 0x3d, 0x0, 0x21290000, 74, 0x21290000 }, + { 0x0, 0x1, 0x3e, 0x0, 0x21840000, 75, 0x21840000 }, + { 0x0, 0x1, 0x3f, 0x0, 0x21880000, 76, 0x21880000 }, + { 0x0, 0x1, 0x40, 0x0, 0x218d0000, 77, 0x218d0000 }, + { 0x0, 0x1, 0x41, 0x0, 0x21950000, 78, 0x21950000 }, + { 0x0, 0x1, 0x42, 0x0, 0x21960000, 79, 0x21960000 }, + { 0x0, 0x1, 0x43, 0x0, 0x21a10000, 80, 0x21a10000 }, + { 0x0, 0x1, 0x44, 0x0, 0x024a0000, 29, 0x024a0000 }, + { 0x0, 0x1, 0x45, 0x0, 0x024c0000, 30, 0x024c0000 }, + { 0x0, 0x1, 0x46, 0x0, 0x032c0000, 34, 0x032c0000 }, + { 0x0, 0x1, 0x47, 0x0, 0x03400000, 37, 0x03400000 }, + { 0x0, 0x1, 0x48, 0x0, 0x130a0000, 41, 0x130a0000 }, + { 0x0, 0x1, 0x49, 0x0, 0x130c0000, 42, 0x130c0000 }, + { 0x0, 0x1, 0x4a, 0x0, 0x208a0000, 60, 0x208a0000 }, + { 0x0, 0x1, 0x4b, 0x0, 0x208c0000, 61, 0x208c0000 }, + { 0x0, 0x1, 0x4c, 0x0, 0x209a0000, 63, 0x209a0000 }, + { 0x0, 0x1, 0x4d, 0x0, 0x21a40000, 81, 0x21a40000 }, + { 0x0, 0x1, 0x4e, 0x0, 0x03440000, 38, 0x03440000 }, + { 0x0, 0x1, 0x4f, 0x0, 0x20d00000, 64, 0x20d00000 }, + { 0x0, 0x1, 0x50, 0x0, 0x21000000, 71, 0x21000000 }, + { 0x0, 0x1, 0x51, 0x0, 0x0b000000, 39, 0x0b000000 }, + { 0x0, 0x2, 0x00, 0x0, 0x00000000, 0, 0x00000000 }, + { 0x0, 0x3, 0x00, 0x0, 0x02340000, 0, 0x00000000 }, + { 0x0, 0x4, 0x00, 0x0, 0x17000000, 0, 0x17000000 }, + { 0x0, 0x4, 0x01, 0x0, 0x18000000, 1, 0x18000000 }, + { 0x0, 0x5, 0x00, 0x0, 0x13e80000, 1, 0x13e80000 }, + { 0x0, 0x5, 0x01, 0x0, 0x15810000, 12, 0x15810000 }, + { 0x0, 0x5, 0x02, 0x0, 0x15840000, 14, 0x15840000 }, + { 0x0, 0x5, 0x03, 0x0, 0x15a40000, 17, 0x15a40000 }, + { 0x0, 0x5, 0x04, 0x0, 0x13f00000, 3, 0x13f00000 }, + { 0x0, 0x5, 0x05, 0x0, 0x15820000, 13, 0x15820000 }, + { 0x0, 0x5, 0x06, 0x0, 0x13ec0000, 2, 0x13ec0000 }, + { 0x0, 0x5, 0x07, 0x0, 0x15200000, 6, 0x15200000 }, + { 0x0, 0x5, 0x08, 0x0, 0x15340000, 7, 0x15340000 }, + { 0x0, 0x5, 0x09, 0x0, 0x15380000, 8, 0x15380000 }, + { 0x0, 0x5, 0x0a, 0x0, 0x15500000, 10, 0x15500000 }, + { 0x0, 0x5, 0x0b, 0x0, 0x155c0000, 11, 0x155c0000 }, + { 0x0, 0x5, 0x0c, 0x0, 0x15a00000, 16, 0x15a00000 }, + { 0x0, 0x5, 0x0d, 0x0, 0x13e00000, 0, 0x13e00000 }, + { 0x0, 0x5, 0x0e, 0x0, 0x15100000, 5, 0x15100000 }, + { 0x0, 0x5, 0x0f, 0x0, 0x15480000, 9, 0x15480000 }, + { 0x0, 0x5, 0x10, 0x0, 0x15880000, 15, 0x15880000 }, + { 0x0, 0x5, 0x11, 0x0, 0x15a80000, 18, 0x15a80000 }, + { 0x0, 0x5, 0x12, 0x0, 0x15b00000, 19, 0x15b00000 }, + { 0x0, 0x5, 0x13, 0x0, 0x14800000, 4, 0x14800000 }, + { 0x0, 0x5, 0x14, 0x0, 0x15c00000, 20, 0x15c00000 }, + { 0x0, 0x5, 0x15, 0x0, 0x16000000, 21, 0x16000000 }, + { 0x0, 0x6, 0x00, 0x0, 0x02000000, 4, 0x02000000 }, + { 0x0, 0x6, 0x01, 0x0, 0x02007000, 5, 0x02007000 }, + { 0x0, 0x6, 0x02, 0x0, 0x02008000, 6, 0x02008000 }, + { 0x0, 0x6, 0x03, 0x0, 0x02013000, 7, 0x02013000 }, + { 0x0, 0x6, 0x04, 0x0, 0x0201c000, 8, 0x0201c000 }, + { 0x0, 0x6, 0x05, 0x0, 0x02020000, 9, 0x02020000 }, + { 0x0, 0x6, 0x06, 0x0, 0x0202a000, 10, 0x0202a000 }, + { 0x0, 0x6, 0x07, 0x0, 0x0202e000, 11, 0x0202e000 }, + { 0x0, 0x6, 0x08, 0x0, 0x06400000, 33, 0x06400000 }, + { 0x0, 0x6, 0x09, 0x0, 0x02038000, 12, 0x02038000 }, + { 0x0, 0x6, 0x0a, 0x0, 0x00100000, 0, 0x00100000 }, + { 0x0, 0x6, 0x0b, 0x0, 0x023b0000, 13, 0x023b0000 }, + { 0x0, 0x6, 0x0c, 0x0, 0x02800000, 16, 0x02800000 }, + { 0x0, 0x6, 0x0d, 0x0, 0x030e0000, 22, 0x030e0000 }, + { 0x0, 0x6, 0x0e, 0x0, 0x03800000, 23, 0x03800000 }, + { 0x0, 0x6, 0x0f, 0x0, 0x03980000, 25, 0x03980000 }, + { 0x0, 0x6, 0x10, 0x0, 0x03a60000, 26, 0x03a60000 }, + { 0x0, 0x6, 0x11, 0x0, 0x03d80000, 31, 0x03d80000 }, + { 0x0, 0x6, 0x12, 0x0, 0x20000000, 36, 0x20000000 }, + { 0x0, 0x6, 0x13, 0x0, 0x20050000, 38, 0x20050000 }, + { 0x0, 0x6, 0x14, 0x0, 0x201e0000, 40, 0x201e0000 }, + { 0x0, 0x6, 0x15, 0x0, 0x20280000, 42, 0x20280000 }, + { 0x0, 0x6, 0x16, 0x0, 0x202c0000, 43, 0x202c0000 }, + { 0x0, 0x6, 0x17, 0x0, 0x20390000, 44, 0x20390000 }, + { 0x0, 0x6, 0x18, 0x0, 0x20430000, 45, 0x20430000 }, + { 0x0, 0x6, 0x19, 0x0, 0x20440000, 46, 0x20440000 }, + { 0x0, 0x6, 0x1a, 0x0, 0x204e0000, 47, 0x204e0000 }, + { 0x0, 0x6, 0x1b, 0x0, 0x20550000, 48, 0x20550000 }, + { 0x0, 0x6, 0x1c, 0x0, 0x20570000, 49, 0x20570000 }, + { 0x0, 0x6, 0x1d, 0x0, 0x20590000, 50, 0x20590000 }, + { 0x0, 0x6, 0x1e, 0x0, 0x20730000, 52, 0x20730000 }, + { 0x0, 0x6, 0x1f, 0x0, 0x209f0000, 54, 0x209f0000 }, + { 0x0, 0x6, 0x20, 0x0, 0x20e20000, 55, 0x20e20000 }, + { 0x0, 0x6, 0x21, 0x0, 0x20ed0000, 56, 0x20ed0000 }, + { 0x0, 0x6, 0x22, 0x0, 0x20fd0000, 57, 0x20fd0000 }, + { 0x0, 0x6, 0x23, 0x0, 0x21120000, 59, 0x21120000 }, + { 0x0, 0x6, 0x24, 0x0, 0x211a0000, 60, 0x211a0000 }, + { 0x0, 0x6, 0x25, 0x0, 0x21850000, 61, 0x21850000 }, + { 0x0, 0x6, 0x26, 0x0, 0x21860000, 62, 0x21860000 }, + { 0x0, 0x6, 0x27, 0x0, 0x21890000, 63, 0x21890000 }, + { 0x0, 0x6, 0x28, 0x0, 0x21970000, 64, 0x21970000 }, + { 0x0, 0x6, 0x29, 0x0, 0x21990000, 65, 0x21990000 }, + { 0x0, 0x6, 0x2a, 0x0, 0x21a00000, 66, 0x21a00000 }, + { 0x0, 0x6, 0x2b, 0x0, 0x21a90000, 68, 0x21a90000 }, + { 0x0, 0x6, 0x2c, 0x0, 0x21ac0000, 70, 0x21ac0000 }, + { 0x0, 0x6, 0x2d, 0x0, 0x01f80000, 3, 0x01f80000 }, + { 0x0, 0x6, 0x2e, 0x0, 0x024e0000, 14, 0x024e0000 }, + { 0x0, 0x6, 0x2f, 0x0, 0x030c0000, 21, 0x030c0000 }, + { 0x0, 0x6, 0x30, 0x0, 0x03820000, 24, 0x03820000 }, + { 0x0, 0x6, 0x31, 0x0, 0x03aa0000, 27, 0x03aa0000 }, + { 0x0, 0x6, 0x32, 0x0, 0x03c80000, 29, 0x03c80000 }, + { 0x0, 0x6, 0x33, 0x0, 0x130e0000, 34, 0x130e0000 }, + { 0x0, 0x6, 0x34, 0x0, 0x20020000, 37, 0x20020000 }, + { 0x0, 0x6, 0x35, 0x0, 0x20060000, 39, 0x20060000 }, + { 0x0, 0x6, 0x36, 0x0, 0x20200000, 41, 0x20200000 }, + { 0x0, 0x6, 0x37, 0x0, 0x206a0000, 51, 0x206a0000 }, + { 0x0, 0x6, 0x38, 0x0, 0x20740000, 53, 0x20740000 }, + { 0x0, 0x6, 0x39, 0x0, 0x20fe0000, 58, 0x20fe0000 }, + { 0x0, 0x6, 0x3a, 0x0, 0x21a20000, 67, 0x21a20000 }, + { 0x0, 0x6, 0x3b, 0x0, 0x21aa0000, 69, 0x21aa0000 }, + { 0x0, 0x6, 0x3c, 0x0, 0x02b80000, 17, 0x02b80000 }, + { 0x0, 0x6, 0x3d, 0x0, 0x03080000, 20, 0x03080000 }, + { 0x0, 0x6, 0x3e, 0x0, 0x13100000, 35, 0x13100000 }, + { 0x0, 0x6, 0x3f, 0x0, 0x01f00000, 2, 0x01f00000 }, + { 0x0, 0x6, 0x40, 0x0, 0x03000000, 19, 0x03000000 }, + { 0x0, 0x6, 0x41, 0x0, 0x03c00000, 28, 0x03c00000 }, + { 0x0, 0x6, 0x42, 0x0, 0x03d00000, 30, 0x03d00000 }, + { 0x0, 0x6, 0x43, 0x0, 0x01700000, 1, 0x01700000 }, + { 0x0, 0x6, 0x44, 0x0, 0x02c00000, 18, 0x02c00000 }, + { 0x0, 0x6, 0x45, 0x0, 0x02600000, 15, 0x02600000 }, + { 0x0, 0x6, 0x46, 0x0, 0x06000000, 32, 0x06000000 }, + { 0x0, 0x6, 0x47, 0x0, 0x24000000, 71, 0x24000000 }, + { 0x0, 0x7, 0x00, 0x0, 0x12000000, 0, 0x12000000 }, + { 0x0, 0x8, 0x00, 0x0, 0x11000000, 0, 0x11000000 }, + { 0x0, 0x9, 0x00, 0x0, 0x10000000, 0, 0x10000000 }, + { 0x0, 0xa, 0x00, 0x0, 0x22000000, 0, 0x22000000 } +}; + +/* + * BPMP NOC aperture lookup table as per file "BPMP_NOC_Structure.info". + */ +static const char * const tegra194_bpmpnoc_routeid_initflow[] = { + [0x0] = "cbb_i/I/0", + [0x1] = "cpu_m_i/I/0", + [0x2] = "cpu_p_i/I/0", + [0x3] = "cvc_i/I/0", + [0x4] = "dma_m_i/I/0", + [0x5] = "dma_p_i/I/0", + [0x6] = "RESERVED", + [0x7] = "RESERVED" +}; + +static const char * const tegra194_bpmpnoc_routeid_targflow[] = { + [0x00] = "multiport0_t/T/actmon", + [0x01] = "multiport0_t/T/ast_0", + [0x02] = "multiport0_t/T/ast_1", + [0x03] = "multiport0_t/T/atcm_cfg", + [0x04] = "multiport0_t/T/car", + [0x05] = "multiport0_t/T/central_pwr_mgr", + [0x06] = "multiport0_t/T/central_vtg_ctlr", + [0x07] = "multiport0_t/T/cfg", + [0x08] = "multiport0_t/T/dma", + [0x09] = "multiport0_t/T/err_collator", + [0x0a] = "multiport0_t/T/err_collator_car", + [0x0b] = "multiport0_t/T/fpga_misc", + [0x0c] = "multiport0_t/T/fpga_uart", + [0x0d] = "multiport0_t/T/gte", + [0x0e] = "multiport0_t/T/hsp", + [0x0f] = "multiport0_t/T/misc", + [0x10] = "multiport0_t/T/pm", + [0x11] = "multiport0_t/T/simon0", + [0x12] = "multiport0_t/T/simon1", + [0x13] = "multiport0_t/T/simon2", + [0x14] = "multiport0_t/T/simon3", + [0x15] = "multiport0_t/T/simon4", + [0x16] = "multiport0_t/T/soc_therm", + [0x17] = "multiport0_t/T/tke", + [0x18] = "multiport0_t/T/vic_0", + [0x19] = "multiport0_t/T/vic_1", + [0x1a] = "ast0_t/T/0", + [0x1b] = "ast1_t/T/0", + [0x1c] = "bpmp_noc_firewall/T/0", + [0x1d] = "cbb_t/T/0", + [0x1e] = "cpu_t/T/0", + [0x1f] = "svc_t/T/0" +}; + +/* + * Fields of BPMP NOC lookup table: + * Init flow, Targ flow, Targ subrange, Init mapping, Init localAddress, + * Targ mapping, Targ localAddress + * ---------------------------------------------------------------------------- + */ +static const struct tegra194_cbb_aperture tegra194_bpmpnoc_apert_lookup[] = { + { 0x0, 0x1c, 0x0, 0x0, 0x0d640000, 0, 0x00000000 }, + { 0x0, 0x1e, 0x0, 0x0, 0x0d400000, 0, 0x0d400000 }, + { 0x0, 0x00, 0x0, 0x0, 0x0d230000, 0, 0x00000000 }, + { 0x0, 0x01, 0x0, 0x0, 0x0d040000, 0, 0x00000000 }, + { 0x0, 0x02, 0x0, 0x0, 0x0d050000, 0, 0x00000000 }, + { 0x0, 0x03, 0x0, 0x0, 0x0d000000, 0, 0x00000000 }, + { 0x0, 0x04, 0x0, 0x0, 0x20ae0000, 3, 0x000e0000 }, + { 0x0, 0x04, 0x1, 0x0, 0x20ac0000, 2, 0x000c0000 }, + { 0x0, 0x04, 0x2, 0x0, 0x20a80000, 1, 0x00080000 }, + { 0x0, 0x04, 0x3, 0x0, 0x20a00000, 0, 0x00000000 }, + { 0x0, 0x05, 0x0, 0x0, 0x0d2a0000, 0, 0x00000000 }, + { 0x0, 0x06, 0x0, 0x0, 0x0d290000, 0, 0x00000000 }, + { 0x0, 0x07, 0x0, 0x0, 0x0d2c0000, 0, 0x00000000 }, + { 0x0, 0x08, 0x0, 0x0, 0x0d0e0000, 4, 0x00080000 }, + { 0x0, 0x08, 0x1, 0x0, 0x0d060000, 0, 0x00000000 }, + { 0x0, 0x08, 0x2, 0x0, 0x0d080000, 1, 0x00020000 }, + { 0x0, 0x08, 0x3, 0x0, 0x0d0a0000, 2, 0x00040000 }, + { 0x0, 0x08, 0x4, 0x0, 0x0d0c0000, 3, 0x00060000 }, + { 0x0, 0x09, 0x0, 0x0, 0x0d650000, 0, 0x00000000 }, + { 0x0, 0x0a, 0x0, 0x0, 0x20af0000, 0, 0x00000000 }, + { 0x0, 0x0b, 0x0, 0x0, 0x0d3e0000, 0, 0x00000000 }, + { 0x0, 0x0c, 0x0, 0x0, 0x0d3d0000, 0, 0x00000000 }, + { 0x0, 0x0d, 0x0, 0x0, 0x0d1e0000, 0, 0x00000000 }, + { 0x0, 0x0e, 0x0, 0x0, 0x0d150000, 0, 0x00000000 }, + { 0x0, 0x0e, 0x1, 0x0, 0x0d160000, 1, 0x00010000 }, + { 0x0, 0x0e, 0x2, 0x0, 0x0d170000, 2, 0x00020000 }, + { 0x0, 0x0e, 0x3, 0x0, 0x0d180000, 3, 0x00030000 }, + { 0x0, 0x0e, 0x4, 0x0, 0x0d190000, 4, 0x00040000 }, + { 0x0, 0x0e, 0x5, 0x0, 0x0d1a0000, 5, 0x00050000 }, + { 0x0, 0x0e, 0x6, 0x0, 0x0d1b0000, 6, 0x00060000 }, + { 0x0, 0x0e, 0x7, 0x0, 0x0d1c0000, 7, 0x00070000 }, + { 0x0, 0x0e, 0x8, 0x0, 0x0d1d0000, 8, 0x00080000 }, + { 0x0, 0x0f, 0x0, 0x0, 0x0d660000, 0, 0x00000000 }, + { 0x0, 0x10, 0x0, 0x0, 0x0d1f0000, 0, 0x00000000 }, + { 0x0, 0x10, 0x1, 0x0, 0x0d200000, 1, 0x00010000 }, + { 0x0, 0x10, 0x2, 0x0, 0x0d210000, 2, 0x00020000 }, + { 0x0, 0x10, 0x3, 0x0, 0x0d220000, 3, 0x00030000 }, + { 0x0, 0x11, 0x0, 0x0, 0x0d240000, 0, 0x00000000 }, + { 0x0, 0x12, 0x0, 0x0, 0x0d250000, 0, 0x00000000 }, + { 0x0, 0x13, 0x0, 0x0, 0x0d260000, 0, 0x00000000 }, + { 0x0, 0x14, 0x0, 0x0, 0x0d270000, 0, 0x00000000 }, + { 0x0, 0x15, 0x0, 0x0, 0x0d2b0000, 0, 0x00000000 }, + { 0x0, 0x16, 0x0, 0x0, 0x0d280000, 0, 0x00000000 }, + { 0x0, 0x17, 0x0, 0x0, 0x0d0f0000, 0, 0x00000000 }, + { 0x0, 0x17, 0x1, 0x0, 0x0d100000, 1, 0x00010000 }, + { 0x0, 0x17, 0x2, 0x0, 0x0d110000, 2, 0x00020000 }, + { 0x0, 0x17, 0x3, 0x0, 0x0d120000, 3, 0x00030000 }, + { 0x0, 0x17, 0x4, 0x0, 0x0d130000, 4, 0x00040000 }, + { 0x0, 0x17, 0x5, 0x0, 0x0d140000, 5, 0x00050000 }, + { 0x0, 0x18, 0x0, 0x0, 0x0d020000, 0, 0x00000000 }, + { 0x0, 0x19, 0x0, 0x0, 0x0d030000, 0, 0x00000000 }, + { 0x0, 0x1f, 0x0, 0x0, 0x0d600000, 0, 0x00000000 }, + { 0x0, 0x1f, 0x1, 0x0, 0x00000000, 0, 0x00000000 }, + { 0x1, 0x1a, 0x0, 0x0, 0x40000000, 0, 0x40000000 }, + { 0x1, 0x1a, 0x1, 0x1, 0x80000000, 1, 0x80000000 }, + { 0x1, 0x1a, 0x2, 0x0, 0x00000000, 0, 0x00000000 }, + { 0x2, 0x1c, 0x0, 0x0, 0x0d640000, 0, 0x00000000 }, + { 0x2, 0x1d, 0x0, 0x0, 0x20b00000, 8, 0x20b00000 }, + { 0x2, 0x1d, 0x1, 0x0, 0x20800000, 7, 0x20800000 }, + { 0x2, 0x1d, 0x2, 0x0, 0x20c00000, 9, 0x20c00000 }, + { 0x2, 0x1d, 0x3, 0x0, 0x0d800000, 3, 0x0d800000 }, + { 0x2, 0x1d, 0x4, 0x0, 0x20000000, 6, 0x20000000 }, + { 0x2, 0x1d, 0x5, 0x0, 0x0c000000, 2, 0x0c000000 }, + { 0x2, 0x1d, 0x6, 0x0, 0x21000000, 10, 0x21000000 }, + { 0x2, 0x1d, 0x7, 0x0, 0x0e000000, 4, 0x0e000000 }, + { 0x2, 0x1d, 0x8, 0x0, 0x22000000, 11, 0x22000000 }, + { 0x2, 0x1d, 0x9, 0x0, 0x08000000, 1, 0x08000000 }, + { 0x2, 0x1d, 0xa, 0x0, 0x24000000, 12, 0x24000000 }, + { 0x2, 0x1d, 0xb, 0x0, 0x00000000, 0, 0x00000000 }, + { 0x2, 0x1d, 0xc, 0x0, 0x28000000, 13, 0x28000000 }, + { 0x2, 0x1d, 0xd, 0x0, 0x10000000, 5, 0x10000000 }, + { 0x2, 0x1d, 0xe, 0x0, 0x30000000, 14, 0x30000000 }, + { 0x2, 0x00, 0x0, 0x0, 0x0d230000, 0, 0x00000000 }, + { 0x2, 0x01, 0x0, 0x0, 0x0d040000, 0, 0x00000000 }, + { 0x2, 0x02, 0x0, 0x0, 0x0d050000, 0, 0x00000000 }, + { 0x2, 0x03, 0x0, 0x0, 0x0d000000, 0, 0x00000000 }, + { 0x2, 0x04, 0x0, 0x0, 0x20ae0000, 3, 0x000e0000 }, + { 0x2, 0x04, 0x1, 0x0, 0x20ac0000, 2, 0x000c0000 }, + { 0x2, 0x04, 0x2, 0x0, 0x20a80000, 1, 0x00080000 }, + { 0x2, 0x04, 0x3, 0x0, 0x20a00000, 0, 0x00000000 }, + { 0x2, 0x05, 0x0, 0x0, 0x0d2a0000, 0, 0x00000000 }, + { 0x2, 0x06, 0x0, 0x0, 0x0d290000, 0, 0x00000000 }, + { 0x2, 0x07, 0x0, 0x0, 0x0d2c0000, 0, 0x00000000 }, + { 0x2, 0x08, 0x0, 0x0, 0x0d0e0000, 4, 0x00080000 }, + { 0x2, 0x08, 0x1, 0x0, 0x0d060000, 0, 0x00000000 }, + { 0x2, 0x08, 0x2, 0x0, 0x0d080000, 1, 0x00020000 }, + { 0x2, 0x08, 0x3, 0x0, 0x0d0a0000, 2, 0x00040000 }, + { 0x2, 0x08, 0x4, 0x0, 0x0d0c0000, 3, 0x00060000 }, + { 0x2, 0x09, 0x0, 0x0, 0x0d650000, 0, 0x00000000 }, + { 0x2, 0x0a, 0x0, 0x0, 0x20af0000, 0, 0x00000000 }, + { 0x2, 0x0b, 0x0, 0x0, 0x0d3e0000, 0, 0x00000000 }, + { 0x2, 0x0c, 0x0, 0x0, 0x0d3d0000, 0, 0x00000000 }, + { 0x2, 0x0d, 0x0, 0x0, 0x0d1e0000, 0, 0x00000000 }, + { 0x2, 0x0e, 0x0, 0x0, 0x0d150000, 0, 0x00000000 }, + { 0x2, 0x0e, 0x1, 0x0, 0x0d160000, 1, 0x00010000 }, + { 0x2, 0x0e, 0x2, 0x0, 0x0d170000, 2, 0x00020000 }, + { 0x2, 0x0e, 0x3, 0x0, 0x0d180000, 3, 0x00030000 }, + { 0x2, 0x0e, 0x4, 0x0, 0x0d190000, 4, 0x00040000 }, + { 0x2, 0x0e, 0x5, 0x0, 0x0d1a0000, 5, 0x00050000 }, + { 0x2, 0x0e, 0x6, 0x0, 0x0d1b0000, 6, 0x00060000 }, + { 0x2, 0x0e, 0x7, 0x0, 0x0d1c0000, 7, 0x00070000 }, + { 0x2, 0x0e, 0x8, 0x0, 0x0d1d0000, 8, 0x00080000 }, + { 0x2, 0x0f, 0x0, 0x0, 0x0d660000, 0, 0x00000000 }, + { 0x2, 0x10, 0x0, 0x0, 0x0d1f0000, 0, 0x00000000 }, + { 0x2, 0x10, 0x1, 0x0, 0x0d200000, 1, 0x00010000 }, + { 0x2, 0x10, 0x2, 0x0, 0x0d210000, 2, 0x00020000 }, + { 0x2, 0x10, 0x3, 0x0, 0x0d220000, 3, 0x00030000 }, + { 0x2, 0x11, 0x0, 0x0, 0x0d240000, 0, 0x00000000 }, + { 0x2, 0x12, 0x0, 0x0, 0x0d250000, 0, 0x00000000 }, + { 0x2, 0x13, 0x0, 0x0, 0x0d260000, 0, 0x00000000 }, + { 0x2, 0x14, 0x0, 0x0, 0x0d270000, 0, 0x00000000 }, + { 0x2, 0x15, 0x0, 0x0, 0x0d2b0000, 0, 0x00000000 }, + { 0x2, 0x16, 0x0, 0x0, 0x0d280000, 0, 0x00000000 }, + { 0x2, 0x17, 0x0, 0x0, 0x0d0f0000, 0, 0x00000000 }, + { 0x2, 0x17, 0x1, 0x0, 0x0d100000, 1, 0x00010000 }, + { 0x2, 0x17, 0x2, 0x0, 0x0d110000, 2, 0x00020000 }, + { 0x2, 0x17, 0x3, 0x0, 0x0d120000, 3, 0x00030000 }, + { 0x2, 0x17, 0x4, 0x0, 0x0d130000, 4, 0x00040000 }, + { 0x2, 0x17, 0x5, 0x0, 0x0d140000, 5, 0x00050000 }, + { 0x2, 0x18, 0x0, 0x0, 0x0d020000, 0, 0x00000000 }, + { 0x2, 0x19, 0x0, 0x0, 0x0d030000, 0, 0x00000000 }, + { 0x2, 0x1f, 0x0, 0x0, 0x0d600000, 0, 0x00000000 }, + { 0x2, 0x1f, 0x1, 0x0, 0x00000000, 0, 0x00000000 }, + { 0x3, 0x1b, 0x0, 0x0, 0x40000000, 0, 0x40000000 }, + { 0x3, 0x1b, 0x1, 0x1, 0x80000000, 1, 0x80000000 }, + { 0x3, 0x1c, 0x0, 0x2, 0x0d640000, 0, 0x00000000 }, + { 0x3, 0x1d, 0x0, 0x2, 0x20b00000, 8, 0x20b00000 }, + { 0x3, 0x1d, 0x1, 0x2, 0x20800000, 7, 0x20800000 }, + { 0x3, 0x1d, 0x2, 0x2, 0x20c00000, 9, 0x20c00000 }, + { 0x3, 0x1d, 0x3, 0x2, 0x0d800000, 3, 0x0d800000 }, + { 0x3, 0x1d, 0x4, 0x2, 0x20000000, 6, 0x20000000 }, + { 0x3, 0x1d, 0x5, 0x2, 0x0c000000, 2, 0x0c000000 }, + { 0x3, 0x1d, 0x6, 0x2, 0x21000000, 10, 0x21000000 }, + { 0x3, 0x1d, 0x7, 0x2, 0x0e000000, 4, 0x0e000000 }, + { 0x3, 0x1d, 0x8, 0x2, 0x22000000, 11, 0x22000000 }, + { 0x3, 0x1d, 0x9, 0x2, 0x08000000, 1, 0x08000000 }, + { 0x3, 0x1d, 0xa, 0x2, 0x24000000, 12, 0x24000000 }, + { 0x3, 0x1d, 0xb, 0x2, 0x00000000, 0, 0x00000000 }, + { 0x3, 0x1d, 0xc, 0x2, 0x28000000, 13, 0x28000000 }, + { 0x3, 0x1d, 0xd, 0x2, 0x10000000, 5, 0x10000000 }, + { 0x3, 0x1d, 0xe, 0x2, 0x30000000, 14, 0x30000000 }, + { 0x3, 0x1e, 0x0, 0x2, 0x0d400000, 0, 0x0d400000 }, + { 0x3, 0x00, 0x0, 0x2, 0x0d230000, 0, 0x00000000 }, + { 0x3, 0x01, 0x0, 0x2, 0x0d040000, 0, 0x00000000 }, + { 0x3, 0x02, 0x0, 0x2, 0x0d050000, 0, 0x00000000 }, + { 0x3, 0x03, 0x0, 0x2, 0x0d000000, 0, 0x00000000 }, + { 0x3, 0x04, 0x0, 0x2, 0x20ae0000, 3, 0x000e0000 }, + { 0x3, 0x04, 0x1, 0x2, 0x20ac0000, 2, 0x000c0000 }, + { 0x3, 0x04, 0x2, 0x2, 0x20a80000, 1, 0x00080000 }, + { 0x3, 0x04, 0x3, 0x2, 0x20a00000, 0, 0x00000000 }, + { 0x3, 0x05, 0x0, 0x2, 0x0d2a0000, 0, 0x00000000 }, + { 0x3, 0x06, 0x0, 0x2, 0x0d290000, 0, 0x00000000 }, + { 0x3, 0x07, 0x0, 0x2, 0x0d2c0000, 0, 0x00000000 }, + { 0x3, 0x08, 0x0, 0x2, 0x0d0e0000, 4, 0x00080000 }, + { 0x3, 0x08, 0x1, 0x2, 0x0d060000, 0, 0x00000000 }, + { 0x3, 0x08, 0x2, 0x2, 0x0d080000, 1, 0x00020000 }, + { 0x3, 0x08, 0x3, 0x2, 0x0d0a0000, 2, 0x00040000 }, + { 0x3, 0x08, 0x4, 0x2, 0x0d0c0000, 3, 0x00060000 }, + { 0x3, 0x09, 0x0, 0x2, 0x0d650000, 0, 0x00000000 }, + { 0x3, 0x0a, 0x0, 0x2, 0x20af0000, 0, 0x00000000 }, + { 0x3, 0x0b, 0x0, 0x2, 0x0d3e0000, 0, 0x00000000 }, + { 0x3, 0x0c, 0x0, 0x2, 0x0d3d0000, 0, 0x00000000 }, + { 0x3, 0x0d, 0x0, 0x2, 0x0d1e0000, 0, 0x00000000 }, + { 0x3, 0x0e, 0x0, 0x2, 0x0d150000, 0, 0x00000000 }, + { 0x3, 0x0e, 0x1, 0x2, 0x0d160000, 1, 0x00010000 }, + { 0x3, 0x0e, 0x2, 0x2, 0x0d170000, 2, 0x00020000 }, + { 0x3, 0x0e, 0x3, 0x2, 0x0d180000, 3, 0x00030000 }, + { 0x3, 0x0e, 0x4, 0x2, 0x0d190000, 4, 0x00040000 }, + { 0x3, 0x0e, 0x5, 0x2, 0x0d1a0000, 5, 0x00050000 }, + { 0x3, 0x0e, 0x6, 0x2, 0x0d1b0000, 6, 0x00060000 }, + { 0x3, 0x0e, 0x7, 0x2, 0x0d1c0000, 7, 0x00070000 }, + { 0x3, 0x0e, 0x8, 0x2, 0x0d1d0000, 8, 0x00080000 }, + { 0x3, 0x0f, 0x0, 0x2, 0x0d660000, 0, 0x00000000 }, + { 0x3, 0x10, 0x0, 0x2, 0x0d1f0000, 0, 0x00000000 }, + { 0x3, 0x10, 0x1, 0x2, 0x0d200000, 1, 0x00010000 }, + { 0x3, 0x10, 0x2, 0x2, 0x0d210000, 2, 0x00020000 }, + { 0x3, 0x10, 0x3, 0x2, 0x0d220000, 3, 0x00030000 }, + { 0x3, 0x11, 0x0, 0x2, 0x0d240000, 0, 0x00000000 }, + { 0x3, 0x12, 0x0, 0x2, 0x0d250000, 0, 0x00000000 }, + { 0x3, 0x13, 0x0, 0x2, 0x0d260000, 0, 0x00000000 }, + { 0x3, 0x14, 0x0, 0x2, 0x0d270000, 0, 0x00000000 }, + { 0x3, 0x15, 0x0, 0x2, 0x0d2b0000, 0, 0x00000000 }, + { 0x3, 0x16, 0x0, 0x2, 0x0d280000, 0, 0x00000000 }, + { 0x3, 0x17, 0x0, 0x2, 0x0d0f0000, 0, 0x00000000 }, + { 0x3, 0x17, 0x1, 0x2, 0x0d100000, 1, 0x00010000 }, + { 0x3, 0x17, 0x2, 0x2, 0x0d110000, 2, 0x00020000 }, + { 0x3, 0x17, 0x3, 0x2, 0x0d120000, 3, 0x00030000 }, + { 0x3, 0x17, 0x4, 0x2, 0x0d130000, 4, 0x00040000 }, + { 0x3, 0x17, 0x5, 0x2, 0x0d140000, 5, 0x00050000 }, + { 0x3, 0x18, 0x0, 0x2, 0x0d020000, 0, 0x00000000 }, + { 0x3, 0x19, 0x0, 0x2, 0x0d030000, 0, 0x00000000 }, + { 0x3, 0x1f, 0x0, 0x2, 0x0d600000, 0, 0x00000000 }, + { 0x3, 0x1f, 0x1, 0x0, 0x00000000, 0, 0x00000000 }, + { 0x4, 0x1b, 0x0, 0x0, 0x40000000, 0, 0x40000000 }, + { 0x4, 0x1b, 0x1, 0x1, 0x80000000, 1, 0x80000000 }, + { 0x4, 0x1e, 0x0, 0x2, 0x0d400000, 0, 0x0d400000 }, + { 0x4, 0x1e, 0x1, 0x0, 0x00000000, 0, 0x00000000 }, + { 0x5, 0x1c, 0x0, 0x0, 0x0d640000, 0, 0x00000000 }, + { 0x5, 0x1d, 0x0, 0x0, 0x20b00000, 8, 0x20b00000 }, + { 0x5, 0x1d, 0x1, 0x0, 0x20800000, 7, 0x20800000 }, + { 0x5, 0x1d, 0x2, 0x0, 0x20c00000, 9, 0x20c00000 }, + { 0x5, 0x1d, 0x3, 0x0, 0x0d800000, 3, 0x0d800000 }, + { 0x5, 0x1d, 0x4, 0x0, 0x20000000, 6, 0x20000000 }, + { 0x5, 0x1d, 0x5, 0x0, 0x0c000000, 2, 0x0c000000 }, + { 0x5, 0x1d, 0x6, 0x0, 0x21000000, 10, 0x21000000 }, + { 0x5, 0x1d, 0x7, 0x0, 0x0e000000, 4, 0x0e000000 }, + { 0x5, 0x1d, 0x8, 0x0, 0x22000000, 11, 0x22000000 }, + { 0x5, 0x1d, 0x9, 0x0, 0x08000000, 1, 0x08000000 }, + { 0x5, 0x1d, 0xa, 0x0, 0x24000000, 12, 0x24000000 }, + { 0x5, 0x1d, 0xb, 0x0, 0x00000000, 0, 0x00000000 }, + { 0x5, 0x1d, 0xc, 0x0, 0x28000000, 13, 0x28000000 }, + { 0x5, 0x1d, 0xd, 0x0, 0x10000000, 5, 0x10000000 }, + { 0x5, 0x1d, 0xe, 0x0, 0x30000000, 14, 0x30000000 }, + { 0x5, 0x00, 0x0, 0x0, 0x0d230000, 0, 0x00000000 }, + { 0x5, 0x01, 0x0, 0x0, 0x0d040000, 0, 0x00000000 }, + { 0x5, 0x02, 0x0, 0x0, 0x0d050000, 0, 0x00000000 }, + { 0x5, 0x03, 0x0, 0x0, 0x0d000000, 0, 0x00000000 }, + { 0x5, 0x04, 0x0, 0x0, 0x20ae0000, 3, 0x000e0000 }, + { 0x5, 0x04, 0x1, 0x0, 0x20ac0000, 2, 0x000c0000 }, + { 0x5, 0x04, 0x2, 0x0, 0x20a80000, 1, 0x00080000 }, + { 0x5, 0x04, 0x3, 0x0, 0x20a00000, 0, 0x00000000 }, + { 0x5, 0x05, 0x0, 0x0, 0x0d2a0000, 0, 0x00000000 }, + { 0x5, 0x06, 0x0, 0x0, 0x0d290000, 0, 0x00000000 }, + { 0x5, 0x07, 0x0, 0x0, 0x0d2c0000, 0, 0x00000000 }, + { 0x5, 0x08, 0x0, 0x0, 0x0d0e0000, 4, 0x00080000 }, + { 0x5, 0x08, 0x1, 0x0, 0x0d060000, 0, 0x00000000 }, + { 0x5, 0x08, 0x2, 0x0, 0x0d080000, 1, 0x00020000 }, + { 0x5, 0x08, 0x3, 0x0, 0x0d0a0000, 2, 0x00040000 }, + { 0x5, 0x08, 0x4, 0x0, 0x0d0c0000, 3, 0x00060000 }, + { 0x5, 0x09, 0x0, 0x0, 0x0d650000, 0, 0x00000000 }, + { 0x5, 0x0a, 0x0, 0x0, 0x20af0000, 0, 0x00000000 }, + { 0x5, 0x0b, 0x0, 0x0, 0x0d3e0000, 0, 0x00000000 }, + { 0x5, 0x0c, 0x0, 0x0, 0x0d3d0000, 0, 0x00000000 }, + { 0x5, 0x0d, 0x0, 0x0, 0x0d1e0000, 0, 0x00000000 }, + { 0x5, 0x0e, 0x0, 0x0, 0x0d150000, 0, 0x00000000 }, + { 0x5, 0x0e, 0x1, 0x0, 0x0d160000, 1, 0x00010000 }, + { 0x5, 0x0e, 0x2, 0x0, 0x0d170000, 2, 0x00020000 }, + { 0x5, 0x0e, 0x3, 0x0, 0x0d180000, 3, 0x00030000 }, + { 0x5, 0x0e, 0x4, 0x0, 0x0d190000, 4, 0x00040000 }, + { 0x5, 0x0e, 0x5, 0x0, 0x0d1a0000, 5, 0x00050000 }, + { 0x5, 0x0e, 0x6, 0x0, 0x0d1b0000, 6, 0x00060000 }, + { 0x5, 0x0e, 0x7, 0x0, 0x0d1c0000, 7, 0x00070000 }, + { 0x5, 0x0e, 0x8, 0x0, 0x0d1d0000, 8, 0x00080000 }, + { 0x5, 0x0f, 0x0, 0x0, 0x0d660000, 0, 0x00000000 }, + { 0x5, 0x10, 0x0, 0x0, 0x0d1f0000, 0, 0x00000000 }, + { 0x5, 0x10, 0x1, 0x0, 0x0d200000, 1, 0x00010000 }, + { 0x5, 0x10, 0x2, 0x0, 0x0d210000, 2, 0x00020000 }, + { 0x5, 0x10, 0x3, 0x0, 0x0d220000, 3, 0x00030000 }, + { 0x5, 0x11, 0x0, 0x0, 0x0d240000, 0, 0x00000000 }, + { 0x5, 0x12, 0x0, 0x0, 0x0d250000, 0, 0x00000000 }, + { 0x5, 0x13, 0x0, 0x0, 0x0d260000, 0, 0x00000000 }, + { 0x5, 0x14, 0x0, 0x0, 0x0d270000, 0, 0x00000000 }, + { 0x5, 0x15, 0x0, 0x0, 0x0d2b0000, 0, 0x00000000 }, + { 0x5, 0x16, 0x0, 0x0, 0x0d280000, 0, 0x00000000 }, + { 0x5, 0x17, 0x0, 0x0, 0x0d0f0000, 0, 0x00000000 }, + { 0x5, 0x17, 0x1, 0x0, 0x0d100000, 1, 0x00010000 }, + { 0x5, 0x17, 0x2, 0x0, 0x0d110000, 2, 0x00020000 }, + { 0x5, 0x17, 0x3, 0x0, 0x0d120000, 3, 0x00030000 }, + { 0x5, 0x17, 0x4, 0x0, 0x0d130000, 4, 0x00040000 }, + { 0x5, 0x17, 0x5, 0x0, 0x0d140000, 5, 0x00050000 }, + { 0x5, 0x18, 0x0, 0x0, 0x0d020000, 0, 0x00000000 }, + { 0x5, 0x19, 0x0, 0x0, 0x0d030000, 0, 0x00000000 }, + { 0x5, 0x1f, 0x0, 0x0, 0x0d600000, 0, 0x00000000 }, + { 0x5, 0x1f, 0x1, 0x0, 0x00000000, 0, 0x00000000 } +}; + +/* + * AON NOC aperture lookup table as per file "AON_NOC_Structure.info". + */ +static const char * const tegra194_aonnoc_routeid_initflow[] = { + [0x0] = "cbb_i/I/0", + [0x1] = "cpu_p_i/I/0", + [0x2] = "dma_m_i/I/0", + [0x3] = "dma_p_i/I/0" +}; + +static const char * const tegra194_aonnoc_routeid_targflow[] = { + [0x00] = "multiport1_t/T/aon_misc", + [0x01] = "multiport1_t/T/avic0", + [0x02] = "multiport1_t/T/avic1", + [0x03] = "multiport1_t/T/can1", + [0x04] = "multiport1_t/T/can2", + [0x05] = "multiport1_t/T/dma", + [0x06] = "multiport1_t/T/dmic", + [0x07] = "multiport1_t/T/err_collator", + [0x08] = "multiport1_t/T/fpga_misc", + [0x09] = "multiport1_t/T/gte", + [0x0a] = "multiport1_t/T/hsp", + [0x0b] = "multiport1_t/T/i2c2", + [0x0c] = "multiport1_t/T/i2c8", + [0x0d] = "multiport1_t/T/pwm", + [0x0e] = "multiport1_t/T/spi2", + [0x0f] = "multiport1_t/T/tke", + [0x10] = "multiport1_t/T/uartg", + [0x11] = "RESERVED", + [0x12] = "RESERVED", + [0x13] = "RESERVED", + [0x14] = "RESERVED", + [0x15] = "RESERVED", + [0x16] = "RESERVED", + [0x17] = "RESERVED", + [0x18] = "RESERVED", + [0x19] = "RESERVED", + [0x1a] = "RESERVED", + [0x1b] = "RESERVED", + [0x1c] = "RESERVED", + [0x1d] = "RESERVED", + [0x1e] = "RESERVED", + [0x1f] = "RESERVED", + [0x20] = "multiport0_t/T/aovc", + [0x21] = "multiport0_t/T/atcm", + [0x22] = "multiport0_t/T/cast", + [0x23] = "multiport0_t/T/dast", + [0x24] = "multiport0_t/T/err_collator_car", + [0x25] = "multiport0_t/T/gpio", + [0x26] = "multiport0_t/T/i2c10", + [0x27] = "multiport0_t/T/mss", + [0x28] = "multiport0_t/T/padctl_a12", + [0x29] = "multiport0_t/T/padctl_a14", + [0x2a] = "multiport0_t/T/padctl_a15", + [0x2b] = "multiport0_t/T/rtc", + [0x2c] = "multiport0_t/T/tsc", + [0x2d] = "RESERVED", + [0x2e] = "RESERVED", + [0x2f] = "RESERVED", + [0x30] = "multiport2_t/T/aon_vref_ro", + [0x31] = "multiport2_t/T/aopm", + [0x32] = "multiport2_t/T/car", + [0x33] = "multiport2_t/T/pmc", + [0x34] = "ast1_t/T/0", + [0x35] = "cbb_t/T/0", + [0x36] = "cpu_t/T/0", + [0x37] = "firewall_t/T/0", + [0x38] = "svc_t/T/0", + [0x39] = "uartc/T/uartc", + [0x3a] = "RESERVED", + [0x3b] = "RESERVED", + [0x3c] = "RESERVED", + [0x3d] = "RESERVED", + [0x3e] = "RESERVED", + [0x3f] = "RESERVED" +}; + +/* + * Fields of AON NOC lookup table: + * Init flow, Targ flow, Targ subrange, Init mapping, Init localAddress, + * Targ mapping, Targ localAddress + * ---------------------------------------------------------------------------- + */ +static const struct tegra194_cbb_aperture tegra194_aonnoc_aperture_lookup[] = { + { 0x0, 0x37, 0x00, 0, 0x0c640000, 0, 0x00000000 }, + { 0x0, 0x20, 0x00, 0, 0x0c3b0000, 0, 0x00000000 }, + { 0x0, 0x21, 0x00, 0, 0x0c000000, 0, 0x00000000 }, + { 0x0, 0x22, 0x00, 0, 0x0c040000, 0, 0x00000000 }, + { 0x0, 0x23, 0x00, 0, 0x0c050000, 0, 0x00000000 }, + { 0x0, 0x24, 0x00, 0, 0x20cf0000, 0, 0x00000000 }, + { 0x0, 0x25, 0x00, 0, 0x0c2f0000, 0, 0x00000000 }, + { 0x0, 0x26, 0x00, 0, 0x0c230000, 0, 0x00000000 }, + { 0x0, 0x27, 0x00, 0, 0x0c350000, 0, 0x00000000 }, + { 0x0, 0x28, 0x00, 0, 0x0c301000, 0, 0x00000000 }, + { 0x0, 0x29, 0x00, 0, 0x0c302000, 0, 0x00000000 }, + { 0x0, 0x2a, 0x00, 0, 0x0c303000, 0, 0x00000000 }, + { 0x0, 0x2b, 0x00, 0, 0x0c2a0000, 0, 0x00000000 }, + { 0x0, 0x2c, 0x00, 0, 0x0c2b0000, 0, 0x00000000 }, + { 0x0, 0x2c, 0x01, 0, 0x0c2c0000, 1, 0x00010000 }, + { 0x0, 0x2c, 0x02, 0, 0x0c2d0000, 2, 0x00020000 }, + { 0x0, 0x2c, 0x03, 0, 0x0c2e0000, 3, 0x00030000 }, + { 0x0, 0x00, 0x00, 0, 0x0c660000, 0, 0x00000000 }, + { 0x0, 0x01, 0x00, 0, 0x0c020000, 0, 0x00000000 }, + { 0x0, 0x02, 0x00, 0, 0x0c030000, 0, 0x00000000 }, + { 0x0, 0x03, 0x00, 0, 0x0c310000, 0, 0x00000000 }, + { 0x0, 0x04, 0x00, 0, 0x0c320000, 0, 0x00000000 }, + { 0x0, 0x05, 0x00, 0, 0x0c0a0000, 2, 0x00040000 }, + { 0x0, 0x05, 0x01, 0, 0x0c0b0000, 3, 0x00050000 }, + { 0x0, 0x05, 0x02, 0, 0x0c0e0000, 5, 0x00080000 }, + { 0x0, 0x05, 0x03, 0, 0x0c060000, 0, 0x00000000 }, + { 0x0, 0x05, 0x04, 0, 0x0c080000, 1, 0x00020000 }, + { 0x0, 0x05, 0x05, 0, 0x0c0c0000, 4, 0x00060000 }, + { 0x0, 0x06, 0x00, 0, 0x0c330000, 0, 0x00000000 }, + { 0x0, 0x07, 0x00, 0, 0x0c650000, 0, 0x00000000 }, + { 0x0, 0x08, 0x00, 0, 0x0c3e0000, 0, 0x00000000 }, + { 0x0, 0x09, 0x00, 0, 0x0c1e0000, 0, 0x00000000 }, + { 0x0, 0x0a, 0x00, 0, 0x0c150000, 0, 0x00000000 }, + { 0x0, 0x0a, 0x01, 0, 0x0c160000, 1, 0x00010000 }, + { 0x0, 0x0a, 0x02, 0, 0x0c170000, 2, 0x00020000 }, + { 0x0, 0x0a, 0x03, 0, 0x0c180000, 3, 0x00030000 }, + { 0x0, 0x0a, 0x04, 0, 0x0c190000, 4, 0x00040000 }, + { 0x0, 0x0a, 0x05, 0, 0x0c1a0000, 5, 0x00050000 }, + { 0x0, 0x0a, 0x06, 0, 0x0c1b0000, 6, 0x00060000 }, + { 0x0, 0x0a, 0x07, 0, 0x0c1c0000, 7, 0x00070000 }, + { 0x0, 0x0a, 0x08, 0, 0x0c1d0000, 8, 0x00080000 }, + { 0x0, 0x0b, 0x00, 0, 0x0c240000, 0, 0x00000000 }, + { 0x0, 0x0c, 0x00, 0, 0x0c250000, 0, 0x00000000 }, + { 0x0, 0x0d, 0x00, 0, 0x0c340000, 0, 0x00000000 }, + { 0x0, 0x0e, 0x00, 0, 0x0c260000, 0, 0x00000000 }, + { 0x0, 0x0f, 0x00, 0, 0x0c0f0000, 0, 0x00000000 }, + { 0x0, 0x0f, 0x01, 0, 0x0c100000, 1, 0x00010000 }, + { 0x0, 0x0f, 0x02, 0, 0x0c110000, 2, 0x00020000 }, + { 0x0, 0x0f, 0x03, 0, 0x0c120000, 3, 0x00030000 }, + { 0x0, 0x0f, 0x04, 0, 0x0c130000, 4, 0x00040000 }, + { 0x0, 0x0f, 0x05, 0, 0x0c140000, 5, 0x00050000 }, + { 0x0, 0x10, 0x00, 0, 0x0c290000, 0, 0x00000000 }, + { 0x0, 0x30, 0x00, 0, 0x20ce0000, 0, 0x00000000 }, + { 0x0, 0x31, 0x00, 0, 0x0c1f0000, 0, 0x00000000 }, + { 0x0, 0x31, 0x01, 0, 0x0c200000, 1, 0x00010000 }, + { 0x0, 0x31, 0x02, 0, 0x0c210000, 2, 0x00020000 }, + { 0x0, 0x31, 0x03, 0, 0x0c220000, 3, 0x00030000 }, + { 0x0, 0x32, 0x00, 0, 0x20cc0000, 3, 0x001c0000 }, + { 0x0, 0x32, 0x01, 0, 0x20c80000, 2, 0x00180000 }, + { 0x0, 0x32, 0x02, 0, 0x20c00000, 1, 0x00100000 }, + { 0x0, 0x32, 0x03, 0, 0x20b00000, 0, 0x00000000 }, + { 0x0, 0x33, 0x00, 0, 0x0c360000, 0, 0x00000000 }, + { 0x0, 0x33, 0x01, 0, 0x0c370000, 1, 0x00010000 }, + { 0x0, 0x33, 0x02, 0, 0x0c3a0000, 3, 0x00040000 }, + { 0x0, 0x33, 0x03, 0, 0x0c380000, 2, 0x00020000 }, + { 0x0, 0x38, 0x00, 0, 0x0c600000, 0, 0x00000000 }, + { 0x0, 0x38, 0x01, 0, 0x00000000, 0, 0x00000000 }, + { 0x0, 0x39, 0x00, 0, 0x0c280000, 0, 0x00000000 }, + { 0x1, 0x35, 0x00, 0, 0x00000000, 0, 0x00000000 }, + { 0x1, 0x35, 0x01, 0, 0x00100000, 1, 0x00100000 }, + { 0x1, 0x35, 0x02, 0, 0x05a00000, 11, 0x05a00000 }, + { 0x1, 0x35, 0x03, 0, 0x05b00000, 32, 0x05b00000 }, + { 0x1, 0x35, 0x04, 0, 0x05c00000, 33, 0x05c00000 }, + { 0x1, 0x35, 0x05, 0, 0x05d00000, 12, 0x05d00000 }, + { 0x1, 0x35, 0x06, 0, 0x20000000, 19, 0x20000000 }, + { 0x1, 0x35, 0x07, 0, 0x20100000, 20, 0x20100000 }, + { 0x1, 0x35, 0x08, 0, 0x20a00000, 24, 0x20a00000 }, + { 0x1, 0x35, 0x09, 0, 0x20d00000, 25, 0x20d00000 }, + { 0x1, 0x35, 0x0a, 0, 0x00200000, 2, 0x00200000 }, + { 0x1, 0x35, 0x0b, 0, 0x05800000, 10, 0x05800000 }, + { 0x1, 0x35, 0x0c, 0, 0x05e00000, 13, 0x05e00000 }, + { 0x1, 0x35, 0x0d, 0, 0x20200000, 21, 0x20200000 }, + { 0x1, 0x35, 0x0e, 0, 0x20800000, 23, 0x20800000 }, + { 0x1, 0x35, 0x0f, 0, 0x20e00000, 26, 0x20e00000 }, + { 0x1, 0x35, 0x10, 0, 0x00400000, 3, 0x00400000 }, + { 0x1, 0x35, 0x11, 0, 0x20400000, 22, 0x20400000 }, + { 0x1, 0x35, 0x12, 0, 0x00800000, 4, 0x00800000 }, + { 0x1, 0x35, 0x13, 0, 0x05000000, 9, 0x05000000 }, + { 0x1, 0x35, 0x14, 0, 0x0c800000, 34, 0x0c800000 }, + { 0x1, 0x35, 0x15, 0, 0x01000000, 5, 0x01000000 }, + { 0x1, 0x35, 0x16, 0, 0x03000000, 7, 0x03000000 }, + { 0x1, 0x35, 0x17, 0, 0x04000000, 8, 0x04000000 }, + { 0x1, 0x35, 0x18, 0, 0x0d000000, 16, 0x0d000000 }, + { 0x1, 0x35, 0x19, 0, 0x21000000, 27, 0x21000000 }, + { 0x1, 0x35, 0x1a, 0, 0x02000000, 6, 0x02000000 }, + { 0x1, 0x35, 0x1b, 0, 0x06000000, 14, 0x06000000 }, + { 0x1, 0x35, 0x1c, 0, 0x0e000000, 17, 0x0e000000 }, + { 0x1, 0x35, 0x1d, 0, 0x22000000, 28, 0x22000000 }, + { 0x1, 0x35, 0x1e, 0, 0x08000000, 15, 0x08000000 }, + { 0x1, 0x35, 0x1f, 0, 0x24000000, 29, 0x24000000 }, + { 0x1, 0x35, 0x20, 0, 0x28000000, 30, 0x28000000 }, + { 0x1, 0x35, 0x21, 0, 0x10000000, 18, 0x10000000 }, + { 0x1, 0x35, 0x22, 0, 0x30000000, 31, 0x30000000 }, + { 0x1, 0x37, 0x00, 0, 0x0c640000, 0, 0x00000000 }, + { 0x1, 0x20, 0x00, 0, 0x0c3b0000, 0, 0x00000000 }, + { 0x1, 0x21, 0x00, 0, 0x0c000000, 0, 0x00000000 }, + { 0x1, 0x22, 0x00, 0, 0x0c040000, 0, 0x00000000 }, + { 0x1, 0x23, 0x00, 0, 0x0c050000, 0, 0x00000000 }, + { 0x1, 0x24, 0x00, 0, 0x20cf0000, 0, 0x00000000 }, + { 0x1, 0x25, 0x00, 0, 0x0c2f0000, 0, 0x00000000 }, + { 0x1, 0x26, 0x00, 0, 0x0c230000, 0, 0x00000000 }, + { 0x1, 0x27, 0x00, 0, 0x0c350000, 0, 0x00000000 }, + { 0x1, 0x28, 0x00, 0, 0x0c301000, 0, 0x00000000 }, + { 0x1, 0x29, 0x00, 0, 0x0c302000, 0, 0x00000000 }, + { 0x1, 0x2a, 0x00, 0, 0x0c303000, 0, 0x00000000 }, + { 0x1, 0x2b, 0x00, 0, 0x0c2a0000, 0, 0x00000000 }, + { 0x1, 0x2c, 0x00, 0, 0x0c2b0000, 0, 0x00000000 }, + { 0x1, 0x2c, 0x01, 0, 0x0c2c0000, 1, 0x00010000 }, + { 0x1, 0x2c, 0x02, 0, 0x0c2d0000, 2, 0x00020000 }, + { 0x1, 0x2c, 0x03, 0, 0x0c2e0000, 3, 0x00030000 }, + { 0x1, 0x00, 0x00, 0, 0x0c660000, 0, 0x00000000 }, + { 0x1, 0x01, 0x00, 0, 0x0c020000, 0, 0x00000000 }, + { 0x1, 0x02, 0x00, 0, 0x0c030000, 0, 0x00000000 }, + { 0x1, 0x03, 0x00, 0, 0x0c310000, 0, 0x00000000 }, + { 0x1, 0x04, 0x00, 0, 0x0c320000, 0, 0x00000000 }, + { 0x1, 0x05, 0x00, 0, 0x0c0a0000, 2, 0x00040000 }, + { 0x1, 0x05, 0x01, 0, 0x0c0b0000, 3, 0x00050000 }, + { 0x1, 0x05, 0x02, 0, 0x0c0e0000, 5, 0x00080000 }, + { 0x1, 0x05, 0x03, 0, 0x0c060000, 0, 0x00000000 }, + { 0x1, 0x05, 0x04, 0, 0x0c080000, 1, 0x00020000 }, + { 0x1, 0x05, 0x05, 0, 0x0c0c0000, 4, 0x00060000 }, + { 0x1, 0x06, 0x00, 0, 0x0c330000, 0, 0x00000000 }, + { 0x1, 0x07, 0x00, 0, 0x0c650000, 0, 0x00000000 }, + { 0x1, 0x08, 0x00, 0, 0x0c3e0000, 0, 0x00000000 }, + { 0x1, 0x09, 0x00, 0, 0x0c1e0000, 0, 0x00000000 }, + { 0x1, 0x0a, 0x00, 0, 0x0c150000, 0, 0x00000000 }, + { 0x1, 0x0a, 0x01, 0, 0x0c160000, 1, 0x00010000 }, + { 0x1, 0x0a, 0x02, 0, 0x0c170000, 2, 0x00020000 }, + { 0x1, 0x0a, 0x03, 0, 0x0c180000, 3, 0x00030000 }, + { 0x1, 0x0a, 0x04, 0, 0x0c190000, 4, 0x00040000 }, + { 0x1, 0x0a, 0x05, 0, 0x0c1a0000, 5, 0x00050000 }, + { 0x1, 0x0a, 0x06, 0, 0x0c1b0000, 6, 0x00060000 }, + { 0x1, 0x0a, 0x07, 0, 0x0c1c0000, 7, 0x00070000 }, + { 0x1, 0x0a, 0x08, 0, 0x0c1d0000, 8, 0x00080000 }, + { 0x1, 0x0b, 0x00, 0, 0x0c240000, 0, 0x00000000 }, + { 0x1, 0x0c, 0x00, 0, 0x0c250000, 0, 0x00000000 }, + { 0x1, 0x0d, 0x00, 0, 0x0c340000, 0, 0x00000000 }, + { 0x1, 0x0e, 0x00, 0, 0x0c260000, 0, 0x00000000 }, + { 0x1, 0x0f, 0x00, 0, 0x0c0f0000, 0, 0x00000000 }, + { 0x1, 0x0f, 0x01, 0, 0x0c100000, 1, 0x00010000 }, + { 0x1, 0x0f, 0x02, 0, 0x0c110000, 2, 0x00020000 }, + { 0x1, 0x0f, 0x03, 0, 0x0c120000, 3, 0x00030000 }, + { 0x1, 0x0f, 0x04, 0, 0x0c130000, 4, 0x00040000 }, + { 0x1, 0x0f, 0x05, 0, 0x0c140000, 5, 0x00050000 }, + { 0x1, 0x10, 0x00, 0, 0x0c290000, 0, 0x00000000 }, + { 0x1, 0x30, 0x00, 0, 0x20ce0000, 0, 0x00000000 }, + { 0x1, 0x31, 0x00, 0, 0x0c1f0000, 0, 0x00000000 }, + { 0x1, 0x31, 0x01, 0, 0x0c200000, 1, 0x00010000 }, + { 0x1, 0x31, 0x02, 0, 0x0c210000, 2, 0x00020000 }, + { 0x1, 0x31, 0x03, 0, 0x0c220000, 3, 0x00030000 }, + { 0x1, 0x32, 0x00, 0, 0x20cc0000, 3, 0x001c0000 }, + { 0x1, 0x32, 0x01, 0, 0x20c80000, 2, 0x00180000 }, + { 0x1, 0x32, 0x02, 0, 0x20c00000, 1, 0x00100000 }, + { 0x1, 0x32, 0x03, 0, 0x20b00000, 0, 0x00000000 }, + { 0x1, 0x33, 0x00, 0, 0x0c360000, 0, 0x00000000 }, + { 0x1, 0x33, 0x01, 0, 0x0c370000, 1, 0x00010000 }, + { 0x1, 0x33, 0x02, 0, 0x0c3a0000, 3, 0x00040000 }, + { 0x1, 0x33, 0x03, 0, 0x0c380000, 2, 0x00020000 }, + { 0x1, 0x38, 0x00, 0, 0x0c600000, 0, 0x00000000 }, + { 0x1, 0x38, 0x01, 0, 0x00000000, 0, 0x00000000 }, + { 0x1, 0x39, 0x00, 0, 0x0c280000, 0, 0x00000000 }, + { 0x2, 0x34, 0x00, 0, 0x40000000, 0, 0x40000000 }, + { 0x2, 0x34, 0x01, 0, 0x80000000, 1, 0x80000000 }, + { 0x2, 0x36, 0x00, 0, 0x0c400000, 0, 0x0c400000 }, + { 0x2, 0x36, 0x01, 0, 0x00000000, 0, 0x00000000 }, + { 0x3, 0x35, 0x00, 0, 0x00000000, 0, 0x00000000 }, + { 0x3, 0x35, 0x01, 0, 0x00100000, 1, 0x00100000 }, + { 0x3, 0x35, 0x02, 0, 0x05a00000, 11, 0x05a00000 }, + { 0x3, 0x35, 0x03, 0, 0x05b00000, 32, 0x05b00000 }, + { 0x3, 0x35, 0x04, 0, 0x05c00000, 33, 0x05c00000 }, + { 0x3, 0x35, 0x05, 0, 0x05d00000, 12, 0x05d00000 }, + { 0x3, 0x35, 0x06, 0, 0x20000000, 19, 0x20000000 }, + { 0x3, 0x35, 0x07, 0, 0x20100000, 20, 0x20100000 }, + { 0x3, 0x35, 0x08, 0, 0x20a00000, 24, 0x20a00000 }, + { 0x3, 0x35, 0x09, 0, 0x20d00000, 25, 0x20d00000 }, + { 0x3, 0x35, 0x0a, 0, 0x00200000, 2, 0x00200000 }, + { 0x3, 0x35, 0x0b, 0, 0x05800000, 10, 0x05800000 }, + { 0x3, 0x35, 0x0c, 0, 0x05e00000, 13, 0x05e00000 }, + { 0x3, 0x35, 0x0d, 0, 0x20200000, 21, 0x20200000 }, + { 0x3, 0x35, 0x0e, 0, 0x20800000, 23, 0x20800000 }, + { 0x3, 0x35, 0x0f, 0, 0x20e00000, 26, 0x20e00000 }, + { 0x3, 0x35, 0x10, 0, 0x00400000, 3, 0x00400000 }, + { 0x3, 0x35, 0x11, 0, 0x20400000, 22, 0x20400000 }, + { 0x3, 0x35, 0x12, 0, 0x00800000, 4, 0x00800000 }, + { 0x3, 0x35, 0x13, 0, 0x50000000, 9, 0x05000000 }, + { 0x3, 0x35, 0x14, 0, 0xc0800000, 34, 0x0c800000 }, + { 0x3, 0x35, 0x15, 0, 0x10000000, 5, 0x01000000 }, + { 0x3, 0x35, 0x16, 0, 0x30000000, 7, 0x03000000 }, + { 0x3, 0x35, 0x17, 0, 0x04000000, 8, 0x04000000 }, + { 0x3, 0x35, 0x18, 0, 0x0d000000, 16, 0x0d000000 }, + { 0x3, 0x35, 0x19, 0, 0x21000000, 27, 0x21000000 }, + { 0x3, 0x35, 0x1a, 0, 0x02000000, 6, 0x02000000 }, + { 0x3, 0x35, 0x1b, 0, 0x06000000, 14, 0x06000000 }, + { 0x3, 0x35, 0x1c, 0, 0x0e000000, 17, 0x0e000000 }, + { 0x3, 0x35, 0x1d, 0, 0x22000000, 28, 0x22000000 }, + { 0x3, 0x35, 0x1e, 0, 0x08000000, 15, 0x08000000 }, + { 0x3, 0x35, 0x1f, 0, 0x24000000, 29, 0x24000000 }, + { 0x3, 0x35, 0x20, 0, 0x28000000, 30, 0x28000000 }, + { 0x3, 0x35, 0x21, 0, 0x10000000, 18, 0x10000000 }, + { 0x3, 0x35, 0x22, 0, 0x30000000, 31, 0x30000000 }, + { 0x3, 0x37, 0x00, 0, 0x0c640000, 0, 0x00000000 }, + { 0x3, 0x20, 0x00, 0, 0x0c3b0000, 0, 0x00000000 }, + { 0x3, 0x21, 0x00, 0, 0x0c000000, 0, 0x00000000 }, + { 0x3, 0x22, 0x00, 0, 0x0c040000, 0, 0x00000000 }, + { 0x3, 0x23, 0x00, 0, 0x0c050000, 0, 0x00000000 }, + { 0x3, 0x24, 0x00, 0, 0x20cf0000, 0, 0x00000000 }, + { 0x3, 0x25, 0x00, 0, 0x0c2f0000, 0, 0x00000000 }, + { 0x3, 0x26, 0x00, 0, 0x0c230000, 0, 0x00000000 }, + { 0x3, 0x27, 0x00, 0, 0x0c350000, 0, 0x00000000 }, + { 0x3, 0x28, 0x00, 0, 0x0c301000, 0, 0x00000000 }, + { 0x3, 0x29, 0x00, 0, 0x0c302000, 0, 0x00000000 }, + { 0x3, 0x2a, 0x00, 0, 0x0c303000, 0, 0x00000000 }, + { 0x3, 0x2b, 0x00, 0, 0x0c2a0000, 0, 0x00000000 }, + { 0x3, 0x2c, 0x00, 0, 0x0c2b0000, 0, 0x00000000 }, + { 0x3, 0x2c, 0x01, 0, 0x0c2c0000, 1, 0x00010000 }, + { 0x3, 0x2c, 0x02, 0, 0x0c2d0000, 2, 0x00020000 }, + { 0x3, 0x2c, 0x03, 0, 0x0c2e0000, 3, 0x00030000 }, + { 0x3, 0x00, 0x00, 0, 0x0c660000, 0, 0x00000000 }, + { 0x3, 0x01, 0x00, 0, 0x0c020000, 0, 0x00000000 }, + { 0x3, 0x02, 0x00, 0, 0x0c030000, 0, 0x00000000 }, + { 0x3, 0x03, 0x00, 0, 0x0c310000, 0, 0x00000000 }, + { 0x3, 0x04, 0x00, 0, 0x0c320000, 0, 0x00000000 }, + { 0x3, 0x05, 0x00, 0, 0x0c0a0000, 2, 0x00040000 }, + { 0x3, 0x05, 0x01, 0, 0x0c0b0000, 3, 0x00050000 }, + { 0x3, 0x05, 0x02, 0, 0x0c0e0000, 5, 0x00080000 }, + { 0x3, 0x05, 0x03, 0, 0x0c060000, 0, 0x00000000 }, + { 0x3, 0x05, 0x04, 0, 0x0c080000, 1, 0x00020000 }, + { 0x3, 0x05, 0x05, 0, 0x0c0c0000, 4, 0x00060000 }, + { 0x3, 0x06, 0x00, 0, 0x0c330000, 0, 0x00000000 }, + { 0x3, 0x07, 0x00, 0, 0x0c650000, 0, 0x00000000 }, + { 0x3, 0x08, 0x00, 0, 0x0c3e0000, 0, 0x00000000 }, + { 0x3, 0x09, 0x00, 0, 0x0c1e0000, 0, 0x00000000 }, + { 0x3, 0x0a, 0x00, 0, 0x0c150000, 0, 0x00000000 }, + { 0x3, 0x0a, 0x01, 0, 0x0c160000, 1, 0x00010000 }, + { 0x3, 0x0a, 0x02, 0, 0x0c170000, 2, 0x00020000 }, + { 0x3, 0x0a, 0x03, 0, 0x0c180000, 3, 0x00030000 }, + { 0x3, 0x0a, 0x04, 0, 0x0c190000, 4, 0x00040000 }, + { 0x3, 0x0a, 0x05, 0, 0x0c1a0000, 5, 0x00050000 }, + { 0x3, 0x0a, 0x06, 0, 0x0c1b0000, 6, 0x00060000 }, + { 0x3, 0x0a, 0x07, 0, 0x0c1c0000, 7, 0x00070000 }, + { 0x3, 0x0a, 0x08, 0, 0x0c1d0000, 8, 0x00080000 }, + { 0x3, 0x0b, 0x00, 0, 0x0c240000, 0, 0x00000000 }, + { 0x3, 0x0c, 0x00, 0, 0x0c250000, 0, 0x00000000 }, + { 0x3, 0x0d, 0x00, 0, 0x0c340000, 0, 0x00000000 }, + { 0x3, 0x0e, 0x00, 0, 0x0c260000, 0, 0x00000000 }, + { 0x3, 0x0f, 0x00, 0, 0x0c0f0000, 0, 0x00000000 }, + { 0x3, 0x0f, 0x01, 0, 0x0c100000, 1, 0x00010000 }, + { 0x3, 0x0f, 0x02, 0, 0x0c110000, 2, 0x00020000 }, + { 0x3, 0x0f, 0x03, 0, 0x0c120000, 3, 0x00030000 }, + { 0x3, 0x0f, 0x04, 0, 0x0c130000, 4, 0x00040000 }, + { 0x3, 0x0f, 0x05, 0, 0x0c140000, 5, 0x00050000 }, + { 0x3, 0x10, 0x00, 0, 0x0c290000, 0, 0x00000000 }, + { 0x3, 0x30, 0x00, 0, 0x20ce0000, 0, 0x00000000 }, + { 0x3, 0x31, 0x00, 0, 0x0c1f0000, 0, 0x00000000 }, + { 0x3, 0x31, 0x01, 0, 0x0c200000, 1, 0x00010000 }, + { 0x3, 0x31, 0x02, 0, 0x0c210000, 2, 0x00020000 }, + { 0x3, 0x31, 0x03, 0, 0x0c220000, 3, 0x00030000 }, + { 0x3, 0x32, 0x00, 0, 0x20cc0000, 3, 0x001c0000 }, + { 0x3, 0x32, 0x01, 0, 0x20c80000, 2, 0x00180000 }, + { 0x3, 0x32, 0x02, 0, 0x20c00000, 1, 0x00100000 }, + { 0x3, 0x32, 0x03, 0, 0x20b00000, 0, 0x00000000 }, + { 0x3, 0x33, 0x00, 0, 0x0c360000, 0, 0x00000000 }, + { 0x3, 0x33, 0x01, 0, 0x0c370000, 1, 0x00010000 }, + { 0x3, 0x33, 0x02, 0, 0x0c3a0000, 3, 0x00040000 }, + { 0x3, 0x33, 0x03, 0, 0x0c380000, 2, 0x00020000 }, + { 0x3, 0x38, 0x00, 0, 0x0c600000, 0, 0x00000000 }, + { 0x3, 0x38, 0x01, 0, 0x00000000, 0, 0x00000000 }, + { 0x3, 0x39, 0x00, 0, 0x0c280000, 0, 0x00000000 } +}; + +/* + * SCE/RCE NOC aperture lookup table as per file "AON_NOC_Structure.info". + */ +static const char * const tegra194_scenoc_routeid_initflow[] = { + [0x0] = "cbb_i/I/0", + [0x1] = "cpu_m_i/I/0", + [0x2] = "cpu_p_i/I/0", + [0x3] = "dma_m_i/I/0", + [0x4] = "dma_p_i/I/0", + [0x5] = "RESERVED", + [0x6] = "RESERVED", + [0x7] = "RESERVED" +}; + +static const char * const tegra194_scenoc_routeid_targflow[] = { + [0x00] = "multiport0_t/T/atcm_cfg", + [0x01] = "multiport0_t/T/car", + [0x02] = "multiport0_t/T/cast", + [0x03] = "multiport0_t/T/cfg", + [0x04] = "multiport0_t/T/dast", + [0x05] = "multiport0_t/T/dma", + [0x06] = "multiport0_t/T/err_collator", + [0x07] = "multiport0_t/T/err_collator_car", + [0x08] = "multiport0_t/T/fpga_misc", + [0x09] = "multiport0_t/T/fpga_uart", + [0x0a] = "multiport0_t/T/gte", + [0x0b] = "multiport0_t/T/hsp", + [0x0c] = "multiport0_t/T/misc", + [0x0d] = "multiport0_t/T/pm", + [0x0e] = "multiport0_t/T/tke", + [0x0f] = "RESERVED", + [0x10] = "multiport1_t/T/hsm", + [0x11] = "multiport1_t/T/vic0", + [0x12] = "multiport1_t/T/vic1", + [0x13] = "ast0_t/T/0", + [0x14] = "ast1_t/T/0", + [0x15] = "cbb_t/T/0", + [0x16] = "cpu_t/T/0", + [0x17] = "sce_noc_firewall/T/0", + [0x18] = "svc_t/T/0", + [0x19] = "RESERVED", + [0x1a] = "RESERVED", + [0x1b] = "RESERVED", + [0x1c] = "RESERVED", + [0x1d] = "RESERVED", + [0x1e] = "RESERVED", + [0x1f] = "RESERVED" +}; + +/* + * Fields of SCE/RCE NOC lookup table: + * Init flow, Targ flow, Targ subrange, Init mapping, Init localAddress, + * Targ mapping, Targ localAddress + * ---------------------------------------------------------------------------- + */ +static const struct tegra194_cbb_aperture tegra194_scenoc_apert_lookup[] = { + { 0x0, 0x16, 0x0, 0, 0x0b400000, 0, 0x0b400000 }, + { 0x0, 0x16, 0x1, 0, 0x0bc00000, 1, 0x0bc00000 }, + { 0x0, 0x0, 0x0, 0, 0x0b000000, 0, 0x00000000 }, + { 0x0, 0x0, 0x1, 0, 0x0b800000, 1, 0x00000000 }, + { 0x0, 0x1, 0x0, 0, 0x20de0000, 3, 0x000e0000 }, + { 0x0, 0x1, 0x1, 0, 0x210e0000, 7, 0x000e0000 }, + { 0x0, 0x1, 0x2, 0, 0x20dc0000, 2, 0x000c0000 }, + { 0x0, 0x1, 0x3, 0, 0x210c0000, 6, 0x000c0000 }, + { 0x0, 0x1, 0x4, 0, 0x20d80000, 1, 0x00080000 }, + { 0x0, 0x1, 0x5, 0, 0x21080000, 5, 0x00080000 }, + { 0x0, 0x1, 0x6, 0, 0x20d00000, 0, 0x00000000 }, + { 0x0, 0x1, 0x7, 0, 0x21000000, 4, 0x00000000 }, + { 0x0, 0x2, 0x0, 0, 0x0b040000, 0, 0x00000000 }, + { 0x0, 0x2, 0x1, 0, 0x0b840000, 1, 0x00000000 }, + { 0x0, 0x3, 0x0, 0, 0x0b230000, 0, 0x00000000 }, + { 0x0, 0x3, 0x1, 0, 0x0ba30000, 1, 0x00000000 }, + { 0x0, 0x4, 0x0, 0, 0x0b050000, 0, 0x00000000 }, + { 0x0, 0x4, 0x1, 0, 0x0b850000, 1, 0x00000000 }, + { 0x0, 0x5, 0x0, 0, 0x0b060000, 0, 0x00000000 }, + { 0x0, 0x5, 0x1, 0, 0x0b070000, 1, 0x00010000 }, + { 0x0, 0x5, 0x2, 0, 0x0b080000, 2, 0x00020000 }, + { 0x0, 0x5, 0x3, 0, 0x0b090000, 3, 0x00030000 }, + { 0x0, 0x5, 0x4, 0, 0x0b0a0000, 4, 0x00040000 }, + { 0x0, 0x5, 0x5, 0, 0x0b0b0000, 5, 0x00050000 }, + { 0x0, 0x5, 0x6, 0, 0x0b0c0000, 6, 0x00060000 }, + { 0x0, 0x5, 0x7, 0, 0x0b0d0000, 7, 0x00070000 }, + { 0x0, 0x5, 0x8, 0, 0x0b0e0000, 8, 0x00080000 }, + { 0x0, 0x5, 0x9, 0, 0x0b860000, 9, 0x00000000 }, + { 0x0, 0x5, 0xa, 0, 0x0b870000, 10, 0x00010000 }, + { 0x0, 0x5, 0xb, 0, 0x0b880000, 11, 0x00020000 }, + { 0x0, 0x5, 0xc, 0, 0x0b890000, 12, 0x00030000 }, + { 0x0, 0x5, 0xd, 0, 0x0b8a0000, 13, 0x00040000 }, + { 0x0, 0x5, 0xe, 0, 0x0b8b0000, 14, 0x00050000 }, + { 0x0, 0x5, 0xf, 0, 0x0b8c0000, 15, 0x00060000 }, + { 0x0, 0x5, 0x10, 0, 0x0b8d0000, 16, 0x00070000 }, + { 0x0, 0x5, 0x11, 0, 0x0b8e0000, 17, 0x00080000 }, + { 0x0, 0x6, 0x0, 0, 0x0b650000, 0, 0x00000000 }, + { 0x0, 0x6, 0x1, 0, 0x0be50000, 1, 0x00000000 }, + { 0x0, 0x7, 0x0, 0, 0x20df0000, 0, 0x00000000 }, + { 0x0, 0x7, 0x1, 0, 0x210f0000, 1, 0x00000000 }, + { 0x0, 0x8, 0x0, 0, 0x0b3e0000, 0, 0x00000000 }, + { 0x0, 0x8, 0x1, 0, 0x0bbe0000, 1, 0x00000000 }, + { 0x0, 0x9, 0x0, 0, 0x0b3d0000, 0, 0x00000000 }, + { 0x0, 0x9, 0x1, 0, 0x0bbd0000, 1, 0x00000000 }, + { 0x0, 0xa, 0x0, 0, 0x0b1e0000, 0, 0x00000000 }, + { 0x0, 0xa, 0x1, 0, 0x0b9e0000, 1, 0x00000000 }, + { 0x0, 0xb, 0x0, 0, 0x0b150000, 0, 0x00000000 }, + { 0x0, 0xb, 0x1, 0, 0x0b160000, 1, 0x00010000 }, + { 0x0, 0xb, 0x2, 0, 0x0b170000, 2, 0x00020000 }, + { 0x0, 0xb, 0x3, 0, 0x0b180000, 3, 0x00030000 }, + { 0x0, 0xb, 0x4, 0, 0x0b190000, 4, 0x00040000 }, + { 0x0, 0xb, 0x5, 0, 0x0b1a0000, 5, 0x00050000 }, + { 0x0, 0xb, 0x6, 0, 0x0b1b0000, 6, 0x00060000 }, + { 0x0, 0xb, 0x7, 0, 0x0b1c0000, 7, 0x00070000 }, + { 0x0, 0xb, 0x8, 0, 0x0b1d0000, 8, 0x00080000 }, + { 0x0, 0xb, 0x9, 0, 0x0b950000, 9, 0x00000000 }, + { 0x0, 0xb, 0xa, 0, 0x0b960000, 10, 0x00010000 }, + { 0x0, 0xb, 0xb, 0, 0x0b970000, 11, 0x00020000 }, + { 0x0, 0xb, 0xc, 0, 0x0b980000, 12, 0x00030000 }, + { 0x0, 0xb, 0xd, 0, 0x0b990000, 13, 0x00040000 }, + { 0x0, 0xb, 0xe, 0, 0x0b9a0000, 14, 0x00050000 }, + { 0x0, 0xb, 0xf, 0, 0x0b9b0000, 15, 0x00060000 }, + { 0x0, 0xb, 0x10, 0, 0x0b9c0000, 16, 0x00070000 }, + { 0x0, 0xb, 0x11, 0, 0x0b9d0000, 17, 0x00080000 }, + { 0x0, 0xc, 0x0, 0, 0x0b660000, 0, 0x00000000 }, + { 0x0, 0xc, 0x1, 0, 0x0be60000, 1, 0x00000000 }, + { 0x0, 0xd, 0x0, 0, 0x0b1f0000, 0, 0x00000000 }, + { 0x0, 0xd, 0x1, 0, 0x0b200000, 1, 0x00010000 }, + { 0x0, 0xd, 0x2, 0, 0x0b210000, 2, 0x00020000 }, + { 0x0, 0xd, 0x3, 0, 0x0b220000, 3, 0x00030000 }, + { 0x0, 0xd, 0x4, 0, 0x0b9f0000, 4, 0x00000000 }, + { 0x0, 0xd, 0x5, 0, 0x0ba00000, 5, 0x00010000 }, + { 0x0, 0xd, 0x6, 0, 0x0ba10000, 6, 0x00020000 }, + { 0x0, 0xd, 0x7, 0, 0x0ba20000, 7, 0x00030000 }, + { 0x0, 0xe, 0x0, 0, 0x0b0f0000, 0, 0x00000000 }, + { 0x0, 0xe, 0x1, 0, 0x0b100000, 1, 0x00010000 }, + { 0x0, 0xe, 0x2, 0, 0x0b110000, 2, 0x00020000 }, + { 0x0, 0xe, 0x3, 0, 0x0b120000, 3, 0x00030000 }, + { 0x0, 0xe, 0x4, 0, 0x0b130000, 4, 0x00040000 }, + { 0x0, 0xe, 0x5, 0, 0x0b140000, 5, 0x00050000 }, + { 0x0, 0xe, 0x6, 0, 0x0b8f0000, 6, 0x00000000 }, + { 0x0, 0xe, 0x7, 0, 0x0b900000, 7, 0x00010000 }, + { 0x0, 0xe, 0x8, 0, 0x0b910000, 8, 0x00020000 }, + { 0x0, 0xe, 0x9, 0, 0x0b920000, 9, 0x00030000 }, + { 0x0, 0xe, 0xa, 0, 0x0b930000, 10, 0x00040000 }, + { 0x0, 0xe, 0xb, 0, 0x0b940000, 11, 0x00050000 }, + { 0x0, 0x10, 0x0, 0, 0x0b240000, 0, 0x00000000 }, + { 0x0, 0x10, 0x1, 0, 0x0ba40000, 1, 0x00000000 }, + { 0x0, 0x11, 0x0, 0, 0x0b020000, 0, 0x00000000 }, + { 0x0, 0x11, 0x1, 0, 0x0b820000, 1, 0x00000000 }, + { 0x0, 0x12, 0x0, 0, 0x0b030000, 0, 0x00000000 }, + { 0x0, 0x12, 0x1, 0, 0x0b830000, 1, 0x00000000 }, + { 0x0, 0x17, 0x0, 0, 0x0b640000, 0, 0x00000000 }, + { 0x0, 0x17, 0x1, 0, 0x0be40000, 1, 0x00000000 }, + { 0x0, 0x18, 0x0, 0, 0x0b600000, 0, 0x00000000 }, + { 0x0, 0x18, 0x1, 0, 0x0be00000, 1, 0x00000000 }, + { 0x0, 0x18, 0x2, 0, 0x00000000, 0, 0x00000000 }, + { 0x0, 0x18, 0x3, 0, 0x00000000, 0, 0x00000000 }, + { 0x1, 0x13, 0x0, 0, 0x40000000, 0, 0x40000000 }, + { 0x1, 0x13, 0x1, 1, 0x80000000, 1, 0x80000000 }, + { 0x1, 0x13, 0x2, 0, 0x00000000, 0, 0x00000000 }, + { 0x2, 0x15, 0x0, 0, 0x20c00000, 8, 0x20c00000 }, + { 0x2, 0x15, 0x1, 0, 0x21100000, 22, 0x21100000 }, + { 0x2, 0x15, 0x2, 0, 0x20e00000, 9, 0x20e00000 }, + { 0x2, 0x15, 0x3, 0, 0x21200000, 23, 0x21200000 }, + { 0x2, 0x15, 0x4, 0, 0x20800000, 7, 0x20800000 }, + { 0x2, 0x15, 0x5, 0, 0x21400000, 24, 0x21400000 }, + { 0x2, 0x15, 0x6, 0, 0x0b000000, 18, 0x0b000000 }, + { 0x2, 0x15, 0x7, 0, 0x0b800000, 3, 0x0b800000 }, + { 0x2, 0x15, 0x8, 0, 0x20000000, 6, 0x20000000 }, + { 0x2, 0x15, 0x9, 0, 0x21800000, 25, 0x21800000 }, + { 0x2, 0x15, 0xa, 0, 0x0a000000, 2, 0x0a000000 }, + { 0x2, 0x15, 0xb, 0, 0x0a000000, 17, 0x0a000000 }, + { 0x2, 0x15, 0xc, 0, 0x20000000, 21, 0x20000000 }, + { 0x2, 0x15, 0xd, 0, 0x21000000, 10, 0x21000000 }, + { 0x2, 0x15, 0xe, 0, 0x08000000, 1, 0x08000000 }, + { 0x2, 0x15, 0xf, 0, 0x08000000, 16, 0x08000000 }, + { 0x2, 0x15, 0x10, 0, 0x22000000, 11, 0x22000000 }, + { 0x2, 0x15, 0x11, 0, 0x22000000, 26, 0x22000000 }, + { 0x2, 0x15, 0x12, 0, 0x0c000000, 4, 0x0c000000 }, + { 0x2, 0x15, 0x13, 0, 0x0c000000, 19, 0x0c000000 }, + { 0x2, 0x15, 0x14, 0, 0x24000000, 12, 0x24000000 }, + { 0x2, 0x15, 0x15, 0, 0x24000000, 27, 0x24000000 }, + { 0x2, 0x15, 0x16, 0, 0x00000000, 0, 0x00000000 }, + { 0x2, 0x15, 0x17, 0, 0x00000000, 15, 0x00000000 }, + { 0x2, 0x15, 0x18, 0, 0x28000000, 13, 0x28000000 }, + { 0x2, 0x15, 0x19, 0, 0x28000000, 28, 0x28000000 }, + { 0x2, 0x15, 0x1a, 0, 0x10000000, 5, 0x10000000 }, + { 0x2, 0x15, 0x1b, 0, 0x10000000, 20, 0x10000000 }, + { 0x2, 0x15, 0x1c, 0, 0x30000000, 14, 0x30000000 }, + { 0x2, 0x15, 0x1d, 0, 0x30000000, 29, 0x30000000 }, + { 0x2, 0x0, 0x0, 0, 0x0b000000, 0, 0x00000000 }, + { 0x2, 0x0, 0x1, 0, 0x0b800000, 1, 0x00000000 }, + { 0x2, 0x1, 0x0, 0, 0x20de0000, 3, 0x000e0000 }, + { 0x2, 0x1, 0x1, 0, 0x210e0000, 7, 0x000e0000 }, + { 0x2, 0x1, 0x2, 0, 0x20dc0000, 2, 0x000c0000 }, + { 0x2, 0x1, 0x3, 0, 0x210c0000, 6, 0x000c0000 }, + { 0x2, 0x1, 0x4, 0, 0x20d80000, 1, 0x00080000 }, + { 0x2, 0x1, 0x5, 0, 0x21080000, 5, 0x00080000 }, + { 0x2, 0x1, 0x6, 0, 0x20d00000, 0, 0x00000000 }, + { 0x2, 0x1, 0x7, 0, 0x21000000, 4, 0x00000000 }, + { 0x2, 0x2, 0x0, 0, 0x0b040000, 0, 0x00000000 }, + { 0x2, 0x2, 0x1, 0, 0x0b840000, 1, 0x00000000 }, + { 0x2, 0x3, 0x0, 0, 0x0b230000, 0, 0x00000000 }, + { 0x2, 0x3, 0x1, 0, 0x0ba30000, 1, 0x00000000 }, + { 0x2, 0x4, 0x0, 0, 0x0b050000, 0, 0x00000000 }, + { 0x2, 0x4, 0x1, 0, 0x0b850000, 1, 0x00000000 }, + { 0x2, 0x5, 0x0, 0, 0x0b060000, 0, 0x00000000 }, + { 0x2, 0x5, 0x1, 0, 0x0b070000, 1, 0x00010000 }, + { 0x2, 0x5, 0x2, 0, 0x0b080000, 2, 0x00020000 }, + { 0x2, 0x5, 0x3, 0, 0x0b090000, 3, 0x00030000 }, + { 0x2, 0x5, 0x4, 0, 0x0b0a0000, 4, 0x00040000 }, + { 0x2, 0x5, 0x5, 0, 0x0b0b0000, 5, 0x00050000 }, + { 0x2, 0x5, 0x6, 0, 0x0b0c0000, 6, 0x00060000 }, + { 0x2, 0x5, 0x7, 0, 0x0b0d0000, 7, 0x00070000 }, + { 0x2, 0x5, 0x8, 0, 0x0b0e0000, 8, 0x00080000 }, + { 0x2, 0x5, 0x9, 0, 0x0b860000, 9, 0x00000000 }, + { 0x2, 0x5, 0xa, 0, 0x0b870000, 10, 0x00010000 }, + { 0x2, 0x5, 0xb, 0, 0x0b880000, 11, 0x00020000 }, + { 0x2, 0x5, 0xc, 0, 0x0b890000, 12, 0x00030000 }, + { 0x2, 0x5, 0xd, 0, 0x0b8a0000, 13, 0x00040000 }, + { 0x2, 0x5, 0xe, 0, 0x0b8b0000, 14, 0x00050000 }, + { 0x2, 0x5, 0xf, 0, 0x0b8c0000, 15, 0x00060000 }, + { 0x2, 0x5, 0x10, 0, 0x0b8d0000, 16, 0x00070000 }, + { 0x2, 0x5, 0x11, 0, 0x0b8e0000, 17, 0x00080000 }, + { 0x2, 0x6, 0x0, 0, 0x0b650000, 0, 0x00000000 }, + { 0x2, 0x6, 0x1, 0, 0x0be50000, 1, 0x00000000 }, + { 0x2, 0x7, 0x0, 0, 0x20df0000, 0, 0x00000000 }, + { 0x2, 0x7, 0x1, 0, 0x210f0000, 1, 0x00000000 }, + { 0x2, 0x8, 0x0, 0, 0x0b3e0000, 0, 0x00000000 }, + { 0x2, 0x8, 0x1, 0, 0x0bbe0000, 1, 0x00000000 }, + { 0x2, 0x9, 0x0, 0, 0x0b3d0000, 0, 0x00000000 }, + { 0x2, 0x9, 0x1, 0, 0x0bbd0000, 1, 0x00000000 }, + { 0x2, 0xa, 0x0, 0, 0x0b1e0000, 0, 0x00000000 }, + { 0x2, 0xa, 0x1, 0, 0x0b9e0000, 1, 0x00000000 }, + { 0x2, 0xb, 0x0, 0, 0x0b150000, 0, 0x00000000 }, + { 0x2, 0xb, 0x1, 0, 0x0b160000, 1, 0x00010000 }, + { 0x2, 0xb, 0x2, 0, 0x0b170000, 2, 0x00020000 }, + { 0x2, 0xb, 0x3, 0, 0x0b180000, 3, 0x00030000 }, + { 0x2, 0xb, 0x4, 0, 0x0b190000, 4, 0x00040000 }, + { 0x2, 0xb, 0x5, 0, 0x0b1a0000, 5, 0x00050000 }, + { 0x2, 0xb, 0x6, 0, 0x0b1b0000, 6, 0x00060000 }, + { 0x2, 0xb, 0x7, 0, 0x0b1c0000, 7, 0x00070000 }, + { 0x2, 0xb, 0x8, 0, 0x0b1d0000, 8, 0x00080000 }, + { 0x2, 0xb, 0x9, 0, 0x0b950000, 9, 0x00000000 }, + { 0x2, 0xb, 0xa, 0, 0x0b960000, 10, 0x00010000 }, + { 0x2, 0xb, 0xb, 0, 0x0b970000, 11, 0x00020000 }, + { 0x2, 0xb, 0xc, 0, 0x0b980000, 12, 0x00030000 }, + { 0x2, 0xb, 0xd, 0, 0x0b990000, 13, 0x00040000 }, + { 0x2, 0xb, 0xe, 0, 0x0b9a0000, 14, 0x00050000 }, + { 0x2, 0xb, 0xf, 0, 0x0b9b0000, 15, 0x00060000 }, + { 0x2, 0xb, 0x10, 0, 0x0b9c0000, 16, 0x00070000 }, + { 0x2, 0xb, 0x11, 0, 0x0b9d0000, 17, 0x00080000 }, + { 0x2, 0xc, 0x0, 0, 0x0b660000, 0, 0x00000000 }, + { 0x2, 0xc, 0x1, 0, 0x0be60000, 1, 0x00000000 }, + { 0x2, 0xd, 0x0, 0, 0x0b1f0000, 0, 0x00000000 }, + { 0x2, 0xd, 0x1, 0, 0x0b200000, 1, 0x00010000 }, + { 0x2, 0xd, 0x2, 0, 0x0b210000, 2, 0x00020000 }, + { 0x2, 0xd, 0x3, 0, 0x0b220000, 3, 0x00030000 }, + { 0x2, 0xd, 0x4, 0, 0x0b9f0000, 4, 0x00000000 }, + { 0x2, 0xd, 0x5, 0, 0x0ba00000, 5, 0x00010000 }, + { 0x2, 0xd, 0x6, 0, 0x0ba10000, 6, 0x00020000 }, + { 0x2, 0xd, 0x7, 0, 0x0ba20000, 7, 0x00030000 }, + { 0x2, 0xe, 0x0, 0, 0x0b0f0000, 0, 0x00000000 }, + { 0x2, 0xe, 0x1, 0, 0x0b100000, 1, 0x00010000 }, + { 0x2, 0xe, 0x2, 0, 0x0b110000, 2, 0x00020000 }, + { 0x2, 0xe, 0x3, 0, 0x0b120000, 3, 0x00030000 }, + { 0x2, 0xe, 0x4, 0, 0x0b130000, 4, 0x00040000 }, + { 0x2, 0xe, 0x5, 0, 0x0b140000, 5, 0x00050000 }, + { 0x2, 0xe, 0x6, 0, 0x0b8f0000, 6, 0x00000000 }, + { 0x2, 0xe, 0x7, 0, 0x0b900000, 7, 0x00010000 }, + { 0x2, 0xe, 0x8, 0, 0x0b910000, 8, 0x00020000 }, + { 0x2, 0xe, 0x9, 0, 0x0b920000, 9, 0x00030000 }, + { 0x2, 0xe, 0xa, 0, 0x0b930000, 10, 0x00040000 }, + { 0x2, 0xe, 0xb, 0, 0x0b940000, 11, 0x00050000 }, + { 0x2, 0x10, 0x0, 0, 0x0b240000, 0, 0x00000000 }, + { 0x2, 0x10, 0x1, 0, 0x0ba40000, 1, 0x00000000 }, + { 0x2, 0x11, 0x0, 0, 0x0b020000, 0, 0x00000000 }, + { 0x2, 0x11, 0x1, 0, 0x0b820000, 1, 0x00000000 }, + { 0x2, 0x12, 0x0, 0, 0x0b030000, 0, 0x00000000 }, + { 0x2, 0x12, 0x1, 0, 0x0b830000, 1, 0x00000000 }, + { 0x2, 0x17, 0x0, 0, 0x0b640000, 0, 0x00000000 }, + { 0x2, 0x17, 0x1, 0, 0x0be40000, 1, 0x00000000 }, + { 0x2, 0x18, 0x0, 0, 0x0b600000, 0, 0x00000000 }, + { 0x2, 0x18, 0x1, 0, 0x0be00000, 1, 0x00000000 }, + { 0x2, 0x18, 0x2, 0, 0x00000000, 0, 0x00000000 }, + { 0x2, 0x18, 0x3, 0, 0x00000000, 0, 0x00000000 }, + { 0x3, 0x14, 0x0, 0, 0x40000000, 0, 0x40000000 }, + { 0x3, 0x14, 0x1, 1, 0x80000000, 1, 0x80000000 }, + { 0x3, 0x16, 0x0, 2, 0x0b400000, 0, 0x0b400000 }, + { 0x3, 0x16, 0x1, 2, 0x0bc00000, 1, 0x0bc00000 }, + { 0x3, 0x16, 0x2, 0, 0x00000000, 0, 0x00000000 }, + { 0x3, 0x16, 0x3, 0, 0x00000000, 0, 0x00000000 }, + { 0x4, 0x15, 0x0, 0, 0x20c00000, 8, 0x20c00000 }, + { 0x4, 0x15, 0x1, 0, 0x21100000, 22, 0x21100000 }, + { 0x4, 0x15, 0x2, 0, 0x20e00000, 9, 0x20e00000 }, + { 0x4, 0x15, 0x3, 0, 0x21200000, 23, 0x21200000 }, + { 0x4, 0x15, 0x4, 0, 0x20800000, 7, 0x20800000 }, + { 0x4, 0x15, 0x5, 0, 0x21400000, 24, 0x21400000 }, + { 0x4, 0x15, 0x6, 0, 0x0b000000, 18, 0x0b000000 }, + { 0x4, 0x15, 0x7, 0, 0x0b800000, 3, 0x0b800000 }, + { 0x4, 0x15, 0x8, 0, 0x20000000, 6, 0x20000000 }, + { 0x4, 0x15, 0x9, 0, 0x21800000, 25, 0x21800000 }, + { 0x4, 0x15, 0xa, 0, 0x0a000000, 2, 0x0a000000 }, + { 0x4, 0x15, 0xb, 0, 0x0a000000, 17, 0x0a000000 }, + { 0x4, 0x15, 0xc, 0, 0x20000000, 21, 0x20000000 }, + { 0x4, 0x15, 0xd, 0, 0x21000000, 10, 0x21000000 }, + { 0x4, 0x15, 0xe, 0, 0x08000000, 1, 0x08000000 }, + { 0x4, 0x15, 0xf, 0, 0x08000000, 16, 0x08000000 }, + { 0x4, 0x15, 0x10, 0, 0x22000000, 11, 0x22000000 }, + { 0x4, 0x15, 0x11, 0, 0x22000000, 26, 0x22000000 }, + { 0x4, 0x15, 0x12, 0, 0x0c000000, 4, 0x0c000000 }, + { 0x4, 0x15, 0x13, 0, 0x0c000000, 19, 0x0c000000 }, + { 0x4, 0x15, 0x14, 0, 0x24000000, 12, 0x24000000 }, + { 0x4, 0x15, 0x15, 0, 0x24000000, 27, 0x24000000 }, + { 0x4, 0x15, 0x16, 0, 0x00000000, 0, 0x00000000 }, + { 0x4, 0x15, 0x17, 0, 0x00000000, 15, 0x00000000 }, + { 0x4, 0x15, 0x18, 0, 0x28000000, 13, 0x28000000 }, + { 0x4, 0x15, 0x19, 0, 0x28000000, 28, 0x28000000 }, + { 0x4, 0x15, 0x1a, 0, 0x10000000, 5, 0x10000000 }, + { 0x4, 0x15, 0x1b, 0, 0x10000000, 20, 0x10000000 }, + { 0x4, 0x15, 0x1c, 0, 0x30000000, 14, 0x30000000 }, + { 0x4, 0x15, 0x1d, 0, 0x30000000, 29, 0x30000000 }, + { 0x4, 0x0, 0x0, 0, 0x0b000000, 0, 0x00000000 }, + { 0x4, 0x0, 0x1, 0, 0x0b800000, 1, 0x00000000 }, + { 0x4, 0x1, 0x0, 0, 0x20de0000, 3, 0x000e0000 }, + { 0x4, 0x1, 0x1, 0, 0x210e0000, 7, 0x000e0000 }, + { 0x4, 0x1, 0x2, 0, 0x20dc0000, 2, 0x000c0000 }, + { 0x4, 0x1, 0x3, 0, 0x210c0000, 6, 0x000c0000 }, + { 0x4, 0x1, 0x4, 0, 0x20d80000, 1, 0x00080000 }, + { 0x4, 0x1, 0x5, 0, 0x21080000, 5, 0x00080000 }, + { 0x4, 0x1, 0x6, 0, 0x20d00000, 0, 0x00000000 }, + { 0x4, 0x1, 0x7, 0, 0x21000000, 4, 0x00000000 }, + { 0x4, 0x2, 0x0, 0, 0x0b040000, 0, 0x00000000 }, + { 0x4, 0x2, 0x1, 0, 0x0b840000, 1, 0x00000000 }, + { 0x4, 0x3, 0x0, 0, 0x0b230000, 0, 0x00000000 }, + { 0x4, 0x3, 0x1, 0, 0x0ba30000, 1, 0x00000000 }, + { 0x4, 0x4, 0x0, 0, 0x0b050000, 0, 0x00000000 }, + { 0x4, 0x4, 0x1, 0, 0x0b850000, 1, 0x00000000 }, + { 0x4, 0x5, 0x0, 0, 0x0b060000, 0, 0x00000000 }, + { 0x4, 0x5, 0x1, 0, 0x0b070000, 1, 0x00010000 }, + { 0x4, 0x5, 0x2, 0, 0x0b080000, 2, 0x00020000 }, + { 0x4, 0x5, 0x3, 0, 0x0b090000, 3, 0x00030000 }, + { 0x4, 0x5, 0x4, 0, 0x0b0a0000, 4, 0x00040000 }, + { 0x4, 0x5, 0x5, 0, 0x0b0b0000, 5, 0x00050000 }, + { 0x4, 0x5, 0x6, 0, 0x0b0c0000, 6, 0x00060000 }, + { 0x4, 0x5, 0x7, 0, 0x0b0d0000, 7, 0x00070000 }, + { 0x4, 0x5, 0x8, 0, 0x0b0e0000, 8, 0x00080000 }, + { 0x4, 0x5, 0x9, 0, 0x0b860000, 9, 0x00000000 }, + { 0x4, 0x5, 0xa, 0, 0x0b870000, 10, 0x00010000 }, + { 0x4, 0x5, 0xb, 0, 0x0b880000, 11, 0x00020000 }, + { 0x4, 0x5, 0xc, 0, 0x0b890000, 12, 0x00030000 }, + { 0x4, 0x5, 0xd, 0, 0x0b8a0000, 13, 0x00040000 }, + { 0x4, 0x5, 0xe, 0, 0x0b8b0000, 14, 0x00050000 }, + { 0x4, 0x5, 0xf, 0, 0x0b8c0000, 15, 0x00060000 }, + { 0x4, 0x5, 0x10, 0, 0x0b8d0000, 16, 0x00070000 }, + { 0x4, 0x5, 0x11, 0, 0x0b8e0000, 17, 0x00080000 }, + { 0x4, 0x6, 0x0, 0, 0x0b650000, 0, 0x00000000 }, + { 0x4, 0x6, 0x1, 0, 0x0be50000, 1, 0x00000000 }, + { 0x4, 0x7, 0x0, 0, 0x20df0000, 0, 0x00000000 }, + { 0x4, 0x7, 0x1, 0, 0x210f0000, 1, 0x00000000 }, + { 0x4, 0x8, 0x0, 0, 0x0b3e0000, 0, 0x00000000 }, + { 0x4, 0x8, 0x1, 0, 0x0bbe0000, 1, 0x00000000 }, + { 0x4, 0x9, 0x0, 0, 0x0b3d0000, 0, 0x00000000 }, + { 0x4, 0x9, 0x1, 0, 0x0bbd0000, 1, 0x00000000 }, + { 0x4, 0xa, 0x0, 0, 0x0b1e0000, 0, 0x00000000 }, + { 0x4, 0xa, 0x1, 0, 0x0b9e0000, 1, 0x00000000 }, + { 0x4, 0xb, 0x0, 0, 0x0b150000, 0, 0x00000000 }, + { 0x4, 0xb, 0x1, 0, 0x0b160000, 1, 0x00010000 }, + { 0x4, 0xb, 0x2, 0, 0x0b170000, 2, 0x00020000 }, + { 0x4, 0xb, 0x3, 0, 0x0b180000, 3, 0x00030000 }, + { 0x4, 0xb, 0x4, 0, 0x0b190000, 4, 0x00040000 }, + { 0x4, 0xb, 0x5, 0, 0x0b1a0000, 5, 0x00050000 }, + { 0x4, 0xb, 0x6, 0, 0x0b1b0000, 6, 0x00060000 }, + { 0x4, 0xb, 0x7, 0, 0x0b1c0000, 7, 0x00070000 }, + { 0x4, 0xb, 0x8, 0, 0x0b1d0000, 8, 0x00080000 }, + { 0x4, 0xb, 0x9, 0, 0x0b950000, 9, 0x00000000 }, + { 0x4, 0xb, 0xa, 0, 0x0b960000, 10, 0x00010000 }, + { 0x4, 0xb, 0xb, 0, 0x0b970000, 11, 0x00020000 }, + { 0x4, 0xb, 0xc, 0, 0x0b980000, 12, 0x00030000 }, + { 0x4, 0xb, 0xd, 0, 0x0b990000, 13, 0x00040000 }, + { 0x4, 0xb, 0xe, 0, 0x0b9a0000, 14, 0x00050000 }, + { 0x4, 0xb, 0xf, 0, 0x0b9b0000, 15, 0x00060000 }, + { 0x4, 0xb, 0x10, 0, 0x0b9c0000, 16, 0x00070000 }, + { 0x4, 0xb, 0x11, 0, 0x0b9d0000, 17, 0x00080000 }, + { 0x4, 0xc, 0x0, 0, 0x0b660000, 0, 0x00000000 }, + { 0x4, 0xc, 0x1, 0, 0x0be60000, 1, 0x00000000 }, + { 0x4, 0xd, 0x0, 0, 0x0b1f0000, 0, 0x00000000 }, + { 0x4, 0xd, 0x1, 0, 0x0b200000, 1, 0x00010000 }, + { 0x4, 0xd, 0x2, 0, 0x0b210000, 2, 0x00020000 }, + { 0x4, 0xd, 0x3, 0, 0x0b220000, 3, 0x00030000 }, + { 0x4, 0xd, 0x4, 0, 0x0b9f0000, 4, 0x00000000 }, + { 0x4, 0xd, 0x5, 0, 0x0ba00000, 5, 0x00010000 }, + { 0x4, 0xd, 0x6, 0, 0x0ba10000, 6, 0x00020000 }, + { 0x4, 0xd, 0x7, 0, 0x0ba20000, 7, 0x00030000 }, + { 0x4, 0xe, 0x0, 0, 0x0b0f0000, 0, 0x00000000 }, + { 0x4, 0xe, 0x1, 0, 0x0b100000, 1, 0x00010000 }, + { 0x4, 0xe, 0x2, 0, 0x0b110000, 2, 0x00020000 }, + { 0x4, 0xe, 0x3, 0, 0x0b120000, 3, 0x00030000 }, + { 0x4, 0xe, 0x4, 0, 0x0b130000, 4, 0x00040000 }, + { 0x4, 0xe, 0x5, 0, 0x0b140000, 5, 0x00050000 }, + { 0x4, 0xe, 0x6, 0, 0x0b8f0000, 6, 0x00000000 }, + { 0x4, 0xe, 0x7, 0, 0x0b900000, 7, 0x00010000 }, + { 0x4, 0xe, 0x8, 0, 0x0b910000, 8, 0x00020000 }, + { 0x4, 0xe, 0x9, 0, 0x0b920000, 9, 0x00030000 }, + { 0x4, 0xe, 0xa, 0, 0x0b930000, 10, 0x00040000 }, + { 0x4, 0xe, 0xb, 0, 0x0b940000, 11, 0x00050000 }, + { 0x4, 0x10, 0x0, 0, 0x0b240000, 0, 0x00000000 }, + { 0x4, 0x10, 0x1, 0, 0x0ba40000, 1, 0x00000000 }, + { 0x4, 0x11, 0x0, 0, 0x0b020000, 0, 0x00000000 }, + { 0x4, 0x11, 0x1, 0, 0x0b820000, 1, 0x00000000 }, + { 0x4, 0x12, 0x0, 0, 0x0b030000, 0, 0x00000000 }, + { 0x4, 0x12, 0x1, 0, 0x0b830000, 1, 0x00000000 }, + { 0x4, 0x17, 0x0, 0, 0x0b640000, 0, 0x00000000 }, + { 0x4, 0x17, 0x1, 0, 0x0be40000, 1, 0x00000000 }, + { 0x4, 0x18, 0x0, 0, 0x0b600000, 0, 0x00000000 }, + { 0x4, 0x18, 0x1, 0, 0x0be00000, 1, 0x00000000 }, + { 0x4, 0x18, 0x2, 0, 0x00000000, 0, 0x00000000 }, + { 0x4, 0x18, 0x3, 0, 0x00000000, 0, 0x00000000 } +}; + +static void cbbcentralnoc_parse_routeid(struct tegra194_cbb_aperture *info, u64 routeid) +{ + info->initflow = FIELD_GET(CBB_NOC_INITFLOW, routeid); + info->targflow = FIELD_GET(CBB_NOC_TARGFLOW, routeid); + info->targ_subrange = FIELD_GET(CBB_NOC_TARG_SUBRANGE, routeid); + info->seqid = FIELD_GET(CBB_NOC_SEQID, routeid); +} + +static void bpmpnoc_parse_routeid(struct tegra194_cbb_aperture *info, u64 routeid) +{ + info->initflow = FIELD_GET(BPMP_NOC_INITFLOW, routeid); + info->targflow = FIELD_GET(BPMP_NOC_TARGFLOW, routeid); + info->targ_subrange = FIELD_GET(BPMP_NOC_TARG_SUBRANGE, routeid); + info->seqid = FIELD_GET(BPMP_NOC_SEQID, routeid); +} + +static void aonnoc_parse_routeid(struct tegra194_cbb_aperture *info, u64 routeid) +{ + info->initflow = FIELD_GET(AON_NOC_INITFLOW, routeid); + info->targflow = FIELD_GET(AON_NOC_TARGFLOW, routeid); + info->targ_subrange = FIELD_GET(AON_NOC_TARG_SUBRANGE, routeid); + info->seqid = FIELD_GET(AON_NOC_SEQID, routeid); +} + +static void scenoc_parse_routeid(struct tegra194_cbb_aperture *info, u64 routeid) +{ + info->initflow = FIELD_GET(SCE_NOC_INITFLOW, routeid); + info->targflow = FIELD_GET(SCE_NOC_TARGFLOW, routeid); + info->targ_subrange = FIELD_GET(SCE_NOC_TARG_SUBRANGE, routeid); + info->seqid = FIELD_GET(SCE_NOC_SEQID, routeid); +} + +static void cbbcentralnoc_parse_userbits(struct tegra194_cbb_userbits *usrbits, u32 elog_5) +{ + usrbits->axcache = FIELD_GET(CBB_NOC_AXCACHE, elog_5); + usrbits->non_mod = FIELD_GET(CBB_NOC_NON_MOD, elog_5); + usrbits->axprot = FIELD_GET(CBB_NOC_AXPROT, elog_5); + usrbits->falconsec = FIELD_GET(CBB_NOC_FALCONSEC, elog_5); + usrbits->grpsec = FIELD_GET(CBB_NOC_GRPSEC, elog_5); + usrbits->vqc = FIELD_GET(CBB_NOC_VQC, elog_5); + usrbits->mstr_id = FIELD_GET(CBB_NOC_MSTR_ID, elog_5) - 1; + usrbits->axi_id = FIELD_GET(CBB_NOC_AXI_ID, elog_5); +} + +static void clusternoc_parse_userbits(struct tegra194_cbb_userbits *usrbits, u32 elog_5) +{ + usrbits->axcache = FIELD_GET(CLUSTER_NOC_AXCACHE, elog_5); + usrbits->axprot = FIELD_GET(CLUSTER_NOC_AXCACHE, elog_5); + usrbits->falconsec = FIELD_GET(CLUSTER_NOC_FALCONSEC, elog_5); + usrbits->grpsec = FIELD_GET(CLUSTER_NOC_GRPSEC, elog_5); + usrbits->vqc = FIELD_GET(CLUSTER_NOC_VQC, elog_5); + usrbits->mstr_id = FIELD_GET(CLUSTER_NOC_MSTR_ID, elog_5) - 1; +} + +static void tegra194_cbb_fault_enable(struct tegra_cbb *cbb) +{ + struct tegra194_cbb *priv = to_tegra194_cbb(cbb); + + writel(1, priv->regs + ERRLOGGER_0_FAULTEN_0); + writel(1, priv->regs + ERRLOGGER_1_FAULTEN_0); + writel(1, priv->regs + ERRLOGGER_2_FAULTEN_0); +} + +static void tegra194_cbb_stall_enable(struct tegra_cbb *cbb) +{ + struct tegra194_cbb *priv = to_tegra194_cbb(cbb); + + writel(1, priv->regs + ERRLOGGER_0_STALLEN_0); + writel(1, priv->regs + ERRLOGGER_1_STALLEN_0); + writel(1, priv->regs + ERRLOGGER_2_STALLEN_0); +} + +static void tegra194_cbb_error_clear(struct tegra_cbb *cbb) +{ + struct tegra194_cbb *priv = to_tegra194_cbb(cbb); + + writel(1, priv->regs + ERRLOGGER_0_ERRCLR_0); + writel(1, priv->regs + ERRLOGGER_1_ERRCLR_0); + writel(1, priv->regs + ERRLOGGER_2_ERRCLR_0); + dsb(sy); +} + +static u32 tegra194_cbb_get_status(struct tegra_cbb *cbb) +{ + struct tegra194_cbb *priv = to_tegra194_cbb(cbb); + u32 value; + + value = readl(priv->regs + ERRLOGGER_0_ERRVLD_0); + value |= (readl(priv->regs + ERRLOGGER_1_ERRVLD_0) << 1); + value |= (readl(priv->regs + ERRLOGGER_2_ERRVLD_0) << 2); + + dsb(sy); + return value; +} + +static u32 tegra194_axi2apb_status(void __iomem *addr) +{ + u32 value; + + value = readl(addr + DMAAPB_X_RAW_INTERRUPT_STATUS); + writel(0xffffffff, addr + DMAAPB_X_RAW_INTERRUPT_STATUS); + + return value; +} + +static bool tegra194_axi2apb_fatal(struct seq_file *file, unsigned int bridge, u32 status) +{ + bool is_fatal = true; + size_t i; + + for (i = 0; i < ARRAY_SIZE(tegra194_axi2apb_error); i++) { + if (status & BIT(i)) { + tegra_cbb_print_err(file, "\t AXI2APB_%d bridge error: %s\n", + bridge + 1, tegra194_axi2apb_error[i]); + if (strstr(tegra194_axi2apb_error[i], "Firewall")) + is_fatal = false; + } + } + + return is_fatal; +} + +/* + * Fetch InitlocalAddress from NOC Aperture lookup table + * using Targflow, Targsubrange + */ +static u32 get_init_localaddress(const struct tegra194_cbb_aperture *info, + const struct tegra194_cbb_aperture *aper, unsigned int max) +{ + unsigned int t_f = 0, t_sr = 0; + u32 addr = 0; + + for (t_f = 0; t_f < max; t_f++) { + if (aper[t_f].targflow == info->targflow) { + t_sr = t_f; + + do { + if (aper[t_sr].targ_subrange == info->targ_subrange) { + addr = aper[t_sr].init_localaddress; + return addr; + } + + if (t_sr >= max) + return 0; + + t_sr++; + } while (aper[t_sr].targflow == aper[t_sr - 1].targflow); + + t_f = t_sr; + } + } + + return addr; +} + +static void print_errlog5(struct seq_file *file, struct tegra194_cbb *cbb) +{ + struct tegra194_cbb_userbits userbits; + + cbb->noc->parse_userbits(&userbits, cbb->errlog5); + + if (!strcmp(cbb->noc->name, "cbb-noc")) { + tegra_cbb_print_err(file, "\t Non-Modify\t\t: %#x\n", userbits.non_mod); + tegra_cbb_print_err(file, "\t AXI ID\t\t: %#x\n", userbits.axi_id); + } + + tegra_cbb_print_err(file, "\t Master ID\t\t: %s\n", + cbb->noc->master_id[userbits.mstr_id]); + tegra_cbb_print_err(file, "\t Security Group(GRPSEC): %#x\n", userbits.grpsec); + tegra_cbb_print_cache(file, userbits.axcache); + tegra_cbb_print_prot(file, userbits.axprot); + tegra_cbb_print_err(file, "\t FALCONSEC\t\t: %#x\n", userbits.falconsec); + tegra_cbb_print_err(file, "\t Virtual Queuing Channel(VQC): %#x\n", userbits.vqc); +} + +/* + * Fetch Base Address/InitlocalAddress from NOC aperture lookup table using TargFlow & + * Targ_subRange extracted from RouteId. Perform address reconstruction as below: + * + * Address = Base Address + (ErrLog3 + ErrLog4) + */ +static void +print_errlog3_4(struct seq_file *file, u32 errlog3, u32 errlog4, + const struct tegra194_cbb_aperture *info, + const struct tegra194_cbb_aperture *aperture, unsigned int max) +{ + u64 addr = (u64)errlog4 << 32 | errlog3; + + /* + * If errlog4[7] = "1", then it's a joker entry. Joker entries are a rare phenomenon and + * such addresses are not reliable. Debugging should be done using only the RouteId + * information. + */ + if (errlog4 & 0x80) + tegra_cbb_print_err(file, "\t debug using RouteId alone as below address is a " + "joker entry and not reliable"); + + addr += get_init_localaddress(info, aperture, max); + + tegra_cbb_print_err(file, "\t Address accessed\t: %#llx\n", addr); +} + +/* + * Get RouteId from ErrLog1+ErrLog2 registers and fetch values of + * InitFlow, TargFlow, Targ_subRange and SeqId values from RouteId + */ +static void +print_errlog1_2(struct seq_file *file, struct tegra194_cbb *cbb, + struct tegra194_cbb_aperture *info) +{ + u64 routeid = (u64)cbb->errlog2 << 32 | cbb->errlog1; + u32 seqid = 0; + + tegra_cbb_print_err(file, "\t RouteId\t\t: %#llx\n", routeid); + + cbb->noc->parse_routeid(info, routeid); + + tegra_cbb_print_err(file, "\t InitFlow\t\t: %s\n", + cbb->noc->routeid_initflow[info->initflow]); + + tegra_cbb_print_err(file, "\t Targflow\t\t: %s\n", + cbb->noc->routeid_targflow[info->targflow]); + + tegra_cbb_print_err(file, "\t TargSubRange\t\t: %d\n", info->targ_subrange); + tegra_cbb_print_err(file, "\t SeqId\t\t\t: %d\n", seqid); +} + +/* + * Print transcation type, error code and description from ErrLog0 for all + * errors. For NOC slave errors, all relevant error info is printed using + * ErrLog0 only. But additional information is printed for errors from + * APB slaves because for them: + * - All errors are logged as SLV(slave) errors due to APB having only single + * bit pslverr to report all errors. + * - Exact cause is printed by reading DMAAPB_X_RAW_INTERRUPT_STATUS register. + * - The driver prints information showing AXI2APB bridge and exact error + * only if there is error in any AXI2APB slave. + * - There is still no way to disambiguate a DEC error from SLV error type. + */ +static bool print_errlog0(struct seq_file *file, struct tegra194_cbb *cbb) +{ + struct tegra194_cbb_packet_header hdr; + bool is_fatal = true; + + hdr.lock = cbb->errlog0 & 0x1; + hdr.opc = FIELD_GET(CBB_ERR_OPC, cbb->errlog0); + hdr.errcode = FIELD_GET(CBB_ERR_ERRCODE, cbb->errlog0); + hdr.len1 = FIELD_GET(CBB_ERR_LEN1, cbb->errlog0); + hdr.format = (cbb->errlog0 >> 31); + + tegra_cbb_print_err(file, "\t Transaction Type\t: %s\n", + tegra194_cbb_trantype[hdr.opc]); + tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", + tegra194_cbb_errors[hdr.errcode].code); + tegra_cbb_print_err(file, "\t Error Source\t\t: %s\n", + tegra194_cbb_errors[hdr.errcode].source); + tegra_cbb_print_err(file, "\t Error Description\t: %s\n", + tegra194_cbb_errors[hdr.errcode].desc); + + /* + * Do not crash system for errors which are only notifications to indicate a transaction + * was not allowed to be attempted. + */ + if (!strcmp(tegra194_cbb_errors[hdr.errcode].code, "SEC") || + !strcmp(tegra194_cbb_errors[hdr.errcode].code, "DEC") || + !strcmp(tegra194_cbb_errors[hdr.errcode].code, "UNS") || + !strcmp(tegra194_cbb_errors[hdr.errcode].code, "DISC")) { + is_fatal = false; + } else if (!strcmp(tegra194_cbb_errors[hdr.errcode].code, "SLV") && + cbb->num_bridges > 0) { + unsigned int i; + u32 status; + + /* For all SLV errors, read DMAAPB_X_RAW_INTERRUPT_STATUS + * register to get error status for all AXI2APB bridges. + * Print bridge details if a bit is set in a bridge's + * status register due to error in a APB slave connected + * to that bridge. For other NOC slaves, none of the status + * register will be set. + */ + + for (i = 0; i < cbb->num_bridges; i++) { + status = tegra194_axi2apb_status(cbb->bridges[i].base); + + if (status) + is_fatal = tegra194_axi2apb_fatal(file, i, status); + } + } + + tegra_cbb_print_err(file, "\t Packet header Lock\t: %d\n", hdr.lock); + tegra_cbb_print_err(file, "\t Packet header Len1\t: %d\n", hdr.len1); + + if (hdr.format) + tegra_cbb_print_err(file, "\t NOC protocol version\t: %s\n", + "version >= 2.7"); + else + tegra_cbb_print_err(file, "\t NOC protocol version\t: %s\n", + "version < 2.7"); + + return is_fatal; +} + +/* + * Print debug information about failed transaction using + * ErrLog registers of error loggger having ErrVld set + */ +static bool print_errloggerX_info(struct seq_file *file, struct tegra194_cbb *cbb, + int errloggerX) +{ + struct tegra194_cbb_aperture info = { 0, }; + bool is_fatal = true; + + tegra_cbb_print_err(file, "\tError Logger\t\t: %d\n", errloggerX); + + if (errloggerX == 0) { + cbb->errlog0 = readl(cbb->regs + ERRLOGGER_0_ERRLOG0_0); + cbb->errlog1 = readl(cbb->regs + ERRLOGGER_0_ERRLOG1_0); + cbb->errlog2 = readl(cbb->regs + ERRLOGGER_0_RSVD_00_0); + cbb->errlog3 = readl(cbb->regs + ERRLOGGER_0_ERRLOG3_0); + cbb->errlog4 = readl(cbb->regs + ERRLOGGER_0_ERRLOG4_0); + cbb->errlog5 = readl(cbb->regs + ERRLOGGER_0_ERRLOG5_0); + } else if (errloggerX == 1) { + cbb->errlog0 = readl(cbb->regs + ERRLOGGER_1_ERRLOG0_0); + cbb->errlog1 = readl(cbb->regs + ERRLOGGER_1_ERRLOG1_0); + cbb->errlog2 = readl(cbb->regs + ERRLOGGER_1_RSVD_00_0); + cbb->errlog3 = readl(cbb->regs + ERRLOGGER_1_ERRLOG3_0); + cbb->errlog4 = readl(cbb->regs + ERRLOGGER_1_ERRLOG4_0); + cbb->errlog5 = readl(cbb->regs + ERRLOGGER_1_ERRLOG5_0); + } else if (errloggerX == 2) { + cbb->errlog0 = readl(cbb->regs + ERRLOGGER_2_ERRLOG0_0); + cbb->errlog1 = readl(cbb->regs + ERRLOGGER_2_ERRLOG1_0); + cbb->errlog2 = readl(cbb->regs + ERRLOGGER_2_RSVD_00_0); + cbb->errlog3 = readl(cbb->regs + ERRLOGGER_2_ERRLOG3_0); + cbb->errlog4 = readl(cbb->regs + ERRLOGGER_2_ERRLOG4_0); + cbb->errlog5 = readl(cbb->regs + ERRLOGGER_2_ERRLOG5_0); + } + + tegra_cbb_print_err(file, "\tErrLog0\t\t\t: %#x\n", cbb->errlog0); + is_fatal = print_errlog0(file, cbb); + + tegra_cbb_print_err(file, "\tErrLog1\t\t\t: %#x\n", cbb->errlog1); + tegra_cbb_print_err(file, "\tErrLog2\t\t\t: %#x\n", cbb->errlog2); + print_errlog1_2(file, cbb, &info); + + tegra_cbb_print_err(file, "\tErrLog3\t\t\t: %#x\n", cbb->errlog3); + tegra_cbb_print_err(file, "\tErrLog4\t\t\t: %#x\n", cbb->errlog4); + print_errlog3_4(file, cbb->errlog3, cbb->errlog4, &info, cbb->noc->noc_aperture, + cbb->noc->max_aperture); + + tegra_cbb_print_err(file, "\tErrLog5\t\t\t: %#x\n", cbb->errlog5); + + if (cbb->errlog5) + print_errlog5(file, cbb); + + return is_fatal; +} + +static bool print_errlog(struct seq_file *file, struct tegra194_cbb *cbb, u32 errvld) +{ + bool is_fatal = true; + + pr_crit("**************************************\n"); + pr_crit("CPU:%d, Error:%s\n", smp_processor_id(), cbb->noc->name); + + if (errvld & 0x1) + is_fatal = print_errloggerX_info(file, cbb, 0); + else if (errvld & 0x2) + is_fatal = print_errloggerX_info(file, cbb, 1); + else if (errvld & 0x4) + is_fatal = print_errloggerX_info(file, cbb, 2); + + tegra_cbb_error_clear(&cbb->base); + tegra_cbb_print_err(file, "\t**************************************\n"); + return is_fatal; +} + +#ifdef CONFIG_DEBUG_FS +static DEFINE_MUTEX(cbb_err_mutex); + +static int tegra194_cbb_debugfs_show(struct tegra_cbb *cbb, struct seq_file *file, void *data) +{ + struct tegra_cbb *noc; + + mutex_lock(&cbb_err_mutex); + + list_for_each_entry(noc, &cbb_list, node) { + struct tegra194_cbb *priv = to_tegra194_cbb(noc); + u32 status; + + status = tegra_cbb_get_status(noc); + if (status) + print_errlog(file, priv, status); + } + + mutex_unlock(&cbb_err_mutex); + + return 0; +} +#endif + +/* + * Handler for CBB errors from different initiators + */ +static irqreturn_t tegra194_cbb_err_isr(int irq, void *data) +{ + bool is_inband_err = false, is_fatal = false; + //struct tegra194_cbb *cbb = data; + struct tegra_cbb *noc; + unsigned long flags; + u8 mstr_id = 0; + + spin_lock_irqsave(&cbb_lock, flags); + + /* XXX only process interrupts for "cbb" instead of iterating over all NOCs? */ + list_for_each_entry(noc, &cbb_list, node) { + struct tegra194_cbb *priv = to_tegra194_cbb(noc); + u32 status = 0; + + status = tegra_cbb_get_status(noc); + + if (status && ((irq == priv->sec_irq) || (irq == priv->nonsec_irq))) { + tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@%llx, irq=%d\n", + smp_processor_id(), priv->noc->name, priv->res->start, + irq); + + mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->errlog5) - 1; + is_fatal = print_errlog(NULL, priv, status); + + /* + * If illegal request is from CCPLEX(0x1) + * initiator then call BUG() to crash system. + */ + if ((mstr_id == 0x1) && priv->noc->erd_mask_inband_err) + is_inband_err = 1; + } + } + + spin_unlock_irqrestore(&cbb_lock, flags); + + if (is_inband_err) { + if (is_fatal) + BUG(); + else + WARN(true, "Warning due to CBB Error\n"); + } + + return IRQ_HANDLED; +} + +/* + * Register handler for CBB_NONSECURE & CBB_SECURE interrupts + * for reporting CBB errors + */ +static int tegra194_cbb_interrupt_enable(struct tegra_cbb *cbb) +{ + struct tegra194_cbb *priv = to_tegra194_cbb(cbb); + struct device *dev = cbb->dev; + int err; + + if (priv->sec_irq) { + err = devm_request_irq(dev, priv->sec_irq, tegra194_cbb_err_isr, 0, dev_name(dev), + priv); + if (err) { + dev_err(dev, "failed to register interrupt %u: %d\n", priv->sec_irq, err); + return err; + } + } + + if (priv->nonsec_irq) { + err = devm_request_irq(dev, priv->nonsec_irq, tegra194_cbb_err_isr, 0, + dev_name(dev), priv); + if (err) { + dev_err(dev, "failed to register interrupt %u: %d\n", priv->nonsec_irq, + err); + return err; + } + } + + return 0; +} + +static void tegra194_cbb_error_enable(struct tegra_cbb *cbb) +{ + /* + * Set “StallEn=1” to enable queuing of error packets till + * first is served & cleared + */ + tegra_cbb_stall_enable(cbb); + + /* set “FaultEn=1” to enable error reporting signal “Fault” */ + tegra_cbb_fault_enable(cbb); +} + +static const struct tegra_cbb_ops tegra194_cbb_ops = { + .get_status = tegra194_cbb_get_status, + .error_clear = tegra194_cbb_error_clear, + .fault_enable = tegra194_cbb_fault_enable, + .stall_enable = tegra194_cbb_stall_enable, + .error_enable = tegra194_cbb_error_enable, + .interrupt_enable = tegra194_cbb_interrupt_enable, +#ifdef CONFIG_DEBUG_FS + .debugfs_show = tegra194_cbb_debugfs_show, +#endif +}; + +static struct tegra194_cbb_noc_data tegra194_cbb_central_noc_data = { + .name = "cbb-noc", + .erd_mask_inband_err = true, + .master_id = tegra194_master_id, + .noc_aperture = tegra194_cbbcentralnoc_apert_lookup, + .max_aperture = ARRAY_SIZE(tegra194_cbbcentralnoc_apert_lookup), + .routeid_initflow = tegra194_cbbcentralnoc_routeid_initflow, + .routeid_targflow = tegra194_cbbcentralnoc_routeid_targflow, + .parse_routeid = cbbcentralnoc_parse_routeid, + .parse_userbits = cbbcentralnoc_parse_userbits +}; + +static struct tegra194_cbb_noc_data tegra194_aon_noc_data = { + .name = "aon-noc", + .erd_mask_inband_err = false, + .master_id = tegra194_master_id, + .noc_aperture = tegra194_aonnoc_aperture_lookup, + .max_aperture = ARRAY_SIZE(tegra194_aonnoc_aperture_lookup), + .routeid_initflow = tegra194_aonnoc_routeid_initflow, + .routeid_targflow = tegra194_aonnoc_routeid_targflow, + .parse_routeid = aonnoc_parse_routeid, + .parse_userbits = clusternoc_parse_userbits +}; + +static struct tegra194_cbb_noc_data tegra194_bpmp_noc_data = { + .name = "bpmp-noc", + .erd_mask_inband_err = false, + .master_id = tegra194_master_id, + .noc_aperture = tegra194_bpmpnoc_apert_lookup, + .max_aperture = ARRAY_SIZE(tegra194_bpmpnoc_apert_lookup), + .routeid_initflow = tegra194_bpmpnoc_routeid_initflow, + .routeid_targflow = tegra194_bpmpnoc_routeid_targflow, + .parse_routeid = bpmpnoc_parse_routeid, + .parse_userbits = clusternoc_parse_userbits +}; + +static struct tegra194_cbb_noc_data tegra194_rce_noc_data = { + .name = "rce-noc", + .erd_mask_inband_err = false, + .master_id = tegra194_master_id, + .noc_aperture = tegra194_scenoc_apert_lookup, + .max_aperture = ARRAY_SIZE(tegra194_scenoc_apert_lookup), + .routeid_initflow = tegra194_scenoc_routeid_initflow, + .routeid_targflow = tegra194_scenoc_routeid_targflow, + .parse_routeid = scenoc_parse_routeid, + .parse_userbits = clusternoc_parse_userbits +}; + +static struct tegra194_cbb_noc_data tegra194_sce_noc_data = { + .name = "sce-noc", + .erd_mask_inband_err = false, + .master_id = tegra194_master_id, + .noc_aperture = tegra194_scenoc_apert_lookup, + .max_aperture = ARRAY_SIZE(tegra194_scenoc_apert_lookup), + .routeid_initflow = tegra194_scenoc_routeid_initflow, + .routeid_targflow = tegra194_scenoc_routeid_targflow, + .parse_routeid = scenoc_parse_routeid, + .parse_userbits = clusternoc_parse_userbits +}; + +static const struct of_device_id tegra194_cbb_match[] = { + { .compatible = "nvidia,tegra194-cbb-noc", .data = &tegra194_cbb_central_noc_data }, + { .compatible = "nvidia,tegra194-aon-noc", .data = &tegra194_aon_noc_data }, + { .compatible = "nvidia,tegra194-bpmp-noc", .data = &tegra194_bpmp_noc_data }, + { .compatible = "nvidia,tegra194-rce-noc", .data = &tegra194_rce_noc_data }, + { .compatible = "nvidia,tegra194-sce-noc", .data = &tegra194_sce_noc_data }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, tegra194_cbb_match); + +static int tegra194_cbb_get_bridges(struct tegra194_cbb *cbb, struct device_node *np) +{ + struct tegra_cbb *entry; + struct resource res; + unsigned long flags; + unsigned int i; + int err; + + spin_lock_irqsave(&cbb_lock, flags); + + list_for_each_entry(entry, &cbb_list, node) { + struct tegra194_cbb *priv = to_tegra194_cbb(entry); + + if (priv->bridges) { + cbb->num_bridges = priv->num_bridges; + cbb->bridges = priv->bridges; + break; + } + } + + spin_unlock_irqrestore(&cbb_lock, flags); + + if (!cbb->bridges) { + while (of_address_to_resource(np, cbb->num_bridges, &res) == 0) + cbb->num_bridges++; + + cbb->bridges = devm_kcalloc(cbb->base.dev, cbb->num_bridges, + sizeof(*cbb->bridges), GFP_KERNEL); + if (!cbb->bridges) + return -ENOMEM; + + for (i = 0; i < cbb->num_bridges; i++) { + err = of_address_to_resource(np, i, &cbb->bridges[i].res); + if (err < 0) + return err; + + cbb->bridges[i].base = devm_ioremap_resource(cbb->base.dev, + &cbb->bridges[i].res); + if (IS_ERR(cbb->bridges[i].base)) { + dev_err(cbb->base.dev, "failed to map AXI2APB range\n"); + return PTR_ERR(cbb->bridges[i].base); + } + } + } + + if (cbb->num_bridges > 0) { + dev_dbg(cbb->base.dev, "AXI2APB bridge info present:\n"); + + for (i = 0; i < cbb->num_bridges; i++) + dev_dbg(cbb->base.dev, " %u: %pR\n", i, &cbb->bridges[i].res); + } + + return 0; +} + +static int tegra194_cbb_probe(struct platform_device *pdev) +{ + const struct tegra194_cbb_noc_data *noc; + struct tegra194_cbb *cbb; + struct device_node *np; + unsigned long flags; + int err; + + noc = of_device_get_match_data(&pdev->dev); + + if (noc->erd_mask_inband_err) { + /* + * Set Error Response Disable(ERD) bit to mask SError/inband + * error and only trigger interrupts for illegal access from + * CCPLEX initiator. + */ + err = tegra194_miscreg_mask_serror(); + if (err) { + dev_err(&pdev->dev, "couldn't mask inband errors\n"); + return err; + } + } + + cbb = devm_kzalloc(&pdev->dev, sizeof(*cbb), GFP_KERNEL); + if (!cbb) + return -ENOMEM; + + INIT_LIST_HEAD(&cbb->base.node); + cbb->base.ops = &tegra194_cbb_ops; + cbb->base.dev = &pdev->dev; + cbb->noc = noc; + + cbb->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &cbb->res); + if (IS_ERR(cbb->regs)) + return PTR_ERR(cbb->regs); + + err = tegra_cbb_get_irq(pdev, &cbb->nonsec_irq, &cbb->sec_irq); + if (err) + return err; + + np = of_parse_phandle(pdev->dev.of_node, "nvidia,axi2apb", 0); + if (np) { + err = tegra194_cbb_get_bridges(cbb, np); + of_node_put(np); + if (err < 0) + return err; + } + + platform_set_drvdata(pdev, cbb); + + spin_lock_irqsave(&cbb_lock, flags); + list_add(&cbb->base.node, &cbb_list); + spin_unlock_irqrestore(&cbb_lock, flags); + + return tegra_cbb_register(&cbb->base); +} + +static int tegra194_cbb_remove(struct platform_device *pdev) +{ + struct tegra194_cbb *cbb = platform_get_drvdata(pdev); + struct tegra_cbb *noc, *tmp; + unsigned long flags; + + spin_lock_irqsave(&cbb_lock, flags); + + list_for_each_entry_safe(noc, tmp, &cbb_list, node) { + struct tegra194_cbb *priv = to_tegra194_cbb(noc); + + if (cbb->res->start == priv->res->start) { + list_del(&noc->node); + break; + } + } + + spin_unlock_irqrestore(&cbb_lock, flags); + + return 0; +} + +static int __maybe_unused tegra194_cbb_resume_noirq(struct device *dev) +{ + struct tegra194_cbb *cbb = dev_get_drvdata(dev); + + tegra194_cbb_error_enable(&cbb->base); + dsb(sy); + + dev_dbg(dev, "%s resumed\n", cbb->noc->name); + return 0; +} + +static const struct dev_pm_ops tegra194_cbb_pm = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, tegra194_cbb_resume_noirq) +}; + +static struct platform_driver tegra194_cbb_driver = { + .probe = tegra194_cbb_probe, + .remove = tegra194_cbb_remove, + .driver = { + .name = "tegra194-cbb", + .of_match_table = of_match_ptr(tegra194_cbb_match), + .pm = &tegra194_cbb_pm, + }, +}; + +static int __init tegra194_cbb_init(void) +{ + return platform_driver_register(&tegra194_cbb_driver); +} +pure_initcall(tegra194_cbb_init); + +static void __exit tegra194_cbb_exit(void) +{ + platform_driver_unregister(&tegra194_cbb_driver); +} +module_exit(tegra194_cbb_exit); + +MODULE_AUTHOR("Sumit Gupta "); +MODULE_DESCRIPTION("Control Backbone error handling driver for Tegra194"); +MODULE_LICENSE("GPL"); diff --git a/include/soc/tegra/tegra-cbb.h b/include/soc/tegra/tegra-cbb.h new file mode 100644 index 000000000000..e864c2ebe794 --- /dev/null +++ b/include/soc/tegra/tegra-cbb.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved + */ + +#ifndef TEGRA_CBB_H +#define TEGRA_CBB_H + +#include + +struct tegra_cbb_error { + const char *code; + const char *source; + const char *desc; +}; + +struct tegra_cbb { + struct device *dev; + const struct tegra_cbb_ops *ops; + struct list_head node; +}; + +struct tegra_cbb_ops { + int (*debugfs_show)(struct tegra_cbb *cbb, struct seq_file *s, void *v); + int (*interrupt_enable)(struct tegra_cbb *cbb); + void (*error_enable)(struct tegra_cbb *cbb); + void (*fault_enable)(struct tegra_cbb *cbb); + void (*stall_enable)(struct tegra_cbb *cbb); + void (*error_clear)(struct tegra_cbb *cbb); + u32 (*get_status)(struct tegra_cbb *cbb); +}; + +int tegra_cbb_get_irq(struct platform_device *pdev, unsigned int *nonsec_irq, + unsigned int *sec_irq); +__printf(2, 3) +void tegra_cbb_print_err(struct seq_file *file, const char *fmt, ...); + +void tegra_cbb_print_cache(struct seq_file *file, u32 cache); +void tegra_cbb_print_prot(struct seq_file *file, u32 prot); +int tegra_cbb_register(struct tegra_cbb *cbb); + +void tegra_cbb_fault_enable(struct tegra_cbb *cbb); +void tegra_cbb_stall_enable(struct tegra_cbb *cbb); +void tegra_cbb_error_clear(struct tegra_cbb *cbb); +u32 tegra_cbb_get_status(struct tegra_cbb *cbb); + +#endif /* TEGRA_CBB_H */ -- cgit v1.2.3 From fc2f151d23145f68a6748c4684a81b70823a489d Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 12 May 2022 01:46:50 +0530 Subject: soc/tegra: cbb: Add driver for Tegra234 CBB 2.0 Adding driver to handle errors from CBB version 2.0 which is used in Tegra234 SoC. The driver prints debug information about failed transaction on receiving interrupt from the error notifier. The error notifier collates the interrupts from various error monitor blocks and presents a single interrupt to the SoC interrupt controller. For timeout errors, the driver also does the lookup to find timed out clients and prints their client ID. Drivers for hardware that needs to be reset on timeout will have to call BPMP from the client IP's driver. BPMP firmware will also clear the timeout bit after resetting the IP so that next transactions are send to them after reset. Signed-off-by: Sumit Gupta Signed-off-by: Thierry Reding --- drivers/soc/tegra/Kconfig | 2 +- drivers/soc/tegra/cbb/Makefile | 1 + drivers/soc/tegra/cbb/tegra234-cbb.c | 846 +++++++++++++++++++++++++++++++++++ 3 files changed, 848 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/tegra/cbb/tegra234-cbb.c (limited to 'drivers') diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 65283a93e78f..bd360488cd82 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -165,7 +165,7 @@ config SOC_TEGRA30_VOLTAGE_COUPLER config SOC_TEGRA_CBB tristate "Tegra driver to handle error from CBB" - depends on ARCH_TEGRA_194_SOC + depends on ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC default y help Support for handling error from Tegra Control Backbone(CBB). diff --git a/drivers/soc/tegra/cbb/Makefile b/drivers/soc/tegra/cbb/Makefile index 711b75610703..e3ac6cdddf5c 100644 --- a/drivers/soc/tegra/cbb/Makefile +++ b/drivers/soc/tegra/cbb/Makefile @@ -5,4 +5,5 @@ ifdef CONFIG_SOC_TEGRA_CBB obj-y += tegra-cbb.o obj-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-cbb.o +obj-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-cbb.o endif diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c new file mode 100644 index 000000000000..c437457aa349 --- /dev/null +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -0,0 +1,846 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved + * + * The driver handles Error's from Control Backbone(CBB) version 2.0. + * generated due to illegal accesses. The driver prints debug information + * about failed transaction on receiving interrupt from Error Notifier. + * Error types supported by CBB2.0 are: + * UNSUPPORTED_ERR, PWRDOWN_ERR, TIMEOUT_ERR, FIREWALL_ERR, DECODE_ERR, + * SLAVE_ERR + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FABRIC_EN_CFG_INTERRUPT_ENABLE_0_0 0x0 +#define FABRIC_EN_CFG_STATUS_0_0 0x40 +#define FABRIC_EN_CFG_ADDR_INDEX_0_0 0x60 +#define FABRIC_EN_CFG_ADDR_LOW_0 0x80 +#define FABRIC_EN_CFG_ADDR_HI_0 0x84 + +#define FABRIC_MN_MASTER_ERR_EN_0 0x200 +#define FABRIC_MN_MASTER_ERR_FORCE_0 0x204 +#define FABRIC_MN_MASTER_ERR_STATUS_0 0x208 +#define FABRIC_MN_MASTER_ERR_OVERFLOW_STATUS_0 0x20c + +#define FABRIC_MN_MASTER_LOG_ERR_STATUS_0 0x300 +#define FABRIC_MN_MASTER_LOG_ADDR_LOW_0 0x304 +#define FABRIC_MN_MASTER_LOG_ADDR_HIGH_0 0x308 +#define FABRIC_MN_MASTER_LOG_ATTRIBUTES0_0 0x30c +#define FABRIC_MN_MASTER_LOG_ATTRIBUTES1_0 0x310 +#define FABRIC_MN_MASTER_LOG_ATTRIBUTES2_0 0x314 +#define FABRIC_MN_MASTER_LOG_USER_BITS0_0 0x318 + +#define AXI_SLV_TIMEOUT_STATUS_0_0 0x8 +#define APB_BLOCK_TMO_STATUS_0 0xc00 +#define APB_BLOCK_NUM_TMO_OFFSET 0x20 + +#define FAB_EM_EL_MSTRID GENMASK(29, 24) +#define FAB_EM_EL_VQC GENMASK(17, 16) +#define FAB_EM_EL_GRPSEC GENMASK(14, 8) +#define FAB_EM_EL_FALCONSEC GENMASK(1, 0) + +#define FAB_EM_EL_FABID GENMASK(20, 16) +#define FAB_EM_EL_SLAVEID GENMASK(7, 0) + +#define FAB_EM_EL_ACCESSID GENMASK(7, 0) + +#define FAB_EM_EL_AXCACHE GENMASK(27, 24) +#define FAB_EM_EL_AXPROT GENMASK(22, 20) +#define FAB_EM_EL_BURSTLENGTH GENMASK(19, 12) +#define FAB_EM_EL_BURSTTYPE GENMASK(9, 8) +#define FAB_EM_EL_BEATSIZE GENMASK(6, 4) +#define FAB_EM_EL_ACCESSTYPE GENMASK(0, 0) + +#define USRBITS_MSTR_ID GENMASK(29, 24) + +#define REQ_SOCKET_ID GENMASK(27, 24) + +enum tegra234_cbb_fabric_ids { + CBB_FAB_ID, + SCE_FAB_ID, + RCE_FAB_ID, + DCE_FAB_ID, + AON_FAB_ID, + PSC_FAB_ID, + BPMP_FAB_ID, + FSI_FAB_ID, + MAX_FAB_ID, +}; + +struct tegra234_slave_lookup { + const char *name; + unsigned int offset; +}; + +struct tegra234_cbb_fabric { + const char *name; + phys_addr_t off_mask_erd; + bool erd_mask_inband_err; + const char * const *master_id; + unsigned int notifier_offset; + const struct tegra_cbb_error *errors; + const struct tegra234_slave_lookup *slave_map; +}; + +struct tegra234_cbb { + struct tegra_cbb base; + + const struct tegra234_cbb_fabric *fabric; + struct resource *res; + void __iomem *regs; + + int num_intr; + int sec_irq; + + /* record */ + void __iomem *mon; + unsigned int type; + u32 mask; + u64 access; + u32 mn_attr0; + u32 mn_attr1; + u32 mn_attr2; + u32 mn_user_bits; +}; + +static inline struct tegra234_cbb *to_tegra234_cbb(struct tegra_cbb *cbb) +{ + return container_of(cbb, struct tegra234_cbb, base); +} + +static LIST_HEAD(cbb_list); +static DEFINE_SPINLOCK(cbb_lock); + +static void tegra234_cbb_fault_enable(struct tegra_cbb *cbb) +{ + struct tegra234_cbb *priv = to_tegra234_cbb(cbb); + void __iomem *addr; + + addr = priv->regs + priv->fabric->notifier_offset; + writel(0x1ff, addr + FABRIC_EN_CFG_INTERRUPT_ENABLE_0_0); + dsb(sy); +} + +static void tegra234_cbb_error_clear(struct tegra_cbb *cbb) +{ + struct tegra234_cbb *priv = to_tegra234_cbb(cbb); + + writel(0x3f, priv->mon + FABRIC_MN_MASTER_ERR_STATUS_0); + dsb(sy); +} + +static u32 tegra234_cbb_get_status(struct tegra_cbb *cbb) +{ + struct tegra234_cbb *priv = to_tegra234_cbb(cbb); + void __iomem *addr; + u32 value; + + addr = priv->regs + priv->fabric->notifier_offset; + value = readl(addr + FABRIC_EN_CFG_STATUS_0_0); + dsb(sy); + + return value; +} + +static void tegra234_cbb_mask_serror(struct tegra234_cbb *cbb) +{ + writel(0x1, cbb->regs + cbb->fabric->off_mask_erd); + dsb(sy); +} + +static u32 tegra234_cbb_get_tmo_slv(void __iomem *addr) +{ + u32 timeout; + + timeout = readl(addr); + return timeout; +} + +static void tegra234_cbb_tmo_slv(struct seq_file *file, const char *slave, void __iomem *addr, + u32 status) +{ + tegra_cbb_print_err(file, "\t %s : %#x\n", slave, status); +} + +static void tegra234_cbb_lookup_apbslv(struct seq_file *file, const char *slave, + void __iomem *base) +{ + unsigned int block = 0; + void __iomem *addr; + char name[64]; + u32 status; + + status = tegra234_cbb_get_tmo_slv(base); + if (status) + tegra_cbb_print_err(file, "\t %s_BLOCK_TMO_STATUS : %#x\n", slave, status); + + while (status) { + if (status & BIT(0)) { + u32 timeout, clients, client = 0; + + addr = base + APB_BLOCK_NUM_TMO_OFFSET + (block * 4); + timeout = tegra234_cbb_get_tmo_slv(addr); + clients = timeout; + + while (timeout) { + if (timeout & BIT(0)) { + if (clients != 0xffffffff) + clients &= BIT(client); + + sprintf(name, "%s_BLOCK%d_TMO", slave, block); + + tegra234_cbb_tmo_slv(file, name, addr, clients); + } + + timeout >>= 1; + client++; + } + } + + status >>= 1; + block++; + } +} + +static void tegra234_lookup_slave_timeout(struct seq_file *file, struct tegra234_cbb *cbb, + u8 slave_id, u8 fab_id) +{ + const struct tegra234_slave_lookup *map = cbb->fabric->slave_map; + void __iomem *addr; + + /* + * 1) Get slave node name and address mapping using slave_id. + * 2) Check if the timed out slave node is APB or AXI. + * 3) If AXI, then print timeout register and reset axi slave + * using _SN_<>_SLV_TIMEOUT_STATUS_0_0 register. + * 4) If APB, then perform an additional lookup to find the client + * which timed out. + * a) Get block number from the index of set bit in + * _SN_AXI2APB_<>_BLOCK_TMO_STATUS_0 register. + * b) Get address of register repective to block number i.e. + * _SN_AXI2APB_<>_BLOCK_TMO_0. + * c) Read the register in above step to get client_id which + * timed out as per the set bits. + * d) Reset the timedout client and print details. + * e) Goto step-a till all bits are set. + */ + + addr = cbb->regs + map[slave_id].offset; + + if (strstr(map[slave_id].name, "AXI2APB")) { + addr += APB_BLOCK_TMO_STATUS_0; + + tegra234_cbb_lookup_apbslv(file, map[slave_id].name, addr); + } else { + char name[64]; + u32 status; + + addr += AXI_SLV_TIMEOUT_STATUS_0_0; + + status = tegra234_cbb_get_tmo_slv(addr); + if (status) { + sprintf(name, "%s_SLV_TIMEOUT_STATUS", map[slave_id].name); + tegra234_cbb_tmo_slv(file, name, addr, status); + } + } +} + +static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb *cbb, u32 status, + u32 overflow) +{ + unsigned int type = 0; + + if (status & (status - 1)) + tegra_cbb_print_err(file, "\t Multiple type of errors reported\n"); + + while (status) { + if (status & 0x1) + tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", + cbb->fabric->errors[type].code); + + status >>= 1; + type++; + } + + type = 0; + + while (overflow) { + if (overflow & 0x1) + tegra_cbb_print_err(file, "\t Overflow\t\t: Multiple %s\n", + cbb->fabric->errors[type].code); + + overflow >>= 1; + type++; + } +} + +static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) +{ + u8 cache_type, prot_type, burst_length, mstr_id, grpsec, vqc, falconsec, beat_size; + u8 access_type, access_id, slave_id, fab_id, burst_type; + char fabric_name[20]; + + mstr_id = FIELD_GET(FAB_EM_EL_MSTRID, cbb->mn_user_bits); + vqc = FIELD_GET(FAB_EM_EL_VQC, cbb->mn_user_bits); + grpsec = FIELD_GET(FAB_EM_EL_GRPSEC, cbb->mn_user_bits); + falconsec = FIELD_GET(FAB_EM_EL_FALCONSEC, cbb->mn_user_bits); + + fab_id = FIELD_GET(FAB_EM_EL_FABID, cbb->mn_attr2); + slave_id = FIELD_GET(FAB_EM_EL_SLAVEID, cbb->mn_attr2); + + access_id = FIELD_GET(FAB_EM_EL_ACCESSID, cbb->mn_attr1); + + cache_type = FIELD_GET(FAB_EM_EL_AXCACHE, cbb->mn_attr0); + prot_type = FIELD_GET(FAB_EM_EL_AXPROT, cbb->mn_attr0); + burst_length = FIELD_GET(FAB_EM_EL_BURSTLENGTH, cbb->mn_attr0); + burst_type = FIELD_GET(FAB_EM_EL_BURSTTYPE, cbb->mn_attr0); + beat_size = FIELD_GET(FAB_EM_EL_BEATSIZE, cbb->mn_attr0); + access_type = FIELD_GET(FAB_EM_EL_ACCESSTYPE, cbb->mn_attr0); + + tegra_cbb_print_err(file, "\n"); + tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", + cbb->fabric->errors[cbb->type].code); + + tegra_cbb_print_err(file, "\t MASTER_ID\t\t: %s\n", cbb->fabric->master_id[mstr_id]); + tegra_cbb_print_err(file, "\t Address\t\t: %#llx\n", cbb->access); + + tegra_cbb_print_cache(file, cache_type); + tegra_cbb_print_prot(file, prot_type); + + tegra_cbb_print_err(file, "\t Access_Type\t\t: %s", (access_type) ? "Write\n" : "Read\n"); + tegra_cbb_print_err(file, "\t Access_ID\t\t: %#x", access_id); + + if (fab_id == PSC_FAB_ID) + strcpy(fabric_name, "psc-fabric"); + else if (fab_id == FSI_FAB_ID) + strcpy(fabric_name, "fsi-fabric"); + else + strcpy(fabric_name, cbb->fabric->name); + + tegra_cbb_print_err(file, "\t Fabric\t\t: %s\n", fabric_name); + tegra_cbb_print_err(file, "\t Slave_Id\t\t: %#x\n", slave_id); + tegra_cbb_print_err(file, "\t Burst_length\t\t: %#x\n", burst_length); + tegra_cbb_print_err(file, "\t Burst_type\t\t: %#x\n", burst_type); + tegra_cbb_print_err(file, "\t Beat_size\t\t: %#x\n", beat_size); + tegra_cbb_print_err(file, "\t VQC\t\t\t: %#x\n", vqc); + tegra_cbb_print_err(file, "\t GRPSEC\t\t: %#x\n", grpsec); + tegra_cbb_print_err(file, "\t FALCONSEC\t\t: %#x\n", falconsec); + + if ((fab_id == PSC_FAB_ID) || (fab_id == FSI_FAB_ID)) + return; + + if (!strcmp(cbb->fabric->errors[cbb->type].code, "TIMEOUT_ERR")) { + tegra234_lookup_slave_timeout(file, cbb, slave_id, fab_id); + return; + } + + tegra_cbb_print_err(file, "\t Slave\t\t\t: %s\n", cbb->fabric->slave_map[slave_id].name); +} + +static int print_errmonX_info(struct seq_file *file, struct tegra234_cbb *cbb) +{ + u32 overflow, status, error; + + status = readl(cbb->mon + FABRIC_MN_MASTER_ERR_STATUS_0); + if (!status) { + pr_err("Error Notifier received a spurious notification\n"); + return -ENODATA; + } + + if (status == 0xffffffff) { + pr_err("CBB registers returning all 1's which is invalid\n"); + return -EINVAL; + } + + overflow = readl(cbb->mon + FABRIC_MN_MASTER_ERR_OVERFLOW_STATUS_0); + + tegra234_cbb_print_error(file, cbb, status, overflow); + + error = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ERR_STATUS_0); + if (!error) { + pr_info("Error Monitor doesn't have Error Logger\n"); + return -EINVAL; + } + + cbb->type = 0; + + while (error) { + if (error & BIT(0)) { + u32 hi, lo; + + hi = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ADDR_HIGH_0); + lo = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ADDR_LOW_0); + + cbb->access = (u64)hi << 32 | lo; + + cbb->mn_attr0 = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ATTRIBUTES0_0); + cbb->mn_attr1 = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ATTRIBUTES1_0); + cbb->mn_attr2 = readl(cbb->mon + FABRIC_MN_MASTER_LOG_ATTRIBUTES2_0); + cbb->mn_user_bits = readl(cbb->mon + FABRIC_MN_MASTER_LOG_USER_BITS0_0); + + print_errlog_err(file, cbb); + } + + cbb->type++; + error >>= 1; + } + + return 0; +} + +static int print_err_notifier(struct seq_file *file, struct tegra234_cbb *cbb, u32 status) +{ + unsigned int index = 0; + int err; + + pr_crit("**************************************\n"); + pr_crit("CPU:%d, Error:%s, Errmon:%d\n", smp_processor_id(), + cbb->fabric->name, status); + + while (status) { + if (status & BIT(0)) { + unsigned int notifier = cbb->fabric->notifier_offset; + u32 hi, lo, mask = BIT(index); + phys_addr_t addr; + u64 offset; + + writel(mask, cbb->regs + notifier + FABRIC_EN_CFG_ADDR_INDEX_0_0); + hi = readl(cbb->regs + notifier + FABRIC_EN_CFG_ADDR_HI_0); + lo = readl(cbb->regs + notifier + FABRIC_EN_CFG_ADDR_LOW_0); + + addr = (u64)hi << 32 | lo; + + offset = addr - cbb->res->start; + cbb->mon = cbb->regs + offset; + cbb->mask = BIT(index); + + err = print_errmonX_info(file, cbb); + tegra234_cbb_error_clear(&cbb->base); + if (err) + return err; + } + + status >>= 1; + index++; + } + + tegra_cbb_print_err(file, "\t**************************************\n"); + return 0; +} + +#ifdef CONFIG_DEBUG_FS +static DEFINE_MUTEX(cbb_debugfs_mutex); + +static int tegra234_cbb_debugfs_show(struct tegra_cbb *cbb, struct seq_file *file, void *data) +{ + int err = 0; + + mutex_lock(&cbb_debugfs_mutex); + + list_for_each_entry(cbb, &cbb_list, node) { + struct tegra234_cbb *priv = to_tegra234_cbb(cbb); + u32 status; + + status = tegra_cbb_get_status(&priv->base); + if (status) { + err = print_err_notifier(file, priv, status); + if (err) + break; + } + } + + mutex_unlock(&cbb_debugfs_mutex); + return err; +} +#endif + +/* + * Handler for CBB errors + */ +static irqreturn_t tegra234_cbb_isr(int irq, void *data) +{ + bool is_inband_err = false; + struct tegra_cbb *cbb; + unsigned long flags; + u8 mstr_id; + int err; + + spin_lock_irqsave(&cbb_lock, flags); + + list_for_each_entry(cbb, &cbb_list, node) { + struct tegra234_cbb *priv = to_tegra234_cbb(cbb); + u32 status = tegra_cbb_get_status(cbb); + + if (status && (irq == priv->sec_irq)) { + tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@%llx, irq=%d\n", + smp_processor_id(), priv->fabric->name, + priv->res->start, irq); + + err = print_err_notifier(NULL, priv, status); + if (err) + goto unlock; + + mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits); + + /* + * If illegal request is from CCPLEX(id:0x1) master then call BUG() to + * crash system. + */ + if ((mstr_id == 0x1) && priv->fabric->off_mask_erd) + is_inband_err = 1; + } + } + +unlock: + spin_unlock_irqrestore(&cbb_lock, flags); + WARN_ON(is_inband_err); + return IRQ_HANDLED; +} + +/* + * Register handler for CBB_SECURE interrupt for reporting errors + */ +static int tegra234_cbb_interrupt_enable(struct tegra_cbb *cbb) +{ + struct tegra234_cbb *priv = to_tegra234_cbb(cbb); + + if (priv->sec_irq) { + int err = devm_request_irq(cbb->dev, priv->sec_irq, tegra234_cbb_isr, 0, + dev_name(cbb->dev), priv); + if (err) { + dev_err(cbb->dev, "failed to register interrupt %u: %d\n", priv->sec_irq, + err); + return err; + } + } + + return 0; +} + +static void tegra234_cbb_error_enable(struct tegra_cbb *cbb) +{ + tegra_cbb_fault_enable(cbb); +} + +static const struct tegra_cbb_ops tegra234_cbb_ops = { + .get_status = tegra234_cbb_get_status, + .error_clear = tegra234_cbb_error_clear, + .fault_enable = tegra234_cbb_fault_enable, + .error_enable = tegra234_cbb_error_enable, + .interrupt_enable = tegra234_cbb_interrupt_enable, +#ifdef CONFIG_DEBUG_FS + .debugfs_show = tegra234_cbb_debugfs_show, +#endif +}; + +static const char * const tegra234_master_id[] = { + [0x00] = "TZ", + [0x01] = "CCPLEX", + [0x02] = "CCPMU", + [0x03] = "BPMP_FW", + [0x04] = "AON", + [0x05] = "SCE", + [0x06] = "GPCDMA_P", + [0x07] = "TSECA_NONSECURE", + [0x08] = "TSECA_LIGHTSECURE", + [0x09] = "TSECA_HEAVYSECURE", + [0x0a] = "CORESIGHT", + [0x0b] = "APE", + [0x0c] = "PEATRANS", + [0x0d] = "JTAGM_DFT", + [0x0e] = "RCE", + [0x0f] = "DCE", + [0x10] = "PSC_FW_USER", + [0x11] = "PSC_FW_SUPERVISOR", + [0x12] = "PSC_FW_MACHINE", + [0x13] = "PSC_BOOT", + [0x14] = "BPMP_BOOT", + [0x15] = "NVDEC_NONSECURE", + [0x16] = "NVDEC_LIGHTSECURE", + [0x17] = "NVDEC_HEAVYSECURE", + [0x18] = "CBB_INTERNAL", + [0x19] = "RSVD" +}; + +static const struct tegra_cbb_error tegra234_cbb_errors[] = { + { + .code = "SLAVE_ERR", + .desc = "Slave being accessed responded with an error" + }, { + .code = "DECODE_ERR", + .desc = "Attempt to access an address hole" + }, { + .code = "FIREWALL_ERR", + .desc = "Attempt to access a region which is firewall protected" + }, { + .code = "TIMEOUT_ERR", + .desc = "No response returned by slave" + }, { + .code = "PWRDOWN_ERR", + .desc = "Attempt to access a portion of fabric that is powered down" + }, { + .code = "UNSUPPORTED_ERR", + .desc = "Attempt to access a slave through an unsupported access" + } +}; + +static const struct tegra234_slave_lookup tegra234_aon_slave_map[] = { + { "AXI2APB", 0x00000 }, + { "AST", 0x14000 }, + { "CBB", 0x15000 }, + { "CPU", 0x16000 }, +}; + +static const struct tegra234_cbb_fabric tegra234_aon_fabric = { + .name = "aon-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_aon_slave_map, + .errors = tegra234_cbb_errors, + .notifier_offset = 0x17000, +}; + +static const struct tegra234_slave_lookup tegra234_bpmp_slave_map[] = { + { "AXI2APB", 0x00000 }, + { "AST0", 0x15000 }, + { "AST1", 0x16000 }, + { "CBB", 0x17000 }, + { "CPU", 0x18000 }, +}; + +static const struct tegra234_cbb_fabric tegra234_bpmp_fabric = { + .name = "bpmp-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_bpmp_slave_map, + .errors = tegra234_cbb_errors, + .notifier_offset = 0x19000, +}; + +static const struct tegra234_slave_lookup tegra234_cbb_slave_map[] = { + { "AON", 0x40000 }, + { "BPMP", 0x41000 }, + { "CBB", 0x42000 }, + { "HOST1X", 0x43000 }, + { "STM", 0x44000 }, + { "FSI", 0x45000 }, + { "PSC", 0x46000 }, + { "PCIE_C1", 0x47000 }, + { "PCIE_C2", 0x48000 }, + { "PCIE_C3", 0x49000 }, + { "PCIE_C0", 0x4a000 }, + { "PCIE_C4", 0x4b000 }, + { "GPU", 0x4c000 }, + { "SMMU0", 0x4d000 }, + { "SMMU1", 0x4e000 }, + { "SMMU2", 0x4f000 }, + { "SMMU3", 0x50000 }, + { "SMMU4", 0x51000 }, + { "PCIE_C10", 0x52000 }, + { "PCIE_C7", 0x53000 }, + { "PCIE_C8", 0x54000 }, + { "PCIE_C9", 0x55000 }, + { "PCIE_C5", 0x56000 }, + { "PCIE_C6", 0x57000 }, + { "DCE", 0x58000 }, + { "RCE", 0x59000 }, + { "SCE", 0x5a000 }, + { "AXI2APB_1", 0x70000 }, + { "AXI2APB_10", 0x71000 }, + { "AXI2APB_11", 0x72000 }, + { "AXI2APB_12", 0x73000 }, + { "AXI2APB_13", 0x74000 }, + { "AXI2APB_14", 0x75000 }, + { "AXI2APB_15", 0x76000 }, + { "AXI2APB_16", 0x77000 }, + { "AXI2APB_17", 0x78000 }, + { "AXI2APB_18", 0x79000 }, + { "AXI2APB_19", 0x7a000 }, + { "AXI2APB_2", 0x7b000 }, + { "AXI2APB_20", 0x7c000 }, + { "AXI2APB_21", 0x7d000 }, + { "AXI2APB_22", 0x7e000 }, + { "AXI2APB_23", 0x7f000 }, + { "AXI2APB_25", 0x80000 }, + { "AXI2APB_26", 0x81000 }, + { "AXI2APB_27", 0x82000 }, + { "AXI2APB_28", 0x83000 }, + { "AXI2APB_29", 0x84000 }, + { "AXI2APB_30", 0x85000 }, + { "AXI2APB_31", 0x86000 }, + { "AXI2APB_32", 0x87000 }, + { "AXI2APB_33", 0x88000 }, + { "AXI2APB_34", 0x89000 }, + { "AXI2APB_35", 0x92000 }, + { "AXI2APB_4", 0x8b000 }, + { "AXI2APB_5", 0x8c000 }, + { "AXI2APB_6", 0x8d000 }, + { "AXI2APB_7", 0x8e000 }, + { "AXI2APB_8", 0x8f000 }, + { "AXI2APB_9", 0x90000 }, + { "AXI2APB_3", 0x91000 }, +}; + +static const struct tegra234_cbb_fabric tegra234_cbb_fabric = { + .name = "cbb-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_cbb_slave_map, + .errors = tegra234_cbb_errors, + .notifier_offset = 0x60000, + .off_mask_erd = 0x3a004 +}; + +static const struct tegra234_slave_lookup tegra234_dce_slave_map[] = { + { "AXI2APB", 0x00000 }, + { "AST0", 0x15000 }, + { "AST1", 0x16000 }, + { "CPU", 0x18000 }, +}; + +static const struct tegra234_cbb_fabric tegra234_dce_fabric = { + .name = "dce-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_dce_slave_map, + .errors = tegra234_cbb_errors, + .notifier_offset = 0x19000, +}; + +static const struct tegra234_slave_lookup tegra234_rce_slave_map[] = { + { "AXI2APB", 0x00000 }, + { "AST0", 0x15000 }, + { "AST1", 0x16000 }, + { "CPU", 0x18000 }, +}; + +static const struct tegra234_cbb_fabric tegra234_rce_fabric = { + .name = "rce-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_rce_slave_map, + .errors = tegra234_cbb_errors, + .notifier_offset = 0x19000, +}; + +static const struct tegra234_slave_lookup tegra234_sce_slave_map[] = { + { "AXI2APB", 0x00000 }, + { "AST0", 0x15000 }, + { "AST1", 0x16000 }, + { "CBB", 0x17000 }, + { "CPU", 0x18000 }, +}; + +static const struct tegra234_cbb_fabric tegra234_sce_fabric = { + .name = "sce-fabric", + .master_id = tegra234_master_id, + .slave_map = tegra234_sce_slave_map, + .errors = tegra234_cbb_errors, + .notifier_offset = 0x19000, +}; + +static const struct of_device_id tegra234_cbb_dt_ids[] = { + { .compatible = "nvidia,tegra234-cbb-fabric", .data = &tegra234_cbb_fabric }, + { .compatible = "nvidia,tegra234-aon-fabric", .data = &tegra234_aon_fabric }, + { .compatible = "nvidia,tegra234-bpmp-fabric", .data = &tegra234_bpmp_fabric }, + { .compatible = "nvidia,tegra234-dce-fabric", .data = &tegra234_dce_fabric }, + { .compatible = "nvidia,tegra234-rce-fabric", .data = &tegra234_rce_fabric }, + { .compatible = "nvidia,tegra234-sce-fabric", .data = &tegra234_sce_fabric }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tegra234_cbb_dt_ids); + +static int tegra234_cbb_probe(struct platform_device *pdev) +{ + const struct tegra234_cbb_fabric *fabric; + struct tegra234_cbb *cbb; + unsigned long flags = 0; + int err; + + fabric = of_device_get_match_data(&pdev->dev); + + cbb = devm_kzalloc(&pdev->dev, sizeof(*cbb), GFP_KERNEL); + if (!cbb) + return -ENOMEM; + + INIT_LIST_HEAD(&cbb->base.node); + cbb->base.ops = &tegra234_cbb_ops; + cbb->base.dev = &pdev->dev; + cbb->fabric = fabric; + + cbb->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &cbb->res); + if (IS_ERR(cbb->regs)) + return PTR_ERR(cbb->regs); + + err = tegra_cbb_get_irq(pdev, NULL, &cbb->sec_irq); + if (err) + return err; + + platform_set_drvdata(pdev, cbb); + + spin_lock_irqsave(&cbb_lock, flags); + list_add(&cbb->base.node, &cbb_list); + spin_unlock_irqrestore(&cbb_lock, flags); + + /* set ERD bit to mask SError and generate interrupt to report error */ + if (cbb->fabric->off_mask_erd) + tegra234_cbb_mask_serror(cbb); + + return tegra_cbb_register(&cbb->base); +} + +static int tegra234_cbb_remove(struct platform_device *pdev) +{ + return 0; +} + +static int __maybe_unused tegra234_cbb_resume_noirq(struct device *dev) +{ + struct tegra234_cbb *cbb = dev_get_drvdata(dev); + + tegra234_cbb_error_enable(&cbb->base); + + dev_dbg(dev, "%s resumed\n", cbb->fabric->name); + + return 0; +} + +static const struct dev_pm_ops tegra234_cbb_pm = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, tegra234_cbb_resume_noirq) +}; + +static struct platform_driver tegra234_cbb_driver = { + .probe = tegra234_cbb_probe, + .remove = tegra234_cbb_remove, + .driver = { + .name = "tegra234-cbb", + .of_match_table = tegra234_cbb_dt_ids, + .pm = &tegra234_cbb_pm, + }, +}; + +static int __init tegra234_cbb_init(void) +{ + return platform_driver_register(&tegra234_cbb_driver); +} +pure_initcall(tegra234_cbb_init); + +static void __exit tegra234_cbb_exit(void) +{ + platform_driver_unregister(&tegra234_cbb_driver); +} +module_exit(tegra234_cbb_exit); + +MODULE_DESCRIPTION("Control Backbone 2.0 error handling driver for Tegra234"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 53283105cab6f408968b7546826303ad329e9983 Mon Sep 17 00:00:00 2001 From: Sumit Gupta Date: Thu, 12 May 2022 01:46:51 +0530 Subject: soc/tegra: cbb: Add support for Tegra241 (Grace) Adding support for Tegra241 (Grace) which uses fabrics based on the CBB 2.0 architecture. Since Tegra241 requires ACPI, implement ACPI-based probe support. Fabrics reporting errors in Tegra241 are "CBB" and "BPMP". The CBB fabric connects various other CBB 2.0 based fabrics and also services the Initiators and Targets which are connected to itself. The BPMP fabric is present in the BPMP cluster. Signed-off-by: Sumit Gupta Signed-off-by: Thierry Reding --- drivers/soc/tegra/cbb/tegra234-cbb.c | 271 ++++++++++++++++++++++++++++++++++- 1 file changed, 269 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c index c437457aa349..3528f9e15d5c 100644 --- a/drivers/soc/tegra/cbb/tegra234-cbb.c +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -10,6 +10,7 @@ * SLAVE_ERR */ +#include #include #include #include @@ -293,14 +294,33 @@ static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) { u8 cache_type, prot_type, burst_length, mstr_id, grpsec, vqc, falconsec, beat_size; - u8 access_type, access_id, slave_id, fab_id, burst_type; + u8 access_type, access_id, requester_socket_id, local_socket_id, slave_id, fab_id; char fabric_name[20]; + bool is_numa = false; + u8 burst_type; + + if (num_possible_nodes() > 1) + is_numa = true; mstr_id = FIELD_GET(FAB_EM_EL_MSTRID, cbb->mn_user_bits); vqc = FIELD_GET(FAB_EM_EL_VQC, cbb->mn_user_bits); grpsec = FIELD_GET(FAB_EM_EL_GRPSEC, cbb->mn_user_bits); falconsec = FIELD_GET(FAB_EM_EL_FALCONSEC, cbb->mn_user_bits); + /* + * For SOC with multiple NUMA nodes, print cross socket access + * errors only if initiator/master_id is CCPLEX, CPMU or GPU. + */ + if (is_numa) { + local_socket_id = numa_node_id(); + requester_socket_id = FIELD_GET(REQ_SOCKET_ID, cbb->mn_attr2); + + if (requester_socket_id != local_socket_id) { + if ((mstr_id != 0x1) && (mstr_id != 0x2) && (mstr_id != 0xB)) + return; + } + } + fab_id = FIELD_GET(FAB_EM_EL_FABID, cbb->mn_attr2); slave_id = FIELD_GET(FAB_EM_EL_SLAVEID, cbb->mn_attr2); @@ -333,6 +353,15 @@ static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) else strcpy(fabric_name, cbb->fabric->name); + if (is_numa) { + tegra_cbb_print_err(file, "\t Requester_Socket_Id\t: %#x\n", + requester_socket_id); + tegra_cbb_print_err(file, "\t Local_Socket_Id\t: %#x\n", + local_socket_id); + tegra_cbb_print_err(file, "\t No. of NUMA_NODES\t: %#x\n", + num_possible_nodes()); + } + tegra_cbb_print_err(file, "\t Fabric\t\t: %s\n", fabric_name); tegra_cbb_print_err(file, "\t Slave_Id\t\t: %#x\n", slave_id); tegra_cbb_print_err(file, "\t Burst_length\t\t: %#x\n", burst_length); @@ -750,6 +779,200 @@ static const struct tegra234_cbb_fabric tegra234_sce_fabric = { .notifier_offset = 0x19000, }; +static const char * const tegra241_master_id[] = { + [0x0] = "TZ", + [0x1] = "CCPLEX", + [0x2] = "CCPMU", + [0x3] = "BPMP_FW", + [0x4] = "PSC_FW_USER", + [0x5] = "PSC_FW_SUPERVISOR", + [0x6] = "PSC_FW_MACHINE", + [0x7] = "PSC_BOOT", + [0x8] = "BPMP_BOOT", + [0x9] = "JTAGM_DFT", + [0xa] = "CORESIGHT", + [0xb] = "GPU", + [0xc] = "PEATRANS", + [0xd ... 0x3f] = "RSVD" +}; + +/* + * Possible causes for Slave and Timeout errors. + * SLAVE_ERR: + * Slave being accessed responded with an error. Slave could return + * an error for various cases : + * Unsupported access, clamp setting when power gated, register + * level firewall(SCR), address hole within the slave, etc + * + * TIMEOUT_ERR: + * No response returned by slave. Can be due to slave being clock + * gated, under reset, powered down or slave inability to respond + * for an internal slave issue + */ +static const struct tegra_cbb_error tegra241_cbb_errors[] = { + { + .code = "SLAVE_ERR", + .desc = "Slave being accessed responded with an error." + }, { + .code = "DECODE_ERR", + .desc = "Attempt to access an address hole or Reserved region of memory." + }, { + .code = "FIREWALL_ERR", + .desc = "Attempt to access a region which is firewalled." + }, { + .code = "TIMEOUT_ERR", + .desc = "No response returned by slave." + }, { + .code = "PWRDOWN_ERR", + .desc = "Attempt to access a portion of the fabric that is powered down." + }, { + .code = "UNSUPPORTED_ERR", + .desc = "Attempt to access a slave through an unsupported access." + }, { + .code = "POISON_ERR", + .desc = "Slave responds with poison error to indicate error in data." + }, { + .code = "RSVD" + }, { + .code = "RSVD" + }, { + .code = "RSVD" + }, { + .code = "RSVD" + }, { + .code = "RSVD" + }, { + .code = "RSVD" + }, { + .code = "RSVD" + }, { + .code = "RSVD" + }, { + .code = "RSVD" + }, { + .code = "NO_SUCH_ADDRESS_ERR", + .desc = "The address belongs to the pri_target range but there is no register " + "implemented at the address." + }, { + .code = "TASK_ERR", + .desc = "Attempt to update a PRI task when the current task has still not " + "completed." + }, { + .code = "EXTERNAL_ERR", + .desc = "Indicates that an external PRI register access met with an error due to " + "any issue in the unit." + }, { + .code = "INDEX_ERR", + .desc = "Applicable to PRI index aperture pair, when the programmed index is " + "outside the range defined in the manual." + }, { + .code = "RESET_ERR", + .desc = "Target in Reset Error: Attempt to access a SubPri or external PRI " + "register but they are in reset." + }, { + .code = "REGISTER_RST_ERR", + .desc = "Attempt to access a PRI register but the register is partial or " + "completely in reset." + }, { + .code = "POWER_GATED_ERR", + .desc = "Returned by external PRI client when the external access goes to a power " + "gated domain." + }, { + .code = "SUBPRI_FS_ERR", + .desc = "Subpri is floorswept: Attempt to access a subpri through the main pri " + "target but subPri logic is floorswept." + }, { + .code = "SUBPRI_CLK_OFF_ERR", + .desc = "Subpri clock is off: Attempt to access a subpri through the main pri " + "target but subPris clock is gated/off." + }, +}; + +static const struct tegra234_slave_lookup tegra241_cbb_slave_map[] = { + { "CCPLEX", 0x50000 }, + { "PCIE_C8", 0x51000 }, + { "PCIE_C9", 0x52000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "AON", 0x5b000 }, + { "BPMP", 0x5c000 }, + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "PSC", 0x5d000 }, + { "STM", 0x5e000 }, + { "AXI2APB_1", 0x70000 }, + { "AXI2APB_10", 0x71000 }, + { "AXI2APB_11", 0x72000 }, + { "AXI2APB_12", 0x73000 }, + { "AXI2APB_13", 0x74000 }, + { "AXI2APB_14", 0x75000 }, + { "AXI2APB_15", 0x76000 }, + { "AXI2APB_16", 0x77000 }, + { "AXI2APB_17", 0x78000 }, + { "AXI2APB_18", 0x79000 }, + { "AXI2APB_19", 0x7a000 }, + { "AXI2APB_2", 0x7b000 }, + { "AXI2APB_20", 0x7c000 }, + { "AXI2APB_4", 0x87000 }, + { "AXI2APB_5", 0x88000 }, + { "AXI2APB_6", 0x89000 }, + { "AXI2APB_7", 0x8a000 }, + { "AXI2APB_8", 0x8b000 }, + { "AXI2APB_9", 0x8c000 }, + { "AXI2APB_3", 0x8d000 }, + { "AXI2APB_21", 0x7d000 }, + { "AXI2APB_22", 0x7e000 }, + { "AXI2APB_23", 0x7f000 }, + { "AXI2APB_24", 0x80000 }, + { "AXI2APB_25", 0x81000 }, + { "AXI2APB_26", 0x82000 }, + { "AXI2APB_27", 0x83000 }, + { "AXI2APB_28", 0x84000 }, + { "PCIE_C4", 0x53000 }, + { "PCIE_C5", 0x54000 }, + { "PCIE_C6", 0x55000 }, + { "PCIE_C7", 0x56000 }, + { "PCIE_C2", 0x57000 }, + { "PCIE_C3", 0x58000 }, + { "PCIE_C0", 0x59000 }, + { "PCIE_C1", 0x5a000 }, + { "AXI2APB_29", 0x85000 }, + { "AXI2APB_30", 0x86000 }, +}; + +static const struct tegra234_cbb_fabric tegra241_cbb_fabric = { + .name = "cbb-fabric", + .master_id = tegra241_master_id, + .slave_map = tegra241_cbb_slave_map, + .errors = tegra241_cbb_errors, + .notifier_offset = 0x60000, + .off_mask_erd = 0x40004, +}; + +static const struct tegra234_slave_lookup tegra241_bpmp_slave_map[] = { + { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, + { "CBB", 0x15000 }, + { "CPU", 0x16000 }, + { "AXI2APB", 0x00000 }, + { "DBB0", 0x17000 }, + { "DBB1", 0x18000 }, +}; + +static const struct tegra234_cbb_fabric tegra241_bpmp_fabric = { + .name = "bpmp-fabric", + .master_id = tegra241_master_id, + .slave_map = tegra241_bpmp_slave_map, + .errors = tegra241_cbb_errors, + .notifier_offset = 0x19000, +}; + static const struct of_device_id tegra234_cbb_dt_ids[] = { { .compatible = "nvidia,tegra234-cbb-fabric", .data = &tegra234_cbb_fabric }, { .compatible = "nvidia,tegra234-aon-fabric", .data = &tegra234_aon_fabric }, @@ -761,6 +984,37 @@ static const struct of_device_id tegra234_cbb_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, tegra234_cbb_dt_ids); +struct tegra234_cbb_acpi_uid { + const char *hid; + const char *uid; + const struct tegra234_cbb_fabric *fabric; +}; + +static const struct tegra234_cbb_acpi_uid tegra234_cbb_acpi_uids[] = { + { "NVDA1070", "1", &tegra241_cbb_fabric }, + { "NVDA1070", "2", &tegra241_bpmp_fabric }, + { }, +}; + +static const struct +tegra234_cbb_fabric *tegra234_cbb_acpi_get_fabric(struct acpi_device *adev) +{ + const struct tegra234_cbb_acpi_uid *entry; + + for (entry = tegra234_cbb_acpi_uids; entry->hid; entry++) { + if (acpi_dev_hid_uid_match(adev, entry->hid, entry->uid)) + return entry->fabric; + } + + return NULL; +} + +static const struct acpi_device_id tegra241_cbb_acpi_ids[] = { + { "NVDA1070" }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, tegra241_cbb_acpi_ids); + static int tegra234_cbb_probe(struct platform_device *pdev) { const struct tegra234_cbb_fabric *fabric; @@ -768,7 +1022,19 @@ static int tegra234_cbb_probe(struct platform_device *pdev) unsigned long flags = 0; int err; - fabric = of_device_get_match_data(&pdev->dev); + if (pdev->dev.of_node) { + fabric = of_device_get_match_data(&pdev->dev); + } else { + struct acpi_device *device = ACPI_COMPANION(&pdev->dev); + if (!device) + return -ENODEV; + + fabric = tegra234_cbb_acpi_get_fabric(device); + if (!fabric) { + dev_err(&pdev->dev, "no device match found\n"); + return -ENODEV; + } + } cbb = devm_kzalloc(&pdev->dev, sizeof(*cbb), GFP_KERNEL); if (!cbb) @@ -826,6 +1092,7 @@ static struct platform_driver tegra234_cbb_driver = { .driver = { .name = "tegra234-cbb", .of_match_table = tegra234_cbb_dt_ids, + .acpi_match_table = tegra241_cbb_acpi_ids, .pm = &tegra234_cbb_pm, }, }; -- cgit v1.2.3 From fa586abcfe4b43e170d72586b6f11bcc48f6766c Mon Sep 17 00:00:00 2001 From: Qing Wang Date: Mon, 18 Oct 2021 04:31:52 -0700 Subject: firmware: tegra: Switch over to memdup_user() This patch fixes the following Coccinelle warning: drivers/firmware/tegra/bpmp-debugfs.c:379: WARNING opportunity for memdup_user Use memdup_user() rather than duplicating its implementation. This is a little bit restricted to reduce false positives. Signed-off-by: Qing Wang Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp-debugfs.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c index 0c440afd5224..9d3874cdaaee 100644 --- a/drivers/firmware/tegra/bpmp-debugfs.c +++ b/drivers/firmware/tegra/bpmp-debugfs.c @@ -377,18 +377,11 @@ static ssize_t bpmp_debug_store(struct file *file, const char __user *buf, if (!filename) return -ENOENT; - databuf = kmalloc(count, GFP_KERNEL); - if (!databuf) - return -ENOMEM; - - if (copy_from_user(databuf, buf, count)) { - err = -EFAULT; - goto free_ret; - } + databuf = memdup_user(buf, count); + if (IS_ERR(databuf)) + return PTR_ERR(databuf); err = mrq_debug_write(bpmp, filename, databuf, count); - -free_ret: kfree(databuf); return err ?: count; -- cgit v1.2.3 From 2254182807fc09ba9dec9a42ef239e373796f1b2 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 23 Sep 2020 03:34:21 +0300 Subject: soc/tegra: fuse: Drop Kconfig dependency on TEGRA20_APB_DMA The DMA subsystem could be entirely disabled in Kconfig and then the TEGRA20_APB_DMA option isn't available too. Hence kernel configuration fails if DMADEVICES Kconfig option is disabled due to the unsatisfiable dependency. The FUSE driver isn't a critical driver and currently it only provides NVMEM interface to userspace which isn't known to be widely used, and thus, it's fine if FUSE driver fails to load. Let's remove the erroneous Kconfig dependency and let the FUSE driver to fail the probing if DMA is unavailable. Fixes: 19d41e5e9c68 ("soc/tegra: fuse: Add APB DMA dependency for Tegra20") Reported-by: Necip Fazil Yildiran Link: https://bugzilla.kernel.org/show_bug.cgi?id=209301 Signed-off-by: Dmitry Osipenko --- drivers/soc/tegra/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 5725c8ef0406..6f601227da3c 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -136,7 +136,6 @@ config SOC_TEGRA_FUSE def_bool y depends on ARCH_TEGRA select SOC_BUS - select TEGRA20_APB_DMA if ARCH_TEGRA_2x_SOC config SOC_TEGRA_FLOWCTRL bool -- cgit v1.2.3 From c18f3524422dd28d2049f9ad3822a70e918a340d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 7 Aug 2022 22:55:59 +0200 Subject: soc/tegra: pmc: Use devm_clk_get_optional() Use devm_clk_get_optional() instead of hand writing it. While at it, use dev_err_probe() to further simplify the code. This is also less verbose if clk_get() returns -EPROBE_DEFER. Signed-off-by: Christophe JAILLET Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 03d614acd521..961b2de16307 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -2904,17 +2904,10 @@ static int tegra_pmc_probe(struct platform_device *pdev) pmc->scratch = base; } - pmc->clk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pmc->clk)) { - err = PTR_ERR(pmc->clk); - - if (err != -ENOENT) { - dev_err(&pdev->dev, "failed to get pclk: %d\n", err); - return err; - } - - pmc->clk = NULL; - } + pmc->clk = devm_clk_get_optional(&pdev->dev, "pclk"); + if (IS_ERR(pmc->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(pmc->clk), + "failed to get pclk\n"); /* * PMC should be last resort for restarting since it soft-resets -- cgit v1.2.3 From 74f7f183d81c26a53c2b1708364069d391b1b4d6 Mon Sep 17 00:00:00 2001 From: Petlozu Pravareshwar Date: Tue, 6 Sep 2022 13:51:17 +0000 Subject: soc/tegra: pmc: Check device node status property In early_initcall, check if PMC device is available for use and avoid accessing PMC resources if the device node status property is set to disabled. Signed-off-by: Manish Bhardwaj Signed-off-by: Petlozu Pravareshwar Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 961b2de16307..678e8bc8a45d 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -4044,7 +4044,7 @@ static int __init tegra_pmc_early_init(void) return -ENXIO; } - if (np) { + if (of_device_is_available(np)) { pmc->soc = match->data; if (pmc->soc->maybe_tz_only) -- cgit v1.2.3 From 1b8501505f57757c393aa20da36fe2d8c29694d0 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 13 Sep 2022 16:01:21 +0200 Subject: soc: mediatek: mutex: Add support for MT6795 Helio X10 display mutex MT6795 has the same mutex mod/sof register layout as MT2712 and MT8173, but supports only four SOF, as it has two DSI and one DPI. Support is added by reusing most of the MT8173 data, with the addition of a mt6795-specific SOF array (and devicetree compatible, of course). Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220913140121.403637-3-angelogioacchino.delregno@collabora.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-mutex.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c index f95100d4de73..c1a33d52038e 100644 --- a/drivers/soc/mediatek/mtk-mutex.c +++ b/drivers/soc/mediatek/mtk-mutex.c @@ -400,6 +400,13 @@ static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = { [MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3, }; +static const unsigned int mt6795_mutex_sof[DDP_MUTEX_SOF_MAX] = { + [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, + [MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0, + [MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1, + [MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0, +}; + static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = { [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, [MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0, @@ -454,6 +461,13 @@ static const struct mtk_mutex_data mt2712_mutex_driver_data = { .mutex_sof_reg = MT2701_MUTEX0_SOF0, }; +static const struct mtk_mutex_data mt6795_mutex_driver_data = { + .mutex_mod = mt8173_mutex_mod, + .mutex_sof = mt6795_mutex_sof, + .mutex_mod_reg = MT2701_MUTEX0_MOD0, + .mutex_sof_reg = MT2701_MUTEX0_SOF0, +}; + static const struct mtk_mutex_data mt8167_mutex_driver_data = { .mutex_mod = mt8167_mutex_mod, .mutex_sof = mt8167_mutex_sof, @@ -828,6 +842,8 @@ static const struct of_device_id mutex_driver_dt_match[] = { .data = &mt2701_mutex_driver_data}, { .compatible = "mediatek,mt2712-disp-mutex", .data = &mt2712_mutex_driver_data}, + { .compatible = "mediatek,mt6795-disp-mutex", + .data = &mt6795_mutex_driver_data}, { .compatible = "mediatek,mt8167-disp-mutex", .data = &mt8167_mutex_driver_data}, { .compatible = "mediatek,mt8173-disp-mutex", -- cgit v1.2.3 From b404cb45990bf24d41c29fe856aafb0746a7b81f Mon Sep 17 00:00:00 2001 From: Xinlei Lee Date: Wed, 14 Sep 2022 21:21:00 +0800 Subject: soc: mediatek: Add mmsys func to adapt to dpi output for MT8186 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add mmsys func to manipulate dpi output format config for MT8186. Co-developed-by: Jitao Shi Signed-off-by: Jitao Shi Signed-off-by: Xinlei Lee Reviewed-by: Nís F. R. A. Prado Link: https://lore.kernel.org/all/1663161662-1598-2-git-send-email-xinlei.lee@mediatek.com/ Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mt8186-mmsys.h | 6 ++++++ drivers/soc/mediatek/mtk-mmsys.c | 20 ++++++++++++++++++++ include/linux/soc/mediatek/mtk-mmsys.h | 2 ++ 3 files changed, 28 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/mediatek/mt8186-mmsys.h b/drivers/soc/mediatek/mt8186-mmsys.h index eb1ad9c37a9c..09b1ccbc0093 100644 --- a/drivers/soc/mediatek/mt8186-mmsys.h +++ b/drivers/soc/mediatek/mt8186-mmsys.h @@ -3,6 +3,12 @@ #ifndef __SOC_MEDIATEK_MT8186_MMSYS_H #define __SOC_MEDIATEK_MT8186_MMSYS_H +/* Values for DPI configuration in MMSYS address space */ +#define MT8186_MMSYS_DPI_OUTPUT_FORMAT 0x400 +#define DPI_FORMAT_MASK 0x1 +#define DPI_RGB888_DDR_CON BIT(0) +#define DPI_RGB565_SDR_CON BIT(1) + #define MT8186_MMSYS_OVL_CON 0xF04 #define MT8186_MMSYS_OVL0_CON_MASK 0x3 #define MT8186_MMSYS_OVL0_2L_CON_MASK 0xC diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index 06d8e83a2cb5..d2c7a87aab87 100644 --- a/drivers/soc/mediatek/mtk-mmsys.c +++ b/drivers/soc/mediatek/mtk-mmsys.c @@ -227,6 +227,26 @@ void mtk_mmsys_ddp_disconnect(struct device *dev, } EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect); +static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val) +{ + u32 tmp; + + tmp = readl_relaxed(mmsys->regs + offset); + tmp = (tmp & ~mask) | val; + writel_relaxed(tmp, mmsys->regs + offset); +} + +void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val) +{ + if (val) + mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8186_MMSYS_DPI_OUTPUT_FORMAT, + DPI_RGB888_DDR_CON, DPI_FORMAT_MASK); + else + mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8186_MMSYS_DPI_OUTPUT_FORMAT, + DPI_RGB565_SDR_CON, DPI_FORMAT_MASK); +} +EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_dpi_fmt_config); + static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id, bool assert) { diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h index 59117d970daf..d2b02bb43768 100644 --- a/include/linux/soc/mediatek/mtk-mmsys.h +++ b/include/linux/soc/mediatek/mtk-mmsys.h @@ -65,4 +65,6 @@ void mtk_mmsys_ddp_disconnect(struct device *dev, enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next); +void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val); + #endif /* __MTK_MMSYS_H */ -- cgit v1.2.3 From c553ca9245f4ee7db54dc48c5892be787f8458a4 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 8 Jul 2022 16:56:29 +0800 Subject: soc: imx: add icc paths for i.MX8MP media blk ctrl Add interconnect paths for i.MX8MP media blk ctrl Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/imx8m-blk-ctrl.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c index dff7529268e4..9b0f81dc292b 100644 --- a/drivers/soc/imx/imx8m-blk-ctrl.c +++ b/drivers/soc/imx/imx8m-blk-ctrl.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -37,6 +38,8 @@ struct imx8m_blk_ctrl_domain_data { const char *name; const char * const *clk_names; int num_clks; + const char * const *path_names; + int num_paths; const char *gpc_name; u32 rst_mask; u32 clk_mask; @@ -52,13 +55,16 @@ struct imx8m_blk_ctrl_domain_data { }; #define DOMAIN_MAX_CLKS 4 +#define DOMAIN_MAX_PATHS 4 struct imx8m_blk_ctrl_domain { struct generic_pm_domain genpd; const struct imx8m_blk_ctrl_domain_data *data; struct clk_bulk_data clks[DOMAIN_MAX_CLKS]; + struct icc_bulk_data paths[DOMAIN_MAX_PATHS]; struct device *power_dev; struct imx8m_blk_ctrl *bc; + int num_paths; }; struct imx8m_blk_ctrl_data { @@ -117,6 +123,10 @@ static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd) if (data->mipi_phy_rst_mask) regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask); + ret = icc_bulk_set_bw(domain->num_paths, domain->paths); + if (ret) + dev_err(bc->dev, "failed to set icc bw\n"); + /* disable upstream clocks */ clk_bulk_disable_unprepare(data->num_clks, domain->clks); @@ -224,10 +234,29 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev) int j; domain->data = data; + domain->num_paths = data->num_paths; for (j = 0; j < data->num_clks; j++) domain->clks[j].id = data->clk_names[j]; + for (j = 0; j < data->num_paths; j++) { + domain->paths[j].name = data->path_names[j]; + /* Fake value for now, just let ICC could configure NoC mode/priority */ + domain->paths[j].avg_bw = 1; + domain->paths[j].peak_bw = 1; + } + + ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths); + if (ret) { + if (ret != -EPROBE_DEFER) { + dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n"); + domain->num_paths = 0; + } else { + dev_err_probe(dev, ret, "failed to get noc entries\n"); + goto cleanup_pds; + } + } + ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks); if (ret) { dev_err_probe(dev, ret, "failed to get clock\n"); @@ -650,6 +679,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[ .gpc_name = "lcdif1", .rst_mask = BIT(4) | BIT(5) | BIT(23), .clk_mask = BIT(4) | BIT(5) | BIT(23), + .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"}, + .num_paths = 2, }, [IMX8MP_MEDIABLK_PD_ISI] = { .name = "mediablk-isi", @@ -658,6 +689,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[ .gpc_name = "isi", .rst_mask = BIT(6) | BIT(7), .clk_mask = BIT(6) | BIT(7), + .path_names = (const char *[]){"isi0", "isi1", "isi2"}, + .num_paths = 3, }, [IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = { .name = "mediablk-mipi-csi2-2", @@ -675,6 +708,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[ .gpc_name = "lcdif2", .rst_mask = BIT(11) | BIT(12) | BIT(24), .clk_mask = BIT(11) | BIT(12) | BIT(24), + .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"}, + .num_paths = 2, }, [IMX8MP_MEDIABLK_PD_ISP] = { .name = "mediablk-isp", @@ -683,6 +718,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[ .gpc_name = "isp", .rst_mask = BIT(16) | BIT(17) | BIT(18), .clk_mask = BIT(16) | BIT(17) | BIT(18), + .path_names = (const char *[]){"isp0", "isp1"}, + .num_paths = 2, }, [IMX8MP_MEDIABLK_PD_DWE] = { .name = "mediablk-dwe", @@ -691,6 +728,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[ .gpc_name = "dwe", .rst_mask = BIT(19) | BIT(20) | BIT(21), .clk_mask = BIT(19) | BIT(20) | BIT(21), + .path_names = (const char *[]){"dwe"}, + .num_paths = 1, }, [IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = { .name = "mediablk-mipi-dsi-2", -- cgit v1.2.3 From 50299fa1f8a05fa8b545e3d64e183b525737fabb Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 8 Jul 2022 16:56:30 +0800 Subject: soc: imx: add icc paths for i.MX8MP hsio/hdmi blk ctrl Add interconnect paths for i.MX8MP hsio/hdmi blk ctrl Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/imx8mp-blk-ctrl.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c index 4ca2ede6871b..6f983adcb47c 100644 --- a/drivers/soc/imx/imx8mp-blk-ctrl.c +++ b/drivers/soc/imx/imx8mp-blk-ctrl.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -36,17 +37,22 @@ struct imx8mp_blk_ctrl_domain_data { const char *name; const char * const *clk_names; int num_clks; + const char * const *path_names; + int num_paths; const char *gpc_name; }; #define DOMAIN_MAX_CLKS 2 +#define DOMAIN_MAX_PATHS 3 struct imx8mp_blk_ctrl_domain { struct generic_pm_domain genpd; const struct imx8mp_blk_ctrl_domain_data *data; struct clk_bulk_data clks[DOMAIN_MAX_CLKS]; + struct icc_bulk_data paths[DOMAIN_MAX_PATHS]; struct device *power_dev; struct imx8mp_blk_ctrl *bc; + int num_paths; int id; }; @@ -144,6 +150,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = { .clk_names = (const char *[]){ "usb" }, .num_clks = 1, .gpc_name = "usb", + .path_names = (const char *[]){"usb1", "usb2"}, + .num_paths = 2, }, [IMX8MP_HSIOBLK_PD_USB_PHY1] = { .name = "hsioblk-usb-phy1", @@ -158,6 +166,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = { .clk_names = (const char *[]){ "pcie" }, .num_clks = 1, .gpc_name = "pcie", + .path_names = (const char *[]){"noc-pcie", "pcie"}, + .num_paths = 2, }, [IMX8MP_HSIOBLK_PD_PCIE_PHY] = { .name = "hsioblk-pcie-phy", @@ -322,6 +332,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = { .clk_names = (const char *[]){ "axi", "apb" }, .num_clks = 2, .gpc_name = "lcdif", + .path_names = (const char *[]){"lcdif-hdmi"}, + .num_paths = 1, }, [IMX8MP_HDMIBLK_PD_PAI] = { .name = "hdmiblk-pai", @@ -395,6 +407,10 @@ static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd) goto clk_disable; } + ret = icc_bulk_set_bw(domain->num_paths, domain->paths); + if (ret) + dev_err(bc->dev, "failed to set icc bw\n"); + clk_bulk_disable_unprepare(data->num_clks, domain->clks); return 0; @@ -510,10 +526,29 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) int j; domain->data = data; + domain->num_paths = data->num_paths; for (j = 0; j < data->num_clks; j++) domain->clks[j].id = data->clk_names[j]; + for (j = 0; j < data->num_paths; j++) { + domain->paths[j].name = data->path_names[j]; + /* Fake value for now, just let ICC could configure NoC mode/priority */ + domain->paths[j].avg_bw = 1; + domain->paths[j].peak_bw = 1; + } + + ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths); + if (ret) { + if (ret != -EPROBE_DEFER) { + dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n"); + domain->num_paths = 0; + } else { + dev_err_probe(dev, ret, "failed to get noc entries\n"); + goto cleanup_pds; + } + } + ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks); if (ret) { dev_err_probe(dev, ret, "failed to get clock\n"); -- cgit v1.2.3 From 77b0ddb42add47748c661f714e6f4b116a6e8759 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 22 Aug 2022 14:45:33 +0800 Subject: soc: imx: add i.MX8MP HDMI blk ctrl HDCP/HRV_MWR i.MX8MP HDMI supports HDCP and HRV_MWR(HDMI RX Video Memory Write Master for RXRX validation), so add them. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/imx8mp-blk-ctrl.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c index 6f983adcb47c..527d45d12a54 100644 --- a/drivers/soc/imx/imx8mp-blk-ctrl.c +++ b/drivers/soc/imx/imx8mp-blk-ctrl.c @@ -235,6 +235,13 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12)); regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3)); break; + case IMX8MP_HDMIBLK_PD_HDCP: + regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11)); + break; + case IMX8MP_HDMIBLK_PD_HRV: + regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5)); + regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15)); + break; default: break; } @@ -283,6 +290,13 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc, regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12)); regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24)); break; + case IMX8MP_HDMIBLK_PD_HDCP: + regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11)); + break; + case IMX8MP_HDMIBLK_PD_HRV: + regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15)); + regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5)); + break; default: break; } @@ -365,6 +379,22 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = { .num_clks = 2, .gpc_name = "hdmi-tx-phy", }, + [IMX8MP_HDMIBLK_PD_HRV] = { + .name = "hdmiblk-hrv", + .clk_names = (const char *[]){ "axi", "apb" }, + .num_clks = 2, + .gpc_name = "hrv", + .path_names = (const char *[]){"hrv"}, + .num_paths = 1, + }, + [IMX8MP_HDMIBLK_PD_HDCP] = { + .name = "hdmiblk-hdcp", + .clk_names = (const char *[]){ "axi", "apb" }, + .num_clks = 2, + .gpc_name = "hdcp", + .path_names = (const char *[]){"hdcp"}, + .num_paths = 1, + }, }; static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = { -- cgit v1.2.3 From a1a5f15f7f6cb5c291f072af843305638c935be6 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 22 Aug 2022 14:45:34 +0800 Subject: soc: imx: imx8m-blk-ctrl: add i.MX8MP VPU blk ctrl i.MX8MP has a VPU blk ctrl module that could supply clk and reset to VPU, so add support for it. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/imx8m-blk-ctrl.c | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c index 9b0f81dc292b..871a387c6b41 100644 --- a/drivers/soc/imx/imx8m-blk-ctrl.c +++ b/drivers/soc/imx/imx8m-blk-ctrl.c @@ -484,6 +484,46 @@ static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = { .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data), }; +static const struct imx8m_blk_ctrl_domain_data imx8mp_vpu_blk_ctl_domain_data[] = { + [IMX8MP_VPUBLK_PD_G1] = { + .name = "vpublk-g1", + .clk_names = (const char *[]){ "g1", }, + .num_clks = 1, + .gpc_name = "g1", + .rst_mask = BIT(1), + .clk_mask = BIT(1), + .path_names = (const char *[]){"g1"}, + .num_paths = 1, + }, + [IMX8MP_VPUBLK_PD_G2] = { + .name = "vpublk-g2", + .clk_names = (const char *[]){ "g2", }, + .num_clks = 1, + .gpc_name = "g2", + .rst_mask = BIT(0), + .clk_mask = BIT(0), + .path_names = (const char *[]){"g2"}, + .num_paths = 1, + }, + [IMX8MP_VPUBLK_PD_VC8000E] = { + .name = "vpublk-vc8000e", + .clk_names = (const char *[]){ "vc8000e", }, + .num_clks = 1, + .gpc_name = "vc8000e", + .rst_mask = BIT(2), + .clk_mask = BIT(2), + .path_names = (const char *[]){"vc8000e"}, + .num_paths = 1, + }, +}; + +static const struct imx8m_blk_ctrl_data imx8mp_vpu_blk_ctl_dev_data = { + .max_reg = 0x18, + .power_notifier_fn = imx8mm_vpu_power_notifier, + .domains = imx8mp_vpu_blk_ctl_domain_data, + .num_domains = ARRAY_SIZE(imx8mp_vpu_blk_ctl_domain_data), +}; + static int imx8mm_disp_power_notifier(struct notifier_block *nb, unsigned long action, void *data) { @@ -827,6 +867,9 @@ static const struct of_device_id imx8m_blk_ctrl_of_match[] = { }, { .compatible = "fsl,imx8mq-vpu-blk-ctrl", .data = &imx8mq_vpu_blk_ctl_dev_data + }, { + .compatible = "fsl,imx8mp-vpu-blk-ctrl", + .data = &imx8mp_vpu_blk_ctl_dev_data }, { /* Sentinel */ } -- cgit v1.2.3 From 5506018d3dec41e6678efb92b836586e9ee1d628 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 2 Sep 2022 16:58:04 +0800 Subject: soc: imx: imx8mp-blk-ctrl: handle PCIe PHY resets Dessert the PHY reset when powering up the domain and put it back into reset when the domain is powered down. Signed-off-by: Lucas Stach Signed-off-by: Richard Zhu Signed-off-by: Shawn Guo --- drivers/soc/imx/imx8mp-blk-ctrl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c index 527d45d12a54..ccb30c6cdc7e 100644 --- a/drivers/soc/imx/imx8mp-blk-ctrl.c +++ b/drivers/soc/imx/imx8mp-blk-ctrl.c @@ -19,6 +19,8 @@ #define GPR_REG0 0x0 #define PCIE_CLOCK_MODULE_EN BIT(0) #define USB_CLOCK_MODULE_EN BIT(1) +#define PCIE_PHY_APB_RST BIT(4) +#define PCIE_PHY_INIT_RST BIT(5) struct imx8mp_blk_ctrl_domain; @@ -81,6 +83,10 @@ static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc, case IMX8MP_HSIOBLK_PD_PCIE: regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN); break; + case IMX8MP_HSIOBLK_PD_PCIE_PHY: + regmap_set_bits(bc->regmap, GPR_REG0, + PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST); + break; default: break; } @@ -96,6 +102,10 @@ static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc, case IMX8MP_HSIOBLK_PD_PCIE: regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN); break; + case IMX8MP_HSIOBLK_PD_PCIE_PHY: + regmap_clear_bits(bc->regmap, GPR_REG0, + PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST); + break; default: break; } -- cgit v1.2.3 From df5a69653586da355b9a88e7851752dc62daa5fd Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 6 Sep 2022 11:39:43 +0800 Subject: soc: imx: imx8m-blk-ctrl: Use genpd_xlate_onecell Simplify driver by using genpd_xlate_onecell instead of driver specific xlate function. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/imx8m-blk-ctrl.c | 14 -------------- drivers/soc/imx/imx8mp-blk-ctrl.c | 14 -------------- 2 files changed, 28 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c index 871a387c6b41..29e25a9ecdcb 100644 --- a/drivers/soc/imx/imx8m-blk-ctrl.c +++ b/drivers/soc/imx/imx8m-blk-ctrl.c @@ -162,19 +162,6 @@ static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd) return 0; } -static struct generic_pm_domain * -imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data) -{ - struct genpd_onecell_data *onecell_data = data; - unsigned int index = args->args[0]; - - if (args->args_count != 1 || - index >= onecell_data->num_domains) - return ERR_PTR(-EINVAL); - - return onecell_data->domains[index]; -} - static struct lock_class_key blk_ctrl_genpd_lock_class; static int imx8m_blk_ctrl_probe(struct platform_device *pdev) @@ -216,7 +203,6 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev) return -ENOMEM; bc->onecell_data.num_domains = bc_data->num_domains; - bc->onecell_data.xlate = imx8m_blk_ctrl_xlate; bc->onecell_data.domains = devm_kcalloc(dev, bc_data->num_domains, sizeof(struct generic_pm_domain *), GFP_KERNEL); diff --git a/drivers/soc/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c index ccb30c6cdc7e..0e3b6ba22f94 100644 --- a/drivers/soc/imx/imx8mp-blk-ctrl.c +++ b/drivers/soc/imx/imx8mp-blk-ctrl.c @@ -490,19 +490,6 @@ static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd) return 0; } -static struct generic_pm_domain * -imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data) -{ - struct genpd_onecell_data *onecell_data = data; - unsigned int index = args->args[0]; - - if (args->args_count != 1 || - index >= onecell_data->num_domains) - return ERR_PTR(-EINVAL); - - return onecell_data->domains[index]; -} - static struct lock_class_key blk_ctrl_genpd_lock_class; static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) @@ -545,7 +532,6 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev) return -ENOMEM; bc->onecell_data.num_domains = num_domains; - bc->onecell_data.xlate = imx8m_blk_ctrl_xlate; bc->onecell_data.domains = devm_kcalloc(dev, num_domains, sizeof(struct generic_pm_domain *), GFP_KERNEL); -- cgit v1.2.3 From 0a0f7cc25d4a525a71260cbd453a848c5c8e61c3 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 6 Sep 2022 11:28:14 +0800 Subject: soc: imx: add i.MX93 SRC power domain driver Support controlling power domain managed by System Reset Controller(SRC). Current supported power domain is mediamix power domain. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/Kconfig | 8 +++ drivers/soc/imx/Makefile | 1 + drivers/soc/imx/imx93-pd.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ drivers/soc/imx/imx93-src.c | 33 +++++++++ 4 files changed, 206 insertions(+) create mode 100644 drivers/soc/imx/imx93-pd.c create mode 100644 drivers/soc/imx/imx93-src.c (limited to 'drivers') diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig index a840494e849a..4b906791d6c7 100644 --- a/drivers/soc/imx/Kconfig +++ b/drivers/soc/imx/Kconfig @@ -20,4 +20,12 @@ config SOC_IMX8M support, it will provide the SoC info like SoC family, ID and revision etc. +config SOC_IMX9 + tristate "i.MX9 SoC family support" + depends on ARCH_MXC || COMPILE_TEST + default ARCH_MXC && ARM64 + select SOC_BUS + help + If you say yes here, you get support for the NXP i.MX9 family + endmenu diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index 63cd29f6d4d2..a0baa2a01adb 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o obj-$(CONFIG_SOC_IMX8M) += imx8m-blk-ctrl.o obj-$(CONFIG_SOC_IMX8M) += imx8mp-blk-ctrl.o +obj-$(CONFIG_SOC_IMX9) += imx93-src.o imx93-pd.o diff --git a/drivers/soc/imx/imx93-pd.c b/drivers/soc/imx/imx93-pd.c new file mode 100644 index 000000000000..1f3d7039c1de --- /dev/null +++ b/drivers/soc/imx/imx93-pd.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MIX_SLICE_SW_CTRL_OFF 0x20 +#define SLICE_SW_CTRL_PSW_CTRL_OFF_MASK BIT(4) +#define SLICE_SW_CTRL_PDN_SOFT_MASK BIT(31) + +#define MIX_FUNC_STAT_OFF 0xB4 + +#define FUNC_STAT_PSW_STAT_MASK BIT(0) +#define FUNC_STAT_RST_STAT_MASK BIT(2) +#define FUNC_STAT_ISO_STAT_MASK BIT(4) + +struct imx93_power_domain { + struct generic_pm_domain genpd; + struct device *dev; + void __iomem *addr; + struct clk_bulk_data *clks; + int num_clks; + bool init_off; +}; + +#define to_imx93_pd(_genpd) container_of(_genpd, struct imx93_power_domain, genpd) + +static int imx93_pd_on(struct generic_pm_domain *genpd) +{ + struct imx93_power_domain *domain = to_imx93_pd(genpd); + void __iomem *addr = domain->addr; + u32 val; + int ret; + + ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); + if (ret) { + dev_err(domain->dev, "failed to enable clocks for domain: %s\n", genpd->name); + return ret; + } + + val = readl(addr + MIX_SLICE_SW_CTRL_OFF); + val &= ~SLICE_SW_CTRL_PDN_SOFT_MASK; + writel(val, addr + MIX_SLICE_SW_CTRL_OFF); + + ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val, + !(val & FUNC_STAT_ISO_STAT_MASK), 1, 10000); + if (ret) { + dev_err(domain->dev, "pd_on timeout: name: %s, stat: %x\n", genpd->name, val); + return ret; + } + + return 0; +} + +static int imx93_pd_off(struct generic_pm_domain *genpd) +{ + struct imx93_power_domain *domain = to_imx93_pd(genpd); + void __iomem *addr = domain->addr; + int ret; + u32 val; + + /* Power off MIX */ + val = readl(addr + MIX_SLICE_SW_CTRL_OFF); + val |= SLICE_SW_CTRL_PDN_SOFT_MASK; + writel(val, addr + MIX_SLICE_SW_CTRL_OFF); + + ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val, + val & FUNC_STAT_PSW_STAT_MASK, 1, 1000); + if (ret) { + dev_err(domain->dev, "pd_off timeout: name: %s, stat: %x\n", genpd->name, val); + return ret; + } + + clk_bulk_disable_unprepare(domain->num_clks, domain->clks); + + return 0; +}; + +static int imx93_pd_remove(struct platform_device *pdev) +{ + struct imx93_power_domain *domain = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + + if (!domain->init_off) + clk_bulk_disable_unprepare(domain->num_clks, domain->clks); + + of_genpd_del_provider(np); + pm_genpd_remove(&domain->genpd); + + return 0; +} + +static int imx93_pd_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct imx93_power_domain *domain; + int ret; + + domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL); + if (!domain) + return -ENOMEM; + + domain->addr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(domain->addr)) + return PTR_ERR(domain->addr); + + domain->num_clks = devm_clk_bulk_get_all(dev, &domain->clks); + if (domain->num_clks < 0) + return dev_err_probe(dev, domain->num_clks, "Failed to get domain's clocks\n"); + + domain->genpd.name = dev_name(dev); + domain->genpd.power_off = imx93_pd_off; + domain->genpd.power_on = imx93_pd_on; + domain->dev = dev; + + domain->init_off = readl(domain->addr + MIX_FUNC_STAT_OFF) & FUNC_STAT_ISO_STAT_MASK; + /* Just to sync the status of hardware */ + if (!domain->init_off) { + ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); + if (ret) { + dev_err(domain->dev, "failed to enable clocks for domain: %s\n", + domain->genpd.name); + return ret; + } + } + + ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off); + if (ret) + return ret; + + platform_set_drvdata(pdev, domain); + + return of_genpd_add_provider_simple(np, &domain->genpd); +} + +static const struct of_device_id imx93_pd_ids[] = { + { .compatible = "fsl,imx93-src-slice" }, + { } +}; +MODULE_DEVICE_TABLE(of, imx93_pd_ids); + +static struct platform_driver imx93_power_domain_driver = { + .driver = { + .name = "imx93_power_domain", + .owner = THIS_MODULE, + .of_match_table = imx93_pd_ids, + }, + .probe = imx93_pd_probe, + .remove = imx93_pd_remove, +}; +module_platform_driver(imx93_power_domain_driver); + +MODULE_AUTHOR("Peng Fan "); +MODULE_DESCRIPTION("NXP i.MX93 power domain driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/imx/imx93-src.c b/drivers/soc/imx/imx93-src.c new file mode 100644 index 000000000000..4d74921cae0f --- /dev/null +++ b/drivers/soc/imx/imx93-src.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 NXP + */ + +#include +#include +#include + +static int imx93_src_probe(struct platform_device *pdev) +{ + return devm_of_platform_populate(&pdev->dev); +} + +static const struct of_device_id imx93_src_ids[] = { + { .compatible = "fsl,imx93-src" }, + { } +}; +MODULE_DEVICE_TABLE(of, imx93_src_ids); + +static struct platform_driver imx93_src_driver = { + .driver = { + .name = "imx93_src", + .owner = THIS_MODULE, + .of_match_table = imx93_src_ids, + }, + .probe = imx93_src_probe, +}; +module_platform_driver(imx93_src_driver); + +MODULE_AUTHOR("Peng Fan "); +MODULE_DESCRIPTION("NXP i.MX93 src driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e9aa77d413c903ba4cf7da3fe0b419cae5b97a81 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 6 Sep 2022 11:28:15 +0800 Subject: soc: imx: add i.MX93 media blk ctrl driver Add i.MX93 mediamix blk ctrl support. i.MX93 mediamix blk ctrl has registers to set QoS(priority) value. It support default QoS value and cfg QoS value. Set an initial value from i.MX design team. If LCDIF/ISI/PXP wanna a different QoS value in future, they could use interconnect to request bandwidth. Signed-off-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/Makefile | 1 + drivers/soc/imx/imx93-blk-ctrl.c | 436 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 437 insertions(+) create mode 100644 drivers/soc/imx/imx93-blk-ctrl.c (limited to 'drivers') diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index a0baa2a01adb..7b4099ceafd6 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o obj-$(CONFIG_SOC_IMX8M) += imx8m-blk-ctrl.o obj-$(CONFIG_SOC_IMX8M) += imx8mp-blk-ctrl.o obj-$(CONFIG_SOC_IMX9) += imx93-src.o imx93-pd.o +obj-$(CONFIG_SOC_IMX9) += imx93-blk-ctrl.o diff --git a/drivers/soc/imx/imx93-blk-ctrl.c b/drivers/soc/imx/imx93-blk-ctrl.c new file mode 100644 index 000000000000..2c600329436c --- /dev/null +++ b/drivers/soc/imx/imx93-blk-ctrl.c @@ -0,0 +1,436 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 NXP, Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BLK_SFT_RSTN 0x0 +#define BLK_CLK_EN 0x4 +#define BLK_MAX_CLKS 4 + +#define DOMAIN_MAX_CLKS 4 + +#define LCDIF_QOS_REG 0xC +#define LCDIF_DEFAULT_QOS_OFF 12 +#define LCDIF_CFG_QOS_OFF 8 + +#define PXP_QOS_REG 0x10 +#define PXP_R_DEFAULT_QOS_OFF 28 +#define PXP_R_CFG_QOS_OFF 24 +#define PXP_W_DEFAULT_QOS_OFF 20 +#define PXP_W_CFG_QOS_OFF 16 + +#define ISI_CACHE_REG 0x14 + +#define ISI_QOS_REG 0x1C +#define ISI_V_DEFAULT_QOS_OFF 28 +#define ISI_V_CFG_QOS_OFF 24 +#define ISI_U_DEFAULT_QOS_OFF 20 +#define ISI_U_CFG_QOS_OFF 16 +#define ISI_Y_R_DEFAULT_QOS_OFF 12 +#define ISI_Y_R_CFG_QOS_OFF 8 +#define ISI_Y_W_DEFAULT_QOS_OFF 4 +#define ISI_Y_W_CFG_QOS_OFF 0 + +#define PRIO_MASK 0xF + +#define PRIO(X) (X) + +struct imx93_blk_ctrl_domain; + +struct imx93_blk_ctrl { + struct device *dev; + struct regmap *regmap; + int num_clks; + struct clk_bulk_data clks[BLK_MAX_CLKS]; + struct imx93_blk_ctrl_domain *domains; + struct genpd_onecell_data onecell_data; +}; + +#define DOMAIN_MAX_QOS 4 + +struct imx93_blk_ctrl_qos { + u32 reg; + u32 cfg_off; + u32 default_prio; + u32 cfg_prio; +}; + +struct imx93_blk_ctrl_domain_data { + const char *name; + const char * const *clk_names; + int num_clks; + u32 rst_mask; + u32 clk_mask; + int num_qos; + struct imx93_blk_ctrl_qos qos[DOMAIN_MAX_QOS]; +}; + +struct imx93_blk_ctrl_domain { + struct generic_pm_domain genpd; + const struct imx93_blk_ctrl_domain_data *data; + struct clk_bulk_data clks[DOMAIN_MAX_CLKS]; + struct imx93_blk_ctrl *bc; +}; + +struct imx93_blk_ctrl_data { + const struct imx93_blk_ctrl_domain_data *domains; + int num_domains; + const char * const *clk_names; + int num_clks; + const struct regmap_access_table *reg_access_table; +}; + +static inline struct imx93_blk_ctrl_domain * +to_imx93_blk_ctrl_domain(struct generic_pm_domain *genpd) +{ + return container_of(genpd, struct imx93_blk_ctrl_domain, genpd); +} + +static int imx93_blk_ctrl_set_qos(struct imx93_blk_ctrl_domain *domain) +{ + const struct imx93_blk_ctrl_domain_data *data = domain->data; + struct imx93_blk_ctrl *bc = domain->bc; + const struct imx93_blk_ctrl_qos *qos; + u32 val, mask; + int i; + + for (i = 0; i < data->num_qos; i++) { + qos = &data->qos[i]; + + mask = PRIO_MASK << qos->cfg_off; + mask |= PRIO_MASK << (qos->cfg_off + 4); + val = qos->cfg_prio << qos->cfg_off; + val |= qos->default_prio << (qos->cfg_off + 4); + + regmap_write_bits(bc->regmap, qos->reg, mask, val); + + dev_dbg(bc->dev, "data->qos[i].reg 0x%x 0x%x\n", qos->reg, val); + } + + return 0; +} + +static int imx93_blk_ctrl_power_on(struct generic_pm_domain *genpd) +{ + struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd); + const struct imx93_blk_ctrl_domain_data *data = domain->data; + struct imx93_blk_ctrl *bc = domain->bc; + int ret; + + ret = clk_bulk_prepare_enable(bc->num_clks, bc->clks); + if (ret) { + dev_err(bc->dev, "failed to enable bus clocks\n"); + return ret; + } + + ret = clk_bulk_prepare_enable(data->num_clks, domain->clks); + if (ret) { + clk_bulk_disable_unprepare(bc->num_clks, bc->clks); + dev_err(bc->dev, "failed to enable clocks\n"); + return ret; + } + + ret = pm_runtime_get_sync(bc->dev); + if (ret < 0) { + pm_runtime_put_noidle(bc->dev); + dev_err(bc->dev, "failed to power up domain\n"); + goto disable_clk; + } + + /* ungate clk */ + regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask); + + /* release reset */ + regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); + + dev_dbg(bc->dev, "pd_on: name: %s\n", genpd->name); + + return imx93_blk_ctrl_set_qos(domain); + +disable_clk: + clk_bulk_disable_unprepare(data->num_clks, domain->clks); + + clk_bulk_disable_unprepare(bc->num_clks, bc->clks); + + return ret; +} + +static int imx93_blk_ctrl_power_off(struct generic_pm_domain *genpd) +{ + struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd); + const struct imx93_blk_ctrl_domain_data *data = domain->data; + struct imx93_blk_ctrl *bc = domain->bc; + + dev_dbg(bc->dev, "pd_off: name: %s\n", genpd->name); + + regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); + regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask); + + pm_runtime_put(bc->dev); + + clk_bulk_disable_unprepare(data->num_clks, domain->clks); + + clk_bulk_disable_unprepare(bc->num_clks, bc->clks); + + return 0; +} + +static int imx93_blk_ctrl_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct imx93_blk_ctrl_data *bc_data = of_device_get_match_data(dev); + struct imx93_blk_ctrl *bc; + void __iomem *base; + int i, ret; + + struct regmap_config regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .rd_table = bc_data->reg_access_table, + .wr_table = bc_data->reg_access_table, + .max_register = SZ_4K, + }; + + bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL); + if (!bc) + return -ENOMEM; + + bc->dev = dev; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + bc->regmap = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(bc->regmap)) + return dev_err_probe(dev, PTR_ERR(bc->regmap), + "failed to init regmap\n"); + + bc->domains = devm_kcalloc(dev, bc_data->num_domains, + sizeof(struct imx93_blk_ctrl_domain), + GFP_KERNEL); + if (!bc->domains) + return -ENOMEM; + + bc->onecell_data.num_domains = bc_data->num_domains; + bc->onecell_data.domains = + devm_kcalloc(dev, bc_data->num_domains, + sizeof(struct generic_pm_domain *), GFP_KERNEL); + if (!bc->onecell_data.domains) + return -ENOMEM; + + for (i = 0; i < bc_data->num_clks; i++) + bc->clks[i].id = bc_data->clk_names[i]; + bc->num_clks = bc_data->num_clks; + + ret = devm_clk_bulk_get(dev, bc->num_clks, bc->clks); + if (ret) { + dev_err_probe(dev, ret, "failed to get bus clock\n"); + return ret; + } + + for (i = 0; i < bc_data->num_domains; i++) { + const struct imx93_blk_ctrl_domain_data *data = &bc_data->domains[i]; + struct imx93_blk_ctrl_domain *domain = &bc->domains[i]; + int j; + + domain->data = data; + + for (j = 0; j < data->num_clks; j++) + domain->clks[j].id = data->clk_names[j]; + + ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks); + if (ret) { + dev_err_probe(dev, ret, "failed to get clock\n"); + goto cleanup_pds; + } + + domain->genpd.name = data->name; + domain->genpd.power_on = imx93_blk_ctrl_power_on; + domain->genpd.power_off = imx93_blk_ctrl_power_off; + domain->bc = bc; + + ret = pm_genpd_init(&domain->genpd, NULL, true); + if (ret) { + dev_err_probe(dev, ret, "failed to init power domain\n"); + goto cleanup_pds; + } + + bc->onecell_data.domains[i] = &domain->genpd; + } + + pm_runtime_enable(dev); + + ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data); + if (ret) { + dev_err_probe(dev, ret, "failed to add power domain provider\n"); + goto cleanup_pds; + } + + dev_set_drvdata(dev, bc); + + return 0; + +cleanup_pds: + for (i--; i >= 0; i--) + pm_genpd_remove(&bc->domains[i].genpd); + + return ret; +} + +static int imx93_blk_ctrl_remove(struct platform_device *pdev) +{ + struct imx93_blk_ctrl *bc = dev_get_drvdata(&pdev->dev); + int i; + + of_genpd_del_provider(pdev->dev.of_node); + + for (i = 0; bc->onecell_data.num_domains; i++) { + struct imx93_blk_ctrl_domain *domain = &bc->domains[i]; + + pm_genpd_remove(&domain->genpd); + } + + return 0; +} + +static const struct imx93_blk_ctrl_domain_data imx93_media_blk_ctl_domain_data[] = { + [IMX93_MEDIABLK_PD_MIPI_DSI] = { + .name = "mediablk-mipi-dsi", + .clk_names = (const char *[]){ "dsi" }, + .num_clks = 1, + .rst_mask = BIT(11) | BIT(12), + .clk_mask = BIT(11) | BIT(12), + }, + [IMX93_MEDIABLK_PD_MIPI_CSI] = { + .name = "mediablk-mipi-csi", + .clk_names = (const char *[]){ "cam", "csi" }, + .num_clks = 2, + .rst_mask = BIT(9) | BIT(10), + .clk_mask = BIT(9) | BIT(10), + }, + [IMX93_MEDIABLK_PD_PXP] = { + .name = "mediablk-pxp", + .clk_names = (const char *[]){ "pxp" }, + .num_clks = 1, + .rst_mask = BIT(7) | BIT(8), + .clk_mask = BIT(7) | BIT(8), + .num_qos = 2, + .qos = { + { + .reg = PXP_QOS_REG, + .cfg_off = PXP_R_CFG_QOS_OFF, + .default_prio = PRIO(3), + .cfg_prio = PRIO(6), + }, { + .reg = PXP_QOS_REG, + .cfg_off = PXP_W_CFG_QOS_OFF, + .default_prio = PRIO(3), + .cfg_prio = PRIO(6), + } + } + }, + [IMX93_MEDIABLK_PD_LCDIF] = { + .name = "mediablk-lcdif", + .clk_names = (const char *[]){ "disp", "lcdif" }, + .num_clks = 2, + .rst_mask = BIT(4) | BIT(5) | BIT(6), + .clk_mask = BIT(4) | BIT(5) | BIT(6), + .num_qos = 1, + .qos = { + { + .reg = LCDIF_QOS_REG, + .cfg_off = LCDIF_CFG_QOS_OFF, + .default_prio = PRIO(3), + .cfg_prio = PRIO(7), + } + } + }, + [IMX93_MEDIABLK_PD_ISI] = { + .name = "mediablk-isi", + .clk_names = (const char *[]){ "isi" }, + .num_clks = 1, + .rst_mask = BIT(2) | BIT(3), + .clk_mask = BIT(2) | BIT(3), + .num_qos = 4, + .qos = { + { + .reg = ISI_QOS_REG, + .cfg_off = ISI_Y_W_CFG_QOS_OFF, + .default_prio = PRIO(3), + .cfg_prio = PRIO(7), + }, { + .reg = ISI_QOS_REG, + .cfg_off = ISI_Y_R_CFG_QOS_OFF, + .default_prio = PRIO(3), + .cfg_prio = PRIO(7), + }, { + .reg = ISI_QOS_REG, + .cfg_off = ISI_U_CFG_QOS_OFF, + .default_prio = PRIO(3), + .cfg_prio = PRIO(7), + }, { + .reg = ISI_QOS_REG, + .cfg_off = ISI_V_CFG_QOS_OFF, + .default_prio = PRIO(3), + .cfg_prio = PRIO(7), + } + } + }, +}; + +static const struct regmap_range imx93_media_blk_ctl_yes_ranges[] = { + regmap_reg_range(BLK_SFT_RSTN, BLK_CLK_EN), + regmap_reg_range(LCDIF_QOS_REG, ISI_CACHE_REG), + regmap_reg_range(ISI_QOS_REG, ISI_QOS_REG), +}; + +static const struct regmap_access_table imx93_media_blk_ctl_access_table = { + .yes_ranges = imx93_media_blk_ctl_yes_ranges, + .n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges), +}; + +static const struct imx93_blk_ctrl_data imx93_media_blk_ctl_dev_data = { + .domains = imx93_media_blk_ctl_domain_data, + .num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data), + .clk_names = (const char *[]){ "axi", "apb", "nic", }, + .num_clks = 3, + .reg_access_table = &imx93_media_blk_ctl_access_table, +}; + +static const struct of_device_id imx93_blk_ctrl_of_match[] = { + { + .compatible = "fsl,imx93-media-blk-ctrl", + .data = &imx93_media_blk_ctl_dev_data + }, { + /* Sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match); + +static struct platform_driver imx93_blk_ctrl_driver = { + .probe = imx93_blk_ctrl_probe, + .remove = imx93_blk_ctrl_remove, + .driver = { + .name = "imx93-blk-ctrl", + .of_match_table = imx93_blk_ctrl_of_match, + }, +}; +module_platform_driver(imx93_blk_ctrl_driver); + +MODULE_AUTHOR("Peng Fan "); +MODULE_DESCRIPTION("i.MX93 BLK CTRL driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From f5a5e83379b537f6252526bb4d285b771f6f0b89 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Wed, 14 Sep 2022 09:34:31 +0100 Subject: soc: apple: rtkit: Add apple_rtkit_poll This allows a client to receive messages in atomic context, by polling. Signed-off-by: Hector Martin Signed-off-by: Russell King (Oracle) Reviewed-by: Sven Peter Reviewed-by: Eric Curtin Reviewed-by: Linus Walleij Signed-off-by: Arnd Bergmann --- drivers/soc/apple/rtkit.c | 6 ++++++ include/linux/soc/apple/rtkit.h | 12 ++++++++++++ 2 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c index cf1129e9f76b..031ec4aa06d5 100644 --- a/drivers/soc/apple/rtkit.c +++ b/drivers/soc/apple/rtkit.c @@ -660,6 +660,12 @@ int apple_rtkit_send_message_wait(struct apple_rtkit *rtk, u8 ep, u64 message, } EXPORT_SYMBOL_GPL(apple_rtkit_send_message_wait); +int apple_rtkit_poll(struct apple_rtkit *rtk) +{ + return mbox_client_peek_data(rtk->mbox_chan); +} +EXPORT_SYMBOL_GPL(apple_rtkit_poll); + int apple_rtkit_start_ep(struct apple_rtkit *rtk, u8 endpoint) { u64 msg; diff --git a/include/linux/soc/apple/rtkit.h b/include/linux/soc/apple/rtkit.h index 88eb832eac7b..c9cabb679cd1 100644 --- a/include/linux/soc/apple/rtkit.h +++ b/include/linux/soc/apple/rtkit.h @@ -152,4 +152,16 @@ int apple_rtkit_send_message(struct apple_rtkit *rtk, u8 ep, u64 message, int apple_rtkit_send_message_wait(struct apple_rtkit *rtk, u8 ep, u64 message, unsigned long timeout, bool atomic); +/* + * Process incoming messages in atomic context. + * This only guarantees that messages arrive as far as the recv_message_early + * callback; drivers expecting to handle incoming messages synchronously + * by calling this function must do it that way. + * Will return 1 if some data was processed, 0 if none was, or a + * negative error code on failure. + * + * @rtk: RTKit reference + */ +int apple_rtkit_poll(struct apple_rtkit *rtk); + #endif /* _LINUX_APPLE_RTKIT_H_ */ -- cgit v1.2.3 From 460d9cb62f7fe82cc835d6b3924a8d06fd2d510a Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:44 -0500 Subject: soc: sunxi: sram: Return void from the release function There is no point in returning an error here, as the caller can do nothing about it. In fact, all callers already ignore the return value. Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220815041248.53268-8-samuel@sholland.org Signed-off-by: Jernej Skrabec --- drivers/soc/sunxi/sunxi_sram.c | 8 +++----- include/linux/soc/sunxi/sunxi_sram.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 09754cd1d57d..9622fd45f5e5 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -261,25 +261,23 @@ int sunxi_sram_claim(struct device *dev) } EXPORT_SYMBOL(sunxi_sram_claim); -int sunxi_sram_release(struct device *dev) +void sunxi_sram_release(struct device *dev) { const struct sunxi_sram_data *sram_data; struct sunxi_sram_desc *sram_desc; if (!dev || !dev->of_node) - return -EINVAL; + return; sram_data = sunxi_sram_of_parse(dev->of_node, NULL); if (IS_ERR(sram_data)) - return -EINVAL; + return; sram_desc = to_sram_desc(sram_data); spin_lock(&sram_lock); sram_desc->claimed = false; spin_unlock(&sram_lock); - - return 0; } EXPORT_SYMBOL(sunxi_sram_release); diff --git a/include/linux/soc/sunxi/sunxi_sram.h b/include/linux/soc/sunxi/sunxi_sram.h index c5f663bba9c2..60e274d1b821 100644 --- a/include/linux/soc/sunxi/sunxi_sram.h +++ b/include/linux/soc/sunxi/sunxi_sram.h @@ -14,6 +14,6 @@ #define _SUNXI_SRAM_H_ int sunxi_sram_claim(struct device *dev); -int sunxi_sram_release(struct device *dev); +void sunxi_sram_release(struct device *dev); #endif /* _SUNXI_SRAM_H_ */ -- cgit v1.2.3 From ee07b9056e3e7cac6d13e0177b6c8cd9ce8a9c5f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:45 -0500 Subject: soc: sunxi: sram: Save a pointer to the OF match data It is inefficient to match the compatible string every time the regmap is accessed. Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220815041248.53268-9-samuel@sholland.org Signed-off-by: Jernej Skrabec --- drivers/soc/sunxi/sunxi_sram.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 9622fd45f5e5..7c6fb17cfe7f 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -305,9 +305,7 @@ static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { static bool sunxi_sram_regmap_accessible_reg(struct device *dev, unsigned int reg) { - const struct sunxi_sramc_variant *variant; - - variant = of_device_get_match_data(dev); + const struct sunxi_sramc_variant *variant = dev_get_drvdata(dev); if (reg < SUNXI_SRAM_EMAC_CLOCK_REG) return false; @@ -340,6 +338,8 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) if (!variant) return -EINVAL; + dev_set_drvdata(dev, (struct sunxi_sramc_variant *)variant); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- cgit v1.2.3 From dd2ae2ecb0b98c7b196fc44ad07010093b7cd3cc Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:46 -0500 Subject: soc: sunxi: sram: Export the LDO control register Some newer Allwinner SoCs contain internal LDOs managed by a register in the system control MMIO space. Export this from the regmap in addtion to the EMAC register. Use generic names now that the regmap is no longer EMAC-specific. Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220815041248.53268-10-samuel@sholland.org Signed-off-by: Jernej Skrabec --- drivers/soc/sunxi/sunxi_sram.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 7c6fb17cfe7f..7e8dab0f0ec4 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -283,6 +283,7 @@ EXPORT_SYMBOL(sunxi_sram_release); struct sunxi_sramc_variant { int num_emac_clocks; + bool has_ldo_ctrl; }; static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { @@ -302,25 +303,28 @@ static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { }; #define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 +#define SUNXI_SYS_LDO_CTRL_REG 0x150 + static bool sunxi_sram_regmap_accessible_reg(struct device *dev, unsigned int reg) { const struct sunxi_sramc_variant *variant = dev_get_drvdata(dev); - if (reg < SUNXI_SRAM_EMAC_CLOCK_REG) - return false; - if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) - return false; + if (reg >= SUNXI_SRAM_EMAC_CLOCK_REG && + reg < SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) + return true; + if (reg == SUNXI_SYS_LDO_CTRL_REG && variant->has_ldo_ctrl) + return true; - return true; + return false; } -static struct regmap_config sunxi_sram_emac_clock_regmap = { +static struct regmap_config sunxi_sram_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, /* last defined register */ - .max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4, + .max_register = SUNXI_SYS_LDO_CTRL_REG, /* other devices have no business accessing other registers */ .readable_reg = sunxi_sram_regmap_accessible_reg, .writeable_reg = sunxi_sram_regmap_accessible_reg, @@ -328,9 +332,9 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { static int __init sunxi_sram_probe(struct platform_device *pdev) { - struct regmap *emac_clock; const struct sunxi_sramc_variant *variant; struct device *dev = &pdev->dev; + struct regmap *regmap; sram_dev = &pdev->dev; @@ -344,12 +348,10 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - if (variant->num_emac_clocks > 0) { - emac_clock = devm_regmap_init_mmio(&pdev->dev, base, - &sunxi_sram_emac_clock_regmap); - - if (IS_ERR(emac_clock)) - return PTR_ERR(emac_clock); + if (variant->num_emac_clocks || variant->has_ldo_ctrl) { + regmap = devm_regmap_init_mmio(dev, base, &sunxi_sram_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); } of_platform_populate(dev->of_node, NULL, NULL, dev); -- cgit v1.2.3 From 1f698cb11dd48ec5c430886f794953878e1ff016 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:47 -0500 Subject: soc: sunxi: sram: Add support for the D1 system control D1 has a single EMAC and some LDOs that need to be exported. Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220815041248.53268-11-samuel@sholland.org Signed-off-by: Jernej Skrabec --- drivers/soc/sunxi/sunxi_sram.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 7e8dab0f0ec4..92f9186c1c42 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -294,6 +294,11 @@ static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = { .num_emac_clocks = 1, }; +static const struct sunxi_sramc_variant sun20i_d1_sramc_variant = { + .num_emac_clocks = 1, + .has_ldo_ctrl = true, +}; + static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = { .num_emac_clocks = 1, }; @@ -382,6 +387,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = { .compatible = "allwinner,sun8i-h3-system-control", .data = &sun8i_h3_sramc_variant, }, + { + .compatible = "allwinner,sun20i-d1-system-control", + .data = &sun20i_d1_sramc_variant, + }, { .compatible = "allwinner,sun50i-a64-sram-controller", .data = &sun50i_a64_sramc_variant, -- cgit v1.2.3 From 998fcd001feb8d71f2838d0949f2aeac2a0cbb9e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 26 Sep 2022 14:02:49 +0300 Subject: firmware/psci: Print a warning if PSCI doesn't accept PC mode The function psci_pd_try_set_osi_mode() will print an error if enabling OSI mode fails. To ease debugging PSCI issues print corresponding message if switching to PC mode fails too. Signed-off-by: Dmitry Baryshkov Reviewed-by: Sudeep Holla Reviewed-by: Ulf Hansson Acked-by: Mark Rutland Link: https://lore.kernel.org/r/20220926110249.666813-1-dmitry.baryshkov@linaro.org' Signed-off-by: Arnd Bergmann --- drivers/cpuidle/cpuidle-psci-domain.c | 4 +--- drivers/firmware/psci/psci.c | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c index 3db4fca1172b..821984947ed9 100644 --- a/drivers/cpuidle/cpuidle-psci-domain.c +++ b/drivers/cpuidle/cpuidle-psci-domain.c @@ -124,10 +124,8 @@ static bool psci_pd_try_set_osi_mode(void) return false; ret = psci_set_osi_mode(true); - if (ret) { - pr_warn("failed to enable OSI mode: %d\n", ret); + if (ret) return false; - } return true; } diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index cfb448eabdaa..1628f1edef4a 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -163,6 +163,8 @@ int psci_set_osi_mode(bool enable) PSCI_1_0_SUSPEND_MODE_PC; err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE, suspend_mode, 0, 0); + if (err < 0) + pr_warn("failed to set %s mode: %d\n", enable ? "OSI" : "PC", err); return psci_to_linux_errno(err); } -- cgit v1.2.3 From 3137f2e60098bccdf9b3a744747b06a96addab9e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 26 Sep 2022 14:07:58 +0300 Subject: firmware/psci: Add debugfs support to ease debugging To ease debugging of PSCI supported features, add debugfs file called 'psci' describing PSCI and SMC CC versions, enabled features and options. Signed-off-by: Dmitry Baryshkov Reviewed-by: Mark Brown Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20220926110758.666922-1-dmitry.baryshkov@linaro.org' Signed-off-by: Arnd Bergmann --- drivers/firmware/psci/psci.c | 116 ++++++++++++++++++++++++++++++++++++++++++- include/uapi/linux/psci.h | 14 ++++++ 2 files changed, 129 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index 1628f1edef4a..42cae0ba10e2 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -326,12 +327,125 @@ static void psci_sys_poweroff(void) invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); } -static int __init psci_features(u32 psci_func_id) +static int psci_features(u32 psci_func_id) { return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES, psci_func_id, 0, 0); } +#ifdef CONFIG_DEBUG_FS + +#define PSCI_ID(ver, _name) \ + { .fn = PSCI_##ver##_FN_##_name, .name = #_name, } +#define PSCI_ID_NATIVE(ver, _name) \ + { .fn = PSCI_FN_NATIVE(ver, _name), .name = #_name, } + +/* A table of all optional functions */ +static const struct { + u32 fn; + const char *name; +} psci_fn_ids[] = { + PSCI_ID_NATIVE(0_2, MIGRATE), + PSCI_ID(0_2, MIGRATE_INFO_TYPE), + PSCI_ID_NATIVE(0_2, MIGRATE_INFO_UP_CPU), + PSCI_ID(1_0, CPU_FREEZE), + PSCI_ID_NATIVE(1_0, CPU_DEFAULT_SUSPEND), + PSCI_ID_NATIVE(1_0, NODE_HW_STATE), + PSCI_ID_NATIVE(1_0, SYSTEM_SUSPEND), + PSCI_ID(1_0, SET_SUSPEND_MODE), + PSCI_ID_NATIVE(1_0, STAT_RESIDENCY), + PSCI_ID_NATIVE(1_0, STAT_COUNT), + PSCI_ID_NATIVE(1_1, SYSTEM_RESET2), + PSCI_ID(1_1, MEM_PROTECT), + PSCI_ID_NATIVE(1_1, MEM_PROTECT_CHECK_RANGE), +}; + +static int psci_debugfs_read(struct seq_file *s, void *data) +{ + int feature, type, i; + u32 ver; + + ver = psci_ops.get_version(); + seq_printf(s, "PSCIv%d.%d\n", + PSCI_VERSION_MAJOR(ver), + PSCI_VERSION_MINOR(ver)); + + /* PSCI_FEATURES is available only starting from 1.0 */ + if (PSCI_VERSION_MAJOR(ver) < 1) + return 0; + + feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID); + if (feature != PSCI_RET_NOT_SUPPORTED) { + ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0); + seq_printf(s, "SMC Calling Convention v%d.%d\n", + PSCI_VERSION_MAJOR(ver), + PSCI_VERSION_MINOR(ver)); + } else { + seq_puts(s, "SMC Calling Convention v1.0 is assumed\n"); + } + + feature = psci_features(PSCI_FN_NATIVE(0_2, CPU_SUSPEND)); + if (feature < 0) { + seq_printf(s, "PSCI_FEATURES(CPU_SUSPEND) error (%d)\n", feature); + } else { + seq_printf(s, "OSI is %ssupported\n", + (feature & BIT(0)) ? "" : "not "); + seq_printf(s, "%s StateID format is used\n", + (feature & BIT(1)) ? "Extended" : "Original"); + } + + type = psci_ops.migrate_info_type(); + if (type == PSCI_0_2_TOS_UP_MIGRATE || + type == PSCI_0_2_TOS_UP_NO_MIGRATE) { + unsigned long cpuid; + + seq_printf(s, "Trusted OS %smigrate capable\n", + type == PSCI_0_2_TOS_UP_NO_MIGRATE ? "not " : ""); + cpuid = psci_migrate_info_up_cpu(); + seq_printf(s, "Trusted OS resident on physical CPU 0x%lx (#%d)\n", + cpuid, resident_cpu); + } else if (type == PSCI_0_2_TOS_MP) { + seq_puts(s, "Trusted OS migration not required\n"); + } else { + if (type != PSCI_RET_NOT_SUPPORTED) + seq_printf(s, "MIGRATE_INFO_TYPE returned unknown type (%d)\n", type); + } + + for (i = 0; i < ARRAY_SIZE(psci_fn_ids); i++) { + feature = psci_features(psci_fn_ids[i].fn); + if (feature == PSCI_RET_NOT_SUPPORTED) + continue; + if (feature < 0) + seq_printf(s, "PSCI_FEATURES(%s) error (%d)\n", + psci_fn_ids[i].name, feature); + else + seq_printf(s, "%s is supported\n", psci_fn_ids[i].name); + } + + return 0; +} + +static int psci_debugfs_open(struct inode *inode, struct file *f) +{ + return single_open(f, psci_debugfs_read, NULL); +} + +static const struct file_operations psci_debugfs_ops = { + .owner = THIS_MODULE, + .open = psci_debugfs_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek +}; + +static int __init psci_debugfs_init(void) +{ + return PTR_ERR_OR_ZERO(debugfs_create_file("psci", 0444, NULL, NULL, + &psci_debugfs_ops)); +} +late_initcall(psci_debugfs_init) +#endif + #ifdef CONFIG_CPU_IDLE static int psci_suspend_finisher(unsigned long state) { diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h index 2bf93c0d6354..3511095c2702 100644 --- a/include/uapi/linux/psci.h +++ b/include/uapi/linux/psci.h @@ -48,12 +48,26 @@ #define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7) #define PSCI_1_0_FN_PSCI_FEATURES PSCI_0_2_FN(10) +#define PSCI_1_0_FN_CPU_FREEZE PSCI_0_2_FN(11) +#define PSCI_1_0_FN_CPU_DEFAULT_SUSPEND PSCI_0_2_FN(12) +#define PSCI_1_0_FN_NODE_HW_STATE PSCI_0_2_FN(13) #define PSCI_1_0_FN_SYSTEM_SUSPEND PSCI_0_2_FN(14) #define PSCI_1_0_FN_SET_SUSPEND_MODE PSCI_0_2_FN(15) +#define PSCI_1_0_FN_STAT_RESIDENCY PSCI_0_2_FN(16) +#define PSCI_1_0_FN_STAT_COUNT PSCI_0_2_FN(17) + #define PSCI_1_1_FN_SYSTEM_RESET2 PSCI_0_2_FN(18) +#define PSCI_1_1_FN_MEM_PROTECT PSCI_0_2_FN(19) +#define PSCI_1_1_FN_MEM_PROTECT_CHECK_RANGE PSCI_0_2_FN(19) +#define PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND PSCI_0_2_FN64(12) +#define PSCI_1_0_FN64_NODE_HW_STATE PSCI_0_2_FN64(13) #define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14) +#define PSCI_1_0_FN64_STAT_RESIDENCY PSCI_0_2_FN64(16) +#define PSCI_1_0_FN64_STAT_COUNT PSCI_0_2_FN64(17) + #define PSCI_1_1_FN64_SYSTEM_RESET2 PSCI_0_2_FN64(18) +#define PSCI_1_1_FN64_MEM_PROTECT_CHECK_RANGE PSCI_0_2_FN64(19) /* PSCI v0.2 power state encoding for CPU_SUSPEND function */ #define PSCI_0_2_POWER_STATE_ID_MASK 0xffff -- cgit v1.2.3