1919
2020#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)
2121#define CMDQ_NUM_CMD (t ) (t->cmd_buf_size / CMDQ_INST_SIZE)
22+ #define CMDQ_GCE_NUM_MAX (2)
2223
2324#define CMDQ_CURR_IRQ_STATUS 0x10
2425#define CMDQ_SYNC_TOKEN_UPDATE 0x68
3637#define CMDQ_THR_WAIT_TOKEN 0x30
3738#define CMDQ_THR_PRIORITY 0x40
3839
40+ #define GCE_GCTL_VALUE 0x48
41+
3942#define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200
4043#define CMDQ_THR_ENABLED 0x1
4144#define CMDQ_THR_DISABLED 0x0
@@ -73,14 +76,18 @@ struct cmdq {
7376 u32 thread_nr ;
7477 u32 irq_mask ;
7578 struct cmdq_thread * thread ;
76- struct clk * clock ;
79+ struct clk_bulk_data clocks [ CMDQ_GCE_NUM_MAX ] ;
7780 bool suspended ;
7881 u8 shift_pa ;
82+ bool control_by_sw ;
83+ u32 gce_num ;
7984};
8085
8186struct gce_plat {
8287 u32 thread_nr ;
8388 u8 shift ;
89+ bool control_by_sw ;
90+ u32 gce_num ;
8491};
8592
8693u8 cmdq_get_shift_pa (struct mbox_chan * chan )
@@ -120,11 +127,13 @@ static void cmdq_init(struct cmdq *cmdq)
120127{
121128 int i ;
122129
123- WARN_ON (clk_enable (cmdq -> clock ) < 0 );
130+ WARN_ON (clk_bulk_enable (cmdq -> gce_num , cmdq -> clocks ));
131+ if (cmdq -> control_by_sw )
132+ writel (0x7 , cmdq -> base + GCE_GCTL_VALUE );
124133 writel (CMDQ_THR_ACTIVE_SLOT_CYCLES , cmdq -> base + CMDQ_THR_SLOT_CYCLES );
125134 for (i = 0 ; i <= CMDQ_MAX_EVENT ; i ++ )
126135 writel (i , cmdq -> base + CMDQ_SYNC_TOKEN_UPDATE );
127- clk_disable (cmdq -> clock );
136+ clk_bulk_disable (cmdq -> gce_num , cmdq -> clocks );
128137}
129138
130139static int cmdq_thread_reset (struct cmdq * cmdq , struct cmdq_thread * thread )
@@ -168,7 +177,8 @@ static void cmdq_task_insert_into_thread(struct cmdq_task *task)
168177 dma_sync_single_for_cpu (dev , prev_task -> pa_base ,
169178 prev_task -> pkt -> cmd_buf_size , DMA_TO_DEVICE );
170179 prev_task_base [CMDQ_NUM_CMD (prev_task -> pkt ) - 1 ] =
171- (u64 )CMDQ_JUMP_BY_PA << 32 | task -> pa_base ;
180+ (u64 )CMDQ_JUMP_BY_PA << 32 |
181+ (task -> pa_base >> task -> cmdq -> shift_pa );
172182 dma_sync_single_for_device (dev , prev_task -> pa_base ,
173183 prev_task -> pkt -> cmd_buf_size , DMA_TO_DEVICE );
174184
@@ -262,7 +272,7 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
262272
263273 if (list_empty (& thread -> task_busy_list )) {
264274 cmdq_thread_disable (cmdq , thread );
265- clk_disable (cmdq -> clock );
275+ clk_bulk_disable (cmdq -> gce_num , cmdq -> clocks );
266276 }
267277}
268278
@@ -307,7 +317,7 @@ static int cmdq_suspend(struct device *dev)
307317 if (task_running )
308318 dev_warn (dev , "exist running task(s) in suspend\n" );
309319
310- clk_unprepare (cmdq -> clock );
320+ clk_bulk_unprepare (cmdq -> gce_num , cmdq -> clocks );
311321
312322 return 0 ;
313323}
@@ -316,7 +326,7 @@ static int cmdq_resume(struct device *dev)
316326{
317327 struct cmdq * cmdq = dev_get_drvdata (dev );
318328
319- WARN_ON (clk_prepare (cmdq -> clock ) < 0 );
329+ WARN_ON (clk_bulk_prepare (cmdq -> gce_num , cmdq -> clocks ) );
320330 cmdq -> suspended = false;
321331 return 0 ;
322332}
@@ -325,8 +335,7 @@ static int cmdq_remove(struct platform_device *pdev)
325335{
326336 struct cmdq * cmdq = platform_get_drvdata (pdev );
327337
328- clk_unprepare (cmdq -> clock );
329-
338+ clk_bulk_unprepare (cmdq -> gce_num , cmdq -> clocks );
330339 return 0 ;
331340}
332341
@@ -352,7 +361,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
352361 task -> pkt = pkt ;
353362
354363 if (list_empty (& thread -> task_busy_list )) {
355- WARN_ON (clk_enable (cmdq -> clock ) < 0 );
364+ WARN_ON (clk_bulk_enable (cmdq -> gce_num , cmdq -> clocks ));
365+
356366 /*
357367 * The thread reset will clear thread related register to 0,
358368 * including pc, end, priority, irq, suspend and enable. Thus
@@ -424,7 +434,8 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
424434 }
425435
426436 cmdq_thread_disable (cmdq , thread );
427- clk_disable (cmdq -> clock );
437+ clk_bulk_disable (cmdq -> gce_num , cmdq -> clocks );
438+
428439done :
429440 /*
430441 * The thread->task_busy_list empty means thread already disable. The
@@ -469,7 +480,7 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
469480
470481 cmdq_thread_resume (thread );
471482 cmdq_thread_disable (cmdq , thread );
472- clk_disable (cmdq -> clock );
483+ clk_bulk_disable (cmdq -> gce_num , cmdq -> clocks );
473484
474485out :
475486 spin_unlock_irqrestore (& thread -> chan -> lock , flags );
@@ -518,6 +529,10 @@ static int cmdq_probe(struct platform_device *pdev)
518529 struct cmdq * cmdq ;
519530 int err , i ;
520531 struct gce_plat * plat_data ;
532+ struct device_node * phandle = dev -> of_node ;
533+ struct device_node * node ;
534+ int alias_id = 0 ;
535+ char clk_name [4 ] = "gce" ;
521536
522537 cmdq = devm_kzalloc (dev , sizeof (* cmdq ), GFP_KERNEL );
523538 if (!cmdq )
@@ -540,6 +555,8 @@ static int cmdq_probe(struct platform_device *pdev)
540555
541556 cmdq -> thread_nr = plat_data -> thread_nr ;
542557 cmdq -> shift_pa = plat_data -> shift ;
558+ cmdq -> control_by_sw = plat_data -> control_by_sw ;
559+ cmdq -> gce_num = plat_data -> gce_num ;
543560 cmdq -> irq_mask = GENMASK (cmdq -> thread_nr - 1 , 0 );
544561 err = devm_request_irq (dev , cmdq -> irq , cmdq_irq_handler , IRQF_SHARED ,
545562 "mtk_cmdq" , cmdq );
@@ -551,10 +568,28 @@ static int cmdq_probe(struct platform_device *pdev)
551568 dev_dbg (dev , "cmdq device: addr:0x%p, va:0x%p, irq:%d\n" ,
552569 dev , cmdq -> base , cmdq -> irq );
553570
554- cmdq -> clock = devm_clk_get (dev , "gce" );
555- if (IS_ERR (cmdq -> clock )) {
556- dev_err (dev , "failed to get gce clk\n" );
557- return PTR_ERR (cmdq -> clock );
571+ if (cmdq -> gce_num > 1 ) {
572+ for_each_child_of_node (phandle -> parent , node ) {
573+ char clk_id [8 ];
574+
575+ alias_id = of_alias_get_id (node , clk_name );
576+ if (alias_id < cmdq -> gce_num ) {
577+ snprintf (clk_id , sizeof (clk_id ), "%s%d" , clk_name , alias_id );
578+ cmdq -> clocks [alias_id ].id = clk_id ;
579+ cmdq -> clocks [alias_id ].clk = of_clk_get (node , 0 );
580+ if (IS_ERR (cmdq -> clocks [alias_id ].clk )) {
581+ dev_err (dev , "failed to get gce clk: %d\n" , alias_id );
582+ return PTR_ERR (cmdq -> clocks [alias_id ].clk );
583+ }
584+ }
585+ }
586+ } else {
587+ cmdq -> clocks [alias_id ].id = clk_name ;
588+ cmdq -> clocks [alias_id ].clk = devm_clk_get (& pdev -> dev , clk_name );
589+ if (IS_ERR (cmdq -> clocks [alias_id ].clk )) {
590+ dev_err (dev , "failed to get gce clk\n" );
591+ return PTR_ERR (cmdq -> clocks [alias_id ].clk );
592+ }
558593 }
559594
560595 cmdq -> mbox .dev = dev ;
@@ -590,7 +625,8 @@ static int cmdq_probe(struct platform_device *pdev)
590625 }
591626
592627 platform_set_drvdata (pdev , cmdq );
593- WARN_ON (clk_prepare (cmdq -> clock ) < 0 );
628+
629+ WARN_ON (clk_bulk_prepare (cmdq -> gce_num , cmdq -> clocks ));
594630
595631 cmdq_init (cmdq );
596632
@@ -602,14 +638,47 @@ static const struct dev_pm_ops cmdq_pm_ops = {
602638 .resume = cmdq_resume ,
603639};
604640
605- static const struct gce_plat gce_plat_v2 = {.thread_nr = 16 };
606- static const struct gce_plat gce_plat_v3 = {.thread_nr = 24 };
607- static const struct gce_plat gce_plat_v4 = {.thread_nr = 24 , .shift = 3 };
641+ static const struct gce_plat gce_plat_v2 = {
642+ .thread_nr = 16 ,
643+ .shift = 0 ,
644+ .control_by_sw = false,
645+ .gce_num = 1
646+ };
647+
648+ static const struct gce_plat gce_plat_v3 = {
649+ .thread_nr = 24 ,
650+ .shift = 0 ,
651+ .control_by_sw = false,
652+ .gce_num = 1
653+ };
654+
655+ static const struct gce_plat gce_plat_v4 = {
656+ .thread_nr = 24 ,
657+ .shift = 3 ,
658+ .control_by_sw = false,
659+ .gce_num = 1
660+ };
661+
662+ static const struct gce_plat gce_plat_v5 = {
663+ .thread_nr = 24 ,
664+ .shift = 3 ,
665+ .control_by_sw = true,
666+ .gce_num = 2
667+ };
668+
669+ static const struct gce_plat gce_plat_v6 = {
670+ .thread_nr = 24 ,
671+ .shift = 3 ,
672+ .control_by_sw = false,
673+ .gce_num = 2
674+ };
608675
609676static const struct of_device_id cmdq_of_ids [] = {
610677 {.compatible = "mediatek,mt8173-gce" , .data = (void * )& gce_plat_v2 },
611678 {.compatible = "mediatek,mt8183-gce" , .data = (void * )& gce_plat_v3 },
612679 {.compatible = "mediatek,mt6779-gce" , .data = (void * )& gce_plat_v4 },
680+ {.compatible = "mediatek,mt8192-gce" , .data = (void * )& gce_plat_v5 },
681+ {.compatible = "mediatek,mt8195-gce" , .data = (void * )& gce_plat_v6 },
613682 {}
614683};
615684
0 commit comments