diff options
Diffstat (limited to 'drivers/soc')
29 files changed, 511 insertions, 161 deletions
diff --git a/drivers/soc/mediatek/mt8173-pm-domains.h b/drivers/soc/mediatek/mt8173-pm-domains.h index 654c717e5467..714fa92575df 100644 --- a/drivers/soc/mediatek/mt8173-pm-domains.h +++ b/drivers/soc/mediatek/mt8173-pm-domains.h @@ -71,6 +71,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { .ctl_offs = SPM_MFG_ASYNC_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = 0, + .caps = MTK_SCPD_DOMAIN_SUPPLY, }, [MT8173_POWER_DOMAIN_MFG_2D] = { .name = "mfg_2d", diff --git a/drivers/soc/mediatek/mt8183-mmsys.h b/drivers/soc/mediatek/mt8183-mmsys.h index 579dfc8dc8fc..9dee485807c9 100644 --- a/drivers/soc/mediatek/mt8183-mmsys.h +++ b/drivers/soc/mediatek/mt8183-mmsys.h @@ -28,25 +28,32 @@ static const struct mtk_mmsys_routes mmsys_mt8183_routing_table[] = { { DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL_2L0, - MT8183_DISP_OVL0_MOUT_EN, MT8183_OVL0_MOUT_EN_OVL0_2L + MT8183_DISP_OVL0_MOUT_EN, MT8183_OVL0_MOUT_EN_OVL0_2L, + MT8183_OVL0_MOUT_EN_OVL0_2L }, { DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0, - MT8183_DISP_OVL0_2L_MOUT_EN, MT8183_OVL0_2L_MOUT_EN_DISP_PATH0 + MT8183_DISP_OVL0_2L_MOUT_EN, MT8183_OVL0_2L_MOUT_EN_DISP_PATH0, + MT8183_OVL0_2L_MOUT_EN_DISP_PATH0 }, { DDP_COMPONENT_OVL_2L1, DDP_COMPONENT_RDMA1, - MT8183_DISP_OVL1_2L_MOUT_EN, MT8183_OVL1_2L_MOUT_EN_RDMA1 + MT8183_DISP_OVL1_2L_MOUT_EN, MT8183_OVL1_2L_MOUT_EN_RDMA1, + MT8183_OVL1_2L_MOUT_EN_RDMA1 }, { DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0, - MT8183_DISP_DITHER0_MOUT_EN, MT8183_DITHER0_MOUT_IN_DSI0 + MT8183_DISP_DITHER0_MOUT_EN, MT8183_DITHER0_MOUT_IN_DSI0, + MT8183_DITHER0_MOUT_IN_DSI0 }, { DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0, - MT8183_DISP_PATH0_SEL_IN, MT8183_DISP_PATH0_SEL_IN_OVL0_2L + MT8183_DISP_PATH0_SEL_IN, MT8183_DISP_PATH0_SEL_IN_OVL0_2L, + MT8183_DISP_PATH0_SEL_IN_OVL0_2L }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, - MT8183_DISP_DPI0_SEL_IN, MT8183_DPI0_SEL_IN_RDMA1 + MT8183_DISP_DPI0_SEL_IN, MT8183_DPI0_SEL_IN_RDMA1, + MT8183_DPI0_SEL_IN_RDMA1 }, { DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, - MT8183_DISP_RDMA0_SOUT_SEL_IN, MT8183_RDMA0_SOUT_COLOR0 + MT8183_DISP_RDMA0_SOUT_SEL_IN, MT8183_RDMA0_SOUT_COLOR0, + MT8183_RDMA0_SOUT_COLOR0 } }; diff --git a/drivers/soc/mediatek/mt8365-mmsys.h b/drivers/soc/mediatek/mt8365-mmsys.h new file mode 100644 index 000000000000..690e3fe2dee0 --- /dev/null +++ b/drivers/soc/mediatek/mt8365-mmsys.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_MT8365_MMSYS_H +#define __SOC_MEDIATEK_MT8365_MMSYS_H + +#define MT8365_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0xf3c +#define MT8365_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL 0xf4c +#define MT8365_DISP_REG_CONFIG_DISP_DITHER0_MOUT_EN 0xf50 +#define MT8365_DISP_REG_CONFIG_DISP_RDMA0_SEL_IN 0xf54 +#define MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN 0xf60 +#define MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0xf64 +#define MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN 0xf68 + +#define MT8365_RDMA0_SOUT_COLOR0 0x1 +#define MT8365_DITHER_MOUT_EN_DSI0 0x1 +#define MT8365_DSI0_SEL_IN_DITHER 0x1 +#define MT8365_RDMA0_SEL_IN_OVL0 0x0 +#define MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 0x0 +#define MT8365_DISP_COLOR_SEL_IN_COLOR0 0x0 +#define MT8365_OVL0_MOUT_PATH0_SEL BIT(0) + +static const struct mtk_mmsys_routes mt8365_mmsys_routing_table[] = { + { + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, + MT8365_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, + MT8365_OVL0_MOUT_PATH0_SEL, MT8365_OVL0_MOUT_PATH0_SEL + }, + { + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, + MT8365_DISP_REG_CONFIG_DISP_RDMA0_SEL_IN, + MT8365_RDMA0_SEL_IN_OVL0, MT8365_RDMA0_SEL_IN_OVL0 + }, + { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, + MT8365_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL, + MT8365_RDMA0_SOUT_COLOR0, MT8365_RDMA0_SOUT_COLOR0 + }, + { + DDP_COMPONENT_COLOR0, DDP_COMPONENT_CCORR, + MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, + MT8365_DISP_COLOR_SEL_IN_COLOR0,MT8365_DISP_COLOR_SEL_IN_COLOR0 + }, + { + DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0, + MT8365_DISP_REG_CONFIG_DISP_DITHER0_MOUT_EN, + MT8365_DITHER_MOUT_EN_DSI0, MT8365_DITHER_MOUT_EN_DSI0 + }, + { + DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0, + MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, + MT8365_DSI0_SEL_IN_DITHER, MT8365_DSI0_SEL_IN_DITHER + }, + { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, + MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN, + MT8365_RDMA0_RSZ0_SEL_IN_RDMA0, MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 + }, +}; + +#endif /* __SOC_MEDIATEK_MT8365_MMSYS_H */ diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index 080660ef11bf..a78e88f27b62 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 "mt8365-mmsys.h" static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { .clk_driver = "clk-mt2701-mm", @@ -52,6 +53,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 mt8365_mmsys_driver_data = { + .clk_driver = "clk-mt8365-mm", + .routes = mt8365_mmsys_routing_table, + .num_routes = ARRAY_SIZE(mt8365_mmsys_routing_table), +}; + struct mtk_mmsys { void __iomem *regs; const struct mtk_mmsys_driver_data *data; @@ -68,7 +75,9 @@ void mtk_mmsys_ddp_connect(struct device *dev, for (i = 0; i < mmsys->data->num_routes; i++) if (cur == routes[i].from_comp && next == routes[i].to_comp) { - reg = readl_relaxed(mmsys->regs + routes[i].addr) | routes[i].val; + reg = readl_relaxed(mmsys->regs + routes[i].addr); + reg &= ~routes[i].mask; + reg |= routes[i].val; writel_relaxed(reg, mmsys->regs + routes[i].addr); } } @@ -85,7 +94,8 @@ void mtk_mmsys_ddp_disconnect(struct device *dev, for (i = 0; i < mmsys->data->num_routes; i++) if (cur == routes[i].from_comp && next == routes[i].to_comp) { - reg = readl_relaxed(mmsys->regs + routes[i].addr) & ~routes[i].val; + reg = readl_relaxed(mmsys->regs + routes[i].addr); + reg &= ~routes[i].mask; writel_relaxed(reg, mmsys->regs + routes[i].addr); } } @@ -157,6 +167,10 @@ static const struct of_device_id of_match_mtk_mmsys[] = { .compatible = "mediatek,mt8183-mmsys", .data = &mt8183_mmsys_driver_data, }, + { + .compatible = "mediatek,mt8365-mmsys", + .data = &mt8365_mmsys_driver_data, + }, { } }; diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h index a760a34e6eca..9e2b81bd38db 100644 --- a/drivers/soc/mediatek/mtk-mmsys.h +++ b/drivers/soc/mediatek/mtk-mmsys.h @@ -35,41 +35,54 @@ #define RDMA0_SOUT_DSI1 0x1 #define RDMA0_SOUT_DSI2 0x4 #define RDMA0_SOUT_DSI3 0x5 +#define RDMA0_SOUT_MASK 0x7 #define RDMA1_SOUT_DPI0 0x2 #define RDMA1_SOUT_DPI1 0x3 #define RDMA1_SOUT_DSI1 0x1 #define RDMA1_SOUT_DSI2 0x4 #define RDMA1_SOUT_DSI3 0x5 +#define RDMA1_SOUT_MASK 0x7 #define RDMA2_SOUT_DPI0 0x2 #define RDMA2_SOUT_DPI1 0x3 #define RDMA2_SOUT_DSI1 0x1 #define RDMA2_SOUT_DSI2 0x4 #define RDMA2_SOUT_DSI3 0x5 +#define RDMA2_SOUT_MASK 0x7 #define DPI0_SEL_IN_RDMA1 0x1 #define DPI0_SEL_IN_RDMA2 0x3 +#define DPI0_SEL_IN_MASK 0x3 #define DPI1_SEL_IN_RDMA1 (0x1 << 8) #define DPI1_SEL_IN_RDMA2 (0x3 << 8) +#define DPI1_SEL_IN_MASK (0x3 << 8) #define DSI0_SEL_IN_RDMA1 0x1 #define DSI0_SEL_IN_RDMA2 0x4 +#define DSI0_SEL_IN_MASK 0x7 #define DSI1_SEL_IN_RDMA1 0x1 #define DSI1_SEL_IN_RDMA2 0x4 +#define DSI1_SEL_IN_MASK 0x7 #define DSI2_SEL_IN_RDMA1 (0x1 << 16) #define DSI2_SEL_IN_RDMA2 (0x4 << 16) +#define DSI2_SEL_IN_MASK (0x7 << 16) #define DSI3_SEL_IN_RDMA1 (0x1 << 16) #define DSI3_SEL_IN_RDMA2 (0x4 << 16) +#define DSI3_SEL_IN_MASK (0x7 << 16) #define COLOR1_SEL_IN_OVL1 0x1 #define OVL_MOUT_EN_RDMA 0x1 #define BLS_TO_DSI_RDMA1_TO_DPI1 0x8 #define BLS_TO_DPI_RDMA1_TO_DSI 0x2 +#define BLS_RDMA1_DSI_DPI_MASK 0xf #define DSI_SEL_IN_BLS 0x0 #define DPI_SEL_IN_BLS 0x0 +#define DPI_SEL_IN_MASK 0x1 #define DSI_SEL_IN_RDMA 0x1 +#define DSI_SEL_IN_MASK 0x1 struct mtk_mmsys_routes { u32 from_comp; u32 to_comp; u32 addr; + u32 mask; u32 val; }; @@ -91,124 +104,168 @@ struct mtk_mmsys_driver_data { static const struct mtk_mmsys_routes mmsys_default_routing_table[] = { { DDP_COMPONENT_BLS, DDP_COMPONENT_DSI0, - DISP_REG_CONFIG_OUT_SEL, BLS_TO_DSI_RDMA1_TO_DPI1 + DISP_REG_CONFIG_OUT_SEL, BLS_RDMA1_DSI_DPI_MASK, + BLS_TO_DSI_RDMA1_TO_DPI1 }, { DDP_COMPONENT_BLS, DDP_COMPONENT_DSI0, - DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_BLS + DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_MASK, + DSI_SEL_IN_BLS }, { DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0, - DISP_REG_CONFIG_OUT_SEL, BLS_TO_DPI_RDMA1_TO_DSI + DISP_REG_CONFIG_OUT_SEL, BLS_RDMA1_DSI_DPI_MASK, + BLS_TO_DPI_RDMA1_TO_DSI }, { DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0, - DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_RDMA + DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_MASK, + DSI_SEL_IN_RDMA }, { DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0, - DISP_REG_CONFIG_DPI_SEL, DPI_SEL_IN_BLS + DISP_REG_CONFIG_DPI_SEL, DPI_SEL_IN_MASK, + DPI_SEL_IN_BLS }, { DDP_COMPONENT_GAMMA, DDP_COMPONENT_RDMA1, - DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN, GAMMA_MOUT_EN_RDMA1 + DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN, GAMMA_MOUT_EN_RDMA1, + GAMMA_MOUT_EN_RDMA1 }, { DDP_COMPONENT_OD0, DDP_COMPONENT_RDMA0, - DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD_MOUT_EN_RDMA0 + DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD_MOUT_EN_RDMA0, + OD_MOUT_EN_RDMA0 }, { DDP_COMPONENT_OD1, DDP_COMPONENT_RDMA1, - DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD1_MOUT_EN_RDMA1 + DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD1_MOUT_EN_RDMA1, + OD1_MOUT_EN_RDMA1 }, { DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, - DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0 + DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0, + OVL0_MOUT_EN_COLOR0 }, { DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, - DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0 + DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0, + COLOR0_SEL_IN_OVL0 }, { DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, - DISP_REG_CONFIG_DISP_OVL_MOUT_EN, OVL_MOUT_EN_RDMA + DISP_REG_CONFIG_DISP_OVL_MOUT_EN, OVL_MOUT_EN_RDMA, + OVL_MOUT_EN_RDMA }, { DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1, - DISP_REG_CONFIG_DISP_OVL1_MOUT_EN, OVL1_MOUT_EN_COLOR1 + DISP_REG_CONFIG_DISP_OVL1_MOUT_EN, OVL1_MOUT_EN_COLOR1, + OVL1_MOUT_EN_COLOR1 }, { DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1, - DISP_REG_CONFIG_DISP_COLOR1_SEL_IN, COLOR1_SEL_IN_OVL1 + DISP_REG_CONFIG_DISP_COLOR1_SEL_IN, COLOR1_SEL_IN_OVL1, + COLOR1_SEL_IN_OVL1 }, { DDP_COMPONENT_RDMA0, DDP_COMPONENT_DPI0, - DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DPI0 + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK, + RDMA0_SOUT_DPI0 }, { DDP_COMPONENT_RDMA0, DDP_COMPONENT_DPI1, - DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DPI1 + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK, + RDMA0_SOUT_DPI1 }, { DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI1, - DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI1 + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK, + RDMA0_SOUT_DSI1 }, { DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI2, - DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI2 + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK, + RDMA0_SOUT_DSI2 }, { DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI3, - DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI3 + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_MASK, + RDMA0_SOUT_DSI3 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, - DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DPI0 + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK, + RDMA1_SOUT_DPI0 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, - DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_RDMA1 + DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_MASK, + DPI0_SEL_IN_RDMA1 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI1, - DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DPI1 + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK, + RDMA1_SOUT_DPI1 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI1, - DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_RDMA1 + DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_MASK, + DPI1_SEL_IN_RDMA1 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI0, - DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_RDMA1 + DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_MASK, + DSI0_SEL_IN_RDMA1 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI1, - DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI1 + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK, + RDMA1_SOUT_DSI1 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI1, - DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_RDMA1 + DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_MASK, + DSI1_SEL_IN_RDMA1 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI2, - DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI2 + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK, + RDMA1_SOUT_DSI2 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI2, - DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_RDMA1 + DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_MASK, + DSI2_SEL_IN_RDMA1 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI3, - DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI3 + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK, + RDMA1_SOUT_DSI3 }, { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI3, - DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_RDMA1 + DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_MASK, + DSI3_SEL_IN_RDMA1 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI0, - DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DPI0 + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK, + RDMA2_SOUT_DPI0 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI0, - DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_RDMA2 + DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_MASK, + DPI0_SEL_IN_RDMA2 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI1, - DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DPI1 + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK, + RDMA2_SOUT_DPI1 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI1, - DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_RDMA2 + DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_MASK, + DPI1_SEL_IN_RDMA2 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI0, - DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_RDMA2 + DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_MASK, + DSI0_SEL_IN_RDMA2 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI1, - DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI1 + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK, + RDMA2_SOUT_DSI1 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI1, - DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_RDMA2 + DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_MASK, + DSI1_SEL_IN_RDMA2 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI2, - DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI2 + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK, + RDMA2_SOUT_DSI2 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI2, - DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_RDMA2 + DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_MASK, + DSI2_SEL_IN_RDMA2 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI3, - DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI3 + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_MASK, + RDMA2_SOUT_DSI3 }, { DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI3, - DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_RDMA2 + DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_MASK, + DSI3_SEL_IN_RDMA2 + }, { + DDP_COMPONENT_UFOE, DDP_COMPONENT_DSI0, + DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, UFOE_MOUT_EN_DSI0, + UFOE_MOUT_EN_DSI0 } }; diff --git a/drivers/soc/mediatek/mtk-pm-domains.h b/drivers/soc/mediatek/mtk-pm-domains.h index 21a4e113bbec..c5ac649ae51b 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.h +++ b/drivers/soc/mediatek/mtk-pm-domains.h @@ -60,7 +60,7 @@ #define BUS_PROT_UPDATE_TOPAXI(_mask) \ BUS_PROT_UPDATE(_mask, \ INFRA_TOPAXI_PROTECTEN, \ - INFRA_TOPAXI_PROTECTEN_CLR, \ + INFRA_TOPAXI_PROTECTEN, \ INFRA_TOPAXI_PROTECTSTA1) struct scpsys_bus_prot_data { diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c index b24cc77d1889..4ce8e816154f 100644 --- a/drivers/soc/qcom/cpr.c +++ b/drivers/soc/qcom/cpr.c @@ -801,38 +801,6 @@ unlock: return ret; } -static int cpr_read_efuse(struct device *dev, const char *cname, u32 *data) -{ - struct nvmem_cell *cell; - ssize_t len; - char *ret; - int i; - - *data = 0; - - cell = nvmem_cell_get(dev, cname); - if (IS_ERR(cell)) { - if (PTR_ERR(cell) != -EPROBE_DEFER) - dev_err(dev, "undefined cell %s\n", cname); - return PTR_ERR(cell); - } - - ret = nvmem_cell_read(cell, &len); - nvmem_cell_put(cell); - if (IS_ERR(ret)) { - dev_err(dev, "can't read cell %s\n", cname); - return PTR_ERR(ret); - } - - for (i = 0; i < len; i++) - *data |= ret[i] << (8 * i); - - kfree(ret); - dev_dbg(dev, "efuse read(%s) = %x, bytes %zd\n", cname, *data, len); - - return 0; -} - static int cpr_populate_ring_osc_idx(struct cpr_drv *drv) { @@ -843,8 +811,7 @@ cpr_populate_ring_osc_idx(struct cpr_drv *drv) int ret; for (; fuse < end; fuse++, fuses++) { - ret = cpr_read_efuse(drv->dev, fuses->ring_osc, - &data); + ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data); if (ret) return ret; fuse->ring_osc_idx = data; @@ -863,7 +830,7 @@ static int cpr_read_fuse_uV(const struct cpr_desc *desc, u32 bits = 0; int ret; - ret = cpr_read_efuse(drv->dev, init_v_efuse, &bits); + ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits); if (ret) return ret; @@ -932,7 +899,7 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv) } /* Populate target quotient by scaling */ - ret = cpr_read_efuse(drv->dev, fuses->quotient, &fuse->quot); + ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot); if (ret) return ret; @@ -1001,7 +968,7 @@ static int cpr_calculate_scaling(const char *quot_offset, prev_fuse = fuse - 1; if (quot_offset) { - ret = cpr_read_efuse(drv->dev, quot_offset, "_diff); + ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, "_diff); if (ret) return ret; @@ -1701,7 +1668,7 @@ static int cpr_probe(struct platform_device *pdev) * initialized after attaching to the power domain, * since it depends on the CPU's OPP table. */ - ret = cpr_read_efuse(dev, "cpr_fuse_revision", &cpr_rev); + ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev); if (ret) return ret; diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index eba7f76f9d61..bda170d7b4a2 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -166,6 +166,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, metadata = qcom_mdt_read_metadata(fw, &metadata_len); if (IS_ERR(metadata)) { ret = PTR_ERR(metadata); + dev_err(dev, "error %d reading firmware %s metadata\n", + ret, fw_name); goto out; } @@ -173,7 +175,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, kfree(metadata); if (ret) { - dev_err(dev, "invalid firmware metadata\n"); + /* Invalid firmware metadata */ + dev_err(dev, "error %d initializing firmware %s\n", + ret, fw_name); goto out; } } @@ -199,7 +203,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); if (ret) { - dev_err(dev, "unable to setup relocation\n"); + /* Unable to set up relocation */ + dev_err(dev, "error %d setting up firmware %s\n", + ret, fw_name); goto out; } } @@ -243,9 +249,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, if (phdr->p_filesz && phdr->p_offset < fw->size) { /* Firmware is large enough to be non-split */ if (phdr->p_offset + phdr->p_filesz > fw->size) { - dev_err(dev, - "failed to load segment %d from truncated file %s\n", - i, firmware); + dev_err(dev, "file %s segment %d would be truncated\n", + fw_name, i); ret = -EINVAL; break; } @@ -257,7 +262,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, ret = request_firmware_into_buf(&seg_fw, fw_name, dev, ptr, phdr->p_filesz); if (ret) { - dev_err(dev, "failed to load %s\n", fw_name); + dev_err(dev, "error %d loading %s\n", + ret, fw_name); break; } diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 5bdfb1565c14..7d649d2cf31e 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -104,7 +104,6 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config", #define GENI_OUTPUT_CTRL 0x24 #define GENI_CGC_CTRL 0x28 #define GENI_CLK_CTRL_RO 0x60 -#define GENI_IF_DISABLE_RO 0x64 #define GENI_FW_S_REVISION_RO 0x6c #define SE_GENI_BYTE_GRAN 0x254 #define SE_GENI_TX_PACKING_CFG0 0x260 @@ -322,6 +321,30 @@ static void geni_se_select_dma_mode(struct geni_se *se) writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); } +static void geni_se_select_gpi_mode(struct geni_se *se) +{ + u32 val; + + geni_se_irq_clear(se); + + writel(0, se->base + SE_IRQ_EN); + + val = readl(se->base + SE_GENI_S_IRQ_EN); + val &= ~S_CMD_DONE_EN; + writel(val, se->base + SE_GENI_S_IRQ_EN); + + val = readl(se->base + SE_GENI_M_IRQ_EN); + val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN | + M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); + writel(val, se->base + SE_GENI_M_IRQ_EN); + + writel(GENI_DMA_MODE_EN, se->base + SE_GENI_DMA_MODE_EN); + + val = readl(se->base + SE_GSI_EVENT_EN); + val |= (DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | GENI_M_EVENT_EN | GENI_S_EVENT_EN); + writel(val, se->base + SE_GSI_EVENT_EN); +} + /** * geni_se_select_mode() - Select the serial engine transfer mode * @se: Pointer to the concerned serial engine. @@ -329,7 +352,7 @@ static void geni_se_select_dma_mode(struct geni_se *se) */ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode) { - WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA); + WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA && mode != GENI_GPI_DMA); switch (mode) { case GENI_SE_FIFO: @@ -338,6 +361,9 @@ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode) case GENI_SE_DMA: geni_se_select_dma_mode(se); break; + case GENI_GPI_DMA: + geni_se_select_gpi_mode(se); + break; case GENI_SE_INVALID: default: break; diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 934fcc4d2b05..536c3e4114fb 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -476,12 +476,12 @@ static int qmp_cooling_device_add(struct qmp *qmp, static int qmp_cooling_devices_register(struct qmp *qmp) { struct device_node *np, *child; - int count = QMP_NUM_COOLING_RESOURCES; + int count = 0; int ret; np = qmp->dev->of_node; - qmp->cooling_devs = devm_kcalloc(qmp->dev, count, + qmp->cooling_devs = devm_kcalloc(qmp->dev, QMP_NUM_COOLING_RESOURCES, sizeof(*qmp->cooling_devs), GFP_KERNEL); @@ -497,12 +497,16 @@ static int qmp_cooling_devices_register(struct qmp *qmp) goto unroll; } + if (!count) + devm_kfree(qmp->dev, qmp->cooling_devs); + return 0; unroll: while (--count >= 0) thermal_cooling_device_unregister (qmp->cooling_devs[count].cdev); + devm_kfree(qmp->dev, qmp->cooling_devs); return ret; } @@ -602,6 +606,7 @@ static const struct of_device_id qmp_dt_match[] = { { .compatible = "qcom,sm8150-aoss-qmp", }, { .compatible = "qcom,sm8250-aoss-qmp", }, { .compatible = "qcom,sm8350-aoss-qmp", }, + { .compatible = "qcom,aoss-qmp", }, {} }; MODULE_DEVICE_TABLE(of, qmp_dt_match); diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c index 2daa17ba54a3..fa209b479ab3 100644 --- a/drivers/soc/qcom/rpmhpd.c +++ b/drivers/soc/qcom/rpmhpd.c @@ -403,12 +403,11 @@ static int rpmhpd_power_on(struct generic_pm_domain *domain) static int rpmhpd_power_off(struct generic_pm_domain *domain) { struct rpmhpd *pd = domain_to_rpmhpd(domain); - int ret = 0; + int ret; mutex_lock(&rpmhpd_lock); - ret = rpmhpd_aggregate_corner(pd, pd->level[0]); - + ret = rpmhpd_aggregate_corner(pd, 0); if (!ret) pd->enabled = false; diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 0b532a892d60..dbf494e92574 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -346,6 +346,33 @@ static const struct rpmpd_desc sdm660_desc = { .max_state = RPM_SMD_LEVEL_TURBO, }; +/* sm4250/6115 RPM Power domains */ +DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0); +DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0); + +DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0); +DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0); + +DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0); +DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0); + +static struct rpmpd *sm6115_rpmpds[] = { + [SM6115_VDDCX] = &sm6115_vddcx, + [SM6115_VDDCX_AO] = &sm6115_vddcx_ao, + [SM6115_VDDCX_VFL] = &sm6115_vddcx_vfl, + [SM6115_VDDMX] = &sm6115_vddmx, + [SM6115_VDDMX_AO] = &sm6115_vddmx_ao, + [SM6115_VDDMX_VFL] = &sm6115_vddmx_vfl, + [SM6115_VDD_LPI_CX] = &sm6115_vdd_lpi_cx, + [SM6115_VDD_LPI_MX] = &sm6115_vdd_lpi_mx, +}; + +static const struct rpmpd_desc sm6115_desc = { + .rpmpds = sm6115_rpmpds, + .num_pds = ARRAY_SIZE(sm6115_rpmpds), + .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, +}; + static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, @@ -356,6 +383,7 @@ static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc }, { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc }, + { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc }, { } }; MODULE_DEVICE_TABLE(of, rpmpd_match_table); diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c index bc0be1d4be5f..dfdd4f20f5fd 100644 --- a/drivers/soc/qcom/smd-rpm.c +++ b/drivers/soc/qcom/smd-rpm.c @@ -242,6 +242,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = { { .compatible = "qcom,rpm-msm8996" }, { .compatible = "qcom,rpm-msm8998" }, { .compatible = "qcom,rpm-sdm660" }, + { .compatible = "qcom,rpm-sm6115" }, { .compatible = "qcom,rpm-sm6125" }, { .compatible = "qcom,rpm-qcs404" }, {} diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c index 1d3d5e3ec2b0..ef15d014c03a 100644 --- a/drivers/soc/qcom/smsm.c +++ b/drivers/soc/qcom/smsm.c @@ -109,7 +109,7 @@ struct smsm_entry { DECLARE_BITMAP(irq_enabled, 32); DECLARE_BITMAP(irq_rising, 32); DECLARE_BITMAP(irq_falling, 32); - u32 last_value; + unsigned long last_value; u32 *remote_state; u32 *subscription; @@ -204,8 +204,7 @@ static irqreturn_t smsm_intr(int irq, void *data) u32 val; val = readl(entry->remote_state); - changed = val ^ entry->last_value; - entry->last_value = val; + changed = val ^ xchg(&entry->last_value, val); for_each_set_bit(i, entry->irq_enabled, 32) { if (!(changed & BIT(i))) @@ -264,6 +263,12 @@ static void smsm_unmask_irq(struct irq_data *irqd) struct qcom_smsm *smsm = entry->smsm; u32 val; + /* Make sure our last cached state is up-to-date */ + if (readl(entry->remote_state) & BIT(irq)) + set_bit(irq, &entry->last_value); + else + clear_bit(irq, &entry->last_value); + set_bit(irq, entry->irq_enabled); if (entry->subscription) { @@ -299,11 +304,28 @@ static int smsm_set_irq_type(struct irq_data *irqd, unsigned int type) return 0; } +static int smsm_get_irqchip_state(struct irq_data *irqd, + enum irqchip_irq_state which, bool *state) +{ + struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd); + irq_hw_number_t irq = irqd_to_hwirq(irqd); + u32 val; + + if (which != IRQCHIP_STATE_LINE_LEVEL) + return -EINVAL; + + val = readl(entry->remote_state); + *state = !!(val & BIT(irq)); + + return 0; +} + static struct irq_chip smsm_irq_chip = { .name = "smsm", .irq_mask = smsm_mask_irq, .irq_unmask = smsm_unmask_irq, .irq_set_type = smsm_set_irq_type, + .irq_get_irqchip_state = smsm_get_irqchip_state, }; /** diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index b2f049faa3df..9faf48302f4b 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -417,8 +417,8 @@ QCOM_OPEN(chip_id, qcom_show_chip_id); static int show_image_##type(struct seq_file *seq, void *p) \ { \ struct smem_image_version *image_version = seq->private; \ - seq_puts(seq, image_version->type); \ - seq_putc(seq, '\n'); \ + if (image_version->type[0] != '\0') \ + seq_printf(seq, "%s\n", image_version->type); \ return 0; \ } \ static int open_image_##type(struct inode *inode, struct file *file) \ diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 71b44c31b012..07e0ecd64319 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -208,6 +208,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. config ARCH_R8A77965 bool "ARM64 Platform support for R-Car M3-N" @@ -229,6 +230,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. config ARCH_R8A77980 bool "ARM64 Platform support for R-Car V3H" diff --git a/drivers/soc/renesas/r8a779a0-sysc.c b/drivers/soc/renesas/r8a779a0-sysc.c index d464ffa1be33..7410b9fa9846 100644 --- a/drivers/soc/renesas/r8a779a0-sysc.c +++ b/drivers/soc/renesas/r8a779a0-sysc.c @@ -404,19 +404,21 @@ static int __init r8a779a0_sysc_pd_init(void) for (i = 0; i < info->num_areas; i++) { const struct r8a779a0_sysc_area *area = &info->areas[i]; struct r8a779a0_sysc_pd *pd; + size_t n; if (!area->name) { /* Skip NULLified area */ continue; } - pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL); + n = strlen(area->name) + 1; + pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL); if (!pd) { error = -ENOMEM; goto out_put; } - strcpy(pd->name, area->name); + memcpy(pd->name, area->name, n); pd->genpd.name = pd->name; pd->pdr = area->pdr; pd->flags = area->flags; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 53387a72ca00..b0a80de34c98 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -396,19 +396,21 @@ static int __init rcar_sysc_pd_init(void) for (i = 0; i < info->num_areas; i++) { const struct rcar_sysc_area *area = &info->areas[i]; struct rcar_sysc_pd *pd; + size_t n; if (!area->name) { /* Skip NULLified area */ continue; } - pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL); + n = strlen(area->name) + 1; + pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL); if (!pd) { error = -ENOMEM; goto out_put; } - strcpy(pd->name, area->name); + memcpy(pd->name, area->name, n); pd->genpd.name = pd->name; pd->ch.chan_offs = area->chan_offs; pd->ch.chan_bit = area->chan_bit; diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 8310fce7714e..dab9f5a0aad0 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -284,11 +284,15 @@ static const struct of_device_id renesas_socs[] __initconst = { #if defined(CONFIG_ARCH_R8A77950) || defined(CONFIG_ARCH_R8A77951) { .compatible = "renesas,r8a7795", .data = &soc_rcar_h3 }, #endif +#ifdef CONFIG_ARCH_R8A77951 + { .compatible = "renesas,r8a779m1", .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,r8a779m3", .data = &soc_rcar_m3_w }, #endif #ifdef CONFIG_ARCH_R8A77965 { .compatible = "renesas,r8a77965", .data = &soc_rcar_m3_n }, diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig index 2c13bf4dd5db..25eb2c1e31bb 100644 --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -6,8 +6,8 @@ if ARCH_ROCKCHIP || COMPILE_TEST # config ROCKCHIP_GRF - bool - default y + bool "Rockchip General Register Files support" if COMPILE_TEST + default y if ARCH_ROCKCHIP help The General Register Files are a central component providing special additional settings registers for a lot of soc-components. diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c index cf8182fc3642..9df513d1219b 100644 --- a/drivers/soc/rockchip/io-domain.c +++ b/drivers/soc/rockchip/io-domain.c @@ -51,13 +51,11 @@ #define RK3399_PMUGRF_CON0_VSEL BIT(8) #define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9 -struct rockchip_iodomain; +#define RK3568_PMU_GRF_IO_VSEL0 (0x0140) +#define RK3568_PMU_GRF_IO_VSEL1 (0x0144) +#define RK3568_PMU_GRF_IO_VSEL2 (0x0148) -struct rockchip_iodomain_soc_data { - int grf_offset; - const char *supply_names[MAX_SUPPLIES]; - void (*init)(struct rockchip_iodomain *iod); -}; +struct rockchip_iodomain; struct rockchip_iodomain_supply { struct rockchip_iodomain *iod; @@ -66,13 +64,62 @@ struct rockchip_iodomain_supply { int idx; }; +struct rockchip_iodomain_soc_data { + int grf_offset; + const char *supply_names[MAX_SUPPLIES]; + void (*init)(struct rockchip_iodomain *iod); + int (*write)(struct rockchip_iodomain_supply *supply, int uV); +}; + struct rockchip_iodomain { struct device *dev; struct regmap *grf; const struct rockchip_iodomain_soc_data *soc_data; struct rockchip_iodomain_supply supplies[MAX_SUPPLIES]; + int (*write)(struct rockchip_iodomain_supply *supply, int uV); }; +static int rk3568_iodomain_write(struct rockchip_iodomain_supply *supply, int uV) +{ + struct rockchip_iodomain *iod = supply->iod; + u32 is_3v3 = uV > MAX_VOLTAGE_1_8; + u32 val0, val1; + int b; + + switch (supply->idx) { + case 0: /* pmuio1 */ + break; + case 1: /* pmuio2 */ + b = supply->idx; + val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b)); + b = supply->idx + 4; + val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0); + + regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val0); + regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val1); + break; + case 3: /* vccio2 */ + break; + case 2: /* vccio1 */ + case 4: /* vccio3 */ + case 5: /* vccio4 */ + case 6: /* vccio5 */ + case 7: /* vccio6 */ + case 8: /* vccio7 */ + b = supply->idx - 1; + val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b)); + val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0); + + regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL0, val0); + regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL1, val1); + break; + default: + return -EINVAL; + } + + return 0; +} + static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply, int uV) { @@ -136,7 +183,7 @@ static int rockchip_iodomain_notify(struct notifier_block *nb, return NOTIFY_BAD; } - ret = rockchip_iodomain_write(supply, uV); + ret = supply->iod->write(supply, uV); if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) return NOTIFY_BAD; @@ -398,6 +445,22 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = { .init = rk3399_pmu_iodomain_init, }; +static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = { + .grf_offset = 0x140, + .supply_names = { + "pmuio1", + "pmuio2", + "vccio1", + "vccio2", + "vccio3", + "vccio4", + "vccio5", + "vccio6", + "vccio7", + }, + .write = rk3568_iodomain_write, +}; + static const struct rockchip_iodomain_soc_data soc_data_rv1108 = { .grf_offset = 0x404, .supply_names = { @@ -470,6 +533,10 @@ static const struct of_device_id rockchip_iodomain_match[] = { .data = &soc_data_rk3399_pmu }, { + .compatible = "rockchip,rk3568-pmu-io-voltage-domain", + .data = &soc_data_rk3568_pmu + }, + { .compatible = "rockchip,rv1108-io-voltage-domain", .data = &soc_data_rv1108 }, @@ -502,6 +569,11 @@ static int rockchip_iodomain_probe(struct platform_device *pdev) match = of_match_node(rockchip_iodomain_match, np); iod->soc_data = match->data; + if (iod->soc_data->write) + iod->write = iod->soc_data->write; + else + iod->write = rockchip_iodomain_write; + parent = pdev->dev.parent; if (parent && parent->of_node) { iod->grf = syscon_node_to_regmap(parent->of_node); @@ -562,7 +634,7 @@ static int rockchip_iodomain_probe(struct platform_device *pdev) supply->reg = reg; supply->nb.notifier_call = rockchip_iodomain_notify; - ret = rockchip_iodomain_write(supply, uV); + ret = iod->write(supply, uV); if (ret) { supply->reg = NULL; goto unreg_notify; diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 3d9da3d359da..f2151815db58 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -13,6 +13,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/sys_soc.h> @@ -210,6 +211,8 @@ static int tegra_fuse_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fuse); fuse->dev = &pdev->dev; + pm_runtime_enable(&pdev->dev); + if (fuse->soc->probe) { err = fuse->soc->probe(fuse); if (err < 0) @@ -246,14 +249,71 @@ static int tegra_fuse_probe(struct platform_device *pdev) return 0; restore: + fuse->clk = NULL; fuse->base = base; + pm_runtime_disable(&pdev->dev); return err; } +static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev) +{ + int err; + + err = clk_prepare_enable(fuse->clk); + if (err < 0) { + dev_err(dev, "failed to enable FUSE clock: %d\n", err); + return err; + } + + return 0; +} + +static int __maybe_unused tegra_fuse_runtime_suspend(struct device *dev) +{ + clk_disable_unprepare(fuse->clk); + + return 0; +} + +static int __maybe_unused tegra_fuse_suspend(struct device *dev) +{ + int ret; + + /* + * Critical for RAM re-repair operation, which must occur on resume + * from LP1 system suspend and as part of CCPLEX cluster switching. + */ + if (fuse->soc->clk_suspend_on) + ret = pm_runtime_resume_and_get(dev); + else + ret = pm_runtime_force_suspend(dev); + + return ret; +} + +static int __maybe_unused tegra_fuse_resume(struct device *dev) +{ + int ret = 0; + + if (fuse->soc->clk_suspend_on) + pm_runtime_put(dev); + else + ret = pm_runtime_force_resume(dev); + + return ret; +} + +static const struct dev_pm_ops tegra_fuse_pm = { + SET_RUNTIME_PM_OPS(tegra_fuse_runtime_suspend, tegra_fuse_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra_fuse_suspend, tegra_fuse_resume) +}; + static struct platform_driver tegra_fuse_driver = { .driver = { .name = "tegra-fuse", .of_match_table = tegra_fuse_match, + .pm = &tegra_fuse_pm, .suppress_bind_attrs = true, }, .probe = tegra_fuse_probe, diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c index 16aaa28573ac..8ec9fc5e5e4b 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra20.c +++ b/drivers/soc/tegra/fuse/fuse-tegra20.c @@ -16,6 +16,7 @@ #include <linux/kobject.h> #include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/random.h> #include <soc/tegra/fuse.h> @@ -46,6 +47,10 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) u32 value = 0; int err; + err = pm_runtime_resume_and_get(fuse->dev); + if (err) + return err; + mutex_lock(&fuse->apbdma.lock); fuse->apbdma.config.src_addr = fuse->phys + FUSE_BEGIN + offset; @@ -66,8 +71,6 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) reinit_completion(&fuse->apbdma.wait); - clk_prepare_enable(fuse->clk); - dmaengine_submit(dma_desc); dma_async_issue_pending(fuse->apbdma.chan); time_left = wait_for_completion_timeout(&fuse->apbdma.wait, @@ -78,10 +81,9 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) else value = *fuse->apbdma.virt; - clk_disable_unprepare(fuse->clk); - out: mutex_unlock(&fuse->apbdma.lock); + pm_runtime_put(fuse->dev); return value; } @@ -165,4 +167,5 @@ const struct tegra_fuse_soc tegra20_fuse_soc = { .probe = tegra20_fuse_probe, .info = &tegra20_fuse_info, .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index c1aa7815bd6e..b071d433d74f 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -12,6 +12,7 @@ #include <linux/of_device.h> #include <linux/of_address.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/random.h> #include <soc/tegra/fuse.h> @@ -52,15 +53,13 @@ static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset) u32 value; int err; - err = clk_prepare_enable(fuse->clk); - if (err < 0) { - dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err); + err = pm_runtime_resume_and_get(fuse->dev); + if (err) return 0; - } value = readl_relaxed(fuse->base + FUSE_BEGIN + offset); - clk_disable_unprepare(fuse->clk); + pm_runtime_put(fuse->dev); return value; } @@ -113,6 +112,7 @@ const struct tegra_fuse_soc tegra30_fuse_soc = { .speedo_init = tegra30_init_speedo_data, .info = &tegra30_fuse_info, .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -128,6 +128,7 @@ const struct tegra_fuse_soc tegra114_fuse_soc = { .speedo_init = tegra114_init_speedo_data, .info = &tegra114_fuse_info, .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -209,6 +210,7 @@ const struct tegra_fuse_soc tegra124_fuse_soc = { .lookups = tegra124_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra124_fuse_lookups), .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = true, }; #endif @@ -295,6 +297,7 @@ const struct tegra_fuse_soc tegra210_fuse_soc = { .lookups = tegra210_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra210_fuse_lookups), .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -325,6 +328,7 @@ const struct tegra_fuse_soc tegra186_fuse_soc = { .lookups = tegra186_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra186_fuse_lookups), .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -355,6 +359,7 @@ const struct tegra_fuse_soc tegra194_fuse_soc = { .lookups = tegra194_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra194_fuse_lookups), .soc_attr_group = &tegra194_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -385,5 +390,6 @@ const struct tegra_fuse_soc tegra234_fuse_soc = { .lookups = tegra234_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra234_fuse_lookups), .soc_attr_group = &tegra194_soc_attr_group, + .clk_suspend_on = false, }; #endif diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h index e057a58e2060..de58feba0435 100644 --- a/drivers/soc/tegra/fuse/fuse.h +++ b/drivers/soc/tegra/fuse/fuse.h @@ -34,6 +34,8 @@ struct tegra_fuse_soc { unsigned int num_lookups; const struct attribute_group *soc_attr_group; + + bool clk_suspend_on; }; struct tegra_fuse { diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index ea62f84d1c8b..50091c4ec948 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -436,7 +436,7 @@ struct tegra_pmc { static struct tegra_pmc *pmc = &(struct tegra_pmc) { .base = NULL, - .suspend_mode = TEGRA_SUSPEND_NONE, + .suspend_mode = TEGRA_SUSPEND_NOT_READY, }; static inline struct tegra_powergate * @@ -1812,6 +1812,7 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np) u32 value, values[2]; if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) { + pmc->suspend_mode = TEGRA_SUSPEND_NONE; } else { switch (value) { case 0: @@ -2785,6 +2786,11 @@ static int tegra_pmc_regmap_init(struct tegra_pmc *pmc) return 0; } +static void tegra_pmc_reset_suspend_mode(void *data) +{ + pmc->suspend_mode = TEGRA_SUSPEND_NOT_READY; +} + static int tegra_pmc_probe(struct platform_device *pdev) { void __iomem *base; @@ -2803,6 +2809,11 @@ static int tegra_pmc_probe(struct platform_device *pdev) if (err < 0) return err; + err = devm_add_action_or_reset(&pdev->dev, tegra_pmc_reset_suspend_mode, + NULL); + if (err) + return err; + /* take over the memory region from the early initialization */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); @@ -2909,6 +2920,7 @@ static int tegra_pmc_probe(struct platform_device *pdev) tegra_pmc_clock_register(pmc, pdev->dev.of_node); platform_set_drvdata(pdev, pmc); + tegra_pm_init_suspend(); return 0; diff --git a/drivers/soc/tegra/powergate-bpmp.c b/drivers/soc/tegra/powergate-bpmp.c index 06c792bafca5..8eaf50d0b6af 100644 --- a/drivers/soc/tegra/powergate-bpmp.c +++ b/drivers/soc/tegra/powergate-bpmp.c @@ -7,7 +7,6 @@ #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/slab.h> -#include <linux/version.h> #include <soc/tegra/bpmp.h> #include <soc/tegra/bpmp-abi.h> diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index f22ac1edbdd0..49da387d7749 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -338,6 +338,7 @@ static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,k2g-pruss" }, { .compatible = "ti,am654-icssg", .data = &am65x_j721e_pruss_data, }, { .compatible = "ti,j721e-icssg", .data = &am65x_j721e_pruss_data, }, + { .compatible = "ti,am642-icssg", .data = &am65x_j721e_pruss_data, }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c index 06cbee5fd254..b5b2fa538d5c 100644 --- a/drivers/soc/ti/smartreflex.c +++ b/drivers/soc/ti/smartreflex.c @@ -126,23 +126,13 @@ static irqreturn_t sr_interrupt(int irq, void *data) static void sr_set_clk_length(struct omap_sr *sr) { - struct clk *fck; u32 fclk_speed; /* Try interconnect target module fck first if it already exists */ - fck = clk_get(sr->pdev->dev.parent, "fck"); - if (IS_ERR(fck)) { - fck = clk_get(&sr->pdev->dev, "fck"); - if (IS_ERR(fck)) { - dev_err(&sr->pdev->dev, - "%s: unable to get fck for device %s\n", - __func__, dev_name(&sr->pdev->dev)); - return; - } - } + if (IS_ERR(sr->fck)) + return; - fclk_speed = clk_get_rate(fck); - clk_put(fck); + fclk_speed = clk_get_rate(sr->fck); switch (fclk_speed) { case 12000000: @@ -587,21 +577,25 @@ int sr_enable(struct omap_sr *sr, unsigned long volt) /* errminlimit is opp dependent and hence linked to voltage */ sr->err_minlimit = nvalue_row->errminlimit; - pm_runtime_get_sync(&sr->pdev->dev); + clk_enable(sr->fck); /* Check if SR is already enabled. If yes do nothing */ if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) - return 0; + goto out_enabled; /* Configure SR */ ret = sr_class->configure(sr); if (ret) - return ret; + goto out_enabled; sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue); /* SRCONFIG - enable SR */ sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE); + +out_enabled: + sr->enabled = 1; + return 0; } @@ -621,7 +615,7 @@ void sr_disable(struct omap_sr *sr) } /* Check if SR clocks are already disabled. If yes do nothing */ - if (pm_runtime_suspended(&sr->pdev->dev)) + if (!sr->enabled) return; /* @@ -642,7 +636,8 @@ void sr_disable(struct omap_sr *sr) } } - pm_runtime_put_sync_suspend(&sr->pdev->dev); + clk_disable(sr->fck); + sr->enabled = 0; } /** @@ -851,8 +846,12 @@ static int omap_sr_probe(struct platform_device *pdev) irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + sr_info->fck = devm_clk_get(pdev->dev.parent, "fck"); + if (IS_ERR(sr_info->fck)) + return PTR_ERR(sr_info->fck); + clk_prepare(sr_info->fck); + pm_runtime_enable(&pdev->dev); - pm_runtime_irq_safe(&pdev->dev); snprintf(sr_info->name, SMARTREFLEX_NAME_LEN, "%s", pdata->name); @@ -878,12 +877,6 @@ static int omap_sr_probe(struct platform_device *pdev) list_add(&sr_info->node, &sr_list); - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) { - pm_runtime_put_noidle(&pdev->dev); - goto err_list_del; - } - /* * Call into late init to do initializations that require * both sr driver and sr class driver to be initiallized. @@ -933,16 +926,13 @@ static int omap_sr_probe(struct platform_device *pdev) } - pm_runtime_put_sync(&pdev->dev); - return ret; err_debugfs: debugfs_remove_recursive(sr_info->dbg_dir); err_list_del: list_del(&sr_info->node); - - pm_runtime_put_sync(&pdev->dev); + clk_unprepare(sr_info->fck); return ret; } @@ -950,6 +940,7 @@ err_list_del: static int omap_sr_remove(struct platform_device *pdev) { struct omap_sr_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; struct omap_sr *sr_info; if (!pdata) { @@ -968,7 +959,8 @@ static int omap_sr_remove(struct platform_device *pdev) sr_stop_vddautocomp(sr_info); debugfs_remove_recursive(sr_info->dbg_dir); - pm_runtime_disable(&pdev->dev); + pm_runtime_disable(dev); + clk_unprepare(sr_info->fck); list_del(&sr_info->node); return 0; } |