35
35
#define GPC_PGC_GPU_PUPSCR 0x264
36
36
#define GPC_PGC_GPU_PDNSCR 0x268
37
37
#define GPC_PGC_CPU_PDN 0x2a0
38
+ #define GPC_PGC_DISP_PGCR_OFFSET 0x240
39
+ #define GPC_PGC_DISP_PUPSCR_OFFSET 0x244
40
+ #define GPC_PGC_DISP_PDNSCR_OFFSET 0x248
41
+ #define GPC_PGC_DISP_SR_OFFSET 0x24c
38
42
#define GPC_M4_LPSR 0x2c
39
43
#define GPC_M4_LPSR_M4_SLEEPING_SHIFT 4
40
44
#define GPC_M4_LPSR_M4_SLEEPING_MASK 0x1
48
52
#define GPU_VPU_PUP_REQ BIT(1)
49
53
#define GPU_VPU_PDN_REQ BIT(0)
50
54
51
- #define GPC_CLK_MAX 6
55
+ #define GPC_CLK_MAX 10
52
56
53
57
struct pu_domain {
54
58
struct generic_pm_domain base ;
@@ -57,6 +61,12 @@ struct pu_domain {
57
61
int num_clks ;
58
62
};
59
63
64
+ struct disp_domain {
65
+ struct generic_pm_domain base ;
66
+ struct clk * clk [GPC_CLK_MAX ];
67
+ int num_clks ;
68
+ };
69
+
60
70
static void __iomem * gpc_base ;
61
71
static u32 gpc_mf_irqs [IMR_NUM ];
62
72
static u32 gpc_wake_irqs [IMR_NUM ];
@@ -374,6 +384,62 @@ static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
374
384
return 0 ;
375
385
}
376
386
387
+ static int imx_pm_dispmix_on (struct generic_pm_domain * genpd )
388
+ {
389
+ struct disp_domain * disp = container_of (genpd , struct disp_domain , base );
390
+ u32 val = readl_relaxed (gpc_base + GPC_CNTR );
391
+ int i ;
392
+
393
+ if ((cpu_is_imx6sl () &&
394
+ imx_get_soc_revision () >= IMX_CHIP_REVISION_1_2 ) || cpu_is_imx6sx ()) {
395
+
396
+ /* Enable reset clocks for all devices in the disp domain */
397
+ for (i = 0 ; i < disp -> num_clks ; i ++ )
398
+ clk_prepare_enable (disp -> clk [i ]);
399
+
400
+ writel_relaxed (0x0 , gpc_base + GPC_PGC_DISP_PGCR_OFFSET );
401
+ writel_relaxed (0x20 | val , gpc_base + GPC_CNTR );
402
+ while (readl_relaxed (gpc_base + GPC_CNTR ) & 0x20 )
403
+ ;
404
+
405
+ writel_relaxed (0x1 , gpc_base + GPC_PGC_DISP_SR_OFFSET );
406
+
407
+ /* Disable reset clocks for all devices in the disp domain */
408
+ for (i = 0 ; i < disp -> num_clks ; i ++ )
409
+ clk_disable_unprepare (disp -> clk [i ]);
410
+ }
411
+ return 0 ;
412
+ }
413
+
414
+ static int imx_pm_dispmix_off (struct generic_pm_domain * genpd )
415
+ {
416
+ struct disp_domain * disp = container_of (genpd , struct disp_domain , base );
417
+ u32 val = readl_relaxed (gpc_base + GPC_CNTR );
418
+ int i ;
419
+
420
+ if ((cpu_is_imx6sl () &&
421
+ imx_get_soc_revision () >= IMX_CHIP_REVISION_1_2 ) || cpu_is_imx6sx ()) {
422
+
423
+ /* Enable reset clocks for all devices in the disp domain */
424
+ for (i = 0 ; i < disp -> num_clks ; i ++ )
425
+ clk_prepare_enable (disp -> clk [i ]);
426
+
427
+ writel_relaxed (0xFFFFFFFF ,
428
+ gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET );
429
+ writel_relaxed (0xFFFFFFFF ,
430
+ gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET );
431
+ writel_relaxed (0x1 , gpc_base + GPC_PGC_DISP_PGCR_OFFSET );
432
+ writel_relaxed (0x10 | val , gpc_base + GPC_CNTR );
433
+ while (readl_relaxed (gpc_base + GPC_CNTR ) & 0x10 )
434
+ ;
435
+
436
+ /* Disable reset clocks for all devices in the disp domain */
437
+ for (i = 0 ; i < disp -> num_clks ; i ++ )
438
+ clk_disable_unprepare (disp -> clk [i ]);
439
+ }
440
+ return 0 ;
441
+ }
442
+
377
443
static struct generic_pm_domain imx6q_arm_domain = {
378
444
.name = "ARM" ,
379
445
};
@@ -388,14 +454,18 @@ static struct pu_domain imx6q_pu_domain = {
388
454
},
389
455
};
390
456
391
- static struct generic_pm_domain imx6sl_display_domain = {
392
- .name = "DISPLAY" ,
457
+ static struct disp_domain imx6s_display_domain = {
458
+ .base = {
459
+ .name = "DISPLAY" ,
460
+ .power_off = imx_pm_dispmix_off ,
461
+ .power_on = imx_pm_dispmix_on ,
462
+ },
393
463
};
394
464
395
465
static struct generic_pm_domain * imx_gpc_domains [] = {
396
466
& imx6q_arm_domain ,
397
467
& imx6q_pu_domain .base ,
398
- & imx6sl_display_domain ,
468
+ & imx6s_display_domain . base ,
399
469
};
400
470
401
471
static struct genpd_onecell_data imx_gpc_onecell_data = {
@@ -407,35 +477,54 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
407
477
{
408
478
struct clk * clk ;
409
479
bool is_off ;
410
- int i ;
480
+ int pu_clks , disp_clks ;
481
+ int i = 0 , k = 0 ;
411
482
412
483
imx6q_pu_domain .base .of_node = dev -> of_node ;
413
484
imx6q_pu_domain .reg = pu_reg ;
414
485
415
- for (i = 0 ; ; i ++ ) {
486
+ imx6s_display_domain .base .of_node = dev -> of_node ;
487
+
488
+ if ((cpu_is_imx6sl () &&
489
+ imx_get_soc_revision () >= IMX_CHIP_REVISION_1_2 )) {
490
+ pu_clks = 2 ;
491
+ disp_clks = 6 ;
492
+ } else if (cpu_is_imx6sx ()) {
493
+ pu_clks = 1 ;
494
+ disp_clks = 7 ;
495
+ } else {
496
+ pu_clks = GPC_CLK_MAX ;
497
+ disp_clks = 0 ;
498
+ }
499
+
500
+ /* Get pu domain clks */
501
+ for (i = 0 ; i < pu_clks ; i ++ ) {
416
502
clk = of_clk_get (dev -> of_node , i );
417
503
if (IS_ERR (clk ))
418
504
break ;
419
- if (i >= GPC_CLK_MAX ) {
420
- dev_err (dev , "more than %d clocks\n" , GPC_CLK_MAX );
421
- goto clk_err ;
422
- }
423
505
imx6q_pu_domain .clk [i ] = clk ;
424
506
}
425
507
imx6q_pu_domain .num_clks = i ;
426
508
509
+ /* Get disp domain clks */
510
+ for (k = 0 , i = pu_clks ; i < pu_clks + disp_clks ; i ++ , k ++ ) {
511
+ clk = of_clk_get (dev -> of_node , i );
512
+ if (IS_ERR (clk ))
513
+ break ;
514
+ imx6s_display_domain .clk [k ] = clk ;
515
+ }
516
+ imx6s_display_domain .num_clks = k ;
517
+
427
518
is_off = IS_ENABLED (CONFIG_PM_RUNTIME );
428
519
if (is_off )
429
520
imx6q_pm_pu_power_off (& imx6q_pu_domain .base );
430
521
431
522
pm_genpd_init (& imx6q_pu_domain .base , NULL , is_off );
523
+ pm_genpd_init (& imx6s_display_domain .base , NULL , is_off );
524
+
432
525
return of_genpd_add_provider (dev -> of_node , of_genpd_xlate_onecell ,
433
526
& imx_gpc_onecell_data );
434
527
435
- clk_err :
436
- while (i -- )
437
- clk_put (imx6q_pu_domain .clk [i ]);
438
- return - EINVAL ;
439
528
}
440
529
441
530
#else
0 commit comments