From 1f3753a5f042fea6539986f9caf2552877527d8a Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 15:17:15 +0800 Subject: [PATCH 001/179] soc: sunxi_sram: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210908071716.772-1-caihuoqing@baidu.com --- drivers/soc/sunxi/sunxi_sram.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 42833e33a96c..a8f3876963a0 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -331,7 +331,6 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { static int sunxi_sram_probe(struct platform_device *pdev) { - struct resource *res; struct dentry *d; struct regmap *emac_clock; const struct sunxi_sramc_variant *variant; @@ -342,8 +341,7 @@ static int sunxi_sram_probe(struct platform_device *pdev) if (!variant) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); From ca8d1fda5b7d2f81ba9c5649462a7c0b64ae9dcd Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Fri, 20 Aug 2021 01:27:18 +0000 Subject: [PATCH 002/179] soc: amlogic: meson-gx-socinfo: Add S905Y2 ID for Radxa Zero Add the SOC ID for the S905Y2 used in the Radxa Zero. Before/After: [ 0.321650] soc soc0: Amlogic Meson G12A (Unknown) Revision 28:b (30:2) Detected [ 0.318533] soc soc0: Amlogic Meson G12A (S905Y2) Revision 28:b (30:2) Detected Signed-off-by: Christian Hewitt Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20210820012718.10761-1-christianshewitt@gmail.com --- drivers/soc/amlogic/meson-gx-socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c index 6f54bd832c8b..165f7548401b 100644 --- a/drivers/soc/amlogic/meson-gx-socinfo.c +++ b/drivers/soc/amlogic/meson-gx-socinfo.c @@ -65,6 +65,7 @@ static const struct meson_gx_package_id { { "A113X", 0x25, 0x37, 0xff }, { "A113D", 0x25, 0x22, 0xff }, { "S905D2", 0x28, 0x10, 0xf0 }, + { "S905Y2", 0x28, 0x30, 0xf0 }, { "S905X2", 0x28, 0x40, 0xf0 }, { "A311D", 0x29, 0x10, 0xf0 }, { "S922X", 0x29, 0x40, 0xf0 }, From 97a4a24087ce354ce0318449e6bd9e660f5c573b Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 15:15:42 +0800 Subject: [PATCH 003/179] soc: amlogic: canvas: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20210908071544.603-1-caihuoqing@baidu.com --- drivers/soc/amlogic/meson-canvas.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c index d0329ad170d1..383b0cfc584e 100644 --- a/drivers/soc/amlogic/meson-canvas.c +++ b/drivers/soc/amlogic/meson-canvas.c @@ -168,7 +168,6 @@ EXPORT_SYMBOL_GPL(meson_canvas_free); static int meson_canvas_probe(struct platform_device *pdev) { - struct resource *res; struct meson_canvas *canvas; struct device *dev = &pdev->dev; @@ -176,8 +175,7 @@ static int meson_canvas_probe(struct platform_device *pdev) if (!canvas) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - canvas->reg_base = devm_ioremap_resource(dev, res); + canvas->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(canvas->reg_base)) return PTR_ERR(canvas->reg_base); From d54dbe9f0ec05935e10d6a38d81e54e2ec8b8a68 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 15:15:43 +0800 Subject: [PATCH 004/179] soc: amlogic: meson-clk-measure: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20210908071544.603-2-caihuoqing@baidu.com --- drivers/soc/amlogic/meson-clk-measure.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c index 6dd190270123..3f3039600357 100644 --- a/drivers/soc/amlogic/meson-clk-measure.c +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -606,7 +606,6 @@ static int meson_msr_probe(struct platform_device *pdev) { const struct meson_msr_id *match_data; struct meson_msr *priv; - struct resource *res; struct dentry *root, *clks; void __iomem *base; int i; @@ -624,8 +623,7 @@ static int meson_msr_probe(struct platform_device *pdev) memcpy(priv->msr_table, match_data, sizeof(priv->msr_table)); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); From cb19c107979b8000825060cb5b84dfe9212f4f86 Mon Sep 17 00:00:00 2001 From: Yongqiang Niu Date: Mon, 2 Aug 2021 16:59:32 +0800 Subject: [PATCH 005/179] soc: mediatek: mmsys: add comp OVL_2L2/POSTMASK/RDMA4 This patch add some more ddp component OVL_2L2 is ovl which include 2 layers overlay POSTMASK control round corner for display frame RDMA4 read dma buffer Signed-off-by: Yongqiang Niu Reviewed-by: Chun-Kuang Hu Reviewed-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/1627894773-23872-2-git-send-email-yongqiang.niu@mediatek.com Signed-off-by: Matthias Brugger --- include/linux/soc/mediatek/mtk-mmsys.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h index 2228bf6133da..4bba275e235a 100644 --- a/include/linux/soc/mediatek/mtk-mmsys.h +++ b/include/linux/soc/mediatek/mtk-mmsys.h @@ -29,13 +29,16 @@ enum mtk_ddp_comp_id { DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_OVL_2L1, + DDP_COMPONENT_OVL_2L2, DDP_COMPONENT_OVL1, + DDP_COMPONENT_POSTMASK0, DDP_COMPONENT_PWM0, DDP_COMPONENT_PWM1, DDP_COMPONENT_PWM2, DDP_COMPONENT_RDMA0, DDP_COMPONENT_RDMA1, DDP_COMPONENT_RDMA2, + DDP_COMPONENT_RDMA4, DDP_COMPONENT_UFOE, DDP_COMPONENT_WDMA0, DDP_COMPONENT_WDMA1, From d687e056a18f71d06e3cb4b10b01815397e30782 Mon Sep 17 00:00:00 2001 From: Yongqiang Niu Date: Mon, 2 Aug 2021 16:59:33 +0800 Subject: [PATCH 006/179] soc: mediatek: mmsys: Add mt8192 mmsys routing table mt8192 has different routing registers than mt8183 Signed-off-by: Yongqiang Niu Link: https://lore.kernel.org/r/1627894773-23872-3-git-send-email-yongqiang.niu@mediatek.com [mb: take mask into account] Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mt8192-mmsys.h | 76 +++++++++++++++++++++++++++++ drivers/soc/mediatek/mtk-mmsys.c | 11 +++++ 2 files changed, 87 insertions(+) create mode 100644 drivers/soc/mediatek/mt8192-mmsys.h diff --git a/drivers/soc/mediatek/mt8192-mmsys.h b/drivers/soc/mediatek/mt8192-mmsys.h new file mode 100644 index 000000000000..6f0a57044a7b --- /dev/null +++ b/drivers/soc/mediatek/mt8192-mmsys.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_MT8192_MMSYS_H +#define __SOC_MEDIATEK_MT8192_MMSYS_H + +#define MT8192_MMSYS_OVL_MOUT_EN 0xf04 +#define MT8192_DISP_OVL1_2L_MOUT_EN 0xf08 +#define MT8192_DISP_OVL0_2L_MOUT_EN 0xf18 +#define MT8192_DISP_OVL0_MOUT_EN 0xf1c +#define MT8192_DISP_RDMA0_SEL_IN 0xf2c +#define MT8192_DISP_RDMA0_SOUT_SEL 0xf30 +#define MT8192_DISP_CCORR0_SOUT_SEL 0xf34 +#define MT8192_DISP_AAL0_SEL_IN 0xf38 +#define MT8192_DISP_DITHER0_MOUT_EN 0xf3c +#define MT8192_DISP_DSI0_SEL_IN 0xf40 +#define MT8192_DISP_OVL2_2L_MOUT_EN 0xf4c + +#define MT8192_DISP_OVL0_GO_BLEND BIT(0) +#define MT8192_DITHER0_MOUT_IN_DSI0 BIT(0) +#define MT8192_OVL0_MOUT_EN_DISP_RDMA0 BIT(0) +#define MT8192_OVL2_2L_MOUT_EN_RDMA4 BIT(0) +#define MT8192_DISP_OVL0_GO_BG BIT(1) +#define MT8192_DISP_OVL0_2L_GO_BLEND BIT(2) +#define MT8192_DISP_OVL0_2L_GO_BG BIT(3) +#define MT8192_OVL1_2L_MOUT_EN_RDMA1 BIT(4) +#define MT8192_OVL0_MOUT_EN_OVL0_2L BIT(4) +#define MT8192_RDMA0_SEL_IN_OVL0_2L 0x3 +#define MT8192_RDMA0_SOUT_COLOR0 0x1 +#define MT8192_CCORR0_SOUT_AAL0 0x1 +#define MT8192_AAL0_SEL_IN_CCORR0 0x1 +#define MT8192_DSI0_SEL_IN_DITHER0 0x1 + +static const struct mtk_mmsys_routes mmsys_mt8192_routing_table[] = { + { + DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0, + MT8192_DISP_OVL0_2L_MOUT_EN, MT8192_OVL0_MOUT_EN_DISP_RDMA0, + MT8192_OVL0_MOUT_EN_DISP_RDMA0 + }, { + DDP_COMPONENT_OVL_2L2, DDP_COMPONENT_RDMA4, + MT8192_DISP_OVL2_2L_MOUT_EN, MT8192_OVL2_2L_MOUT_EN_RDMA4, + MT8192_OVL2_2L_MOUT_EN_RDMA4 + }, { + DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0, + MT8192_DISP_DITHER0_MOUT_EN, MT8192_DITHER0_MOUT_IN_DSI0, + MT8192_DITHER0_MOUT_IN_DSI0 + }, { + DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0, + MT8192_DISP_RDMA0_SEL_IN, MT8192_RDMA0_SEL_IN_OVL0_2L, + MT8192_RDMA0_SEL_IN_OVL0_2L + }, { + DDP_COMPONENT_CCORR, DDP_COMPONENT_AAL0, + MT8192_DISP_AAL0_SEL_IN, MT8192_AAL0_SEL_IN_CCORR0, + MT8192_AAL0_SEL_IN_CCORR0 + }, { + DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0, + MT8192_DISP_DSI0_SEL_IN, MT8192_DSI0_SEL_IN_DITHER0 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, + MT8192_DISP_RDMA0_SOUT_SEL, MT8192_RDMA0_SOUT_COLOR0, + MT8192_RDMA0_SOUT_COLOR0 + }, { + DDP_COMPONENT_CCORR, DDP_COMPONENT_AAL0, + MT8192_DISP_CCORR0_SOUT_SEL, MT8192_CCORR0_SOUT_AAL0, + MT8192_CCORR0_SOUT_AAL0 + }, { + DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL_2L0, + MT8192_MMSYS_OVL_MOUT_EN, MT8192_DISP_OVL0_GO_BG, + MT8192_DISP_OVL0_GO_BG + }, { + DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0, + MT8192_MMSYS_OVL_MOUT_EN, MT8192_DISP_OVL0_2L_GO_BLEND, + MT8192_DISP_OVL0_2L_GO_BLEND + } +}; + +#endif /* __SOC_MEDIATEK_MT8192_MMSYS_H */ diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index a78e88f27b62..5ecfe09a5751 100644 --- a/drivers/soc/mediatek/mtk-mmsys.c +++ b/drivers/soc/mediatek/mtk-mmsys.c @@ -13,6 +13,7 @@ #include "mtk-mmsys.h" #include "mt8167-mmsys.h" #include "mt8183-mmsys.h" +#include "mt8192-mmsys.h" #include "mt8365-mmsys.h" static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { @@ -53,6 +54,12 @@ static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { .num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table), }; +static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { + .clk_driver = "clk-mt8192-mm", + .routes = mmsys_mt8192_routing_table, + .num_routes = ARRAY_SIZE(mmsys_mt8192_routing_table), +}; + static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = { .clk_driver = "clk-mt8365-mm", .routes = mt8365_mmsys_routing_table, @@ -167,6 +174,10 @@ static const struct of_device_id of_match_mtk_mmsys[] = { .compatible = "mediatek,mt8183-mmsys", .data = &mt8183_mmsys_driver_data, }, + { + .compatible = "mediatek,mt8192-mmsys", + .data = &mt8192_mmsys_driver_data, + }, { .compatible = "mediatek,mt8365-mmsys", .data = &mt8365_mmsys_driver_data, From 2ed1e4815922a3b22561b6e0e6f6d3d15a4e1007 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 Aug 2021 13:23:52 +0200 Subject: [PATCH 007/179] soc: renesas: Identify more R-Car Gen3e SoCs Add support for identifying the remaining R-Car Gen3e SoCs: R-Car H3e (R8A779M0), M3e (R8A779M2), M3Ne (R8A779M4), M3Ne-2G (R8A779M5), E3e (R8A779M6), D3e (R8A779M7), and H3Ne (R8A779M8). As these are different gradings of the already supported R-Car Gen3 SoCs, support for them is enabled through the existing ARCH_R8A779* configuration symbols. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/ccf2206b24147b3d977e4119bbdefaedceb28644.1628766192.git.geert+renesas@glider.be --- drivers/soc/renesas/Kconfig | 7 +++++-- drivers/soc/renesas/renesas-soc.c | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 07e0ecd64319..ce16ef5c939c 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -186,6 +186,7 @@ config ARCH_R8A77995 select SYSC_R8A77995 help This enables support for the Renesas R-Car D3 SoC. + This includes different gradings like R-Car D3e. config ARCH_R8A77990 bool "ARM64 Platform support for R-Car E3" @@ -193,6 +194,7 @@ config ARCH_R8A77990 select SYSC_R8A77990 help This enables support for the Renesas R-Car E3 SoC. + This includes different gradings like R-Car E3e. config ARCH_R8A77950 bool "ARM64 Platform support for R-Car H3 ES1.x" @@ -208,7 +210,7 @@ config ARCH_R8A77951 help This enables support for the Renesas R-Car H3 SoC (revisions 2.0 and later). - This includes different gradings like R-Car H3e-2G. + This includes different gradings like R-Car H3e, H3e-2G, and H3Ne. config ARCH_R8A77965 bool "ARM64 Platform support for R-Car M3-N" @@ -216,6 +218,7 @@ config ARCH_R8A77965 select SYSC_R8A77965 help This enables support for the Renesas R-Car M3-N SoC. + This includes different gradings like R-Car M3Ne and M3Ne-2G. config ARCH_R8A77960 bool "ARM64 Platform support for R-Car M3-W" @@ -230,7 +233,7 @@ config ARCH_R8A77961 select SYSC_R8A77961 help This enables support for the Renesas R-Car M3-W+ SoC. - This includes different gradings like R-Car M3e-2G. + This includes different gradings like R-Car M3e and M3e-2G. config ARCH_R8A77980 bool "ARM64 Platform support for R-Car V3H" diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index dab9f5a0aad0..7961b0be1850 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -285,17 +285,22 @@ static const struct of_device_id renesas_socs[] __initconst = { { .compatible = "renesas,r8a7795", .data = &soc_rcar_h3 }, #endif #ifdef CONFIG_ARCH_R8A77951 + { .compatible = "renesas,r8a779m0", .data = &soc_rcar_h3 }, { .compatible = "renesas,r8a779m1", .data = &soc_rcar_h3 }, + { .compatible = "renesas,r8a779m8", .data = &soc_rcar_h3 }, #endif #ifdef CONFIG_ARCH_R8A77960 { .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w }, #endif #ifdef CONFIG_ARCH_R8A77961 { .compatible = "renesas,r8a77961", .data = &soc_rcar_m3_w }, + { .compatible = "renesas,r8a779m2", .data = &soc_rcar_m3_w }, { .compatible = "renesas,r8a779m3", .data = &soc_rcar_m3_w }, #endif #ifdef CONFIG_ARCH_R8A77965 { .compatible = "renesas,r8a77965", .data = &soc_rcar_m3_n }, + { .compatible = "renesas,r8a779m4", .data = &soc_rcar_m3_n }, + { .compatible = "renesas,r8a779m5", .data = &soc_rcar_m3_n }, #endif #ifdef CONFIG_ARCH_R8A77970 { .compatible = "renesas,r8a77970", .data = &soc_rcar_v3m }, @@ -305,9 +310,11 @@ static const struct of_device_id renesas_socs[] __initconst = { #endif #ifdef CONFIG_ARCH_R8A77990 { .compatible = "renesas,r8a77990", .data = &soc_rcar_e3 }, + { .compatible = "renesas,r8a779m6", .data = &soc_rcar_e3 }, #endif #ifdef CONFIG_ARCH_R8A77995 { .compatible = "renesas,r8a77995", .data = &soc_rcar_d3 }, + { .compatible = "renesas,r8a779m7", .data = &soc_rcar_d3 }, #endif #ifdef CONFIG_ARCH_R8A779A0 { .compatible = "renesas,r8a779a0", .data = &soc_rcar_v3u }, From dc3401c83f950bfecb7cdffff2b78ac3e09ef505 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 15:14:15 +0800 Subject: [PATCH 008/179] soc: bcm: bcm-pmb: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Florian Fainelli --- drivers/soc/bcm/bcm63xx/bcm-pmb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/bcm/bcm63xx/bcm-pmb.c b/drivers/soc/bcm/bcm63xx/bcm-pmb.c index 774465c119be..7bbe46ea5f94 100644 --- a/drivers/soc/bcm/bcm63xx/bcm-pmb.c +++ b/drivers/soc/bcm/bcm63xx/bcm-pmb.c @@ -276,7 +276,6 @@ 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; @@ -287,8 +286,7 @@ static int bcm_pmb_probe(struct platform_device *pdev) pmb->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pmb->base = devm_ioremap_resource(&pdev->dev, res); + pmb->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pmb->base)) return PTR_ERR(pmb->base); From 9787ab5833054500201b980a58ababa3a3ae193c Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 15:14:16 +0800 Subject: [PATCH 009/179] soc: bcm63xx-power: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Florian Fainelli --- drivers/soc/bcm/bcm63xx/bcm63xx-power.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/bcm/bcm63xx/bcm63xx-power.c b/drivers/soc/bcm/bcm63xx/bcm63xx-power.c index 515fe182dc34..aa72e13d5d0e 100644 --- a/drivers/soc/bcm/bcm63xx/bcm63xx-power.c +++ b/drivers/soc/bcm/bcm63xx/bcm63xx-power.c @@ -91,7 +91,6 @@ static int bcm63xx_power_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct resource *res; const struct bcm63xx_power_data *entry, *table; struct bcm63xx_power *power; unsigned int ndom; @@ -102,8 +101,7 @@ static int bcm63xx_power_probe(struct platform_device *pdev) if (!power) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - power->base = devm_ioremap_resource(&pdev->dev, res); + power->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(power->base)) return PTR_ERR(power->base); From d71b90e3633ff4af8e915ba7adc3c26f7f5edcfe Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 19 Aug 2021 14:31:55 +0100 Subject: [PATCH 010/179] memory: tegra: make the array list static const, makes object smaller Don't populate the array list on the stack but instead it static const. Makes the object code smaller by 110 bytes: Before: text data bss dec hex filename 37713 21992 64 59769 e979 .../tegra/tegra210-emc-cc-r21021.o After: text data bss dec hex filename 37539 22056 64 59659 e90b .../tegra/tegra210-emc-cc-r21021.o (gcc version 10.3.0) Signed-off-by: Colin Ian King Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20210819133155.10441-1-colin.king@canonical.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra210-emc-cc-r21021.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/tegra/tegra210-emc-cc-r21021.c b/drivers/memory/tegra/tegra210-emc-cc-r21021.c index 0ebfa8eccf0c..cc76adb8d7e8 100644 --- a/drivers/memory/tegra/tegra210-emc-cc-r21021.c +++ b/drivers/memory/tegra/tegra210-emc-cc-r21021.c @@ -478,7 +478,7 @@ static u32 periodic_compensation_handler(struct tegra210_emc *emc, u32 type, static u32 tegra210_emc_r21021_periodic_compensation(struct tegra210_emc *emc) { u32 emc_cfg, emc_cfg_o, emc_cfg_update, del, value; - u32 list[] = { + static const u32 list[] = { EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2, From e12bc3540ad79b2cfc0b801ed16c93b13741d32e Mon Sep 17 00:00:00 2001 From: jing yangyang Date: Fri, 20 Aug 2021 20:52:23 -0700 Subject: [PATCH 011/179] memory: tegra30-emc: replace DEFINE_SIMPLE_ATTRIBUTE with DEFINE_DEBUGFS_ATTRIBUTE Fix the following coccicheck warning: drivers/memory/tegra/tegra30-emc.c:1322:0-23:WARNING: tegra_emc_debug_max_rate_fops should be defined with DEFINE_DEBUGFS_ATTRIBUTE Signed-off-by: jing yangyang Link: https://lore.kernel.org/r/20210821035223.28282-1-jing.yangyang@zte.com.cn Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra30-emc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c index 7e21a852f2e1..80f98d717e13 100644 --- a/drivers/memory/tegra/tegra30-emc.c +++ b/drivers/memory/tegra/tegra30-emc.c @@ -1289,7 +1289,7 @@ static int tegra_emc_debug_min_rate_set(void *data, u64 rate) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(tegra_emc_debug_min_rate_fops, +DEFINE_DEBUGFS_ATTRIBUTE(tegra_emc_debug_min_rate_fops, tegra_emc_debug_min_rate_get, tegra_emc_debug_min_rate_set, "%llu\n"); @@ -1319,7 +1319,7 @@ static int tegra_emc_debug_max_rate_set(void *data, u64 rate) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(tegra_emc_debug_max_rate_fops, +DEFINE_DEBUGFS_ATTRIBUTE(tegra_emc_debug_max_rate_fops, tegra_emc_debug_max_rate_get, tegra_emc_debug_max_rate_set, "%llu\n"); From 6fc5f1adf5a11422d748aa71e43e7c979208b8f2 Mon Sep 17 00:00:00 2001 From: Jing Yangyang Date: Tue, 24 Aug 2021 23:37:39 -0700 Subject: [PATCH 012/179] memory: tegra210-emc: replace DEFINE_SIMPLE_ATTRIBUTE with DEFINE_DEBUGFS_ATTRIBUTE Fix the following coccicheck warning: drivers/memory/tegra/tegra210-emc-core.c:1665:0-23:WARNING tegra210_emc_debug_min_rate_fops should be defined with DEFINE_DEBUGFS_ATTRIBUTE Signed-off-by: Jing Yangyang Link: https://lore.kernel.org/r/20210825063739.70260-1-deng.changcheng@zte.com.cn Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra210-emc-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memory/tegra/tegra210-emc-core.c b/drivers/memory/tegra/tegra210-emc-core.c index 06c0f17fa429..3b8284c6678e 100644 --- a/drivers/memory/tegra/tegra210-emc-core.c +++ b/drivers/memory/tegra/tegra210-emc-core.c @@ -1692,7 +1692,7 @@ static int tegra210_emc_debug_max_rate_set(void *data, u64 rate) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(tegra210_emc_debug_max_rate_fops, +DEFINE_DEBUGFS_ATTRIBUTE(tegra210_emc_debug_max_rate_fops, tegra210_emc_debug_max_rate_get, tegra210_emc_debug_max_rate_set, "%llu\n"); @@ -1723,7 +1723,7 @@ static int tegra210_emc_debug_temperature_set(void *data, u64 temperature) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(tegra210_emc_debug_temperature_fops, +DEFINE_DEBUGFS_ATTRIBUTE(tegra210_emc_debug_temperature_fops, tegra210_emc_debug_temperature_get, tegra210_emc_debug_temperature_set, "%llu\n"); From e37ef6dcdb1f4738b01cec7fb7be46af07816af9 Mon Sep 17 00:00:00 2001 From: David Virag Date: Fri, 10 Sep 2021 00:28:12 +0200 Subject: [PATCH 013/179] soc: samsung: exynos-pmu: Fix compilation when nothing selects CONFIG_MFD_CORE Commit 93618e344a5e ("soc: samsung: exynos-pmu: instantiate clkout driver as MFD") adds a "devm_mfd_add_devices" call in the exynos-pmu driver which depends on CONFIG_MFD_CORE. If no driver selects that config, the build will fail if CONFIG_EXYNOS_PMU is enabled with the following error: drivers/soc/samsung/exynos-pmu.c:137: undefined reference to `devm_mfd_add_devices' Fix this by making CONFIG_EXYNOS_PMU select CONFIG_MFD_CORE. Fixes: 93618e344a5e ("soc: samsung: exynos-pmu: instantiate clkout driver as MFD") Cc: Signed-off-by: David Virag Link: https://lore.kernel.org/r/20210909222812.108614-1-virag.david003@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/soc/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig index 5745d7e5908e..1f643c0f5c93 100644 --- a/drivers/soc/samsung/Kconfig +++ b/drivers/soc/samsung/Kconfig @@ -25,6 +25,7 @@ config EXYNOS_PMU bool "Exynos PMU controller driver" if COMPILE_TEST depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST) select EXYNOS_PMU_ARM_DRIVERS if ARM && ARCH_EXYNOS + select MFD_CORE # There is no need to enable these drivers for ARMv8 config EXYNOS_PMU_ARM_DRIVERS From e8377f497dec2f48bf7599cc9a047941740ecbd3 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 14 Sep 2021 15:21:45 -0700 Subject: [PATCH 014/179] soc: bcm: brcmstb: biuctrl: Tune MCP settings for 72113 72113 uses a dual core Cortex-A72 CPU complex which requires tuning of its bus interface unit the same way that the existing Cortex-A72 based systems are tuned. Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/biuctrl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c index 7f8dc302ae6e..e6579fc82b9e 100644 --- a/drivers/soc/bcm/brcmstb/biuctrl.c +++ b/drivers/soc/bcm/brcmstb/biuctrl.c @@ -136,6 +136,7 @@ static int __init mcp_write_pairing_set(void) static const u32 a72_b53_mach_compat[] = { 0x7211, + 0x72113, 0x7216, 0x72164, 0x72165, From 6e42e16a42c4669d2eb23d6ba3714e03c4c1e387 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 14 Sep 2021 15:21:46 -0700 Subject: [PATCH 015/179] soc: bcm: brcmstb: biuctrl: Tune MCP settings for 72116 72116 uses a quad core Brahma-B53 CPU complex which uses the same tuning as done for previous chips, add that chip to the list. Signed-off-by: Florian Fainelli --- drivers/soc/bcm/brcmstb/biuctrl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/bcm/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c index e6579fc82b9e..2c975d79fe8e 100644 --- a/drivers/soc/bcm/brcmstb/biuctrl.c +++ b/drivers/soc/bcm/brcmstb/biuctrl.c @@ -137,6 +137,7 @@ static int __init mcp_write_pairing_set(void) static const u32 a72_b53_mach_compat[] = { 0x7211, 0x72113, + 0x72116, 0x7216, 0x72164, 0x72165, From 77b14c9d05bd72d6a3f11b4982591d6cb0090ffe Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Sep 2021 21:30:09 +0300 Subject: [PATCH 016/179] memory: tegra: Remove interconnect state syncing hack State syncing works properly now, previously the sync callback was never invoked. Apparently it was fixed in drivers core, so let's remove the hack. The state won't be synced until all consumer drivers of devices that reference memory controller in a device-tree are probed, i.e. keeping bandwidth at maximum until both display and devfreq drivers are probed. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210912183009.6400-1-digetx@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 3c5aae7abf35..6b710c204799 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -706,15 +706,6 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) goto remove_nodes; } - /* - * MC driver is registered too early, so early that generic driver - * syncing doesn't work for the MC. But it doesn't really matter - * since syncing works for the EMC drivers, hence we can sync the - * MC driver by ourselves and then EMC will complete syncing of - * the whole ICC state. - */ - icc_sync_state(mc->dev); - return 0; remove_nodes: @@ -835,6 +826,15 @@ static int __maybe_unused tegra_mc_resume(struct device *dev) return 0; } +static void tegra_mc_sync_state(struct device *dev) +{ + struct tegra_mc *mc = dev_get_drvdata(dev); + + /* check whether ICC provider is registered */ + if (mc->provider.dev == dev) + icc_sync_state(dev); +} + static const struct dev_pm_ops tegra_mc_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(tegra_mc_suspend, tegra_mc_resume) }; @@ -845,6 +845,7 @@ static struct platform_driver tegra_mc_driver = { .of_match_table = tegra_mc_of_match, .pm = &tegra_mc_pm_ops, .suppress_bind_attrs = true, + .sync_state = tegra_mc_sync_state, }, .prevent_deferred_probe = true, .probe = tegra_mc_probe, From 13324edbe9269e6fbca4d0f5146b18ef8478c958 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Wed, 15 Sep 2021 11:55:15 +0300 Subject: [PATCH 017/179] memory: tegra186-emc: Handle errors in BPMP response The return value from tegra_bpmp_transfer indicates the success or failure of the IPC transaction with BPMP. If the transaction succeeded, we also need to check the actual command's result code. Add code to do this. Signed-off-by: Mikko Perttunen Link: https://lore.kernel.org/r/20210915085517.1669675-3-mperttunen@nvidia.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra186-emc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c index d65e7c2a580b..abc0c2eeaab7 100644 --- a/drivers/memory/tegra/tegra186-emc.c +++ b/drivers/memory/tegra/tegra186-emc.c @@ -197,6 +197,10 @@ static int tegra186_emc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to EMC DVFS pairs: %d\n", err); goto put_bpmp; } + if (msg.rx.ret < 0) { + dev_err(&pdev->dev, "EMC DVFS MRQ failed: %d (BPMP error code)\n", msg.rx.ret); + goto put_bpmp; + } emc->debugfs.min_rate = ULONG_MAX; emc->debugfs.max_rate = 0; From b3e9431854e8f305385d5de225441c0477b936cb Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 018/179] bus: ti-sysc: Fix timekeeping_suspended warning on resume On resume we can get a warning at kernel/time/timekeeping.c:824 for timekeeping_suspended. Let's fix this by adding separate functions for sysc_poll_reset_sysstatus() and sysc_poll_reset_sysconfig() and have the new functions handle also timekeeping_suspended. If iopoll at some point supports timekeeping_suspended, we can just drop the custom handling from these functions. Fixes: d46f9fbec719 ("bus: ti-sysc: Use optional clocks on for enable and wait for softreset bit") Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 65 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index a51c2a8feed9..efd8f0f7cfe3 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -223,37 +224,77 @@ static u32 sysc_read_sysstatus(struct sysc *ddata) return sysc_read(ddata, offset); } -/* Poll on reset status */ -static int sysc_wait_softreset(struct sysc *ddata) +static int sysc_poll_reset_sysstatus(struct sysc *ddata) { - u32 sysc_mask, syss_done, rstval; - int syss_offset, error = 0; - - if (ddata->cap->regbits->srst_shift < 0) - return 0; - - syss_offset = ddata->offsets[SYSC_SYSSTATUS]; - sysc_mask = BIT(ddata->cap->regbits->srst_shift); + int error, retries; + u32 syss_done, rstval; if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED) syss_done = 0; else syss_done = ddata->cfg.syss_mask; - if (syss_offset >= 0) { + if (likely(!timekeeping_suspended)) { error = readx_poll_timeout_atomic(sysc_read_sysstatus, ddata, rstval, (rstval & ddata->cfg.syss_mask) == syss_done, 100, MAX_MODULE_SOFTRESET_WAIT); + } else { + retries = MAX_MODULE_SOFTRESET_WAIT; + while (retries--) { + rstval = sysc_read_sysstatus(ddata); + if ((rstval & ddata->cfg.syss_mask) == syss_done) + return 0; + udelay(2); /* Account for udelay flakeyness */ + } + error = -ETIMEDOUT; + } - } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) { + return error; +} + +static int sysc_poll_reset_sysconfig(struct sysc *ddata) +{ + int error, retries; + u32 sysc_mask, rstval; + + sysc_mask = BIT(ddata->cap->regbits->srst_shift); + + if (likely(!timekeeping_suspended)) { error = readx_poll_timeout_atomic(sysc_read_sysconfig, ddata, rstval, !(rstval & sysc_mask), 100, MAX_MODULE_SOFTRESET_WAIT); + } else { + retries = MAX_MODULE_SOFTRESET_WAIT; + while (retries--) { + rstval = sysc_read_sysconfig(ddata); + if (!(rstval & sysc_mask)) + return 0; + udelay(2); /* Account for udelay flakeyness */ + } + error = -ETIMEDOUT; } return error; } +/* Poll on reset status */ +static int sysc_wait_softreset(struct sysc *ddata) +{ + int syss_offset, error = 0; + + if (ddata->cap->regbits->srst_shift < 0) + return 0; + + syss_offset = ddata->offsets[SYSC_SYSSTATUS]; + + if (syss_offset >= 0) + error = sysc_poll_reset_sysstatus(ddata); + else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) + error = sysc_poll_reset_sysconfig(ddata); + + return error; +} + static int sysc_add_named_clock_from_child(struct sysc *ddata, const char *name, const char *optfck_name) From 95ec14faac6a44bd233c54666722ef75b2276512 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 019/179] bus: ti-sysc: Check for lost context in sysc_reinit_module() There is no need to restore context if it was not lost. Let's add a new function sysc_check_context() to check for lost context. To make use of it, we need to save the sysconfig register status on enable and disable. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 60 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index efd8f0f7cfe3..9e958343a719 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -132,6 +132,7 @@ struct sysc { struct ti_sysc_cookie cookie; const char *name; u32 revision; + u32 sysconfig; unsigned int reserved:1; unsigned int enabled:1; unsigned int needs_resume:1; @@ -1135,7 +1136,8 @@ set_midle: best_mode = fls(ddata->cfg.midlemodes) - 1; if (best_mode > SYSC_IDLE_MASK) { dev_err(dev, "%s: invalid midlemode\n", __func__); - return -EINVAL; + error = -EINVAL; + goto save_context; } if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_MSTANDBY) @@ -1153,13 +1155,16 @@ set_autoidle: sysc_write_sysconfig(ddata, reg); } - /* Flush posted write */ - sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); + error = 0; + +save_context: + /* Save context and flush posted write */ + ddata->sysconfig = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); if (ddata->module_enable_quirk) ddata->module_enable_quirk(ddata); - return 0; + return error; } static int sysc_best_idle_mode(u32 idlemodes, u32 *best_mode) @@ -1216,8 +1221,10 @@ static int sysc_disable_module(struct device *dev) set_sidle: /* Set SIDLE mode */ idlemodes = ddata->cfg.sidlemodes; - if (!idlemodes || regbits->sidle_shift < 0) - return 0; + if (!idlemodes || regbits->sidle_shift < 0) { + ret = 0; + goto save_context; + } if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_SIDLE) { best_mode = SYSC_IDLE_FORCE; @@ -1225,7 +1232,8 @@ set_sidle: ret = sysc_best_idle_mode(idlemodes, &best_mode); if (ret) { dev_err(dev, "%s: invalid sidlemode\n", __func__); - return ret; + ret = -EINVAL; + goto save_context; } } @@ -1236,10 +1244,13 @@ set_sidle: reg |= 1 << regbits->autoidle_shift; sysc_write_sysconfig(ddata, reg); - /* Flush posted write */ - sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); + ret = 0; - return 0; +save_context: + /* Save context and flush posted write */ + ddata->sysconfig = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); + + return ret; } static int __maybe_unused sysc_runtime_suspend_legacy(struct device *dev, @@ -1377,13 +1388,40 @@ err_allow_idle: return error; } +/* + * Checks if device context was lost. Assumes the sysconfig register value + * after lost context is different from the configured value. Only works for + * enabled devices. + * + * Eventually we may want to also add support to using the context lost + * registers that some SoCs have. + */ +static int sysc_check_context(struct sysc *ddata) +{ + u32 reg; + + if (!ddata->enabled) + return -ENODATA; + + reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); + if (reg == ddata->sysconfig) + return 0; + + return -EACCES; +} + static int sysc_reinit_module(struct sysc *ddata, bool leave_enabled) { struct device *dev = ddata->dev; int error; - /* Disable target module if it is enabled */ if (ddata->enabled) { + /* Nothing to do if enabled and context not lost */ + error = sysc_check_context(ddata); + if (!error) + return 0; + + /* Disable target module if it is enabled */ error = sysc_runtime_suspend(dev); if (error) dev_warn(dev, "reinit suspend failed: %i\n", error); From 9d881361206ebcf6285c2ec2ef275aff80875347 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 020/179] bus: ti-sysc: Add quirk handling for reinit on context lost Some interconnect target modules such as otg and gpmc on am335x need a re-init after resume. As we also have PM runtime cases where the context may be lost, let's handle these all with cpu_pm. For the am335x resume path, we already have cpu_pm_resume() call cpu_pm_cluster_exit(). Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 108 ++++++++++++++++++++++++-- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 9e958343a719..a73c707d14c3 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -52,11 +53,18 @@ struct sysc_address { struct list_head node; }; +struct sysc_module { + struct sysc *ddata; + struct list_head node; +}; + struct sysc_soc_info { unsigned long general_purpose:1; enum sysc_soc soc; - struct mutex list_lock; /* disabled modules list lock */ + struct mutex list_lock; /* disabled and restored modules list lock */ struct list_head disabled_modules; + struct list_head restored_modules; + struct notifier_block nb; }; enum sysc_clocks { @@ -2477,6 +2485,79 @@ static struct dev_pm_domain sysc_child_pm_domain = { } }; +/* Caller needs to take list_lock if ever used outside of cpu_pm */ +static void sysc_reinit_modules(struct sysc_soc_info *soc) +{ + struct sysc_module *module; + struct list_head *pos; + struct sysc *ddata; + int error = 0; + + list_for_each(pos, &sysc_soc->restored_modules) { + module = list_entry(pos, struct sysc_module, node); + ddata = module->ddata; + error = sysc_reinit_module(ddata, ddata->enabled); + } +} + +/** + * sysc_context_notifier - optionally reset and restore module after idle + * @nb: notifier block + * @cmd: unused + * @v: unused + * + * Some interconnect target modules need to be restored, or reset and restored + * on CPU_PM CPU_PM_CLUSTER_EXIT notifier. This is needed at least for am335x + * OTG and GPMC target modules even if the modules are unused. + */ +static int sysc_context_notifier(struct notifier_block *nb, unsigned long cmd, + void *v) +{ + struct sysc_soc_info *soc; + + soc = container_of(nb, struct sysc_soc_info, nb); + + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + break; + case CPU_CLUSTER_PM_ENTER_FAILED: /* No need to restore context */ + break; + case CPU_CLUSTER_PM_EXIT: + sysc_reinit_modules(soc); + break; + } + + return NOTIFY_OK; +} + +/** + * sysc_add_restored - optionally add reset and restore quirk hanlling + * @ddata: device data + */ +static void sysc_add_restored(struct sysc *ddata) +{ + struct sysc_module *restored_module; + + restored_module = kzalloc(sizeof(*restored_module), GFP_KERNEL); + if (!restored_module) + return; + + restored_module->ddata = ddata; + + mutex_lock(&sysc_soc->list_lock); + + list_add(&restored_module->node, &sysc_soc->restored_modules); + + if (sysc_soc->nb.notifier_call) + goto out_unlock; + + sysc_soc->nb.notifier_call = sysc_context_notifier; + cpu_pm_register_notifier(&sysc_soc->nb); + +out_unlock: + mutex_unlock(&sysc_soc->list_lock); +} + /** * sysc_legacy_idle_quirk - handle children in omap_device compatible way * @ddata: device driver data @@ -2976,12 +3057,14 @@ static int sysc_add_disabled(unsigned long base) } /* - * One time init to detect the booted SoC and disable unavailable features. + * One time init to detect the booted SoC, disable unavailable features + * and initialize list for optional cpu_pm notifier. + * * Note that we initialize static data shared across all ti-sysc instances * so ddata is only used for SoC type. This can be called from module_init * once we no longer need to rely on platform data. */ -static int sysc_init_soc(struct sysc *ddata) +static int sysc_init_static_data(struct sysc *ddata) { const struct soc_device_attribute *match; struct ti_sysc_platform_data *pdata; @@ -2997,6 +3080,7 @@ static int sysc_init_soc(struct sysc *ddata) mutex_init(&sysc_soc->list_lock); INIT_LIST_HEAD(&sysc_soc->disabled_modules); + INIT_LIST_HEAD(&sysc_soc->restored_modules); sysc_soc->general_purpose = true; pdata = dev_get_platdata(ddata->dev); @@ -3060,15 +3144,24 @@ static int sysc_init_soc(struct sysc *ddata) return 0; } -static void sysc_cleanup_soc(void) +static void sysc_cleanup_static_data(void) { + struct sysc_module *restored_module; struct sysc_address *disabled_module; struct list_head *pos, *tmp; if (!sysc_soc) return; + if (sysc_soc->nb.notifier_call) + cpu_pm_unregister_notifier(&sysc_soc->nb); + mutex_lock(&sysc_soc->list_lock); + list_for_each_safe(pos, tmp, &sysc_soc->restored_modules) { + restored_module = list_entry(pos, struct sysc_module, node); + list_del(pos); + kfree(restored_module); + } list_for_each_safe(pos, tmp, &sysc_soc->disabled_modules) { disabled_module = list_entry(pos, struct sysc_address, node); list_del(pos); @@ -3136,7 +3229,7 @@ static int sysc_probe(struct platform_device *pdev) ddata->dev = &pdev->dev; platform_set_drvdata(pdev, ddata); - error = sysc_init_soc(ddata); + error = sysc_init_static_data(ddata); if (error) return error; @@ -3234,6 +3327,9 @@ static int sysc_probe(struct platform_device *pdev) pm_runtime_put(&pdev->dev); } + if (ddata->cfg.quirks & SYSC_QUIRK_REINIT_ON_CTX_LOST) + sysc_add_restored(ddata); + return 0; err: @@ -3315,7 +3411,7 @@ static void __exit sysc_exit(void) { bus_unregister_notifier(&platform_bus_type, &sysc_nb); platform_driver_unregister(&sysc_driver); - sysc_cleanup_soc(); + sysc_cleanup_static_data(); } module_exit(sysc_exit); diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 9837fb011f2f..989aa30c598d 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -50,6 +50,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_QUIRK_REINIT_ON_CTX_LOST BIT(28) #define SYSC_QUIRK_REINIT_ON_RESUME BIT(27) #define SYSC_QUIRK_GPMC_DEBUG BIT(26) #define SYSC_MODULE_QUIRK_ENA_RESETDONE BIT(25) From 6a52bc2b81fa06b7ab98472c7d80644e8e071af6 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 021/179] bus: ti-sysc: Add quirk handling for reset on re-init At least am335x gpmc module needs a reset in addition to re-init on resume. Let's add a quirk handling for reset on re-init. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 10 ++++++++++ include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index a73c707d14c3..cacdc4e301fb 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -157,6 +157,7 @@ struct sysc { static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, bool is_child); +static int sysc_reset(struct sysc *ddata); static void sysc_write(struct sysc *ddata, int offset, u32 value) { @@ -1440,6 +1441,15 @@ static int sysc_reinit_module(struct sysc *ddata, bool leave_enabled) if (error) dev_warn(dev, "reinit resume failed: %i\n", error); + /* Some modules like am335x gpmc need reset and restore of sysconfig */ + if (ddata->cfg.quirks & SYSC_QUIRK_RESET_ON_CTX_LOST) { + error = sysc_reset(ddata); + if (error) + dev_warn(dev, "reinit reset failed: %i\n", error); + + sysc_write_sysconfig(ddata, ddata->sysconfig); + } + if (leave_enabled) return error; diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 989aa30c598d..f11244f5c0b6 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -50,6 +50,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_QUIRK_RESET_ON_CTX_LOST BIT(29) #define SYSC_QUIRK_REINIT_ON_CTX_LOST BIT(28) #define SYSC_QUIRK_REINIT_ON_RESUME BIT(27) #define SYSC_QUIRK_GPMC_DEBUG BIT(26) From d48dca51935b8ca13356e726442c21ec94668d69 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 022/179] bus: ti-sysc: Use context lost quirks for gpmc At least on am335x, the gpmc module needs a re-init and reset if context has been lost on resume. We can enable this for all gpmc revisions as we check if the context was lost before restoring it. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index cacdc4e301fb..b93e0ae94d47 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1574,6 +1574,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), SYSC_QUIRK("gpmc", 0, 0, 0x10, 0x14, 0x00000060, 0xffffffff, + SYSC_QUIRK_REINIT_ON_CTX_LOST | SYSC_QUIRK_RESET_ON_CTX_LOST | SYSC_QUIRK_GPMC_DEBUG), SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50030200, 0xffffffff, SYSC_QUIRK_OPT_CLKS_NEEDED), From 9067839ff45a528bcb015cc2f24f656126b91e3f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 023/179] bus: ti-sysc: Use context lost quirk for otg Let's use SYSC_QUIRK_REINIT_ON_CTX_LOST quirk for am335x otg instead of SYSC_QUIRK_REINIT_ON_RESUME quirk as we can now handle the context loss in a more generic way. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index b93e0ae94d47..88524faa61cc 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1613,7 +1613,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY | - SYSC_QUIRK_REINIT_ON_RESUME), + SYSC_QUIRK_REINIT_ON_CTX_LOST), SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, SYSC_MODULE_QUIRK_WDT), /* PRUSS on am3, am4 and am5 */ From 5c99fa737c693a50419606d8f8266974a3521b32 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 024/179] bus: ti-sysc: Handle otg force idle quirk Let's add handling the otg force idle quirk for the old omap2430 glue layer used up to omap4 as the musb driver quirk only works if the driver is loaded. Unlike with the am335x glue layer, looks like we don't need the quirk handling for SYSC_QUIRK_REINIT_ON_CTX_LOST. Eventually when all the musb using SoCs are booting with device tree based configuration, we can just remove the related quirk handling from the musb driver. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 24 +++++++++++++++++++++++- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 88524faa61cc..fc6968dc7397 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1610,7 +1610,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -ENODEV, 0x50700101, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, - 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), + 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY | + SYSC_MODULE_QUIRK_OTG), SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY | SYSC_QUIRK_REINIT_ON_CTX_LOST), @@ -1969,6 +1970,22 @@ static void sysc_module_lock_quirk_rtc(struct sysc *ddata) sysc_quirk_rtc(ddata, true); } +/* OTG omap2430 glue layer up to omap4 needs OTG_FORCESTDBY configured */ +static void sysc_module_enable_quirk_otg(struct sysc *ddata) +{ + int offset = 0x414; /* OTG_FORCESTDBY */ + + sysc_write(ddata, offset, 0); +} + +static void sysc_module_disable_quirk_otg(struct sysc *ddata) +{ + int offset = 0x414; /* OTG_FORCESTDBY */ + u32 val = BIT(0); /* ENABLEFORCE */ + + sysc_write(ddata, offset, val); +} + /* 36xx SGX needs a quirk for to bypass OCP IPG interrupt logic */ static void sysc_module_enable_quirk_sgx(struct sysc *ddata) { @@ -2051,6 +2068,11 @@ static void sysc_init_module_quirks(struct sysc *ddata) return; } + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_OTG) { + ddata->module_enable_quirk = sysc_module_enable_quirk_otg; + ddata->module_disable_quirk = sysc_module_disable_quirk_otg; + } + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_SGX) ddata->module_enable_quirk = sysc_module_enable_quirk_sgx; diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index f11244f5c0b6..eb556f988d57 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -50,6 +50,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_MODULE_QUIRK_OTG BIT(30) #define SYSC_QUIRK_RESET_ON_CTX_LOST BIT(29) #define SYSC_QUIRK_REINIT_ON_CTX_LOST BIT(28) #define SYSC_QUIRK_REINIT_ON_RESUME BIT(27) From 1b99c1ee844cf123bf1dfe2141a24a25912ea96a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 025/179] bus: ti-sysc: Drop legacy quirk flag for gpio There is no need for the legacy flag any longer for gpio as the gpio-omap driver has been fixed to not rely on pm_runtime_irq_safe(). Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index fc6968dc7397..5105084c0a2e 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1539,8 +1539,6 @@ struct sysc_revision_quirk { static const struct sysc_revision_quirk sysc_revision_quirks[] = { /* These drivers need to be fixed to not use pm_runtime_irq_safe() */ - SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffff00ff, - SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET), SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff, @@ -1573,6 +1571,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK_CLKDM_NOAUTO), SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, SYSC_QUIRK_CLKDM_NOAUTO), + SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffff00ff, + SYSC_QUIRK_OPT_CLKS_IN_RESET), SYSC_QUIRK("gpmc", 0, 0, 0x10, 0x14, 0x00000060, 0xffffffff, SYSC_QUIRK_REINIT_ON_CTX_LOST | SYSC_QUIRK_RESET_ON_CTX_LOST | SYSC_QUIRK_GPMC_DEBUG), From ce7b43237f16c94908acb0b235250ba34c4a0fc2 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Sep 2021 12:42:25 +0300 Subject: [PATCH 026/179] bus: ti-sysc: Drop legacy quirk flag for sham There is no need for the legacy flag any longer for gpio as the omap-sham driver has been fixed to not rely on pm_runtime_irq_safe(). Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 5105084c0a2e..d4e873ab813c 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1539,8 +1539,6 @@ struct sysc_revision_quirk { static const struct sysc_revision_quirk sysc_revision_quirks[] = { /* These drivers need to be fixed to not use pm_runtime_irq_safe() */ - SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff, - SYSC_QUIRK_LEGACY_IDLE), SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff, @@ -1679,6 +1677,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("sdio", 0, 0, 0x10, -ENODEV, 0x40202301, 0xffff0ff0, 0), SYSC_QUIRK("sdio", 0, 0x2fc, 0x110, 0x114, 0x31010000, 0xffffffff, 0), SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 0), + SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff, 0), SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40000902, 0xffffffff, 0), SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40002903, 0xffffffff, 0), SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x24, -ENODEV, 0x00000000, 0xffffffff, 0), From 8c75d585b931ac874fbe4ee5a8f1811d20c2817f Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Tue, 31 Aug 2021 20:00:27 +0530 Subject: [PATCH 027/179] soc: qcom: aoss: Expose send for generic usecase Not all upcoming usecases will have an interface to allow the aoss driver to hook onto. Expose the send api and create a get function to enable drivers to send their own messages to aoss. Signed-off-by: Chris Lew Signed-off-by: Deepak Kumar Singh Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1630420228-31075-2-git-send-email-deesin@codeaurora.org --- drivers/soc/qcom/qcom_aoss.c | 54 +++++++++++++++++++++++++++++- include/linux/soc/qcom/qcom_aoss.h | 38 +++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 include/linux/soc/qcom/qcom_aoss.h diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 536c3e4114fb..bb336cc8df6f 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -8,10 +8,12 @@ #include #include #include +#include #include #include #include #include +#include #define QMP_DESC_MAGIC 0x0 #define QMP_DESC_VERSION 0x4 @@ -223,11 +225,14 @@ static bool qmp_message_empty(struct qmp *qmp) * * Return: 0 on success, negative errno on failure */ -static int qmp_send(struct qmp *qmp, const void *data, size_t len) +int qmp_send(struct qmp *qmp, const void *data, size_t len) { long time_left; int ret; + if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data)) + return -EINVAL; + if (WARN_ON(len + sizeof(u32) > qmp->size)) return -EINVAL; @@ -261,6 +266,7 @@ static int qmp_send(struct qmp *qmp, const void *data, size_t len) return ret; } +EXPORT_SYMBOL(qmp_send); static int qmp_qdss_clk_prepare(struct clk_hw *hw) { @@ -519,6 +525,51 @@ static void qmp_cooling_devices_remove(struct qmp *qmp) thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev); } +/** + * qmp_get() - get a qmp handle from a device + * @dev: client device pointer + * + * Return: handle to qmp device on success, ERR_PTR() on failure + */ +struct qmp *qmp_get(struct device *dev) +{ + struct platform_device *pdev; + struct device_node *np; + struct qmp *qmp; + + if (!dev || !dev->of_node) + return ERR_PTR(-EINVAL); + + np = of_parse_phandle(dev->of_node, "qcom,qmp", 0); + if (!np) + return ERR_PTR(-ENODEV); + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (!pdev) + return ERR_PTR(-EINVAL); + + qmp = platform_get_drvdata(pdev); + + return qmp ? qmp : ERR_PTR(-EPROBE_DEFER); +} +EXPORT_SYMBOL(qmp_get); + +/** + * qmp_put() - release a qmp handle + * @qmp: qmp handle obtained from qmp_get() + */ +void qmp_put(struct qmp *qmp) +{ + /* + * Match get_device() inside of_find_device_by_node() in + * qmp_get() + */ + if (!IS_ERR_OR_NULL(qmp)) + put_device(qmp->dev); +} +EXPORT_SYMBOL(qmp_put); + static int qmp_probe(struct platform_device *pdev) { struct resource *res; @@ -615,6 +666,7 @@ static struct platform_driver qmp_driver = { .driver = { .name = "qcom_aoss_qmp", .of_match_table = qmp_dt_match, + .suppress_bind_attrs = true, }, .probe = qmp_probe, .remove = qmp_remove, diff --git a/include/linux/soc/qcom/qcom_aoss.h b/include/linux/soc/qcom/qcom_aoss.h new file mode 100644 index 000000000000..3c2a82e606f8 --- /dev/null +++ b/include/linux/soc/qcom/qcom_aoss.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef __QCOM_AOSS_H__ +#define __QCOM_AOSS_H__ + +#include +#include + +struct qmp; + +#if IS_ENABLED(CONFIG_QCOM_AOSS_QMP) + +int qmp_send(struct qmp *qmp, const void *data, size_t len); +struct qmp *qmp_get(struct device *dev); +void qmp_put(struct qmp *qmp); + +#else + +static inline int qmp_send(struct qmp *qmp, const void *data, size_t len) +{ + return -ENODEV; +} + +static inline struct qmp *qmp_get(struct device *dev) +{ + return ERR_PTR(-ENODEV); +} + +static inline void qmp_put(struct qmp *qmp) +{ +} + +#endif + +#endif From c2b854b03adf325056f57f1aa239440c4e9c7c56 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 20 Aug 2021 22:31:02 +0200 Subject: [PATCH 028/179] soc: qcom: rpmhpd: Add SM6350 Add the power domains exposed by RPMH in the Qualcomm SM6350 platform. Acked-by: AngeloGioacchino Del Regno Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210820203105.229764-4-konrad.dybcio@somainline.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmhpd.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c index fa209b479ab3..e280a8194725 100644 --- a/drivers/soc/qcom/rpmhpd.c +++ b/drivers/soc/qcom/rpmhpd.c @@ -147,6 +147,21 @@ static const struct rpmhpd_desc sdx55_desc = { .num_pds = ARRAY_SIZE(sdx55_rpmhpds), }; +/* SM6350 RPMH powerdomains */ +static struct rpmhpd *sm6350_rpmhpds[] = { + [SM6350_CX] = &sdm845_cx, + [SM6350_GFX] = &sdm845_gfx, + [SM6350_LCX] = &sdm845_lcx, + [SM6350_LMX] = &sdm845_lmx, + [SM6350_MSS] = &sdm845_mss, + [SM6350_MX] = &sdm845_mx, +}; + +static const struct rpmhpd_desc sm6350_desc = { + .rpmhpds = sm6350_rpmhpds, + .num_pds = ARRAY_SIZE(sm6350_rpmhpds), +}; + /* SM8150 RPMH powerdomains */ static struct rpmhpd sm8150_mmcx_ao; @@ -297,6 +312,7 @@ static const struct of_device_id rpmhpd_match_table[] = { { .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc }, { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc }, { .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc}, + { .compatible = "qcom,sm6350-rpmhpd", .data = &sm6350_desc }, { .compatible = "qcom,sm8150-rpmhpd", .data = &sm8150_desc }, { .compatible = "qcom,sm8250-rpmhpd", .data = &sm8250_desc }, { .compatible = "qcom,sm8350-rpmhpd", .data = &sm8350_desc }, From 1f7b2b6327ffd16d8704bfbf0c28b6bdb6ece39f Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 20 Aug 2021 22:31:04 +0200 Subject: [PATCH 029/179] soc: qcom: llcc: Add configuration data for SM6350 Add LLCC configuration data for SM6350 SoC. Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210820203105.229764-6-konrad.dybcio@somainline.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/llcc-qcom.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 15a36dcab990..fb471cc4066b 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -142,6 +142,16 @@ static const struct llcc_slice_config sdm845_data[] = { { LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0 }, }; +static const struct llcc_slice_config sm6350_data[] = { + { LLCC_CPUSS, 1, 768, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 1 }, + { LLCC_MDM, 8, 512, 2, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, + { LLCC_GPUHTW, 11, 256, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, + { LLCC_GPU, 12, 512, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, + { LLCC_MDMPNG, 21, 768, 0, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, + { LLCC_NPU, 23, 768, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, + { LLCC_MODPE, 29, 64, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 }, +}; + static const struct llcc_slice_config sm8150_data[] = { { LLCC_CPUSS, 1, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 1 }, { LLCC_VIDSC0, 2, 512, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 }, @@ -203,6 +213,11 @@ static const struct qcom_llcc_config sdm845_cfg = { .need_llcc_cfg = false, }; +static const struct qcom_llcc_config sm6350_cfg = { + .sct_data = sm6350_data, + .size = ARRAY_SIZE(sm6350_data), +}; + static const struct qcom_llcc_config sm8150_cfg = { .sct_data = sm8150_data, .size = ARRAY_SIZE(sm8150_data), @@ -626,6 +641,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfg }, { .compatible = "qcom,sc7280-llcc", .data = &sc7280_cfg }, { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg }, + { .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfg }, { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg }, { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg }, { } From 2b9575d47841daa69f6c102e8534bf862b098606 Mon Sep 17 00:00:00 2001 From: Bartosz Dudziak Date: Sun, 6 Jun 2021 22:16:11 +0200 Subject: [PATCH 030/179] dt-bindings: arm: Add SMP enable-method for MSM8226 Add binding in enable-method property for MSM8226 SoC SMP support. Signed-off-by: Bartosz Dudziak Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210606201612.100752-2-bartosz.dudziak@snejp.pl Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/arm/cpus.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index 9a2432a88074..6a1e3d455897 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -209,6 +209,7 @@ properties: - qcom,gcc-msm8660 - qcom,kpss-acc-v1 - qcom,kpss-acc-v2 + - qcom,msm8226-smp - renesas,apmu - renesas,r9a06g032-smp - rockchip,rk3036-smp @@ -293,7 +294,7 @@ properties: Specifies the ACC* node associated with this CPU. Required for systems that have an "enable-method" property - value of "qcom,kpss-acc-v1" or "qcom,kpss-acc-v2" + value of "qcom,kpss-acc-v1", "qcom,kpss-acc-v2" or "qcom,msm8226-smp" * arm/msm/qcom,kpss-acc.txt From 7a010c3c64e2edd22f17e1165f43ba0a40904182 Mon Sep 17 00:00:00 2001 From: Bartosz Dudziak Date: Sun, 6 Jun 2021 22:16:12 +0200 Subject: [PATCH 031/179] arm: qcom: Add SMP support for MSM8226 Implement support for Cortex-A7 CPU release sequence in MSM8226 SoC. Signed-off-by: Bartosz Dudziak Reviewed-by: Stephan Gerhold Link: https://lore.kernel.org/r/20210606201612.100752-3-bartosz.dudziak@snejp.pl Signed-off-by: Bjorn Andersson --- arch/arm/mach-qcom/platsmp.c | 71 ++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c index 630a038f4513..60496554c6dd 100644 --- a/arch/arm/mach-qcom/platsmp.c +++ b/arch/arm/mach-qcom/platsmp.c @@ -29,6 +29,7 @@ #define COREPOR_RST BIT(5) #define CORE_RST BIT(4) #define L2DT_SLP BIT(3) +#define CORE_MEM_CLAMP BIT(1) #define CLAMP BIT(0) #define APC_PWR_GATE_CTL 0x14 @@ -75,6 +76,62 @@ static int scss_release_secondary(unsigned int cpu) return 0; } +static int cortex_a7_release_secondary(unsigned int cpu) +{ + int ret = 0; + void __iomem *reg; + struct device_node *cpu_node, *acc_node; + u32 reg_val; + + cpu_node = of_get_cpu_node(cpu, NULL); + if (!cpu_node) + return -ENODEV; + + acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); + if (!acc_node) { + ret = -ENODEV; + goto out_acc; + } + + reg = of_iomap(acc_node, 0); + if (!reg) { + ret = -ENOMEM; + goto out_acc_map; + } + + /* Put the CPU into reset. */ + reg_val = CORE_RST | COREPOR_RST | CLAMP | CORE_MEM_CLAMP; + writel(reg_val, reg + APCS_CPU_PWR_CTL); + + /* Turn on the BHS and set the BHS_CNT to 16 XO clock cycles */ + writel(BHS_EN | (0x10 << BHS_CNT_SHIFT), reg + APC_PWR_GATE_CTL); + /* Wait for the BHS to settle */ + udelay(2); + + reg_val &= ~CORE_MEM_CLAMP; + writel(reg_val, reg + APCS_CPU_PWR_CTL); + reg_val |= L2DT_SLP; + writel(reg_val, reg + APCS_CPU_PWR_CTL); + udelay(2); + + reg_val = (reg_val | BIT(17)) & ~CLAMP; + writel(reg_val, reg + APCS_CPU_PWR_CTL); + udelay(2); + + /* Release CPU out of reset and bring it to life. */ + reg_val &= ~(CORE_RST | COREPOR_RST); + writel(reg_val, reg + APCS_CPU_PWR_CTL); + reg_val |= CORE_PWRD_UP; + writel(reg_val, reg + APCS_CPU_PWR_CTL); + + iounmap(reg); +out_acc_map: + of_node_put(acc_node); +out_acc: + of_node_put(cpu_node); + return ret; +} + static int kpssv1_release_secondary(unsigned int cpu) { int ret = 0; @@ -281,6 +338,11 @@ static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle) return qcom_boot_secondary(cpu, scss_release_secondary); } +static int cortex_a7_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + return qcom_boot_secondary(cpu, cortex_a7_release_secondary); +} + static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle) { return qcom_boot_secondary(cpu, kpssv1_release_secondary); @@ -315,6 +377,15 @@ static const struct smp_operations smp_msm8660_ops __initconst = { }; CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops); +static const struct smp_operations qcom_smp_cortex_a7_ops __initconst = { + .smp_prepare_cpus = qcom_smp_prepare_cpus, + .smp_boot_secondary = cortex_a7_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = qcom_cpu_die, +#endif +}; +CPU_METHOD_OF_DECLARE(qcom_smp_msm8226, "qcom,msm8226-smp", &qcom_smp_cortex_a7_ops); + static const struct smp_operations qcom_smp_kpssv1_ops __initconst = { .smp_prepare_cpus = qcom_smp_prepare_cpus, .smp_boot_secondary = kpssv1_boot_secondary, From b03543067a88879169ebfdfdb36d9e8e827eeb6d Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sun, 12 Sep 2021 01:26:57 +0200 Subject: [PATCH 032/179] dt-bindings: firmware: scm: Add compatible for msm8226 Add devicetree compatible for SCM present in msm8226 platform. Signed-off-by: Luca Weiss Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210911232707.259615-4-luca@z3ntu.xyz --- Documentation/devicetree/bindings/firmware/qcom,scm.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt index a7333ad938d2..5a90e84b8dcf 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt @@ -13,6 +13,7 @@ Required properties: * "qcom,scm-ipq806x" * "qcom,scm-ipq8074" * "qcom,scm-mdm9607" + * "qcom,scm-msm8226" * "qcom,scm-msm8660" * "qcom,scm-msm8916" * "qcom,scm-msm8960" From 60f3692b5f0b3e1df3ccc07c28758379052d0ab6 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 29 Jul 2021 17:56:05 +0200 Subject: [PATCH 033/179] cpuidle: qcom_spm: Detach state machine from main SPM handling In commit a871be6b8eee ("cpuidle: Convert Qualcomm SPM driver to a generic CPUidle driver") the SPM driver has been converted to a generic CPUidle driver: that was mainly made to simplify the driver and that was a great accomplishment; Though, at that time, this driver was only applicable to ARM 32-bit SoCs, lacking logic about the handling of newer generation SAW. In preparation for the enablement of SPM features on AArch64/ARM64, split the cpuidle-qcom-spm driver in two: the CPUIdle related state machine (currently used only on ARM SoCs) stays there, while the SPM communication handling lands back in soc/qcom/spm.c and also making sure to not discard the simplifications that were introduced in the aforementioned commit. Since now the "two drivers" are split, the SCM dependency in the main SPM handling is gone and for this reason it was also possible to move the SPM initialization early: this will also make sure that whenever the SAW CPUIdle driver is getting initialized, the SPM driver will be ready to do the job. Please note that the anticipation of the SPM initialization was also done to optimize the boot times on platforms that have their CPU/L2 idle states managed by other means (such as PSCI), while needing SAW initialization for other purposes, like AVS control. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Stephan Gerhold Tested-by: Stephan Gerhold Acked-by: Daniel Lezcano Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210729155609.608159-2-angelogioacchino.delregno@somainline.org --- drivers/cpuidle/Kconfig.arm | 1 + drivers/cpuidle/cpuidle-qcom-spm.c | 326 +++++++---------------------- drivers/soc/qcom/Kconfig | 9 + drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/spm.c | 216 +++++++++++++++++++ include/soc/qcom/spm.h | 41 ++++ 6 files changed, 340 insertions(+), 254 deletions(-) create mode 100644 drivers/soc/qcom/spm.c create mode 100644 include/soc/qcom/spm.h diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 334f83e56120..8a02213c8391 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -112,6 +112,7 @@ config ARM_QCOM_SPM_CPUIDLE select CPU_IDLE_MULTIPLE_DRIVERS select DT_IDLE_STATES select QCOM_SCM + select QCOM_SPM help Select this to enable cpuidle for Qualcomm processors. The Subsystem Power Manager (SPM) controls low power modes for the diff --git a/drivers/cpuidle/cpuidle-qcom-spm.c b/drivers/cpuidle/cpuidle-qcom-spm.c index c0e7971da2da..01e77913a414 100644 --- a/drivers/cpuidle/cpuidle-qcom-spm.c +++ b/drivers/cpuidle/cpuidle-qcom-spm.c @@ -18,158 +18,18 @@ #include #include #include +#include #include #include #include "dt_idle_states.h" -#define MAX_PMIC_DATA 2 -#define MAX_SEQ_DATA 64 -#define SPM_CTL_INDEX 0x7f -#define SPM_CTL_INDEX_SHIFT 4 -#define SPM_CTL_EN BIT(0) - -enum pm_sleep_mode { - PM_SLEEP_MODE_STBY, - PM_SLEEP_MODE_RET, - PM_SLEEP_MODE_SPC, - PM_SLEEP_MODE_PC, - PM_SLEEP_MODE_NR, -}; - -enum spm_reg { - SPM_REG_CFG, - SPM_REG_SPM_CTL, - SPM_REG_DLY, - SPM_REG_PMIC_DLY, - SPM_REG_PMIC_DATA_0, - SPM_REG_PMIC_DATA_1, - SPM_REG_VCTL, - SPM_REG_SEQ_ENTRY, - SPM_REG_SPM_STS, - SPM_REG_PMIC_STS, - SPM_REG_NR, -}; - -struct spm_reg_data { - const u8 *reg_offset; - u32 spm_cfg; - u32 spm_dly; - u32 pmic_dly; - u32 pmic_data[MAX_PMIC_DATA]; - u8 seq[MAX_SEQ_DATA]; - u8 start_index[PM_SLEEP_MODE_NR]; -}; - -struct spm_driver_data { +struct cpuidle_qcom_spm_data { struct cpuidle_driver cpuidle_driver; - void __iomem *reg_base; - const struct spm_reg_data *reg_data; + struct spm_driver_data *spm; }; -static const u8 spm_reg_offset_v2_1[SPM_REG_NR] = { - [SPM_REG_CFG] = 0x08, - [SPM_REG_SPM_CTL] = 0x30, - [SPM_REG_DLY] = 0x34, - [SPM_REG_SEQ_ENTRY] = 0x80, -}; - -/* SPM register data for 8974, 8084 */ -static const struct spm_reg_data spm_reg_8974_8084_cpu = { - .reg_offset = spm_reg_offset_v2_1, - .spm_cfg = 0x1, - .spm_dly = 0x3C102800, - .seq = { 0x03, 0x0B, 0x0F, 0x00, 0x20, 0x80, 0x10, 0xE8, 0x5B, 0x03, - 0x3B, 0xE8, 0x5B, 0x82, 0x10, 0x0B, 0x30, 0x06, 0x26, 0x30, - 0x0F }, - .start_index[PM_SLEEP_MODE_STBY] = 0, - .start_index[PM_SLEEP_MODE_SPC] = 3, -}; - -/* SPM register data for 8226 */ -static const struct spm_reg_data spm_reg_8226_cpu = { - .reg_offset = spm_reg_offset_v2_1, - .spm_cfg = 0x0, - .spm_dly = 0x3C102800, - .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90, - 0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B, - 0x80, 0x10, 0x26, 0x30, 0x0F }, - .start_index[PM_SLEEP_MODE_STBY] = 0, - .start_index[PM_SLEEP_MODE_SPC] = 5, -}; - -static const u8 spm_reg_offset_v1_1[SPM_REG_NR] = { - [SPM_REG_CFG] = 0x08, - [SPM_REG_SPM_CTL] = 0x20, - [SPM_REG_PMIC_DLY] = 0x24, - [SPM_REG_PMIC_DATA_0] = 0x28, - [SPM_REG_PMIC_DATA_1] = 0x2C, - [SPM_REG_SEQ_ENTRY] = 0x80, -}; - -/* SPM register data for 8064 */ -static const struct spm_reg_data spm_reg_8064_cpu = { - .reg_offset = spm_reg_offset_v1_1, - .spm_cfg = 0x1F, - .pmic_dly = 0x02020004, - .pmic_data[0] = 0x0084009C, - .pmic_data[1] = 0x00A4001C, - .seq = { 0x03, 0x0F, 0x00, 0x24, 0x54, 0x10, 0x09, 0x03, 0x01, - 0x10, 0x54, 0x30, 0x0C, 0x24, 0x30, 0x0F }, - .start_index[PM_SLEEP_MODE_STBY] = 0, - .start_index[PM_SLEEP_MODE_SPC] = 2, -}; - -static inline void spm_register_write(struct spm_driver_data *drv, - enum spm_reg reg, u32 val) -{ - if (drv->reg_data->reg_offset[reg]) - writel_relaxed(val, drv->reg_base + - drv->reg_data->reg_offset[reg]); -} - -/* Ensure a guaranteed write, before return */ -static inline void spm_register_write_sync(struct spm_driver_data *drv, - enum spm_reg reg, u32 val) -{ - u32 ret; - - if (!drv->reg_data->reg_offset[reg]) - return; - - do { - writel_relaxed(val, drv->reg_base + - drv->reg_data->reg_offset[reg]); - ret = readl_relaxed(drv->reg_base + - drv->reg_data->reg_offset[reg]); - if (ret == val) - break; - cpu_relax(); - } while (1); -} - -static inline u32 spm_register_read(struct spm_driver_data *drv, - enum spm_reg reg) -{ - return readl_relaxed(drv->reg_base + drv->reg_data->reg_offset[reg]); -} - -static void spm_set_low_power_mode(struct spm_driver_data *drv, - enum pm_sleep_mode mode) -{ - u32 start_index; - u32 ctl_val; - - start_index = drv->reg_data->start_index[mode]; - - ctl_val = spm_register_read(drv, SPM_REG_SPM_CTL); - ctl_val &= ~(SPM_CTL_INDEX << SPM_CTL_INDEX_SHIFT); - ctl_val |= start_index << SPM_CTL_INDEX_SHIFT; - ctl_val |= SPM_CTL_EN; - spm_register_write_sync(drv, SPM_REG_SPM_CTL, ctl_val); -} - static int qcom_pm_collapse(unsigned long int unused) { qcom_scm_cpu_power_down(QCOM_SCM_CPU_PWR_DOWN_L2_ON); @@ -201,10 +61,10 @@ static int qcom_cpu_spc(struct spm_driver_data *drv) static int spm_enter_idle_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, int idx) { - struct spm_driver_data *data = container_of(drv, struct spm_driver_data, - cpuidle_driver); + struct cpuidle_qcom_spm_data *data = container_of(drv, struct cpuidle_qcom_spm_data, + cpuidle_driver); - return CPU_PM_CPU_IDLE_ENTER_PARAM(qcom_cpu_spc, idx, data); + return CPU_PM_CPU_IDLE_ENTER_PARAM(qcom_cpu_spc, idx, data->spm); } static struct cpuidle_driver qcom_spm_idle_driver = { @@ -225,134 +85,92 @@ static const struct of_device_id qcom_idle_state_match[] = { { }, }; -static int spm_cpuidle_init(struct cpuidle_driver *drv, int cpu) +static int spm_cpuidle_register(struct device *cpuidle_dev, int cpu) { + struct platform_device *pdev = NULL; + struct device_node *cpu_node, *saw_node; + struct cpuidle_qcom_spm_data *data = NULL; int ret; - memcpy(drv, &qcom_spm_idle_driver, sizeof(*drv)); - drv->cpumask = (struct cpumask *)cpumask_of(cpu); + cpu_node = of_cpu_device_node_get(cpu); + if (!cpu_node) + return -ENODEV; - /* Parse idle states from device tree */ - ret = dt_init_idle_driver(drv, qcom_idle_state_match, 1); + saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); + if (!saw_node) + return -ENODEV; + + pdev = of_find_device_by_node(saw_node); + of_node_put(saw_node); + of_node_put(cpu_node); + if (!pdev) + return -ENODEV; + + data = devm_kzalloc(cpuidle_dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->spm = dev_get_drvdata(&pdev->dev); + if (!data->spm) + return -EINVAL; + + data->cpuidle_driver = qcom_spm_idle_driver; + data->cpuidle_driver.cpumask = (struct cpumask *)cpumask_of(cpu); + + ret = dt_init_idle_driver(&data->cpuidle_driver, + qcom_idle_state_match, 1); if (ret <= 0) return ret ? : -ENODEV; - /* We have atleast one power down mode */ - return qcom_scm_set_warm_boot_addr(cpu_resume_arm, drv->cpumask); + ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm, cpumask_of(cpu)); + if (ret) + return ret; + + return cpuidle_register(&data->cpuidle_driver, NULL); } -static struct spm_driver_data *spm_get_drv(struct platform_device *pdev, - int *spm_cpu) +static int spm_cpuidle_drv_probe(struct platform_device *pdev) { - struct spm_driver_data *drv = NULL; - struct device_node *cpu_node, *saw_node; - int cpu; - bool found = 0; - - for_each_possible_cpu(cpu) { - cpu_node = of_cpu_device_node_get(cpu); - if (!cpu_node) - continue; - saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); - found = (saw_node == pdev->dev.of_node); - of_node_put(saw_node); - of_node_put(cpu_node); - if (found) - break; - } - - if (found) { - drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); - if (drv) - *spm_cpu = cpu; - } - - return drv; -} - -static const struct of_device_id spm_match_table[] = { - { .compatible = "qcom,msm8226-saw2-v2.1-cpu", - .data = &spm_reg_8226_cpu }, - { .compatible = "qcom,msm8974-saw2-v2.1-cpu", - .data = &spm_reg_8974_8084_cpu }, - { .compatible = "qcom,apq8084-saw2-v2.1-cpu", - .data = &spm_reg_8974_8084_cpu }, - { .compatible = "qcom,apq8064-saw2-v1.1-cpu", - .data = &spm_reg_8064_cpu }, - { }, -}; - -static int spm_dev_probe(struct platform_device *pdev) -{ - struct spm_driver_data *drv; - struct resource *res; - const struct of_device_id *match_id; - void __iomem *addr; int cpu, ret; if (!qcom_scm_is_available()) return -EPROBE_DEFER; - drv = spm_get_drv(pdev, &cpu); - if (!drv) - return -EINVAL; - platform_set_drvdata(pdev, drv); + for_each_possible_cpu(cpu) { + ret = spm_cpuidle_register(&pdev->dev, cpu); + if (ret && ret != -ENODEV) { + dev_err(&pdev->dev, + "Cannot register for CPU%d: %d\n", cpu, ret); + } + } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drv->reg_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(drv->reg_base)) - return PTR_ERR(drv->reg_base); - - match_id = of_match_node(spm_match_table, pdev->dev.of_node); - if (!match_id) - return -ENODEV; - - drv->reg_data = match_id->data; - - ret = spm_cpuidle_init(&drv->cpuidle_driver, cpu); - if (ret) - return ret; - - /* Write the SPM sequences first.. */ - addr = drv->reg_base + drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY]; - __iowrite32_copy(addr, drv->reg_data->seq, - ARRAY_SIZE(drv->reg_data->seq) / 4); - - /* - * ..and then the control registers. - * On some SoC if the control registers are written first and if the - * CPU was held in reset, the reset signal could trigger the SPM state - * machine, before the sequences are completely written. - */ - spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg); - spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly); - spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly); - spm_register_write(drv, SPM_REG_PMIC_DATA_0, - drv->reg_data->pmic_data[0]); - spm_register_write(drv, SPM_REG_PMIC_DATA_1, - drv->reg_data->pmic_data[1]); - - /* Set up Standby as the default low power mode */ - spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); - - return cpuidle_register(&drv->cpuidle_driver, NULL); -} - -static int spm_dev_remove(struct platform_device *pdev) -{ - struct spm_driver_data *drv = platform_get_drvdata(pdev); - - cpuidle_unregister(&drv->cpuidle_driver); return 0; } -static struct platform_driver spm_driver = { - .probe = spm_dev_probe, - .remove = spm_dev_remove, +static struct platform_driver spm_cpuidle_driver = { + .probe = spm_cpuidle_drv_probe, .driver = { - .name = "saw", - .of_match_table = spm_match_table, + .name = "qcom-spm-cpuidle", + .suppress_bind_attrs = true, }, }; -builtin_platform_driver(spm_driver); +static int __init qcom_spm_cpuidle_init(void) +{ + struct platform_device *pdev; + int ret; + + ret = platform_driver_register(&spm_cpuidle_driver); + if (ret) + return ret; + + pdev = platform_device_register_simple("qcom-spm-cpuidle", + -1, NULL, 0); + if (IS_ERR(pdev)) { + platform_driver_unregister(&spm_cpuidle_driver); + return PTR_ERR(pdev); + } + + return 0; +} +device_initcall(qcom_spm_cpuidle_init); diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 79b568f82a1c..fe3c486ae32d 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -190,6 +190,15 @@ config QCOM_SOCINFO Say yes here to support the Qualcomm socinfo driver, providing information about the SoC to user space. +config QCOM_SPM + tristate "Qualcomm Subsystem Power Manager (SPM)" + depends on ARCH_QCOM + select QCOM_SCM + help + Enable the support for the Qualcomm Subsystem Power Manager, used + to manage cores, L2 low power modes and to configure the internal + Adaptive Voltage Scaler parameters, where supported. + config QCOM_WCNSS_CTRL tristate "Qualcomm WCNSS control driver" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index ad675a6593d0..24514c722832 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o obj-$(CONFIG_QCOM_SMP2P) += smp2p.o obj-$(CONFIG_QCOM_SMSM) += smsm.o obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o +obj-$(CONFIG_QCOM_SPM) += spm.o obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o obj-$(CONFIG_QCOM_APR) += apr.o obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c new file mode 100644 index 000000000000..ef20607877de --- /dev/null +++ b/drivers/soc/qcom/spm.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014,2015, Linaro Ltd. + * + * SAW power controller driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPM_CTL_INDEX 0x7f +#define SPM_CTL_INDEX_SHIFT 4 +#define SPM_CTL_EN BIT(0) + +enum spm_reg { + SPM_REG_CFG, + SPM_REG_SPM_CTL, + SPM_REG_DLY, + SPM_REG_PMIC_DLY, + SPM_REG_PMIC_DATA_0, + SPM_REG_PMIC_DATA_1, + SPM_REG_VCTL, + SPM_REG_SEQ_ENTRY, + SPM_REG_SPM_STS, + SPM_REG_PMIC_STS, + SPM_REG_NR, +}; + +static const u8 spm_reg_offset_v2_1[SPM_REG_NR] = { + [SPM_REG_CFG] = 0x08, + [SPM_REG_SPM_CTL] = 0x30, + [SPM_REG_DLY] = 0x34, + [SPM_REG_SEQ_ENTRY] = 0x80, +}; + +/* SPM register data for 8974, 8084 */ +static const struct spm_reg_data spm_reg_8974_8084_cpu = { + .reg_offset = spm_reg_offset_v2_1, + .spm_cfg = 0x1, + .spm_dly = 0x3C102800, + .seq = { 0x03, 0x0B, 0x0F, 0x00, 0x20, 0x80, 0x10, 0xE8, 0x5B, 0x03, + 0x3B, 0xE8, 0x5B, 0x82, 0x10, 0x0B, 0x30, 0x06, 0x26, 0x30, + 0x0F }, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 3, +}; + +/* SPM register data for 8226 */ +static const struct spm_reg_data spm_reg_8226_cpu = { + .reg_offset = spm_reg_offset_v2_1, + .spm_cfg = 0x0, + .spm_dly = 0x3C102800, + .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x10, 0x80, 0x30, 0x90, + 0x5B, 0x60, 0x03, 0x60, 0x3B, 0x76, 0x76, 0x0B, 0x94, 0x5B, + 0x80, 0x10, 0x26, 0x30, 0x0F }, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 5, +}; + +static const u8 spm_reg_offset_v1_1[SPM_REG_NR] = { + [SPM_REG_CFG] = 0x08, + [SPM_REG_SPM_CTL] = 0x20, + [SPM_REG_PMIC_DLY] = 0x24, + [SPM_REG_PMIC_DATA_0] = 0x28, + [SPM_REG_PMIC_DATA_1] = 0x2C, + [SPM_REG_SEQ_ENTRY] = 0x80, +}; + +/* SPM register data for 8064 */ +static const struct spm_reg_data spm_reg_8064_cpu = { + .reg_offset = spm_reg_offset_v1_1, + .spm_cfg = 0x1F, + .pmic_dly = 0x02020004, + .pmic_data[0] = 0x0084009C, + .pmic_data[1] = 0x00A4001C, + .seq = { 0x03, 0x0F, 0x00, 0x24, 0x54, 0x10, 0x09, 0x03, 0x01, + 0x10, 0x54, 0x30, 0x0C, 0x24, 0x30, 0x0F }, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 2, +}; + +static inline void spm_register_write(struct spm_driver_data *drv, + enum spm_reg reg, u32 val) +{ + if (drv->reg_data->reg_offset[reg]) + writel_relaxed(val, drv->reg_base + + drv->reg_data->reg_offset[reg]); +} + +/* Ensure a guaranteed write, before return */ +static inline void spm_register_write_sync(struct spm_driver_data *drv, + enum spm_reg reg, u32 val) +{ + u32 ret; + + if (!drv->reg_data->reg_offset[reg]) + return; + + do { + writel_relaxed(val, drv->reg_base + + drv->reg_data->reg_offset[reg]); + ret = readl_relaxed(drv->reg_base + + drv->reg_data->reg_offset[reg]); + if (ret == val) + break; + cpu_relax(); + } while (1); +} + +static inline u32 spm_register_read(struct spm_driver_data *drv, + enum spm_reg reg) +{ + return readl_relaxed(drv->reg_base + drv->reg_data->reg_offset[reg]); +} + +void spm_set_low_power_mode(struct spm_driver_data *drv, + enum pm_sleep_mode mode) +{ + u32 start_index; + u32 ctl_val; + + start_index = drv->reg_data->start_index[mode]; + + ctl_val = spm_register_read(drv, SPM_REG_SPM_CTL); + ctl_val &= ~(SPM_CTL_INDEX << SPM_CTL_INDEX_SHIFT); + ctl_val |= start_index << SPM_CTL_INDEX_SHIFT; + ctl_val |= SPM_CTL_EN; + spm_register_write_sync(drv, SPM_REG_SPM_CTL, ctl_val); +} + +static const struct of_device_id spm_match_table[] = { + { .compatible = "qcom,msm8226-saw2-v2.1-cpu", + .data = &spm_reg_8226_cpu }, + { .compatible = "qcom,msm8974-saw2-v2.1-cpu", + .data = &spm_reg_8974_8084_cpu }, + { .compatible = "qcom,apq8084-saw2-v2.1-cpu", + .data = &spm_reg_8974_8084_cpu }, + { .compatible = "qcom,apq8064-saw2-v1.1-cpu", + .data = &spm_reg_8064_cpu }, + { }, +}; +MODULE_DEVICE_TABLE(of, spm_match_table); + +static int spm_dev_probe(struct platform_device *pdev) +{ + const struct of_device_id *match_id; + struct spm_driver_data *drv; + struct resource *res; + void __iomem *addr; + + drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + drv->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(drv->reg_base)) + return PTR_ERR(drv->reg_base); + + match_id = of_match_node(spm_match_table, pdev->dev.of_node); + if (!match_id) + return -ENODEV; + + drv->reg_data = match_id->data; + platform_set_drvdata(pdev, drv); + + /* Write the SPM sequences first.. */ + addr = drv->reg_base + drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY]; + __iowrite32_copy(addr, drv->reg_data->seq, + ARRAY_SIZE(drv->reg_data->seq) / 4); + + /* + * ..and then the control registers. + * On some SoC if the control registers are written first and if the + * CPU was held in reset, the reset signal could trigger the SPM state + * machine, before the sequences are completely written. + */ + spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg); + spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly); + spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly); + spm_register_write(drv, SPM_REG_PMIC_DATA_0, + drv->reg_data->pmic_data[0]); + spm_register_write(drv, SPM_REG_PMIC_DATA_1, + drv->reg_data->pmic_data[1]); + + /* Set up Standby as the default low power mode */ + spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); + + return 0; +} + +static struct platform_driver spm_driver = { + .probe = spm_dev_probe, + .driver = { + .name = "qcom_spm", + .of_match_table = spm_match_table, + }, +}; + +static int __init qcom_spm_init(void) +{ + return platform_driver_register(&spm_driver); +} +arch_initcall(qcom_spm_init); + +MODULE_LICENSE("GPL v2"); diff --git a/include/soc/qcom/spm.h b/include/soc/qcom/spm.h new file mode 100644 index 000000000000..4c7e5ac2583d --- /dev/null +++ b/include/soc/qcom/spm.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014,2015, Linaro Ltd. + */ + +#ifndef __SPM_H__ +#define __SPM_H__ + +#include + +#define MAX_PMIC_DATA 2 +#define MAX_SEQ_DATA 64 + +enum pm_sleep_mode { + PM_SLEEP_MODE_STBY, + PM_SLEEP_MODE_RET, + PM_SLEEP_MODE_SPC, + PM_SLEEP_MODE_PC, + PM_SLEEP_MODE_NR, +}; + +struct spm_reg_data { + const u8 *reg_offset; + u32 spm_cfg; + u32 spm_dly; + u32 pmic_dly; + u32 pmic_data[MAX_PMIC_DATA]; + u8 seq[MAX_SEQ_DATA]; + u8 start_index[PM_SLEEP_MODE_NR]; +}; + +struct spm_driver_data { + void __iomem *reg_base; + const struct spm_reg_data *reg_data; +}; + +void spm_set_low_power_mode(struct spm_driver_data *drv, + enum pm_sleep_mode mode); + +#endif /* __SPM_H__ */ From f8881c5d2fcb24b5b10b0d462e5fa0bbe9014af5 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 29 Jul 2021 17:56:06 +0200 Subject: [PATCH 034/179] dt-bindings: soc: qcom: Add devicetree binding for QCOM SPM Add devicetree binding for Qualcomm Subsystem Power Manager (SPM). Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210729155609.608159-3-angelogioacchino.delregno@somainline.org --- .../bindings/soc/qcom/qcom,spm.yaml | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml new file mode 100644 index 000000000000..507216100e3f --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/soc/qcom/qcom,spm.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Qualcomm Subsystem Power Manager binding + +maintainers: + - Andy Gross + - Bjorn Andersson + +description: | + This binding describes the Qualcomm Subsystem Power Manager, used to control + the peripheral logic surrounding the application cores in Qualcomm platforms. + +properties: + compatible: + items: + - enum: + - qcom,msm8226-saw2-v2.1-cpu + - qcom,msm8974-saw2-v2.1-cpu + - qcom,apq8084-saw2-v2.1-cpu + - qcom,apq8064-saw2-v1.1-cpu + - const: qcom,saw2 + + reg: + description: Base address and size of the SPM register region + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "qcom,kryo"; + device_type = "cpu"; + enable-method = "qcom,kpss-acc-v2"; + qcom,saw = <&saw0>; + reg = <0x0>; + operating-points-v2 = <&cpu_opp_table>; + }; + }; + + saw0: power-manager@f9089000 { + compatible = "qcom,msm8974-saw2-v2.1-cpu", "qcom,saw2"; + reg = <0xf9089000 0x1000>; + }; + +... From 13e72c3e22611915f9a71a513b640e064a403e78 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 29 Jul 2021 17:56:07 +0200 Subject: [PATCH 035/179] soc: qcom: spm: Implement support for SAWv4.1, SDM630/660 L2 AVS Implement the support for SAW v4.1, used in at least MSM8998, SDM630, SDM660 and APQ variants and, while at it, also add the configuration for the SDM630/660 Silver and Gold cluster L2 Adaptive Voltage Scaler: this is also one of the prerequisites to allow the OSM controller to perform DCVS. Please note that despite there are various "versions" of these values downstream, these are the only ones that are perfectly stable on the entire set of tested devices. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Stephan Gerhold Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210729155609.608159-4-angelogioacchino.delregno@somainline.org --- drivers/soc/qcom/spm.c | 32 +++++++++++++++++++++++++++++--- include/soc/qcom/spm.h | 4 +++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index ef20607877de..fb8de9dcfee7 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -33,10 +33,29 @@ enum spm_reg { SPM_REG_SEQ_ENTRY, SPM_REG_SPM_STS, SPM_REG_PMIC_STS, + SPM_REG_AVS_CTL, + SPM_REG_AVS_LIMIT, SPM_REG_NR, }; -static const u8 spm_reg_offset_v2_1[SPM_REG_NR] = { +static const u16 spm_reg_offset_v4_1[SPM_REG_NR] = { + [SPM_REG_AVS_CTL] = 0x904, + [SPM_REG_AVS_LIMIT] = 0x908, +}; + +static const struct spm_reg_data spm_reg_660_gold_l2 = { + .reg_offset = spm_reg_offset_v4_1, + .avs_ctl = 0x1010031, + .avs_limit = 0x4580458, +}; + +static const struct spm_reg_data spm_reg_660_silver_l2 = { + .reg_offset = spm_reg_offset_v4_1, + .avs_ctl = 0x101c031, + .avs_limit = 0x4580458, +}; + +static const u16 spm_reg_offset_v2_1[SPM_REG_NR] = { [SPM_REG_CFG] = 0x08, [SPM_REG_SPM_CTL] = 0x30, [SPM_REG_DLY] = 0x34, @@ -67,7 +86,7 @@ static const struct spm_reg_data spm_reg_8226_cpu = { .start_index[PM_SLEEP_MODE_SPC] = 5, }; -static const u8 spm_reg_offset_v1_1[SPM_REG_NR] = { +static const u16 spm_reg_offset_v1_1[SPM_REG_NR] = { [SPM_REG_CFG] = 0x08, [SPM_REG_SPM_CTL] = 0x20, [SPM_REG_PMIC_DLY] = 0x24, @@ -139,6 +158,10 @@ void spm_set_low_power_mode(struct spm_driver_data *drv, } static const struct of_device_id spm_match_table[] = { + { .compatible = "qcom,sdm660-gold-saw2-v4.1-l2", + .data = &spm_reg_660_gold_l2 }, + { .compatible = "qcom,sdm660-silver-saw2-v4.1-l2", + .data = &spm_reg_660_silver_l2 }, { .compatible = "qcom,msm8226-saw2-v2.1-cpu", .data = &spm_reg_8226_cpu }, { .compatible = "qcom,msm8974-saw2-v2.1-cpu", @@ -185,6 +208,8 @@ static int spm_dev_probe(struct platform_device *pdev) * CPU was held in reset, the reset signal could trigger the SPM state * machine, before the sequences are completely written. */ + spm_register_write(drv, SPM_REG_AVS_CTL, drv->reg_data->avs_ctl); + spm_register_write(drv, SPM_REG_AVS_LIMIT, drv->reg_data->avs_limit); spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg); spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly); spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly); @@ -194,7 +219,8 @@ static int spm_dev_probe(struct platform_device *pdev) drv->reg_data->pmic_data[1]); /* Set up Standby as the default low power mode */ - spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); + if (drv->reg_data->reg_offset[SPM_REG_SPM_CTL]) + spm_set_low_power_mode(drv, PM_SLEEP_MODE_STBY); return 0; } diff --git a/include/soc/qcom/spm.h b/include/soc/qcom/spm.h index 4c7e5ac2583d..4951f9d8b0bd 100644 --- a/include/soc/qcom/spm.h +++ b/include/soc/qcom/spm.h @@ -21,11 +21,13 @@ enum pm_sleep_mode { }; struct spm_reg_data { - const u8 *reg_offset; + const u16 *reg_offset; u32 spm_cfg; u32 spm_dly; u32 pmic_dly; u32 pmic_data[MAX_PMIC_DATA]; + u32 avs_ctl; + u32 avs_limit; u8 seq[MAX_SEQ_DATA]; u8 start_index[PM_SLEEP_MODE_NR]; }; From e48e6fb9ebdf90a290933712621319cf2cfcb777 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 29 Jul 2021 17:56:08 +0200 Subject: [PATCH 036/179] soc: qcom: spm: Add compatible for MSM8998 SAWv4.1 L2 Add the SAWv4.1 parameters for MSM8998's Gold and Silver clusters. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Stephan Gerhold Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210729155609.608159-5-angelogioacchino.delregno@somainline.org --- drivers/soc/qcom/spm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index fb8de9dcfee7..2961a89d929c 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -55,6 +55,18 @@ static const struct spm_reg_data spm_reg_660_silver_l2 = { .avs_limit = 0x4580458, }; +static const struct spm_reg_data spm_reg_8998_gold_l2 = { + .reg_offset = spm_reg_offset_v4_1, + .avs_ctl = 0x1010031, + .avs_limit = 0x4700470, +}; + +static const struct spm_reg_data spm_reg_8998_silver_l2 = { + .reg_offset = spm_reg_offset_v4_1, + .avs_ctl = 0x1010031, + .avs_limit = 0x4200420, +}; + static const u16 spm_reg_offset_v2_1[SPM_REG_NR] = { [SPM_REG_CFG] = 0x08, [SPM_REG_SPM_CTL] = 0x30, @@ -166,6 +178,10 @@ static const struct of_device_id spm_match_table[] = { .data = &spm_reg_8226_cpu }, { .compatible = "qcom,msm8974-saw2-v2.1-cpu", .data = &spm_reg_8974_8084_cpu }, + { .compatible = "qcom,msm8998-gold-saw2-v4.1-l2", + .data = &spm_reg_8998_gold_l2 }, + { .compatible = "qcom,msm8998-silver-saw2-v4.1-l2", + .data = &spm_reg_8998_silver_l2 }, { .compatible = "qcom,apq8084-saw2-v2.1-cpu", .data = &spm_reg_8974_8084_cpu }, { .compatible = "qcom,apq8064-saw2-v1.1-cpu", From 926576172d7111f8230fc6cb346b95250b607ab7 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 29 Jul 2021 17:56:09 +0200 Subject: [PATCH 037/179] dt-bindings: soc: qcom: spm: Document SDM660 and MSM8998 compatibles The driver was updated to add SAW2 v4.1 support for new SoCs: document the new compatibles. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210729155609.608159-6-angelogioacchino.delregno@somainline.org --- .../bindings/soc/qcom/qcom,spm.yaml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml index 507216100e3f..d68c002527fa 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml @@ -18,6 +18,10 @@ properties: compatible: items: - enum: + - qcom,sdm660-gold-saw2-v4.1-l2 + - qcom,sdm660-silver-saw2-v4.1-l2 + - qcom,msm8998-gold-saw2-v4.1-l2 + - qcom,msm8998-silver-saw2-v4.1-l2 - qcom,msm8226-saw2-v2.1-cpu - qcom,msm8974-saw2-v2.1-cpu - qcom,apq8084-saw2-v2.1-cpu @@ -36,6 +40,8 @@ additionalProperties: false examples: - | + + /* Example 1: SoC using SAW2 and kpss-acc-v2 CPUIdle */ cpus { #address-cells = <1>; #size-cells = <0>; @@ -55,4 +61,20 @@ examples: reg = <0xf9089000 0x1000>; }; + - | + + /* + * Example 2: New-gen multi cluster SoC using SAW only for L2; + * This does not require any cpuidle driver, nor any cpu phandle. + */ + power-manager@17812000 { + compatible = "qcom,msm8998-gold-saw2-v4.1-l2", "qcom,saw2"; + reg = <0x17812000 0x1000>; + }; + + power-manager@17912000 { + compatible = "qcom,msm8998-silver-saw2-v4.1-l2", "qcom,saw2"; + reg = <0x17912000 0x1000>; + }; + ... From 96c42812f798c5e48d55cd6fc2101ce99af19608 Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Wed, 25 Aug 2021 22:29:42 +0530 Subject: [PATCH 038/179] dt-bindings: soc: qcom: smd-rpm: Add compatible for MSM8953 SoC Document compatible for MSM8953 SoC. Signed-off-by: Vladimir Lypak Signed-off-by: Adam Skladowski Signed-off-by: Sireesh Kodali Acked-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210825165943.19415-1-sireeshkodali1@gmail.com --- Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml index cc3fe5ed7421..77963b86b714 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml @@ -34,6 +34,7 @@ properties: - qcom,rpm-ipq6018 - qcom,rpm-msm8226 - qcom,rpm-msm8916 + - qcom,rpm-msm8953 - qcom,rpm-msm8974 - qcom,rpm-msm8976 - qcom,rpm-msm8996 @@ -57,6 +58,7 @@ if: - qcom,rpm-apq8084 - qcom,rpm-msm8916 - qcom,rpm-msm8974 + - qcom,rpm-msm8953 then: required: - qcom,smd-channels From e972a290b03f83eb06c70610eaed7b0984babde7 Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Wed, 25 Aug 2021 22:31:51 +0530 Subject: [PATCH 039/179] soc: qcom: smd-rpm: Add compatible for MSM8953 SoC Add a compatible for MSM8953 Signed-off-by: Vladimir Lypak Signed-off-by: Adam Skladowski Signed-off-by: Sireesh Kodali Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210825170151.19698-1-sireeshkodali1@gmail.com --- drivers/soc/qcom/smd-rpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c index dfdd4f20f5fd..fb4896d7a9a7 100644 --- a/drivers/soc/qcom/smd-rpm.c +++ b/drivers/soc/qcom/smd-rpm.c @@ -236,6 +236,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = { { .compatible = "qcom,rpm-msm8226" }, { .compatible = "qcom,rpm-msm8916" }, { .compatible = "qcom,rpm-msm8936" }, + { .compatible = "qcom,rpm-msm8953" }, { .compatible = "qcom,rpm-msm8974" }, { .compatible = "qcom,rpm-msm8976" }, { .compatible = "qcom,rpm-msm8994" }, From cdb6f6044aeaed0dce066a780aee9bc6f3dd4fab Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Wed, 25 Aug 2021 22:32:32 +0530 Subject: [PATCH 040/179] dt-bindings: power: rpmpd: Add MSM8953 to rpmpd binding Add compatible and constants for the power domains exposed by the RPM in the Qualcomm MSM8953 platform. Signed-off-by: Vladimir Lypak Signed-off-by: Adam Skladowski Signed-off-by: Sireesh Kodali Acked-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210825170233.19859-1-sireeshkodali1@gmail.com --- Documentation/devicetree/bindings/power/qcom,rpmpd.yaml | 1 + include/dt-bindings/power/qcom-rpmpd.h | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml index 239f37881cae..996ddd360de9 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml @@ -19,6 +19,7 @@ properties: - qcom,mdm9607-rpmpd - qcom,msm8916-rpmpd - qcom,msm8939-rpmpd + - qcom,msm8953-rpmpd - qcom,msm8976-rpmpd - qcom,msm8994-rpmpd - qcom,msm8996-rpmpd diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index 4533dbbf9937..f367cf6fedf3 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -133,6 +133,15 @@ #define MSM8916_VDDMX 3 #define MSM8916_VDDMX_AO 4 +/* MSM8953 Power Domain Indexes */ +#define MSM8953_VDDMD 0 +#define MSM8953_VDDMD_AO 1 +#define MSM8953_VDDCX 2 +#define MSM8953_VDDCX_AO 3 +#define MSM8953_VDDCX_VFL 4 +#define MSM8953_VDDMX 5 +#define MSM8953_VDDMX_AO 6 + /* MSM8976 Power Domain Indexes */ #define MSM8976_VDDCX 0 #define MSM8976_VDDCX_AO 1 From e7ec00eafe944e7a4d02918517aa31c2c3b6c48a Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Wed, 25 Aug 2021 22:32:51 +0530 Subject: [PATCH 041/179] soc: qcom: rpmpd: Add power domains for MSM8953 Add support for MSM8953 power domains. Signed-off-by: Vladimir Lypak Signed-off-by: Adam Skladowski Signed-off-by: Sireesh Kodali Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210825170252.20137-1-sireeshkodali1@gmail.com --- drivers/soc/qcom/rpmpd.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index dbf494e92574..4f69fb9b2e0e 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -185,6 +185,29 @@ static const struct rpmpd_desc msm8916_desc = { .max_state = MAX_CORNER_RPMPD_STATE, }; +/* msm8953 RPM Power Domains */ +DEFINE_RPMPD_PAIR(msm8953, vddmd, vddmd_ao, SMPA, LEVEL, 1); +DEFINE_RPMPD_PAIR(msm8953, vddcx, vddcx_ao, SMPA, LEVEL, 2); +DEFINE_RPMPD_PAIR(msm8953, vddmx, vddmx_ao, SMPA, LEVEL, 7); + +DEFINE_RPMPD_VFL(msm8953, vddcx_vfl, SMPA, 2); + +static struct rpmpd *msm8953_rpmpds[] = { + [MSM8953_VDDMD] = &msm8953_vddmd, + [MSM8953_VDDMD_AO] = &msm8953_vddmd_ao, + [MSM8953_VDDCX] = &msm8953_vddcx, + [MSM8953_VDDCX_AO] = &msm8953_vddcx_ao, + [MSM8953_VDDCX_VFL] = &msm8953_vddcx_vfl, + [MSM8953_VDDMX] = &msm8953_vddmx, + [MSM8953_VDDMX_AO] = &msm8953_vddmx_ao, +}; + +static const struct rpmpd_desc msm8953_desc = { + .rpmpds = msm8953_rpmpds, + .num_pds = ARRAY_SIZE(msm8953_rpmpds), + .max_state = RPM_SMD_LEVEL_TURBO, +}; + /* msm8976 RPM Power Domains */ DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2); DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6); @@ -377,6 +400,7 @@ static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc }, + { .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc }, { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc }, { .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc }, { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc }, From aa88e34f2bfdb7516510b0d154eaa6c0a9b284cb Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 5 Sep 2021 19:11:31 +0200 Subject: [PATCH 042/179] soc: qcom: socinfo: Add IPQ8074 family ID-s IPQ8074 family SoC ID-s are missing, so lets add them based on the downstream driver. Signed-off-by: Robert Marko Reviewed-by: Kathiravan T Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210905171131.660885-1-robimarko@gmail.com --- drivers/soc/qcom/socinfo.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 9faf48302f4b..288897868435 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -281,19 +281,31 @@ static const struct soc_id soc_id[] = { { 319, "APQ8098" }, { 321, "SDM845" }, { 322, "MDM9206" }, + { 323, "IPQ8074" }, { 324, "SDA660" }, { 325, "SDM658" }, { 326, "SDA658" }, { 327, "SDA630" }, { 338, "SDM450" }, { 341, "SDA845" }, + { 342, "IPQ8072" }, + { 343, "IPQ8076" }, + { 344, "IPQ8078" }, { 345, "SDM636" }, { 346, "SDA636" }, { 349, "SDM632" }, { 350, "SDA632" }, { 351, "SDA450" }, { 356, "SM8250" }, + { 375, "IPQ8070" }, + { 376, "IPQ8071" }, + { 389, "IPQ8072A" }, + { 390, "IPQ8074A" }, + { 391, "IPQ8076A" }, + { 392, "IPQ8078A" }, { 394, "SM6125" }, + { 395, "IPQ8070A" }, + { 396, "IPQ8071A" }, { 402, "IPQ6018" }, { 403, "IPQ6028" }, { 421, "IPQ6000" }, From 0e6fda9c65634e1f6f4a18fd1c48acf0af761deb Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 16:02:11 +0800 Subject: [PATCH 043/179] PM: AVS: qcom-cpr: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210908080216.1301-1-caihuoqing@baidu.com --- drivers/soc/qcom/cpr.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c index 4ce8e816154f..1d818a8ba208 100644 --- a/drivers/soc/qcom/cpr.c +++ b/drivers/soc/qcom/cpr.c @@ -1614,7 +1614,6 @@ static void cpr_debugfs_init(struct cpr_drv *drv) static int cpr_probe(struct platform_device *pdev) { - struct resource *res; struct device *dev = &pdev->dev; struct cpr_drv *drv; int irq, ret; @@ -1648,8 +1647,7 @@ static int cpr_probe(struct platform_device *pdev) if (IS_ERR(drv->tcsr)) return PTR_ERR(drv->tcsr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drv->base = devm_ioremap_resource(dev, res); + drv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(drv->base)) return PTR_ERR(drv->base); From 172037b12be46aee55dae3ae4f8468a2dbd5eaa3 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 16:02:12 +0800 Subject: [PATCH 044/179] soc: qcom: ocmem: Make use of the helper function devm_platform_ioremap_resource_byname() Use the devm_platform_ioremap_resource_byname() helper instead of calling platform_get_resource_byname() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210908080216.1301-2-caihuoqing@baidu.com --- drivers/soc/qcom/ocmem.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index f1875dc31ae2..d2dacbbaafbd 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -300,7 +300,6 @@ static int ocmem_dev_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; unsigned long reg, region_size; int i, j, ret, num_banks; - struct resource *res; struct ocmem *ocmem; if (!qcom_scm_is_available()) @@ -321,8 +320,7 @@ static int ocmem_dev_probe(struct platform_device *pdev) return ret; } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl"); - ocmem->mmio = devm_ioremap_resource(&pdev->dev, res); + ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); if (IS_ERR(ocmem->mmio)) { dev_err(&pdev->dev, "Failed to ioremap ocmem_ctrl resource\n"); return PTR_ERR(ocmem->mmio); From d21dc0be36bbe8d424a956f6594c3f2b9f7884a6 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 16:02:13 +0800 Subject: [PATCH 045/179] soc: qcom: geni: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210908080216.1301-3-caihuoqing@baidu.com --- drivers/soc/qcom/qcom-geni-se.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 7d649d2cf31e..28a8c0dda66c 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -871,7 +871,6 @@ EXPORT_SYMBOL(geni_icc_disable); static int geni_se_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct geni_wrapper *wrapper; int ret; @@ -880,8 +879,7 @@ static int geni_se_probe(struct platform_device *pdev) return -ENOMEM; wrapper->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wrapper->base = devm_ioremap_resource(dev, res); + wrapper->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(wrapper->base)) return PTR_ERR(wrapper->base); From c318dcbcccd35a033e7bd79ba51004d2daeb4acb Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 16:02:14 +0800 Subject: [PATCH 046/179] soc: qcom: aoss: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210908080216.1301-4-caihuoqing@baidu.com --- drivers/soc/qcom/qcom_aoss.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 536c3e4114fb..c42b80ee3920 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -521,7 +521,6 @@ static void qmp_cooling_devices_remove(struct qmp *qmp) static int qmp_probe(struct platform_device *pdev) { - struct resource *res; struct qmp *qmp; int irq; int ret; @@ -534,8 +533,7 @@ static int qmp_probe(struct platform_device *pdev) init_waitqueue_head(&qmp->event); mutex_init(&qmp->tx_lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - qmp->msgram = devm_ioremap_resource(&pdev->dev, res); + qmp->msgram = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(qmp->msgram)) return PTR_ERR(qmp->msgram); From eb242d57aa6f93b702b15c40682f2775049c467d Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 16:02:15 +0800 Subject: [PATCH 047/179] soc: qcom: gsbi: Make use of the helper function devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210908080216.1301-5-caihuoqing@baidu.com --- drivers/soc/qcom/qcom_gsbi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/qcom/qcom_gsbi.c b/drivers/soc/qcom/qcom_gsbi.c index 304afc223a58..290bdefbf28a 100644 --- a/drivers/soc/qcom/qcom_gsbi.c +++ b/drivers/soc/qcom/qcom_gsbi.c @@ -127,7 +127,6 @@ static int gsbi_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; struct device_node *tcsr_node; const struct of_device_id *match; - struct resource *res; void __iomem *base; struct gsbi_info *gsbi; int i, ret; @@ -139,8 +138,7 @@ static int gsbi_probe(struct platform_device *pdev) if (!gsbi) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); From f69a91e376695ae6048934c92f6b7eea6c51cd86 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 16:02:16 +0800 Subject: [PATCH 048/179] soc: qcom: rpmh-rsc: Make use of the helper function devm_platform_ioremap_resource_byname() Use the devm_platform_ioremap_resource_byname() helper instead of calling platform_get_resource_byname() and devm_ioremap_resource() separately Signed-off-by: Cai Huoqing Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210908080216.1301-6-caihuoqing@baidu.com --- drivers/soc/qcom/rpmh-rsc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index e749a2b285d8..3a12a482f6b2 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -910,7 +910,6 @@ static int rpmh_rsc_probe(struct platform_device *pdev) { struct device_node *dn = pdev->dev.of_node; struct rsc_drv *drv; - struct resource *res; char drv_id[10] = {0}; int ret, irq; u32 solver_config; @@ -941,8 +940,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev) drv->name = dev_name(&pdev->dev); snprintf(drv_id, ARRAY_SIZE(drv_id), "drv-%d", drv->id); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, drv_id); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource_byname(pdev, drv_id); if (IS_ERR(base)) return PTR_ERR(base); From 26bc7a6a0beed882032aa7c945e44d7e82887073 Mon Sep 17 00:00:00 2001 From: Len Baker Date: Sun, 8 Aug 2021 14:50:10 +0200 Subject: [PATCH 049/179] soc: qcom: pdr: Prefer strscpy over strcpy strcpy() performs no bounds checking on the destination buffer. This could result in linear overflows beyond the end of the buffer, leading to all kinds of misbehaviors. The safe replacement is strscpy(). This is a previous step in the path to remove the strcpy() function entirely from the kernel. Signed-off-by: Len Baker Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210808125012.4715-2-len.baker@gmx.com --- drivers/soc/qcom/pdr_interface.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c index 915d5bc3d46e..fc580a3c4336 100644 --- a/drivers/soc/qcom/pdr_interface.c +++ b/drivers/soc/qcom/pdr_interface.c @@ -131,7 +131,7 @@ static int pdr_register_listener(struct pdr_handle *pdr, return ret; req.enable = enable; - strcpy(req.service_path, pds->service_path); + strscpy(req.service_path, pds->service_path, sizeof(req.service_path)); ret = qmi_send_request(&pdr->notifier_hdl, &pds->addr, &txn, SERVREG_REGISTER_LISTENER_REQ, @@ -257,7 +257,7 @@ static int pdr_send_indack_msg(struct pdr_handle *pdr, struct pdr_service *pds, return ret; req.transaction_id = tid; - strcpy(req.service_path, pds->service_path); + strscpy(req.service_path, pds->service_path, sizeof(req.service_path)); ret = qmi_send_request(&pdr->notifier_hdl, &pds->addr, &txn, SERVREG_SET_ACK_REQ, @@ -406,7 +406,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds) return -ENOMEM; /* Prepare req message */ - strcpy(req.service_name, pds->service_name); + strscpy(req.service_name, pds->service_name, sizeof(req.service_name)); req.domain_offset_valid = true; req.domain_offset = 0; @@ -531,8 +531,8 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr, return ERR_PTR(-ENOMEM); pds->service = SERVREG_NOTIFIER_SERVICE; - strcpy(pds->service_name, service_name); - strcpy(pds->service_path, service_path); + strscpy(pds->service_name, service_name, sizeof(pds->service_name)); + strscpy(pds->service_path, service_path, sizeof(pds->service_path)); pds->need_locator_lookup = true; mutex_lock(&pdr->list_lock); @@ -587,7 +587,7 @@ int pdr_restart_pd(struct pdr_handle *pdr, struct pdr_service *pds) break; /* Prepare req message */ - strcpy(req.service_path, pds->service_path); + strscpy(req.service_path, pds->service_path, sizeof(req.service_path)); addr = pds->addr; break; } From 0fdeecf9e33053f9c1629000682bc4d864242061 Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Tue, 10 Aug 2021 16:44:39 +0000 Subject: [PATCH 050/179] dt-bindings: firmware: qcom-scm: Document msm8953 bindings SCM driver on MSM8953 requires 3 clocks. Signed-off-by: Vladimir Lypak Signed-off-by: Sireesh Kodali Acked-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210810164347.45578-4-sireeshkodali@protonmail.com --- Documentation/devicetree/bindings/firmware/qcom,scm.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt index 5a90e84b8dcf..d7e3cda8924e 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt @@ -16,6 +16,7 @@ Required properties: * "qcom,scm-msm8226" * "qcom,scm-msm8660" * "qcom,scm-msm8916" + * "qcom,scm-msm8953" * "qcom,scm-msm8960" * "qcom,scm-msm8974" * "qcom,scm-msm8994" @@ -34,7 +35,7 @@ Required properties: * core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660" and "qcom,scm-msm8960" * core, iface and bus clocks required for "qcom,scm-apq8084", - "qcom,scm-msm8916" and "qcom,scm-msm8974" + "qcom,scm-msm8916", "qcom,scm-msm8953" and "qcom,scm-msm8974" - clock-names: Must contain "core" for the core clock, "iface" for the interface clock and "bus" for the bus clock per the requirements of the compatible. - qcom,dload-mode: phandle to the TCSR hardware block and offset of the From bca4392a1aa1cedc7153d975ca551d23a965b1bb Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Tue, 10 Aug 2021 16:44:48 +0000 Subject: [PATCH 051/179] firmware: qcom_scm: Add compatible for MSM8953 SoC Add compatible for SCM on MSM8953. Signed-off-by: Vladimir Lypak Signed-off-by: Sireesh Kodali Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210810164347.45578-5-sireeshkodali@protonmail.com --- drivers/firmware/qcom_scm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 2ee97bab7440..a861033616ee 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -1348,6 +1348,10 @@ static const struct of_device_id qcom_scm_dt_match[] = { SCM_HAS_IFACE_CLK | SCM_HAS_BUS_CLK) }, + { .compatible = "qcom,scm-msm8953", .data = (void *)(SCM_HAS_CORE_CLK | + SCM_HAS_IFACE_CLK | + SCM_HAS_BUS_CLK) + }, { .compatible = "qcom,scm-msm8974", .data = (void *)(SCM_HAS_CORE_CLK | SCM_HAS_IFACE_CLK | SCM_HAS_BUS_CLK) From b624c15088cb3e009785b4ad3984a9d6d1b7cea6 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 14 Sep 2021 09:53:48 +0800 Subject: [PATCH 052/179] dt-bindings: soc: qcom: smd-rpm: Add QCM2290 compatible Add compatible for the RPM on Qualcomm QCM2290 SoC. Signed-off-by: Shawn Guo Acked-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210914015349.29295-2-shawn.guo@linaro.org --- Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml index 77963b86b714..b32457c2fc0b 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml @@ -42,6 +42,7 @@ properties: - qcom,rpm-sdm660 - qcom,rpm-sm6115 - qcom,rpm-sm6125 + - qcom,rpm-qcm2290 - qcom,rpm-qcs404 qcom,smd-channels: From 3e035cbd445f98760d828154b25f3c55f577d299 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 14 Sep 2021 09:53:49 +0800 Subject: [PATCH 053/179] soc: qcom: smd-rpm: Add QCM2290 compatible Add compatible for QCM2290 SoC support. Signed-off-by: Shawn Guo Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210914015349.29295-3-shawn.guo@linaro.org --- drivers/soc/qcom/smd-rpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c index fb4896d7a9a7..30dda1af63c8 100644 --- a/drivers/soc/qcom/smd-rpm.c +++ b/drivers/soc/qcom/smd-rpm.c @@ -245,6 +245,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = { { .compatible = "qcom,rpm-sdm660" }, { .compatible = "qcom,rpm-sm6115" }, { .compatible = "qcom,rpm-sm6125" }, + { .compatible = "qcom,rpm-qcm2290" }, { .compatible = "qcom,rpm-qcs404" }, {} }; From 3a461009e195c3c17f6af73da310b886991309fd Mon Sep 17 00:00:00 2001 From: Naina Mehta Date: Tue, 21 Sep 2021 11:29:42 +0530 Subject: [PATCH 054/179] soc: qcom: llcc: Disable MMUHWT retention Disable MMUHWT retention for SC7280 as done for other platforms to avoid more power burn. Fixes: f6a07be63301 ("soc: qcom: llcc: Add configuration data for SC7280") Signed-off-by: Naina Mehta Signed-off-by: Sai Prakash Ranjan Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210921055942.30600-1-saiprakash.ranjan@codeaurora.org --- drivers/soc/qcom/llcc-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index fb471cc4066b..6bf2f1d1f2c5 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -115,7 +115,7 @@ static const struct llcc_slice_config sc7280_data[] = { { LLCC_CMPT, 10, 768, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, { LLCC_GPUHTW, 11, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, { LLCC_GPU, 12, 512, 1, 0, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_MMUHWT, 13, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 1, 0}, + { LLCC_MMUHWT, 13, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 0, 1, 0}, { LLCC_MDMPNG, 21, 768, 0, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, { LLCC_WLHW, 24, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, { LLCC_MODPE, 29, 64, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, From 069f01fac33b2506c36aa73b604b16b23f7d8e90 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 20 Aug 2021 22:31:00 +0200 Subject: [PATCH 055/179] dt-bindings: soc: qcom: aoss: Add SM6350 compatible Add SM6350 AOSS QMP compatible to the list of possible bindings. Signed-off-by: Konrad Dybcio Acked-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210820203105.229764-2-konrad.dybcio@somainline.org --- Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index 93e4b737ee1b..1904612fad85 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -30,6 +30,7 @@ properties: - qcom,sc7280-aoss-qmp - qcom,sc8180x-aoss-qmp - qcom,sdm845-aoss-qmp + - qcom,sm6350-aoss-qmp - qcom,sm8150-aoss-qmp - qcom,sm8250-aoss-qmp - qcom,sm8350-aoss-qmp From 92dde3279df9fd11b4a10cf6c7d01525c3d373ea Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 20 Aug 2021 22:31:01 +0200 Subject: [PATCH 056/179] dt-bindings: power: rpmpd: Add SM6350 to rpmpd binding Add compatible and constants for the power domains exposed by the RPMH in the Qualcomm SM6350 platform. Acked-by: AngeloGioacchino Del Regno Signed-off-by: Konrad Dybcio Acked-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210820203105.229764-3-konrad.dybcio@somainline.org --- Documentation/devicetree/bindings/power/qcom,rpmpd.yaml | 1 + include/dt-bindings/power/qcom-rpmpd.h | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml index 996ddd360de9..e810480e3eb7 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml @@ -32,6 +32,7 @@ properties: - qcom,sdm845-rpmhpd - qcom,sdx55-rpmhpd - qcom,sm6115-rpmpd + - qcom,sm6350-rpmhpd - qcom,sm8150-rpmhpd - qcom,sm8250-rpmhpd - qcom,sm8350-rpmhpd diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index f367cf6fedf3..960f7976a807 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -20,6 +20,14 @@ #define SDX55_MX 1 #define SDX55_CX 2 +/* SM6350 Power Domain Indexes */ +#define SM6350_CX 0 +#define SM6350_GFX 1 +#define SM6350_LCX 2 +#define SM6350_LMX 3 +#define SM6350_MSS 4 +#define SM6350_MX 5 + /* SM8150 Power Domain Indexes */ #define SM8150_MSS 0 #define SM8150_EBI 1 From b01065eee432b3ae91a2c0aaab66c2cae2e9812d Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:51 +0800 Subject: [PATCH 057/179] dt-bindings: memory: mediatek: Add mt8195 smi binding Add mt8195 smi supporting in the bindings. In mt8195, there are two smi-common HW, one is for vdo(video output), the other is for vpp(video processing pipe). They connect with different smi-larbs, then some setting(bus_sel) is different. Differentiate them with the compatible string. Something like this: IOMMU(VDO) IOMMU(VPP) | | SMI_COMMON_VDO SMI_COMMON_VPP ---------------- ---------------- | | ... | | ... larb0 larb2 ... larb1 larb3 ... Signed-off-by: Yong Wu Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210914113703.31466-2-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- .../bindings/memory-controllers/mediatek,smi-common.yaml | 6 +++++- .../bindings/memory-controllers/mediatek,smi-larb.yaml | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml index e87e4382807c..602592b6c3f5 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml @@ -16,7 +16,7 @@ description: | MediaTek SMI have two generations of HW architecture, here is the list which generation the SoCs use: generation 1: mt2701 and mt7623. - generation 2: mt2712, mt6779, mt8167, mt8173, mt8183 and mt8192. + generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8192 and mt8195. There's slight differences between the two SMI, for generation 2, the register which control the iommu port is at each larb's register base. But @@ -36,6 +36,8 @@ properties: - mediatek,mt8173-smi-common - mediatek,mt8183-smi-common - mediatek,mt8192-smi-common + - mediatek,mt8195-smi-common-vdo + - mediatek,mt8195-smi-common-vpp - description: for mt7623 items: @@ -98,6 +100,8 @@ allOf: - mediatek,mt6779-smi-common - mediatek,mt8183-smi-common - mediatek,mt8192-smi-common + - mediatek,mt8195-smi-common-vdo + - mediatek,mt8195-smi-common-vpp then: properties: diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml index 2353f6cf3c80..eaeff1ada7f8 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml @@ -24,6 +24,7 @@ properties: - mediatek,mt8173-smi-larb - mediatek,mt8183-smi-larb - mediatek,mt8192-smi-larb + - mediatek,mt8195-smi-larb - description: for mt7623 items: @@ -74,6 +75,7 @@ allOf: compatible: enum: - mediatek,mt8183-smi-larb + - mediatek,mt8195-smi-larb then: properties: @@ -108,6 +110,7 @@ allOf: - mediatek,mt6779-smi-larb - mediatek,mt8167-smi-larb - mediatek,mt8192-smi-larb + - mediatek,mt8195-smi-larb then: required: From 599e681a31a2dfa7359b8e420a1157ed015f840b Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:52 +0800 Subject: [PATCH 058/179] dt-bindings: memory: mediatek: Add mt8195 smi sub common Add the binding for smi-sub-common. The SMI block diagram like this: IOMMU | | smi-common ------------------ | .... | larb0 larb7 <-max is 8 The smi-common connects with smi-larb and IOMMU. The maximum larbs number that connects with a smi-common is 8. If the engines number is over 8, sometimes we use a smi-sub-common which is nearly same with smi-common. It supports up to 8 input and 1 output(smi-common has 2 output) Something like: IOMMU | | smi-common --------------------- | | ... larb0 sub-common ... <-max is 8 ----------- | | ... <-max is 8 too. larb2 larb5 We don't need extra SW setting for smi-sub-common, only the sub-common has special clocks need to enable when the engines access dram. If it is sub-common, it should have a "mediatek,smi" phandle to point to its smi-common. meanwhile the sub-common only has one gals clock. Signed-off-by: Yong Wu Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210914113703.31466-3-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- .../mediatek,smi-common.yaml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml index 602592b6c3f5..3a82b0b27fa0 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml @@ -38,6 +38,7 @@ properties: - mediatek,mt8192-smi-common - mediatek,mt8195-smi-common-vdo - mediatek,mt8195-smi-common-vpp + - mediatek,mt8195-smi-sub-common - description: for mt7623 items: @@ -67,6 +68,10 @@ properties: minItems: 2 maxItems: 4 + mediatek,smi: + $ref: /schemas/types.yaml#/definitions/phandle + description: a phandle to the smi-common node above. Only for sub-common. + required: - compatible - reg @@ -93,6 +98,29 @@ allOf: - const: smi - const: async + - if: # only for sub common + properties: + compatible: + contains: + enum: + - mediatek,mt8195-smi-sub-common + then: + required: + - mediatek,smi + properties: + clock: + items: + minItems: 3 + maxItems: 3 + clock-names: + items: + - const: apb + - const: smi + - const: gals0 + else: + properties: + mediatek,smi: false + - if: # for gen2 HW that have gals properties: compatible: From 0e14917c57f9d8b9b7d4f41813849a29659447b3 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:53 +0800 Subject: [PATCH 059/179] memory: mtk-smi: Use clk_bulk clock ops Use clk_bulk interface instead of the orginal one to simplify the code. For SMI larbs: Require apb/smi clocks while gals is optional. For SMI common: Require apb/smi/gals0/gal1 in has_gals case. Otherwise, also only require apb/smi, No optional clk here. About the "has_gals" flag, for smi larbs, the gals clock also may be optional even this platform support it. thus it always use *_bulk_get_optional, then the flag has_gals is unnecessary. Remove it. The smi_common's has_gals still keep it. Also remove clk fail logs since bulk interface already output fail log. Signed-off-by: Yong Wu Link: https://lore.kernel.org/r/20210914113703.31466-4-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 141 +++++++++++++++------------------------ 1 file changed, 54 insertions(+), 87 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index c5fb51f73b34..f91eaf5c3ab0 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -60,6 +60,20 @@ enum mtk_smi_gen { MTK_SMI_GEN2 }; +#define MTK_SMI_CLK_NR_MAX 4 + +/* larbs: Require apb/smi clocks while gals is optional. */ +static const char * const mtk_smi_larb_clks[] = {"apb", "smi", "gals"}; +#define MTK_SMI_LARB_REQ_CLK_NR 2 +#define MTK_SMI_LARB_OPT_CLK_NR 1 + +/* + * common: Require these four clocks in has_gals case. Otherwise, only apb/smi are required. + */ +static const char * const mtk_smi_common_clks[] = {"apb", "smi", "gals0", "gals1"}; +#define MTK_SMI_COM_REQ_CLK_NR 2 +#define MTK_SMI_COM_GALS_REQ_CLK_NR MTK_SMI_CLK_NR_MAX + struct mtk_smi_common_plat { enum mtk_smi_gen gen; bool has_gals; @@ -70,13 +84,12 @@ struct mtk_smi_larb_gen { int port_in_larb[MTK_LARB_NR_MAX + 1]; void (*config_port)(struct device *dev); unsigned int larb_direct_to_common_mask; - bool has_gals; }; struct mtk_smi { struct device *dev; - struct clk *clk_apb, *clk_smi; - struct clk *clk_gals0, *clk_gals1; + unsigned int clk_num; + struct clk_bulk_data clks[MTK_SMI_CLK_NR_MAX]; struct clk *clk_async; /*only needed by mt2701*/ union { void __iomem *smi_ao_base; /* only for gen1 */ @@ -95,45 +108,6 @@ struct mtk_smi_larb { /* larb: local arbiter */ unsigned char *bank; }; -static int mtk_smi_clk_enable(const struct mtk_smi *smi) -{ - int ret; - - ret = clk_prepare_enable(smi->clk_apb); - if (ret) - return ret; - - ret = clk_prepare_enable(smi->clk_smi); - if (ret) - goto err_disable_apb; - - ret = clk_prepare_enable(smi->clk_gals0); - if (ret) - goto err_disable_smi; - - ret = clk_prepare_enable(smi->clk_gals1); - if (ret) - goto err_disable_gals0; - - return 0; - -err_disable_gals0: - clk_disable_unprepare(smi->clk_gals0); -err_disable_smi: - clk_disable_unprepare(smi->clk_smi); -err_disable_apb: - clk_disable_unprepare(smi->clk_apb); - return ret; -} - -static void mtk_smi_clk_disable(const struct mtk_smi *smi) -{ - clk_disable_unprepare(smi->clk_gals1); - clk_disable_unprepare(smi->clk_gals0); - clk_disable_unprepare(smi->clk_smi); - clk_disable_unprepare(smi->clk_apb); -} - int mtk_smi_larb_get(struct device *larbdev) { int ret = pm_runtime_resume_and_get(larbdev); @@ -270,7 +244,6 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt6779 = { }; static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = { - .has_gals = true, .config_port = mtk_smi_larb_config_port_gen2_general, .larb_direct_to_common_mask = BIT(2) | BIT(3) | BIT(7), /* IPU0 | IPU1 | CCU */ @@ -312,6 +285,27 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = { {} }; +static int mtk_smi_dts_clk_init(struct device *dev, struct mtk_smi *smi, + const char * const clks[], + unsigned int clk_nr_required, + unsigned int clk_nr_optional) +{ + int i, ret; + + for (i = 0; i < clk_nr_required; i++) + smi->clks[i].id = clks[i]; + ret = devm_clk_bulk_get(dev, clk_nr_required, smi->clks); + if (ret) + return ret; + + for (i = clk_nr_required; i < clk_nr_required + clk_nr_optional; i++) + smi->clks[i].id = clks[i]; + ret = devm_clk_bulk_get_optional(dev, clk_nr_optional, + smi->clks + clk_nr_required); + smi->clk_num = clk_nr_required + clk_nr_optional; + return ret; +} + static int mtk_smi_larb_probe(struct platform_device *pdev) { struct mtk_smi_larb *larb; @@ -320,6 +314,7 @@ static int mtk_smi_larb_probe(struct platform_device *pdev) struct device_node *smi_node; struct platform_device *smi_pdev; struct device_link *link; + int ret; larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL); if (!larb) @@ -331,24 +326,12 @@ static int mtk_smi_larb_probe(struct platform_device *pdev) if (IS_ERR(larb->base)) return PTR_ERR(larb->base); - larb->smi.clk_apb = devm_clk_get(dev, "apb"); - if (IS_ERR(larb->smi.clk_apb)) - return PTR_ERR(larb->smi.clk_apb); + ret = mtk_smi_dts_clk_init(dev, &larb->smi, mtk_smi_larb_clks, + MTK_SMI_LARB_REQ_CLK_NR, MTK_SMI_LARB_OPT_CLK_NR); + if (ret) + return ret; - larb->smi.clk_smi = devm_clk_get(dev, "smi"); - if (IS_ERR(larb->smi.clk_smi)) - return PTR_ERR(larb->smi.clk_smi); - - if (larb->larb_gen->has_gals) { - /* The larbs may still haven't gals even if the SoC support.*/ - larb->smi.clk_gals0 = devm_clk_get(dev, "gals"); - if (PTR_ERR(larb->smi.clk_gals0) == -ENOENT) - larb->smi.clk_gals0 = NULL; - else if (IS_ERR(larb->smi.clk_gals0)) - return PTR_ERR(larb->smi.clk_gals0); - } larb->smi.dev = dev; - smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0); if (!smi_node) return -EINVAL; @@ -391,11 +374,9 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev) const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen; int ret; - ret = mtk_smi_clk_enable(&larb->smi); - if (ret < 0) { - dev_err(dev, "Failed to enable clock(%d).\n", ret); + ret = clk_bulk_prepare_enable(larb->smi.clk_num, larb->smi.clks); + if (ret < 0) return ret; - } /* Configure the basic setting for this larb */ larb_gen->config_port(dev); @@ -407,7 +388,7 @@ static int __maybe_unused mtk_smi_larb_suspend(struct device *dev) { struct mtk_smi_larb *larb = dev_get_drvdata(dev); - mtk_smi_clk_disable(&larb->smi); + clk_bulk_disable_unprepare(larb->smi.clk_num, larb->smi.clks); return 0; } @@ -493,7 +474,7 @@ static int mtk_smi_common_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct mtk_smi *common; struct resource *res; - int ret; + int ret, clk_required = MTK_SMI_COM_REQ_CLK_NR; common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL); if (!common) @@ -501,23 +482,11 @@ static int mtk_smi_common_probe(struct platform_device *pdev) common->dev = dev; common->plat = of_device_get_match_data(dev); - common->clk_apb = devm_clk_get(dev, "apb"); - if (IS_ERR(common->clk_apb)) - return PTR_ERR(common->clk_apb); - - common->clk_smi = devm_clk_get(dev, "smi"); - if (IS_ERR(common->clk_smi)) - return PTR_ERR(common->clk_smi); - - if (common->plat->has_gals) { - common->clk_gals0 = devm_clk_get(dev, "gals0"); - if (IS_ERR(common->clk_gals0)) - return PTR_ERR(common->clk_gals0); - - common->clk_gals1 = devm_clk_get(dev, "gals1"); - if (IS_ERR(common->clk_gals1)) - return PTR_ERR(common->clk_gals1); - } + if (common->plat->has_gals) + clk_required = MTK_SMI_COM_GALS_REQ_CLK_NR; + ret = mtk_smi_dts_clk_init(dev, common, mtk_smi_common_clks, clk_required, 0); + if (ret) + return ret; /* * for mtk smi gen 1, we need to get the ao(always on) base to config @@ -561,11 +530,9 @@ static int __maybe_unused mtk_smi_common_resume(struct device *dev) u32 bus_sel = common->plat->bus_sel; int ret; - ret = mtk_smi_clk_enable(common); - if (ret) { - dev_err(common->dev, "Failed to enable clock(%d).\n", ret); + ret = clk_bulk_prepare_enable(common->clk_num, common->clks); + if (ret) return ret; - } if (common->plat->gen == MTK_SMI_GEN2 && bus_sel) writel(bus_sel, common->base + SMI_BUS_SEL); @@ -576,7 +543,7 @@ static int __maybe_unused mtk_smi_common_suspend(struct device *dev) { struct mtk_smi *common = dev_get_drvdata(dev); - mtk_smi_clk_disable(common); + clk_bulk_disable_unprepare(common->clk_num, common->clks); return 0; } From a5c18986f404206fdbc27f208620dc13bffb5657 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:54 +0800 Subject: [PATCH 060/179] memory: mtk-smi: Rename smi_gen to smi_type Prepare for adding smi sub common. Only rename from smi_gen to smi_type. No functional change. About the current "smi_gen", we have gen1/gen2 that stand for the generation number for HW. I plan to add a new type(sub_common), then the name "gen" is not proper. Signed-off-by: Yong Wu Reviewed-by: Ikjoon Jang Link: https://lore.kernel.org/r/20210914113703.31466-5-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index f91eaf5c3ab0..02a584dfb9b1 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -55,7 +55,7 @@ /* All are MMU0 defaultly. Only specialize mmu1 here. */ #define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid)) -enum mtk_smi_gen { +enum mtk_smi_type { MTK_SMI_GEN1, MTK_SMI_GEN2 }; @@ -75,9 +75,9 @@ static const char * const mtk_smi_common_clks[] = {"apb", "smi", "gals0", "gals1 #define MTK_SMI_COM_GALS_REQ_CLK_NR MTK_SMI_CLK_NR_MAX struct mtk_smi_common_plat { - enum mtk_smi_gen gen; - bool has_gals; - u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */ + enum mtk_smi_type type; + bool has_gals; + u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */ }; struct mtk_smi_larb_gen { @@ -409,29 +409,29 @@ static struct platform_driver mtk_smi_larb_driver = { }; static const struct mtk_smi_common_plat mtk_smi_common_gen1 = { - .gen = MTK_SMI_GEN1, + .type = MTK_SMI_GEN1, }; static const struct mtk_smi_common_plat mtk_smi_common_gen2 = { - .gen = MTK_SMI_GEN2, + .type = MTK_SMI_GEN2, }; static const struct mtk_smi_common_plat mtk_smi_common_mt6779 = { - .gen = MTK_SMI_GEN2, - .has_gals = true, - .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(4) | - F_MMU1_LARB(5) | F_MMU1_LARB(6) | F_MMU1_LARB(7), + .type = MTK_SMI_GEN2, + .has_gals = true, + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(4) | + F_MMU1_LARB(5) | F_MMU1_LARB(6) | F_MMU1_LARB(7), }; static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = { - .gen = MTK_SMI_GEN2, + .type = MTK_SMI_GEN2, .has_gals = true, .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) | F_MMU1_LARB(7), }; static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = { - .gen = MTK_SMI_GEN2, + .type = MTK_SMI_GEN2, .has_gals = true, .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) | F_MMU1_LARB(6), @@ -494,7 +494,7 @@ static int mtk_smi_common_probe(struct platform_device *pdev) * clock into emi clock domain, but for mtk smi gen2, there's no smi ao * base. */ - if (common->plat->gen == MTK_SMI_GEN1) { + if (common->plat->type == MTK_SMI_GEN1) { res = platform_get_resource(pdev, IORESOURCE_MEM, 0); common->smi_ao_base = devm_ioremap_resource(dev, res); if (IS_ERR(common->smi_ao_base)) @@ -534,7 +534,7 @@ static int __maybe_unused mtk_smi_common_resume(struct device *dev) if (ret) return ret; - if (common->plat->gen == MTK_SMI_GEN2 && bus_sel) + if (common->plat->type == MTK_SMI_GEN2 && bus_sel) writel(bus_sel, common->base + SMI_BUS_SEL); return 0; } From 534e0ad2ed4f9296a8c7ccb1a393bc4d5000dbad Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:55 +0800 Subject: [PATCH 061/179] memory: mtk-smi: Adjust some code position No functional change. Only move the code position to make the code more readable. 1. Put the register smi-common above smi-larb. Prepare to add some others register setting. 2. Put mtk_smi_larb_unbind around larb_bind. 3. Sort the SoC data alphabetically. and put them in one line as the current kernel allow it. Signed-off-by: Yong Wu Reviewed-by: Ikjoon Jang Link: https://lore.kernel.org/r/20210914113703.31466-6-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 188 ++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 113 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 02a584dfb9b1..33b6c5efe102 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -17,13 +17,16 @@ #include #include -/* mt8173 */ -#define SMI_LARB_MMU_EN 0xf00 +/* SMI COMMON */ +#define SMI_BUS_SEL 0x220 +#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1) +/* All are MMU0 defaultly. Only specialize mmu1 here. */ +#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid)) -/* mt8167 */ -#define MT8167_SMI_LARB_MMU_EN 0xfc0 +/* SMI LARB */ -/* mt2701 */ +/* Below are about mmu enable registers, they are different in SoCs */ +/* gen1: mt2701 */ #define REG_SMI_SECUR_CON_BASE 0x5c0 /* every register control 8 port, register offset 0x4 */ @@ -41,20 +44,21 @@ /* mt2701 domain should be set to 3 */ #define SMI_SECUR_CON_VAL_DOMAIN(id) (0x3 << ((((id) & 0x7) << 2) + 1)) -/* mt2712 */ -#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4)) -#define F_MMU_EN BIT(0) -#define BANK_SEL(id) ({ \ +/* gen2: */ +/* mt8167 */ +#define MT8167_SMI_LARB_MMU_EN 0xfc0 + +/* mt8173 */ +#define MT8173_SMI_LARB_MMU_EN 0xf00 + +/* general */ +#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4)) +#define F_MMU_EN BIT(0) +#define BANK_SEL(id) ({ \ u32 _id = (id) & 0x3; \ (_id << 8 | _id << 10 | _id << 12 | _id << 14); \ }) -/* SMI COMMON */ -#define SMI_BUS_SEL 0x220 -#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1) -/* All are MMU0 defaultly. Only specialize mmu1 here. */ -#define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid)) - enum mtk_smi_type { MTK_SMI_GEN1, MTK_SMI_GEN2 @@ -140,36 +144,16 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data) return -ENODEV; } -static void mtk_smi_larb_config_port_gen2_general(struct device *dev) +static void +mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data) { - struct mtk_smi_larb *larb = dev_get_drvdata(dev); - u32 reg; - int i; - - if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask) - return; - - for_each_set_bit(i, (unsigned long *)larb->mmu, 32) { - reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i)); - reg |= F_MMU_EN; - reg |= BANK_SEL(larb->bank[i]); - writel(reg, larb->base + SMI_LARB_NONSEC_CON(i)); - } + /* Do nothing as the iommu is always enabled. */ } -static void mtk_smi_larb_config_port_mt8173(struct device *dev) -{ - struct mtk_smi_larb *larb = dev_get_drvdata(dev); - - writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN); -} - -static void mtk_smi_larb_config_port_mt8167(struct device *dev) -{ - struct mtk_smi_larb *larb = dev_get_drvdata(dev); - - writel(*larb->mmu, larb->base + MT8167_SMI_LARB_MMU_EN); -} +static const struct component_ops mtk_smi_larb_component_ops = { + .bind = mtk_smi_larb_bind, + .unbind = mtk_smi_larb_unbind, +}; static void mtk_smi_larb_config_port_gen1(struct device *dev) { @@ -202,26 +186,36 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev) } } -static void -mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data) +static void mtk_smi_larb_config_port_mt8167(struct device *dev) { - /* Do nothing as the iommu is always enabled. */ + struct mtk_smi_larb *larb = dev_get_drvdata(dev); + + writel(*larb->mmu, larb->base + MT8167_SMI_LARB_MMU_EN); } -static const struct component_ops mtk_smi_larb_component_ops = { - .bind = mtk_smi_larb_bind, - .unbind = mtk_smi_larb_unbind, -}; +static void mtk_smi_larb_config_port_mt8173(struct device *dev) +{ + struct mtk_smi_larb *larb = dev_get_drvdata(dev); -static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = { - /* mt8173 do not need the port in larb */ - .config_port = mtk_smi_larb_config_port_mt8173, -}; + writel(*larb->mmu, larb->base + MT8173_SMI_LARB_MMU_EN); +} -static const struct mtk_smi_larb_gen mtk_smi_larb_mt8167 = { - /* mt8167 do not need the port in larb */ - .config_port = mtk_smi_larb_config_port_mt8167, -}; +static void mtk_smi_larb_config_port_gen2_general(struct device *dev) +{ + struct mtk_smi_larb *larb = dev_get_drvdata(dev); + u32 reg; + int i; + + if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask) + return; + + for_each_set_bit(i, (unsigned long *)larb->mmu, 32) { + reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i)); + reg |= F_MMU_EN; + reg |= BANK_SEL(larb->bank[i]); + writel(reg, larb->base + SMI_LARB_NONSEC_CON(i)); + } +} static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = { .port_in_larb = { @@ -243,6 +237,16 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt6779 = { /* DUMMY | IPU0 | IPU1 | CCU | MDLA */ }; +static const struct mtk_smi_larb_gen mtk_smi_larb_mt8167 = { + /* mt8167 do not need the port in larb */ + .config_port = mtk_smi_larb_config_port_mt8167, +}; + +static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = { + /* mt8173 do not need the port in larb */ + .config_port = mtk_smi_larb_config_port_mt8173, +}; + static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = { .config_port = mtk_smi_larb_config_port_gen2_general, .larb_direct_to_common_mask = BIT(2) | BIT(3) | BIT(7), @@ -254,34 +258,13 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = { }; static const struct of_device_id mtk_smi_larb_of_ids[] = { - { - .compatible = "mediatek,mt8167-smi-larb", - .data = &mtk_smi_larb_mt8167 - }, - { - .compatible = "mediatek,mt8173-smi-larb", - .data = &mtk_smi_larb_mt8173 - }, - { - .compatible = "mediatek,mt2701-smi-larb", - .data = &mtk_smi_larb_mt2701 - }, - { - .compatible = "mediatek,mt2712-smi-larb", - .data = &mtk_smi_larb_mt2712 - }, - { - .compatible = "mediatek,mt6779-smi-larb", - .data = &mtk_smi_larb_mt6779 - }, - { - .compatible = "mediatek,mt8183-smi-larb", - .data = &mtk_smi_larb_mt8183 - }, - { - .compatible = "mediatek,mt8192-smi-larb", - .data = &mtk_smi_larb_mt8192 - }, + {.compatible = "mediatek,mt2701-smi-larb", .data = &mtk_smi_larb_mt2701}, + {.compatible = "mediatek,mt2712-smi-larb", .data = &mtk_smi_larb_mt2712}, + {.compatible = "mediatek,mt6779-smi-larb", .data = &mtk_smi_larb_mt6779}, + {.compatible = "mediatek,mt8167-smi-larb", .data = &mtk_smi_larb_mt8167}, + {.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173}, + {.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183}, + {.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192}, {} }; @@ -438,34 +421,13 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = { }; static const struct of_device_id mtk_smi_common_of_ids[] = { - { - .compatible = "mediatek,mt8173-smi-common", - .data = &mtk_smi_common_gen2, - }, - { - .compatible = "mediatek,mt8167-smi-common", - .data = &mtk_smi_common_gen2, - }, - { - .compatible = "mediatek,mt2701-smi-common", - .data = &mtk_smi_common_gen1, - }, - { - .compatible = "mediatek,mt2712-smi-common", - .data = &mtk_smi_common_gen2, - }, - { - .compatible = "mediatek,mt6779-smi-common", - .data = &mtk_smi_common_mt6779, - }, - { - .compatible = "mediatek,mt8183-smi-common", - .data = &mtk_smi_common_mt8183, - }, - { - .compatible = "mediatek,mt8192-smi-common", - .data = &mtk_smi_common_mt8192, - }, + {.compatible = "mediatek,mt2701-smi-common", .data = &mtk_smi_common_gen1}, + {.compatible = "mediatek,mt2712-smi-common", .data = &mtk_smi_common_gen2}, + {.compatible = "mediatek,mt6779-smi-common", .data = &mtk_smi_common_mt6779}, + {.compatible = "mediatek,mt8167-smi-common", .data = &mtk_smi_common_gen2}, + {.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2}, + {.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183}, + {.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192}, {} }; From 30b869e77a1c626190bbbe6b4e5f5382b0102ac3 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:56 +0800 Subject: [PATCH 062/179] memory: mtk-smi: Add error handle for smi_probe Add error handle while component_add fail. Signed-off-by: Yong Wu Reviewed-by: Ikjoon Jang Link: https://lore.kernel.org/r/20210914113703.31466-7-yong.wu@mediatek.com Fixes: 6ce2c05b2118 ("memory: mtk-smi: Add device-link between smi-larb and smi-common") Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 33b6c5efe102..b362d528944e 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -338,7 +338,15 @@ static int mtk_smi_larb_probe(struct platform_device *pdev) pm_runtime_enable(dev); platform_set_drvdata(pdev, larb); - return component_add(dev, &mtk_smi_larb_component_ops); + ret = component_add(dev, &mtk_smi_larb_component_ops); + if (ret) + goto err_pm_disable; + return 0; + +err_pm_disable: + pm_runtime_disable(dev); + device_link_remove(dev, larb->smi_common_dev); + return ret; } static int mtk_smi_larb_remove(struct platform_device *pdev) From 47404757702ec8aa5c8310cdf58a267081f0ce6c Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:57 +0800 Subject: [PATCH 063/179] memory: mtk-smi: Add device link for smi-sub-common In mt8195, there are some larbs connect with the smi-sub-common, then connect with smi-common. Before we create device link between smi-larb with smi-common. If we have sub-common, we should use device link the smi-larb and smi-sub-common, then use device link between the smi-sub-common with smi-common. This is for enabling clock/power automatically. Move the device link code to a new interface for reusing. Signed-off-by: Yong Wu Reviewed-by: Ikjoon Jang Link: https://lore.kernel.org/r/20210914113703.31466-8-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 75 +++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index b362d528944e..5c2bd5795cfd 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -61,7 +61,8 @@ enum mtk_smi_type { MTK_SMI_GEN1, - MTK_SMI_GEN2 + MTK_SMI_GEN2, /* gen2 smi common */ + MTK_SMI_GEN2_SUB_COMM, /* gen2 smi sub common */ }; #define MTK_SMI_CLK_NR_MAX 4 @@ -99,13 +100,14 @@ struct mtk_smi { void __iomem *smi_ao_base; /* only for gen1 */ void __iomem *base; /* only for gen2 */ }; + struct device *smi_common_dev; /* for sub common */ const struct mtk_smi_common_plat *plat; }; struct mtk_smi_larb { /* larb: local arbiter */ struct mtk_smi smi; void __iomem *base; - struct device *smi_common_dev; + struct device *smi_common_dev; /* common or sub-common dev */ const struct mtk_smi_larb_gen *larb_gen; int larbid; u32 *mmu; @@ -268,6 +270,38 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = { {} }; +static int mtk_smi_device_link_common(struct device *dev, struct device **com_dev) +{ + struct platform_device *smi_com_pdev; + struct device_node *smi_com_node; + struct device *smi_com_dev; + struct device_link *link; + + smi_com_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0); + if (!smi_com_node) + return -EINVAL; + + smi_com_pdev = of_find_device_by_node(smi_com_node); + of_node_put(smi_com_node); + if (smi_com_pdev) { + /* smi common is the supplier, Make sure it is ready before */ + if (!platform_get_drvdata(smi_com_pdev)) + return -EPROBE_DEFER; + smi_com_dev = &smi_com_pdev->dev; + link = device_link_add(dev, smi_com_dev, + DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS); + if (!link) { + dev_err(dev, "Unable to link smi-common dev\n"); + return -ENODEV; + } + *com_dev = smi_com_dev; + } else { + dev_err(dev, "Failed to get the smi_common device\n"); + return -EINVAL; + } + return 0; +} + static int mtk_smi_dts_clk_init(struct device *dev, struct mtk_smi *smi, const char * const clks[], unsigned int clk_nr_required, @@ -294,9 +328,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev) struct mtk_smi_larb *larb; struct resource *res; struct device *dev = &pdev->dev; - struct device_node *smi_node; - struct platform_device *smi_pdev; - struct device_link *link; int ret; larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL); @@ -315,26 +346,10 @@ static int mtk_smi_larb_probe(struct platform_device *pdev) return ret; larb->smi.dev = dev; - smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0); - if (!smi_node) - return -EINVAL; - smi_pdev = of_find_device_by_node(smi_node); - of_node_put(smi_node); - if (smi_pdev) { - if (!platform_get_drvdata(smi_pdev)) - return -EPROBE_DEFER; - larb->smi_common_dev = &smi_pdev->dev; - link = device_link_add(dev, larb->smi_common_dev, - DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS); - if (!link) { - dev_err(dev, "Unable to link smi-common dev\n"); - return -ENODEV; - } - } else { - dev_err(dev, "Failed to get the smi_common device\n"); - return -EINVAL; - } + ret = mtk_smi_device_link_common(dev, &larb->smi_common_dev); + if (ret < 0) + return ret; pm_runtime_enable(dev); platform_set_drvdata(pdev, larb); @@ -483,6 +498,14 @@ static int mtk_smi_common_probe(struct platform_device *pdev) if (IS_ERR(common->base)) return PTR_ERR(common->base); } + + /* link its smi-common if this is smi-sub-common */ + if (common->plat->type == MTK_SMI_GEN2_SUB_COMM) { + ret = mtk_smi_device_link_common(dev, &common->smi_common_dev); + if (ret < 0) + return ret; + } + pm_runtime_enable(dev); platform_set_drvdata(pdev, common); return 0; @@ -490,6 +513,10 @@ static int mtk_smi_common_probe(struct platform_device *pdev) static int mtk_smi_common_remove(struct platform_device *pdev) { + struct mtk_smi *common = dev_get_drvdata(&pdev->dev); + + if (common->plat->type == MTK_SMI_GEN2_SUB_COMM) + device_link_remove(&pdev->dev, common->smi_common_dev); pm_runtime_disable(&pdev->dev); return 0; } From 3e4f74e0ea5a6a6d6d825fd7afd8a10afbd1152c Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:58 +0800 Subject: [PATCH 064/179] memory: mtk-smi: Add clocks for smi-sub-common SMI sub common only have one output port. thus it has only one gals clocks(gals0). then, smi-sub-common require the three clocks(apb/smi/gals0) in has_gals case. Signed-off-by: Yong Wu Link: https://lore.kernel.org/r/20210914113703.31466-9-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 5c2bd5795cfd..58d9f7667490 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -74,10 +74,12 @@ static const char * const mtk_smi_larb_clks[] = {"apb", "smi", "gals"}; /* * common: Require these four clocks in has_gals case. Otherwise, only apb/smi are required. + * sub common: Require apb/smi/gals0 clocks in has_gals case. Otherwise, only apb/smi are required. */ static const char * const mtk_smi_common_clks[] = {"apb", "smi", "gals0", "gals1"}; #define MTK_SMI_COM_REQ_CLK_NR 2 #define MTK_SMI_COM_GALS_REQ_CLK_NR MTK_SMI_CLK_NR_MAX +#define MTK_SMI_SUB_COM_GALS_REQ_CLK_NR 3 struct mtk_smi_common_plat { enum mtk_smi_type type; @@ -467,8 +469,12 @@ static int mtk_smi_common_probe(struct platform_device *pdev) common->dev = dev; common->plat = of_device_get_match_data(dev); - if (common->plat->has_gals) - clk_required = MTK_SMI_COM_GALS_REQ_CLK_NR; + if (common->plat->has_gals) { + if (common->plat->type == MTK_SMI_GEN2) + clk_required = MTK_SMI_COM_GALS_REQ_CLK_NR; + else if (common->plat->type == MTK_SMI_GEN2_SUB_COMM) + clk_required = MTK_SMI_SUB_COM_GALS_REQ_CLK_NR; + } ret = mtk_smi_dts_clk_init(dev, common, mtk_smi_common_clks, clk_required, 0); if (ret) return ret; From 912fea8bf8d854aef967c82a279ffd20be0326d7 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:36:59 +0800 Subject: [PATCH 065/179] memory: mtk-smi: Use devm_platform_ioremap_resource No functional change. Simplify probing code. Signed-off-by: Yong Wu Reviewed-by: Ikjoon Jang Link: https://lore.kernel.org/r/20210914113703.31466-10-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 58d9f7667490..a001e41f5074 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -328,7 +328,6 @@ static int mtk_smi_dts_clk_init(struct device *dev, struct mtk_smi *smi, static int mtk_smi_larb_probe(struct platform_device *pdev) { struct mtk_smi_larb *larb; - struct resource *res; struct device *dev = &pdev->dev; int ret; @@ -337,8 +336,7 @@ static int mtk_smi_larb_probe(struct platform_device *pdev) return -ENOMEM; larb->larb_gen = of_device_get_match_data(dev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - larb->base = devm_ioremap_resource(dev, res); + larb->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(larb->base)) return PTR_ERR(larb->base); @@ -460,7 +458,6 @@ static int mtk_smi_common_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mtk_smi *common; - struct resource *res; int ret, clk_required = MTK_SMI_COM_REQ_CLK_NR; common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL); @@ -486,8 +483,7 @@ static int mtk_smi_common_probe(struct platform_device *pdev) * base. */ if (common->plat->type == MTK_SMI_GEN1) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - common->smi_ao_base = devm_ioremap_resource(dev, res); + common->smi_ao_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(common->smi_ao_base)) return PTR_ERR(common->smi_ao_base); @@ -499,8 +495,7 @@ static int mtk_smi_common_probe(struct platform_device *pdev) if (ret) return ret; } else { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - common->base = devm_ioremap_resource(dev, res); + common->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(common->base)) return PTR_ERR(common->base); } From cc4f9dcd9c1543394d6ee0d635551a2bd96bcacb Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:37:00 +0800 Subject: [PATCH 066/179] memory: mtk-smi: mt8195: Add smi support MT8195 has two smi-common, their IP are the same. Only the larbs that connect with the smi-common are different. thus the bus_sel are different for the two smi-common. Signed-off-by: Yong Wu Reviewed-by: Ikjoon Jang Link: https://lore.kernel.org/r/20210914113703.31466-11-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index a001e41f5074..35853ba980c9 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -261,6 +261,10 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = { .config_port = mtk_smi_larb_config_port_gen2_general, }; +static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = { + .config_port = mtk_smi_larb_config_port_gen2_general, +}; + static const struct of_device_id mtk_smi_larb_of_ids[] = { {.compatible = "mediatek,mt2701-smi-larb", .data = &mtk_smi_larb_mt2701}, {.compatible = "mediatek,mt2712-smi-larb", .data = &mtk_smi_larb_mt2712}, @@ -269,6 +273,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,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192}, + {.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195}, {} }; @@ -443,6 +448,24 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = { F_MMU1_LARB(6), }; +static const struct mtk_smi_common_plat mtk_smi_common_mt8195_vdo = { + .type = MTK_SMI_GEN2, + .has_gals = true, + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(3) | F_MMU1_LARB(5) | + F_MMU1_LARB(7), +}; + +static const struct mtk_smi_common_plat mtk_smi_common_mt8195_vpp = { + .type = MTK_SMI_GEN2, + .has_gals = true, + .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(7), +}; + +static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8195 = { + .type = MTK_SMI_GEN2_SUB_COMM, + .has_gals = true, +}; + static const struct of_device_id mtk_smi_common_of_ids[] = { {.compatible = "mediatek,mt2701-smi-common", .data = &mtk_smi_common_gen1}, {.compatible = "mediatek,mt2712-smi-common", .data = &mtk_smi_common_gen2}, @@ -451,6 +474,9 @@ 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,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}, + {.compatible = "mediatek,mt8195-smi-sub-common", .data = &mtk_smi_sub_common_mt8195}, {} }; From 431e9cab7097b5d5eb3cf2b04d4b12d272df85e0 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:37:01 +0800 Subject: [PATCH 067/179] memory: mtk-smi: mt8195: Add initial setting for smi-common To improve the performance, add initial setting for smi-common. some register use some fix setting(suggested from DE). Signed-off-by: Yong Wu Link: https://lore.kernel.org/r/20210914113703.31466-12-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 42 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 35853ba980c9..689a45b39a65 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -18,11 +18,19 @@ #include /* SMI COMMON */ +#define SMI_L1LEN 0x100 + #define SMI_BUS_SEL 0x220 #define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1) /* All are MMU0 defaultly. Only specialize mmu1 here. */ #define F_MMU1_LARB(larbid) (0x1 << SMI_BUS_LARB_SHIFT(larbid)) +#define SMI_M4U_TH 0x234 +#define SMI_FIFO_TH1 0x238 +#define SMI_FIFO_TH2 0x23c +#define SMI_DCM 0x300 +#define SMI_DUMMY 0x444 + /* SMI LARB */ /* Below are about mmu enable registers, they are different in SoCs */ @@ -59,6 +67,13 @@ (_id << 8 | _id << 10 | _id << 12 | _id << 14); \ }) +#define SMI_COMMON_INIT_REGS_NR 6 + +struct mtk_smi_reg_pair { + unsigned int offset; + u32 value; +}; + enum mtk_smi_type { MTK_SMI_GEN1, MTK_SMI_GEN2, /* gen2 smi common */ @@ -85,6 +100,8 @@ struct mtk_smi_common_plat { enum mtk_smi_type type; bool has_gals; u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */ + + const struct mtk_smi_reg_pair *init; }; struct mtk_smi_larb_gen { @@ -419,6 +436,15 @@ static struct platform_driver mtk_smi_larb_driver = { } }; +static const struct mtk_smi_reg_pair mtk_smi_common_mt8195_init[SMI_COMMON_INIT_REGS_NR] = { + {SMI_L1LEN, 0xb}, + {SMI_M4U_TH, 0xe100e10}, + {SMI_FIFO_TH1, 0x506090a}, + {SMI_FIFO_TH2, 0x506090a}, + {SMI_DCM, 0x4f1}, + {SMI_DUMMY, 0x1}, +}; + static const struct mtk_smi_common_plat mtk_smi_common_gen1 = { .type = MTK_SMI_GEN1, }; @@ -453,12 +479,14 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8195_vdo = { .has_gals = true, .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(3) | F_MMU1_LARB(5) | F_MMU1_LARB(7), + .init = mtk_smi_common_mt8195_init, }; static const struct mtk_smi_common_plat mtk_smi_common_mt8195_vpp = { .type = MTK_SMI_GEN2, .has_gals = true, .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_sub_common_mt8195 = { @@ -551,15 +579,21 @@ static int mtk_smi_common_remove(struct platform_device *pdev) static int __maybe_unused mtk_smi_common_resume(struct device *dev) { struct mtk_smi *common = dev_get_drvdata(dev); - u32 bus_sel = common->plat->bus_sel; - int ret; + const struct mtk_smi_reg_pair *init = common->plat->init; + u32 bus_sel = common->plat->bus_sel; /* default is 0 */ + int ret, i; ret = clk_bulk_prepare_enable(common->clk_num, common->clks); if (ret) return ret; - if (common->plat->type == MTK_SMI_GEN2 && bus_sel) - writel(bus_sel, common->base + SMI_BUS_SEL); + if (common->plat->type != MTK_SMI_GEN2) + return 0; + + for (i = 0; i < SMI_COMMON_INIT_REGS_NR && init && init[i].offset; i++) + writel_relaxed(init[i].value, common->base + init[i].offset); + + writel(bus_sel, common->base + SMI_BUS_SEL); return 0; } From fe6dd2a4017d3dfbf4a530d95270a1d498a16a4c Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:37:02 +0800 Subject: [PATCH 068/179] memory: mtk-smi: mt8195: Add initial setting for smi-larb To improve the performance, We add some initial setting for smi larbs. there are two part: 1), Each port has the special ostd(outstanding) value in each larb. 2), Two general settings for each larb. a. THRT_UPDATE: the value in bits[7:4] of 0x24 is not so good. The HW default is 4, and we expect it is 5, thus, add a flag to update it. This is only a DE recommendatory value, not a actual issue. The register name(THRT_CON) means: throttling control, and the field RD_NU_LMT means: Read Non-ultra commands limit. This change means update the Read non-ultra command from 4 to 5 here. b. SW_FLAG: Set 1 to the FLAG register. this is only for helping debug. We could confirm if the larb is reset from this value is 1 or 0. In some SoC, this setting maybe changed dynamically for some special case like 4K, and this initial setting is enough in mt8195. Signed-off-by: Yong Wu Link: https://lore.kernel.org/r/20210914113703.31466-13-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/mtk-smi.c | 79 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 689a45b39a65..b883dcc0bbfa 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -32,6 +32,15 @@ #define SMI_DUMMY 0x444 /* SMI LARB */ +#define SMI_LARB_CMD_THRT_CON 0x24 +#define SMI_LARB_THRT_RD_NU_LMT_MSK GENMASK(7, 4) +#define SMI_LARB_THRT_RD_NU_LMT (5 << 4) + +#define SMI_LARB_SW_FLAG 0x40 +#define SMI_LARB_SW_FLAG_1 0x1 + +#define SMI_LARB_OSTDL_PORT 0x200 +#define SMI_LARB_OSTDL_PORTx(id) (SMI_LARB_OSTDL_PORT + (((id) & 0x1f) << 2)) /* Below are about mmu enable registers, they are different in SoCs */ /* gen1: mt2701 */ @@ -68,6 +77,11 @@ }) #define SMI_COMMON_INIT_REGS_NR 6 +#define SMI_LARB_PORT_NR_MAX 32 + +#define MTK_SMI_FLAG_THRT_UPDATE BIT(0) +#define MTK_SMI_FLAG_SW_FLAG BIT(1) +#define MTK_SMI_CAPS(flags, _x) (!!((flags) & (_x))) struct mtk_smi_reg_pair { unsigned int offset; @@ -108,6 +122,8 @@ struct mtk_smi_larb_gen { int port_in_larb[MTK_LARB_NR_MAX + 1]; void (*config_port)(struct device *dev); unsigned int larb_direct_to_common_mask; + unsigned int flags_general; + const u8 (*ostd)[SMI_LARB_PORT_NR_MAX]; }; struct mtk_smi { @@ -224,12 +240,26 @@ static void mtk_smi_larb_config_port_mt8173(struct device *dev) static void mtk_smi_larb_config_port_gen2_general(struct device *dev) { struct mtk_smi_larb *larb = dev_get_drvdata(dev); - u32 reg; + u32 reg, flags_general = larb->larb_gen->flags_general; + const u8 *larbostd = larb->larb_gen->ostd[larb->larbid]; int i; if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask) return; + if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_THRT_UPDATE)) { + reg = readl_relaxed(larb->base + SMI_LARB_CMD_THRT_CON); + reg &= ~SMI_LARB_THRT_RD_NU_LMT_MSK; + reg |= SMI_LARB_THRT_RD_NU_LMT; + writel_relaxed(reg, larb->base + SMI_LARB_CMD_THRT_CON); + } + + if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_SW_FLAG)) + writel_relaxed(SMI_LARB_SW_FLAG_1, larb->base + SMI_LARB_SW_FLAG); + + for (i = 0; i < SMI_LARB_PORT_NR_MAX && larbostd && !!larbostd[i]; i++) + writel_relaxed(larbostd[i], larb->base + SMI_LARB_OSTDL_PORTx(i)); + for_each_set_bit(i, (unsigned long *)larb->mmu, 32) { reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i)); reg |= F_MMU_EN; @@ -238,6 +268,51 @@ static void mtk_smi_larb_config_port_gen2_general(struct device *dev) } } +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 */ + [2] = {0x12, 0x12, 0x12, 0x12, 0x0a,}, /* ... */ + [3] = {0x12, 0x12, 0x12, 0x12, 0x28, 0x28, 0x0a,}, + [4] = {0x06, 0x01, 0x17, 0x06, 0x0a,}, + [5] = {0x06, 0x01, 0x17, 0x06, 0x06, 0x01, 0x06, 0x0a,}, + [6] = {0x06, 0x01, 0x06, 0x0a,}, + [7] = {0x0c, 0x0c, 0x12,}, + [8] = {0x0c, 0x0c, 0x12,}, + [9] = {0x0a, 0x08, 0x04, 0x06, 0x01, 0x01, 0x10, 0x18, 0x11, 0x0a, + 0x08, 0x04, 0x11, 0x06, 0x02, 0x06, 0x01, 0x11, 0x11, 0x06,}, + [10] = {0x18, 0x08, 0x01, 0x01, 0x20, 0x12, 0x18, 0x06, 0x05, 0x10, + 0x08, 0x08, 0x10, 0x08, 0x08, 0x18, 0x0c, 0x09, 0x0b, 0x0d, + 0x0d, 0x06, 0x10, 0x10,}, + [11] = {0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x01, 0x01, 0x01, 0x01,}, + [12] = {0x09, 0x09, 0x05, 0x05, 0x0c, 0x18, 0x02, 0x02, 0x04, 0x02,}, + [13] = {0x02, 0x02, 0x12, 0x12, 0x02, 0x02, 0x02, 0x02, 0x08, 0x01,}, + [14] = {0x12, 0x12, 0x02, 0x02, 0x02, 0x02, 0x16, 0x01, 0x16, 0x01, + 0x01, 0x02, 0x02, 0x08, 0x02,}, + [15] = {}, + [16] = {0x28, 0x02, 0x02, 0x12, 0x02, 0x12, 0x10, 0x02, 0x02, 0x0a, + 0x12, 0x02, 0x0a, 0x16, 0x02, 0x04,}, + [17] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,}, + [18] = {0x12, 0x06, 0x12, 0x06,}, + [19] = {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,}, + [20] = {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,}, + [21] = {0x28, 0x19, 0x0c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,}, + [22] = {0x28, 0x19, 0x0c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,}, + [23] = {0x18, 0x01,}, + [24] = {0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, + 0x01, 0x01,}, + [25] = {0x02, 0x02, 0x02, 0x28, 0x16, 0x02, 0x02, 0x02, 0x12, 0x16, + 0x02, 0x01,}, + [26] = {0x02, 0x02, 0x02, 0x28, 0x16, 0x02, 0x02, 0x02, 0x12, 0x16, + 0x02, 0x01,}, + [27] = {0x02, 0x02, 0x02, 0x28, 0x16, 0x02, 0x02, 0x02, 0x12, 0x16, + 0x02, 0x01,}, + [28] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,}, +}; + static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = { .port_in_larb = { LARB0_PORT_OFFSET, LARB1_PORT_OFFSET, @@ -280,6 +355,8 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = { static const struct mtk_smi_larb_gen mtk_smi_larb_mt8195 = { .config_port = mtk_smi_larb_config_port_gen2_general, + .flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG, + .ostd = mtk_smi_larb_mt8195_ostd, }; static const struct of_device_id mtk_smi_larb_of_ids[] = { From 93403ede5aa4edeec2c63541b185d9c4fc9ae1e4 Mon Sep 17 00:00:00 2001 From: Yong Wu Date: Tue, 14 Sep 2021 19:37:03 +0800 Subject: [PATCH 069/179] MAINTAINERS: Add entry for MediaTek SMI I am the author of MediaTek SMI driver, and will to maintain and develop it further. Add myself to cover these items. Signed-off-by: Yong Wu Link: https://lore.kernel.org/r/20210914113703.31466-14-yong.wu@mediatek.com Signed-off-by: Krzysztof Kozlowski --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index eeb4c70b3d5b..52b956fedfbc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11865,6 +11865,14 @@ M: Sean Wang S: Maintained F: drivers/char/hw_random/mtk-rng.c +MEDIATEK SMI DRIVER +M: Yong Wu +L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) +S: Supported +F: Documentation/devicetree/bindings/memory-controllers/mediatek,smi* +F: drivers/memory/mtk-smi.c +F: include/soc/mediatek/smi.h + MEDIATEK SWITCH DRIVER M: Sean Wang M: Landen Chao From 1a561c521ba901ac86acaf698e79ad6ecedbec2b Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Tue, 21 Sep 2021 16:04:27 +0530 Subject: [PATCH 070/179] soc: qcom: smp2p: Add wakeup capability to SMP2P IRQ Remote susbsystems notify fatal crash through smp2p interrupt. When remoteproc crashes it can cause soc to come out of low power state and may not allow again to enter in low power state until crash is handled. Mark smp2p interrupt wakeup capable so that interrupt handler is executed and remoteproc crash can be handled in system resume path. This patch marks interrupt wakeup capable but keeps wakeup disabled by default. User space can enable it based on its requirement for wakeup from suspend. Signed-off-by: Deepak Kumar Singh Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1632220467-27410-1-git-send-email-deesin@codeaurora.org --- drivers/soc/qcom/smp2p.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index 2df488333be9..38585a7edfe7 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -538,9 +539,26 @@ static int qcom_smp2p_probe(struct platform_device *pdev) goto unwind_interfaces; } + /* + * Treat smp2p interrupt as wakeup source, but keep it disabled + * by default. User space can decide enabling it depending on its + * use cases. For example if remoteproc crashes and device wants + * to handle it immediatedly (e.g. to not miss phone calls) it can + * enable wakeup source from user space, while other devices which + * do not have proper autosleep feature may want to handle it with + * other wakeup events (e.g. Power button) instead waking up immediately. + */ + device_set_wakeup_capable(&pdev->dev, true); + + ret = dev_pm_set_wake_irq(&pdev->dev, irq); + if (ret) + goto set_wake_irq_fail; return 0; +set_wake_irq_fail: + dev_pm_clear_wake_irq(&pdev->dev); + unwind_interfaces: list_for_each_entry(entry, &smp2p->inbound, node) irq_domain_remove(entry->domain); @@ -565,6 +583,8 @@ static int qcom_smp2p_remove(struct platform_device *pdev) struct qcom_smp2p *smp2p = platform_get_drvdata(pdev); struct smp2p_entry *entry; + dev_pm_clear_wake_irq(&pdev->dev); + list_for_each_entry(entry, &smp2p->inbound, node) irq_domain_remove(entry->domain); From 1d8e0223bb52071ffc59391f0ebefa06ce5643d7 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 22 Sep 2021 21:00:01 +0800 Subject: [PATCH 071/179] memory: tegra: Make use of the helper function devm_add_action_or_reset() Use devm_add_action_or_reset() instead of devm_add_action() to simplify the error handling. Signed-off-by: Cai Huoqing Link: https://lore.kernel.org/r/20210922130002.586-1-caihuoqing@baidu.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/mc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 6b710c204799..44b4a4080920 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -87,11 +87,9 @@ struct tegra_mc *devm_tegra_memory_controller_get(struct device *dev) return ERR_PTR(-EPROBE_DEFER); } - err = devm_add_action(dev, tegra_mc_devm_action_put_device, mc); - if (err) { - put_device(mc->dev); + err = devm_add_action_or_reset(dev, tegra_mc_devm_action_put_device, mc); + if (err) return ERR_PTR(err); - } return mc; } From 797f082738b10ff397c8d3b7804b747d766e62e6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 22 Sep 2021 10:58:31 +0200 Subject: [PATCH 072/179] dt-bindings: rpc: renesas-rpc-if: Add support for the R8A779A0 RPC-IF Add bindings for the R8A779A0 (R-Car V3U). Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210922085831.5375-1-wsa+renesas@sang-engineering.com Signed-off-by: Krzysztof Kozlowski --- .../devicetree/bindings/memory-controllers/renesas,rpc-if.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml index d25072c414e4..9da80e8f2444 100644 --- a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml @@ -33,6 +33,7 @@ properties: - renesas,r8a77970-rpc-if # R-Car V3M - renesas,r8a77980-rpc-if # R-Car V3H - renesas,r8a77995-rpc-if # R-Car D3 + - renesas,r8a779a0-rpc-if # R-Car V3U - const: renesas,rcar-gen3-rpc-if # a generic R-Car gen3 or RZ/G2 device reg: From a4fe5159038f22604e9ef3a8c38b680db4456138 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 16 Sep 2021 19:29:18 +0530 Subject: [PATCH 073/179] dt-bindings: soc: qcom: aoss: Drop the load state power-domain The power-domains exposed by AOSS QMP node are used to notify the Always on Subsystem (AOSS) that a particular co-processor is up/down. These co-processors enter low-power modes independent to that of the application processor and their states are expected to remain unaltered across system suspend/resume cycles. To achieve this behavior let's drop the load power-domain and replace them with generic qmp_send interface instead. Signed-off-by: Sibi Sankar Reviewed-by: Matthias Kaehlcke Reviewed-by: Stephen Boyd Acked-by: Rob Herring Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1631800770-371-2-git-send-email-sibis@codeaurora.org --- .../devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml index 1904612fad85..e2e173dfada7 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml @@ -19,8 +19,7 @@ description: The AOSS side channel exposes control over a set of resources, used to control a set of debug related clocks and to affect the low power state of resources - related to the secondary subsystems. These resources are exposed as a set of - power-domains. + related to the secondary subsystems. properties: compatible: @@ -58,13 +57,6 @@ properties: description: The single clock represents the QDSS clock. - "#power-domain-cells": - const: 1 - description: | - The provided power-domains are: - CDSP state (0), LPASS state (1), modem state (2), SLPI - state (3), SPSS state (4) and Venus state (5). - required: - compatible - reg @@ -102,7 +94,6 @@ examples: mboxes = <&apss_shared 0>; #clock-cells = <0>; - #power-domain-cells = <1>; cx_cdev: cx { #cooling-cells = <2>; From 99512191f4f1dd4e0ad92e6f61ffe4d8a22aa3ba Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 16 Sep 2021 19:29:28 +0530 Subject: [PATCH 074/179] soc: qcom: aoss: Drop power domain support Strip out the load state power-domain support from the driver since the low power mode signalling for the co-processors is now accessible through the direct qmp message send interface. Signed-off-by: Sibi Sankar Reviewed-by: Matthias Kaehlcke Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1631800770-371-12-git-send-email-sibis@codeaurora.org --- drivers/soc/qcom/qcom_aoss.c | 107 ----------------------------------- 1 file changed, 107 deletions(-) diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index aac36f0b58e4..34acf58bbb0d 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -2,7 +2,6 @@ /* * Copyright (c) 2019, Linaro Ltd */ -#include #include #include #include @@ -10,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -66,7 +64,6 @@ struct qmp_cooling_device { * @event: wait_queue for synchronization with the IRQ * @tx_lock: provides synchronization between multiple callers of qmp_send() * @qdss_clk: QDSS clock hw struct - * @pd_data: genpd data * @cooling_devs: thermal cooling devices */ struct qmp { @@ -84,17 +81,9 @@ struct qmp { struct mutex tx_lock; struct clk_hw qdss_clk; - struct genpd_onecell_data pd_data; struct qmp_cooling_device *cooling_devs; }; -struct qmp_pd { - struct qmp *qmp; - struct generic_pm_domain pd; -}; - -#define to_qmp_pd_resource(res) container_of(res, struct qmp_pd, pd) - static void qmp_kick(struct qmp *qmp) { mbox_send_message(qmp->mbox_chan, NULL); @@ -320,95 +309,6 @@ static void qmp_qdss_clk_remove(struct qmp *qmp) clk_hw_unregister(&qmp->qdss_clk); } -static int qmp_pd_power_toggle(struct qmp_pd *res, bool enable) -{ - char buf[QMP_MSG_LEN] = {}; - - snprintf(buf, sizeof(buf), - "{class: image, res: load_state, name: %s, val: %s}", - res->pd.name, enable ? "on" : "off"); - return qmp_send(res->qmp, buf, sizeof(buf)); -} - -static int qmp_pd_power_on(struct generic_pm_domain *domain) -{ - return qmp_pd_power_toggle(to_qmp_pd_resource(domain), true); -} - -static int qmp_pd_power_off(struct generic_pm_domain *domain) -{ - return qmp_pd_power_toggle(to_qmp_pd_resource(domain), false); -} - -static const char * const sdm845_resources[] = { - [AOSS_QMP_LS_CDSP] = "cdsp", - [AOSS_QMP_LS_LPASS] = "adsp", - [AOSS_QMP_LS_MODEM] = "modem", - [AOSS_QMP_LS_SLPI] = "slpi", - [AOSS_QMP_LS_SPSS] = "spss", - [AOSS_QMP_LS_VENUS] = "venus", -}; - -static int qmp_pd_add(struct qmp *qmp) -{ - struct genpd_onecell_data *data = &qmp->pd_data; - struct device *dev = qmp->dev; - struct qmp_pd *res; - size_t num = ARRAY_SIZE(sdm845_resources); - int ret; - int i; - - res = devm_kcalloc(dev, num, sizeof(*res), GFP_KERNEL); - if (!res) - return -ENOMEM; - - data->domains = devm_kcalloc(dev, num, sizeof(*data->domains), - GFP_KERNEL); - if (!data->domains) - return -ENOMEM; - - for (i = 0; i < num; i++) { - res[i].qmp = qmp; - res[i].pd.name = sdm845_resources[i]; - res[i].pd.power_on = qmp_pd_power_on; - res[i].pd.power_off = qmp_pd_power_off; - - ret = pm_genpd_init(&res[i].pd, NULL, true); - if (ret < 0) { - dev_err(dev, "failed to init genpd\n"); - goto unroll_genpds; - } - - data->domains[i] = &res[i].pd; - } - - data->num_domains = i; - - ret = of_genpd_add_provider_onecell(dev->of_node, data); - if (ret < 0) - goto unroll_genpds; - - return 0; - -unroll_genpds: - for (i--; i >= 0; i--) - pm_genpd_remove(data->domains[i]); - - return ret; -} - -static void qmp_pd_remove(struct qmp *qmp) -{ - struct genpd_onecell_data *data = &qmp->pd_data; - struct device *dev = qmp->dev; - int i; - - of_genpd_del_provider(dev->of_node); - - for (i = 0; i < data->num_domains; i++) - pm_genpd_remove(data->domains[i]); -} - static int qmp_cdev_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state) { @@ -612,10 +512,6 @@ static int qmp_probe(struct platform_device *pdev) if (ret) goto err_close_qmp; - ret = qmp_pd_add(qmp); - if (ret) - goto err_remove_qdss_clk; - ret = qmp_cooling_devices_register(qmp); if (ret) dev_err(&pdev->dev, "failed to register aoss cooling devices\n"); @@ -624,8 +520,6 @@ static int qmp_probe(struct platform_device *pdev) return 0; -err_remove_qdss_clk: - qmp_qdss_clk_remove(qmp); err_close_qmp: qmp_close(qmp); err_free_mbox: @@ -639,7 +533,6 @@ static int qmp_remove(struct platform_device *pdev) struct qmp *qmp = platform_get_drvdata(pdev); qmp_qdss_clk_remove(qmp); - qmp_pd_remove(qmp); qmp_cooling_devices_remove(qmp); qmp_close(qmp); From ec908595825ce84fb40e94a68b378f13c65076af Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 16 Sep 2021 19:29:29 +0530 Subject: [PATCH 075/179] dt-bindings: msm/dp: Remove aoss-qmp header Remove the unused aoss-qmp header from the list of includes. Signed-off-by: Sibi Sankar Acked-by: Rob Herring Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1631800770-371-13-git-send-email-sibis@codeaurora.org --- Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 64d8d9e5e47a..d89b3c510c27 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -95,7 +95,6 @@ examples: - | #include #include - #include #include displayport-controller@ae90000 { From e603577231d4d041eceeaf23c25935df5d008798 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 16 Sep 2021 19:29:30 +0530 Subject: [PATCH 076/179] dt-bindings: soc: qcom: aoss: Delete unused power-domain definitions Delete unused power-domain definitions exposed by AOSS QMP. Signed-off-by: Sibi Sankar Reviewed-by: Stephen Boyd Acked-by: Rob Herring Reviewed-by: Matthias Kaehlcke Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/1631800770-371-14-git-send-email-sibis@codeaurora.org --- include/dt-bindings/power/qcom-aoss-qmp.h | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 include/dt-bindings/power/qcom-aoss-qmp.h diff --git a/include/dt-bindings/power/qcom-aoss-qmp.h b/include/dt-bindings/power/qcom-aoss-qmp.h deleted file mode 100644 index ec336d31dee4..000000000000 --- a/include/dt-bindings/power/qcom-aoss-qmp.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2018, Linaro Ltd. */ - -#ifndef __DT_BINDINGS_POWER_QCOM_AOSS_QMP_H -#define __DT_BINDINGS_POWER_QCOM_AOSS_QMP_H - -#define AOSS_QMP_LS_CDSP 0 -#define AOSS_QMP_LS_LPASS 1 -#define AOSS_QMP_LS_MODEM 2 -#define AOSS_QMP_LS_SLPI 3 -#define AOSS_QMP_LS_SPSS 4 -#define AOSS_QMP_LS_VENUS 5 - -#endif From 707a4cdf86e5d6a2c4fad51fb98a6ff3425f820e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 24 Sep 2021 12:10:34 -0700 Subject: [PATCH 077/179] bus: brcmstb_gisb: Allow building as module Allow building the Broadcom STB GISB arbiter driver as a module, however similar to interrupt controller drivers, don't allow its unbind/removal since it is not quite prepared for that and we want it to catch bus errors all the time. Signed-off-by: Florian Fainelli --- drivers/bus/Kconfig | 2 +- drivers/bus/brcmstb_gisb.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index a5b96f3aad67..9cfeae3fc244 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -30,7 +30,7 @@ config ARM_INTEGRATOR_LM found on the ARM Integrator AP (Application Platform) config BRCMSTB_GISB_ARB - bool "Broadcom STB GISB bus arbiter" + tristate "Broadcom STB GISB bus arbiter" depends on ARM || ARM64 || MIPS default ARCH_BRCMSTB || BMIPS_GENERIC help diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c index 6551286a60cc..4c2f7d61cb9b 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2014-2017 Broadcom + * Copyright (C) 2014-2021 Broadcom */ #include @@ -536,6 +536,7 @@ static struct platform_driver brcmstb_gisb_arb_driver = { .name = "brcm-gisb-arb", .of_match_table = brcmstb_gisb_arb_of_match, .pm = &brcmstb_gisb_arb_pm_ops, + .suppress_bind_attrs = true, }, }; @@ -546,3 +547,7 @@ static int __init brcm_gisb_driver_init(void) } module_init(brcm_gisb_driver_init); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("Broadcom STB GISB arbiter driver"); +MODULE_LICENSE("GPL v2"); From fff53a551db50f5edecaa0b29a64056ab8d2bbca Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 22 Sep 2021 11:10:06 +0200 Subject: [PATCH 078/179] memory: renesas-rpc-if: Correct QSPI data transfer in Manual mode This patch fixes 2 problems: [1] The output warning logs and data loss when performing mount/umount then remount the device with jffs2 format. [2] The access width of SMWDR[0:1]/SMRDR[0:1] register is wrong. This is the sample warning logs when performing mount/umount then remount the device with jffs2 format: jffs2: jffs2_scan_inode_node(): CRC failed on node at 0x031c51d4: Read 0x00034e00, calculated 0xadb272a7 The reason for issue [1] is that the writing data seems to get messed up. Data is only completed when the number of bytes is divisible by 4. If you only have 3 bytes of data left to write, 1 garbage byte is inserted after the end of the write stream. If you only have 2 bytes of data left to write, 2 bytes of '00' are added into the write stream. If you only have 1 byte of data left to write, 2 bytes of '00' are added into the write stream. 1 garbage byte is inserted after the end of the write stream. To solve problem [1], data must be written continuously in serial and the write stream ends when data is out. Following HW manual 62.2.15, access to SMWDR0 register should be in the same size as the transfer size specified in the SPIDE[3:0] bits in the manual mode enable setting register (SMENR). Be sure to access from address 0. So, in 16-bit transfer (SPIDE[3:0]=b'1100), SMWDR0 should be accessed by 16-bit width. Similar to SMWDR1, SMDDR0/1 registers. In current code, SMWDR0 register is accessed by regmap_write() that only set up to do 32-bit width. To solve problem [2], data must be written 16-bit or 8-bit when transferring 1-byte or 2-byte. Fixes: ca7d8b980b67 ("memory: add Renesas RPC-IF driver") Cc: Signed-off-by: Duc Nguyen [wsa: refactored to use regmap only via reg_read/reg_write] Signed-off-by: Wolfram Sang Tested-by: Lad Prabhakar Link: https://lore.kernel.org/r/20210922091007.5516-1-wsa+renesas@sang-engineering.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 113 ++++++++++++++++++++++---------- include/memory/renesas-rpc-if.h | 1 + 2 files changed, 79 insertions(+), 35 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 45eed659b0c6..77a011d5ff8c 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -160,10 +160,62 @@ static const struct regmap_access_table rpcif_volatile_table = { .n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges), }; + +/* + * Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed + * with proper width. Requires SMENR_SPIDE to be correctly set before! + */ +static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + struct rpcif *rpc = context; + + if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { + u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); + + if (spide == 0x8) { + *val = readb(rpc->base + reg); + return 0; + } else if (spide == 0xC) { + *val = readw(rpc->base + reg); + return 0; + } else if (spide != 0xF) { + return -EILSEQ; + } + } + + *val = readl(rpc->base + reg); + return 0; + +} + +static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val) +{ + struct rpcif *rpc = context; + + if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { + u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); + + if (spide == 0x8) { + writeb(val, rpc->base + reg); + return 0; + } else if (spide == 0xC) { + writew(val, rpc->base + reg); + return 0; + } else if (spide != 0xF) { + return -EILSEQ; + } + } + + writel(val, rpc->base + reg); + return 0; +} + static const struct regmap_config rpcif_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .reg_read = rpcif_reg_read, + .reg_write = rpcif_reg_write, .fast_io = true, .max_register = RPCIF_PHYINT, .volatile_table = &rpcif_volatile_table, @@ -173,17 +225,15 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct resource *res; - void __iomem *base; rpc->dev = dev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); + rpc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rpc->base)) + return PTR_ERR(rpc->base); - rpc->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &rpcif_regmap_config); + rpc->regmap = devm_regmap_init(&pdev->dev, NULL, rpc, &rpcif_regmap_config); if (IS_ERR(rpc->regmap)) { dev_err(&pdev->dev, "failed to init regmap for rpcif, error %ld\n", @@ -354,20 +404,16 @@ void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs, nbytes = op->data.nbytes; rpc->xferlen = nbytes; - rpc->enable |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)) | - RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth)); + rpc->enable |= RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth)); } } EXPORT_SYMBOL(rpcif_prepare); int rpcif_manual_xfer(struct rpcif *rpc) { - u32 smenr, smcr, pos = 0, max = 4; + u32 smenr, smcr, pos = 0, max = rpc->bus_size == 2 ? 8 : 4; int ret = 0; - if (rpc->bus_size == 2) - max = 8; - pm_runtime_get_sync(rpc->dev); regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, @@ -378,37 +424,36 @@ int rpcif_manual_xfer(struct rpcif *rpc) regmap_write(rpc->regmap, RPCIF_SMOPR, rpc->option); regmap_write(rpc->regmap, RPCIF_SMDMCR, rpc->dummy); regmap_write(rpc->regmap, RPCIF_SMDRENR, rpc->ddr); + regmap_write(rpc->regmap, RPCIF_SMADR, rpc->smadr); smenr = rpc->enable; switch (rpc->dir) { case RPCIF_DATA_OUT: while (pos < rpc->xferlen) { - u32 nbytes = rpc->xferlen - pos; - u32 data[2]; + u32 bytes_left = rpc->xferlen - pos; + u32 nbytes, data[2]; smcr = rpc->smcr | RPCIF_SMCR_SPIE; - if (nbytes > max) { - nbytes = max; + + /* nbytes may only be 1, 2, 4, or 8 */ + nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left)); + if (bytes_left > nbytes) smcr |= RPCIF_SMCR_SSLKP; - } + + smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); + regmap_write(rpc->regmap, RPCIF_SMENR, smenr); memcpy(data, rpc->buffer + pos, nbytes); - if (nbytes > 4) { + if (nbytes == 8) { regmap_write(rpc->regmap, RPCIF_SMWDR1, data[0]); regmap_write(rpc->regmap, RPCIF_SMWDR0, data[1]); - } else if (nbytes > 2) { + } else { regmap_write(rpc->regmap, RPCIF_SMWDR0, data[0]); - } else { - regmap_write(rpc->regmap, RPCIF_SMWDR0, - data[0] << 16); } - regmap_write(rpc->regmap, RPCIF_SMADR, - rpc->smadr + pos); - regmap_write(rpc->regmap, RPCIF_SMENR, smenr); regmap_write(rpc->regmap, RPCIF_SMCR, smcr); ret = wait_msg_xfer_end(rpc); if (ret) @@ -448,14 +493,16 @@ int rpcif_manual_xfer(struct rpcif *rpc) break; } while (pos < rpc->xferlen) { - u32 nbytes = rpc->xferlen - pos; - u32 data[2]; + u32 bytes_left = rpc->xferlen - pos; + u32 nbytes, data[2]; - if (nbytes > max) - nbytes = max; + /* nbytes may only be 1, 2, 4, or 8 */ + nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left)); regmap_write(rpc->regmap, RPCIF_SMADR, rpc->smadr + pos); + smenr &= ~RPCIF_SMENR_SPIDE(0xF); + smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); regmap_write(rpc->regmap, RPCIF_SMENR, smenr); regmap_write(rpc->regmap, RPCIF_SMCR, rpc->smcr | RPCIF_SMCR_SPIE); @@ -463,18 +510,14 @@ int rpcif_manual_xfer(struct rpcif *rpc) if (ret) goto err_out; - if (nbytes > 4) { + if (nbytes == 8) { regmap_read(rpc->regmap, RPCIF_SMRDR1, &data[0]); regmap_read(rpc->regmap, RPCIF_SMRDR0, &data[1]); - } else if (nbytes > 2) { + } else { regmap_read(rpc->regmap, RPCIF_SMRDR0, &data[0]); - } else { - regmap_read(rpc->regmap, RPCIF_SMRDR0, - &data[0]); - data[0] >>= 16; } memcpy(rpc->buffer + pos, data, nbytes); diff --git a/include/memory/renesas-rpc-if.h b/include/memory/renesas-rpc-if.h index e3e770f76f34..77c694a19149 100644 --- a/include/memory/renesas-rpc-if.h +++ b/include/memory/renesas-rpc-if.h @@ -59,6 +59,7 @@ struct rpcif_op { struct rpcif { struct device *dev; + void __iomem *base; void __iomem *dirmap; struct regmap *regmap; struct reset_control *rstc; From 1869023e24c0de73a160a424dac4621cefd628ae Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Wed, 22 Sep 2021 13:48:30 -0500 Subject: [PATCH 079/179] memory: renesas-rpc-if: Avoid unaligned bus access for HyperFlash HyperFlash devices in Renesas SoCs use 2-bytes addressing, according to HW manual paragraph 62.3.3 (which officially describes Serial Flash access, but seems to be applicable to HyperFlash too). And 1-byte bus read operations to 2-bytes unaligned addresses in external address space read mode work incorrectly (returns the other byte from the same word). Function memcpy_fromio(), used by the driver to read data from the bus, in ARM64 architecture (to which Renesas cores belong) uses 8-bytes bus accesses for appropriate aligned addresses, and 1-bytes accesses for other addresses. This results in incorrect data read from HyperFlash in unaligned cases. This issue can be reproduced using something like the following commands (where mtd1 is a parition on Hyperflash storage, defined properly in a device tree): [Correct fragment, read from Hyperflash] root@rcar-gen3:~# dd if=/dev/mtd1 of=/tmp/zz bs=32 count=1 root@rcar-gen3:~# hexdump -C /tmp/zz 00000000 f4 03 00 aa f5 03 01 aa f6 03 02 aa f7 03 03 aa |................| 00000010 00 00 80 d2 40 20 18 d5 00 06 81 d2 a0 18 a6 f2 |....@ ..........| 00000020 [Incorrect read of the same fragment: see the difference at offsets 8-11] root@rcar-gen3:~# dd if=/dev/mtd1 of=/tmp/zz bs=12 count=1 root@rcar-gen3:~# hexdump -C /tmp/zz 00000000 f4 03 00 aa f5 03 01 aa 03 03 aa aa |............| 0000000c Fix this issue by creating a local replacement of the copying function, that performs only properly aligned bus accesses, and is used for reading from HyperFlash. Fixes: ca7d8b980b67f ("memory: add Renesas RPC-IF driver") Cc: Signed-off-by: Andrew Gabbasov Link: https://lore.kernel.org/r/20210922184830.29147-1-andrew_gabbasov@mentor.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/renesas-rpc-if.c | 48 +++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 77a011d5ff8c..7435baad0007 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -185,7 +185,6 @@ static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val) *val = readl(rpc->base + reg); return 0; - } static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val) @@ -545,6 +544,48 @@ err_out: } EXPORT_SYMBOL(rpcif_manual_xfer); +static void memcpy_fromio_readw(void *to, + const void __iomem *from, + size_t count) +{ + const int maxw = (IS_ENABLED(CONFIG_64BIT)) ? 8 : 4; + u8 buf[2]; + + if (count && ((unsigned long)from & 1)) { + *(u16 *)buf = __raw_readw((void __iomem *)((unsigned long)from & ~1)); + *(u8 *)to = buf[1]; + from++; + to++; + count--; + } + while (count >= 2 && !IS_ALIGNED((unsigned long)from, maxw)) { + *(u16 *)to = __raw_readw(from); + from += 2; + to += 2; + count -= 2; + } + while (count >= maxw) { +#ifdef CONFIG_64BIT + *(u64 *)to = __raw_readq(from); +#else + *(u32 *)to = __raw_readl(from); +#endif + from += maxw; + to += maxw; + count -= maxw; + } + while (count >= 2) { + *(u16 *)to = __raw_readw(from); + from += 2; + to += 2; + count -= 2; + } + if (count) { + *(u16 *)buf = __raw_readw(from); + *(u8 *)to = buf[0]; + } +} + ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf) { loff_t from = offs & (RPCIF_DIRMAP_SIZE - 1); @@ -566,7 +607,10 @@ ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf) regmap_write(rpc->regmap, RPCIF_DRDMCR, rpc->dummy); regmap_write(rpc->regmap, RPCIF_DRDRENR, rpc->ddr); - memcpy_fromio(buf, rpc->dirmap + from, len); + if (rpc->bus_size == 2) + memcpy_fromio_readw(buf, rpc->dirmap + from, len); + else + memcpy_fromio(buf, rpc->dirmap + from, len); pm_runtime_put(rpc->dev); From 6b20a5d173cd5647f0bb1ac8796264b70c377d79 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Sep 2021 15:34:06 +0200 Subject: [PATCH 080/179] memory: samsung: describe drivers in KConfig Rephrase the Kconfig option and make it clear it applies only to Samsung SoC. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20210924133406.112174-1-krzysztof.kozlowski@canonical.com --- drivers/memory/samsung/Kconfig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/memory/samsung/Kconfig b/drivers/memory/samsung/Kconfig index 8e240f078afc..7fb70f573031 100644 --- a/drivers/memory/samsung/Kconfig +++ b/drivers/memory/samsung/Kconfig @@ -14,11 +14,12 @@ config EXYNOS5422_DMC depends on DEVFREQ_GOV_SIMPLE_ONDEMAND depends on (PM_DEVFREQ && PM_DEVFREQ_EVENT) help - This adds driver for Exynos5422 DMC (Dynamic Memory Controller). - The driver provides support for Dynamic Voltage and Frequency Scaling in - DMC and DRAM. It also supports changing timings of DRAM running with - different frequency. The timings are calculated based on DT memory - information. + This adds driver for Samsung Exynos5422 SoC DMC (Dynamic Memory + Controller). The driver provides support for Dynamic Voltage and + Frequency Scaling in DMC and DRAM. It also supports changing timings + of DRAM running with different frequency. The timings are calculated + based on DT memory information. + If unsure, say Y on devices with Samsung Exynos SoCs. config EXYNOS_SROM bool "Exynos SROM controller driver" if COMPILE_TEST @@ -29,6 +30,6 @@ config EXYNOS_SROM during suspend. If however appropriate device tree configuration is provided, the driver enables support for external memory or external devices. - If unsure, say Y on devices with Samsung Exynos SocS. + If unsure, say Y on devices with Samsung Exynos SoCs. endif From d1141886c8d72ad77920e6e4b617d366e6e3ee8a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 19 Sep 2021 11:31:12 +0200 Subject: [PATCH 081/179] soc: samsung: exynos-chipid: avoid soc_device_to_device() soc_device_to_device() seems to be discouraged [1] so remove it in favor of printing info message with platform device. This will only change the prefix in the info message from "soc soc0: " to "exynos-chipid 10000000.chipid:". [1] https://lore.kernel.org/lkml/20191111052741.GB3176397@kroah.com/ Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Tested-by: Sylwester Nawrocki Reviewed-by: Alim Akhtar Tested-by: Alim Akhtar Link: https://lore.kernel.org/r/20210919093114.35987-2-krzysztof.kozlowski@canonical.com --- drivers/soc/samsung/exynos-chipid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index 5c1d0f97f766..dcd9a08ce706 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -104,8 +104,7 @@ static int exynos_chipid_probe(struct platform_device *pdev) platform_set_drvdata(pdev, soc_dev); - dev_info(soc_device_to_device(soc_dev), - "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", + dev_info(&pdev->dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", soc_dev_attr->soc_id, product_id, revision); return 0; From 1e3e559f8d4e5b4c873414078facb35273ecbf4b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 19 Sep 2021 11:31:13 +0200 Subject: [PATCH 082/179] soc: samsung: exynos-chipid: convert to a module Exynos ChipID and ASV (Adaptive Supply Voltage) driver is not essential to system boot and it can successfully be built and loaded as module. This makes core kernel image smaller and reduces the memory footprint when multi-platform kernel is booted on non-Exynos board. Usually it is also distro-friendly. Add multiple authors of the driver since its conversion from mach-exynos, ordered alphabetically by first name. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Tested-by: Sylwester Nawrocki Reviewed-by: Alim Akhtar Tested-by: Alim Akhtar Link: https://lore.kernel.org/r/20210919093114.35987-3-krzysztof.kozlowski@canonical.com --- drivers/soc/samsung/Kconfig | 3 ++- drivers/soc/samsung/Makefile | 3 ++- drivers/soc/samsung/exynos-chipid.c | 11 ++++++++++- drivers/soc/samsung/exynos5422-asv.c | 1 + 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig index 1f643c0f5c93..fe139f26d093 100644 --- a/drivers/soc/samsung/Kconfig +++ b/drivers/soc/samsung/Kconfig @@ -13,13 +13,14 @@ config EXYNOS_ASV_ARM depends on EXYNOS_CHIPID config EXYNOS_CHIPID - bool "Exynos ChipID controller and ASV driver" if COMPILE_TEST + tristate "Exynos ChipID controller and ASV driver" if COMPILE_TEST depends on ARCH_EXYNOS || COMPILE_TEST select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS select MFD_SYSCON select SOC_BUS help Support for Samsung Exynos SoC ChipID and Adaptive Supply Voltage. + This driver can also be built as module (exynos_chipid). config EXYNOS_PMU bool "Exynos PMU controller driver" if COMPILE_TEST diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile index 0c523a8de4eb..2ae4bea804cf 100644 --- a/drivers/soc/samsung/Makefile +++ b/drivers/soc/samsung/Makefile @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_EXYNOS_ASV_ARM) += exynos5422-asv.o +obj-$(CONFIG_EXYNOS_CHIPID) += exynos_chipid.o +exynos_chipid-y += exynos-chipid.o exynos-asv.o -obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o exynos-asv.o obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \ diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index dcd9a08ce706..b2627a3a127a 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,7 @@ static const struct of_device_id exynos_chipid_of_device_ids[] = { { .compatible = "samsung,exynos4210-chipid" }, {} }; +MODULE_DEVICE_TABLE(of, exynos_chipid_of_device_ids); static struct platform_driver exynos_chipid_driver = { .driver = { @@ -137,4 +139,11 @@ static struct platform_driver exynos_chipid_driver = { .probe = exynos_chipid_probe, .remove = exynos_chipid_remove, }; -builtin_platform_driver(exynos_chipid_driver); +module_platform_driver(exynos_chipid_driver); + +MODULE_DESCRIPTION("Samsung Exynos ChipID controller and ASV driver"); +MODULE_AUTHOR("Bartlomiej Zolnierkiewicz "); +MODULE_AUTHOR("Krzysztof Kozlowski "); +MODULE_AUTHOR("Pankaj Dubey "); +MODULE_AUTHOR("Sylwester Nawrocki "); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/samsung/exynos5422-asv.c b/drivers/soc/samsung/exynos5422-asv.c index ca409a976e34..475ae5276529 100644 --- a/drivers/soc/samsung/exynos5422-asv.c +++ b/drivers/soc/samsung/exynos5422-asv.c @@ -503,3 +503,4 @@ int exynos5422_asv_init(struct exynos_asv *asv) return 0; } +EXPORT_SYMBOL_GPL(exynos5422_asv_init); From 140bbfe7cd4be0aa6543f94d3994e4774b325abc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 19 Sep 2021 11:31:14 +0200 Subject: [PATCH 083/179] soc: samsung: exynos-chipid: do not enforce built-in After converting the Exynos ChipID and ASV driver to a module, allow to actually choose it to be a module, while being a default built-in. The side effect is that driver could be now entirely disabled even for kernel with ARCH_EXYNOS, but this is not a critical issue because driver is not necessary for the proper platform boot. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Tested-by: Sylwester Nawrocki Reviewed-by: Alim Akhtar Tested-by: Alim Akhtar Link: https://lore.kernel.org/r/20210919093114.35987-4-krzysztof.kozlowski@canonical.com --- arch/arm/mach-exynos/Kconfig | 1 - drivers/soc/samsung/Kconfig | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 5a48abac6af4..30f930e20599 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -13,7 +13,6 @@ menuconfig ARCH_EXYNOS select ARM_GIC select EXYNOS_IRQ_COMBINER select COMMON_CLK_SAMSUNG - select EXYNOS_CHIPID select EXYNOS_THERMAL select EXYNOS_PMU select EXYNOS_SROM diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig index fe139f26d093..e2cedef1e8d1 100644 --- a/drivers/soc/samsung/Kconfig +++ b/drivers/soc/samsung/Kconfig @@ -13,8 +13,9 @@ config EXYNOS_ASV_ARM depends on EXYNOS_CHIPID config EXYNOS_CHIPID - tristate "Exynos ChipID controller and ASV driver" if COMPILE_TEST + tristate "Exynos ChipID controller and ASV driver" depends on ARCH_EXYNOS || COMPILE_TEST + default ARCH_EXYNOS select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS select MFD_SYSCON select SOC_BUS From 6ad4185220e6e3b7ebac7c7a5f55197aedd000da Mon Sep 17 00:00:00 2001 From: Will McVicker Date: Tue, 28 Sep 2021 23:56:18 +0000 Subject: [PATCH 084/179] arm64: exynos: don't have ARCH_EXYNOS select EXYNOS_CHIPID Now that EXYNOS_CHIPID can be a module and is enabled by default via ARCH_EXYNOS, we don't need to have ARCH_EXYNOS directly select it. So remove that. Signed-off-by: Will McVicker Link: https://lore.kernel.org/r/20210928235635.1348330-2-willmcvicker@google.com [krzysztof: the driver is not essential to boot and on ARMv7 it is also allowed to disable it] Signed-off-by: Krzysztof Kozlowski --- arch/arm64/Kconfig.platforms | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index b0ce18d4cc98..90c5cf4856e1 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -92,7 +92,6 @@ config ARCH_BRCMSTB config ARCH_EXYNOS bool "ARMv8 based Samsung Exynos SoC family" select COMMON_CLK_SAMSUNG - select EXYNOS_CHIPID select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS select EXYNOS_PMU select HAVE_S3C_RTC if RTC_CLASS From 13f995ceb4e0d669e293aedaaaea07e7b8a5792a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 23 Sep 2021 20:14:59 -0700 Subject: [PATCH 085/179] memory: brcmstb_dpfe: Allow building Broadcom STB DPFE as module Allow building the Broadcom STB DPFE driver as a module, it is already a platform driver proper with all of the resource releasing device managed. Signed-off-by: Florian Fainelli Acked-by: Markus Mayer Link: https://lore.kernel.org/r/20210924031459.8911-1-f.fainelli@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 72c0df129d5c..0ebb83b35a64 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -55,8 +55,8 @@ config ATMEL_EBI SRAMs, ATA devices, etc. config BRCMSTB_DPFE - bool "Broadcom STB DPFE driver" if COMPILE_TEST - default y if ARCH_BRCMSTB + tristate "Broadcom STB DPFE driver" + default ARCH_BRCMSTB depends on ARCH_BRCMSTB || COMPILE_TEST help This driver provides access to the DPFE interface of Broadcom From 34a01d9ea7c4981e19c9e926f5e293b011ecd5a3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 7 Sep 2021 04:38:29 +0200 Subject: [PATCH 086/179] soc: imx: gpcv2: Turn domain->pgc into bitfield There is currently the MX8MM GPU domain, which is in fact a composite domain for both GPU2D and GPU3D. To correctly configure this domain, it is necessary to control both GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) at the same time. This is currently not possible. Turn the domain->pgc from value into bitfield and use for_each_set_bit() to iterate over all bits set in domain->pgc when configuring GPC_PGC_nCTRL register array. This way it is possible to configure all GPC_PGC_nCTRL registers required in a particular domain. This is a preparatory patch, no functional change. Reviewed-by: Peng Fan Signed-off-by: Marek Vasut Cc: Frieder Schrempf Cc: Lucas Stach Cc: NXP Linux Team Cc: Peng Fan Cc: Shawn Guo Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 72 ++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 34a9ac1f2b9b..acd8734d960a 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -192,7 +192,7 @@ struct imx_pgc_domain { struct clk_bulk_data *clks; int num_clks; - unsigned int pgc; + unsigned long pgc; const struct { u32 pxx; @@ -220,7 +220,7 @@ to_imx_pgc_domain(struct generic_pm_domain *genpd) static int imx_pgc_power_up(struct generic_pm_domain *genpd) { struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd); - u32 reg_val; + u32 reg_val, pgc; int ret; ret = pm_runtime_get_sync(domain->dev); @@ -262,8 +262,10 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) } /* disable power control */ - regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), - GPC_PGC_CTRL_PCR); + for_each_set_bit(pgc, &domain->pgc, 32) { + regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc), + GPC_PGC_CTRL_PCR); + } } reset_control_assert(domain->reset); @@ -311,7 +313,7 @@ out_put_pm: static int imx_pgc_power_down(struct generic_pm_domain *genpd) { struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd); - u32 reg_val; + u32 reg_val, pgc; int ret; /* Enable reset clocks for all devices in the domain */ @@ -338,8 +340,10 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd) if (domain->bits.pxx) { /* enable power control */ - regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), - GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR); + for_each_set_bit(pgc, &domain->pgc, 32) { + regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc), + GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR); + } /* request the domain to power down */ regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ, @@ -389,7 +393,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = { .map = IMX7_MIPI_PHY_A_CORE_DOMAIN, }, .voltage = 1000000, - .pgc = IMX7_PGC_MIPI, + .pgc = BIT(IMX7_PGC_MIPI), }, [IMX7_POWER_DOMAIN_PCIE_PHY] = { @@ -401,7 +405,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = { .map = IMX7_PCIE_PHY_A_CORE_DOMAIN, }, .voltage = 1000000, - .pgc = IMX7_PGC_PCIE, + .pgc = BIT(IMX7_PGC_PCIE), }, [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = { @@ -413,7 +417,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = { .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN, }, .voltage = 1200000, - .pgc = IMX7_PGC_USB_HSIC, + .pgc = BIT(IMX7_PGC_USB_HSIC), }, }; @@ -448,7 +452,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .pxx = IMX8M_MIPI_SW_Pxx_REQ, .map = IMX8M_MIPI_A53_DOMAIN, }, - .pgc = IMX8M_PGC_MIPI, + .pgc = BIT(IMX8M_PGC_MIPI), }, [IMX8M_POWER_DOMAIN_PCIE1] = { @@ -459,7 +463,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .pxx = IMX8M_PCIE1_SW_Pxx_REQ, .map = IMX8M_PCIE1_A53_DOMAIN, }, - .pgc = IMX8M_PGC_PCIE1, + .pgc = BIT(IMX8M_PGC_PCIE1), }, [IMX8M_POWER_DOMAIN_USB_OTG1] = { @@ -470,7 +474,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .pxx = IMX8M_OTG1_SW_Pxx_REQ, .map = IMX8M_OTG1_A53_DOMAIN, }, - .pgc = IMX8M_PGC_OTG1, + .pgc = BIT(IMX8M_PGC_OTG1), }, [IMX8M_POWER_DOMAIN_USB_OTG2] = { @@ -481,7 +485,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .pxx = IMX8M_OTG2_SW_Pxx_REQ, .map = IMX8M_OTG2_A53_DOMAIN, }, - .pgc = IMX8M_PGC_OTG2, + .pgc = BIT(IMX8M_PGC_OTG2), }, [IMX8M_POWER_DOMAIN_DDR1] = { @@ -492,7 +496,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .pxx = IMX8M_DDR1_SW_Pxx_REQ, .map = IMX8M_DDR2_A53_DOMAIN, }, - .pgc = IMX8M_PGC_DDR1, + .pgc = BIT(IMX8M_PGC_DDR1), }, [IMX8M_POWER_DOMAIN_GPU] = { @@ -505,7 +509,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .hskreq = IMX8M_GPU_HSK_PWRDNREQN, .hskack = IMX8M_GPU_HSK_PWRDNACKN, }, - .pgc = IMX8M_PGC_GPU, + .pgc = BIT(IMX8M_PGC_GPU), }, [IMX8M_POWER_DOMAIN_VPU] = { @@ -518,7 +522,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .hskreq = IMX8M_VPU_HSK_PWRDNREQN, .hskack = IMX8M_VPU_HSK_PWRDNACKN, }, - .pgc = IMX8M_PGC_VPU, + .pgc = BIT(IMX8M_PGC_VPU), }, [IMX8M_POWER_DOMAIN_DISP] = { @@ -531,7 +535,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .hskreq = IMX8M_DISP_HSK_PWRDNREQN, .hskack = IMX8M_DISP_HSK_PWRDNACKN, }, - .pgc = IMX8M_PGC_DISP, + .pgc = BIT(IMX8M_PGC_DISP), }, [IMX8M_POWER_DOMAIN_MIPI_CSI1] = { @@ -542,7 +546,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ, .map = IMX8M_MIPI_CSI1_A53_DOMAIN, }, - .pgc = IMX8M_PGC_MIPI_CSI1, + .pgc = BIT(IMX8M_PGC_MIPI_CSI1), }, [IMX8M_POWER_DOMAIN_MIPI_CSI2] = { @@ -553,7 +557,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ, .map = IMX8M_MIPI_CSI2_A53_DOMAIN, }, - .pgc = IMX8M_PGC_MIPI_CSI2, + .pgc = BIT(IMX8M_PGC_MIPI_CSI2), }, [IMX8M_POWER_DOMAIN_PCIE2] = { @@ -564,7 +568,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .pxx = IMX8M_PCIE2_SW_Pxx_REQ, .map = IMX8M_PCIE2_A53_DOMAIN, }, - .pgc = IMX8M_PGC_PCIE2, + .pgc = BIT(IMX8M_PGC_PCIE2), }, }; @@ -627,7 +631,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .pxx = IMX8MM_PCIE_SW_Pxx_REQ, .map = IMX8MM_PCIE_A53_DOMAIN, }, - .pgc = IMX8MM_PGC_PCIE, + .pgc = BIT(IMX8MM_PGC_PCIE), }, [IMX8MM_POWER_DOMAIN_OTG1] = { @@ -638,7 +642,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .pxx = IMX8MM_OTG1_SW_Pxx_REQ, .map = IMX8MM_OTG1_A53_DOMAIN, }, - .pgc = IMX8MM_PGC_OTG1, + .pgc = BIT(IMX8MM_PGC_OTG1), }, [IMX8MM_POWER_DOMAIN_OTG2] = { @@ -649,7 +653,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .pxx = IMX8MM_OTG2_SW_Pxx_REQ, .map = IMX8MM_OTG2_A53_DOMAIN, }, - .pgc = IMX8MM_PGC_OTG2, + .pgc = BIT(IMX8MM_PGC_OTG2), }, [IMX8MM_POWER_DOMAIN_GPUMIX] = { @@ -662,7 +666,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN, .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN, }, - .pgc = IMX8MM_PGC_GPUMIX, + .pgc = BIT(IMX8MM_PGC_GPUMIX), }, [IMX8MM_POWER_DOMAIN_GPU] = { @@ -675,7 +679,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskreq = IMX8MM_GPU_HSK_PWRDNREQN, .hskack = IMX8MM_GPU_HSK_PWRDNACKN, }, - .pgc = IMX8MM_PGC_GPU2D, + .pgc = BIT(IMX8MM_PGC_GPU2D), }, [IMX8MM_POWER_DOMAIN_VPUMIX] = { @@ -688,7 +692,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN, .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN, }, - .pgc = IMX8MM_PGC_VPUMIX, + .pgc = BIT(IMX8MM_PGC_VPUMIX), }, [IMX8MM_POWER_DOMAIN_VPUG1] = { @@ -699,7 +703,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .pxx = IMX8MM_VPUG1_SW_Pxx_REQ, .map = IMX8MM_VPUG1_A53_DOMAIN, }, - .pgc = IMX8MM_PGC_VPUG1, + .pgc = BIT(IMX8MM_PGC_VPUG1), }, [IMX8MM_POWER_DOMAIN_VPUG2] = { @@ -710,7 +714,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .pxx = IMX8MM_VPUG2_SW_Pxx_REQ, .map = IMX8MM_VPUG2_A53_DOMAIN, }, - .pgc = IMX8MM_PGC_VPUG2, + .pgc = BIT(IMX8MM_PGC_VPUG2), }, [IMX8MM_POWER_DOMAIN_VPUH1] = { @@ -721,7 +725,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .pxx = IMX8MM_VPUH1_SW_Pxx_REQ, .map = IMX8MM_VPUH1_A53_DOMAIN, }, - .pgc = IMX8MM_PGC_VPUH1, + .pgc = BIT(IMX8MM_PGC_VPUH1), }, [IMX8MM_POWER_DOMAIN_DISPMIX] = { @@ -734,7 +738,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN, .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN, }, - .pgc = IMX8MM_PGC_DISPMIX, + .pgc = BIT(IMX8MM_PGC_DISPMIX), }, [IMX8MM_POWER_DOMAIN_MIPI] = { @@ -745,7 +749,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .pxx = IMX8MM_MIPI_SW_Pxx_REQ, .map = IMX8MM_MIPI_A53_DOMAIN, }, - .pgc = IMX8MM_PGC_MIPI, + .pgc = BIT(IMX8MM_PGC_MIPI), }, }; @@ -812,7 +816,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = { .pxx = IMX8MN_OTG1_SW_Pxx_REQ, .map = IMX8MN_OTG1_A53_DOMAIN, }, - .pgc = IMX8MN_PGC_OTG1, + .pgc = BIT(IMX8MN_PGC_OTG1), }, [IMX8MN_POWER_DOMAIN_GPUMIX] = { @@ -825,7 +829,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = { .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN, .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN, }, - .pgc = IMX8MN_PGC_GPUMIX, + .pgc = BIT(IMX8MN_PGC_GPUMIX), }, }; From 19791f518f10b9cbf0a0171166373b4bf3d4be47 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 7 Sep 2021 04:38:30 +0200 Subject: [PATCH 087/179] soc: imx: gpcv2: Set both GPC_PGC_nCTRL(GPU_2D|GPU_3D) for MX8MM GPU domain To bring up the MX8MM GPU domain, it is necessary to configure both GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) registers. Without this configuration, the system might hang on boot when bringing up the GPU power domain. This is sporadically observed on multiple disparate systems. Add the GPU3D bit into MX8MM GPU domain pgc bitfield, so that both GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) registers are configured when bringing up the GPU domain. This fixes the sporadic hang. Reviewed-by: Peng Fan Signed-off-by: Marek Vasut Cc: Frieder Schrempf Cc: Lucas Stach Cc: NXP Linux Team Cc: Peng Fan Cc: Shawn Guo Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index acd8734d960a..46aac23a35e3 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -679,7 +679,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskreq = IMX8MM_GPU_HSK_PWRDNREQN, .hskack = IMX8MM_GPU_HSK_PWRDNACKN, }, - .pgc = BIT(IMX8MM_PGC_GPU2D), + .pgc = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D), }, [IMX8MM_POWER_DOMAIN_VPUMIX] = { From 45e934407b7efa08cde651d5669d1984a3a4bc69 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Sep 2021 23:29:02 +0300 Subject: [PATCH 088/179] soc/tegra: fuse: Add stubs needed for compile testing Add stubs needed for compile-testing of tegra-cpuidle driver. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- include/soc/tegra/fuse.h | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h index 990701f788bc..67d2bc856fbc 100644 --- a/include/soc/tegra/fuse.h +++ b/include/soc/tegra/fuse.h @@ -6,6 +6,8 @@ #ifndef __SOC_TEGRA_FUSE_H__ #define __SOC_TEGRA_FUSE_H__ +#include + #define TEGRA20 0x20 #define TEGRA30 0x30 #define TEGRA114 0x35 @@ -22,11 +24,6 @@ #ifndef __ASSEMBLY__ -u32 tegra_read_chipid(void); -u8 tegra_get_chip_id(void); -u8 tegra_get_platform(void); -bool tegra_is_silicon(void); - enum tegra_revision { TEGRA_REVISION_UNKNOWN = 0, TEGRA_REVISION_A01, @@ -57,6 +54,10 @@ extern struct tegra_sku_info tegra_sku_info; u32 tegra_read_straps(void); u32 tegra_read_ram_code(void); int tegra_fuse_readl(unsigned long offset, u32 *value); +u32 tegra_read_chipid(void); +u8 tegra_get_chip_id(void); +u8 tegra_get_platform(void); +bool tegra_is_silicon(void); #else static struct tegra_sku_info tegra_sku_info __maybe_unused; @@ -74,6 +75,26 @@ static inline int tegra_fuse_readl(unsigned long offset, u32 *value) { return -ENODEV; } + +static inline u32 tegra_read_chipid(void) +{ + return 0; +} + +static inline u8 tegra_get_chip_id(void) +{ + return 0; +} + +static inline u8 tegra_get_platform(void) +{ + return 0; +} + +static inline bool tegra_is_silicon(void) +{ + return false; +} #endif struct device *tegra_soc_device_register(void); From aa54686e285c13bfbafc02e7cc3cf18f2fbca4b0 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Sep 2021 23:29:03 +0300 Subject: [PATCH 089/179] soc/tegra: irq: Add stubs needed for compile testing Add stubs needed for compile-testing of tegra-cpuidle driver. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- include/soc/tegra/irq.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/soc/tegra/irq.h b/include/soc/tegra/irq.h index 8eb11a7109e4..94539551c8c1 100644 --- a/include/soc/tegra/irq.h +++ b/include/soc/tegra/irq.h @@ -6,8 +6,15 @@ #ifndef __SOC_TEGRA_IRQ_H #define __SOC_TEGRA_IRQ_H -#if defined(CONFIG_ARM) +#include + +#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_TEGRA) bool tegra_pending_sgi(void); +#else +static inline bool tegra_pending_sgi(void) +{ + return false; +} #endif #endif /* __SOC_TEGRA_IRQ_H */ From 0d7281b27af9d9602a6d62a132f19932b1b0fd88 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Sep 2021 23:29:04 +0300 Subject: [PATCH 090/179] soc/tegra: pm: Make stubs usable for compile testing The PM stubs need to depend on ARCH_TEGRA in order to be usable for compile-testing of tegra-cpuidle driver. Add the dependency. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- include/soc/tegra/pm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/soc/tegra/pm.h b/include/soc/tegra/pm.h index 433878927026..ce4d0b1bd0d6 100644 --- a/include/soc/tegra/pm.h +++ b/include/soc/tegra/pm.h @@ -17,7 +17,7 @@ enum tegra_suspend_mode { TEGRA_SUSPEND_NOT_READY, }; -#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) && defined(CONFIG_ARCH_TEGRA) enum tegra_suspend_mode tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode); From 33110589a3f0ed8e2c4c8213bc44858a93cefc01 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 27 Sep 2021 01:40:26 +0300 Subject: [PATCH 091/179] soc/tegra: pmc: Disable PMC state syncing Disable PMC state syncing in order to ensure that we won't break older kernels once device-trees will be updated with the addition of the power domains. This also allows to apply device-tree PM patches independently from the driver patches. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 50091c4ec948..fb8faf7b226a 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -360,6 +360,7 @@ struct tegra_pmc_soc { unsigned int num_pmc_clks; bool has_blink_output; bool has_usb_sleepwalk; + bool supports_core_domain; }; /** @@ -3041,6 +3042,7 @@ static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc, } static const struct tegra_pmc_soc tegra20_pmc_soc = { + .supports_core_domain = false, .num_powergates = ARRAY_SIZE(tegra20_powergates), .powergates = tegra20_powergates, .num_cpu_powergates = 0, @@ -3101,6 +3103,7 @@ static const char * const tegra30_reset_sources[] = { }; static const struct tegra_pmc_soc tegra30_pmc_soc = { + .supports_core_domain = false, .num_powergates = ARRAY_SIZE(tegra30_powergates), .powergates = tegra30_powergates, .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates), @@ -3157,6 +3160,7 @@ static const u8 tegra114_cpu_powergates[] = { }; static const struct tegra_pmc_soc tegra114_pmc_soc = { + .supports_core_domain = false, .num_powergates = ARRAY_SIZE(tegra114_powergates), .powergates = tegra114_powergates, .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates), @@ -3273,6 +3277,7 @@ static const struct pinctrl_pin_desc tegra124_pin_descs[] = { }; static const struct tegra_pmc_soc tegra124_pmc_soc = { + .supports_core_domain = false, .num_powergates = ARRAY_SIZE(tegra124_powergates), .powergates = tegra124_powergates, .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates), @@ -3398,6 +3403,7 @@ static const struct tegra_wake_event tegra210_wake_events[] = { }; static const struct tegra_pmc_soc tegra210_pmc_soc = { + .supports_core_domain = false, .num_powergates = ARRAY_SIZE(tegra210_powergates), .powergates = tegra210_powergates, .num_cpu_powergates = ARRAY_SIZE(tegra210_cpu_powergates), @@ -3555,6 +3561,7 @@ static const struct tegra_wake_event tegra186_wake_events[] = { }; static const struct tegra_pmc_soc tegra186_pmc_soc = { + .supports_core_domain = false, .num_powergates = 0, .powergates = NULL, .num_cpu_powergates = 0, @@ -3689,6 +3696,7 @@ static const struct tegra_wake_event tegra194_wake_events[] = { }; static const struct tegra_pmc_soc tegra194_pmc_soc = { + .supports_core_domain = false, .num_powergates = 0, .powergates = NULL, .num_cpu_powergates = 0, @@ -3757,6 +3765,7 @@ static const char * const tegra234_reset_sources[] = { }; static const struct tegra_pmc_soc tegra234_pmc_soc = { + .supports_core_domain = false, .num_powergates = 0, .powergates = NULL, .num_cpu_powergates = 0, @@ -3803,6 +3812,14 @@ static void tegra_pmc_sync_state(struct device *dev) { int err; + /* + * Newer device-trees have power domains, but we need to prepare all + * device drivers with runtime PM and OPP support first, otherwise + * state syncing is unsafe. + */ + if (!pmc->soc->supports_core_domain) + return; + /* * Older device-trees don't have core PD, and thus, there are * no dependencies that will block the state syncing. We shouldn't From ceba814b37d0f07419068225fe49f0e69f9602f9 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Sep 2021 21:17:14 +0300 Subject: [PATCH 092/179] soc/tegra: pmc: Expose USB regmap to all SoCs All Tegra SoCs prior to Tegra186 have USB power controls within the Power Management controller. These controls need to be configured by USB driver. Expose the regmap to these SoCs. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index fb8faf7b226a..2ad7b3bceb80 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -3067,7 +3067,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { .pmc_clks_data = NULL, .num_pmc_clks = 0, .has_blink_output = true, - .has_usb_sleepwalk = false, + .has_usb_sleepwalk = true, }; static const char * const tegra30_powergates[] = { @@ -3128,7 +3128,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { .pmc_clks_data = tegra_pmc_clks_data, .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data), .has_blink_output = true, - .has_usb_sleepwalk = false, + .has_usb_sleepwalk = true, }; static const char * const tegra114_powergates[] = { @@ -3185,7 +3185,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { .pmc_clks_data = tegra_pmc_clks_data, .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data), .has_blink_output = true, - .has_usb_sleepwalk = false, + .has_usb_sleepwalk = true, }; static const char * const tegra124_powergates[] = { From f617a8717657e9142de02e54c8e6c885c569692d Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Fri, 24 Sep 2021 11:01:46 -0300 Subject: [PATCH 093/179] imx: soc: Select REGMAP_MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The imx-gpcv2 driver needs Regmap MMIO. Select it, and fix: drivers/soc/imx/gpcv2.c:420:34: error: array type has incomplete element type ‘struct regmap_range’ 420 | static const struct regmap_range imx7_yes_ranges[] = { | ^~~~~~~~~~~~~~~ drivers/soc/imx/gpcv2.c:421:17: error: implicit declaration of function ‘regmap_reg_range’; did you mean ‘remap_pfn_range’? [-Werror=implicit-function-declaration] 421 | regmap_reg_range(GPC_LPCR_A_CORE_BSC, | ^~~~~~~~~~~~~~~~ | remap_pfn_range Signed-off-by: Ezequiel Garcia Signed-off-by: Shawn Guo --- drivers/soc/imx/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig index 05812f8ae734..a840494e849a 100644 --- a/drivers/soc/imx/Kconfig +++ b/drivers/soc/imx/Kconfig @@ -6,6 +6,7 @@ config IMX_GPCV2_PM_DOMAINS depends on ARCH_MXC || (COMPILE_TEST && OF) depends on PM select PM_GENERIC_DOMAINS + select REGMAP_MMIO default y if SOC_IMX7D config SOC_IMX8M From 8da8bd5399cfc2ff98514a6b31a3aa2159516fe6 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sat, 2 Oct 2021 14:48:52 +0200 Subject: [PATCH 094/179] soc: imx: gpcv2: allow to disable individual power domains Some board designs don't supply power to all of the power domains, as they are not used anyways. In that case we must make sure to not touch those power domains at all, as trying to power up a domain that has no power supplied to it will obviously end in a system crash. Allow to disable those domains via the standard DT status property. Signed-off-by: Lucas Stach Reviewed-By: Tim Harvey Tested-By: Tim Harvey Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 46aac23a35e3..39a581f9b4ac 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -990,6 +990,9 @@ static int imx_gpcv2_probe(struct platform_device *pdev) struct imx_pgc_domain *domain; u32 domain_index; + if (!of_device_is_available(np)) + continue; + ret = of_property_read_u32(np, "reg", &domain_index); if (ret) { dev_err(dev, "Failed to read 'reg' property\n"); From 2b2f106eb55276a60a89ac27a52d0d738b57a546 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sat, 2 Oct 2021 02:59:37 +0200 Subject: [PATCH 095/179] Revert "soc: imx: gpcv2: move reset assert after requesting domain power up" This reverts commit a77ebdd9f553. It turns out that the VPU domain has no different requirements, even though the downstream ATF implementation seems to suggest otherwise. Powering on the domain with the reset asserted works fine. As the changed sequence has caused sporadic issues with the GPU domains, just revert the change to go back to the working sequence. Cc: # 5.14 Signed-off-by: Lucas Stach Acked-by: Peng Fan Tested-by: Adam Ford #imx8mm-beacon Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 39a581f9b4ac..7fbf1f25b48e 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -244,6 +244,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) goto out_regulator_disable; } + reset_control_assert(domain->reset); + if (domain->bits.pxx) { /* request the domain to power up */ regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ, @@ -268,8 +270,6 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) } } - reset_control_assert(domain->reset); - /* delay for reset to propagate */ udelay(5); From 5694ca290f08cc21e7a0b9e54b31638c1ae5dac0 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 23 Sep 2021 20:08:40 -0700 Subject: [PATCH 096/179] reset: Allow building Broadcom STB RESCAL as module The driver can be built as a module and uses device managed resources. Signed-off-by: Florian Fainelli Link: https://lore.kernel.org/r/20210924030840.9650-1-f.fainelli@gmail.com Signed-off-by: Philipp Zabel --- drivers/reset/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index be799a5abf8a..f9d8b364db5f 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -58,7 +58,7 @@ config RESET_BRCMSTB a SUN_TOP_CTRL_SW_INIT style controller. config RESET_BRCMSTB_RESCAL - bool "Broadcom STB RESCAL reset controller" + tristate "Broadcom STB RESCAL reset controller" depends on HAS_IOMEM depends on ARCH_BRCMSTB || COMPILE_TEST default ARCH_BRCMSTB From 300d24759def6b34a9e34c682baa91e477614b17 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 5 Oct 2021 11:10:40 +0900 Subject: [PATCH 097/179] reset: uniphier: Add audio system and video input reset control for PXs3 Add reset lines for audio subsystem (AIO) and video input subsystem (EXIV) on UniPhier PXs3 SoC. Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1633399842-1402-2-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-uniphier.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c index 5f75783f9397..4a6cfd8f399d 100644 --- a/drivers/reset/reset-uniphier.c +++ b/drivers/reset/reset-uniphier.c @@ -136,6 +136,8 @@ static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = { UNIPHIER_RESETX(28, 0x200c, 7), /* SATA0 */ UNIPHIER_RESETX(29, 0x200c, 8), /* SATA1 */ UNIPHIER_RESETX(30, 0x200c, 21), /* SATA-PHY */ + UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */ + UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */ UNIPHIER_RESET_END, }; From 659b83ccdac313e6030a27075e7bb853d5759f18 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 5 Oct 2021 11:10:41 +0900 Subject: [PATCH 098/179] dt-bindings: reset: uniphier: Add NX1 reset control binding Update reset controller binding document for UniPhier NX1 SoC. Signed-off-by: Masahiro Yamada Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1633399842-1402-3-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Philipp Zabel --- .../bindings/reset/socionext,uniphier-glue-reset.yaml | 1 + .../devicetree/bindings/reset/socionext,uniphier-reset.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/reset/socionext,uniphier-glue-reset.yaml b/Documentation/devicetree/bindings/reset/socionext,uniphier-glue-reset.yaml index 29e4a900cad7..bfbd3e9b4186 100644 --- a/Documentation/devicetree/bindings/reset/socionext,uniphier-glue-reset.yaml +++ b/Documentation/devicetree/bindings/reset/socionext,uniphier-glue-reset.yaml @@ -23,6 +23,7 @@ properties: - socionext,uniphier-pxs2-usb3-reset - socionext,uniphier-ld20-usb3-reset - socionext,uniphier-pxs3-usb3-reset + - socionext,uniphier-nx1-usb3-reset - socionext,uniphier-pro4-ahci-reset - socionext,uniphier-pxs2-ahci-reset - socionext,uniphier-pxs3-ahci-reset diff --git a/Documentation/devicetree/bindings/reset/socionext,uniphier-reset.yaml b/Documentation/devicetree/bindings/reset/socionext,uniphier-reset.yaml index 4c9b0ebf6869..377a7d242323 100644 --- a/Documentation/devicetree/bindings/reset/socionext,uniphier-reset.yaml +++ b/Documentation/devicetree/bindings/reset/socionext,uniphier-reset.yaml @@ -23,6 +23,7 @@ properties: - socionext,uniphier-ld11-reset - socionext,uniphier-ld20-reset - socionext,uniphier-pxs3-reset + - socionext,uniphier-nx1-reset - description: Media I/O (MIO) reset, SD reset enum: - socionext,uniphier-ld4-mio-reset @@ -34,6 +35,7 @@ properties: - socionext,uniphier-ld11-sd-reset - socionext,uniphier-ld20-sd-reset - socionext,uniphier-pxs3-sd-reset + - socionext,uniphier-nx1-sd-reset - description: Peripheral reset enum: - socionext,uniphier-ld4-peri-reset @@ -44,6 +46,7 @@ properties: - socionext,uniphier-ld11-peri-reset - socionext,uniphier-ld20-peri-reset - socionext,uniphier-pxs3-peri-reset + - socionext,uniphier-nx1-peri-reset - description: Analog signal amplifier reset enum: - socionext,uniphier-ld11-adamv-reset From 3440b8fa067db5763f501496ec79d2856bc26060 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 5 Oct 2021 11:10:42 +0900 Subject: [PATCH 099/179] reset: uniphier: Add NX1 reset support Add basic reset data for UniPhier NX1 SoC. Signed-off-by: Masahiro Yamada Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1633399842-1402-4-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Philipp Zabel --- drivers/reset/reset-uniphier-glue.c | 4 ++++ drivers/reset/reset-uniphier.c | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/reset/reset-uniphier-glue.c b/drivers/reset/reset-uniphier-glue.c index 027990b79f61..908c1d5bc41e 100644 --- a/drivers/reset/reset-uniphier-glue.c +++ b/drivers/reset/reset-uniphier-glue.c @@ -155,6 +155,10 @@ static const struct of_device_id uniphier_glue_reset_match[] = { .compatible = "socionext,uniphier-pxs3-usb3-reset", .data = &uniphier_pxs2_data, }, + { + .compatible = "socionext,uniphier-nx1-usb3-reset", + .data = &uniphier_pxs2_data, + }, { .compatible = "socionext,uniphier-pro4-ahci-reset", .data = &uniphier_pro4_data, diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c index 4a6cfd8f399d..ff7580f38056 100644 --- a/drivers/reset/reset-uniphier.c +++ b/drivers/reset/reset-uniphier.c @@ -141,6 +141,19 @@ static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = { UNIPHIER_RESET_END, }; +static const struct uniphier_reset_data uniphier_nx1_sys_reset_data[] = { + UNIPHIER_RESETX(4, 0x2008, 8), /* eMMC */ + UNIPHIER_RESETX(6, 0x200c, 0), /* Ether */ + UNIPHIER_RESETX(12, 0x200c, 16), /* USB30 link */ + UNIPHIER_RESETX(16, 0x200c, 24), /* USB30-PHY0 */ + UNIPHIER_RESETX(17, 0x200c, 25), /* USB30-PHY1 */ + UNIPHIER_RESETX(18, 0x200c, 26), /* USB30-PHY2 */ + UNIPHIER_RESETX(24, 0x200c, 8), /* PCIe */ + UNIPHIER_RESETX(52, 0x2010, 0), /* VOC */ + UNIPHIER_RESETX(58, 0x2010, 8), /* HDMI-Tx */ + UNIPHIER_RESET_END, +}; + /* Media I/O reset data */ #define UNIPHIER_MIO_RESET_SD(id, ch) \ UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0) @@ -402,6 +415,10 @@ static const struct of_device_id uniphier_reset_match[] = { .compatible = "socionext,uniphier-pxs3-reset", .data = uniphier_pxs3_sys_reset_data, }, + { + .compatible = "socionext,uniphier-nx1-reset", + .data = uniphier_nx1_sys_reset_data, + }, /* Media I/O reset, SD reset */ { .compatible = "socionext,uniphier-ld4-mio-reset", @@ -439,6 +456,10 @@ static const struct of_device_id uniphier_reset_match[] = { .compatible = "socionext,uniphier-pxs3-sd-reset", .data = uniphier_pro5_sd_reset_data, }, + { + .compatible = "socionext,uniphier-nx1-sd-reset", + .data = uniphier_pro5_sd_reset_data, + }, /* Peripheral reset */ { .compatible = "socionext,uniphier-ld4-peri-reset", @@ -472,6 +493,10 @@ static const struct of_device_id uniphier_reset_match[] = { .compatible = "socionext,uniphier-pxs3-peri-reset", .data = uniphier_pro4_peri_reset_data, }, + { + .compatible = "socionext,uniphier-nx1-peri-reset", + .data = uniphier_pro4_peri_reset_data, + }, /* Analog signal amplifiers reset */ { .compatible = "socionext,uniphier-ld11-adamv-reset", From 4ad81f6ef89b62434f1d2ed26e9bec9d0e3d9dfe Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 4 Oct 2021 22:06:41 +0200 Subject: [PATCH 100/179] clk: tegra: Add stubs needed for compile testing These stubs are needed to allow the tegra-cpuidle driver to be compile-tested. Signed-off-by: Thierry Reding --- include/linux/clk/tegra.h | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h index d128ad1570aa..3650e926e93f 100644 --- a/include/linux/clk/tegra.h +++ b/include/linux/clk/tegra.h @@ -42,6 +42,7 @@ struct tegra_cpu_car_ops { #endif }; +#ifdef CONFIG_ARCH_TEGRA extern struct tegra_cpu_car_ops *tegra_cpu_car_ops; static inline void tegra_wait_cpu_in_reset(u32 cpu) @@ -83,8 +84,29 @@ static inline void tegra_disable_cpu_clock(u32 cpu) tegra_cpu_car_ops->disable_clock(cpu); } +#else +static inline void tegra_wait_cpu_in_reset(u32 cpu) +{ +} -#ifdef CONFIG_PM_SLEEP +static inline void tegra_put_cpu_in_reset(u32 cpu) +{ +} + +static inline void tegra_cpu_out_of_reset(u32 cpu) +{ +} + +static inline void tegra_enable_cpu_clock(u32 cpu) +{ +} + +static inline void tegra_disable_cpu_clock(u32 cpu) +{ +} +#endif + +#if defined(CONFIG_ARCH_TEGRA) && defined(CONFIG_PM_SLEEP) static inline bool tegra_cpu_rail_off_ready(void) { if (WARN_ON(!tegra_cpu_car_ops->rail_off_ready)) From faae6c9f2e68e62687636a7d6e0517b3bf594add Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Sep 2021 23:29:06 +0300 Subject: [PATCH 101/179] cpuidle: tegra: Enable compile testing Enable compile testing of tegra-cpuidle driver. Signed-off-by: Dmitry Osipenko Acked-by: Daniel Lezcano Signed-off-by: Thierry Reding --- drivers/cpuidle/Kconfig.arm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 334f83e56120..599286fc0b08 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -99,7 +99,7 @@ config ARM_MVEBU_V7_CPUIDLE config ARM_TEGRA_CPUIDLE bool "CPU Idle Driver for NVIDIA Tegra SoCs" - depends on ARCH_TEGRA && !ARM64 + depends on (ARCH_TEGRA || COMPILE_TEST) && !ARM64 && MMU select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP select ARM_CPU_SUSPEND help From bdb1ffdad3b73e4d0538098fc02e2ea87a6b27cd Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Sep 2021 23:29:07 +0300 Subject: [PATCH 102/179] cpuidle: tegra: Check whether PMC is ready Check whether PMC is ready before proceeding with the cpuidle registration. This fixes racing with the PMC driver probe order, which results in a disabled deepest CC6 idling state if cpuidle driver is probed before the PMC. Acked-by: Daniel Lezcano Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/cpuidle/cpuidle-tegra.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cpuidle/cpuidle-tegra.c b/drivers/cpuidle/cpuidle-tegra.c index 508bd9f23792..9845629aeb6d 100644 --- a/drivers/cpuidle/cpuidle-tegra.c +++ b/drivers/cpuidle/cpuidle-tegra.c @@ -337,6 +337,9 @@ static void tegra_cpuidle_setup_tegra114_c7_state(void) static int tegra_cpuidle_probe(struct platform_device *pdev) { + if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NOT_READY) + return -EPROBE_DEFER; + /* LP2 could be disabled in device-tree */ if (tegra_pmc_get_suspend_mode() < TEGRA_SUSPEND_LP2) tegra_cpuidle_disable_state(TEGRA_CC6); From 1b1da99b845337362a3dafe0f7b49927ab4ae041 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 6 Oct 2021 08:38:09 +0300 Subject: [PATCH 103/179] bus: ti-sysc: Fix variable set but not used warning for reinit_modules Fix drivers/bus/ti-sysc.c:2494:13: error: variable 'error' set but not used introduced by commit 9d881361206e ("bus: ti-sysc: Add quirk handling for reinit on context lost"). Reported-by: kernel test robot Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index d4e873ab813c..a1e60753ae5a 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -2523,12 +2523,11 @@ static void sysc_reinit_modules(struct sysc_soc_info *soc) struct sysc_module *module; struct list_head *pos; struct sysc *ddata; - int error = 0; list_for_each(pos, &sysc_soc->restored_modules) { module = list_entry(pos, struct sysc_module, node); ddata = module->ddata; - error = sysc_reinit_module(ddata, ddata->enabled); + sysc_reinit_module(ddata, ddata->enabled); } } From fadf79a07b48af66e367b49c3a445a1282148fcf Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sat, 2 Oct 2021 02:59:40 +0200 Subject: [PATCH 104/179] soc: imx: gpcv2: add lockdep annotation Some of the GPCv2 power domains are nested inside each other without visibility to lockdep at the genpd level, as they are in separate driver instances and don't have a parent/child power-domain relationship. Add a subclass annotation to the nested domains to let lockdep know that it is okay to take the genpd lock in a nested fashion. Signed-off-by: Lucas Stach Reviewed-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 7fbf1f25b48e..fcea95317287 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -898,6 +898,10 @@ static int imx_pgc_domain_probe(struct platform_device *pdev) goto out_domain_unmap; } + if (IS_ENABLED(CONFIG_LOCKDEP) && + of_property_read_bool(domain->dev->of_node, "power-domains")) + lockdep_set_subclass(&domain->genpd.mlock, 1); + ret = of_genpd_add_provider_simple(domain->dev->of_node, &domain->genpd); if (ret) { From 18c98573a4cf2dc183cd884cec23869ba0c9fc1b Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sat, 2 Oct 2021 02:59:41 +0200 Subject: [PATCH 105/179] soc: imx: gpcv2: add domain option to keep domain clocks enabled Some of the MIX domains are using clocks to drive the bus bridges. Those must be enabled at all times, as long as the domain is powered up and they don't have any other consumer than the power domain. Add an option to keep the clocks attached to a domain enabled as long as the domain is power up and only disable them after the domain is powered down. Signed-off-by: Lucas Stach Reviewed-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index fcea95317287..e5a98107ad56 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -202,6 +202,7 @@ struct imx_pgc_domain { } bits; const int voltage; + const bool keep_clocks; struct device *dev; }; @@ -295,7 +296,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) } /* Disable reset clocks for all devices in the domain */ - clk_bulk_disable_unprepare(domain->num_clks, domain->clks); + if (!domain->keep_clocks) + clk_bulk_disable_unprepare(domain->num_clks, domain->clks); return 0; @@ -317,10 +319,12 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd) int ret; /* Enable reset clocks for all devices in the domain */ - ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); - if (ret) { - dev_err(domain->dev, "failed to enable reset clocks\n"); - return ret; + if (!domain->keep_clocks) { + ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks); + if (ret) { + dev_err(domain->dev, "failed to enable reset clocks\n"); + return ret; + } } /* request the ADB400 to power down */ From 656ade7aa42a2c6d08b3c5ddff074b54d025ccc2 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sat, 2 Oct 2021 02:59:42 +0200 Subject: [PATCH 106/179] soc: imx: gpcv2: keep i.MX8M* bus clocks enabled Annotate the domains with bus clocks to keep those clocks enabled as long as the domain is active. Signed-off-by: Lucas Stach Reviewed-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index e5a98107ad56..abf840609c56 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -527,6 +527,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .hskack = IMX8M_VPU_HSK_PWRDNACKN, }, .pgc = BIT(IMX8M_PGC_VPU), + .keep_clocks = true, }, [IMX8M_POWER_DOMAIN_DISP] = { @@ -625,6 +626,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN, .hskack = IMX8MM_HSIO_HSK_PWRDNACKN, }, + .keep_clocks = true, }, [IMX8MM_POWER_DOMAIN_PCIE] = { @@ -671,6 +673,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN, }, .pgc = BIT(IMX8MM_PGC_GPUMIX), + .keep_clocks = true, }, [IMX8MM_POWER_DOMAIN_GPU] = { @@ -697,6 +700,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN, }, .pgc = BIT(IMX8MM_PGC_VPUMIX), + .keep_clocks = true, }, [IMX8MM_POWER_DOMAIN_VPUG1] = { @@ -743,6 +747,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN, }, .pgc = BIT(IMX8MM_PGC_DISPMIX), + .keep_clocks = true, }, [IMX8MM_POWER_DOMAIN_MIPI] = { @@ -810,6 +815,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = { .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN, .hskack = IMX8MN_HSIO_HSK_PWRDNACKN, }, + .keep_clocks = true, }, [IMX8MN_POWER_DOMAIN_OTG1] = { From da4112230f86558f7d3b2cb261e71160e4f88849 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sat, 2 Oct 2021 02:59:43 +0200 Subject: [PATCH 107/179] soc: imx: gpcv2: support system suspend/resume Our usage of runtime PM to control the hierarchy of power domains is slightly unusual and means that powering up a domain may fail in early system resume, as runtime PM is still disallowed at this stage. However the system suspend/resume path takes care of powering down/up the power domains in the order defined by the device parent/child and power-domain provider/consumer hierarachy. So we can just runtime resume all our power-domain devices to allow the power-up to work properly in the resume path. System suspend will still disable all domains as intended. Signed-off-by: Lucas Stach Acked-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/gpcv2.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index abf840609c56..b8d52d8d29db 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -948,6 +948,36 @@ static int imx_pgc_domain_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int imx_pgc_domain_suspend(struct device *dev) +{ + int ret; + + /* + * This may look strange, but is done so the generic PM_SLEEP code + * can power down our domain and more importantly power it up again + * after resume, without tripping over our usage of runtime PM to + * power up/down the nested domains. + */ + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + return ret; + } + + return 0; +} + +static int imx_pgc_domain_resume(struct device *dev) +{ + return pm_runtime_put(dev); +} +#endif + +static const struct dev_pm_ops imx_pgc_domain_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume) +}; + static const struct platform_device_id imx_pgc_domain_id[] = { { "imx-pgc-domain", }, { }, @@ -956,6 +986,7 @@ static const struct platform_device_id imx_pgc_domain_id[] = { static struct platform_driver imx_pgc_domain_driver = { .driver = { .name = "imx-pgc", + .pm = &imx_pgc_domain_pm_ops, }, .probe = imx_pgc_domain_probe, .remove = imx_pgc_domain_remove, From 2684ac05a8c4d2d5c49e6c11eb6206b30a284813 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sat, 2 Oct 2021 02:59:46 +0200 Subject: [PATCH 108/179] soc: imx: add i.MX8M blk-ctrl driver This adds a driver for the blk-ctrl blocks found in the i.MX8M* line of SoCs. The blk-ctrl is a top-level peripheral located in the various *MIX power domains and interacts with the GPC power controller to provide the peripherals in the power domain access to the NoC and ensures that those peripherals are properly reset when their respective power domain is brought back to life. Software needs to do different things to make the bus handshake happen after the GPC *MIX domain is powered up and before it is powered down. As the requirements are quite different between the various blk-ctrls there is a callback function provided to hook in the proper sequence. The peripheral domains are quite uniform, they handle the soft clock enables and resets in the blk-ctrl address space and sequencing with the upstream GPC power domains. Signed-off-by: Lucas Stach Acked-by: Frieder Schrempf Reviewed-by: Philipp Zabel Signed-off-by: Shawn Guo --- drivers/soc/imx/Makefile | 1 + drivers/soc/imx/imx8m-blk-ctrl.c | 453 +++++++++++++++++++++++++++++++ 2 files changed, 454 insertions(+) create mode 100644 drivers/soc/imx/imx8m-blk-ctrl.c diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index 078dc918f4f3..8a707077914c 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -5,3 +5,4 @@ endif obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o +obj-$(CONFIG_SOC_IMX8M) += imx8m-blk-ctrl.o diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c new file mode 100644 index 000000000000..f8db0ebd02c3 --- /dev/null +++ b/drivers/soc/imx/imx8m-blk-ctrl.c @@ -0,0 +1,453 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright 2021 Pengutronix, Lucas Stach + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BLK_SFT_RSTN 0x0 +#define BLK_CLK_EN 0x4 + +struct imx8m_blk_ctrl_domain; + +struct imx8m_blk_ctrl { + struct device *dev; + struct notifier_block power_nb; + struct device *bus_power_dev; + struct regmap *regmap; + struct imx8m_blk_ctrl_domain *domains; + struct genpd_onecell_data onecell_data; +}; + +struct imx8m_blk_ctrl_domain_data { + const char *name; + const char * const *clk_names; + int num_clks; + const char *gpc_name; + u32 rst_mask; + u32 clk_mask; +}; + +#define DOMAIN_MAX_CLKS 3 + +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 device *power_dev; + struct imx8m_blk_ctrl *bc; +}; + +struct imx8m_blk_ctrl_data { + int max_reg; + notifier_fn_t power_notifier_fn; + const struct imx8m_blk_ctrl_domain_data *domains; + int num_domains; +}; + +static inline struct imx8m_blk_ctrl_domain * +to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd) +{ + return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd); +} + +static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd) +{ + struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd); + const struct imx8m_blk_ctrl_domain_data *data = domain->data; + struct imx8m_blk_ctrl *bc = domain->bc; + int ret; + + /* make sure bus domain is awake */ + ret = pm_runtime_get_sync(bc->bus_power_dev); + if (ret < 0) { + pm_runtime_put_noidle(bc->bus_power_dev); + dev_err(bc->dev, "failed to power up bus domain\n"); + return ret; + } + + /* put devices into reset */ + regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); + + /* enable upstream and blk-ctrl clocks to allow reset to propagate */ + ret = clk_bulk_prepare_enable(data->num_clks, domain->clks); + if (ret) { + dev_err(bc->dev, "failed to enable clocks\n"); + goto bus_put; + } + regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask); + + /* power up upstream GPC domain */ + ret = pm_runtime_get_sync(domain->power_dev); + if (ret < 0) { + dev_err(bc->dev, "failed to power up peripheral domain\n"); + goto clk_disable; + } + + /* wait for reset to propagate */ + udelay(5); + + /* release reset */ + regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); + + /* disable upstream clocks */ + clk_bulk_disable_unprepare(data->num_clks, domain->clks); + + return 0; + +clk_disable: + clk_bulk_disable_unprepare(data->num_clks, domain->clks); +bus_put: + pm_runtime_put(bc->bus_power_dev); + + return ret; +} + +static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd) +{ + struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd); + const struct imx8m_blk_ctrl_domain_data *data = domain->data; + struct imx8m_blk_ctrl *bc = domain->bc; + + /* put devices into reset and disable clocks */ + regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask); + regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask); + + /* power down upstream GPC domain */ + pm_runtime_put(domain->power_dev); + + /* allow bus domain to suspend */ + pm_runtime_put(bc->bus_power_dev); + + 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) +{ + const struct imx8m_blk_ctrl_data *bc_data; + struct device *dev = &pdev->dev; + struct imx8m_blk_ctrl *bc; + void __iomem *base; + int i, ret; + + struct regmap_config regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + }; + + bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL); + if (!bc) + return -ENOMEM; + + bc->dev = dev; + + bc_data = of_device_get_match_data(dev); + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + regmap_config.max_register = bc_data->max_reg; + 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 imx8m_blk_ctrl_domain), + GFP_KERNEL); + if (!bc->domains) + 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); + if (!bc->onecell_data.domains) + return -ENOMEM; + + bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus"); + if (IS_ERR(bc->bus_power_dev)) + return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev), + "failed to attach power domain\n"); + + for (i = 0; i < bc_data->num_domains; i++) { + const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i]; + struct imx8m_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->power_dev = + dev_pm_domain_attach_by_name(dev, data->gpc_name); + if (IS_ERR(domain->power_dev)) { + dev_err_probe(dev, PTR_ERR(domain->power_dev), + "failed to attach power domain\n"); + ret = PTR_ERR(domain->power_dev); + goto cleanup_pds; + } + + domain->genpd.name = data->name; + domain->genpd.power_on = imx8m_blk_ctrl_power_on; + domain->genpd.power_off = imx8m_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"); + dev_pm_domain_detach(domain->power_dev, true); + goto cleanup_pds; + } + + /* + * We use runtime PM to trigger power on/off of the upstream GPC + * domain, as a strict hierarchical parent/child power domain + * setup doesn't allow us to meet the sequencing requirements. + * This means we have nested locking of genpd locks, without the + * nesting being visible at the genpd level, so we need a + * separate lock class to make lockdep aware of the fact that + * this are separate domain locks that can be nested without a + * self-deadlock. + */ + lockdep_set_class(&domain->genpd.mlock, + &blk_ctrl_genpd_lock_class); + + bc->onecell_data.domains[i] = &domain->genpd; + } + + 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; + } + + bc->power_nb.notifier_call = bc_data->power_notifier_fn; + ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb); + if (ret) { + dev_err_probe(dev, ret, "failed to add power notifier\n"); + goto cleanup_provider; + } + + dev_set_drvdata(dev, bc); + + return 0; + +cleanup_provider: + of_genpd_del_provider(dev->of_node); +cleanup_pds: + for (i--; i >= 0; i--) { + pm_genpd_remove(&bc->domains[i].genpd); + dev_pm_domain_detach(bc->domains[i].power_dev, true); + } + + dev_pm_domain_detach(bc->bus_power_dev, true); + + return ret; +} + +static int imx8m_blk_ctrl_remove(struct platform_device *pdev) +{ + struct imx8m_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 imx8m_blk_ctrl_domain *domain = &bc->domains[i]; + + pm_genpd_remove(&domain->genpd); + dev_pm_domain_detach(domain->power_dev, true); + } + + dev_pm_genpd_remove_notifier(bc->bus_power_dev); + + dev_pm_domain_detach(bc->bus_power_dev, true); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int imx8m_blk_ctrl_suspend(struct device *dev) +{ + struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev); + int ret, i; + + /* + * This may look strange, but is done so the generic PM_SLEEP code + * can power down our domains and more importantly power them up again + * after resume, without tripping over our usage of runtime PM to + * control the upstream GPC domains. Things happen in the right order + * in the system suspend/resume paths due to the device parent/child + * hierarchy. + */ + ret = pm_runtime_get_sync(bc->bus_power_dev); + if (ret < 0) { + pm_runtime_put_noidle(bc->bus_power_dev); + return ret; + } + + for (i = 0; i < bc->onecell_data.num_domains; i++) { + struct imx8m_blk_ctrl_domain *domain = &bc->domains[i]; + + ret = pm_runtime_get_sync(domain->power_dev); + if (ret < 0) { + pm_runtime_put_noidle(domain->power_dev); + goto out_fail; + } + } + + return 0; + +out_fail: + for (i--; i >= 0; i--) + pm_runtime_put(bc->domains[i].power_dev); + + pm_runtime_put(bc->bus_power_dev); + + return ret; +} + +static int imx8m_blk_ctrl_resume(struct device *dev) +{ + struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev); + int i; + + for (i = 0; i < bc->onecell_data.num_domains; i++) + pm_runtime_put(bc->domains[i].power_dev); + + pm_runtime_put(bc->bus_power_dev); + + return 0; +} +#endif + +static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume) +}; + +static int imx8mm_vpu_power_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl, + power_nb); + + if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF) + return NOTIFY_OK; + + /* + * The ADB in the VPUMIX domain has no separate reset and clock + * enable bits, but is ungated together with the VPU clocks. To + * allow the handshake with the GPC to progress we put the VPUs + * in reset and ungate the clocks. + */ + regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2)); + regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2)); + + if (action == GENPD_NOTIFY_ON) { + /* + * On power up we have no software backchannel to the GPC to + * wait for the ADB handshake to happen, so we just delay for a + * bit. On power down the GPC driver waits for the handshake. + */ + udelay(5); + + /* set "fuse" bits to enable the VPUs */ + regmap_set_bits(bc->regmap, 0x8, 0xffffffff); + regmap_set_bits(bc->regmap, 0xc, 0xffffffff); + regmap_set_bits(bc->regmap, 0x10, 0xffffffff); + regmap_set_bits(bc->regmap, 0x14, 0xffffffff); + } + + return NOTIFY_OK; +} + +static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = { + [IMX8MM_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), + }, + [IMX8MM_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), + }, + [IMX8MM_VPUBLK_PD_H1] = { + .name = "vpublk-h1", + .clk_names = (const char *[]){ "h1", }, + .num_clks = 1, + .gpc_name = "h1", + .rst_mask = BIT(2), + .clk_mask = BIT(2), + }, +}; + +static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = { + .max_reg = 0x18, + .power_notifier_fn = imx8mm_vpu_power_notifier, + .domains = imx8mm_vpu_blk_ctl_domain_data, + .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data), +}; + +static const struct of_device_id imx8m_blk_ctrl_of_match[] = { + { + .compatible = "fsl,imx8mm-vpu-blk-ctrl", + .data = &imx8mm_vpu_blk_ctl_dev_data + }, { + /* Sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match); + +static struct platform_driver imx8m_blk_ctrl_driver = { + .probe = imx8m_blk_ctrl_probe, + .remove = imx8m_blk_ctrl_remove, + .driver = { + .name = "imx8m-blk-ctrl", + .pm = &imx8m_blk_ctrl_pm_ops, + .of_match_table = imx8m_blk_ctrl_of_match, + }, +}; +module_platform_driver(imx8m_blk_ctrl_driver); From 926e57c065dfcf5a824b206760330f32e786dd8c Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Sat, 2 Oct 2021 02:59:49 +0200 Subject: [PATCH 109/179] soc: imx: imx8m-blk-ctrl: add DISP blk-ctrl This adds the description for the i.MX8MM disp blk-ctrl. Signed-off-by: Lucas Stach Reviewed-by: Peng Fan Signed-off-by: Shawn Guo --- drivers/soc/imx/imx8m-blk-ctrl.c | 70 ++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c index f8db0ebd02c3..e172d295c441 100644 --- a/drivers/soc/imx/imx8m-blk-ctrl.c +++ b/drivers/soc/imx/imx8m-blk-ctrl.c @@ -431,11 +431,81 @@ static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = { .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data), }; +static int imx8mm_disp_power_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl, + power_nb); + + if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF) + return NOTIFY_OK; + + /* Enable bus clock and deassert bus reset */ + regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12)); + regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6)); + + /* + * On power up we have no software backchannel to the GPC to + * wait for the ADB handshake to happen, so we just delay for a + * bit. On power down the GPC driver waits for the handshake. + */ + if (action == GENPD_NOTIFY_ON) + udelay(5); + + + return NOTIFY_OK; +} + +static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = { + [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = { + .name = "dispblk-csi-bridge", + .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb", + "csi-bridge-core", }, + .num_clks = 3, + .gpc_name = "csi-bridge", + .rst_mask = BIT(0) | BIT(1) | BIT(2), + .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5), + }, + [IMX8MM_DISPBLK_PD_LCDIF] = { + .name = "dispblk-lcdif", + .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", }, + .num_clks = 3, + .gpc_name = "lcdif", + .clk_mask = BIT(6) | BIT(7), + }, + [IMX8MM_DISPBLK_PD_MIPI_DSI] = { + .name = "dispblk-mipi-dsi", + .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", }, + .num_clks = 2, + .gpc_name = "mipi-dsi", + .rst_mask = BIT(5), + .clk_mask = BIT(8) | BIT(9), + }, + [IMX8MM_DISPBLK_PD_MIPI_CSI] = { + .name = "dispblk-mipi-csi", + .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" }, + .num_clks = 2, + .gpc_name = "mipi-csi", + .rst_mask = BIT(3) | BIT(4), + .clk_mask = BIT(10) | BIT(11), + }, +}; + +static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = { + .max_reg = 0x2c, + .power_notifier_fn = imx8mm_disp_power_notifier, + .domains = imx8mm_disp_blk_ctl_domain_data, + .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data), +}; + static const struct of_device_id imx8m_blk_ctrl_of_match[] = { { .compatible = "fsl,imx8mm-vpu-blk-ctrl", .data = &imx8mm_vpu_blk_ctl_dev_data }, { + .compatible = "fsl,imx8mm-disp-blk-ctrl", + .data = &imx8mm_disp_blk_ctl_dev_data + } ,{ /* Sentinel */ } }; From 986b5094708e508baa452a23ffe809870934a7df Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 27 Jun 2021 17:54:31 +0200 Subject: [PATCH 110/179] soc/tegra: Fix an error handling path in tegra_powergate_power_up() If an error occurs after a successful tegra_powergate_enable_clocks() call, it must be undone by a tegra_powergate_disable_clocks() call, as already done in the below and above error handling paths of this function. Update the 'goto' to branch at the correct place of the error handling path. Fixes: a38045121bf4 ("soc/tegra: pmc: Add generic PM domain support") Signed-off-by: Christophe JAILLET Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 2ad7b3bceb80..6695935a81f1 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -783,7 +783,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg, err = reset_control_deassert(pg->reset); if (err) - goto powergate_off; + goto disable_clks; usleep_range(10, 20); From 982ca19a09ac0365ad1409f919da43596d2a2276 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 28 Sep 2021 10:15:45 +0800 Subject: [PATCH 111/179] memory: tegra186-emc: Fix error return code in tegra186_emc_probe() Return the error code when command fails. Fixes: 13324edbe926 ("memory: tegra186-emc: Handle errors in BPMP response") Signed-off-by: Yang Yingliang Reviewed-by: Mikko Perttunen Link: https://lore.kernel.org/r/20210928021545.3774677-1-yangyingliang@huawei.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra186-emc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c index abc0c2eeaab7..746c4ef2c0af 100644 --- a/drivers/memory/tegra/tegra186-emc.c +++ b/drivers/memory/tegra/tegra186-emc.c @@ -198,6 +198,7 @@ static int tegra186_emc_probe(struct platform_device *pdev) goto put_bpmp; } if (msg.rx.ret < 0) { + err = -EINVAL; dev_err(&pdev->dev, "EMC DVFS MRQ failed: %d (BPMP error code)\n", msg.rx.ret); goto put_bpmp; } From 4a26df8e60e534110f37e23c068f25f2f523bb83 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 5 Oct 2021 17:29:22 +0200 Subject: [PATCH 112/179] memory: renesas-rpc-if: RENESAS_RPCIF should select RESET_CONTROLLER The Renesas RPC-IF driver calls devm_reset_control_get_exclusive(), which returns -ENOTSUPP if CONFIG_RESET_CONTROLLER is not enabled. Signed-off-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Link: https://lore.kernel.org/r/e443aa66d146da5646b7ebece8876545b8621063.1633447756.git.geert+renesas@glider.be Signed-off-by: Krzysztof Kozlowski --- drivers/memory/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 72c0df129d5c..547f956f6c29 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -210,6 +210,7 @@ config RENESAS_RPCIF tristate "Renesas RPC-IF driver" depends on ARCH_RENESAS || COMPILE_TEST select REGMAP_MMIO + select RESET_CONTROLLER help This supports Renesas R-Car Gen3 or RZ/G2 RPC-IF which provides either SPI host or HyperFlash. You'll have to select individual From 31b88d85f0432e1c0738fe0714191e8504f505c3 Mon Sep 17 00:00:00 2001 From: Kai Song Date: Tue, 5 Oct 2021 12:35:14 +0800 Subject: [PATCH 113/179] memory: tegra210-emc: replace DEFINE_SIMPLE_ATTRIBUTE with fix debugfs_simple_attr.cocci warning: drivers/memory/tegra/tegra210-emc-core.c:1665:0-23: WARNING:tegra210_emc_debug_min_rate_fops should be defined with DEFINE_DEBUGFS_ATTRIBUTE Commit 6fc5f1adf5a1 ("memory: tegra210-emc: replace DEFINE_SIMPLE_ATTRIBUTE with DEFINE_DEBUGFS_ATTRIBUTE") fixed the same warning, but didn't fix all matches in this file at once. Signed-off-by: Kai Song Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20211005043514.9650-1-songkai01@inspur.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/tegra/tegra210-emc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memory/tegra/tegra210-emc-core.c b/drivers/memory/tegra/tegra210-emc-core.c index 3b8284c6678e..13584f9317a4 100644 --- a/drivers/memory/tegra/tegra210-emc-core.c +++ b/drivers/memory/tegra/tegra210-emc-core.c @@ -1662,7 +1662,7 @@ static int tegra210_emc_debug_min_rate_set(void *data, u64 rate) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(tegra210_emc_debug_min_rate_fops, +DEFINE_DEBUGFS_ATTRIBUTE(tegra210_emc_debug_min_rate_fops, tegra210_emc_debug_min_rate_get, tegra210_emc_debug_min_rate_set, "%llu\n"); From 4ed2f3545c2e5acfbccd7f85fea5b1a82e9862d7 Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Sat, 25 Sep 2021 23:14:32 +0800 Subject: [PATCH 114/179] memory: fsl_ifc: fix leak of irq and nand_irq in fsl_ifc_ctrl_probe The error handling code of fsl_ifc_ctrl_probe is problematic. When fsl_ifc_ctrl_init fails or request_irq of fsl_ifc_ctrl_dev->irq fails, it forgets to free the irq and nand_irq. Meanwhile, if request_irq of fsl_ifc_ctrl_dev->nand_irq fails, it will still free nand_irq even if the request_irq is not successful. Fix this by refactoring the error handling code. Fixes: d2ae2e20fbdd ("driver/memory:Move Freescale IFC driver to a common driver") Signed-off-by: Dongliang Mu Link: https://lore.kernel.org/r/20210925151434.8170-1-mudongliangabcd@gmail.com Signed-off-by: Krzysztof Kozlowski --- drivers/memory/fsl_ifc.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c index d062c2f8250f..75a8c38df939 100644 --- a/drivers/memory/fsl_ifc.c +++ b/drivers/memory/fsl_ifc.c @@ -263,7 +263,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev); if (ret < 0) - goto err; + goto err_unmap_nandirq; init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait); @@ -272,7 +272,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) if (ret != 0) { dev_err(&dev->dev, "failed to install irq (%d)\n", fsl_ifc_ctrl_dev->irq); - goto err_irq; + goto err_unmap_nandirq; } if (fsl_ifc_ctrl_dev->nand_irq) { @@ -281,17 +281,16 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) if (ret != 0) { dev_err(&dev->dev, "failed to install irq (%d)\n", fsl_ifc_ctrl_dev->nand_irq); - goto err_nandirq; + goto err_free_irq; } } return 0; -err_nandirq: - free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev); - irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq); -err_irq: +err_free_irq: free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev); +err_unmap_nandirq: + irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq); irq_dispose_mapping(fsl_ifc_ctrl_dev->irq); err: iounmap(fsl_ifc_ctrl_dev->gregs); From 06c2d9a078abe784fd9fd0f1534e318e827712b4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Sep 2021 14:41:40 +0200 Subject: [PATCH 115/179] firmware: tegra: Reduce stack usage Building the bpmp-debugfs driver for Arm results in a warning for stack usage: drivers/firmware/tegra/bpmp-debugfs.c:321:16: error: stack frame size of 1224 bytes in function 'bpmp_debug_store' [-Werror,-Wframe-larger-than=] static ssize_t bpmp_debug_store(struct file *file, const char __user *buf, It should be possible to rearrange the code to not require two separate buffers for the file name, but the easiest workaround is to use dynamic allocation. Fixes: 5e37b9c137ee ("firmware: tegra: Add support for in-band debug") Link: https://lore.kernel.org/all/20201204193714.3134651-1-arnd@kernel.org/ Signed-off-by: Arnd Bergmann [treding@nvidia.com: consistently return NULL on failure] Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp-debugfs.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c index 3e9fa4b54358..6d66fe03fb6a 100644 --- a/drivers/firmware/tegra/bpmp-debugfs.c +++ b/drivers/firmware/tegra/bpmp-debugfs.c @@ -74,28 +74,36 @@ static void seqbuf_seek(struct seqbuf *seqbuf, ssize_t offset) static const char *get_filename(struct tegra_bpmp *bpmp, const struct file *file, char *buf, int size) { - char root_path_buf[512]; - const char *root_path; - const char *filename; + const char *root_path, *filename = NULL; + char *root_path_buf; size_t root_len; + root_path_buf = kzalloc(512, GFP_KERNEL); + if (!root_path_buf) + goto out; + root_path = dentry_path(bpmp->debugfs_mirror, root_path_buf, sizeof(root_path_buf)); if (IS_ERR(root_path)) - return NULL; + goto out; root_len = strlen(root_path); filename = dentry_path(file->f_path.dentry, buf, size); - if (IS_ERR(filename)) - return NULL; + if (IS_ERR(filename)) { + filename = NULL; + goto out; + } - if (strlen(filename) < root_len || - strncmp(filename, root_path, root_len)) - return NULL; + if (strlen(filename) < root_len || strncmp(filename, root_path, root_len)) { + filename = NULL; + goto out; + } filename += root_len; +out: + kfree(root_path_buf); return filename; } From f11c34bddf8cd2a3107a7d11b6446c66deda9590 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Wed, 8 Sep 2021 18:56:23 +0800 Subject: [PATCH 116/179] firmware: tegra: bpmp: Use devm_platform_ioremap_resource() Use the devm_platform_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately. Signed-off-by: Cai Huoqing Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp-tegra210.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/tegra/bpmp-tegra210.c b/drivers/firmware/tegra/bpmp-tegra210.c index c32754055c60..c9c830f658c3 100644 --- a/drivers/firmware/tegra/bpmp-tegra210.c +++ b/drivers/firmware/tegra/bpmp-tegra210.c @@ -162,7 +162,6 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp) { struct platform_device *pdev = to_platform_device(bpmp->dev); struct tegra210_bpmp *priv; - struct resource *res; unsigned int i; int err; @@ -172,13 +171,11 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp) bpmp->priv = priv; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->atomics = devm_ioremap_resource(&pdev->dev, res); + priv->atomics = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->atomics)) return PTR_ERR(priv->atomics); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->arb_sema = devm_ioremap_resource(&pdev->dev, res); + priv->arb_sema = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(priv->arb_sema)) return PTR_ERR(priv->arb_sema); From 13d9624da4e10a06446e5b09d962ff42dd10357f Mon Sep 17 00:00:00 2001 From: Yongqiang Niu Date: Thu, 30 Sep 2021 23:52:21 +0800 Subject: [PATCH 117/179] soc: mediatek: add mtk mutex support for MT8192 Add mtk mutex support for MT8192 SoC. Signed-off-by: Yongqiang Niu Signed-off-by: Hsin-Yi Wang Reviewed-by: CK Hu Link: https://lore.kernel.org/r/20210930155222.5861-5-yongqiang.niu@mediatek.com Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-mutex.c | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c index 2e4bcc300576..2ca55bb5a8be 100644 --- a/drivers/soc/mediatek/mtk-mutex.c +++ b/drivers/soc/mediatek/mtk-mutex.c @@ -39,6 +39,18 @@ #define MT8167_MUTEX_MOD_DISP_DITHER 15 #define MT8167_MUTEX_MOD_DISP_UFOE 16 +#define MT8192_MUTEX_MOD_DISP_OVL0 0 +#define MT8192_MUTEX_MOD_DISP_OVL0_2L 1 +#define MT8192_MUTEX_MOD_DISP_RDMA0 2 +#define MT8192_MUTEX_MOD_DISP_COLOR0 4 +#define MT8192_MUTEX_MOD_DISP_CCORR0 5 +#define MT8192_MUTEX_MOD_DISP_AAL0 6 +#define MT8192_MUTEX_MOD_DISP_GAMMA0 7 +#define MT8192_MUTEX_MOD_DISP_POSTMASK0 8 +#define MT8192_MUTEX_MOD_DISP_DITHER0 9 +#define MT8192_MUTEX_MOD_DISP_OVL2_2L 16 +#define MT8192_MUTEX_MOD_DISP_RDMA4 17 + #define MT8183_MUTEX_MOD_DISP_RDMA0 0 #define MT8183_MUTEX_MOD_DISP_RDMA1 1 #define MT8183_MUTEX_MOD_DISP_OVL0 9 @@ -214,6 +226,20 @@ static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_WDMA0] = MT8183_MUTEX_MOD_DISP_WDMA0, }; +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, + [DDP_COMPONENT_COLOR0] = MT8192_MUTEX_MOD_DISP_COLOR0, + [DDP_COMPONENT_DITHER] = MT8192_MUTEX_MOD_DISP_DITHER0, + [DDP_COMPONENT_GAMMA] = MT8192_MUTEX_MOD_DISP_GAMMA0, + [DDP_COMPONENT_POSTMASK0] = MT8192_MUTEX_MOD_DISP_POSTMASK0, + [DDP_COMPONENT_OVL0] = MT8192_MUTEX_MOD_DISP_OVL0, + [DDP_COMPONENT_OVL_2L0] = MT8192_MUTEX_MOD_DISP_OVL0_2L, + [DDP_COMPONENT_OVL_2L2] = MT8192_MUTEX_MOD_DISP_OVL2_2L, + [DDP_COMPONENT_RDMA0] = MT8192_MUTEX_MOD_DISP_RDMA0, + [DDP_COMPONENT_RDMA4] = MT8192_MUTEX_MOD_DISP_RDMA4, +}; + static const unsigned int mt2712_mutex_sof[MUTEX_SOF_DSI3 + 1] = { [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, [MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0, @@ -275,6 +301,13 @@ static const struct mtk_mutex_data mt8183_mutex_driver_data = { .no_clk = true, }; +static const struct mtk_mutex_data mt8192_mutex_driver_data = { + .mutex_mod = mt8192_mutex_mod, + .mutex_sof = mt8183_mutex_sof, + .mutex_mod_reg = MT8183_MUTEX0_MOD0, + .mutex_sof_reg = MT8183_MUTEX0_SOF0, +}; + struct mtk_mutex *mtk_mutex_get(struct device *dev) { struct mtk_mutex_ctx *mtx = dev_get_drvdata(dev); @@ -507,6 +540,8 @@ static const struct of_device_id mutex_driver_dt_match[] = { .data = &mt8173_mutex_driver_data}, { .compatible = "mediatek,mt8183-disp-mutex", .data = &mt8183_mutex_driver_data}, + { .compatible = "mediatek,mt8192-disp-mutex", + .data = &mt8192_mutex_driver_data}, {}, }; MODULE_DEVICE_TABLE(of, mutex_driver_dt_match); From f27ef2856343e2ddc392975d7b15120442e4d7b7 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 30 Sep 2021 10:31:49 +0200 Subject: [PATCH 118/179] soc: mediatek: mmsys: Add reset controller support Among other features the mmsys driver should implement a reset controller to be able to reset different bits from their space. Cc: Jitao Shi Suggested-by: Chun-Kuang Hu Signed-off-by: Enric Balletbo i Serra Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20210930103105.v4.6.I15e2419141a69b2e5c7e700c34d92a69df47e04d@changeid Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-mmsys.c | 68 ++++++++++++++++++++++++++++++++ drivers/soc/mediatek/mtk-mmsys.h | 2 + 2 files changed, 70 insertions(+) diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index 5ecfe09a5751..1e448f1ffefb 100644 --- a/drivers/soc/mediatek/mtk-mmsys.c +++ b/drivers/soc/mediatek/mtk-mmsys.c @@ -4,10 +4,12 @@ * Author: James Liao */ +#include #include #include #include #include +#include #include #include "mtk-mmsys.h" @@ -69,6 +71,8 @@ static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = { struct mtk_mmsys { void __iomem *regs; const struct mtk_mmsys_driver_data *data; + spinlock_t lock; /* protects mmsys_sw_rst_b reg */ + struct reset_controller_dev rcdev; }; void mtk_mmsys_ddp_connect(struct device *dev, @@ -108,6 +112,58 @@ void mtk_mmsys_ddp_disconnect(struct device *dev, } EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect); +static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id, + bool assert) +{ + struct mtk_mmsys *mmsys = container_of(rcdev, struct mtk_mmsys, rcdev); + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&mmsys->lock, flags); + + reg = readl_relaxed(mmsys->regs + MMSYS_SW0_RST_B); + + if (assert) + reg &= ~BIT(id); + else + reg |= BIT(id); + + writel_relaxed(reg, mmsys->regs + MMSYS_SW0_RST_B); + + spin_unlock_irqrestore(&mmsys->lock, flags); + + return 0; +} + +static int mtk_mmsys_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + return mtk_mmsys_reset_update(rcdev, id, true); +} + +static int mtk_mmsys_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + return mtk_mmsys_reset_update(rcdev, id, false); +} + +static int mtk_mmsys_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + int ret; + + ret = mtk_mmsys_reset_assert(rcdev, id); + if (ret) + return ret; + + usleep_range(1000, 1100); + + return mtk_mmsys_reset_deassert(rcdev, id); +} + +static const struct reset_control_ops mtk_mmsys_reset_ops = { + .assert = mtk_mmsys_reset_assert, + .deassert = mtk_mmsys_reset_deassert, + .reset = mtk_mmsys_reset, +}; + static int mtk_mmsys_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -127,6 +183,18 @@ static int mtk_mmsys_probe(struct platform_device *pdev) return ret; } + spin_lock_init(&mmsys->lock); + + mmsys->rcdev.owner = THIS_MODULE; + mmsys->rcdev.nr_resets = 32; + mmsys->rcdev.ops = &mtk_mmsys_reset_ops; + mmsys->rcdev.of_node = pdev->dev.of_node; + ret = devm_reset_controller_register(&pdev->dev, &mmsys->rcdev); + if (ret) { + dev_err(&pdev->dev, "Couldn't register mmsys reset controller: %d\n", ret); + return ret; + } + mmsys->data = of_device_get_match_data(&pdev->dev); platform_set_drvdata(pdev, mmsys); diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h index 9e2b81bd38db..8b0ed05117ea 100644 --- a/drivers/soc/mediatek/mtk-mmsys.h +++ b/drivers/soc/mediatek/mtk-mmsys.h @@ -78,6 +78,8 @@ #define DSI_SEL_IN_RDMA 0x1 #define DSI_SEL_IN_MASK 0x1 +#define MMSYS_SW0_RST_B 0x140 + struct mtk_mmsys_routes { u32 from_comp; u32 to_comp; From 605c83753d97946aab176735020a33ebfb0b4615 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 30 Sep 2021 10:31:50 +0200 Subject: [PATCH 119/179] drm/mediatek: mtk_dsi: Reset the dsi0 hardware Reset dsi0 HW to default when power on. This prevents to have different settingis between the bootloader and the kernel. As not all Mediatek boards have the reset consumer configured in their board description, also is not needed on all of them, the reset is optional, so the change is compatible with all boards. Cc: Jitao Shi Suggested-by: Chun-Kuang Hu Signed-off-by: Enric Balletbo i Serra Acked-by: Chun-Kuang Hu Reviewed-by: Matthias Brugger Link: https://lore.kernel.org/r/20210930103105.v4.7.Idbb4727ddf00ba2fe796b630906baff10d994d89@changeid Signed-off-by: Matthias Brugger --- drivers/gpu/drm/mediatek/mtk_dsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 93b40c245f00..5d90d2eb0019 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -11,6 +11,7 @@ #include #include #include +#include #include