1515#include <linux/soc/mediatek/dvfsrc.h>
1616#include <linux/soc/mediatek/mtk_sip_svc.h>
1717
18+ /* DVFSRC_BASIC_CONTROL */
19+ #define DVFSRC_V4_BASIC_CTRL_OPP_COUNT GENMASK(26, 20)
20+
1821/* DVFSRC_LEVEL */
1922#define DVFSRC_V1_LEVEL_TARGET_LEVEL GENMASK(15, 0)
2023#define DVFSRC_TGT_LEVEL_IDLE 0x00
2124#define DVFSRC_V1_LEVEL_CURRENT_LEVEL GENMASK(31, 16)
2225
26+ #define DVFSRC_V4_LEVEL_TARGET_LEVEL GENMASK(15, 8)
27+ #define DVFSRC_V4_LEVEL_TARGET_PRESENT BIT(16)
28+
2329/* DVFSRC_SW_REQ, DVFSRC_SW_REQ2 */
2430#define DVFSRC_V1_SW_REQ2_DRAM_LEVEL GENMASK(1, 0)
2531#define DVFSRC_V1_SW_REQ2_VCORE_LEVEL GENMASK(3, 2)
2632
2733#define DVFSRC_V2_SW_REQ_DRAM_LEVEL GENMASK(3, 0)
2834#define DVFSRC_V2_SW_REQ_VCORE_LEVEL GENMASK(6, 4)
2935
36+ #define DVFSRC_V4_SW_REQ_EMI_LEVEL GENMASK(3, 0)
37+ #define DVFSRC_V4_SW_REQ_DRAM_LEVEL GENMASK(15, 12)
38+
3039/* DVFSRC_VCORE */
3140#define DVFSRC_V2_VCORE_REQ_VSCP_LEVEL GENMASK(14, 12)
3241
42+ /* DVFSRC_TARGET_GEAR */
43+ #define DVFSRC_V4_GEAR_TARGET_DRAM GENMASK(7, 0)
44+ #define DVFSRC_V4_GEAR_TARGET_VCORE GENMASK(15, 8)
45+
46+ /* DVFSRC_GEAR_INFO */
47+ #define DVFSRC_V4_GEAR_INFO_REG_WIDTH 0x4
48+ #define DVFSRC_V4_GEAR_INFO_REG_LEVELS 64
49+ #define DVFSRC_V4_GEAR_INFO_VCORE GENMASK(3, 0)
50+ #define DVFSRC_V4_GEAR_INFO_EMI GENMASK(7, 4)
51+ #define DVFSRC_V4_GEAR_INFO_DRAM GENMASK(15, 12)
52+
3353#define DVFSRC_POLL_TIMEOUT_US 1000
3454#define STARTUP_TIME_US 1
3555
@@ -52,6 +72,7 @@ struct dvfsrc_bw_constraints {
5272struct dvfsrc_opp {
5373 u32 vcore_opp ;
5474 u32 dram_opp ;
75+ u32 emi_opp ;
5576};
5677
5778struct dvfsrc_opp_desc {
@@ -72,13 +93,16 @@ struct mtk_dvfsrc {
7293
7394struct dvfsrc_soc_data {
7495 const int * regs ;
96+ const u8 * bw_units ;
7597 const bool has_emi_ddr ;
7698 const struct dvfsrc_opp_desc * opps_desc ;
7799 u32 (* calc_dram_bw )(struct mtk_dvfsrc * dvfsrc , int type , u64 bw );
78100 u32 (* get_target_level )(struct mtk_dvfsrc * dvfsrc );
79101 u32 (* get_current_level )(struct mtk_dvfsrc * dvfsrc );
80102 u32 (* get_vcore_level )(struct mtk_dvfsrc * dvfsrc );
81103 u32 (* get_vscp_level )(struct mtk_dvfsrc * dvfsrc );
104+ u32 (* get_opp_count )(struct mtk_dvfsrc * dvfsrc );
105+ int (* get_hw_opps )(struct mtk_dvfsrc * dvfsrc );
82106 void (* set_dram_bw )(struct mtk_dvfsrc * dvfsrc , u64 bw );
83107 void (* set_dram_peak_bw )(struct mtk_dvfsrc * dvfsrc , u64 bw );
84108 void (* set_dram_hrt_bw )(struct mtk_dvfsrc * dvfsrc , u64 bw );
@@ -101,6 +125,7 @@ static void dvfsrc_writel(struct mtk_dvfsrc *dvfs, u32 offset, u32 val)
101125}
102126
103127enum dvfsrc_regs {
128+ DVFSRC_BASIC_CONTROL ,
104129 DVFSRC_SW_REQ ,
105130 DVFSRC_SW_REQ2 ,
106131 DVFSRC_LEVEL ,
@@ -110,6 +135,9 @@ enum dvfsrc_regs {
110135 DVFSRC_SW_HRT_BW ,
111136 DVFSRC_SW_EMI_BW ,
112137 DVFSRC_VCORE ,
138+ DVFSRC_TARGET_GEAR ,
139+ DVFSRC_GEAR_INFO_L ,
140+ DVFSRC_GEAR_INFO_H ,
113141 DVFSRC_REGS_MAX ,
114142};
115143
@@ -130,13 +158,43 @@ static const int dvfsrc_mt8195_regs[] = {
130158 [DVFSRC_TARGET_LEVEL ] = 0xd48 ,
131159};
132160
161+ static const int dvfsrc_mt8196_regs [] = {
162+ [DVFSRC_BASIC_CONTROL ] = 0x0 ,
163+ [DVFSRC_SW_REQ ] = 0x18 ,
164+ [DVFSRC_VCORE ] = 0x80 ,
165+ [DVFSRC_GEAR_INFO_L ] = 0xfc ,
166+ [DVFSRC_SW_BW ] = 0x1e8 ,
167+ [DVFSRC_SW_PEAK_BW ] = 0x1f4 ,
168+ [DVFSRC_SW_HRT_BW ] = 0x20c ,
169+ [DVFSRC_LEVEL ] = 0x5f0 ,
170+ [DVFSRC_TARGET_LEVEL ] = 0x5f0 ,
171+ [DVFSRC_SW_REQ2 ] = 0x604 ,
172+ [DVFSRC_SW_EMI_BW ] = 0x60c ,
173+ [DVFSRC_TARGET_GEAR ] = 0x6ac ,
174+ [DVFSRC_GEAR_INFO_H ] = 0x6b0 ,
175+ };
176+
133177static const struct dvfsrc_opp * dvfsrc_get_current_opp (struct mtk_dvfsrc * dvfsrc )
134178{
135179 u32 level = dvfsrc -> dvd -> get_current_level (dvfsrc );
136180
137181 return & dvfsrc -> curr_opps -> opps [level ];
138182}
139183
184+ static u32 dvfsrc_get_current_target_vcore_gear (struct mtk_dvfsrc * dvfsrc )
185+ {
186+ u32 val = dvfsrc_readl (dvfsrc , DVFSRC_TARGET_GEAR );
187+
188+ return FIELD_GET (DVFSRC_V4_GEAR_TARGET_VCORE , val );
189+ }
190+
191+ static u32 dvfsrc_get_current_target_dram_gear (struct mtk_dvfsrc * dvfsrc )
192+ {
193+ u32 val = dvfsrc_readl (dvfsrc , DVFSRC_TARGET_GEAR );
194+
195+ return FIELD_GET (DVFSRC_V4_GEAR_TARGET_DRAM , val );
196+ }
197+
140198static bool dvfsrc_is_idle (struct mtk_dvfsrc * dvfsrc )
141199{
142200 if (!dvfsrc -> dvd -> get_target_level )
@@ -193,6 +251,24 @@ static int dvfsrc_wait_for_opp_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level)
193251 return 0 ;
194252}
195253
254+ static int dvfsrc_wait_for_vcore_level_v4 (struct mtk_dvfsrc * dvfsrc , u32 level )
255+ {
256+ u32 val ;
257+
258+ return readx_poll_timeout_atomic (dvfsrc_get_current_target_vcore_gear ,
259+ dvfsrc , val , val >= level ,
260+ STARTUP_TIME_US , DVFSRC_POLL_TIMEOUT_US );
261+ }
262+
263+ static int dvfsrc_wait_for_opp_level_v4 (struct mtk_dvfsrc * dvfsrc , u32 level )
264+ {
265+ u32 val ;
266+
267+ return readx_poll_timeout_atomic (dvfsrc_get_current_target_dram_gear ,
268+ dvfsrc , val , val >= level ,
269+ STARTUP_TIME_US , DVFSRC_POLL_TIMEOUT_US );
270+ }
271+
196272static u32 dvfsrc_get_target_level_v1 (struct mtk_dvfsrc * dvfsrc )
197273{
198274 u32 val = dvfsrc_readl (dvfsrc , DVFSRC_LEVEL );
@@ -226,6 +302,27 @@ static u32 dvfsrc_get_current_level_v2(struct mtk_dvfsrc *dvfsrc)
226302 return 0 ;
227303}
228304
305+ static u32 dvfsrc_get_target_level_v4 (struct mtk_dvfsrc * dvfsrc )
306+ {
307+ u32 val = dvfsrc_readl (dvfsrc , DVFSRC_TARGET_LEVEL );
308+
309+ if (val & DVFSRC_V4_LEVEL_TARGET_PRESENT )
310+ return FIELD_GET (DVFSRC_V4_LEVEL_TARGET_LEVEL , val ) + 1 ;
311+ return 0 ;
312+ }
313+
314+ static u32 dvfsrc_get_current_level_v4 (struct mtk_dvfsrc * dvfsrc )
315+ {
316+ u32 level = dvfsrc_readl (dvfsrc , DVFSRC_LEVEL ) + 1 ;
317+
318+ /* Valid levels */
319+ if (level < dvfsrc -> curr_opps -> num_opp )
320+ return dvfsrc -> curr_opps -> num_opp - level ;
321+
322+ /* Zero for level 0 or invalid level */
323+ return 0 ;
324+ }
325+
229326static u32 dvfsrc_get_vcore_level_v1 (struct mtk_dvfsrc * dvfsrc )
230327{
231328 u32 val = dvfsrc_readl (dvfsrc , DVFSRC_SW_REQ2 );
@@ -277,11 +374,30 @@ static void dvfsrc_set_vscp_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level)
277374 dvfsrc_writel (dvfsrc , DVFSRC_VCORE , val );
278375}
279376
377+ static u32 dvfsrc_get_opp_count_v4 (struct mtk_dvfsrc * dvfsrc )
378+ {
379+ u32 val = dvfsrc_readl (dvfsrc , DVFSRC_BASIC_CONTROL );
380+
381+ return FIELD_GET (DVFSRC_V4_BASIC_CTRL_OPP_COUNT , val ) + 1 ;
382+ }
383+
280384static u32 dvfsrc_calc_dram_bw_v1 (struct mtk_dvfsrc * dvfsrc , int type , u64 bw )
281385{
282386 return (u32 )div_u64 (bw , 100 * 1000 );
283387}
284388
389+ static u32 dvfsrc_calc_dram_bw_v4 (struct mtk_dvfsrc * dvfsrc , int type , u64 bw )
390+ {
391+ u8 bw_unit = dvfsrc -> dvd -> bw_units [type ];
392+ u64 bw_mbps ;
393+
394+ if (type < DVFSRC_BW_AVG || type >= DVFSRC_BW_MAX )
395+ return 0 ;
396+
397+ bw_mbps = div_u64 (bw , 1000 );
398+ return (u32 )div_u64 ((bw_mbps + bw_unit - 1 ), bw_unit );
399+ }
400+
285401static void __dvfsrc_set_dram_bw_v1 (struct mtk_dvfsrc * dvfsrc , u32 reg ,
286402 int type , u16 max_bw , u16 min_bw , u64 bw )
287403{
@@ -333,6 +449,100 @@ static void dvfsrc_set_opp_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level)
333449 dvfsrc_writel (dvfsrc , DVFSRC_SW_REQ , val );
334450}
335451
452+ static u32 dvfsrc_get_opp_gear (struct mtk_dvfsrc * dvfsrc , u8 level )
453+ {
454+ u32 reg_ofst , val ;
455+ u8 idx ;
456+
457+ /* Calculate register offset and index for requested gear */
458+ if (level < DVFSRC_V4_GEAR_INFO_REG_LEVELS ) {
459+ reg_ofst = dvfsrc -> dvd -> regs [DVFSRC_GEAR_INFO_L ];
460+ idx = level ;
461+ } else {
462+ reg_ofst = dvfsrc -> dvd -> regs [DVFSRC_GEAR_INFO_H ];
463+ idx = level - DVFSRC_V4_GEAR_INFO_REG_LEVELS ;
464+ }
465+ reg_ofst += DVFSRC_V4_GEAR_INFO_REG_WIDTH * (level / 2 );
466+
467+ /* Read the corresponding gear register */
468+ val = readl (dvfsrc -> regs + reg_ofst );
469+
470+ /* Each register contains two sets of data, 16 bits per gear */
471+ val >>= 16 * (idx % 2 );
472+
473+ return val ;
474+ }
475+
476+ static int dvfsrc_get_hw_opps_v4 (struct mtk_dvfsrc * dvfsrc )
477+ {
478+ struct dvfsrc_opp * dvfsrc_opps ;
479+ struct dvfsrc_opp_desc * desc ;
480+ u32 num_opps , gear_info ;
481+ u8 num_vcore , num_dram ;
482+ u8 num_emi ;
483+ int i ;
484+
485+ num_opps = dvfsrc_get_opp_count_v4 (dvfsrc );
486+ if (num_opps == 0 ) {
487+ dev_err (dvfsrc -> dev , "No OPPs programmed in DVFSRC MCU.\n" );
488+ return - EINVAL ;
489+ }
490+
491+ /*
492+ * The first 16 bits set in the gear info table says how many OPPs
493+ * and how many vcore, dram and emi table entries are available.
494+ */
495+ gear_info = dvfsrc_readl (dvfsrc , DVFSRC_GEAR_INFO_L );
496+ if (gear_info == 0 ) {
497+ dev_err (dvfsrc -> dev , "No gear info in DVFSRC MCU.\n" );
498+ return - EINVAL ;
499+ }
500+
501+ num_vcore = FIELD_GET (DVFSRC_V4_GEAR_INFO_VCORE , gear_info ) + 1 ;
502+ num_dram = FIELD_GET (DVFSRC_V4_GEAR_INFO_DRAM , gear_info ) + 1 ;
503+ num_emi = FIELD_GET (DVFSRC_V4_GEAR_INFO_EMI , gear_info ) + 1 ;
504+ dev_info (dvfsrc -> dev ,
505+ "Discovered %u gears and %u vcore, %u dram, %u emi table entries.\n" ,
506+ num_opps , num_vcore , num_dram , num_emi );
507+
508+ /* Allocate everything now as anything else after that cannot fail */
509+ desc = devm_kzalloc (dvfsrc -> dev , sizeof (* desc ), GFP_KERNEL );
510+ if (!desc )
511+ return - ENOMEM ;
512+
513+ dvfsrc_opps = devm_kcalloc (dvfsrc -> dev , num_opps + 1 ,
514+ sizeof (* dvfsrc_opps ), GFP_KERNEL );
515+ if (!dvfsrc_opps )
516+ return - ENOMEM ;
517+
518+ /* Read the OPP table gear indices */
519+ for (i = 0 ; i <= num_opps ; i ++ ) {
520+ gear_info = dvfsrc_get_opp_gear (dvfsrc , num_opps - i );
521+ dvfsrc_opps [i ].vcore_opp = FIELD_GET (DVFSRC_V4_GEAR_INFO_VCORE , gear_info );
522+ dvfsrc_opps [i ].dram_opp = FIELD_GET (DVFSRC_V4_GEAR_INFO_DRAM , gear_info );
523+ dvfsrc_opps [i ].emi_opp = FIELD_GET (DVFSRC_V4_GEAR_INFO_EMI , gear_info );
524+ };
525+ desc -> num_opp = num_opps + 1 ;
526+ desc -> opps = dvfsrc_opps ;
527+
528+ /* Assign to main structure now that everything is done! */
529+ dvfsrc -> curr_opps = desc ;
530+
531+ return 0 ;
532+ }
533+
534+ static void dvfsrc_set_dram_level_v4 (struct mtk_dvfsrc * dvfsrc , u32 level )
535+ {
536+ u32 val = dvfsrc_readl (dvfsrc , DVFSRC_SW_REQ );
537+
538+ val &= ~DVFSRC_V4_SW_REQ_DRAM_LEVEL ;
539+ val |= FIELD_PREP (DVFSRC_V4_SW_REQ_DRAM_LEVEL , level );
540+
541+ dev_dbg (dvfsrc -> dev , "%s level=%u\n" , __func__ , level );
542+
543+ dvfsrc_writel (dvfsrc , DVFSRC_SW_REQ , val );
544+ }
545+
336546int mtk_dvfsrc_send_request (const struct device * dev , u32 cmd , u64 data )
337547{
338548 struct mtk_dvfsrc * dvfsrc = dev_get_drvdata (dev );
@@ -448,7 +658,14 @@ static int mtk_dvfsrc_probe(struct platform_device *pdev)
448658 dvfsrc -> dram_type = ares .a1 ;
449659 dev_dbg (& pdev -> dev , "DRAM Type: %d\n" , dvfsrc -> dram_type );
450660
451- dvfsrc -> curr_opps = & dvfsrc -> dvd -> opps_desc [dvfsrc -> dram_type ];
661+ /* Newer versions of the DVFSRC MCU have pre-programmed gear tables */
662+ if (dvfsrc -> dvd -> get_hw_opps ) {
663+ ret = dvfsrc -> dvd -> get_hw_opps (dvfsrc );
664+ if (ret )
665+ return ret ;
666+ } else {
667+ dvfsrc -> curr_opps = & dvfsrc -> dvd -> opps_desc [dvfsrc -> dram_type ];
668+ }
452669 platform_set_drvdata (pdev , dvfsrc );
453670
454671 ret = devm_of_platform_populate (& pdev -> dev );
@@ -576,10 +793,39 @@ static const struct dvfsrc_soc_data mt8195_data = {
576793 .bw_constraints = & dvfsrc_bw_constr_v2 ,
577794};
578795
796+ static const u8 mt8196_bw_units [] = {
797+ [DVFSRC_BW_AVG ] = 64 ,
798+ [DVFSRC_BW_PEAK ] = 64 ,
799+ [DVFSRC_BW_HRT ] = 30 ,
800+ };
801+
802+ static const struct dvfsrc_soc_data mt8196_data = {
803+ .regs = dvfsrc_mt8196_regs ,
804+ .bw_units = mt8196_bw_units ,
805+ .has_emi_ddr = true,
806+ .get_target_level = dvfsrc_get_target_level_v4 ,
807+ .get_current_level = dvfsrc_get_current_level_v4 ,
808+ .get_vcore_level = dvfsrc_get_vcore_level_v2 ,
809+ .get_vscp_level = dvfsrc_get_vscp_level_v2 ,
810+ .get_opp_count = dvfsrc_get_opp_count_v4 ,
811+ .get_hw_opps = dvfsrc_get_hw_opps_v4 ,
812+ .calc_dram_bw = dvfsrc_calc_dram_bw_v4 ,
813+ .set_dram_bw = dvfsrc_set_dram_bw_v1 ,
814+ .set_dram_peak_bw = dvfsrc_set_dram_peak_bw_v1 ,
815+ .set_dram_hrt_bw = dvfsrc_set_dram_hrt_bw_v1 ,
816+ .set_opp_level = dvfsrc_set_dram_level_v4 ,
817+ .set_vcore_level = dvfsrc_set_vcore_level_v2 ,
818+ .set_vscp_level = dvfsrc_set_vscp_level_v2 ,
819+ .wait_for_opp_level = dvfsrc_wait_for_opp_level_v4 ,
820+ .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v4 ,
821+ .bw_constraints = & dvfsrc_bw_constr_v1 ,
822+ };
823+
579824static const struct of_device_id mtk_dvfsrc_of_match [] = {
580825 { .compatible = "mediatek,mt6893-dvfsrc" , .data = & mt6893_data },
581826 { .compatible = "mediatek,mt8183-dvfsrc" , .data = & mt8183_data },
582827 { .compatible = "mediatek,mt8195-dvfsrc" , .data = & mt8195_data },
828+ { .compatible = "mediatek,mt8196-dvfsrc" , .data = & mt8196_data },
583829 { /* sentinel */ }
584830};
585831
0 commit comments