diff options
author | Arnd Bergmann <arnd@arndb.de> | 2023-12-22 11:12:46 +0000 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2023-12-22 11:12:55 +0000 |
commit | e92c0b8b1592ef58c5fb65625b5a90f84b6b4c44 (patch) | |
tree | bd14aafd0f0eddff1099ef00c4aa23e5392bde4a /drivers/soc | |
parent | 125b02edde58b316c2eeb078b7719dc21f5a979d (diff) | |
parent | 2bfbf82956e2de75249ce83901800c68d17d9e62 (diff) |
Merge tag 'mtk-soc-for-v6.8' of https://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux into soc/drivers
MediaTek soc driver updates for v6.8
This adds a refactoring of the MediaTek Smart Voltage Scaling (SVS)
driver and the addition of support for MT8186 and MT8195 in it, and
adds support for the MT8188 VDOSYS and resets in the MMSYS driver.
* tag 'mtk-soc-for-v6.8' of https://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux: (24 commits)
soc: mediatek: mtk-svs: Constify runtime-immutable members of svs_bank
soc: mediatek: mtk-svs: Use ULONG_MAX to compare floor frequency
soc: mediatek: mtk-svs: Check if SVS mode is available in the beginning
soc: mediatek: mtk-svs: Cleanup of svs_probe() function
soc: mediatek: mtk-svs: Compress of_device_id entries
soc: mediatek: mtk-svs: Remove redundant print in svs_get_efuse_data
soc: mediatek: mtk-svs: Commonize MT8192 probe function for MT8186
soc: mediatek: mtk-svs: Drop supplementary svs per-bank pointer
soc: mediatek: mtk-svs: Commonize efuse parse function for most SoCs
soc: mediatek: mtk-svs: Move t-calibration-data retrieval to svs_probe()
soc: mediatek: mtk-svs: Add SVS-Thermal coefficient to SoC platform data
soc: mediatek: mtk-svs: Add a map to retrieve fused values
soc: mediatek: mtk-svs: Change the thermal sensor device name
soc: mediatek: mtk-svs: Reduce memory footprint of struct svs_bank
soc: mediatek: mtk-svs: Build bank name string dynamically
soc: mediatek: mtk-svs: Convert sw_id and type to enumerations
soc: mediatek: mtk-svs: Subtract offset from regs_v2 to avoid conflict
soc: mediatek: Add MT8188 VDOSYS reset bit map
soc: mediatek: Support reset bit mapping in mmsys driver
soc: mediatek: Support MT8188 VDOSYS1 Padding in mtk-mmsys
...
Link: https://lore.kernel.org/r/20231212114515.121695-2-angelogioacchino.delregno@collabora.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/soc')
-rw-r--r-- | drivers/soc/mediatek/mt8188-mmsys.h | 210 | ||||
-rw-r--r-- | drivers/soc/mediatek/mtk-mmsys.c | 39 | ||||
-rw-r--r-- | drivers/soc/mediatek/mtk-mmsys.h | 32 | ||||
-rw-r--r-- | drivers/soc/mediatek/mtk-mutex.c | 51 | ||||
-rw-r--r-- | drivers/soc/mediatek/mtk-svs.c | 1678 |
5 files changed, 1334 insertions, 676 deletions
diff --git a/drivers/soc/mediatek/mt8188-mmsys.h b/drivers/soc/mediatek/mt8188-mmsys.h index 448cc3761b43..6bebf1a69fc0 100644 --- a/drivers/soc/mediatek/mt8188-mmsys.h +++ b/drivers/soc/mediatek/mt8188-mmsys.h @@ -3,6 +3,10 @@ #ifndef __SOC_MEDIATEK_MT8188_MMSYS_H #define __SOC_MEDIATEK_MT8188_MMSYS_H +#include <linux/soc/mediatek/mtk-mmsys.h> +#include <dt-bindings/reset/mt8188-resets.h> + +#define MT8188_VDO0_SW0_RST_B 0x190 #define MT8188_VDO0_OVL_MOUT_EN 0xf14 #define MT8188_MOUT_DISP_OVL0_TO_DISP_RDMA0 BIT(0) #define MT8188_MOUT_DISP_OVL0_TO_DISP_WDMA0 BIT(1) @@ -67,6 +71,136 @@ #define MT8188_SOUT_DSC_WRAP0_OUT_TO_VPP_MERGE BIT(18) #define MT8188_SOUT_DSC_WRAP0_OUT_TO_DISP_WDMA0 BIT(19) +#define MT8188_VDO1_SW0_RST_B 0x1d0 +#define MT8188_VDO1_HDR_TOP_CFG 0xd00 +#define MT8188_VDO1_MIXER_IN1_ALPHA 0xd30 +#define MT8188_VDO1_MIXER_IN1_PAD 0xd40 +#define MT8188_VDO1_MIXER_VSYNC_LEN 0xd5c +#define MT8188_VDO1_MERGE0_ASYNC_CFG_WD 0xe30 +#define MT8188_VDO1_HDRBE_ASYNC_CFG_WD 0xe70 +#define MT8188_VDO1_VPP_MERGE0_P0_SEL_IN 0xf04 +#define MT8188_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0 1 +#define MT8188_VDO1_VPP_MERGE0_P1_SEL_IN 0xf08 +#define MT8188_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1 1 +#define MT8188_VDO1_DISP_DPI1_SEL_IN 0xf10 +#define MT8188_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT 0 +#define MT8188_VDO1_DISP_DP_INTF0_SEL_IN 0xf14 +#define MT8188_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT 0 +#define MT8188_VDO1_MERGE4_SOUT_SEL 0xf18 +#define MT8188_MERGE4_SOUT_TO_DPI1_SEL BIT(2) +#define MT8188_MERGE4_SOUT_TO_DP_INTF0_SEL BIT(3) +#define MT8188_VDO1_MIXER_IN1_SEL_IN 0xf24 +#define MT8188_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT 1 +#define MT8188_VDO1_MIXER_IN2_SEL_IN 0xf28 +#define MT8188_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT 1 +#define MT8188_VDO1_MIXER_IN3_SEL_IN 0xf2c +#define MT8188_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT 1 +#define MT8188_VDO1_MIXER_IN4_SEL_IN 0xf30 +#define MT8188_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT 1 +#define MT8188_VDO1_MIXER_OUT_SOUT_SEL 0xf34 +#define MT8188_MIXER_SOUT_TO_MERGE4_ASYNC_SEL 1 +#define MT8188_VDO1_VPP_MERGE1_P0_SEL_IN 0xf3c +#define MT8188_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2 1 +#define MT8188_VDO1_MERGE0_ASYNC_SOUT_SEL 0xf40 +#define MT8188_SOUT_TO_MIXER_IN1_SEL 1 +#define MT8188_VDO1_MERGE1_ASYNC_SOUT_SEL 0xf44 +#define MT8188_SOUT_TO_MIXER_IN2_SEL 1 +#define MT8188_VDO1_MERGE2_ASYNC_SOUT_SEL 0xf48 +#define MT8188_SOUT_TO_MIXER_IN3_SEL 1 +#define MT8188_VDO1_MERGE3_ASYNC_SOUT_SEL 0xf4c +#define MT8188_SOUT_TO_MIXER_IN4_SEL 1 +#define MT8188_VDO1_MERGE4_ASYNC_SEL_IN 0xf50 +#define MT8188_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT 1 +#define MT8188_VDO1_MIXER_IN1_SOUT_SEL 0xf58 +#define MT8188_MIXER_IN1_SOUT_TO_DISP_MIXER 0 +#define MT8188_VDO1_MIXER_IN2_SOUT_SEL 0xf5c +#define MT8188_MIXER_IN2_SOUT_TO_DISP_MIXER 0 +#define MT8188_VDO1_MIXER_IN3_SOUT_SEL 0xf60 +#define MT8188_MIXER_IN3_SOUT_TO_DISP_MIXER 0 +#define MT8188_VDO1_MIXER_IN4_SOUT_SEL 0xf64 +#define MT8188_MIXER_IN4_SOUT_TO_DISP_MIXER 0 +#define MT8188_VDO1_MIXER_SOUT_SEL_IN 0xf68 +#define MT8188_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER 0 + +static const u8 mmsys_mt8188_vdo0_rst_tb[] = { + [MT8188_VDO0_RST_DISP_OVL0] = MMSYS_RST_NR(0, 0), + [MT8188_VDO0_RST_FAKE_ENG0] = MMSYS_RST_NR(0, 2), + [MT8188_VDO0_RST_DISP_CCORR0] = MMSYS_RST_NR(0, 4), + [MT8188_VDO0_RST_DISP_MUTEX0] = MMSYS_RST_NR(0, 6), + [MT8188_VDO0_RST_DISP_GAMMA0] = MMSYS_RST_NR(0, 8), + [MT8188_VDO0_RST_DISP_DITHER0] = MMSYS_RST_NR(0, 10), + [MT8188_VDO0_RST_DISP_WDMA0] = MMSYS_RST_NR(0, 17), + [MT8188_VDO0_RST_DISP_RDMA0] = MMSYS_RST_NR(0, 19), + [MT8188_VDO0_RST_DSI0] = MMSYS_RST_NR(0, 21), + [MT8188_VDO0_RST_DSI1] = MMSYS_RST_NR(0, 22), + [MT8188_VDO0_RST_DSC_WRAP0] = MMSYS_RST_NR(0, 23), + [MT8188_VDO0_RST_VPP_MERGE0] = MMSYS_RST_NR(0, 24), + [MT8188_VDO0_RST_DP_INTF0] = MMSYS_RST_NR(0, 25), + [MT8188_VDO0_RST_DISP_AAL0] = MMSYS_RST_NR(0, 26), + [MT8188_VDO0_RST_INLINEROT0] = MMSYS_RST_NR(0, 27), + [MT8188_VDO0_RST_APB_BUS] = MMSYS_RST_NR(0, 28), + [MT8188_VDO0_RST_DISP_COLOR0] = MMSYS_RST_NR(0, 29), + [MT8188_VDO0_RST_MDP_WROT0] = MMSYS_RST_NR(0, 30), + [MT8188_VDO0_RST_DISP_RSZ0] = MMSYS_RST_NR(0, 31), +}; + +static const u8 mmsys_mt8188_vdo1_rst_tb[] = { + [MT8188_VDO1_RST_SMI_LARB2] = MMSYS_RST_NR(0, 0), + [MT8188_VDO1_RST_SMI_LARB3] = MMSYS_RST_NR(0, 1), + [MT8188_VDO1_RST_GALS] = MMSYS_RST_NR(0, 2), + [MT8188_VDO1_RST_FAKE_ENG0] = MMSYS_RST_NR(0, 3), + [MT8188_VDO1_RST_FAKE_ENG1] = MMSYS_RST_NR(0, 4), + [MT8188_VDO1_RST_MDP_RDMA0] = MMSYS_RST_NR(0, 5), + [MT8188_VDO1_RST_MDP_RDMA1] = MMSYS_RST_NR(0, 6), + [MT8188_VDO1_RST_MDP_RDMA2] = MMSYS_RST_NR(0, 7), + [MT8188_VDO1_RST_MDP_RDMA3] = MMSYS_RST_NR(0, 8), + [MT8188_VDO1_RST_VPP_MERGE0] = MMSYS_RST_NR(0, 9), + [MT8188_VDO1_RST_VPP_MERGE1] = MMSYS_RST_NR(0, 10), + [MT8188_VDO1_RST_VPP_MERGE2] = MMSYS_RST_NR(0, 11), + [MT8188_VDO1_RST_VPP_MERGE3] = MMSYS_RST_NR(1, 0), + [MT8188_VDO1_RST_VPP_MERGE4] = MMSYS_RST_NR(1, 1), + [MT8188_VDO1_RST_VPP2_TO_VDO1_DL_ASYNC] = MMSYS_RST_NR(1, 2), + [MT8188_VDO1_RST_VPP3_TO_VDO1_DL_ASYNC] = MMSYS_RST_NR(1, 3), + [MT8188_VDO1_RST_DISP_MUTEX] = MMSYS_RST_NR(1, 4), + [MT8188_VDO1_RST_MDP_RDMA4] = MMSYS_RST_NR(1, 5), + [MT8188_VDO1_RST_MDP_RDMA5] = MMSYS_RST_NR(1, 6), + [MT8188_VDO1_RST_MDP_RDMA6] = MMSYS_RST_NR(1, 7), + [MT8188_VDO1_RST_MDP_RDMA7] = MMSYS_RST_NR(1, 8), + [MT8188_VDO1_RST_DP_INTF1_MMCK] = MMSYS_RST_NR(1, 9), + [MT8188_VDO1_RST_DPI0_MM_CK] = MMSYS_RST_NR(1, 10), + [MT8188_VDO1_RST_DPI1_MM_CK] = MMSYS_RST_NR(1, 11), + [MT8188_VDO1_RST_MERGE0_DL_ASYNC] = MMSYS_RST_NR(1, 13), + [MT8188_VDO1_RST_MERGE1_DL_ASYNC] = MMSYS_RST_NR(1, 14), + [MT8188_VDO1_RST_MERGE2_DL_ASYNC] = MMSYS_RST_NR(1, 15), + [MT8188_VDO1_RST_MERGE3_DL_ASYNC] = MMSYS_RST_NR(1, 16), + [MT8188_VDO1_RST_MERGE4_DL_ASYNC] = MMSYS_RST_NR(1, 17), + [MT8188_VDO1_RST_VDO0_DSC_TO_VDO1_DL_ASYNC] = MMSYS_RST_NR(1, 18), + [MT8188_VDO1_RST_VDO0_MERGE_TO_VDO1_DL_ASYNC] = MMSYS_RST_NR(1, 19), + [MT8188_VDO1_RST_PADDING0] = MMSYS_RST_NR(1, 20), + [MT8188_VDO1_RST_PADDING1] = MMSYS_RST_NR(1, 21), + [MT8188_VDO1_RST_PADDING2] = MMSYS_RST_NR(1, 22), + [MT8188_VDO1_RST_PADDING3] = MMSYS_RST_NR(1, 23), + [MT8188_VDO1_RST_PADDING4] = MMSYS_RST_NR(1, 24), + [MT8188_VDO1_RST_PADDING5] = MMSYS_RST_NR(1, 25), + [MT8188_VDO1_RST_PADDING6] = MMSYS_RST_NR(1, 26), + [MT8188_VDO1_RST_PADDING7] = MMSYS_RST_NR(1, 27), + [MT8188_VDO1_RST_DISP_RSZ0] = MMSYS_RST_NR(1, 28), + [MT8188_VDO1_RST_DISP_RSZ1] = MMSYS_RST_NR(1, 29), + [MT8188_VDO1_RST_DISP_RSZ2] = MMSYS_RST_NR(1, 30), + [MT8188_VDO1_RST_DISP_RSZ3] = MMSYS_RST_NR(1, 31), + [MT8188_VDO1_RST_HDR_VDO_FE0] = MMSYS_RST_NR(2, 0), + [MT8188_VDO1_RST_HDR_GFX_FE0] = MMSYS_RST_NR(2, 1), + [MT8188_VDO1_RST_HDR_VDO_BE] = MMSYS_RST_NR(2, 2), + [MT8188_VDO1_RST_HDR_VDO_FE1] = MMSYS_RST_NR(2, 16), + [MT8188_VDO1_RST_HDR_GFX_FE1] = MMSYS_RST_NR(2, 17), + [MT8188_VDO1_RST_DISP_MIXER] = MMSYS_RST_NR(2, 18), + [MT8188_VDO1_RST_HDR_VDO_FE0_DL_ASYNC] = MMSYS_RST_NR(2, 19), + [MT8188_VDO1_RST_HDR_VDO_FE1_DL_ASYNC] = MMSYS_RST_NR(2, 20), + [MT8188_VDO1_RST_HDR_GFX_FE0_DL_ASYNC] = MMSYS_RST_NR(2, 21), + [MT8188_VDO1_RST_HDR_GFX_FE1_DL_ASYNC] = MMSYS_RST_NR(2, 22), + [MT8188_VDO1_RST_HDR_VDO_BE_DL_ASYNC] = MMSYS_RST_NR(2, 23), +}; + static const struct mtk_mmsys_routes mmsys_mt8188_routing_table[] = { { DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, @@ -146,4 +280,80 @@ static const struct mtk_mmsys_routes mmsys_mt8188_routing_table[] = { }, }; +static const struct mtk_mmsys_routes mmsys_mt8188_vdo1_routing_table[] = { + { + DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1, + MT8188_VDO1_VPP_MERGE0_P0_SEL_IN, GENMASK(0, 0), + MT8188_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0 + }, { + DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1, + MT8188_VDO1_VPP_MERGE0_P1_SEL_IN, GENMASK(0, 0), + MT8188_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1 + }, { + DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2, + MT8188_VDO1_VPP_MERGE1_P0_SEL_IN, GENMASK(0, 0), + MT8188_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2 + }, { + DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER, + MT8188_VDO1_MERGE0_ASYNC_SOUT_SEL, GENMASK(1, 0), + MT8188_SOUT_TO_MIXER_IN1_SEL + }, { + DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER, + MT8188_VDO1_MERGE1_ASYNC_SOUT_SEL, GENMASK(1, 0), + MT8188_SOUT_TO_MIXER_IN2_SEL + }, { + DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER, + MT8188_VDO1_MERGE2_ASYNC_SOUT_SEL, GENMASK(1, 0), + MT8188_SOUT_TO_MIXER_IN3_SEL + }, { + DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER, + MT8188_VDO1_MERGE3_ASYNC_SOUT_SEL, GENMASK(1, 0), + MT8188_SOUT_TO_MIXER_IN4_SEL + }, { + DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5, + MT8188_VDO1_MIXER_OUT_SOUT_SEL, GENMASK(0, 0), + MT8188_MIXER_SOUT_TO_MERGE4_ASYNC_SEL + }, { + DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER, + MT8188_VDO1_MIXER_IN1_SEL_IN, GENMASK(0, 0), + MT8188_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT + }, { + DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER, + MT8188_VDO1_MIXER_IN2_SEL_IN, GENMASK(0, 0), + MT8188_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT + }, { + DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER, + MT8188_VDO1_MIXER_IN3_SEL_IN, GENMASK(0, 0), + MT8188_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT + }, { + DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER, + MT8188_VDO1_MIXER_IN4_SEL_IN, GENMASK(0, 0), + MT8188_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT + }, { + DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5, + MT8188_VDO1_MIXER_SOUT_SEL_IN, GENMASK(2, 0), + MT8188_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER + }, { + DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5, + MT8188_VDO1_MERGE4_ASYNC_SEL_IN, GENMASK(2, 0), + MT8188_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT + }, { + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1, + MT8188_VDO1_DISP_DPI1_SEL_IN, GENMASK(1, 0), + MT8188_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT + }, { + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1, + MT8188_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0), + MT8188_MERGE4_SOUT_TO_DPI1_SEL + }, { + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1, + MT8188_VDO1_DISP_DP_INTF0_SEL_IN, GENMASK(1, 0), + MT8188_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT + }, { + DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1, + MT8188_VDO1_MERGE4_SOUT_SEL, GENMASK(3, 0), + MT8188_MERGE4_SOUT_TO_DP_INTF0_SEL + } +}; + #endif /* __SOC_MEDIATEK_MT8188_MMSYS_H */ diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index 88209102ff3b..f370f4ec4b88 100644 --- a/drivers/soc/mediatek/mtk-mmsys.c +++ b/drivers/soc/mediatek/mtk-mmsys.c @@ -87,6 +87,29 @@ static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = { .clk_driver = "clk-mt8188-vdo0", .routes = mmsys_mt8188_routing_table, .num_routes = ARRAY_SIZE(mmsys_mt8188_routing_table), + .sw0_rst_offset = MT8188_VDO0_SW0_RST_B, + .rst_tb = mmsys_mt8188_vdo0_rst_tb, + .num_resets = ARRAY_SIZE(mmsys_mt8188_vdo0_rst_tb), +}; + +static const struct mtk_mmsys_driver_data mt8188_vdosys1_driver_data = { + .clk_driver = "clk-mt8188-vdo1", + .routes = mmsys_mt8188_vdo1_routing_table, + .num_routes = ARRAY_SIZE(mmsys_mt8188_vdo1_routing_table), + .sw0_rst_offset = MT8188_VDO1_SW0_RST_B, + .rst_tb = mmsys_mt8188_vdo1_rst_tb, + .num_resets = ARRAY_SIZE(mmsys_mt8188_vdo1_rst_tb), + .vsync_len = 1, +}; + +static const struct mtk_mmsys_driver_data mt8188_vppsys0_driver_data = { + .clk_driver = "clk-mt8188-vpp0", + .is_vppsys = true, +}; + +static const struct mtk_mmsys_driver_data mt8188_vppsys1_driver_data = { + .clk_driver = "clk-mt8188-vpp1", + .is_vppsys = true, }; static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { @@ -169,6 +192,10 @@ void mtk_mmsys_ddp_connect(struct device *dev, if (cur == routes[i].from_comp && next == routes[i].to_comp) mtk_mmsys_update_bits(mmsys, routes[i].addr, routes[i].mask, routes[i].val, NULL); + + if (mmsys->data->vsync_len) + mtk_mmsys_update_bits(mmsys, MT8188_VDO1_MIXER_VSYNC_LEN, GENMASK(31, 0), + mmsys->data->vsync_len, NULL); } EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect); @@ -302,6 +329,15 @@ static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned l u32 offset; u32 reg; + if (mmsys->data->rst_tb) { + if (id >= mmsys->data->num_resets) { + dev_err(rcdev->dev, "Invalid reset ID: %lu (>=%u)\n", + id, mmsys->data->num_resets); + return -EINVAL; + } + id = mmsys->data->rst_tb[id]; + } + offset = (id / MMSYS_SW_RESET_PER_REG) * sizeof(u32); id = id % MMSYS_SW_RESET_PER_REG; reg = mmsys->data->sw0_rst_offset + offset; @@ -429,6 +465,9 @@ static const struct of_device_id of_match_mtk_mmsys[] = { { .compatible = "mediatek,mt8183-mmsys", .data = &mt8183_mmsys_driver_data }, { .compatible = "mediatek,mt8186-mmsys", .data = &mt8186_mmsys_driver_data }, { .compatible = "mediatek,mt8188-vdosys0", .data = &mt8188_vdosys0_driver_data }, + { .compatible = "mediatek,mt8188-vdosys1", .data = &mt8188_vdosys1_driver_data }, + { .compatible = "mediatek,mt8188-vppsys0", .data = &mt8188_vppsys0_driver_data }, + { .compatible = "mediatek,mt8188-vppsys1", .data = &mt8188_vppsys1_driver_data }, { .compatible = "mediatek,mt8192-mmsys", .data = &mt8192_mmsys_driver_data }, /* "mediatek,mt8195-mmsys" compatible is deprecated */ { .compatible = "mediatek,mt8195-mmsys", .data = &mt8195_vdosys0_driver_data }, diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h index 6725403d2e3a..d370192737ca 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_RST_NR(bank, bit) (((bank) * 32) + (bit)) + struct mtk_mmsys_routes { u32 from_comp; u32 to_comp; @@ -86,13 +88,43 @@ struct mtk_mmsys_routes { u32 val; }; +/** + * struct mtk_mmsys_driver_data - Settings of the mmsys + * @clk_driver: Clock driver name that the mmsys is using + * (defined in drivers/clk/mediatek/clk-*.c). + * @routes: Routing table of the mmsys. + * It provides mux settings from one module to another. + * @num_routes: Array size of the routes. + * @sw0_rst_offset: Register offset for the reset control. + * @num_resets: Number of reset bits that are defined + * @is_vppsys: Whether the mmsys is VPPSYS (Video Processing Pipe) + * or VDOSYS (Video). Only VDOSYS needs to be added to drm driver. + * @vsync_len: VSYNC length of the MIXER. + * VSYNC is usually triggered by the connector, so its length is a + * fixed value when the frame rate is decided, but ETHDR and + * MIXER generate their own VSYNC due to hardware design, therefore + * MIXER has to sync with ETHDR by adjusting VSYNC length. + * On MT8195, there is no such setting so we use the gap between + * falling edge and rising edge of SOF (Start of Frame) signal to + * do the job, but since MT8188, VSYNC_LEN setting is introduced to + * solve the problem and is given 0x40 (ticks) as the default value. + * Please notice that this value has to be set to 1 (minimum) if + * ETHDR is bypassed, otherwise MIXER could wait too long and causing + * underflow. + * + * Each MMSYS (multi-media system) may have different settings, they may use + * different clock sources, mux settings, reset control ...etc., and these + * differences are all stored here. + */ struct mtk_mmsys_driver_data { const char *clk_driver; const struct mtk_mmsys_routes *routes; const unsigned int num_routes; const u16 sw0_rst_offset; + const u8 *rst_tb; const u32 num_resets; const bool is_vppsys; + const u8 vsync_len; }; /* diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c index 9d9f5ae578ac..73c256d3950b 100644 --- a/drivers/soc/mediatek/mtk-mutex.c +++ b/drivers/soc/mediatek/mtk-mutex.c @@ -133,6 +133,30 @@ #define MT8188_MUTEX_MOD_DISP_POSTMASK0 24 #define MT8188_MUTEX_MOD2_DISP_PWM0 33 +#define MT8188_MUTEX_MOD_DISP1_MDP_RDMA0 0 +#define MT8188_MUTEX_MOD_DISP1_MDP_RDMA1 1 +#define MT8188_MUTEX_MOD_DISP1_MDP_RDMA2 2 +#define MT8188_MUTEX_MOD_DISP1_MDP_RDMA3 3 +#define MT8188_MUTEX_MOD_DISP1_MDP_RDMA4 4 +#define MT8188_MUTEX_MOD_DISP1_MDP_RDMA5 5 +#define MT8188_MUTEX_MOD_DISP1_MDP_RDMA6 6 +#define MT8188_MUTEX_MOD_DISP1_MDP_RDMA7 7 +#define MT8188_MUTEX_MOD_DISP1_PADDING0 8 +#define MT8188_MUTEX_MOD_DISP1_PADDING1 9 +#define MT8188_MUTEX_MOD_DISP1_PADDING2 10 +#define MT8188_MUTEX_MOD_DISP1_PADDING3 11 +#define MT8188_MUTEX_MOD_DISP1_PADDING4 12 +#define MT8188_MUTEX_MOD_DISP1_PADDING5 13 +#define MT8188_MUTEX_MOD_DISP1_PADDING6 14 +#define MT8188_MUTEX_MOD_DISP1_PADDING7 15 +#define MT8188_MUTEX_MOD_DISP1_VPP_MERGE0 20 +#define MT8188_MUTEX_MOD_DISP1_VPP_MERGE1 21 +#define MT8188_MUTEX_MOD_DISP1_VPP_MERGE2 22 +#define MT8188_MUTEX_MOD_DISP1_VPP_MERGE3 23 +#define MT8188_MUTEX_MOD_DISP1_VPP_MERGE4 24 +#define MT8188_MUTEX_MOD_DISP1_DISP_MIXER 30 +#define MT8188_MUTEX_MOD_DISP1_DP_INTF1 39 + #define MT8195_MUTEX_MOD_DISP_OVL0 0 #define MT8195_MUTEX_MOD_DISP_WDMA0 1 #define MT8195_MUTEX_MOD_DISP_RDMA0 2 @@ -264,6 +288,7 @@ #define MT8183_MUTEX_SOF_DPI0 2 #define MT8188_MUTEX_SOF_DSI0 1 #define MT8188_MUTEX_SOF_DP_INTF0 3 +#define MT8188_MUTEX_SOF_DP_INTF1 4 #define MT8195_MUTEX_SOF_DSI0 1 #define MT8195_MUTEX_SOF_DSI1 2 #define MT8195_MUTEX_SOF_DP_INTF0 3 @@ -275,6 +300,7 @@ #define MT8183_MUTEX_EOF_DPI0 (MT8183_MUTEX_SOF_DPI0 << 6) #define MT8188_MUTEX_EOF_DSI0 (MT8188_MUTEX_SOF_DSI0 << 7) #define MT8188_MUTEX_EOF_DP_INTF0 (MT8188_MUTEX_SOF_DP_INTF0 << 7) +#define MT8188_MUTEX_EOF_DP_INTF1 (MT8188_MUTEX_SOF_DP_INTF1 << 7) #define MT8195_MUTEX_EOF_DSI0 (MT8195_MUTEX_SOF_DSI0 << 7) #define MT8195_MUTEX_EOF_DSI1 (MT8195_MUTEX_SOF_DSI1 << 7) #define MT8195_MUTEX_EOF_DP_INTF0 (MT8195_MUTEX_SOF_DP_INTF0 << 7) @@ -445,6 +471,29 @@ static const unsigned int mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_DSI0] = MT8188_MUTEX_MOD_DISP_DSI0, [DDP_COMPONENT_PWM0] = MT8188_MUTEX_MOD2_DISP_PWM0, [DDP_COMPONENT_DP_INTF0] = MT8188_MUTEX_MOD_DISP_DP_INTF0, + [DDP_COMPONENT_DP_INTF1] = MT8188_MUTEX_MOD_DISP1_DP_INTF1, + [DDP_COMPONENT_ETHDR_MIXER] = MT8188_MUTEX_MOD_DISP1_DISP_MIXER, + [DDP_COMPONENT_MDP_RDMA0] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA0, + [DDP_COMPONENT_MDP_RDMA1] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA1, + [DDP_COMPONENT_MDP_RDMA2] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA2, + [DDP_COMPONENT_MDP_RDMA3] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA3, + [DDP_COMPONENT_MDP_RDMA4] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA4, + [DDP_COMPONENT_MDP_RDMA5] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA5, + [DDP_COMPONENT_MDP_RDMA6] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA6, + [DDP_COMPONENT_MDP_RDMA7] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA7, + [DDP_COMPONENT_PADDING0] = MT8188_MUTEX_MOD_DISP1_PADDING0, + [DDP_COMPONENT_PADDING1] = MT8188_MUTEX_MOD_DISP1_PADDING1, + [DDP_COMPONENT_PADDING2] = MT8188_MUTEX_MOD_DISP1_PADDING2, + [DDP_COMPONENT_PADDING3] = MT8188_MUTEX_MOD_DISP1_PADDING3, + [DDP_COMPONENT_PADDING4] = MT8188_MUTEX_MOD_DISP1_PADDING4, + [DDP_COMPONENT_PADDING5] = MT8188_MUTEX_MOD_DISP1_PADDING5, + [DDP_COMPONENT_PADDING6] = MT8188_MUTEX_MOD_DISP1_PADDING6, + [DDP_COMPONENT_PADDING7] = MT8188_MUTEX_MOD_DISP1_PADDING7, + [DDP_COMPONENT_MERGE1] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE0, + [DDP_COMPONENT_MERGE2] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE1, + [DDP_COMPONENT_MERGE3] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE2, + [DDP_COMPONENT_MERGE4] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE3, + [DDP_COMPONENT_MERGE5] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE4, }; static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = { @@ -605,6 +654,8 @@ static const unsigned int mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = { MT8188_MUTEX_SOF_DSI0 | MT8188_MUTEX_EOF_DSI0, [MUTEX_SOF_DP_INTF0] = MT8188_MUTEX_SOF_DP_INTF0 | MT8188_MUTEX_EOF_DP_INTF0, + [MUTEX_SOF_DP_INTF1] = + MT8188_MUTEX_SOF_DP_INTF1 | MT8188_MUTEX_EOF_DP_INTF1, }; static const unsigned int mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = { diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index f31e3bedff50..c832f5c670bc 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2022 MediaTek Inc. + * Copyright (C) 2022 Collabora Ltd. + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> */ #include <linux/bitfield.h> @@ -32,16 +34,6 @@ #include <linux/spinlock.h> #include <linux/thermal.h> -/* svs bank 1-line software id */ -#define SVSB_CPU_LITTLE BIT(0) -#define SVSB_CPU_BIG BIT(1) -#define SVSB_CCI BIT(2) -#define SVSB_GPU BIT(3) - -/* svs bank 2-line type */ -#define SVSB_LOW BIT(8) -#define SVSB_HIGH BIT(9) - /* svs bank mode support */ #define SVSB_MODE_ALL_DISABLE 0 #define SVSB_MODE_INIT01 BIT(1) @@ -128,6 +120,13 @@ #define SVSB_VOPS_FLD_VOP2_6 GENMASK(23, 16) #define SVSB_VOPS_FLD_VOP3_7 GENMASK(31, 24) +/* SVS Thermal Coefficients */ +#define SVSB_TS_COEFF_MT8195 250460 +#define SVSB_TS_COEFF_MT8186 204650 + +/* Algo helpers */ +#define FUSE_DATA_NOT_VALID U32_MAX + /* svs bank related setting */ #define BITS8 8 #define MAX_OPP_ENTRIES 16 @@ -175,6 +174,36 @@ static DEFINE_SPINLOCK(svs_lock); #endif /** + * enum svsb_sw_id - SVS Bank Software ID + * @SVSB_SWID_CPU_LITTLE: CPU little cluster Bank + * @SVSB_SWID_CPU_BIG: CPU big cluster Bank + * @SVSB_SWID_CCI: Cache Coherent Interconnect Bank + * @SVSB_SWID_GPU: GPU Bank + * @SVSB_SWID_MAX: Total number of Banks + */ +enum svsb_sw_id { + SVSB_SWID_CPU_LITTLE, + SVSB_SWID_CPU_BIG, + SVSB_SWID_CCI, + SVSB_SWID_GPU, + SVSB_SWID_MAX +}; + +/** + * enum svsb_type - SVS Bank 2-line: Type and Role + * @SVSB_TYPE_NONE: One-line type Bank - Global role + * @SVSB_TYPE_LOW: Two-line type Bank - Low bank role + * @SVSB_TYPE_HIGH: Two-line type Bank - High bank role + * @SVSB_TYPE_MAX: Total number of bank types + */ +enum svsb_type { + SVSB_TYPE_NONE, + SVSB_TYPE_LOW, + SVSB_TYPE_HIGH, + SVSB_TYPE_MAX +}; + +/** * enum svsb_phase - svs bank phase enumeration * @SVSB_PHASE_ERROR: svs bank encounters unexpected condition * @SVSB_PHASE_INIT01: svs bank basic init for data calibration @@ -256,60 +285,88 @@ enum svs_reg_index { }; static const u32 svs_regs_v2[] = { - [DESCHAR] = 0xc00, - [TEMPCHAR] = 0xc04, - [DETCHAR] = 0xc08, - [AGECHAR] = 0xc0c, - [DCCONFIG] = 0xc10, - [AGECONFIG] = 0xc14, - [FREQPCT30] = 0xc18, - [FREQPCT74] = 0xc1c, - [LIMITVALS] = 0xc20, - [VBOOT] = 0xc24, - [DETWINDOW] = 0xc28, - [CONFIG] = 0xc2c, - [TSCALCS] = 0xc30, - [RUNCONFIG] = 0xc34, - [SVSEN] = 0xc38, - [INIT2VALS] = 0xc3c, - [DCVALUES] = 0xc40, - [AGEVALUES] = 0xc44, - [VOP30] = 0xc48, - [VOP74] = 0xc4c, - [TEMP] = 0xc50, - [INTSTS] = 0xc54, - [INTSTSRAW] = 0xc58, - [INTEN] = 0xc5c, - [CHKINT] = 0xc60, - [CHKSHIFT] = 0xc64, - [STATUS] = 0xc68, - [VDESIGN30] = 0xc6c, - [VDESIGN74] = 0xc70, - [DVT30] = 0xc74, - [DVT74] = 0xc78, - [AGECOUNT] = 0xc7c, - [SMSTATE0] = 0xc80, - [SMSTATE1] = 0xc84, - [CTL0] = 0xc88, - [DESDETSEC] = 0xce0, - [TEMPAGESEC] = 0xce4, - [CTRLSPARE0] = 0xcf0, - [CTRLSPARE1] = 0xcf4, - [CTRLSPARE2] = 0xcf8, - [CTRLSPARE3] = 0xcfc, - [CORESEL] = 0xf00, - [THERMINTST] = 0xf04, - [INTST] = 0xf08, - [THSTAGE0ST] = 0xf0c, - [THSTAGE1ST] = 0xf10, - [THSTAGE2ST] = 0xf14, - [THAHBST0] = 0xf18, - [THAHBST1] = 0xf1c, - [SPARE0] = 0xf20, - [SPARE1] = 0xf24, - [SPARE2] = 0xf28, - [SPARE3] = 0xf2c, - [THSLPEVEB] = 0xf30, + [DESCHAR] = 0x00, + [TEMPCHAR] = 0x04, + [DETCHAR] = 0x08, + [AGECHAR] = 0x0c, + [DCCONFIG] = 0x10, + [AGECONFIG] = 0x14, + [FREQPCT30] = 0x18, + [FREQPCT74] = 0x1c, + [LIMITVALS] = 0x20, + [VBOOT] = 0x24, + [DETWINDOW] = 0x28, + [CONFIG] = 0x2c, + [TSCALCS] = 0x30, + [RUNCONFIG] = 0x34, + [SVSEN] = 0x38, + [INIT2VALS] = 0x3c, + [DCVALUES] = 0x40, + [AGEVALUES] = 0x44, + [VOP30] = 0x48, + [VOP74] = 0x4c, + [TEMP] = 0x50, + [INTSTS] = 0x54, + [INTSTSRAW] = 0x58, + [INTEN] = 0x5c, + [CHKINT] = 0x60, + [CHKSHIFT] = 0x64, + [STATUS] = 0x68, + [VDESIGN30] = 0x6c, + [VDESIGN74] = 0x70, + [DVT30] = 0x74, + [DVT74] = 0x78, + [AGECOUNT] = 0x7c, + [SMSTATE0] = 0x80, + [SMSTATE1] = 0x84, + [CTL0] = 0x88, + [DESDETSEC] = 0xe0, + [TEMPAGESEC] = 0xe4, + [CTRLSPARE0] = 0xf0, + [CTRLSPARE1] = 0xf4, + [CTRLSPARE2] = 0xf8, + [CTRLSPARE3] = 0xfc, + [CORESEL] = 0x300, + [THERMINTST] = 0x304, + [INTST] = 0x308, + [THSTAGE0ST] = 0x30c, + [THSTAGE1ST] = 0x310, + [THSTAGE2ST] = 0x314, + [THAHBST0] = 0x318, + [THAHBST1] = 0x31c, + [SPARE0] = 0x320, + [SPARE1] = 0x324, + [SPARE2] = 0x328, + [SPARE3] = 0x32c, + [THSLPEVEB] = 0x330, +}; + +static const char * const svs_swid_names[SVSB_SWID_MAX] = { + "SVSB_CPU_LITTLE", "SVSB_CPU_BIG", "SVSB_CCI", "SVSB_GPU" +}; + +static const char * const svs_type_names[SVSB_TYPE_MAX] = { + "", "_LOW", "_HIGH" +}; + +enum svs_fusemap_dev { + BDEV_BDES, + BDEV_MDES, + BDEV_MTDES, + BDEV_DCBDET, + BDEV_DCMDET, + BDEV_MAX +}; + +enum svs_fusemap_glb { + GLB_FT_PGM, + GLB_VMIN, + GLB_MAX +}; + +struct svs_fusemap { + s8 index; + u8 ofst; }; /** @@ -317,88 +374,124 @@ static const u32 svs_regs_v2[] = { * @base: svs platform register base * @dev: svs platform device * @main_clk: main clock for svs bank - * @pbank: svs bank pointer needing to be protected by spin_lock section * @banks: svs banks that svs platform supports * @rst: svs platform reset control * @efuse_max: total number of svs efuse * @tefuse_max: total number of thermal efuse * @regs: svs platform registers map - * @bank_max: total number of svs banks * @efuse: svs efuse data received from NVMEM framework * @tefuse: thermal efuse data received from NVMEM framework + * @ts_coeff: thermal sensors coefficient + * @bank_max: total number of svs banks */ struct svs_platform { void __iomem *base; struct device *dev; struct clk *main_clk; - struct svs_bank *pbank; struct svs_bank *banks; struct reset_control *rst; size_t efuse_max; size_t tefuse_max; const u32 *regs; - u32 bank_max; u32 *efuse; u32 *tefuse; + u32 ts_coeff; + u16 bank_max; }; struct svs_platform_data { char *name; struct svs_bank *banks; - bool (*efuse_parsing)(struct svs_platform *svsp); + bool (*efuse_parsing)(struct svs_platform *svsp, const struct svs_platform_data *pdata); int (*probe)(struct svs_platform *svsp); + const struct svs_fusemap *glb_fuse_map; const u32 *regs; - u32 bank_max; + u32 ts_coeff; + u16 bank_max; +}; + +/** + * struct svs_bank_pdata - SVS Bank immutable config parameters + * @dev_fuse_map: Bank fuse map data + * @buck_name: Regulator name + * @tzone_name: Thermal zone name + * @age_config: Bank age configuration + * @ctl0: TS-x selection + * @dc_config: Bank dc configuration + * @int_st: Bank interrupt identification + * @turn_freq_base: Reference frequency for 2-line turn point + * @tzone_htemp: Thermal zone high temperature threshold + * @tzone_ltemp: Thermal zone low temperature threshold + * @volt_step: Bank voltage step + * @volt_base: Bank voltage base + * @tzone_htemp_voffset: Thermal zone high temperature voltage offset + * @tzone_ltemp_voffset: Thermal zone low temperature voltage offset + * @chk_shift: Bank chicken shift + * @cpu_id: CPU core ID for SVS CPU bank use only + * @opp_count: Bank opp count + * @vboot: Voltage request for bank init01 only + * @vco: Bank VCO value + * @sw_id: Bank software identification + * @type: SVS Bank Type (1 or 2-line) and Role (high/low) + * @set_freq_pct: function pointer to set bank frequency percent table + * @get_volts: function pointer to get bank voltages + */ +struct svs_bank_pdata { + const struct svs_fusemap *dev_fuse_map; + char *buck_name; + char *tzone_name; + u32 age_config; + u32 ctl0; + u32 dc_config; + u32 int_st; + u32 turn_freq_base; + u32 tzone_htemp; + u32 tzone_ltemp; + u32 volt_step; + u32 volt_base; + u16 tzone_htemp_voffset; + u16 tzone_ltemp_voffset; + u8 chk_shift; + u8 cpu_id; + u8 opp_count; + u8 vboot; + u8 vco; + u8 sw_id; + u8 type; + + /* Callbacks */ + void (*set_freq_pct)(struct svs_platform *svsp, struct svs_bank *svsb); + void (*get_volts)(struct svs_platform *svsp, struct svs_bank *svsb); }; /** * struct svs_bank - svs bank representation + * @pdata: SVS Bank immutable config parameters * @dev: bank device * @opp_dev: device for opp table/buck control * @init_completion: the timeout completion for bank init * @buck: regulator used by opp_dev * @tzd: thermal zone device for getting temperature * @lock: mutex lock to protect voltage update process - * @set_freq_pct: function pointer to set bank frequency percent table - * @get_volts: function pointer to get bank voltages * @name: bank name - * @buck_name: regulator name - * @tzone_name: thermal zone name * @phase: bank current phase * @volt_od: bank voltage overdrive * @reg_data: bank register data in different phase for debug purpose * @pm_runtime_enabled_count: bank pm runtime enabled count - * @mode_support: bank mode support. + * @mode_support: bank mode support * @freq_base: reference frequency for bank init - * @turn_freq_base: refenrece frequency for 2-line turn point - * @vboot: voltage request for bank init01 only * @opp_dfreq: default opp frequency table * @opp_dvolt: default opp voltage table * @freq_pct: frequency percent table for bank init * @volt: bank voltage table - * @volt_step: bank voltage step - * @volt_base: bank voltage base * @volt_flags: bank voltage flags * @vmax: bank voltage maximum * @vmin: bank voltage minimum - * @age_config: bank age configuration * @age_voffset_in: bank age voltage offset - * @dc_config: bank dc configuration * @dc_voffset_in: bank dc voltage offset * @dvt_fixed: bank dvt fixed value - * @vco: bank VCO value - * @chk_shift: bank chicken shift * @core_sel: bank selection - * @opp_count: bank opp count - * @int_st: bank interrupt identification - * @sw_id: bank software identification - * @cpu_id: cpu core id for SVS CPU bank use only - * @ctl0: TS-x selection * @temp: bank temperature - * @tzone_htemp: thermal zone high temperature threshold - * @tzone_htemp_voffset: thermal zone high temperature voltage offset - * @tzone_ltemp: thermal zone low temperature threshold - * @tzone_ltemp_voffset: thermal zone low temperature voltage offset * @bts: svs efuse data * @mts: svs efuse data * @bdes: svs efuse data @@ -408,70 +501,48 @@ struct svs_platform_data { * @dcmdet: svs efuse data * @turn_pt: 2-line turn point tells which opp_volt calculated by high/low bank * @vbin_turn_pt: voltage bin turn point helps know which svsb_volt should be overridden - * @type: bank type to represent it is 2-line (high/low) bank or 1-line bank * - * Svs bank will generate suitalbe voltages by below general math equation + * Svs bank will generate suitable voltages by below general math equation * and provide these voltages to opp voltage table. * * opp_volt[i] = (volt[i] * volt_step) + volt_base; */ struct svs_bank { + const struct svs_bank_pdata pdata; struct device *dev; struct device *opp_dev; struct completion init_completion; struct regulator *buck; struct thermal_zone_device *tzd; - struct mutex lock; /* lock to protect voltage update process */ - void (*set_freq_pct)(struct svs_platform *svsp); - void (*get_volts)(struct svs_platform *svsp); + struct mutex lock; + int pm_runtime_enabled_count; + short int volt_od; char *name; - char *buck_name; - char *tzone_name; enum svsb_phase phase; - s32 volt_od; u32 reg_data[SVSB_PHASE_MAX][SVS_REG_MAX]; - u32 pm_runtime_enabled_count; - u32 mode_support; - u32 freq_base; - u32 turn_freq_base; - u32 vboot; + u8 mode_support; u32 opp_dfreq[MAX_OPP_ENTRIES]; u32 opp_dvolt[MAX_OPP_ENTRIES]; u32 freq_pct[MAX_OPP_ENTRIES]; u32 volt[MAX_OPP_ENTRIES]; - u32 volt_step; - u32 volt_base; u32 volt_flags; - u32 vmax; - u32 vmin; - u32 age_config; - u32 age_voffset_in; - u32 dc_config; - u32 dc_voffset_in; - u32 dvt_fixed; - u32 vco; - u32 chk_shift; - u32 core_sel; - u32 opp_count; - u32 int_st; - u32 sw_id; - u32 cpu_id; - u32 ctl0; - u32 temp; - u32 tzone_htemp; - u32 tzone_htemp_voffset; - u32 tzone_ltemp; - u32 tzone_ltemp_voffset; - u32 bts; - u32 mts; - u32 bdes; - u32 mdes; - u32 mtdes; - u32 dcbdet; - u32 dcmdet; + u32 freq_base; u32 turn_pt; u32 vbin_turn_pt; - u32 type; + u32 core_sel; + u32 temp; + u16 age_voffset_in; + u16 dc_voffset_in; + u8 dvt_fixed; + u8 vmax; + u8 vmin; + u16 bts; + u16 mts; + u16 bdes; + u16 mdes; + u8 mtdes; + u8 dcbdet; + u8 dcmdet; }; static u32 percent(u32 numerator, u32 denominator) @@ -494,10 +565,8 @@ static void svs_writel_relaxed(struct svs_platform *svsp, u32 val, writel_relaxed(val, svsp->base + svsp->regs[rg_i]); } -static void svs_switch_bank(struct svs_platform *svsp) +static void svs_switch_bank(struct svs_platform *svsp, struct svs_bank *svsb) { - struct svs_bank *svsb = svsp->pbank; - svs_writel_relaxed(svsp, svsb->core_sel, CORESEL); } @@ -515,10 +584,11 @@ static u32 svs_opp_volt_to_bank_volt(u32 opp_u_volt, u32 svsb_volt_step, static int svs_sync_bank_volts_from_opp(struct svs_bank *svsb) { + const struct svs_bank_pdata *bdata = &svsb->pdata; struct dev_pm_opp *opp; u32 i, opp_u_volt; - for (i = 0; i < svsb->opp_count; i++) { + for (i = 0; i < bdata->opp_count; i++) { opp = dev_pm_opp_find_freq_exact(svsb->opp_dev, svsb->opp_dfreq[i], true); @@ -530,8 +600,8 @@ static int svs_sync_bank_volts_from_opp(struct svs_bank *svsb) opp_u_volt = dev_pm_opp_get_voltage(opp); svsb->volt[i] = svs_opp_volt_to_bank_volt(opp_u_volt, - svsb->volt_step, - svsb->volt_base); + bdata->volt_step, + bdata->volt_base); dev_pm_opp_put(opp); } @@ -541,6 +611,7 @@ static int svs_sync_bank_volts_from_opp(struct svs_bank *svsb) static int svs_adjust_pm_opp_volts(struct svs_bank *svsb) { int ret = -EPERM, tzone_temp = 0; + const struct svs_bank_pdata *bdata = &svsb->pdata; u32 i, svsb_volt, opp_volt, temp_voffset = 0, opp_start, opp_stop; mutex_lock(&svsb->lock); @@ -549,15 +620,15 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb) * 2-line bank updates its corresponding opp volts. * 1-line bank updates all opp volts. */ - if (svsb->type == SVSB_HIGH) { + if (bdata->type == SVSB_TYPE_HIGH) { opp_start = 0; opp_stop = svsb->turn_pt; - } else if (svsb->type == SVSB_LOW) { + } else if (bdata->type == SVSB_TYPE_LOW) { opp_start = svsb->turn_pt; - opp_stop = svsb->opp_count; + opp_stop = bdata->opp_count; } else { opp_start = 0; - opp_stop = svsb->opp_count; + opp_stop = bdata->opp_count; } /* Get thermal effect */ @@ -566,20 +637,20 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb) if (ret || (svsb->temp > SVSB_TEMP_UPPER_BOUND && svsb->temp < SVSB_TEMP_LOWER_BOUND)) { dev_err(svsb->dev, "%s: %d (0x%x), run default volts\n", - svsb->tzone_name, ret, svsb->temp); + bdata->tzone_name, ret, svsb->temp); svsb->phase = SVSB_PHASE_ERROR; } - if (tzone_temp >= svsb->tzone_htemp) - temp_voffset += svsb->tzone_htemp_voffset; - else if (tzone_temp <= svsb->tzone_ltemp) - temp_voffset += svsb->tzone_ltemp_voffset; + if (tzone_temp >= bdata->tzone_htemp) + temp_voffset += bdata->tzone_htemp_voffset; + else if (tzone_temp <= bdata->tzone_ltemp) + temp_voffset += bdata->tzone_ltemp_voffset; /* 2-line bank update all opp volts when running mon mode */ - if (svsb->phase == SVSB_PHASE_MON && (svsb->type == SVSB_HIGH || - svsb->type == SVSB_LOW)) { + if (svsb->phase == SVSB_PHASE_MON && (bdata->type == SVSB_TYPE_HIGH || + bdata->type == SVSB_TYPE_LOW)) { opp_start = 0; - opp_stop = svsb->opp_count; + opp_stop = bdata->opp_count; } } @@ -596,8 +667,8 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb) case SVSB_PHASE_MON: svsb_volt = max(svsb->volt[i] + temp_voffset, svsb->vmin); opp_volt = svs_bank_volt_to_opp_volt(svsb_volt, - svsb->volt_step, - svsb->volt_base); + bdata->volt_step, + bdata->volt_base); break; default: dev_err(svsb->dev, "unknown phase: %u\n", svsb->phase); @@ -632,8 +703,7 @@ static void svs_bank_disable_and_restore_default_volts(struct svs_platform *svsp return; spin_lock_irqsave(&svs_lock, flags); - svsp->pbank = svsb; - svs_switch_bank(svsp); + svs_switch_bank(svsp, svsb); svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS); spin_unlock_irqrestore(&svs_lock, flags); @@ -760,7 +830,7 @@ static int svs_status_debug_show(struct seq_file *m, void *v) svsb->name, tzone_temp, svsb->vbin_turn_pt, svsb->turn_pt); - for (i = 0; i < svsb->opp_count; i++) { + for (i = 0; i < svsb->pdata.opp_count; i++) { opp = dev_pm_opp_find_freq_exact(svsb->opp_dev, svsb->opp_dfreq[i], true); if (IS_ERR(opp)) { @@ -865,12 +935,12 @@ static u32 interpolate(u32 f0, u32 f1, u32 v0, u32 v1, u32 fx) return DIV_ROUND_UP(vx, 100); } -static void svs_get_bank_volts_v3(struct svs_platform *svsp) +static void svs_get_bank_volts_v3(struct svs_platform *svsp, struct svs_bank *svsb) { - struct svs_bank *svsb = svsp->pbank; + const struct svs_bank_pdata *bdata = &svsb->pdata; u32 i, j, *vop, vop74, vop30, turn_pt = svsb->turn_pt; u32 b_sft, shift_byte = 0, opp_start = 0, opp_stop = 0; - u32 middle_index = (svsb->opp_count / 2); + u32 middle_index = (bdata->opp_count / 2); if (svsb->phase == SVSB_PHASE_MON && svsb->volt_flags & SVSB_MON_VOLT_IGNORE) @@ -881,7 +951,7 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) /* Target is to set svsb->volt[] by algorithm */ if (turn_pt < middle_index) { - if (svsb->type == SVSB_HIGH) { + if (bdata->type == SVSB_TYPE_HIGH) { /* volt[0] ~ volt[turn_pt - 1] */ for (i = 0; i < turn_pt; i++) { b_sft = BITS8 * (shift_byte % REG_BYTES); @@ -890,12 +960,12 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) svsb->volt[i] = (*vop >> b_sft) & GENMASK(7, 0); shift_byte++; } - } else if (svsb->type == SVSB_LOW) { + } else if (bdata->type == SVSB_TYPE_LOW) { /* volt[turn_pt] + volt[j] ~ volt[opp_count - 1] */ - j = svsb->opp_count - 7; + j = bdata->opp_count - 7; svsb->volt[turn_pt] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30); shift_byte++; - for (i = j; i < svsb->opp_count; i++) { + for (i = j; i < bdata->opp_count; i++) { b_sft = BITS8 * (shift_byte % REG_BYTES); vop = (shift_byte < REG_BYTES) ? &vop30 : &vop74; @@ -912,7 +982,7 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) svsb->freq_pct[i]); } } else { - if (svsb->type == SVSB_HIGH) { + if (bdata->type == SVSB_TYPE_HIGH) { /* volt[0] + volt[j] ~ volt[turn_pt - 1] */ j = turn_pt - 7; svsb->volt[0] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30); @@ -932,9 +1002,9 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) svsb->volt[0], svsb->volt[j], svsb->freq_pct[i]); - } else if (svsb->type == SVSB_LOW) { + } else if (bdata->type == SVSB_TYPE_LOW) { /* volt[turn_pt] ~ volt[opp_count - 1] */ - for (i = turn_pt; i < svsb->opp_count; i++) { + for (i = turn_pt; i < bdata->opp_count; i++) { b_sft = BITS8 * (shift_byte % REG_BYTES); vop = (shift_byte < REG_BYTES) ? &vop30 : &vop74; @@ -944,12 +1014,12 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) } } - if (svsb->type == SVSB_HIGH) { + if (bdata->type == SVSB_TYPE_HIGH) { opp_start = 0; opp_stop = svsb->turn_pt; - } else if (svsb->type == SVSB_LOW) { + } else if (bdata->type == SVSB_TYPE_LOW) { opp_start = svsb->turn_pt; - opp_stop = svsb->opp_count; + opp_stop = bdata->opp_count; } for (i = opp_start; i < opp_stop; i++) @@ -959,11 +1029,11 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) /* For voltage bin support */ if (svsb->opp_dfreq[0] > svsb->freq_base) { svsb->volt[0] = svs_opp_volt_to_bank_volt(svsb->opp_dvolt[0], - svsb->volt_step, - svsb->volt_base); + bdata->volt_step, + bdata->volt_base); /* Find voltage bin turn point */ - for (i = 0; i < svsb->opp_count; i++) { + for (i = 0; i < bdata->opp_count; i++) { if (svsb->opp_dfreq[i] <= svsb->freq_base) { svsb->vbin_turn_pt = i; break; @@ -980,15 +1050,15 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp) } } -static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp) +static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp, struct svs_bank *svsb) { - struct svs_bank *svsb = svsp->pbank; + const struct svs_bank_pdata *bdata = &svsb->pdata; u32 i, j, *freq_pct, freq_pct74 = 0, freq_pct30 = 0; u32 b_sft, shift_byte = 0, turn_pt; - u32 middle_index = (svsb->opp_count / 2); + u32 middle_index = (bdata->opp_count / 2); - for (i = 0; i < svsb->opp_count; i++) { - if (svsb->opp_dfreq[i] <= svsb->turn_freq_base) { + for (i = 0; i < bdata->opp_count; i++) { + if (svsb->opp_dfreq[i] <= bdata->turn_freq_base) { svsb->turn_pt = i; break; } @@ -998,11 +1068,11 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp) /* Target is to fill out freq_pct74 / freq_pct30 by algorithm */ if (turn_pt < middle_index) { - if (svsb->type == SVSB_HIGH) { + if (bdata->type == SVSB_TYPE_HIGH) { /* * If we don't handle this situation, - * SVSB_HIGH's FREQPCT74 / FREQPCT30 would keep "0" - * and this leads SVSB_LOW to work abnormally. + * SVSB_TYPE_HIGH's FREQPCT74 / FREQPCT30 would keep "0" + * and this leads SVSB_TYPE_LOW to work abnormally. */ if (turn_pt == 0) freq_pct30 = svsb->freq_pct[0]; @@ -1015,15 +1085,15 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp) *freq_pct |= (svsb->freq_pct[i] << b_sft); shift_byte++; } - } else if (svsb->type == SVSB_LOW) { + } else if (bdata->type == SVSB_TYPE_LOW) { /* * freq_pct[turn_pt] + * freq_pct[opp_count - 7] ~ freq_pct[opp_count -1] */ freq_pct30 = svsb->freq_pct[turn_pt]; shift_byte++; - j = svsb->opp_count - 7; - for (i = j; i < svsb->opp_count; i++) { + j = bdata->opp_count - 7; + for (i = j; i < bdata->opp_count; i++) { b_sft = BITS8 * (shift_byte % REG_BYTES); freq_pct = (shift_byte < REG_BYTES) ? &freq_pct30 : &freq_pct74; @@ -1032,7 +1102,7 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp) } } } else { - if (svsb->type == SVSB_HIGH) { + if (bdata->type == SVSB_TYPE_HIGH) { /* * freq_pct[0] + * freq_pct[turn_pt - 7] ~ freq_pct[turn_pt - 1] @@ -1047,9 +1117,9 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp) *freq_pct |= (svsb->freq_pct[i] << b_sft); shift_byte++; } - } else if (svsb->type == SVSB_LOW) { + } else if (bdata->type == SVSB_TYPE_LOW) { /* freq_pct[turn_pt] ~ freq_pct[opp_count - 1] */ - for (i = turn_pt; i < svsb->opp_count; i++) { + for (i = turn_pt; i < bdata->opp_count; i++) { b_sft = BITS8 * (shift_byte % REG_BYTES); freq_pct = (shift_byte < REG_BYTES) ? &freq_pct30 : &freq_pct74; @@ -1063,9 +1133,9 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp) svs_writel_relaxed(svsp, freq_pct30, FREQPCT30); } -static void svs_get_bank_volts_v2(struct svs_platform *svsp) +static void svs_get_bank_volts_v2(struct svs_platform *svsp, struct svs_bank *svsb) { - struct svs_bank *svsb = svsp->pbank; + const struct svs_bank_pdata *bdata = &svsb->pdata; u32 temp, i; temp = svs_readl_relaxed(svsp, VOP74); @@ -1093,17 +1163,17 @@ static void svs_get_bank_volts_v2(struct svs_platform *svsp) svsb->volt[14], svsb->freq_pct[15]); - for (i = 0; i < svsb->opp_count; i++) + for (i = 0; i < bdata->opp_count; i++) svsb->volt[i] += svsb->volt_od; /* For voltage bin support */ if (svsb->opp_dfreq[0] > svsb->freq_base) { svsb->volt[0] = svs_opp_volt_to_bank_volt(svsb->opp_dvolt[0], - svsb->volt_step, - svsb->volt_base); + bdata->volt_step, + bdata->volt_base); /* Find voltage bin turn point */ - for (i = 0; i < svsb->opp_count; i++) { + for (i = 0; i < bdata->opp_count; i++) { if (svsb->opp_dfreq[i] <= svsb->freq_base) { svsb->vbin_turn_pt = i; break; @@ -1120,9 +1190,8 @@ static void svs_get_bank_volts_v2(struct svs_platform *svsp) } } -static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp) +static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp, struct svs_bank *svsb) { - struct svs_bank *svsb = svsp->pbank; u32 freqpct74_val, freqpct30_val; freqpct74_val = FIELD_PREP(SVSB_FREQPCTS_FLD_PCT0_4, svsb->freq_pct[8]) | @@ -1140,18 +1209,20 @@ static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp) } static void svs_set_bank_phase(struct svs_platform *svsp, + unsigned int bank_idx, enum svsb_phase target_phase) { - struct svs_bank *svsb = svsp->pbank; + struct svs_bank *svsb = &svsp->banks[bank_idx]; + const struct svs_bank_pdata *bdata = &svsb->pdata; u32 des_char, temp_char, det_char, limit_vals, init2vals, ts_calcs; - svs_switch_bank(svsp); + svs_switch_bank(svsp, svsb); des_char = FIELD_PREP(SVSB_DESCHAR_FLD_BDES, svsb->bdes) | FIELD_PREP(SVSB_DESCHAR_FLD_MDES, svsb->mdes); svs_writel_relaxed(svsp, des_char, DESCHAR); - temp_char = FIELD_PREP(SVSB_TEMPCHAR_FLD_VCO, svsb->vco) | + temp_char = FIELD_PREP(SVSB_TEMPCHAR_FLD_VCO, bdata->vco) | FIELD_PREP(SVSB_TEMPCHAR_FLD_MTDES, svsb->mtdes) | FIELD_PREP(SVSB_TEMPCHAR_FLD_DVT_FIXED, svsb->dvt_fixed); svs_writel_relaxed(svsp, temp_char, TEMPCHAR); @@ -1160,11 +1231,11 @@ static void svs_set_bank_phase(struct svs_platform *svsp, FIELD_PREP(SVSB_DETCHAR_FLD_DCMDET, svsb->dcmdet); svs_writel_relaxed(svsp, det_char, DETCHAR); - svs_writel_relaxed(svsp, svsb->dc_config, DCCONFIG); - svs_writel_relaxed(svsp, svsb->age_config, AGECONFIG); + svs_writel_relaxed(svsp, bdata->dc_config, DCCONFIG); + svs_writel_relaxed(svsp, bdata->age_config, AGECONFIG); svs_writel_relaxed(svsp, SVSB_RUNCONFIG_DEFAULT, RUNCONFIG); - svsb->set_freq_pct(svsp); + bdata->set_freq_pct(svsp, svsb); limit_vals = FIELD_PREP(SVSB_LIMITVALS_FLD_DTLO, SVSB_VAL_DTLO) | FIELD_PREP(SVSB_LIMITVALS_FLD_DTHI, SVSB_VAL_DTHI) | @@ -1174,13 +1245,13 @@ static void svs_set_bank_phase(struct svs_platform *svsp, svs_writel_relaxed(svsp, SVSB_DET_WINDOW, DETWINDOW); svs_writel_relaxed(svsp, SVSB_DET_MAX, CONFIG); - svs_writel_relaxed(svsp, svsb->chk_shift, CHKSHIFT); - svs_writel_relaxed(svsp, svsb->ctl0, CTL0); + svs_writel_relaxed(svsp, bdata->chk_shift, CHKSHIFT); + svs_writel_relaxed(svsp, bdata->ctl0, CTL0); svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS); switch (target_phase) { case SVSB_PHASE_INIT01: - svs_writel_relaxed(svsp, svsb->vboot, VBOOT); + svs_writel_relaxed(svsp, bdata->vboot, VBOOT); svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN); svs_writel_relaxed(svsp, SVSB_PTPEN_INIT01, SVSEN); break; @@ -1206,18 +1277,20 @@ static void svs_set_bank_phase(struct svs_platform *svsp, } static inline void svs_save_bank_register_data(struct svs_platform *svsp, + unsigned short bank_idx, enum svsb_phase phase) { - struct svs_bank *svsb = svsp->pbank; + struct svs_bank *svsb = &svsp->banks[bank_idx]; enum svs_reg_index rg_i; for (rg_i = DESCHAR; rg_i < SVS_REG_MAX; rg_i++) svsb->reg_data[phase][rg_i] = svs_readl_relaxed(svsp, rg_i); } -static inline void svs_error_isr_handler(struct svs_platform *svsp) +static inline void svs_error_isr_handler(struct svs_platform *svsp, + unsigned short bank_idx) { - struct svs_bank *svsb = svsp->pbank; + struct svs_bank *svsb = &svsp->banks[bank_idx]; dev_err(svsb->dev, "%s: CORESEL = 0x%08x\n", __func__, svs_readl_relaxed(svsp, CORESEL)); @@ -1229,27 +1302,29 @@ static inline void svs_error_isr_handler(struct svs_platform *svsp) svs_readl_relaxed(svsp, SMSTATE1)); dev_err(svsb->dev, "TEMP = 0x%08x\n", svs_readl_relaxed(svsp, TEMP)); - svs_save_bank_register_data(svsp, SVSB_PHASE_ERROR); + svs_save_bank_register_data(svsp, bank_idx, SVSB_PHASE_ERROR); svsb->phase = SVSB_PHASE_ERROR; svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS); } -static inline void svs_init01_isr_handler(struct svs_platform *svsp) +static inline void svs_init01_isr_handler(struct svs_platform *svsp, + unsigned short bank_idx) { - struct svs_bank *svsb = svsp->pbank; + struct svs_bank *svsb = &svsp->banks[bank_idx]; + u32 val; dev_info(svsb->dev, "%s: VDN74~30:0x%08x~0x%08x, DC:0x%08x\n", __func__, svs_readl_relaxed(svsp, VDESIGN74), svs_readl_relaxed(svsp, VDESIGN30), svs_readl_relaxed(svsp, DCVALUES)); - svs_save_bank_register_data(svsp, SVSB_PHASE_INIT01); + svs_save_bank_register_data(svsp, bank_idx, SVSB_PHASE_INIT01); svsb->phase = SVSB_PHASE_INIT01; - svsb->dc_voffset_in = ~(svs_readl_relaxed(svsp, DCVALUES) & - GENMASK(15, 0)) + 1; + val = ~(svs_readl_relaxed(svsp, DCVALUES) & GENMASK(15, 0)) + 1; + svsb->dc_voffset_in = val & GENMASK(15, 0); if (svsb->volt_flags & SVSB_INIT01_VOLT_IGNORE || (svsb->dc_voffset_in & SVSB_DC_SIGNED_BIT && svsb->volt_flags & SVSB_INIT01_VOLT_INC_ONLY)) @@ -1263,32 +1338,36 @@ static inline void svs_init01_isr_handler(struct svs_platform *svsp) svsb->core_sel &= ~SVSB_DET_CLK_EN; } -static inline void svs_init02_isr_handler(struct svs_platform *svsp) +static inline void svs_init02_isr_handler(struct svs_platform *svsp, + unsigned short bank_idx) { - struct svs_bank *svsb = svsp->pbank; + struct svs_bank *svsb = &svsp->banks[bank_idx]; + const struct svs_bank_pdata *bdata = &svsb->pdata; dev_info(svsb->dev, "%s: VOP74~30:0x%08x~0x%08x, DC:0x%08x\n", __func__, svs_readl_relaxed(svsp, VOP74), svs_readl_relaxed(svsp, VOP30), svs_readl_relaxed(svsp, DCVALUES)); - svs_save_bank_register_data(svsp, SVSB_PHASE_INIT02); + svs_save_bank_register_data(svsp, bank_idx, SVSB_PHASE_INIT02); svsb->phase = SVSB_PHASE_INIT02; - svsb->get_volts(svsp); + bdata->get_volts(svsp, svsb); svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN); svs_writel_relaxed(svsp, SVSB_INTSTS_F0_COMPLETE, INTSTS); } -static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp) +static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp, + unsigned short bank_idx) { - struct svs_bank *svsb = svsp->pbank; + struct svs_bank *svsb = &svsp->banks[bank_idx]; + const struct svs_bank_pdata *bdata = &svsb->pdata; - svs_save_bank_register_data(svsp, SVSB_PHASE_MON); + svs_save_bank_register_data(svsp, bank_idx, SVSB_PHASE_MON); svsb->phase = SVSB_PHASE_MON; - svsb->get_volts(svsp); + bdata->get_volts(svsp, svsb); svsb->temp = svs_readl_relaxed(svsp, TEMP) & GENMASK(7, 0); svs_writel_relaxed(svsp, SVSB_INTSTS_FLD_MONVOP, INTSTS); @@ -1297,37 +1376,38 @@ static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp) static irqreturn_t svs_isr(int irq, void *data) { struct svs_platform *svsp = data; + const struct svs_bank_pdata *bdata; struct svs_bank *svsb = NULL; unsigned long flags; u32 idx, int_sts, svs_en; for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; WARN(!svsb, "%s: svsb(%s) is null", __func__, svsb->name); spin_lock_irqsave(&svs_lock, flags); - svsp->pbank = svsb; /* Find out which svs bank fires interrupt */ - if (svsb->int_st & svs_readl_relaxed(svsp, INTST)) { + if (bdata->int_st & svs_readl_relaxed(svsp, INTST)) { spin_unlock_irqrestore(&svs_lock, flags); continue; } - svs_switch_bank(svsp); + svs_switch_bank(svsp, svsb); int_sts = svs_readl_relaxed(svsp, INTSTS); svs_en = svs_readl_relaxed(svsp, SVSEN); if (int_sts == SVSB_INTSTS_F0_COMPLETE && svs_en == SVSB_PTPEN_INIT01) - svs_init01_isr_handler(svsp); + svs_init01_isr_handler(svsp, idx); else if (int_sts == SVSB_INTSTS_F0_COMPLETE && svs_en == SVSB_PTPEN_INIT02) - svs_init02_isr_handler(svsp); + svs_init02_isr_handler(svsp, idx); else if (int_sts & SVSB_INTSTS_FLD_MONVOP) - svs_mon_mode_isr_handler(svsp); + svs_mon_mode_isr_handler(svsp, idx); else - svs_error_isr_handler(svsp); + svs_error_isr_handler(svsp, idx); spin_unlock_irqrestore(&svs_lock, flags); break; @@ -1342,20 +1422,35 @@ static irqreturn_t svs_isr(int irq, void *data) return IRQ_HANDLED; } +static bool svs_mode_available(struct svs_platform *svsp, u8 mode) +{ + int i; + + for (i = 0; i < svsp->bank_max; i++) + if (svsp->banks[i].mode_support & mode) + return true; + return false; +} + static int svs_init01(struct svs_platform *svsp) { + const struct svs_bank_pdata *bdata; struct svs_bank *svsb; unsigned long flags, time_left; bool search_done; int ret = 0, r; u32 opp_freq, opp_vboot, buck_volt, idx, i; + if (!svs_mode_available(svsp, SVSB_MODE_INIT01)) + return 0; + /* Keep CPUs' core power on for svs_init01 initialization */ cpuidle_pause_and_lock(); /* Svs bank init01 preparation - power enable */ for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; if (!(svsb->mode_support & SVSB_MODE_INIT01)) continue; @@ -1363,7 +1458,7 @@ static int svs_init01(struct svs_platform *svsp) ret = regulator_enable(svsb->buck); if (ret) { dev_err(svsb->dev, "%s enable fail: %d\n", - svsb->buck_name, ret); + bdata->buck_name, ret); goto svs_init01_resume_cpuidle; } @@ -1393,6 +1488,7 @@ static int svs_init01(struct svs_platform *svsp) */ for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; if (!(svsb->mode_support & SVSB_MODE_INIT01)) continue; @@ -1402,11 +1498,11 @@ static int svs_init01(struct svs_platform *svsp) * fix to that freq until svs_init01 is done. */ search_done = false; - opp_vboot = svs_bank_volt_to_opp_volt(svsb->vboot, - svsb->volt_step, - svsb->volt_base); + opp_vboot = svs_bank_volt_to_opp_volt(bdata->vboot, + bdata->volt_step, + bdata->volt_base); - for (i = 0; i < svsb->opp_count; i++) { + for (i = 0; i < bdata->opp_count; i++) { opp_freq = svsb->opp_dfreq[i]; if (!search_done && svsb->opp_dvolt[i] <= opp_vboot) { ret = dev_pm_opp_adjust_voltage(svsb->opp_dev, @@ -1438,13 +1534,14 @@ static int svs_init01(struct svs_platform *svsp) /* Svs bank init01 begins */ for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; if (!(svsb->mode_support & SVSB_MODE_INIT01)) continue; - opp_vboot = svs_bank_volt_to_opp_volt(svsb->vboot, - svsb->volt_step, - svsb->volt_base); + opp_vboot = svs_bank_volt_to_opp_volt(bdata->vboot, + bdata->volt_step, + bdata->volt_base); buck_volt = regulator_get_voltage(svsb->buck); if (buck_volt != opp_vboot) { @@ -1456,8 +1553,7 @@ static int svs_init01(struct svs_platform *svsp) } spin_lock_irqsave(&svs_lock, flags); - svsp->pbank = svsb; - svs_set_bank_phase(svsp, SVSB_PHASE_INIT01); + svs_set_bank_phase(svsp, idx, SVSB_PHASE_INIT01); spin_unlock_irqrestore(&svs_lock, flags); time_left = wait_for_completion_timeout(&svsb->init_completion, @@ -1472,11 +1568,12 @@ static int svs_init01(struct svs_platform *svsp) svs_init01_finish: for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; if (!(svsb->mode_support & SVSB_MODE_INIT01)) continue; - for (i = 0; i < svsb->opp_count; i++) { + for (i = 0; i < bdata->opp_count; i++) { r = dev_pm_opp_enable(svsb->opp_dev, svsb->opp_dfreq[i]); if (r) @@ -1502,7 +1599,7 @@ svs_init01_finish: r = regulator_disable(svsb->buck); if (r) dev_err(svsb->dev, "%s disable fail: %d\n", - svsb->buck_name, r); + bdata->buck_name, r); } svs_init01_resume_cpuidle: @@ -1513,11 +1610,15 @@ svs_init01_resume_cpuidle: static int svs_init02(struct svs_platform *svsp) { + const struct svs_bank_pdata *bdata; struct svs_bank *svsb; unsigned long flags, time_left; int ret; u32 idx; + if (!svs_mode_available(svsp, SVSB_MODE_INIT02)) + return 0; + for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; @@ -1526,8 +1627,7 @@ static int svs_init02(struct svs_platform *svsp) reinit_completion(&svsb->init_completion); spin_lock_irqsave(&svs_lock, flags); - svsp->pbank = svsb; - svs_set_bank_phase(svsp, SVSB_PHASE_INIT02); + svs_set_bank_phase(svsp, idx, SVSB_PHASE_INIT02); spin_unlock_irqrestore(&svs_lock, flags); time_left = wait_for_completion_timeout(&svsb->init_completion, @@ -1546,11 +1646,12 @@ static int svs_init02(struct svs_platform *svsp) */ for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; if (!(svsb->mode_support & SVSB_MODE_INIT02)) continue; - if (svsb->type == SVSB_HIGH || svsb->type == SVSB_LOW) { + if (bdata->type == SVSB_TYPE_HIGH || bdata->type == SVSB_TYPE_LOW) { if (svs_sync_bank_volts_from_opp(svsb)) { dev_err(svsb->dev, "sync volt fail\n"); ret = -EPERM; @@ -1583,8 +1684,7 @@ static void svs_mon_mode(struct svs_platform *svsp) continue; spin_lock_irqsave(&svs_lock, flags); - svsp->pbank = svsb; - svs_set_bank_phase(svsp, SVSB_PHASE_MON); + svs_set_bank_phase(svsp, idx, SVSB_PHASE_MON); spin_unlock_irqrestore(&svs_lock, flags); } } @@ -1609,12 +1709,12 @@ static int svs_start(struct svs_platform *svsp) static int svs_suspend(struct device *dev) { struct svs_platform *svsp = dev_get_drvdata(dev); - struct svs_bank *svsb; int ret; u32 idx; for (idx = 0; idx < svsp->bank_max; idx++) { - svsb = &svsp->banks[idx]; + struct svs_bank *svsb = &svsp->banks[idx]; + svs_bank_disable_and_restore_default_volts(svsp, svsb); } @@ -1665,6 +1765,7 @@ out_of_resume: static int svs_bank_resource_setup(struct svs_platform *svsp) { + const struct svs_bank_pdata *bdata; struct svs_bank *svsb; struct dev_pm_opp *opp; unsigned long freq; @@ -1675,35 +1776,23 @@ static int svs_bank_resource_setup(struct svs_platform *svsp) for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; - switch (svsb->sw_id) { - case SVSB_CPU_LITTLE: - svsb->name = "SVSB_CPU_LITTLE"; - break; - case SVSB_CPU_BIG: - svsb->name = "SVSB_CPU_BIG"; - break; - case SVSB_CCI: - svsb->name = "SVSB_CCI"; - break; - case SVSB_GPU: - if (svsb->type == SVSB_HIGH) - svsb->name = "SVSB_GPU_HIGH"; - else if (svsb->type == SVSB_LOW) - svsb->name = "SVSB_GPU_LOW"; - else - svsb->name = "SVSB_GPU"; - break; - default: - dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id); + if (bdata->sw_id >= SVSB_SWID_MAX || bdata->type >= SVSB_TYPE_MAX) { + dev_err(svsb->dev, "unknown bank sw_id or type\n"); return -EINVAL; } - svsb->dev = devm_kzalloc(svsp->dev, sizeof(*svsb->dev), - GFP_KERNEL); + svsb->dev = devm_kzalloc(svsp->dev, sizeof(*svsb->dev), GFP_KERNEL); if (!svsb->dev) return -ENOMEM; + svsb->name = devm_kasprintf(svsp->dev, GFP_KERNEL, "%s%s", + svs_swid_names[bdata->sw_id], + svs_type_names[bdata->type]); + if (!svsb->name) + return -ENOMEM; + ret = dev_set_name(svsb->dev, "%s", svsb->name); if (ret) return ret; @@ -1721,32 +1810,32 @@ static int svs_bank_resource_setup(struct svs_platform *svsp) if (svsb->mode_support & SVSB_MODE_INIT01) { svsb->buck = devm_regulator_get_optional(svsb->opp_dev, - svsb->buck_name); + bdata->buck_name); if (IS_ERR(svsb->buck)) { dev_err(svsb->dev, "cannot get \"%s-supply\"\n", - svsb->buck_name); + bdata->buck_name); return PTR_ERR(svsb->buck); } } - if (!IS_ERR_OR_NULL(svsb->tzone_name)) { - svsb->tzd = thermal_zone_get_zone_by_name(svsb->tzone_name); + if (!IS_ERR_OR_NULL(bdata->tzone_name)) { + svsb->tzd = thermal_zone_get_zone_by_name(bdata->tzone_name); if (IS_ERR(svsb->tzd)) { dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n", - svsb->tzone_name); + bdata->tzone_name); return PTR_ERR(svsb->tzd); } } count = dev_pm_opp_get_opp_count(svsb->opp_dev); - if (svsb->opp_count != count) { + if (bdata->opp_count != count) { dev_err(svsb->dev, "opp_count not \"%u\" but get \"%d\"?\n", - svsb->opp_count, count); + bdata->opp_count, count); return count; } - for (i = 0, freq = U32_MAX; i < svsb->opp_count; i++, freq--) { + for (i = 0, freq = ULONG_MAX; i < bdata->opp_count; i++, freq--) { opp = dev_pm_opp_find_freq_floor(svsb->opp_dev, &freq); if (IS_ERR(opp)) { dev_err(svsb->dev, "cannot find freq = %ld\n", @@ -1780,8 +1869,6 @@ static int svs_get_efuse_data(struct svs_platform *svsp, *svsp_efuse = nvmem_cell_read(cell, svsp_efuse_max); if (IS_ERR(*svsp_efuse)) { - dev_err(svsp->dev, "cannot read \"%s\" efuse: %ld\n", - nvmem_cell_name, PTR_ERR(*svsp_efuse)); nvmem_cell_put(cell); return PTR_ERR(*svsp_efuse); } @@ -1792,139 +1879,91 @@ static int svs_get_efuse_data(struct svs_platform *svsp, return 0; } -static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp) +static u32 svs_get_fuse_val(u32 *fuse_array, const struct svs_fusemap *fmap, u8 nbits) { - struct svs_bank *svsb; - u32 idx, i, vmin, golden_temp; - int ret; - - for (i = 0; i < svsp->efuse_max; i++) - if (svsp->efuse[i]) - dev_info(svsp->dev, "M_HW_RES%d: 0x%08x\n", - i, svsp->efuse[i]); - - if (!svsp->efuse[9]) { - dev_notice(svsp->dev, "svs_efuse[9] = 0x0?\n"); - return false; - } - - /* Svs efuse parsing */ - vmin = (svsp->efuse[19] >> 4) & GENMASK(1, 0); - - for (idx = 0; idx < svsp->bank_max; idx++) { - svsb = &svsp->banks[idx]; + u32 val; - if (vmin == 0x1) - svsb->vmin = 0x1e; - - if (svsb->type == SVSB_LOW) { - svsb->mtdes = svsp->efuse[10] & GENMASK(7, 0); - svsb->bdes = (svsp->efuse[10] >> 16) & GENMASK(7, 0); - svsb->mdes = (svsp->efuse[10] >> 24) & GENMASK(7, 0); - svsb->dcbdet = (svsp->efuse[17]) & GENMASK(7, 0); - svsb->dcmdet = (svsp->efuse[17] >> 8) & GENMASK(7, 0); - } else if (svsb->type == SVSB_HIGH) { - svsb->mtdes = svsp->efuse[9] & GENMASK(7, 0); - svsb->bdes = (svsp->efuse[9] >> 16) & GENMASK(7, 0); - svsb->mdes = (svsp->efuse[9] >> 24) & GENMASK(7, 0); - svsb->dcbdet = (svsp->efuse[17] >> 16) & GENMASK(7, 0); - svsb->dcmdet = (svsp->efuse[17] >> 24) & GENMASK(7, 0); - } + if (fmap->index < 0) + return FUSE_DATA_NOT_VALID; - svsb->vmax += svsb->dvt_fixed; - } + val = fuse_array[fmap->index] >> fmap->ofst; + val &= GENMASK(nbits - 1, 0); - ret = svs_get_efuse_data(svsp, "t-calibration-data", - &svsp->tefuse, &svsp->tefuse_max); - if (ret) - return false; + return val; +} - for (i = 0; i < svsp->tefuse_max; i++) - if (svsp->tefuse[i] != 0) - break; +static bool svs_is_available(struct svs_platform *svsp) +{ + int i, num_populated = 0; - if (i == svsp->tefuse_max) - golden_temp = 50; /* All thermal efuse data are 0 */ - else - golden_temp = (svsp->tefuse[0] >> 24) & GENMASK(7, 0); + /* If at least two fuse arrays are populated, SVS is calibrated */ + for (i = 0; i < svsp->efuse_max; i++) { + if (svsp->efuse[i]) + num_populated++; - for (idx = 0; idx < svsp->bank_max; idx++) { - svsb = &svsp->banks[idx]; - svsb->mts = 500; - svsb->bts = (((500 * golden_temp + 250460) / 1000) - 25) * 4; + if (num_populated > 1) + return true; } - return true; + return false; } -static bool svs_mt8188_efuse_parsing(struct svs_platform *svsp) +static bool svs_common_parse_efuse(struct svs_platform *svsp, + const struct svs_platform_data *pdata) { - struct svs_bank *svsb; - u32 idx, i, golden_temp; - int ret; - - for (i = 0; i < svsp->efuse_max; i++) - if (svsp->efuse[i]) - dev_info(svsp->dev, "M_HW_RES%d: 0x%08x\n", - i, svsp->efuse[i]); + const struct svs_fusemap *gfmap = pdata->glb_fuse_map; + struct svs_fusemap tfm = { 0, 24 }; + u32 golden_temp, val; + u8 ft_pgm, vmin; + int i; - if (!svsp->efuse[5]) { - dev_notice(svsp->dev, "svs_efuse[5] = 0x0?\n"); + if (!svs_is_available(svsp)) return false; - } - /* Svs efuse parsing */ - for (idx = 0; idx < svsp->bank_max; idx++) { - svsb = &svsp->banks[idx]; + /* Get golden temperature from SVS-Thermal calibration */ + val = svs_get_fuse_val(svsp->tefuse, &tfm, 8); - if (svsb->type == SVSB_LOW) { - svsb->mtdes = svsp->efuse[5] & GENMASK(7, 0); - svsb->bdes = (svsp->efuse[5] >> 16) & GENMASK(7, 0); - svsb->mdes = (svsp->efuse[5] >> 24) & GENMASK(7, 0); - svsb->dcbdet = (svsp->efuse[15] >> 16) & GENMASK(7, 0); - svsb->dcmdet = (svsp->efuse[15] >> 24) & GENMASK(7, 0); - } else if (svsb->type == SVSB_HIGH) { - svsb->mtdes = svsp->efuse[4] & GENMASK(7, 0); - svsb->bdes = (svsp->efuse[4] >> 16) & GENMASK(7, 0); - svsb->mdes = (svsp->efuse[4] >> 24) & GENMASK(7, 0); - svsb->dcbdet = svsp->efuse[14] & GENMASK(7, 0); - svsb->dcmdet = (svsp->efuse[14] >> 8) & GENMASK(7, 0); - } + /* If golden temp is not programmed, use the default of 50 */ + golden_temp = val ? val : 50; - svsb->vmax += svsb->dvt_fixed; - } + /* Parse fused SVS calibration */ + ft_pgm = svs_get_fuse_val(svsp->efuse, &gfmap[GLB_FT_PGM], 8); + vmin = svs_get_fuse_val(svsp->efuse, &gfmap[GLB_VMIN], 2); - ret = svs_get_efuse_data(svsp, "t-calibration-data", - &svsp->tefuse, &svsp->tefuse_max); - if (ret) - return false; + for (i = 0; i < svsp->bank_max; i++) { + struct svs_bank *svsb = &svsp->banks[i]; + const struct svs_bank_pdata *bdata = &svsb->pdata; + const struct svs_fusemap *dfmap = bdata->dev_fuse_map; - for (i = 0; i < svsp->tefuse_max; i++) - if (svsp->tefuse[i] != 0) - break; + if (vmin == 1) + svsb->vmin = 0x1e; - if (i == svsp->tefuse_max) - golden_temp = 50; /* All thermal efuse data are 0 */ - else - golden_temp = (svsp->tefuse[0] >> 24) & GENMASK(7, 0); + if (ft_pgm == 0) + svsb->volt_flags |= SVSB_INIT01_VOLT_IGNORE; - for (idx = 0; idx < svsp->bank_max; idx++) { - svsb = &svsp->banks[idx]; - svsb->mts = 500; - svsb->bts = (((500 * golden_temp + 250460) / 1000) - 25) * 4; + svsb->mtdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_MTDES], 8); + svsb->bdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_BDES], 8); + svsb->mdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_MDES], 8); + svsb->dcbdet = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_DCBDET], 8); + svsb->dcmdet = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_DCMDET], 8); + svsb->vmax += svsb->dvt_fixed; + + svsb->mts = (svsp->ts_coeff * 2) / 1000; + svsb->bts = (((500 * golden_temp + svsp->ts_coeff) / 1000) - 25) * 4; } return true; } -static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp) +static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp, + const struct svs_platform_data *pdata) { struct svs_bank *svsb; + const struct svs_bank_pdata *bdata; int format[6], x_roomt[6], o_vtsmcu[5], o_vtsabb, tb_roomt = 0; int adc_ge_t, adc_oe_t, ge, oe, gain, degc_cali, adc_cali_en_t; int o_slope, o_slope_sign, ts_id; u32 idx, i, ft_pgm, mts, temp0, temp1, temp2; - int ret; for (i = 0; i < svsp->efuse_max; i++) if (svsp->efuse[i]) @@ -1937,74 +1976,48 @@ static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp) } /* Svs efuse parsing */ - ft_pgm = (svsp->efuse[0] >> 4) & GENMASK(3, 0); + ft_pgm = svs_get_fuse_val(svsp->efuse, &pdata->glb_fuse_map[GLB_FT_PGM], 4); for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; + const struct svs_fusemap *dfmap = bdata->dev_fuse_map; if (ft_pgm <= 1) svsb->volt_flags |= SVSB_INIT01_VOLT_IGNORE; - switch (svsb->sw_id) { - case SVSB_CPU_LITTLE: - svsb->bdes = svsp->efuse[16] & GENMASK(7, 0); - svsb->mdes = (svsp->efuse[16] >> 8) & GENMASK(7, 0); - svsb->dcbdet = (svsp->efuse[16] >> 16) & GENMASK(7, 0); - svsb->dcmdet = (svsp->efuse[16] >> 24) & GENMASK(7, 0); - svsb->mtdes = (svsp->efuse[17] >> 16) & GENMASK(7, 0); + svsb->mtdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_MTDES], 8); + svsb->bdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_BDES], 8); + svsb->mdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_MDES], 8); + svsb->dcbdet = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_DCBDET], 8); + svsb->dcmdet = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_DCMDET], 8); + switch (bdata->sw_id) { + case SVSB_SWID_CPU_LITTLE: + case SVSB_SWID_CCI: if (ft_pgm <= 3) svsb->volt_od += 10; else svsb->volt_od += 2; break; - case SVSB_CPU_BIG: - svsb->bdes = svsp->efuse[18] & GENMASK(7, 0); - svsb->mdes = (svsp->efuse[18] >> 8) & GENMASK(7, 0); - svsb->dcbdet = (svsp->efuse[18] >> 16) & GENMASK(7, 0); - svsb->dcmdet = (svsp->efuse[18] >> 24) & GENMASK(7, 0); - svsb->mtdes = svsp->efuse[17] & GENMASK(7, 0); - + case SVSB_SWID_CPU_BIG: if (ft_pgm <= 3) svsb->volt_od += 15; else svsb->volt_od += 12; break; - case SVSB_CCI: - svsb->bdes = svsp->efuse[4] & GENMASK(7, 0); - svsb->mdes = (svsp->efuse[4] >> 8) & GENMASK(7, 0); - svsb->dcbdet = (svsp->efuse[4] >> 16) & GENMASK(7, 0); - svsb->dcmdet = (svsp->efuse[4] >> 24) & GENMASK(7, 0); - svsb->mtdes = (svsp->efuse[5] >> 16) & GENMASK(7, 0); - - if (ft_pgm <= 3) - svsb->volt_od += 10; - else - svsb->volt_od += 2; - break; - case SVSB_GPU: - svsb->bdes = svsp->efuse[6] & GENMASK(7, 0); - svsb->mdes = (svsp->efuse[6] >> 8) & GENMASK(7, 0); - svsb->dcbdet = (svsp->efuse[6] >> 16) & GENMASK(7, 0); - svsb->dcmdet = (svsp->efuse[6] >> 24) & GENMASK(7, 0); - svsb->mtdes = svsp->efuse[5] & GENMASK(7, 0); - - if (ft_pgm >= 2) { + case SVSB_SWID_GPU: + if (ft_pgm != FUSE_DATA_NOT_VALID && ft_pgm >= 2) { svsb->freq_base = 800000000; /* 800MHz */ svsb->dvt_fixed = 2; } break; default: - dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id); + dev_err(svsb->dev, "unknown sw_id: %u\n", bdata->sw_id); return false; } } - ret = svs_get_efuse_data(svsp, "t-calibration-data", - &svsp->tefuse, &svsp->tefuse_max); - if (ret) - return false; - /* Thermal efuse parsing */ adc_ge_t = (svsp->tefuse[1] >> 22) & GENMASK(9, 0); adc_oe_t = (svsp->tefuse[1] >> 12) & GENMASK(9, 0); @@ -2064,23 +2077,24 @@ static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp) for (idx = 0; idx < svsp->bank_max; idx++) { svsb = &svsp->banks[idx]; + bdata = &svsb->pdata; svsb->mts = mts; - switch (svsb->sw_id) { - case SVSB_CPU_LITTLE: + switch (bdata->sw_id) { + case SVSB_SWID_CPU_LITTLE: tb_roomt = x_roomt[3]; break; - case SVSB_CPU_BIG: + case SVSB_SWID_CPU_BIG: tb_roomt = x_roomt[4]; break; - case SVSB_CCI: + case SVSB_SWID_CCI: tb_roomt = x_roomt[3]; break; - case SVSB_GPU: + case SVSB_SWID_GPU: tb_roomt = x_roomt[1]; break; default: - dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id); + dev_err(svsb->dev, "unknown sw_id: %u\n", bdata->sw_id); goto remove_mt8183_svsb_mon_mode; } @@ -2153,7 +2167,6 @@ static struct device *svs_add_device_link(struct svs_platform *svsp, static int svs_mt8192_platform_probe(struct svs_platform *svsp) { struct device *dev; - struct svs_bank *svsb; u32 idx; svsp->rst = devm_reset_control_get_optional(svsp->dev, "svs_rst"); @@ -2161,18 +2174,33 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp) return dev_err_probe(svsp->dev, PTR_ERR(svsp->rst), "cannot get svs reset control\n"); - dev = svs_add_device_link(svsp, "lvts"); + dev = svs_add_device_link(svsp, "thermal-sensor"); if (IS_ERR(dev)) return dev_err_probe(svsp->dev, PTR_ERR(dev), "failed to get lvts device\n"); for (idx = 0; idx < svsp->bank_max; idx++) { - svsb = &svsp->banks[idx]; + struct svs_bank *svsb = &svsp->banks[idx]; + const struct svs_bank_pdata *bdata = &svsb->pdata; - if (svsb->type == SVSB_HIGH) - svsb->opp_dev = svs_add_device_link(svsp, "gpu"); - else if (svsb->type == SVSB_LOW) - svsb->opp_dev = svs_get_subsys_device(svsp, "gpu"); + switch (bdata->sw_id) { + case SVSB_SWID_CPU_LITTLE: + case SVSB_SWID_CPU_BIG: + svsb->opp_dev = get_cpu_device(bdata->cpu_id); + break; + case SVSB_SWID_CCI: + svsb->opp_dev = svs_add_device_link(svsp, "cci"); + break; + case SVSB_SWID_GPU: + if (bdata->type == SVSB_TYPE_LOW) + svsb->opp_dev = svs_get_subsys_device(svsp, "gpu"); + else + svsb->opp_dev = svs_add_device_link(svsp, "gpu"); + break; + default: + dev_err(svsb->dev, "unknown sw_id: %u\n", bdata->sw_id); + return -EINVAL; + } if (IS_ERR(svsb->opp_dev)) return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev), @@ -2186,30 +2214,30 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp) static int svs_mt8183_platform_probe(struct svs_platform *svsp) { struct device *dev; - struct svs_bank *svsb; u32 idx; - dev = svs_add_device_link(svsp, "thermal"); + dev = svs_add_device_link(svsp, "thermal-sensor"); if (IS_ERR(dev)) return dev_err_probe(svsp->dev, PTR_ERR(dev), "failed to get thermal device\n"); for (idx = 0; idx < svsp->bank_max; idx++) { - svsb = &svsp->banks[idx]; + struct svs_bank *svsb = &svsp->banks[idx]; + const struct svs_bank_pdata *bdata = &svsb->pdata; - switch (svsb->sw_id) { - case SVSB_CPU_LITTLE: - case SVSB_CPU_BIG: - svsb->opp_dev = get_cpu_device(svsb->cpu_id); + switch (bdata->sw_id) { + case SVSB_SWID_CPU_LITTLE: + case SVSB_SWID_CPU_BIG: + svsb->opp_dev = get_cpu_device(bdata->cpu_id); break; - case SVSB_CCI: + case SVSB_SWID_CCI: svsb->opp_dev = svs_add_device_link(svsp, "cci"); break; - case SVSB_GPU: + case SVSB_SWID_GPU: svsb->opp_dev = svs_add_device_link(svsp, "gpu"); break; default: - dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id); + dev_err(svsb->dev, "unknown sw_id: %u\n", bdata->sw_id); return -EINVAL; } @@ -2222,241 +2250,544 @@ static int svs_mt8183_platform_probe(struct svs_platform *svsp) return 0; } +static struct svs_bank svs_mt8195_banks[] = { + { + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_GPU, + .type = SVSB_TYPE_LOW, + .set_freq_pct = svs_set_bank_freq_pct_v3, + .get_volts = svs_get_bank_volts_v3, + .opp_count = MAX_OPP_ENTRIES, + .turn_freq_base = 640000000, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x555555, + .dc_config = 0x1, + .vco = 0x18, + .chk_shift = 0x87, + .int_st = BIT(0), + .ctl0 = 0x00540003, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 10, 16 }, { 10, 24 }, { 10, 0 }, { 8, 0 }, { 8, 8 } + } + }, + .mode_support = SVSB_MODE_INIT02, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT, + .freq_base = 640000000, + .core_sel = 0x0fff0100, + .dvt_fixed = 0x1, + .vmax = 0x38, + .vmin = 0x14, + }, + { + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_GPU, + .type = SVSB_TYPE_HIGH, + .set_freq_pct = svs_set_bank_freq_pct_v3, + .get_volts = svs_get_bank_volts_v3, + .tzone_name = "gpu", + .opp_count = MAX_OPP_ENTRIES, + .turn_freq_base = 640000000, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x555555, + .dc_config = 0x1, + .vco = 0x18, + .chk_shift = 0x87, + .int_st = BIT(1), + .ctl0 = 0x00540003, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 0, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 7, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 9, 16 }, { 9, 24 }, { 9, 0 }, { 8, 0 }, { 8, 8 } + }, + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE, + .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, + .freq_base = 880000000, + .core_sel = 0x0fff0101, + .dvt_fixed = 0x6, + .vmax = 0x38, + .vmin = 0x14, + }, +}; + static struct svs_bank svs_mt8192_banks[] = { { - .sw_id = SVSB_GPU, - .type = SVSB_LOW, - .set_freq_pct = svs_set_bank_freq_pct_v3, - .get_volts = svs_get_bank_volts_v3, - .tzone_name = "gpu1", - .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT, - .mode_support = SVSB_MODE_INIT02, - .opp_count = MAX_OPP_ENTRIES, - .freq_base = 688000000, - .turn_freq_base = 688000000, - .volt_step = 6250, - .volt_base = 400000, - .vmax = 0x60, - .vmin = 0x1a, - .age_config = 0x555555, - .dc_config = 0x1, - .dvt_fixed = 0x1, - .vco = 0x18, - .chk_shift = 0x87, - .core_sel = 0x0fff0100, - .int_st = BIT(0), - .ctl0 = 0x00540003, - .tzone_htemp = 85000, - .tzone_htemp_voffset = 0, - .tzone_ltemp = 25000, - .tzone_ltemp_voffset = 7, + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_GPU, + .type = SVSB_TYPE_LOW, + .set_freq_pct = svs_set_bank_freq_pct_v3, + .get_volts = svs_get_bank_volts_v3, + .tzone_name = "gpu", + .opp_count = MAX_OPP_ENTRIES, + .turn_freq_base = 688000000, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x555555, + .dc_config = 0x1, + .vco = 0x18, + .chk_shift = 0x87, + .int_st = BIT(0), + .ctl0 = 0x00540003, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 0, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 7, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 10, 16 }, { 10, 24 }, { 10, 0 }, { 17, 0 }, { 17, 8 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT, + .mode_support = SVSB_MODE_INIT02, + .freq_base = 688000000, + .core_sel = 0x0fff0100, + .dvt_fixed = 0x1, + .vmax = 0x60, + .vmin = 0x1a, }, { - .sw_id = SVSB_GPU, - .type = SVSB_HIGH, - .set_freq_pct = svs_set_bank_freq_pct_v3, - .get_volts = svs_get_bank_volts_v3, - .tzone_name = "gpu1", - .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | - SVSB_MON_VOLT_IGNORE, - .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, - .opp_count = MAX_OPP_ENTRIES, - .freq_base = 902000000, - .turn_freq_base = 688000000, - .volt_step = 6250, - .volt_base = 400000, - .vmax = 0x60, - .vmin = 0x1a, - .age_config = 0x555555, - .dc_config = 0x1, - .dvt_fixed = 0x6, - .vco = 0x18, - .chk_shift = 0x87, - .core_sel = 0x0fff0101, - .int_st = BIT(1), - .ctl0 = 0x00540003, - .tzone_htemp = 85000, - .tzone_htemp_voffset = 0, - .tzone_ltemp = 25000, - .tzone_ltemp_voffset = 7, + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_GPU, + .type = SVSB_TYPE_HIGH, + .set_freq_pct = svs_set_bank_freq_pct_v3, + .get_volts = svs_get_bank_volts_v3, + .tzone_name = "gpu", + .opp_count = MAX_OPP_ENTRIES, + .turn_freq_base = 688000000, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x555555, + .dc_config = 0x1, + .vco = 0x18, + .chk_shift = 0x87, + .int_st = BIT(1), + .ctl0 = 0x00540003, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 0, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 7, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 9, 16 }, { 9, 24 }, { 17, 0 }, { 17, 16 }, { 17, 24 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE, + .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, + .freq_base = 902000000, + .core_sel = 0x0fff0101, + .dvt_fixed = 0x6, + .vmax = 0x60, + .vmin = 0x1a, }, }; static struct svs_bank svs_mt8188_banks[] = { { - .sw_id = SVSB_GPU, - .type = SVSB_LOW, - .set_freq_pct = svs_set_bank_freq_pct_v3, - .get_volts = svs_get_bank_volts_v3, - .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT, - .mode_support = SVSB_MODE_INIT02, - .opp_count = MAX_OPP_ENTRIES, - .freq_base = 640000000, - .turn_freq_base = 640000000, - .volt_step = 6250, - .volt_base = 400000, - .vmax = 0x38, - .vmin = 0x1c, - .age_config = 0x555555, - .dc_config = 0x555555, - .dvt_fixed = 0x1, - .vco = 0x10, - .chk_shift = 0x87, - .core_sel = 0x0fff0000, - .int_st = BIT(0), - .ctl0 = 0x00100003, + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_GPU, + .type = SVSB_TYPE_LOW, + .set_freq_pct = svs_set_bank_freq_pct_v3, + .get_volts = svs_get_bank_volts_v3, + .opp_count = MAX_OPP_ENTRIES, + .turn_freq_base = 640000000, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x555555, + .dc_config = 0x555555, + .vco = 0x10, + .chk_shift = 0x87, + .int_st = BIT(0), + .ctl0 = 0x00100003, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 5, 16 }, { 5, 24 }, { 5, 0 }, { 15, 16 }, { 15, 24 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT, + .mode_support = SVSB_MODE_INIT02, + .freq_base = 640000000, + .core_sel = 0x0fff0000, + .dvt_fixed = 0x1, + .vmax = 0x38, + .vmin = 0x1c, + }, + { + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_GPU, + .type = SVSB_TYPE_HIGH, + .set_freq_pct = svs_set_bank_freq_pct_v3, + .get_volts = svs_get_bank_volts_v3, + .tzone_name = "gpu", + .opp_count = MAX_OPP_ENTRIES, + .turn_freq_base = 640000000, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x555555, + .dc_config = 0x555555, + .vco = 0x10, + .chk_shift = 0x87, + .int_st = BIT(1), + .ctl0 = 0x00100003, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 0, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 7, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 4, 16 }, { 4, 24 }, { 4, 0 }, { 14, 0 }, { 14, 8 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE, + .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, + .freq_base = 880000000, + .core_sel = 0x0fff0001, + .dvt_fixed = 0x4, + .vmax = 0x38, + .vmin = 0x1c, + }, +}; + +static struct svs_bank svs_mt8186_banks[] = { + { + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_CPU_BIG, + .type = SVSB_TYPE_LOW, + .set_freq_pct = svs_set_bank_freq_pct_v3, + .get_volts = svs_get_bank_volts_v3, + .cpu_id = 6, + .opp_count = MAX_OPP_ENTRIES, + .turn_freq_base = 1670000000, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x1, + .dc_config = 0x1, + .vco = 0x10, + .chk_shift = 0x87, + .int_st = BIT(0), + .ctl0 = 0x00540003, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 3, 16 }, { 3, 24 }, { 3, 0 }, { 14, 16 }, { 14, 24 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT, + .volt_od = 4, + .mode_support = SVSB_MODE_INIT02, + .freq_base = 1670000000, + .core_sel = 0x0fff0100, + .dvt_fixed = 0x3, + .vmax = 0x59, + .vmin = 0x20, + }, + { + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_CPU_BIG, + .type = SVSB_TYPE_HIGH, + .set_freq_pct = svs_set_bank_freq_pct_v3, + .get_volts = svs_get_bank_volts_v3, + .cpu_id = 6, + .tzone_name = "cpu-big", + .opp_count = MAX_OPP_ENTRIES, + .turn_freq_base = 1670000000, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x1, + .dc_config = 0x1, + .vco = 0x10, + .chk_shift = 0x87, + .int_st = BIT(1), + .ctl0 = 0x00540003, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 8, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 8, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 2, 16 }, { 2, 24 }, { 2, 0 }, { 13, 0 }, { 13, 8 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE, + .volt_od = 4, + .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, + .freq_base = 2050000000, + .core_sel = 0x0fff0101, + .dvt_fixed = 0x6, + .vmax = 0x73, + .vmin = 0x20, + }, + { + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_CPU_LITTLE, + .set_freq_pct = svs_set_bank_freq_pct_v2, + .get_volts = svs_get_bank_volts_v2, + .cpu_id = 0, + .tzone_name = "cpu-little", + .opp_count = MAX_OPP_ENTRIES, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x1, + .dc_config = 0x1, + .vco = 0x10, + .chk_shift = 0x87, + .int_st = BIT(2), + .ctl0 = 0x3210000f, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 8, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 8, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 4, 16 }, { 4, 24 }, { 4, 0 }, { 14, 0 }, { 14, 8 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE, + .volt_od = 3, + .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, + .freq_base = 2000000000, + .core_sel = 0x0fff0102, + .dvt_fixed = 0x6, + .vmax = 0x65, + .vmin = 0x20, }, { - .sw_id = SVSB_GPU, - .type = SVSB_HIGH, - .set_freq_pct = svs_set_bank_freq_pct_v3, - .get_volts = svs_get_bank_volts_v3, - .tzone_name = "gpu1", - .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | - SVSB_MON_VOLT_IGNORE, - .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, - .opp_count = MAX_OPP_ENTRIES, - .freq_base = 880000000, - .turn_freq_base = 640000000, - .volt_step = 6250, - .volt_base = 400000, - .vmax = 0x38, - .vmin = 0x1c, - .age_config = 0x555555, - .dc_config = 0x555555, - .dvt_fixed = 0x4, - .vco = 0x10, - .chk_shift = 0x87, - .core_sel = 0x0fff0001, - .int_st = BIT(1), - .ctl0 = 0x00100003, - .tzone_htemp = 85000, - .tzone_htemp_voffset = 0, - .tzone_ltemp = 25000, - .tzone_ltemp_voffset = 7, + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_CCI, + .set_freq_pct = svs_set_bank_freq_pct_v2, + .get_volts = svs_get_bank_volts_v2, + .tzone_name = "cci", + .opp_count = MAX_OPP_ENTRIES, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x1, + .dc_config = 0x1, + .vco = 0x10, + .chk_shift = 0x87, + .int_st = BIT(3), + .ctl0 = 0x3210000f, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 8, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 8, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 5, 16 }, { 5, 24 }, { 5, 0 }, { 15, 16 }, { 15, 24 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE, + .volt_od = 3, + .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, + .freq_base = 1400000000, + .core_sel = 0x0fff0103, + .dvt_fixed = 0x6, + .vmax = 0x65, + .vmin = 0x20, + }, + { + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_GPU, + .set_freq_pct = svs_set_bank_freq_pct_v2, + .get_volts = svs_get_bank_volts_v2, + .tzone_name = "gpu", + .opp_count = MAX_OPP_ENTRIES, + .volt_step = 6250, + .volt_base = 400000, + .age_config = 0x555555, + .dc_config = 0x1, + .vco = 0x10, + .chk_shift = 0x87, + .int_st = BIT(4), + .ctl0 = 0x00100003, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 8, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 7, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 6, 16 }, { 6, 24 }, { 6, 0 }, { 15, 8 }, { 15, 0 } + } + }, + .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE, + .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON, + .freq_base = 850000000, + .core_sel = 0x0fff0104, + .dvt_fixed = 0x4, + .vmax = 0x58, + .vmin = 0x20, }, }; static struct svs_bank svs_mt8183_banks[] = { { - .sw_id = SVSB_CPU_LITTLE, - .set_freq_pct = svs_set_bank_freq_pct_v2, - .get_volts = svs_get_bank_volts_v2, - .cpu_id = 0, - .buck_name = "proc", - .volt_flags = SVSB_INIT01_VOLT_INC_ONLY, - .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02, - .opp_count = MAX_OPP_ENTRIES, - .freq_base = 1989000000, - .vboot = 0x30, - .volt_step = 6250, - .volt_base = 500000, - .vmax = 0x64, - .vmin = 0x18, - .age_config = 0x555555, - .dc_config = 0x555555, - .dvt_fixed = 0x7, - .vco = 0x10, - .chk_shift = 0x77, - .core_sel = 0x8fff0000, - .int_st = BIT(0), - .ctl0 = 0x00010001, + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_CPU_LITTLE, + .set_freq_pct = svs_set_bank_freq_pct_v2, + .get_volts = svs_get_bank_volts_v2, + .cpu_id = 0, + .buck_name = "proc", + .opp_count = MAX_OPP_ENTRIES, + .vboot = 0x30, + .volt_step = 6250, + .volt_base = 500000, + .age_config = 0x555555, + .dc_config = 0x555555, + .vco = 0x10, + .chk_shift = 0x77, + .int_st = BIT(0), + .ctl0 = 0x00010001, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 16, 0 }, { 16, 8 }, { 17, 16 }, { 16, 16 }, { 16, 24 } + } + }, + .volt_flags = SVSB_INIT01_VOLT_INC_ONLY, + .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02, + .freq_base = 1989000000, + .core_sel = 0x8fff0000, + .dvt_fixed = 0x7, + .vmax = 0x64, + .vmin = 0x18, + }, { - .sw_id = SVSB_CPU_BIG, - .set_freq_pct = svs_set_bank_freq_pct_v2, - .get_volts = svs_get_bank_volts_v2, - .cpu_id = 4, - .buck_name = "proc", - .volt_flags = SVSB_INIT01_VOLT_INC_ONLY, - .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02, - .opp_count = MAX_OPP_ENTRIES, - .freq_base = 1989000000, - .vboot = 0x30, - .volt_step = 6250, - .volt_base = 500000, - .vmax = 0x58, - .vmin = 0x10, - .age_config = 0x555555, - .dc_config = 0x555555, - .dvt_fixed = 0x7, - .vco = 0x10, - .chk_shift = 0x77, - .core_sel = 0x8fff0001, - .int_st = BIT(1), - .ctl0 = 0x00000001, + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_CPU_BIG, + .set_freq_pct = svs_set_bank_freq_pct_v2, + .get_volts = svs_get_bank_volts_v2, + .cpu_id = 4, + .buck_name = "proc", + .opp_count = MAX_OPP_ENTRIES, + .vboot = 0x30, + .volt_step = 6250, + .volt_base = 500000, + .age_config = 0x555555, + .dc_config = 0x555555, + .vco = 0x10, + .chk_shift = 0x77, + .int_st = BIT(1), + .ctl0 = 0x00000001, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 18, 0 }, { 18, 8 }, { 17, 0 }, { 18, 16 }, { 18, 24 } + } + }, + .volt_flags = SVSB_INIT01_VOLT_INC_ONLY, + .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02, + .freq_base = 1989000000, + .core_sel = 0x8fff0001, + .dvt_fixed = 0x7, + .vmax = 0x58, + .vmin = 0x10, + }, { - .sw_id = SVSB_CCI, - .set_freq_pct = svs_set_bank_freq_pct_v2, - .get_volts = svs_get_bank_volts_v2, - .buck_name = "proc", - .volt_flags = SVSB_INIT01_VOLT_INC_ONLY, - .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02, - .opp_count = MAX_OPP_ENTRIES, - .freq_base = 1196000000, - .vboot = 0x30, - .volt_step = 6250, - .volt_base = 500000, - .vmax = 0x64, - .vmin = 0x18, - .age_config = 0x555555, - .dc_config = 0x555555, - .dvt_fixed = 0x7, - .vco = 0x10, - .chk_shift = 0x77, - .core_sel = 0x8fff0002, - .int_st = BIT(2), - .ctl0 = 0x00100003, + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_CCI, + .set_freq_pct = svs_set_bank_freq_pct_v2, + .get_volts = svs_get_bank_volts_v2, + .buck_name = "proc", + .opp_count = MAX_OPP_ENTRIES, + .vboot = 0x30, + .volt_step = 6250, + .volt_base = 500000, + .age_config = 0x555555, + .dc_config = 0x555555, + .vco = 0x10, + .chk_shift = 0x77, + .int_st = BIT(2), + .ctl0 = 0x00100003, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 4, 0 }, { 4, 8 }, { 5, 16 }, { 4, 16 }, { 4, 24 } + } + }, + .volt_flags = SVSB_INIT01_VOLT_INC_ONLY, + .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02, + .freq_base = 1196000000, + .core_sel = 0x8fff0002, + .dvt_fixed = 0x7, + .vmax = 0x64, + .vmin = 0x18, }, { - .sw_id = SVSB_GPU, - .set_freq_pct = svs_set_bank_freq_pct_v2, - .get_volts = svs_get_bank_volts_v2, - .buck_name = "mali", - .tzone_name = "tzts2", - .volt_flags = SVSB_INIT01_PD_REQ | - SVSB_INIT01_VOLT_INC_ONLY, - .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02 | - SVSB_MODE_MON, - .opp_count = MAX_OPP_ENTRIES, - .freq_base = 900000000, - .vboot = 0x30, - .volt_step = 6250, - .volt_base = 500000, - .vmax = 0x40, - .vmin = 0x14, - .age_config = 0x555555, - .dc_config = 0x555555, - .dvt_fixed = 0x3, - .vco = 0x10, - .chk_shift = 0x77, - .core_sel = 0x8fff0003, - .int_st = BIT(3), - .ctl0 = 0x00050001, - .tzone_htemp = 85000, - .tzone_htemp_voffset = 0, - .tzone_ltemp = 25000, - .tzone_ltemp_voffset = 3, + .pdata = (const struct svs_bank_pdata) { + .sw_id = SVSB_SWID_GPU, + .set_freq_pct = svs_set_bank_freq_pct_v2, + .get_volts = svs_get_bank_volts_v2, + .buck_name = "mali", + .tzone_name = "gpu", + .opp_count = MAX_OPP_ENTRIES, + .vboot = 0x30, + .volt_step = 6250, + .volt_base = 500000, + .age_config = 0x555555, + .dc_config = 0x555555, + .vco = 0x10, + .chk_shift = 0x77, + .int_st = BIT(3), + .ctl0 = 0x00050001, + .tzone_htemp = 85000, + .tzone_htemp_voffset = 0, + .tzone_ltemp = 25000, + .tzone_ltemp_voffset = 3, + .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) { + { 6, 0 }, { 6, 8 }, { 5, 0 }, { 6, 16 }, { 6, 24 } + } + }, + .volt_flags = SVSB_INIT01_PD_REQ | SVSB_INIT01_VOLT_INC_ONLY, + .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02 | SVSB_MODE_MON, + .freq_base = 900000000, + .core_sel = 0x8fff0003, + .dvt_fixed = 0x3, + .vmax = 0x40, + .vmin = 0x14, }, }; +static const struct svs_platform_data svs_mt8195_platform_data = { + .name = "mt8195-svs", + .banks = svs_mt8195_banks, + .efuse_parsing = svs_common_parse_efuse, + .probe = svs_mt8192_platform_probe, + .regs = svs_regs_v2, + .bank_max = ARRAY_SIZE(svs_mt8195_banks), + .ts_coeff = SVSB_TS_COEFF_MT8195, + .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) { + { 0, 0 }, { 19, 4 } + } +}; + static const struct svs_platform_data svs_mt8192_platform_data = { .name = "mt8192-svs", .banks = svs_mt8192_banks, - .efuse_parsing = svs_mt8192_efuse_parsing, + .efuse_parsing = svs_common_parse_efuse, .probe = svs_mt8192_platform_probe, .regs = svs_regs_v2, .bank_max = ARRAY_SIZE(svs_mt8192_banks), + .ts_coeff = SVSB_TS_COEFF_MT8195, + .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) { + /* FT_PGM not present */ + { -1, 0 }, { 19, 4 } + } }; static const struct svs_platform_data svs_mt8188_platform_data = { .name = "mt8188-svs", .banks = svs_mt8188_banks, - .efuse_parsing = svs_mt8188_efuse_parsing, + .efuse_parsing = svs_common_parse_efuse, .probe = svs_mt8192_platform_probe, .regs = svs_regs_v2, .bank_max = ARRAY_SIZE(svs_mt8188_banks), + .ts_coeff = SVSB_TS_COEFF_MT8195, + .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) { + /* FT_PGM and VMIN not present */ + { -1, 0 }, { -1, 0 } + } +}; + +static const struct svs_platform_data svs_mt8186_platform_data = { + .name = "mt8186-svs", + .banks = svs_mt8186_banks, + .efuse_parsing = svs_common_parse_efuse, + .probe = svs_mt8192_platform_probe, + .regs = svs_regs_v2, + .bank_max = ARRAY_SIZE(svs_mt8186_banks), + .ts_coeff = SVSB_TS_COEFF_MT8186, + .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) { + /* FT_PGM and VMIN not present */ + { -1, 0 }, { -1, 0 } + } }; static const struct svs_platform_data svs_mt8183_platform_data = { @@ -2466,21 +2797,19 @@ static const struct svs_platform_data svs_mt8183_platform_data = { .probe = svs_mt8183_platform_probe, .regs = svs_regs_v2, .bank_max = ARRAY_SIZE(svs_mt8183_banks), + .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) { + /* VMIN not present */ + { 0, 4 }, { -1, 0 } + } }; static const struct of_device_id svs_of_match[] = { - { - .compatible = "mediatek,mt8192-svs", - .data = &svs_mt8192_platform_data, - }, { - .compatible = "mediatek,mt8188-svs", - .data = &svs_mt8188_platform_data, - }, { - .compatible = "mediatek,mt8183-svs", - .data = &svs_mt8183_platform_data, - }, { - /* Sentinel */ - }, + { .compatible = "mediatek,mt8195-svs", .data = &svs_mt8195_platform_data }, + { .compatible = "mediatek,mt8192-svs", .data = &svs_mt8192_platform_data }, + { .compatible = "mediatek,mt8188-svs", .data = &svs_mt8188_platform_data }, + { .compatible = "mediatek,mt8186-svs", .data = &svs_mt8186_platform_data }, + { .compatible = "mediatek,mt8183-svs", .data = &svs_mt8183_platform_data }, + { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, svs_of_match); @@ -2500,6 +2829,7 @@ static int svs_probe(struct platform_device *pdev) svsp->banks = svsp_data->banks; svsp->regs = svsp_data->regs; svsp->bank_max = svsp_data->bank_max; + svsp->ts_coeff = svsp_data->ts_coeff; ret = svsp_data->probe(svsp); if (ret) @@ -2507,20 +2837,24 @@ static int svs_probe(struct platform_device *pdev) ret = svs_get_efuse_data(svsp, "svs-calibration-data", &svsp->efuse, &svsp->efuse_max); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Cannot read SVS calibration\n"); + + ret = svs_get_efuse_data(svsp, "t-calibration-data", + &svsp->tefuse, &svsp->tefuse_max); if (ret) { - ret = -EPERM; + dev_err_probe(&pdev->dev, ret, "Cannot read SVS-Thermal calibration\n"); goto svs_probe_free_efuse; } - if (!svsp_data->efuse_parsing(svsp)) { - dev_err(svsp->dev, "efuse data parsing failed\n"); - ret = -EPERM; + if (!svsp_data->efuse_parsing(svsp, svsp_data)) { + ret = dev_err_probe(svsp->dev, -EINVAL, "efuse data parsing failed\n"); goto svs_probe_free_tefuse; } ret = svs_bank_resource_setup(svsp); if (ret) { - dev_err(svsp->dev, "svs bank resource setup fail: %d\n", ret); + dev_err_probe(svsp->dev, ret, "svs bank resource setup fail\n"); goto svs_probe_free_tefuse; } @@ -2532,43 +2866,40 @@ static int svs_probe(struct platform_device *pdev) svsp->main_clk = devm_clk_get(svsp->dev, "main"); if (IS_ERR(svsp->main_clk)) { - dev_err(svsp->dev, "failed to get clock: %ld\n", - PTR_ERR(svsp->main_clk)); - ret = PTR_ERR(svsp->main_clk); + ret = dev_err_probe(svsp->dev, PTR_ERR(svsp->main_clk), + "failed to get clock\n"); goto svs_probe_free_tefuse; } ret = clk_prepare_enable(svsp->main_clk); if (ret) { - dev_err(svsp->dev, "cannot enable main clk: %d\n", ret); + dev_err_probe(svsp->dev, ret, "cannot enable main clk\n"); goto svs_probe_free_tefuse; } svsp->base = of_iomap(svsp->dev->of_node, 0); if (IS_ERR_OR_NULL(svsp->base)) { - dev_err(svsp->dev, "cannot find svs register base\n"); - ret = -EINVAL; + ret = dev_err_probe(svsp->dev, -EINVAL, "cannot find svs register base\n"); goto svs_probe_clk_disable; } ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr, IRQF_ONESHOT, svsp_data->name, svsp); if (ret) { - dev_err(svsp->dev, "register irq(%d) failed: %d\n", - svsp_irq, ret); + dev_err_probe(svsp->dev, ret, "register irq(%d) failed\n", svsp_irq); goto svs_probe_iounmap; } ret = svs_start(svsp); if (ret) { - dev_err(svsp->dev, "svs start fail: %d\n", ret); + dev_err_probe(svsp->dev, ret, "svs start fail\n"); goto svs_probe_iounmap; } #ifdef CONFIG_DEBUG_FS ret = svs_create_debug_cmds(svsp); if (ret) { - dev_err(svsp->dev, "svs create debug cmds fail: %d\n", ret); + dev_err_probe(svsp->dev, ret, "svs create debug cmds fail\n"); goto svs_probe_iounmap; } #endif @@ -2577,18 +2908,12 @@ static int svs_probe(struct platform_device *pdev) svs_probe_iounmap: iounmap(svsp->base); - svs_probe_clk_disable: clk_disable_unprepare(svsp->main_clk); - svs_probe_free_tefuse: - if (!IS_ERR_OR_NULL(svsp->tefuse)) - kfree(svsp->tefuse); - + kfree(svsp->tefuse); svs_probe_free_efuse: - if (!IS_ERR_OR_NULL(svsp->efuse)) - kfree(svsp->efuse); - + kfree(svsp->efuse); return ret; } @@ -2606,5 +2931,6 @@ static struct platform_driver svs_driver = { module_platform_driver(svs_driver); MODULE_AUTHOR("Roger Lu <roger.lu@mediatek.com>"); +MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); MODULE_DESCRIPTION("MediaTek SVS driver"); MODULE_LICENSE("GPL"); |