3131#define MTK_POLL_DELAY_US 10
3232#define MTK_POLL_TIMEOUT USEC_PER_SEC
3333
34+ #define MTK_HWV_POLL_DELAY_US 5
35+ #define MTK_HWV_POLL_TIMEOUT (300 * USEC_PER_MSEC)
36+
37+ #define MTK_HWV_PREPARE_DELAY_US 1
38+ #define MTK_HWV_PREPARE_TIMEOUT (3 * USEC_PER_MSEC)
39+
3440#define PWR_RST_B_BIT BIT(0)
3541#define PWR_ISO_BIT BIT(1)
3642#define PWR_ON_BIT BIT(2)
4854struct scpsys_domain {
4955 struct generic_pm_domain genpd ;
5056 const struct scpsys_domain_data * data ;
57+ const struct scpsys_hwv_domain_data * hwv_data ;
5158 struct scpsys * scpsys ;
5259 int num_clks ;
5360 struct clk_bulk_data * clks ;
@@ -83,6 +90,32 @@ static bool scpsys_domain_is_on(struct scpsys_domain *pd)
8390 return status && status2 ;
8491}
8592
93+ static bool scpsys_hwv_domain_is_disable_done (struct scpsys_domain * pd )
94+ {
95+ const struct scpsys_hwv_domain_data * hwv = pd -> hwv_data ;
96+ u32 regs [2 ] = { hwv -> done , hwv -> clr_sta };
97+ u32 val [2 ];
98+ u32 mask = BIT (hwv -> setclr_bit );
99+
100+ regmap_multi_reg_read (pd -> scpsys -> base , regs , val , 2 );
101+
102+ /* Disable is done when the bit is set in DONE, cleared in CLR_STA */
103+ return (val [0 ] & mask ) && !(val [1 ] & mask );
104+ }
105+
106+ static bool scpsys_hwv_domain_is_enable_done (struct scpsys_domain * pd )
107+ {
108+ const struct scpsys_hwv_domain_data * hwv = pd -> hwv_data ;
109+ u32 regs [3 ] = { hwv -> done , hwv -> en , hwv -> set_sta };
110+ u32 val [3 ];
111+ u32 mask = BIT (hwv -> setclr_bit );
112+
113+ regmap_multi_reg_read (pd -> scpsys -> base , regs , val , 3 );
114+
115+ /* Enable is done when the bit is set in DONE and EN, cleared in SET_STA */
116+ return (val [0 ] & mask ) && (val [1 ] & mask ) && !(val [2 ] & mask );
117+ }
118+
86119static int scpsys_sram_enable (struct scpsys_domain * pd )
87120{
88121 u32 expected_ack , pdn_ack = pd -> data -> sram_pdn_ack_bits ;
@@ -250,6 +283,137 @@ static int scpsys_regulator_disable(struct regulator *supply)
250283 return supply ? regulator_disable (supply ) : 0 ;
251284}
252285
286+ static int scpsys_hwv_power_on (struct generic_pm_domain * genpd )
287+ {
288+ struct scpsys_domain * pd = container_of (genpd , struct scpsys_domain , genpd );
289+ const struct scpsys_hwv_domain_data * hwv = pd -> hwv_data ;
290+ struct scpsys * scpsys = pd -> scpsys ;
291+ u32 val ;
292+ int ret ;
293+
294+ ret = scpsys_regulator_enable (pd -> supply );
295+ if (ret )
296+ return ret ;
297+
298+ ret = clk_bulk_prepare_enable (pd -> num_clks , pd -> clks );
299+ if (ret )
300+ goto err_reg ;
301+
302+ /* For HWV the subsys clocks refer to the HWV low power subsystem */
303+ ret = clk_bulk_prepare_enable (pd -> num_subsys_clks , pd -> subsys_clks );
304+ if (ret )
305+ goto err_disable_clks ;
306+
307+ /* Make sure the HW Voter is idle and able to accept commands */
308+ ret = regmap_read_poll_timeout_atomic (scpsys -> base , hwv -> done , val ,
309+ val & BIT (hwv -> setclr_bit ),
310+ MTK_HWV_POLL_DELAY_US ,
311+ MTK_HWV_POLL_TIMEOUT );
312+ if (ret ) {
313+ dev_err (scpsys -> dev , "Failed to power on: HW Voter busy.\n" );
314+ goto err_disable_subsys_clks ;
315+ }
316+
317+ /*
318+ * Instruct the HWV to power on the MTCMOS (power domain): after that,
319+ * the same bit will be unset immediately by the hardware.
320+ */
321+ regmap_write (scpsys -> base , hwv -> set , BIT (hwv -> setclr_bit ));
322+
323+ /*
324+ * Wait until the HWV sets the bit again, signalling that its internal
325+ * state machine was started and it now processing the vote command.
326+ */
327+ ret = regmap_read_poll_timeout_atomic (scpsys -> base , hwv -> set , val ,
328+ val & BIT (hwv -> setclr_bit ),
329+ MTK_HWV_PREPARE_DELAY_US ,
330+ MTK_HWV_PREPARE_TIMEOUT );
331+ if (ret ) {
332+ dev_err (scpsys -> dev , "Failed to power on: HW Voter not starting.\n" );
333+ goto err_disable_subsys_clks ;
334+ }
335+
336+ /* Wait for ACK, signalling that the MTCMOS was enabled */
337+ ret = readx_poll_timeout_atomic (scpsys_hwv_domain_is_enable_done , pd , val , val ,
338+ MTK_HWV_POLL_DELAY_US , MTK_HWV_POLL_TIMEOUT );
339+ if (ret ) {
340+ dev_err (scpsys -> dev , "Failed to power on: HW Voter ACK timeout.\n" );
341+ goto err_disable_subsys_clks ;
342+ }
343+
344+ /* It's done! Disable the HWV low power subsystem clocks */
345+ clk_bulk_disable_unprepare (pd -> num_subsys_clks , pd -> subsys_clks );
346+
347+ return 0 ;
348+
349+ err_disable_subsys_clks :
350+ clk_bulk_disable_unprepare (pd -> num_subsys_clks , pd -> subsys_clks );
351+ err_disable_clks :
352+ clk_bulk_disable_unprepare (pd -> num_clks , pd -> clks );
353+ err_reg :
354+ scpsys_regulator_disable (pd -> supply );
355+ return ret ;
356+ };
357+
358+ static int scpsys_hwv_power_off (struct generic_pm_domain * genpd )
359+ {
360+ struct scpsys_domain * pd = container_of (genpd , struct scpsys_domain , genpd );
361+ const struct scpsys_hwv_domain_data * hwv = pd -> hwv_data ;
362+ struct scpsys * scpsys = pd -> scpsys ;
363+ u32 val ;
364+ int ret ;
365+
366+ ret = clk_bulk_prepare_enable (pd -> num_subsys_clks , pd -> subsys_clks );
367+ if (ret )
368+ return ret ;
369+
370+ /* Make sure the HW Voter is idle and able to accept commands */
371+ ret = regmap_read_poll_timeout_atomic (scpsys -> base , hwv -> done , val ,
372+ val & BIT (hwv -> setclr_bit ),
373+ MTK_HWV_POLL_DELAY_US ,
374+ MTK_HWV_POLL_TIMEOUT );
375+ if (ret )
376+ goto err_disable_subsys_clks ;
377+
378+
379+ /*
380+ * Instruct the HWV to power off the MTCMOS (power domain): differently
381+ * from poweron, the bit will be kept set.
382+ */
383+ regmap_write (scpsys -> base , hwv -> clr , BIT (hwv -> setclr_bit ));
384+
385+ /*
386+ * Wait until the HWV clears the bit, signalling that its internal
387+ * state machine was started and it now processing the clear command.
388+ */
389+ ret = regmap_read_poll_timeout_atomic (scpsys -> base , hwv -> clr , val ,
390+ !(val & BIT (hwv -> setclr_bit )),
391+ MTK_HWV_PREPARE_DELAY_US ,
392+ MTK_HWV_PREPARE_TIMEOUT );
393+ if (ret )
394+ goto err_disable_subsys_clks ;
395+
396+ /* Poweroff needs 100us for the HW to stabilize */
397+ udelay (100 );
398+
399+ /* Wait for ACK, signalling that the MTCMOS was disabled */
400+ ret = readx_poll_timeout_atomic (scpsys_hwv_domain_is_disable_done , pd , val , val ,
401+ MTK_HWV_POLL_DELAY_US , MTK_HWV_POLL_TIMEOUT );
402+ if (ret )
403+ goto err_disable_subsys_clks ;
404+
405+ clk_bulk_disable_unprepare (pd -> num_subsys_clks , pd -> subsys_clks );
406+ clk_bulk_disable_unprepare (pd -> num_clks , pd -> clks );
407+
408+ scpsys_regulator_disable (pd -> supply );
409+
410+ return 0 ;
411+
412+ err_disable_subsys_clks :
413+ clk_bulk_disable_unprepare (pd -> num_subsys_clks , pd -> subsys_clks );
414+ return ret ;
415+ };
416+
253417static int scpsys_ctl_pwrseq_on (struct scpsys_domain * pd )
254418{
255419 struct scpsys * scpsys = pd -> scpsys ;
@@ -514,6 +678,7 @@ static struct
514678generic_pm_domain * scpsys_add_one_domain (struct scpsys * scpsys , struct device_node * node )
515679{
516680 const struct scpsys_domain_data * domain_data ;
681+ const struct scpsys_hwv_domain_data * hwv_domain_data ;
517682 struct scpsys_domain * pd ;
518683 struct property * prop ;
519684 const char * clk_name ;
@@ -529,14 +694,33 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
529694 return ERR_PTR (- EINVAL );
530695 }
531696
532- if (id >= scpsys -> soc_data -> num_domains ) {
533- dev_err (scpsys -> dev , "%pOF: invalid domain id %d\n" , node , id );
534- return ERR_PTR (- EINVAL );
535- }
697+ switch (scpsys -> soc_data -> type ) {
698+ case SCPSYS_MTCMOS_TYPE_DIRECT_CTL :
699+ if (id >= scpsys -> soc_data -> num_domains ) {
700+ dev_err (scpsys -> dev , "%pOF: invalid domain id %d\n" , node , id );
701+ return ERR_PTR (- EINVAL );
702+ }
703+
704+ domain_data = & scpsys -> soc_data -> domains_data [id ];
705+ hwv_domain_data = NULL ;
536706
537- domain_data = & scpsys -> soc_data -> domains_data [id ];
538- if (domain_data -> sta_mask == 0 ) {
539- dev_err (scpsys -> dev , "%pOF: undefined domain id %d\n" , node , id );
707+ if (domain_data -> sta_mask == 0 ) {
708+ dev_err (scpsys -> dev , "%pOF: undefined domain id %d\n" , node , id );
709+ return ERR_PTR (- EINVAL );
710+ }
711+
712+ break ;
713+ case SCPSYS_MTCMOS_TYPE_HW_VOTER :
714+ if (id >= scpsys -> soc_data -> num_hwv_domains ) {
715+ dev_err (scpsys -> dev , "%pOF: invalid HWV domain id %d\n" , node , id );
716+ return ERR_PTR (- EINVAL );
717+ }
718+
719+ domain_data = NULL ;
720+ hwv_domain_data = & scpsys -> soc_data -> hwv_domains_data [id ];
721+
722+ break ;
723+ default :
540724 return ERR_PTR (- EINVAL );
541725 }
542726
@@ -545,6 +729,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
545729 return ERR_PTR (- ENOMEM );
546730
547731 pd -> data = domain_data ;
732+ pd -> hwv_data = hwv_domain_data ;
548733 pd -> scpsys = scpsys ;
549734
550735 if (MTK_SCPD_CAPS (pd , MTK_SCPD_DOMAIN_SUPPLY )) {
@@ -604,6 +789,31 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
604789 pd -> subsys_clks [i ].clk = clk ;
605790 }
606791
792+ if (scpsys -> domains [id ]) {
793+ ret = - EINVAL ;
794+ dev_err (scpsys -> dev ,
795+ "power domain with id %d already exists, check your device-tree\n" , id );
796+ goto err_put_subsys_clocks ;
797+ }
798+
799+ if (pd -> data && pd -> data -> name )
800+ pd -> genpd .name = pd -> data -> name ;
801+ else if (pd -> hwv_data && pd -> hwv_data -> name )
802+ pd -> genpd .name = pd -> hwv_data -> name ;
803+ else
804+ pd -> genpd .name = node -> name ;
805+
806+ if (scpsys -> soc_data -> type == SCPSYS_MTCMOS_TYPE_DIRECT_CTL ) {
807+ pd -> genpd .power_off = scpsys_power_off ;
808+ pd -> genpd .power_on = scpsys_power_on ;
809+ } else {
810+ pd -> genpd .power_off = scpsys_hwv_power_off ;
811+ pd -> genpd .power_on = scpsys_hwv_power_on ;
812+
813+ /* HW-Voter code can be invoked in atomic context */
814+ pd -> genpd .flags |= GENPD_FLAG_IRQ_SAFE ;
815+ }
816+
607817 /*
608818 * Initially turn on all domains to make the domains usable
609819 * with !CONFIG_PM and to get the hardware in sync with the
@@ -615,7 +825,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
615825 dev_warn (scpsys -> dev ,
616826 "%pOF: A default off power domain has been ON\n" , node );
617827 } else {
618- ret = scpsys_power_on (& pd -> genpd );
828+ ret = pd -> genpd . power_on (& pd -> genpd );
619829 if (ret < 0 ) {
620830 dev_err (scpsys -> dev , "%pOF: failed to power on domain: %d\n" , node , ret );
621831 goto err_put_subsys_clocks ;
@@ -625,21 +835,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
625835 pd -> genpd .flags |= GENPD_FLAG_ALWAYS_ON ;
626836 }
627837
628- if (scpsys -> domains [id ]) {
629- ret = - EINVAL ;
630- dev_err (scpsys -> dev ,
631- "power domain with id %d already exists, check your device-tree\n" , id );
632- goto err_put_subsys_clocks ;
633- }
634-
635- if (!pd -> data -> name )
636- pd -> genpd .name = node -> name ;
637- else
638- pd -> genpd .name = pd -> data -> name ;
639-
640- pd -> genpd .power_off = scpsys_power_off ;
641- pd -> genpd .power_on = scpsys_power_on ;
642-
643838 if (MTK_SCPD_CAPS (pd , MTK_SCPD_ACTIVE_WAKEUP ))
644839 pd -> genpd .flags |= GENPD_FLAG_ACTIVE_WAKEUP ;
645840
@@ -934,15 +1129,17 @@ static int scpsys_probe(struct platform_device *pdev)
9341129 struct device_node * node ;
9351130 struct device * parent ;
9361131 struct scpsys * scpsys ;
937- int ret ;
1132+ int num_domains , ret ;
9381133
9391134 soc = of_device_get_match_data (& pdev -> dev );
9401135 if (!soc ) {
9411136 dev_err (& pdev -> dev , "no power controller data\n" );
9421137 return - EINVAL ;
9431138 }
9441139
945- scpsys = devm_kzalloc (dev , struct_size (scpsys , domains , soc -> num_domains ), GFP_KERNEL );
1140+ num_domains = soc -> num_domains + soc -> num_hwv_domains ;
1141+
1142+ scpsys = devm_kzalloc (dev , struct_size (scpsys , domains , num_domains ), GFP_KERNEL );
9461143 if (!scpsys )
9471144 return - ENOMEM ;
9481145
0 commit comments