diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-21 05:42:28 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-21 05:42:28 +0300 |
commit | e767b3530acbf651593e3d357fe1168a024d8061 (patch) | |
tree | 0f549bbb4cf187661416f672dd0329c59b7a8fee /drivers/soc | |
parent | 82851fce6107d5a3e66d95aee2ae68860a732703 (diff) | |
parent | 4f79a8b06fccec3dd68935db5a4662435c472abf (diff) | |
download | linux-e767b3530acbf651593e3d357fe1168a024d8061.tar.xz |
Merge tag 'arm-drivers-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann:
"Updates for SoC specific drivers include a few subsystems that have
their own maintainers but send them through the soc tree:
SCMI firmware:
- add support for a completion interrupt
Reset controllers:
- new driver for BCM4908
- new devm_reset_control_get_optional_exclusive_released() function
Memory controllers:
- Renesas RZ/G2 support
- Tegra124 interconnect support
- Allow more drivers to be loadable modules
TEE/optee firmware:
- minor code cleanup
The other half of this is SoC specific drivers that do not belong into
any other subsystem, most of them living in drivers/soc:
- Allwinner/sunxi power management work
- Allwinner H616 support
- ASpeed AST2600 system identification support
- AT91 SAMA7G5 SoC ID driver
- AT91 SoC driver cleanups
- Broadcom BCM4908 power management bus support
- Marvell mbus cleanups
- Mediatek MT8167 power domain support
- Qualcomm socinfo driver support for PMIC
- Qualcomm SoC identification for many more products
- TI Keystone driver cleanups for PRUSS and elsewhere"
* tag 'arm-drivers-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (89 commits)
soc: aspeed: socinfo: Add new systems
soc: aspeed: snoop: Add clock control logic
memory: tegra186-emc: Replace DEFINE_SIMPLE_ATTRIBUTE with DEFINE_DEBUGFS_ATTRIBUTE
memory: samsung: exynos5422-dmc: Correct function names in kerneldoc
memory: ti-emif-pm: Drop of_match_ptr from of_device_id table
optee: simplify i2c access
drivers: soc: atmel: fix type for same7
tee: optee: remove need_resched() before cond_resched()
soc: qcom: ocmem: don't return NULL in of_get_ocmem
optee: sync OP-TEE headers
tee: optee: fix 'physical' typos
drivers: optee: use flexible-array member instead of zero-length array
tee: fix some comment typos in header files
soc: ti: k3-ringacc: Use of_device_get_match_data()
soc: ti: pruss: Refactor the CFG sub-module init
soc: mediatek: pm-domains: Don't print an error if child domain is deferred
soc: mediatek: pm-domains: Add domain regulator supply
dt-bindings: power: Add domain regulator supply
soc: mediatek: cmdq: Remove cmdq_pkt_flush()
soc: mediatek: pm-domains: Add support for mt8167
...
Diffstat (limited to 'drivers/soc')
28 files changed, 1035 insertions, 250 deletions
diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c index 682ba0eb4eba..20acac6342ef 100644 --- a/drivers/soc/aspeed/aspeed-lpc-snoop.c +++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c @@ -11,6 +11,7 @@ */ #include <linux/bitops.h> +#include <linux/clk.h> #include <linux/interrupt.h> #include <linux/fs.h> #include <linux/kfifo.h> @@ -67,6 +68,7 @@ struct aspeed_lpc_snoop_channel { struct aspeed_lpc_snoop { struct regmap *regmap; int irq; + struct clk *clk; struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS]; }; @@ -282,22 +284,42 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) return -ENODEV; } + lpc_snoop->clk = devm_clk_get(dev, NULL); + if (IS_ERR(lpc_snoop->clk)) { + rc = PTR_ERR(lpc_snoop->clk); + if (rc != -EPROBE_DEFER) + dev_err(dev, "couldn't get clock\n"); + return rc; + } + rc = clk_prepare_enable(lpc_snoop->clk); + if (rc) { + dev_err(dev, "couldn't enable clock\n"); + return rc; + } + rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev); if (rc) - return rc; + goto err; rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port); if (rc) - return rc; + goto err; /* Configuration of 2nd snoop channel port is optional */ if (of_property_read_u32_index(dev->of_node, "snoop-ports", 1, &port) == 0) { rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port); - if (rc) + if (rc) { aspeed_lpc_disable_snoop(lpc_snoop, 0); + goto err; + } } + return 0; + +err: + clk_disable_unprepare(lpc_snoop->clk); + return rc; } @@ -309,6 +331,8 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev) aspeed_lpc_disable_snoop(lpc_snoop, 0); aspeed_lpc_disable_snoop(lpc_snoop, 1); + clk_disable_unprepare(lpc_snoop->clk); + return 0; } diff --git a/drivers/soc/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c index 773930e0cb10..e3215f826d17 100644 --- a/drivers/soc/aspeed/aspeed-socinfo.c +++ b/drivers/soc/aspeed/aspeed-socinfo.c @@ -25,6 +25,7 @@ static struct { /* AST2600 */ { "AST2600", 0x05000303 }, { "AST2620", 0x05010203 }, + { "AST2605", 0x05030103 }, }; static const char *siliconid_to_name(u32 siliconid) @@ -43,14 +44,30 @@ static const char *siliconid_to_name(u32 siliconid) static const char *siliconid_to_rev(u32 siliconid) { unsigned int rev = (siliconid >> 16) & 0xff; - - switch (rev) { - case 0: - return "A0"; - case 1: - return "A1"; - case 3: - return "A2"; + unsigned int gen = (siliconid >> 24) & 0xff; + + if (gen < 0x5) { + /* AST2500 and below */ + switch (rev) { + case 0: + return "A0"; + case 1: + return "A1"; + case 3: + return "A2"; + } + } else { + /* AST2600 */ + switch (rev) { + case 0: + return "A0"; + case 1: + return "A1"; + case 2: + return "A2"; + case 3: + return "A3"; + } } return "??"; diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index 698d21f50516..a490ad7e090f 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2015 Atmel * * Alexandre Belloni <alexandre.belloni@free-electrons.com * Boris Brezillon <boris.brezillon@free-electrons.com - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * */ #define pr_fmt(fmt) "AT91: " fmt @@ -25,137 +21,218 @@ #define AT91_DBGU_EXID 0x44 #define AT91_CHIPID_CIDR 0x00 #define AT91_CHIPID_EXID 0x04 -#define AT91_CIDR_VERSION(x) ((x) & 0x1f) +#define AT91_CIDR_VERSION(x, m) ((x) & (m)) +#define AT91_CIDR_VERSION_MASK GENMASK(4, 0) +#define AT91_CIDR_VERSION_MASK_SAMA7G5 GENMASK(3, 0) #define AT91_CIDR_EXT BIT(31) -#define AT91_CIDR_MATCH_MASK 0x7fffffe0 +#define AT91_CIDR_MATCH_MASK GENMASK(30, 5) +#define AT91_CIDR_MASK_SAMA7G5 GENMASK(27, 5) -static const struct at91_soc __initconst socs[] = { +static const struct at91_soc socs[] __initconst = { #ifdef CONFIG_SOC_AT91RM9200 - AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"), + AT91_SOC(AT91RM9200_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91rm9200 BGA", "at91rm9200"), #endif #ifdef CONFIG_SOC_AT91SAM9 - AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL), - AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL), - AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL), - AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL), - AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH, + AT91_SOC(AT91SAM9260_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9260", NULL), + AT91_SOC(AT91SAM9261_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9261", NULL), + AT91_SOC(AT91SAM9263_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9263", NULL), + AT91_SOC(AT91SAM9G20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9g20", NULL), + AT91_SOC(AT91SAM9RL64_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9rl64", NULL), + AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9M11_EXID_MATCH, "at91sam9m11", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH, + AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9M10_EXID_MATCH, "at91sam9m10", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH, + AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G46_EXID_MATCH, "at91sam9g46", "at91sam9g45"), - AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH, + AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G45_EXID_MATCH, "at91sam9g45", "at91sam9g45"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G15_EXID_MATCH, "at91sam9g15", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G35_EXID_MATCH, "at91sam9g35", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9X35_EXID_MATCH, "at91sam9x35", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9G25_EXID_MATCH, "at91sam9g25", "at91sam9x5"), - AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH, + AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9X25_EXID_MATCH, "at91sam9x25", "at91sam9x5"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH, + AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9CN12_EXID_MATCH, "at91sam9cn12", "at91sam9n12"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH, + AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9N12_EXID_MATCH, "at91sam9n12", "at91sam9n12"), - AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH, + AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, AT91SAM9CN11_EXID_MATCH, "at91sam9cn11", "at91sam9n12"), - AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"), - AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"), - AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"), + AT91_SOC(AT91SAM9XE128_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9xe128", "at91sam9xe128"), + AT91_SOC(AT91SAM9XE256_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9xe256", "at91sam9xe256"), + AT91_SOC(AT91SAM9XE512_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, 0, "at91sam9xe512", "at91sam9xe512"), #endif #ifdef CONFIG_SOC_SAM9X60 - AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_EXID_MATCH, "sam9x60", "sam9x60"), + AT91_SOC(SAM9X60_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH, + "sam9x60", "sam9x60"), AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D5M_EXID_MATCH, + AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH, "sam9x60 64MiB DDR2 SiP", "sam9x60"), AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D1G_EXID_MATCH, + AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH, "sam9x60 128MiB DDR2 SiP", "sam9x60"), AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D6K_EXID_MATCH, + AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH, "sam9x60 8MiB SDRAM SiP", "sam9x60"), #endif #ifdef CONFIG_SOC_SAMA5 - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D21CU_EXID_MATCH, "sama5d21", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D22CU_EXID_MATCH, "sama5d22", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D225C_D1M_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D225C_D1M_EXID_MATCH, "sama5d225c 16MiB SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D23CU_EXID_MATCH, "sama5d23", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D24CX_EXID_MATCH, "sama5d24", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D24CU_EXID_MATCH, "sama5d24", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D26CU_EXID_MATCH, "sama5d26", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27CU_EXID_MATCH, "sama5d27", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27CN_EXID_MATCH, "sama5d27", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_D1G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27C_D1G_EXID_MATCH, "sama5d27c 128MiB SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_D5M_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27C_D5M_EXID_MATCH, "sama5d27c 64MiB SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_LD1G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27C_LD1G_EXID_MATCH, "sama5d27c 128MiB LPDDR2 SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_LD2G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D27C_LD2G_EXID_MATCH, "sama5d27c 256MiB LPDDR2 SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28CU_EXID_MATCH, "sama5d28", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28CN_EXID_MATCH, "sama5d28", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_D1G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28C_D1G_EXID_MATCH, "sama5d28c 128MiB SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_LD1G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28C_LD1G_EXID_MATCH, "sama5d28c 128MiB LPDDR2 SiP", "sama5d2"), - AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_LD2G_EXID_MATCH, + AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D28C_LD2G_EXID_MATCH, "sama5d28c 256MiB LPDDR2 SiP", "sama5d2"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D31_EXID_MATCH, "sama5d31", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D33_EXID_MATCH, "sama5d33", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D34_EXID_MATCH, "sama5d34", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D35_EXID_MATCH, "sama5d35", "sama5d3"), - AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH, + AT91_SOC(SAMA5D3_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D36_EXID_MATCH, "sama5d36", "sama5d3"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH, + AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D41_EXID_MATCH, "sama5d41", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH, + AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D42_EXID_MATCH, "sama5d42", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH, + AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D43_EXID_MATCH, "sama5d43", "sama5d4"), - AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH, + AT91_SOC(SAMA5D4_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMA5D44_EXID_MATCH, "sama5d44", "sama5d4"), #endif #ifdef CONFIG_SOC_SAMV7 - AT91_SOC(SAME70Q21_CIDR_MATCH, SAME70Q21_EXID_MATCH, + AT91_SOC(SAME70Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAME70Q21_EXID_MATCH, "same70q21", "same7"), - AT91_SOC(SAME70Q20_CIDR_MATCH, SAME70Q20_EXID_MATCH, + AT91_SOC(SAME70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAME70Q20_EXID_MATCH, "same70q20", "same7"), - AT91_SOC(SAME70Q19_CIDR_MATCH, SAME70Q19_EXID_MATCH, + AT91_SOC(SAME70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAME70Q19_EXID_MATCH, "same70q19", "same7"), - AT91_SOC(SAMS70Q21_CIDR_MATCH, SAMS70Q21_EXID_MATCH, + AT91_SOC(SAMS70Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMS70Q21_EXID_MATCH, "sams70q21", "sams7"), - AT91_SOC(SAMS70Q20_CIDR_MATCH, SAMS70Q20_EXID_MATCH, + AT91_SOC(SAMS70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMS70Q20_EXID_MATCH, "sams70q20", "sams7"), - AT91_SOC(SAMS70Q19_CIDR_MATCH, SAMS70Q19_EXID_MATCH, + AT91_SOC(SAMS70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMS70Q19_EXID_MATCH, "sams70q19", "sams7"), - AT91_SOC(SAMV71Q21_CIDR_MATCH, SAMV71Q21_EXID_MATCH, + AT91_SOC(SAMV71Q21_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV71Q21_EXID_MATCH, "samv71q21", "samv7"), - AT91_SOC(SAMV71Q20_CIDR_MATCH, SAMV71Q20_EXID_MATCH, + AT91_SOC(SAMV71Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV71Q20_EXID_MATCH, "samv71q20", "samv7"), - AT91_SOC(SAMV71Q19_CIDR_MATCH, SAMV71Q19_EXID_MATCH, + AT91_SOC(SAMV71Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV71Q19_EXID_MATCH, "samv71q19", "samv7"), - AT91_SOC(SAMV70Q20_CIDR_MATCH, SAMV70Q20_EXID_MATCH, + AT91_SOC(SAMV70Q20_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV70Q20_EXID_MATCH, "samv70q20", "samv7"), - AT91_SOC(SAMV70Q19_CIDR_MATCH, SAMV70Q19_EXID_MATCH, + AT91_SOC(SAMV70Q19_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK, SAMV70Q19_EXID_MATCH, "samv70q19", "samv7"), #endif +#ifdef CONFIG_SOC_SAMA7 + AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G51_EXID_MATCH, + "sama7g51", "sama7g5"), + AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G52_EXID_MATCH, + "sama7g52", "sama7g5"), + AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G53_EXID_MATCH, + "sama7g53", "sama7g5"), + AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK, + AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G54_EXID_MATCH, + "sama7g54", "sama7g5"), +#endif { /* sentinel */ }, }; @@ -191,8 +268,13 @@ static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid) { struct device_node *np; void __iomem *regs; + static const struct of_device_id chipids[] = { + { .compatible = "atmel,sama5d2-chipid" }, + { .compatible = "microchip,sama7g5-chipid" }, + { }, + }; - np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid"); + np = of_find_matching_node(NULL, chipids); if (!np) return -ENODEV; @@ -235,7 +317,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) } for (soc = socs; soc->name; soc++) { - if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK)) + if (soc->cidr_match != (cidr & soc->cidr_mask)) continue; if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid) @@ -254,7 +336,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) soc_dev_attr->family = soc->family; soc_dev_attr->soc_id = soc->name; soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", - AT91_CIDR_VERSION(cidr)); + AT91_CIDR_VERSION(cidr, soc->version_mask)); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { kfree(soc_dev_attr->revision); @@ -266,7 +348,7 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) if (soc->family) pr_info("Detected SoC family: %s\n", soc->family); pr_info("Detected SoC: %s, revision %X\n", soc->name, - AT91_CIDR_VERSION(cidr)); + AT91_CIDR_VERSION(cidr, soc->version_mask)); return soc_dev; } @@ -276,6 +358,7 @@ static const struct of_device_id at91_soc_allowed_list[] __initconst = { { .compatible = "atmel,at91sam9", }, { .compatible = "atmel,sama5", }, { .compatible = "atmel,samv7", }, + { .compatible = "microchip,sama7g5", }, { } }; diff --git a/drivers/soc/atmel/soc.h b/drivers/soc/atmel/soc.h index 5849846a69d6..c3eb3c8f0834 100644 --- a/drivers/soc/atmel/soc.h +++ b/drivers/soc/atmel/soc.h @@ -1,12 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2015 Atmel * * Boris Brezillon <boris.brezillon@free-electrons.com - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * */ #ifndef __AT91_SOC_H @@ -16,14 +12,19 @@ struct at91_soc { u32 cidr_match; + u32 cidr_mask; + u32 version_mask; u32 exid_match; const char *name; const char *family; }; -#define AT91_SOC(__cidr, __exid, __name, __family) \ +#define AT91_SOC(__cidr, __cidr_mask, __version_mask, __exid, \ + __name, __family) \ { \ .cidr_match = (__cidr), \ + .cidr_mask = (__cidr_mask), \ + .version_mask = (__version_mask), \ .exid_match = (__exid), \ .name = (__name), \ .family = (__family), \ @@ -43,6 +44,7 @@ at91_soc_init(const struct at91_soc *socs); #define AT91SAM9X5_CIDR_MATCH 0x019a05a0 #define AT91SAM9N12_CIDR_MATCH 0x019a07a0 #define SAM9X60_CIDR_MATCH 0x019b35a0 +#define SAMA7G5_CIDR_MATCH 0x00162100 #define AT91SAM9M11_EXID_MATCH 0x00000001 #define AT91SAM9M10_EXID_MATCH 0x00000002 @@ -64,6 +66,11 @@ at91_soc_init(const struct at91_soc *socs); #define SAM9X60_D1G_EXID_MATCH 0x00000010 #define SAM9X60_D6K_EXID_MATCH 0x00000011 +#define SAMA7G51_EXID_MATCH 0x3 +#define SAMA7G52_EXID_MATCH 0x2 +#define SAMA7G53_EXID_MATCH 0x1 +#define SAMA7G54_EXID_MATCH 0x0 + #define AT91SAM9XE128_CIDR_MATCH 0x329973a0 #define AT91SAM9XE256_CIDR_MATCH 0x329a93a0 #define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0 diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile index 7bc90e0bd773..0f0efa28d92b 100644 --- a/drivers/soc/bcm/Makefile +++ b/drivers/soc/bcm/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_BCM2835_POWER) += bcm2835-power.o obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o -obj-$(CONFIG_SOC_BCM63XX) += bcm63xx/ +obj-y += bcm63xx/ obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ diff --git a/drivers/soc/bcm/bcm63xx/Kconfig b/drivers/soc/bcm/bcm63xx/Kconfig index 16f648a6c70a..9e501c8ac5ce 100644 --- a/drivers/soc/bcm/bcm63xx/Kconfig +++ b/drivers/soc/bcm/bcm63xx/Kconfig @@ -10,3 +10,12 @@ config BCM63XX_POWER BCM6318, BCM6328, BCM6362 and BCM63268 SoCs. endif # SOC_BCM63XX + +config BCM_PMB + bool "Broadcom PMB (Power Management Bus) driver" + depends on ARCH_BCM4908 || (COMPILE_TEST && OF) + default ARCH_BCM4908 + select PM_GENERIC_DOMAINS if PM + help + This enables support for the Broadcom's PMB (Power Management Bus) that + is used for disabling and enabling SoC devices. diff --git a/drivers/soc/bcm/bcm63xx/Makefile b/drivers/soc/bcm/bcm63xx/Makefile index 0710d5e018cc..557eed3d67bd 100644 --- a/drivers/soc/bcm/bcm63xx/Makefile +++ b/drivers/soc/bcm/bcm63xx/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o +obj-$(CONFIG_BCM_PMB) += bcm-pmb.o diff --git a/drivers/soc/bcm/bcm63xx/bcm-pmb.c b/drivers/soc/bcm/bcm63xx/bcm-pmb.c new file mode 100644 index 000000000000..c223023dc64f --- /dev/null +++ b/drivers/soc/bcm/bcm63xx/bcm-pmb.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2013 Broadcom + * Copyright (C) 2020 Rafał Miłecki <rafal@milecki.pl> + */ + +#include <dt-bindings/soc/bcm-pmb.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_domain.h> +#include <linux/reset/bcm63xx_pmb.h> + +#define BPCM_ID_REG 0x00 +#define BPCM_CAPABILITIES 0x04 +#define BPCM_CAP_NUM_ZONES 0x000000ff +#define BPCM_CAP_SR_REG_BITS 0x0000ff00 +#define BPCM_CAP_PLLTYPE 0x00030000 +#define BPCM_CAP_UBUS 0x00080000 +#define BPCM_CONTROL 0x08 +#define BPCM_STATUS 0x0c +#define BPCM_ROSC_CONTROL 0x10 +#define BPCM_ROSC_THRESH_H 0x14 +#define BPCM_ROSC_THRESHOLD_BCM6838 0x14 +#define BPCM_ROSC_THRESH_S 0x18 +#define BPCM_ROSC_COUNT_BCM6838 0x18 +#define BPCM_ROSC_COUNT 0x1c +#define BPCM_PWD_CONTROL_BCM6838 0x1c +#define BPCM_PWD_CONTROL 0x20 +#define BPCM_SR_CONTROL_BCM6838 0x20 +#define BPCM_PWD_ACCUM_CONTROL 0x24 +#define BPCM_SR_CONTROL 0x28 +#define BPCM_GLOBAL_CONTROL 0x2c +#define BPCM_MISC_CONTROL 0x30 +#define BPCM_MISC_CONTROL2 0x34 +#define BPCM_SGPHY_CNTL 0x38 +#define BPCM_SGPHY_STATUS 0x3c +#define BPCM_ZONE0 0x40 +#define BPCM_ZONE_CONTROL 0x00 +#define BPCM_ZONE_CONTROL_MANUAL_CLK_EN 0x00000001 +#define BPCM_ZONE_CONTROL_MANUAL_RESET_CTL 0x00000002 +#define BPCM_ZONE_CONTROL_FREQ_SCALE_USED 0x00000004 /* R/O */ +#define BPCM_ZONE_CONTROL_DPG_CAPABLE 0x00000008 /* R/O */ +#define BPCM_ZONE_CONTROL_MANUAL_MEM_PWR 0x00000030 +#define BPCM_ZONE_CONTROL_MANUAL_ISO_CTL 0x00000040 +#define BPCM_ZONE_CONTROL_MANUAL_CTL 0x00000080 +#define BPCM_ZONE_CONTROL_DPG_CTL_EN 0x00000100 +#define BPCM_ZONE_CONTROL_PWR_DN_REQ 0x00000200 +#define BPCM_ZONE_CONTROL_PWR_UP_REQ 0x00000400 +#define BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN 0x00000800 +#define BPCM_ZONE_CONTROL_BLK_RESET_ASSERT 0x00001000 +#define BPCM_ZONE_CONTROL_MEM_STBY 0x00002000 +#define BPCM_ZONE_CONTROL_RESERVED 0x0007c000 +#define BPCM_ZONE_CONTROL_PWR_CNTL_STATE 0x00f80000 +#define BPCM_ZONE_CONTROL_FREQ_SCALAR_DYN_SEL 0x01000000 /* R/O */ +#define BPCM_ZONE_CONTROL_PWR_OFF_STATE 0x02000000 /* R/O */ +#define BPCM_ZONE_CONTROL_PWR_ON_STATE 0x04000000 /* R/O */ +#define BPCM_ZONE_CONTROL_PWR_GOOD 0x08000000 /* R/O */ +#define BPCM_ZONE_CONTROL_DPG_PWR_STATE 0x10000000 /* R/O */ +#define BPCM_ZONE_CONTROL_MEM_PWR_STATE 0x20000000 /* R/O */ +#define BPCM_ZONE_CONTROL_ISO_STATE 0x40000000 /* R/O */ +#define BPCM_ZONE_CONTROL_RESET_STATE 0x80000000 /* R/O */ +#define BPCM_ZONE_CONFIG1 0x04 +#define BPCM_ZONE_CONFIG2 0x08 +#define BPCM_ZONE_FREQ_SCALAR_CONTROL 0x0c +#define BPCM_ZONE_SIZE 0x10 + +struct bcm_pmb { + struct device *dev; + void __iomem *base; + spinlock_t lock; + bool little_endian; + struct genpd_onecell_data genpd_onecell_data; +}; + +struct bcm_pmb_pd_data { + const char * const name; + int id; + u8 bus; + u8 device; +}; + +struct bcm_pmb_pm_domain { + struct bcm_pmb *pmb; + const struct bcm_pmb_pd_data *data; + struct generic_pm_domain genpd; +}; + +static int bcm_pmb_bpcm_read(struct bcm_pmb *pmb, int bus, u8 device, + int offset, u32 *val) +{ + void __iomem *base = pmb->base + bus * 0x20; + unsigned long flags; + int err; + + spin_lock_irqsave(&pmb->lock, flags); + err = bpcm_rd(base, device, offset, val); + spin_unlock_irqrestore(&pmb->lock, flags); + + if (!err) + *val = pmb->little_endian ? le32_to_cpu(*val) : be32_to_cpu(*val); + + return err; +} + +static int bcm_pmb_bpcm_write(struct bcm_pmb *pmb, int bus, u8 device, + int offset, u32 val) +{ + void __iomem *base = pmb->base + bus * 0x20; + unsigned long flags; + int err; + + val = pmb->little_endian ? cpu_to_le32(val) : cpu_to_be32(val); + + spin_lock_irqsave(&pmb->lock, flags); + err = bpcm_wr(base, device, offset, val); + spin_unlock_irqrestore(&pmb->lock, flags); + + return err; +} + +static int bcm_pmb_power_off_zone(struct bcm_pmb *pmb, int bus, u8 device, + int zone) +{ + int offset; + u32 val; + int err; + + offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL; + + err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); + if (err) + return err; + + val |= BPCM_ZONE_CONTROL_PWR_DN_REQ; + val &= ~BPCM_ZONE_CONTROL_PWR_UP_REQ; + + err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); + + return err; +} + +static int bcm_pmb_power_on_zone(struct bcm_pmb *pmb, int bus, u8 device, + int zone) +{ + int offset; + u32 val; + int err; + + offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL; + + err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); + if (err) + return err; + + if (!(val & BPCM_ZONE_CONTROL_PWR_ON_STATE)) { + val &= ~BPCM_ZONE_CONTROL_PWR_DN_REQ; + val |= BPCM_ZONE_CONTROL_DPG_CTL_EN; + val |= BPCM_ZONE_CONTROL_PWR_UP_REQ; + val |= BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN; + val |= BPCM_ZONE_CONTROL_BLK_RESET_ASSERT; + + err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); + } + + return err; +} + +static int bcm_pmb_power_off_device(struct bcm_pmb *pmb, int bus, u8 device) +{ + int offset; + u32 val; + int err; + + /* Entire device can be powered off by powering off the 0th zone */ + offset = BPCM_ZONE0 + BPCM_ZONE_CONTROL; + + err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val); + if (err) + return err; + + if (!(val & BPCM_ZONE_CONTROL_PWR_OFF_STATE)) { + val = BPCM_ZONE_CONTROL_PWR_DN_REQ; + + err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val); + } + + return err; +} + +static int bcm_pmb_power_on_device(struct bcm_pmb *pmb, int bus, u8 device) +{ + u32 val; + int err; + int i; + + err = bcm_pmb_bpcm_read(pmb, bus, device, BPCM_CAPABILITIES, &val); + if (err) + return err; + + for (i = 0; i < (val & BPCM_CAP_NUM_ZONES); i++) { + err = bcm_pmb_power_on_zone(pmb, bus, device, i); + if (err) + return err; + } + + return err; +} + +static int bcm_pmb_power_on(struct generic_pm_domain *genpd) +{ + struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd); + const struct bcm_pmb_pd_data *data = pd->data; + struct bcm_pmb *pmb = pd->pmb; + + switch (data->id) { + case BCM_PMB_PCIE0: + case BCM_PMB_PCIE1: + case BCM_PMB_PCIE2: + return bcm_pmb_power_on_zone(pmb, data->bus, data->device, 0); + case BCM_PMB_HOST_USB: + return bcm_pmb_power_on_device(pmb, data->bus, data->device); + default: + dev_err(pmb->dev, "unsupported device id: %d\n", data->id); + return -EINVAL; + } +} + +static int bcm_pmb_power_off(struct generic_pm_domain *genpd) +{ + struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd); + const struct bcm_pmb_pd_data *data = pd->data; + struct bcm_pmb *pmb = pd->pmb; + + switch (data->id) { + case BCM_PMB_PCIE0: + case BCM_PMB_PCIE1: + case BCM_PMB_PCIE2: + return bcm_pmb_power_off_zone(pmb, data->bus, data->device, 0); + case BCM_PMB_HOST_USB: + return bcm_pmb_power_off_device(pmb, data->bus, data->device); + default: + dev_err(pmb->dev, "unsupported device id: %d\n", data->id); + return -EINVAL; + } +} + +static int bcm_pmb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct bcm_pmb_pd_data *table; + const struct bcm_pmb_pd_data *e; + struct resource *res; + struct bcm_pmb *pmb; + int max_id; + int err; + + pmb = devm_kzalloc(dev, sizeof(*pmb), GFP_KERNEL); + if (!pmb) + return -ENOMEM; + + pmb->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pmb->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pmb->base)) + return PTR_ERR(pmb->base); + + spin_lock_init(&pmb->lock); + + pmb->little_endian = !of_device_is_big_endian(dev->of_node); + + table = of_device_get_match_data(dev); + if (!table) + return -EINVAL; + + max_id = 0; + for (e = table; e->name; e++) + max_id = max(max_id, e->id); + + pmb->genpd_onecell_data.num_domains = max_id + 1; + pmb->genpd_onecell_data.domains = + devm_kcalloc(dev, pmb->genpd_onecell_data.num_domains, + sizeof(struct generic_pm_domain *), GFP_KERNEL); + if (!pmb->genpd_onecell_data.domains) + return -ENOMEM; + + for (e = table; e->name; e++) { + struct bcm_pmb_pm_domain *pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + + pd->pmb = pmb; + pd->data = e; + pd->genpd.name = e->name; + pd->genpd.power_on = bcm_pmb_power_on; + pd->genpd.power_off = bcm_pmb_power_off; + + pm_genpd_init(&pd->genpd, NULL, true); + pmb->genpd_onecell_data.domains[e->id] = &pd->genpd; + } + + err = of_genpd_add_provider_onecell(dev->of_node, &pmb->genpd_onecell_data); + if (err) { + dev_err(dev, "failed to add genpd provider: %d\n", err); + return err; + } + + return 0; +} + +static const struct bcm_pmb_pd_data bcm_pmb_bcm4908_data[] = { + { .name = "pcie2", .id = BCM_PMB_PCIE2, .bus = 0, .device = 2, }, + { .name = "pcie0", .id = BCM_PMB_PCIE0, .bus = 1, .device = 14, }, + { .name = "pcie1", .id = BCM_PMB_PCIE1, .bus = 1, .device = 15, }, + { .name = "usb", .id = BCM_PMB_HOST_USB, .bus = 1, .device = 17, }, + { }, +}; + +static const struct of_device_id bcm_pmb_of_match[] = { + { .compatible = "brcm,bcm4908-pmb", .data = &bcm_pmb_bcm4908_data, }, + { }, +}; + +static struct platform_driver bcm_pmb_driver = { + .driver = { + .name = "bcm-pmb", + .of_match_table = bcm_pmb_of_match, + }, + .probe = bcm_pmb_probe, +}; + +builtin_platform_driver(bcm_pmb_driver); diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c index d33a383701dd..e87dfc6660f3 100644 --- a/drivers/soc/bcm/brcmstb/common.c +++ b/drivers/soc/bcm/brcmstb/common.c @@ -11,8 +11,6 @@ #include <linux/soc/brcmstb/brcmstb.h> #include <linux/sys_soc.h> -#include <soc/brcmstb/common.h> - static u32 family_id; static u32 product_id; @@ -21,21 +19,6 @@ static const struct of_device_id brcmstb_machine_match[] = { { } }; -bool soc_is_brcmstb(void) -{ - const struct of_device_id *match; - struct device_node *root; - - root = of_find_node_by_path("/"); - if (!root) - return false; - - match = of_match_node(brcmstb_machine_match, root); - of_node_put(root); - - return match != NULL; -} - u32 brcmstb_get_family_id(void) { return family_id; diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c index cc57a384d74d..071e14496e4b 100644 --- a/drivers/soc/imx/soc-imx8m.c +++ b/drivers/soc/imx/soc-imx8m.c @@ -5,6 +5,8 @@ #include <linux/init.h> #include <linux/io.h> +#include <linux/module.h> +#include <linux/nvmem-consumer.h> #include <linux/of_address.h> #include <linux/slab.h> #include <linux/sys_soc.h> @@ -29,7 +31,7 @@ struct imx8_soc_data { char *name; - u32 (*soc_revision)(void); + u32 (*soc_revision)(struct device *dev); }; static u64 soc_uid; @@ -50,7 +52,7 @@ static u32 imx8mq_soc_revision_from_atf(void) static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; }; #endif -static u32 __init imx8mq_soc_revision(void) +static u32 __init imx8mq_soc_revision(struct device *dev) { struct device_node *np; void __iomem *ocotp_base; @@ -75,9 +77,20 @@ static u32 __init imx8mq_soc_revision(void) rev = REV_B1; } - soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); - soc_uid <<= 32; - soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + if (dev) { + int ret; + + ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid); + if (ret) { + iounmap(ocotp_base); + of_node_put(np); + return ret; + } + } else { + soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH); + soc_uid <<= 32; + soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); + } iounmap(ocotp_base); of_node_put(np); @@ -107,7 +120,7 @@ static void __init imx8mm_soc_uid(void) of_node_put(np); } -static u32 __init imx8mm_soc_revision(void) +static u32 __init imx8mm_soc_revision(struct device *dev) { struct device_node *np; void __iomem *anatop_base; @@ -125,7 +138,15 @@ static u32 __init imx8mm_soc_revision(void) iounmap(anatop_base); of_node_put(np); - imx8mm_soc_uid(); + if (dev) { + int ret; + + ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid); + if (ret) + return ret; + } else { + imx8mm_soc_uid(); + } return rev; } @@ -150,7 +171,7 @@ static const struct imx8_soc_data imx8mp_soc_data = { .soc_revision = imx8mm_soc_revision, }; -static __maybe_unused const struct of_device_id imx8_soc_match[] = { +static __maybe_unused const struct of_device_id imx8_machine_match[] = { { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, }, { .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, }, { .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, }, @@ -158,12 +179,20 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = { { } }; +static __maybe_unused const struct of_device_id imx8_soc_match[] = { + { .compatible = "fsl,imx8mq-soc", .data = &imx8mq_soc_data, }, + { .compatible = "fsl,imx8mm-soc", .data = &imx8mm_soc_data, }, + { .compatible = "fsl,imx8mn-soc", .data = &imx8mn_soc_data, }, + { .compatible = "fsl,imx8mp-soc", .data = &imx8mp_soc_data, }, + { } +}; + #define imx8_revision(soc_rev) \ soc_rev ? \ kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \ "unknown" -static int __init imx8_soc_init(void) +static int imx8_soc_info(struct platform_device *pdev) { struct soc_device_attribute *soc_dev_attr; struct soc_device *soc_dev; @@ -182,7 +211,10 @@ static int __init imx8_soc_init(void) if (ret) goto free_soc; - id = of_match_node(imx8_soc_match, of_root); + if (pdev) + id = of_match_node(imx8_soc_match, pdev->dev.of_node); + else + id = of_match_node(imx8_machine_match, of_root); if (!id) { ret = -ENODEV; goto free_soc; @@ -191,8 +223,16 @@ static int __init imx8_soc_init(void) data = id->data; if (data) { soc_dev_attr->soc_id = data->name; - if (data->soc_revision) - soc_rev = data->soc_revision(); + if (data->soc_revision) { + if (pdev) { + soc_rev = data->soc_revision(&pdev->dev); + ret = soc_rev; + if (ret < 0) + goto free_soc; + } else { + soc_rev = data->soc_revision(NULL); + } + } } soc_dev_attr->revision = imx8_revision(soc_rev); @@ -230,4 +270,24 @@ free_soc: kfree(soc_dev_attr); return ret; } + +/* Retain device_initcall is for backward compatibility with DTS. */ +static int __init imx8_soc_init(void) +{ + if (of_find_matching_node_and_match(NULL, imx8_soc_match, NULL)) + return 0; + + return imx8_soc_info(NULL); +} device_initcall(imx8_soc_init); + +static struct platform_driver imx8_soc_info_driver = { + .probe = imx8_soc_info, + .driver = { + .name = "imx8_soc_info", + .of_match_table = imx8_soc_match, + }, +}; + +module_platform_driver(imx8_soc_info_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/mediatek/mt8167-pm-domains.h b/drivers/soc/mediatek/mt8167-pm-domains.h new file mode 100644 index 000000000000..ad0b8dfa0527 --- /dev/null +++ b/drivers/soc/mediatek/mt8167-pm-domains.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_MT8167_PM_DOMAINS_H +#define __SOC_MEDIATEK_MT8167_PM_DOMAINS_H + +#include "mtk-pm-domains.h" +#include <dt-bindings/power/mt8167-power.h> + +#define MT8167_PWR_STATUS_MFG_2D BIT(24) +#define MT8167_PWR_STATUS_MFG_ASYNC BIT(25) + +/* + * MT8167 power domain support + */ + +static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { + [MT8167_POWER_DOMAIN_MM] = { + .sta_mask = PWR_STATUS_DISP, + .ctl_offs = SPM_DIS_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(12, 12), + .bp_infracfg = { + BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MM_EMI | + MT8167_TOP_AXI_PROT_EN_MCU_MM), + }, + .caps = MTK_SCPD_ACTIVE_WAKEUP, + }, + [MT8167_POWER_DOMAIN_VDEC] = { + .sta_mask = PWR_STATUS_VDEC, + .ctl_offs = SPM_VDE_PWR_CON, + .sram_pdn_bits = GENMASK(8, 8), + .sram_pdn_ack_bits = GENMASK(12, 12), + .caps = MTK_SCPD_ACTIVE_WAKEUP, + }, + [MT8167_POWER_DOMAIN_ISP] = { + .sta_mask = PWR_STATUS_ISP, + .ctl_offs = SPM_ISP_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(13, 12), + .caps = MTK_SCPD_ACTIVE_WAKEUP, + }, + [MT8167_POWER_DOMAIN_MFG_ASYNC] = { + .sta_mask = MT8167_PWR_STATUS_MFG_ASYNC, + .ctl_offs = SPM_MFG_ASYNC_PWR_CON, + .sram_pdn_bits = 0, + .sram_pdn_ack_bits = 0, + .bp_infracfg = { + BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MCU_MFG | + MT8167_TOP_AXI_PROT_EN_MFG_EMI), + }, + }, + [MT8167_POWER_DOMAIN_MFG_2D] = { + .sta_mask = MT8167_PWR_STATUS_MFG_2D, + .ctl_offs = SPM_MFG_2D_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + }, + [MT8167_POWER_DOMAIN_MFG] = { + .sta_mask = PWR_STATUS_MFG, + .ctl_offs = SPM_MFG_PWR_CON, + .sram_pdn_bits = GENMASK(11, 8), + .sram_pdn_ack_bits = GENMASK(15, 12), + }, + [MT8167_POWER_DOMAIN_CONN] = { + .sta_mask = PWR_STATUS_CONN, + .ctl_offs = SPM_CONN_PWR_CON, + .sram_pdn_bits = GENMASK(8, 8), + .sram_pdn_ack_bits = 0, + .caps = MTK_SCPD_ACTIVE_WAKEUP, + .bp_infracfg = { + BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_CONN_EMI | + MT8167_TOP_AXI_PROT_EN_CONN_MCU | + MT8167_TOP_AXI_PROT_EN_MCU_CONN), + }, + }, +}; + +static const struct scpsys_soc_data mt8167_scpsys_data = { + .domains_data = scpsys_domain_data_mt8167, + .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167), + .pwr_sta_offs = SPM_PWR_STATUS, + .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND, +}; + +#endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */ + diff --git a/drivers/soc/mediatek/mt8183-pm-domains.h b/drivers/soc/mediatek/mt8183-pm-domains.h index 8d996c5d2682..aa5230e6c12f 100644 --- a/drivers/soc/mediatek/mt8183-pm-domains.h +++ b/drivers/soc/mediatek/mt8183-pm-domains.h @@ -38,6 +38,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { .ctl_offs = 0x0338, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), + .caps = MTK_SCPD_DOMAIN_SUPPLY, }, [MT8183_POWER_DOMAIN_MFG_CORE0] = { .sta_mask = BIT(7), diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 280d3bd9f675..3c8e4212d941 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -463,36 +463,4 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, } EXPORT_SYMBOL(cmdq_pkt_flush_async); -struct cmdq_flush_completion { - struct completion cmplt; - bool err; -}; - -static void cmdq_pkt_flush_cb(struct cmdq_cb_data data) -{ - struct cmdq_flush_completion *cmplt; - - cmplt = (struct cmdq_flush_completion *)data.data; - if (data.sta != CMDQ_CB_NORMAL) - cmplt->err = true; - else - cmplt->err = false; - complete(&cmplt->cmplt); -} - -int cmdq_pkt_flush(struct cmdq_pkt *pkt) -{ - struct cmdq_flush_completion cmplt; - int err; - - init_completion(&cmplt.cmplt); - err = cmdq_pkt_flush_async(pkt, cmdq_pkt_flush_cb, &cmplt); - if (err < 0) - return err; - wait_for_completion(&cmplt.cmplt); - - return cmplt.err ? -EFAULT : 0; -} -EXPORT_SYMBOL(cmdq_pkt_flush); - MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c index fb70cb3b07b3..b7f697666bdd 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.c +++ b/drivers/soc/mediatek/mtk-pm-domains.c @@ -13,8 +13,10 @@ #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/regmap.h> +#include <linux/regulator/consumer.h> #include <linux/soc/mediatek/infracfg.h> +#include "mt8167-pm-domains.h" #include "mt8173-pm-domains.h" #include "mt8183-pm-domains.h" #include "mt8192-pm-domains.h" @@ -40,6 +42,7 @@ struct scpsys_domain { struct clk_bulk_data *subsys_clks; struct regmap *infracfg; struct regmap *smi; + struct regulator *supply; }; struct scpsys { @@ -187,6 +190,16 @@ static int scpsys_bus_protect_disable(struct scpsys_domain *pd) return _scpsys_bus_protect_disable(pd->data->bp_infracfg, pd->infracfg); } +static int scpsys_regulator_enable(struct regulator *supply) +{ + return supply ? regulator_enable(supply) : 0; +} + +static int scpsys_regulator_disable(struct regulator *supply) +{ + return supply ? regulator_disable(supply) : 0; +} + static int scpsys_power_on(struct generic_pm_domain *genpd) { struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd); @@ -194,10 +207,14 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) bool tmp; int ret; - ret = clk_bulk_enable(pd->num_clks, pd->clks); + ret = scpsys_regulator_enable(pd->supply); if (ret) return ret; + ret = clk_bulk_enable(pd->num_clks, pd->clks); + if (ret) + goto err_reg; + /* subsys power on */ regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); @@ -232,6 +249,8 @@ err_disable_subsys_clks: clk_bulk_disable(pd->num_subsys_clks, pd->subsys_clks); err_pwr_ack: clk_bulk_disable(pd->num_clks, pd->clks); +err_reg: + scpsys_regulator_disable(pd->supply); return ret; } @@ -267,6 +286,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) clk_bulk_disable(pd->num_clks, pd->clks); + scpsys_regulator_disable(pd->supply); + return 0; } @@ -275,6 +296,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no { const struct scpsys_domain_data *domain_data; struct scpsys_domain *pd; + struct device_node *root_node = scpsys->dev->of_node; struct property *prop; const char *clk_name; int i, ret, num_clks; @@ -307,6 +329,25 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no pd->data = domain_data; pd->scpsys = scpsys; + if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) { + /* + * Find regulator in current power domain node. + * devm_regulator_get() finds regulator in a node and its child + * node, so set of_node to current power domain node then change + * back to original node after regulator is found for current + * power domain node. + */ + scpsys->dev->of_node = node; + pd->supply = devm_regulator_get(scpsys->dev, "domain"); + scpsys->dev->of_node = root_node; + if (IS_ERR(pd->supply)) { + dev_err_probe(scpsys->dev, PTR_ERR(pd->supply), + "%pOF: failed to get power supply.\n", + node); + return ERR_CAST(pd->supply); + } + } + pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg"); if (IS_ERR(pd->infracfg)) return ERR_CAST(pd->infracfg); @@ -446,8 +487,8 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren child_pd = scpsys_add_one_domain(scpsys, child); if (IS_ERR(child_pd)) { - ret = PTR_ERR(child_pd); - dev_err(scpsys->dev, "%pOF: failed to get child domain id\n", child); + dev_err_probe(scpsys->dev, PTR_ERR(child_pd), + "%pOF: failed to get child domain id\n", child); goto err_put_node; } @@ -515,6 +556,10 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys) static const struct of_device_id scpsys_of_match[] = { { + .compatible = "mediatek,mt8167-power-controller", + .data = &mt8167_scpsys_data, + }, + { .compatible = "mediatek,mt8173-power-controller", .data = &mt8173_scpsys_data, }, diff --git a/drivers/soc/mediatek/mtk-pm-domains.h b/drivers/soc/mediatek/mtk-pm-domains.h index a2f4d8f97e05..141dc76054e6 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.h +++ b/drivers/soc/mediatek/mtk-pm-domains.h @@ -7,6 +7,7 @@ #define MTK_SCPD_FWAIT_SRAM BIT(1) #define MTK_SCPD_SRAM_ISO BIT(2) #define MTK_SCPD_KEEP_DEFAULT_OFF BIT(3) +#define MTK_SCPD_DOMAIN_SUPPLY BIT(4) #define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x)) #define SPM_VDE_PWR_CON 0x0210 @@ -14,6 +15,7 @@ #define SPM_VEN_PWR_CON 0x0230 #define SPM_ISP_PWR_CON 0x0238 #define SPM_DIS_PWR_CON 0x023c +#define SPM_CONN_PWR_CON 0x0280 #define SPM_VEN2_PWR_CON 0x0298 #define SPM_AUDIO_PWR_CON 0x029c #define SPM_MFG_2D_PWR_CON 0x02c0 diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 16b421608e9c..8403a77b59fe 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -4,6 +4,7 @@ * */ +#include <linux/bitfield.h> #include <linux/bitmap.h> #include <linux/bitops.h> #include <linux/device.h> @@ -35,6 +36,9 @@ #define CACHE_LINE_SIZE_SHIFT 6 +#define LLCC_COMMON_HW_INFO 0x00030000 +#define LLCC_MAJOR_VERSION_MASK GENMASK(31, 24) + #define LLCC_COMMON_STATUS0 0x0003000c #define LLCC_LB_CNT_MASK GENMASK(31, 28) #define LLCC_LB_CNT_SHIFT 28 @@ -47,6 +51,7 @@ #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 #define LLCC_TRP_PCB_ACT 0x21f04 +#define LLCC_TRP_WRSC_EN 0x21f20 #define BANK_OFFSET_STRIDE 0x80000 @@ -73,6 +78,7 @@ * then the ways assigned to this client are not flushed on power * collapse. * @activate_on_init: Activate the slice immediately after it is programmed + * @write_scid_en: Bit enables write cache support for a given scid. */ struct llcc_slice_config { u32 usecase_id; @@ -87,6 +93,7 @@ struct llcc_slice_config { bool dis_cap_alloc; bool retain_on_pc; bool activate_on_init; + bool write_scid_en; }; struct qcom_llcc_config { @@ -147,6 +154,25 @@ static const struct llcc_slice_config sm8150_data[] = { { LLCC_WRCACHE, 31, 128, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0 }, }; +static const struct llcc_slice_config sm8250_data[] = { + { LLCC_CPUSS, 1, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 }, + { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_AUDIO, 6, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, + { LLCC_CMPT, 10, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 }, + { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_GPU, 12, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 }, + { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, + { LLCC_CMPTDMA, 15, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_DISP, 16, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_VIDFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_NPU, 23, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_WLHW, 24, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_CVP, 28, 256, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 }, + { LLCC_APTCM, 30, 128, 3, 0, 0x0, 0x3, 1, 0, 0, 1, 0, 0 }, + { LLCC_WRCACHE, 31, 256, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 }, +}; + static const struct qcom_llcc_config sc7180_cfg = { .sct_data = sc7180_data, .size = ARRAY_SIZE(sc7180_data), @@ -164,6 +190,11 @@ static const struct qcom_llcc_config sm8150_cfg = { .size = ARRAY_SIZE(sm8150_data), }; +static const struct qcom_llcc_config sm8250_cfg = { + .sct_data = sm8250_data, + .size = ARRAY_SIZE(sm8250_data), +}; + static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; /** @@ -413,6 +444,16 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, return ret; } + if (drv_data->major_version == 2) { + u32 wren; + + wren = config->write_scid_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_WRSC_EN, + BIT(config->slice_id), wren); + if (ret) + return ret; + } + if (config->activate_on_init) { desc.slice_id = config->slice_id; ret = llcc_slice_activate(&desc); @@ -476,6 +517,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) const struct qcom_llcc_config *cfg; const struct llcc_slice_config *llcc_cfg; u32 sz; + u32 version; drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); if (!drv_data) { @@ -496,6 +538,13 @@ static int qcom_llcc_probe(struct platform_device *pdev) goto err; } + /* Extract major version of the IP */ + ret = regmap_read(drv_data->bcast_regmap, LLCC_COMMON_HW_INFO, &version); + if (ret) + goto err; + + drv_data->major_version = FIELD_GET(LLCC_MAJOR_VERSION_MASK, version); + ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, &num_banks); if (ret) @@ -559,6 +608,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfg }, { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg }, { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg }, + { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg }, { } }; diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 7f9e9944d1ea..f1875dc31ae2 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -189,6 +189,7 @@ struct ocmem *of_get_ocmem(struct device *dev) { struct platform_device *pdev; struct device_node *devnode; + struct ocmem *ocmem; devnode = of_parse_phandle(dev->of_node, "sram", 0); if (!devnode || !devnode->parent) { @@ -202,7 +203,12 @@ struct ocmem *of_get_ocmem(struct device *dev) return ERR_PTR(-EPROBE_DEFER); } - return platform_get_drvdata(pdev); + ocmem = platform_get_drvdata(pdev); + if (!ocmem) { + dev_err(dev, "Cannot get ocmem\n"); + return ERR_PTR(-ENODEV); + } + return ocmem; } EXPORT_SYMBOL(of_get_ocmem); diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index b5840d624bc6..53acb9423bd6 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -600,6 +600,7 @@ static const struct of_device_id qmp_dt_match[] = { { .compatible = "qcom,sdm845-aoss-qmp", }, { .compatible = "qcom,sm8150-aoss-qmp", }, { .compatible = "qcom,sm8250-aoss-qmp", }, + { .compatible = "qcom,sm8350-aoss-qmp", }, {} }; MODULE_DEVICE_TABLE(of, qmp_dt_match); diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index 37969dcbaf14..a84ab0d6a9d4 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -231,10 +231,9 @@ static void tcs_invalidate(struct rsc_drv *drv, int type) if (bitmap_empty(tcs->slots, MAX_TCS_SLOTS)) return; - for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) { + for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0); - write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, m, 0); - } + bitmap_zero(tcs->slots, MAX_TCS_SLOTS); } @@ -364,7 +363,7 @@ static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger) enable = TCS_AMC_MODE_ENABLE; write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); enable |= TCS_AMC_MODE_TRIGGER; - write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, enable); } } @@ -443,7 +442,6 @@ static irqreturn_t tcs_tx_done(int irq, void *p) skip: /* Reclaim the TCS */ write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0); - write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, i, 0); writel_relaxed(BIT(i), drv->tcs_base + RSC_DRV_IRQ_CLEAR); spin_lock(&drv->lock); clear_bit(i, drv->tcs_in_use); @@ -476,23 +474,23 @@ skip: static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, const struct tcs_request *msg) { - u32 msgid, cmd_msgid; + u32 msgid; + u32 cmd_msgid = CMD_MSGID_LEN | CMD_MSGID_WRITE; u32 cmd_enable = 0; - u32 cmd_complete; struct tcs_cmd *cmd; int i, j; - cmd_msgid = CMD_MSGID_LEN; + /* Convert all commands to RR when the request has wait_for_compl set */ cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0; - cmd_msgid |= CMD_MSGID_WRITE; - - cmd_complete = read_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id); for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) { cmd = &msg->cmds[i]; cmd_enable |= BIT(j); - cmd_complete |= cmd->wait << j; msgid = cmd_msgid; + /* + * Additionally, if the cmd->wait is set, make the command + * response reqd even if the overall request was fire-n-forget. + */ msgid |= cmd->wait ? CMD_MSGID_RESP_REQ : 0; write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid); @@ -501,7 +499,6 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd); } - write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, cmd_complete); cmd_enable |= read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id); write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, cmd_enable); } @@ -652,7 +649,6 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) * cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate() */ write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0); - write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, 0); enable_tcs_irq(drv, tcs_id, true); } spin_unlock_irqrestore(&drv->lock, flags); diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 85d1207b72d7..27733b0e7fca 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -21,6 +21,8 @@ * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */ #define RPMPD_SMPA 0x61706d73 #define RPMPD_LDOA 0x616f646c +#define RPMPD_SMPB 0x62706d73 +#define RPMPD_LDOB 0x626f646c #define RPMPD_RWCX 0x78637772 #define RPMPD_RWMX 0x786d7772 #define RPMPD_RWLC 0x636c7772 @@ -184,6 +186,31 @@ static const struct rpmpd_desc msm8976_desc = { .max_state = RPM_SMD_LEVEL_TURBO_HIGH, }; +/* msm8994 RPM Power domains */ +DEFINE_RPMPD_PAIR(msm8994, vddcx, vddcx_ao, SMPA, CORNER, 1); +DEFINE_RPMPD_PAIR(msm8994, vddmx, vddmx_ao, SMPA, CORNER, 2); +/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */ +DEFINE_RPMPD_CORNER(msm8994, vddgfx, SMPB, 2); + +DEFINE_RPMPD_VFC(msm8994, vddcx_vfc, SMPA, 1); +DEFINE_RPMPD_VFC(msm8994, vddgfx_vfc, SMPB, 2); + +static struct rpmpd *msm8994_rpmpds[] = { + [MSM8994_VDDCX] = &msm8994_vddcx, + [MSM8994_VDDCX_AO] = &msm8994_vddcx_ao, + [MSM8994_VDDCX_VFC] = &msm8994_vddcx_vfc, + [MSM8994_VDDMX] = &msm8994_vddmx, + [MSM8994_VDDMX_AO] = &msm8994_vddmx_ao, + [MSM8994_VDDGFX] = &msm8994_vddgfx, + [MSM8994_VDDGFX_VFC] = &msm8994_vddgfx_vfc, +}; + +static const struct rpmpd_desc msm8994_desc = { + .rpmpds = msm8994_rpmpds, + .num_pds = ARRAY_SIZE(msm8994_rpmpds), + .max_state = MAX_CORNER_RPMPD_STATE, +}; + /* msm8996 RPM Power domains */ DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1); DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2); @@ -302,6 +329,7 @@ static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc }, { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc }, + { .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc }, { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc }, { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc }, { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 7251827bac88..cc4e0655a47b 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -732,9 +732,7 @@ qcom_smem_partition_header(struct qcom_smem *smem, header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { - dev_err(smem->dev, "bad partition magic %02x %02x %02x %02x\n", - header->magic[0], header->magic[1], - header->magic[2], header->magic[3]); + dev_err(smem->dev, "bad partition magic %4ph\n", header->magic); return NULL; } diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index d21530d24253..f6cfb79338f0 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -15,6 +15,8 @@ #include <linux/sys_soc.h> #include <linux/types.h> +#include <asm/unaligned.h> + /* * SoC version type with major number in the upper 16 bits and minor * number in the lower 16 bits. @@ -83,6 +85,11 @@ static const char *const pmic_models[] = { [23] = "PM8038", [24] = "PM8922", [25] = "PM8917", + [30] = "PM8150", + [31] = "PM8150L", + [32] = "PM8150B", + [33] = "PMK8002", + [36] = "PM8009", }; #endif /* CONFIG_DEBUG_FS */ @@ -217,23 +224,39 @@ static const struct soc_id soc_id[] = { { 250, "MSM8616" }, { 251, "MSM8992" }, { 253, "APQ8094" }, + { 290, "MDM9607" }, { 291, "APQ8096" }, + { 292, "MSM8998" }, { 293, "MSM8953" }, + { 296, "MDM8207" }, + { 297, "MDM9207" }, + { 298, "MDM9307" }, + { 299, "MDM9628" }, { 304, "APQ8053" }, { 305, "MSM8996SG" }, { 310, "MSM8996AU" }, { 311, "APQ8096AU" }, { 312, "APQ8096SG" }, + { 317, "SDM660" }, { 318, "SDM630" }, + { 319, "APQ8098" }, { 321, "SDM845" }, + { 322, "MDM9206" }, + { 324, "SDA660" }, + { 325, "SDM658" }, + { 326, "SDA658" }, + { 327, "SDA630" }, { 338, "SDM450" }, { 341, "SDA845" }, + { 345, "SDM636" }, + { 346, "SDA636" }, { 349, "SDM632" }, { 350, "SDA632" }, { 351, "SDA450" }, { 356, "SM8250" }, { 402, "IPQ6018" }, { 425, "SC7180" }, + { 455, "QRB5165" }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) @@ -264,7 +287,7 @@ static const struct file_operations qcom_ ##name## _ops = { \ } #define DEBUGFS_ADD(info, name) \ - debugfs_create_file(__stringify(name), 0400, \ + debugfs_create_file(__stringify(name), 0444, \ qcom_socinfo->dbg_root, \ info, &qcom_ ##name## _ops) @@ -286,7 +309,7 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p) if (model < 0) return -EINVAL; - if (model <= ARRAY_SIZE(pmic_models) && pmic_models[model]) + if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) seq_printf(seq, "%s\n", pmic_models[model]); else seq_printf(seq, "unknown (%d)\n", model); @@ -294,6 +317,32 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p) return 0; } +static int qcom_show_pmic_model_array(struct seq_file *seq, void *p) +{ + struct socinfo *socinfo = seq->private; + unsigned int num_pmics = le32_to_cpu(socinfo->num_pmics); + unsigned int pmic_array_offset = le32_to_cpu(socinfo->pmic_array_offset); + int i; + void *ptr = socinfo; + + ptr += pmic_array_offset; + + /* No need for bounds checking, it happened at socinfo_debugfs_init */ + for (i = 0; i < num_pmics; i++) { + unsigned int model = SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * sizeof(u32))); + unsigned int die_rev = get_unaligned_le32(ptr + (2 * i + 1) * sizeof(u32)); + + if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) + seq_printf(seq, "%s %u.%u\n", pmic_models[model], + SOCINFO_MAJOR(die_rev), + SOCINFO_MINOR(die_rev)); + else + seq_printf(seq, "unknown (%d)\n", model); + } + + return 0; +} + static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p) { struct socinfo *socinfo = seq->private; @@ -316,6 +365,7 @@ static int qcom_show_chip_id(struct seq_file *seq, void *p) QCOM_OPEN(build_id, qcom_show_build_id); QCOM_OPEN(pmic_model, qcom_show_pmic_model); +QCOM_OPEN(pmic_model_array, qcom_show_pmic_model_array); QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision); QCOM_OPEN(chip_id, qcom_show_chip_id); @@ -344,25 +394,27 @@ DEFINE_IMAGE_OPS(variant); DEFINE_IMAGE_OPS(oem); static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, - struct socinfo *info) + struct socinfo *info, size_t info_size) { struct smem_image_version *versions; struct dentry *dentry; size_t size; int i; + unsigned int num_pmics; + unsigned int pmic_array_offset; qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL); qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt); - debugfs_create_x32("info_fmt", 0400, qcom_socinfo->dbg_root, + debugfs_create_x32("info_fmt", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.fmt); switch (qcom_socinfo->info.fmt) { case SOCINFO_VERSION(0, 15): qcom_socinfo->info.nmodem_supported = __le32_to_cpu(info->nmodem_supported); - debugfs_create_u32("nmodem_supported", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("nmodem_supported", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.nmodem_supported); fallthrough; case SOCINFO_VERSION(0, 14): @@ -371,19 +423,19 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.num_defective_parts = __le32_to_cpu(info->num_defective_parts); qcom_socinfo->info.ndefective_parts_array_offset = __le32_to_cpu(info->ndefective_parts_array_offset); - debugfs_create_u32("num_clusters", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.num_clusters); - debugfs_create_u32("ncluster_array_offset", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.ncluster_array_offset); - debugfs_create_u32("num_defective_parts", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.num_defective_parts); - debugfs_create_u32("ndefective_parts_array_offset", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.ndefective_parts_array_offset); fallthrough; case SOCINFO_VERSION(0, 13): qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id); - debugfs_create_u32("nproduct_id", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("nproduct_id", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.nproduct_id); DEBUGFS_ADD(info, chip_id); fallthrough; @@ -395,21 +447,26 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.raw_device_num = __le32_to_cpu(info->raw_device_num); - debugfs_create_x32("chip_family", 0400, qcom_socinfo->dbg_root, + debugfs_create_x32("chip_family", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.chip_family); - debugfs_create_x32("raw_device_family", 0400, + debugfs_create_x32("raw_device_family", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_device_family); - debugfs_create_x32("raw_device_number", 0400, + debugfs_create_x32("raw_device_number", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_device_num); fallthrough; case SOCINFO_VERSION(0, 11): + num_pmics = le32_to_cpu(info->num_pmics); + pmic_array_offset = le32_to_cpu(info->pmic_array_offset); + if (pmic_array_offset + 2 * num_pmics * sizeof(u32) <= info_size) + DEBUGFS_ADD(info, pmic_model_array); + fallthrough; case SOCINFO_VERSION(0, 10): case SOCINFO_VERSION(0, 9): qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id); - debugfs_create_u32("foundry_id", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("foundry_id", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.foundry_id); fallthrough; case SOCINFO_VERSION(0, 8): @@ -421,7 +478,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.hw_plat_subtype = __le32_to_cpu(info->hw_plat_subtype); - debugfs_create_u32("hardware_platform_subtype", 0400, + debugfs_create_u32("hardware_platform_subtype", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.hw_plat_subtype); fallthrough; @@ -429,28 +486,28 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, qcom_socinfo->info.accessory_chip = __le32_to_cpu(info->accessory_chip); - debugfs_create_u32("accessory_chip", 0400, + debugfs_create_u32("accessory_chip", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.accessory_chip); fallthrough; case SOCINFO_VERSION(0, 4): qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver); - debugfs_create_u32("platform_version", 0400, + debugfs_create_u32("platform_version", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.plat_ver); fallthrough; case SOCINFO_VERSION(0, 3): qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat); - debugfs_create_u32("hardware_platform", 0400, + debugfs_create_u32("hardware_platform", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.hw_plat); fallthrough; case SOCINFO_VERSION(0, 2): qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver); - debugfs_create_u32("raw_version", 0400, qcom_socinfo->dbg_root, + debugfs_create_u32("raw_version", 0444, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_ver); fallthrough; case SOCINFO_VERSION(0, 1): @@ -467,11 +524,11 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, dentry = debugfs_create_dir(socinfo_image_names[i], qcom_socinfo->dbg_root); - debugfs_create_file("name", 0400, dentry, &versions[i], + debugfs_create_file("name", 0444, dentry, &versions[i], &qcom_image_name_ops); - debugfs_create_file("variant", 0400, dentry, &versions[i], + debugfs_create_file("variant", 0444, dentry, &versions[i], &qcom_image_variant_ops); - debugfs_create_file("oem", 0400, dentry, &versions[i], + debugfs_create_file("oem", 0444, dentry, &versions[i], &qcom_image_oem_ops); } } @@ -482,7 +539,7 @@ static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) } #else static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, - struct socinfo *info) + struct socinfo *info, size_t info_size) { } static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { } @@ -522,7 +579,7 @@ static int qcom_socinfo_probe(struct platform_device *pdev) if (IS_ERR(qs->soc_dev)) return PTR_ERR(qs->soc_dev); - socinfo_debugfs_init(qs, info); + socinfo_debugfs_init(qs, info, item_size); /* Feed the soc specific unique data into entropy pool */ add_device_randomness(info, item_size); diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index d4c7bd59429e..42833e33a96c 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -283,7 +283,7 @@ int sunxi_sram_release(struct device *dev) EXPORT_SYMBOL(sunxi_sram_release); struct sunxi_sramc_variant { - bool has_emac_clock; + int num_emac_clocks; }; static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { @@ -291,20 +291,31 @@ static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { }; static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = { - .has_emac_clock = true, + .num_emac_clocks = 1, }; static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = { - .has_emac_clock = true, + .num_emac_clocks = 1, +}; + +static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { + .num_emac_clocks = 2, }; #define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 static bool sunxi_sram_regmap_accessible_reg(struct device *dev, unsigned int reg) { - if (reg == SUNXI_SRAM_EMAC_CLOCK_REG) - return true; - return false; + const struct sunxi_sramc_variant *variant; + + variant = of_device_get_match_data(dev); + + if (reg < SUNXI_SRAM_EMAC_CLOCK_REG) + return false; + if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) + return false; + + return true; } static struct regmap_config sunxi_sram_emac_clock_regmap = { @@ -312,7 +323,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { .val_bits = 32, .reg_stride = 4, /* last defined register */ - .max_register = SUNXI_SRAM_EMAC_CLOCK_REG, + .max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4, /* other devices have no business accessing other registers */ .readable_reg = sunxi_sram_regmap_accessible_reg, .writeable_reg = sunxi_sram_regmap_accessible_reg, @@ -343,7 +354,7 @@ static int sunxi_sram_probe(struct platform_device *pdev) if (!d) return -ENOMEM; - if (variant->has_emac_clock) { + if (variant->num_emac_clocks > 0) { emac_clock = devm_regmap_init_mmio(&pdev->dev, base, &sunxi_sram_emac_clock_regmap); @@ -387,6 +398,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = { .compatible = "allwinner,sun50i-h5-system-control", .data = &sun50i_a64_sramc_variant, }, + { + .compatible = "allwinner,sun50i-h616-system-control", + .data = &sun50i_h616_sramc_variant, + }, { }, }; MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match); diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c index b495b0d5d0fa..312ba0f98ad7 100644 --- a/drivers/soc/ti/k3-ringacc.c +++ b/drivers/soc/ti/k3-ringacc.c @@ -9,6 +9,7 @@ #include <linux/io.h> #include <linux/init.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/sys_soc.h> #include <linux/dma/ti-cppi5.h> @@ -1517,15 +1518,13 @@ EXPORT_SYMBOL_GPL(k3_ringacc_dmarings_init); static int k3_ringacc_probe(struct platform_device *pdev) { const struct ringacc_match_data *match_data; - const struct of_device_id *match; struct device *dev = &pdev->dev; struct k3_ringacc *ringacc; int ret; - match = of_match_node(k3_ringacc_of_match, dev->of_node); - if (!match) + match_data = of_device_get_match_data(&pdev->dev); + if (!match_data) return -ENODEV; - match_data = match->data; ringacc = devm_kzalloc(dev, sizeof(*ringacc), GFP_KERNEL); if (!ringacc) diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index 7b5cb5d48f7d..591d14ebcb11 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -758,6 +758,7 @@ static int knav_dma_probe(struct platform_device *pdev) for_each_child_of_node(node, child) { ret = dma_init(node, child); if (ret) { + of_node_put(child); dev_err(&pdev->dev, "init failed with %d\n", ret); break; } diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 2e521f1eda96..2ac3856b8d42 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -1087,6 +1087,7 @@ static int knav_queue_setup_regions(struct knav_device *kdev, for_each_child_of_node(regions, child) { region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); if (!region) { + of_node_put(child); dev_err(dev, "out of memory allocating region\n"); return -ENOMEM; } @@ -1399,6 +1400,7 @@ static int knav_queue_init_qmgrs(struct knav_device *kdev, for_each_child_of_node(qmgrs, child) { qmgr = devm_kzalloc(dev, sizeof(*qmgr), GFP_KERNEL); if (!qmgr) { + of_node_put(child); dev_err(dev, "out of memory allocating qmgr\n"); return -ENOMEM; } @@ -1498,6 +1500,7 @@ static int knav_queue_init_pdsps(struct knav_device *kdev, for_each_child_of_node(pdsps, child) { pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL); if (!pdsp) { + of_node_put(child); dev_err(dev, "out of memory allocating pdsp\n"); return -ENOMEM; } diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c index 64f3e3105540..7bab4bbaf02d 100644 --- a/drivers/soc/ti/pm33xx.c +++ b/drivers/soc/ti/pm33xx.c @@ -535,7 +535,7 @@ static int am33xx_pm_probe(struct platform_device *pdev) ret = am33xx_push_sram_idle(); if (ret) - goto err_free_sram; + goto err_unsetup_rtc; am33xx_pm_set_ipc_ops(); @@ -575,6 +575,9 @@ err_pm_runtime_put: err_pm_runtime_disable: pm_runtime_disable(dev); wkup_m3_ipc_put(m3_ipc); +err_unsetup_rtc: + iounmap(rtc_base_virt); + clk_put(rtc_fck); err_free_sram: am33xx_pm_free_sram(); pm33xx_dev = NULL; diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 5d6e7132a5c4..f22ac1edbdd0 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -161,6 +161,53 @@ static struct regmap_config regmap_conf = { .reg_stride = 4, }; +static int pruss_cfg_of_init(struct device *dev, struct pruss *pruss) +{ + struct device_node *np = dev_of_node(dev); + struct device_node *child; + struct resource res; + int ret; + + child = of_get_child_by_name(np, "cfg"); + if (!child) { + dev_err(dev, "%pOF is missing its 'cfg' node\n", child); + return -ENODEV; + } + + if (of_address_to_resource(child, 0, &res)) { + ret = -ENOMEM; + goto node_put; + } + + pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res)); + if (!pruss->cfg_base) { + ret = -ENOMEM; + goto node_put; + } + + regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child, + (u64)res.start); + regmap_conf.max_register = resource_size(&res) - 4; + + pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base, + ®map_conf); + kfree(regmap_conf.name); + if (IS_ERR(pruss->cfg_regmap)) { + dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n", + PTR_ERR(pruss->cfg_regmap)); + ret = PTR_ERR(pruss->cfg_regmap); + goto node_put; + } + + ret = pruss_clk_init(pruss, child); + if (ret) + dev_err(dev, "pruss_clk_init failed, ret = %d\n", ret); + +node_put: + of_node_put(child); + return ret; +} + static int pruss_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -239,56 +286,18 @@ static int pruss_probe(struct platform_device *pdev) goto rpm_disable; } - child = of_get_child_by_name(np, "cfg"); - if (!child) { - dev_err(dev, "%pOF is missing its 'cfg' node\n", child); - ret = -ENODEV; + ret = pruss_cfg_of_init(dev, pruss); + if (ret < 0) goto rpm_put; - } - - if (of_address_to_resource(child, 0, &res)) { - ret = -ENOMEM; - goto node_put; - } - - pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res)); - if (!pruss->cfg_base) { - ret = -ENOMEM; - goto node_put; - } - - regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child, - (u64)res.start); - regmap_conf.max_register = resource_size(&res) - 4; - - pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base, - ®map_conf); - kfree(regmap_conf.name); - if (IS_ERR(pruss->cfg_regmap)) { - dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n", - PTR_ERR(pruss->cfg_regmap)); - ret = PTR_ERR(pruss->cfg_regmap); - goto node_put; - } - - ret = pruss_clk_init(pruss, child); - if (ret) { - dev_err(dev, "failed to setup coreclk-mux\n"); - goto node_put; - } ret = devm_of_platform_populate(dev); if (ret) { dev_err(dev, "failed to register child devices\n"); - goto node_put; + goto rpm_put; } - of_node_put(child); - return 0; -node_put: - of_node_put(child); rpm_put: pm_runtime_put_sync(dev); rpm_disable: |