Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'omap-for-v5.10/prm-genpd' into omap-for-v5.10/ti-sysc-drop-pdata

+298 -131
+2
Documentation/devicetree/bindings/arm/omap/prm-inst.txt
··· 18 18 (base address and length) 19 19 20 20 Optional properties: 21 + - #power-domain-cells: Should be 0 if the instance is a power domain provider. 21 22 - #reset-cells: Should be 1 if the PRM instance in question supports resets. 22 23 23 24 Example: ··· 26 25 prm_dsp2: prm@1b00 { 27 26 compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst"; 28 27 reg = <0x1b00 0x40>; 28 + #power-domain-cells = <0>; 29 29 #reset-cells = <1>; 30 30 };
+2
arch/arm/boot/dts/am33xx.dtsi
··· 578 578 <SYSC_IDLE_SMART>; 579 579 clocks = <&gfx_l3_clkctrl AM3_GFX_L3_GFX_CLKCTRL 0>; 580 580 clock-names = "fck"; 581 + power-domains = <&prm_gfx>; 581 582 resets = <&prm_gfx 0>; 582 583 reset-names = "rstctrl"; 583 584 #address-cells = <1>; ··· 618 617 prm_gfx: prm@1100 { 619 618 compatible = "ti,am3-prm-inst", "ti,omap-prm-inst"; 620 619 reg = <0x1100 0x100>; 620 + #power-domain-cells = <0>; 621 621 #reset-cells = <1>; 622 622 }; 623 623 };
+2
arch/arm/boot/dts/am4372.dtsi
··· 517 517 <SYSC_IDLE_SMART>; 518 518 clocks = <&gfx_l3_clkctrl AM4_GFX_L3_GFX_CLKCTRL 0>; 519 519 clock-names = "fck"; 520 + power-domains = <&prm_gfx>; 520 521 resets = <&prm_gfx 0>; 521 522 reset-names = "rstctrl"; 522 523 #address-cells = <1>; ··· 534 533 prm_gfx: prm@400 { 535 534 compatible = "ti,am4-prm-inst", "ti,omap-prm-inst"; 536 535 reg = <0x400 0x100>; 536 + #power-domain-cells = <0>; 537 537 #reset-cells = <1>; 538 538 }; 539 539
+4 -2
arch/arm/boot/dts/omap4-l4-abe.dtsi
··· 1 1 &l4_abe { /* 0x40100000 */ 2 - compatible = "ti,omap4-l4-abe", "simple-bus"; 2 + compatible = "ti,omap4-l4-abe", "simple-pm-bus"; 3 3 reg = <0x40100000 0x400>, 4 4 <0x40100400 0x400>; 5 5 reg-names = "la", "ap"; 6 + power-domains = <&prm_abe>; 7 + /* OMAP4_L4_ABE_CLKCTRL is read-only */ 6 8 #address-cells = <1>; 7 9 #size-cells = <1>; 8 10 ranges = <0x00000000 0x40100000 0x100000>, /* segment 0 */ 9 11 <0x49000000 0x49000000 0x100000>; 10 12 segment@0 { /* 0x40100000 */ 11 - compatible = "simple-bus"; 13 + compatible = "simple-pm-bus"; 12 14 #address-cells = <1>; 13 15 #size-cells = <1>; 14 16 ranges =
+6
arch/arm/boot/dts/omap4.dtsi
··· 658 658 #reset-cells = <1>; 659 659 }; 660 660 661 + prm_abe: prm@500 { 662 + compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst"; 663 + reg = <0x500 0x100>; 664 + #power-domain-cells = <0>; 665 + }; 666 + 661 667 prm_core: prm@700 { 662 668 compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst"; 663 669 reg = <0x700 0x100>;
+4 -2
arch/arm/boot/dts/omap5-l4-abe.dtsi
··· 1 1 &l4_abe { /* 0x40100000 */ 2 - compatible = "ti,omap5-l4-abe", "simple-bus"; 2 + compatible = "ti,omap5-l4-abe", "simple-pm-bus"; 3 3 reg = <0x40100000 0x400>, 4 4 <0x40100400 0x400>; 5 5 reg-names = "la", "ap"; 6 + power-domains = <&prm_abe>; 7 + /* OMAP5_L4_ABE_CLKCTRL is read-only */ 6 8 #address-cells = <1>; 7 9 #size-cells = <1>; 8 10 ranges = <0x00000000 0x40100000 0x100000>, /* segment 0 */ 9 11 <0x49000000 0x49000000 0x100000>; 10 12 segment@0 { /* 0x40100000 */ 11 - compatible = "simple-bus"; 13 + compatible = "simple-pm-bus"; 12 14 #address-cells = <1>; 13 15 #size-cells = <1>; 14 16 ranges =
+6
arch/arm/boot/dts/omap5.dtsi
··· 674 674 #reset-cells = <1>; 675 675 }; 676 676 677 + prm_abe: prm@500 { 678 + compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst"; 679 + reg = <0x500 0x100>; 680 + #power-domain-cells = <0>; 681 + }; 682 + 677 683 prm_core: prm@700 { 678 684 compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst"; 679 685 reg = <0x700 0x100>;
+1
arch/arm/mach-omap2/Kconfig
··· 7 7 depends on ARCH_MULTI_V6 8 8 select ARCH_OMAP2PLUS 9 9 select CPU_V6 10 + select PM_GENERIC_DOMAINS if PM 10 11 select SOC_HAS_OMAP2_SDRC 11 12 12 13 config ARCH_OMAP3
-16
arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
··· 74 74 .user = OCP_USER_MPU | OCP_USER_SDMA, 75 75 }; 76 76 77 - /* gfx -> l3 main */ 78 - struct omap_hwmod_ocp_if am33xx_gfx__l3_main = { 79 - .master = &am33xx_gfx_hwmod, 80 - .slave = &am33xx_l3_main_hwmod, 81 - .clk = "dpll_core_m4_ck", 82 - .user = OCP_USER_MPU | OCP_USER_SDMA, 83 - }; 84 - 85 - /* l3 main -> gfx */ 86 - struct omap_hwmod_ocp_if am33xx_l3_main__gfx = { 87 - .master = &am33xx_l3_main_hwmod, 88 - .slave = &am33xx_gfx_hwmod, 89 - .clk = "dpll_core_m4_ck", 90 - .user = OCP_USER_MPU | OCP_USER_SDMA, 91 - }; 92 - 93 77 /* l3s cfg -> gpmc */ 94 78 struct omap_hwmod_ocp_if am33xx_l3_s__gpmc = { 95 79 .master = &am33xx_l3_s_hwmod,
-40
arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
··· 132 132 .name = "wkup_m3", 133 133 }; 134 134 135 - /* gfx */ 136 - /* Pseudo hwmod for reset control purpose only */ 137 - static struct omap_hwmod_class am33xx_gfx_hwmod_class = { 138 - .name = "gfx", 139 - }; 140 - 141 - static struct omap_hwmod_rst_info am33xx_gfx_resets[] = { 142 - { .name = "gfx", .rst_shift = 0, .st_shift = 0}, 143 - }; 144 - 145 - struct omap_hwmod am33xx_gfx_hwmod = { 146 - .name = "gfx", 147 - .class = &am33xx_gfx_hwmod_class, 148 - .clkdm_name = "gfx_l3_clkdm", 149 - .main_clk = "gfx_fck_div_ck", 150 - .prcm = { 151 - .omap4 = { 152 - .modulemode = MODULEMODE_SWCTRL, 153 - }, 154 - }, 155 - .rst_lines = am33xx_gfx_resets, 156 - .rst_lines_cnt = ARRAY_SIZE(am33xx_gfx_resets), 157 - }; 158 - 159 135 /* 160 136 * 'prcm' class 161 137 * power and reset manager (whole prcm infrastructure) ··· 259 283 CLKCTRL(am33xx_l4_ls_hwmod, AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET); 260 284 CLKCTRL(am33xx_l4_wkup_hwmod, AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET); 261 285 CLKCTRL(am33xx_l3_main_hwmod, AM33XX_CM_PER_L3_CLKCTRL_OFFSET); 262 - CLKCTRL(am33xx_gfx_hwmod, AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET); 263 286 CLKCTRL(am33xx_mpu_hwmod , AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET); 264 287 CLKCTRL(am33xx_l3_instr_hwmod , AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET); 265 288 CLKCTRL(am33xx_ocmcram_hwmod , AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET); 266 289 } 267 290 268 - static void omap_hwmod_am33xx_rst(void) 269 - { 270 - RSTCTRL(am33xx_gfx_hwmod, AM33XX_RM_GFX_RSTCTRL_OFFSET); 271 - RSTST(am33xx_gfx_hwmod, AM33XX_RM_GFX_RSTST_OFFSET); 272 - } 273 - 274 291 void omap_hwmod_am33xx_reg(void) 275 292 { 276 293 omap_hwmod_am33xx_clkctrl(); 277 - omap_hwmod_am33xx_rst(); 278 294 } 279 295 280 296 static void omap_hwmod_am43xx_clkctrl(void) ··· 279 311 CLKCTRL(am33xx_l4_ls_hwmod, AM43XX_CM_PER_L4LS_CLKCTRL_OFFSET); 280 312 CLKCTRL(am33xx_l4_wkup_hwmod, AM43XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET); 281 313 CLKCTRL(am33xx_l3_main_hwmod, AM43XX_CM_PER_L3_CLKCTRL_OFFSET); 282 - CLKCTRL(am33xx_gfx_hwmod, AM43XX_CM_GFX_GFX_CLKCTRL_OFFSET); 283 314 CLKCTRL(am33xx_mpu_hwmod , AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET); 284 315 CLKCTRL(am33xx_l3_instr_hwmod , AM43XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET); 285 316 CLKCTRL(am33xx_ocmcram_hwmod , AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET); 286 317 } 287 318 288 - static void omap_hwmod_am43xx_rst(void) 289 - { 290 - RSTCTRL(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTCTRL_OFFSET); 291 - RSTST(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTST_OFFSET); 292 - } 293 - 294 319 void omap_hwmod_am43xx_reg(void) 295 320 { 296 321 omap_hwmod_am43xx_clkctrl(); 297 - omap_hwmod_am43xx_rst(); 298 322 }
-2
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
··· 274 274 &am33xx_l3_main__l4_hs, 275 275 &am33xx_l3_main__l3_s, 276 276 &am33xx_l3_main__l3_instr, 277 - &am33xx_l3_main__gfx, 278 277 &am33xx_l3_s__l3_main, 279 278 &am33xx_wkup_m3__l4_wkup, 280 - &am33xx_gfx__l3_main, 281 279 &am33xx_l3_main__debugss, 282 280 &am33xx_l4_wkup__wkup_m3, 283 281 &am33xx_l4_wkup__control,
-2
arch/arm/mach-omap2/omap_hwmod_43xx_data.c
··· 143 143 &am43xx_l3_main__l4_hs, 144 144 &am33xx_l3_main__l3_s, 145 145 &am33xx_l3_main__l3_instr, 146 - &am33xx_l3_main__gfx, 147 146 &am33xx_l3_s__l3_main, 148 147 &am43xx_l3_main__emif, 149 148 &am43xx_wkup_m3__l4_wkup, 150 - &am33xx_gfx__l3_main, 151 149 &am43xx_l4_wkup__wkup_m3, 152 150 &am43xx_l4_wkup__control, 153 151 &am43xx_l4_wkup__smartreflex0,
-33
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
··· 124 124 .name = "l4", 125 125 }; 126 126 127 - /* l4_abe */ 128 - static struct omap_hwmod omap44xx_l4_abe_hwmod = { 129 - .name = "l4_abe", 130 - .class = &omap44xx_l4_hwmod_class, 131 - .clkdm_name = "abe_clkdm", 132 - .prcm = { 133 - .omap4 = { 134 - .clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET, 135 - .context_offs = OMAP4_RM_ABE_AESS_CONTEXT_OFFSET, 136 - .lostcontext_mask = OMAP4430_LOSTMEM_AESSMEM_MASK, 137 - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, 138 - }, 139 - }, 140 - }; 141 - 142 127 /* l4_cfg */ 143 128 static struct omap_hwmod omap44xx_l4_cfg_hwmod = { 144 129 .name = "l4_cfg", ··· 756 771 .user = OCP_USER_MPU | OCP_USER_SDMA, 757 772 }; 758 773 759 - /* l3_main_1 -> l4_abe */ 760 - static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = { 761 - .master = &omap44xx_l3_main_1_hwmod, 762 - .slave = &omap44xx_l4_abe_hwmod, 763 - .clk = "l3_div_ck", 764 - .user = OCP_USER_MPU | OCP_USER_SDMA, 765 - }; 766 - 767 - /* mpu -> l4_abe */ 768 - static struct omap_hwmod_ocp_if omap44xx_mpu__l4_abe = { 769 - .master = &omap44xx_mpu_hwmod, 770 - .slave = &omap44xx_l4_abe_hwmod, 771 - .clk = "ocp_abe_iclk", 772 - .user = OCP_USER_MPU | OCP_USER_SDMA, 773 - }; 774 - 775 774 /* l3_main_1 -> l4_cfg */ 776 775 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = { 777 776 .master = &omap44xx_l3_main_1_hwmod, ··· 957 988 &omap44xx_l3_main_1__l3_main_3, 958 989 &omap44xx_l3_main_2__l3_main_3, 959 990 &omap44xx_l4_cfg__l3_main_3, 960 - &omap44xx_l3_main_1__l4_abe, 961 - &omap44xx_mpu__l4_abe, 962 991 &omap44xx_l3_main_1__l4_cfg, 963 992 &omap44xx_l3_main_2__l4_per, 964 993 &omap44xx_l4_cfg__l4_wkup,
-31
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
··· 121 121 .name = "l4", 122 122 }; 123 123 124 - /* l4_abe */ 125 - static struct omap_hwmod omap54xx_l4_abe_hwmod = { 126 - .name = "l4_abe", 127 - .class = &omap54xx_l4_hwmod_class, 128 - .clkdm_name = "abe_clkdm", 129 - .prcm = { 130 - .omap4 = { 131 - .clkctrl_offs = OMAP54XX_CM_ABE_L4_ABE_CLKCTRL_OFFSET, 132 - .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, 133 - }, 134 - }, 135 - }; 136 - 137 124 /* l4_cfg */ 138 125 static struct omap_hwmod omap54xx_l4_cfg_hwmod = { 139 126 .name = "l4_cfg", ··· 382 395 .user = OCP_USER_MPU | OCP_USER_SDMA, 383 396 }; 384 397 385 - /* l3_main_1 -> l4_abe */ 386 - static struct omap_hwmod_ocp_if omap54xx_l3_main_1__l4_abe = { 387 - .master = &omap54xx_l3_main_1_hwmod, 388 - .slave = &omap54xx_l4_abe_hwmod, 389 - .clk = "abe_iclk", 390 - .user = OCP_USER_MPU | OCP_USER_SDMA, 391 - }; 392 - 393 - /* mpu -> l4_abe */ 394 - static struct omap_hwmod_ocp_if omap54xx_mpu__l4_abe = { 395 - .master = &omap54xx_mpu_hwmod, 396 - .slave = &omap54xx_l4_abe_hwmod, 397 - .clk = "abe_iclk", 398 - .user = OCP_USER_MPU | OCP_USER_SDMA, 399 - }; 400 - 401 398 /* l3_main_1 -> l4_cfg */ 402 399 static struct omap_hwmod_ocp_if omap54xx_l3_main_1__l4_cfg = { 403 400 .master = &omap54xx_l3_main_1_hwmod, ··· 449 478 &omap54xx_l3_main_1__l3_main_3, 450 479 &omap54xx_l3_main_2__l3_main_3, 451 480 &omap54xx_l4_cfg__l3_main_3, 452 - &omap54xx_l3_main_1__l4_abe, 453 - &omap54xx_mpu__l4_abe, 454 481 &omap54xx_l3_main_1__l4_cfg, 455 482 &omap54xx_l3_main_2__l4_per, 456 483 &omap54xx_l3_main_1__l4_wkup,
+271 -3
drivers/soc/ti/omap_prm.c
··· 10 10 #include <linux/device.h> 11 11 #include <linux/io.h> 12 12 #include <linux/iopoll.h> 13 + #include <linux/module.h> 13 14 #include <linux/of.h> 14 15 #include <linux/of_device.h> 15 16 #include <linux/platform_device.h> 17 + #include <linux/pm_domain.h> 16 18 #include <linux/reset-controller.h> 17 19 #include <linux/delay.h> 18 20 19 21 #include <linux/platform_data/ti-prm.h> 22 + 23 + enum omap_prm_domain_mode { 24 + OMAP_PRMD_OFF, 25 + OMAP_PRMD_RETENTION, 26 + OMAP_PRMD_ON_INACTIVE, 27 + OMAP_PRMD_ON_ACTIVE, 28 + }; 29 + 30 + struct omap_prm_domain_map { 31 + unsigned int usable_modes; /* Mask of hardware supported modes */ 32 + unsigned long statechange:1; /* Optional low-power state change */ 33 + unsigned long logicretstate:1; /* Optional logic off mode */ 34 + }; 35 + 36 + struct omap_prm_domain { 37 + struct device *dev; 38 + struct omap_prm *prm; 39 + struct generic_pm_domain pd; 40 + u16 pwrstctrl; 41 + u16 pwrstst; 42 + const struct omap_prm_domain_map *cap; 43 + u32 pwrstctrl_saved; 44 + }; 20 45 21 46 struct omap_rst_map { 22 47 s8 rst; ··· 52 27 u32 base; 53 28 const char *name; 54 29 const char *clkdm_name; 30 + u16 pwrstctrl; 31 + u16 pwrstst; 32 + const struct omap_prm_domain_map *dmap; 55 33 u16 rstctrl; 56 34 u16 rstst; 57 35 const struct omap_rst_map *rstmap; ··· 64 36 struct omap_prm { 65 37 const struct omap_prm_data *data; 66 38 void __iomem *base; 39 + struct omap_prm_domain *prmd; 67 40 }; 68 41 69 42 struct omap_reset_data { ··· 76 47 struct device *dev; 77 48 }; 78 49 50 + #define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd) 79 51 #define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev) 80 52 81 53 #define OMAP_MAX_RESETS 8 ··· 87 57 #define OMAP_PRM_HAS_NO_CLKDM BIT(2) 88 58 89 59 #define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST) 60 + 61 + #define PRM_STATE_MAX_WAIT 10000 62 + #define PRM_LOGICRETSTATE BIT(2) 63 + #define PRM_LOWPOWERSTATECHANGE BIT(4) 64 + #define PRM_POWERSTATE_MASK OMAP_PRMD_ON_ACTIVE 65 + 66 + #define PRM_ST_INTRANSITION BIT(20) 67 + 68 + static const struct omap_prm_domain_map omap_prm_all = { 69 + .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) | 70 + BIT(OMAP_PRMD_RETENTION) | BIT(OMAP_PRMD_OFF), 71 + .statechange = 1, 72 + .logicretstate = 1, 73 + }; 74 + 75 + static const struct omap_prm_domain_map omap_prm_noinact = { 76 + .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION) | 77 + BIT(OMAP_PRMD_OFF), 78 + .statechange = 1, 79 + .logicretstate = 1, 80 + }; 81 + 82 + static const struct omap_prm_domain_map omap_prm_nooff = { 83 + .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) | 84 + BIT(OMAP_PRMD_RETENTION), 85 + .statechange = 1, 86 + .logicretstate = 1, 87 + }; 88 + 89 + static const struct omap_prm_domain_map omap_prm_onoff_noauto = { 90 + .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_OFF), 91 + .statechange = 1, 92 + }; 90 93 91 94 static const struct omap_rst_map rst_map_0[] = { 92 95 { .rst = 0, .st = 0 }, ··· 141 78 142 79 static const struct omap_prm_data omap4_prm_data[] = { 143 80 { .name = "tesla", .base = 0x4a306400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 81 + { 82 + .name = "abe", .base = 0x4a306500, 83 + .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_all, 84 + }, 144 85 { .name = "core", .base = 0x4a306700, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati", .rstmap = rst_map_012 }, 145 86 { .name = "ivahd", .base = 0x4a306f00, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 }, 146 87 { .name = "device", .base = 0x4a307b00, .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, ··· 153 86 154 87 static const struct omap_prm_data omap5_prm_data[] = { 155 88 { .name = "dsp", .base = 0x4ae06400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 }, 89 + { 90 + .name = "abe", .base = 0x4ae06500, 91 + .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_nooff, 92 + }, 156 93 { .name = "core", .base = 0x4ae06700, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu", .rstmap = rst_map_012 }, 157 94 { .name = "iva", .base = 0x4ae07200, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 }, 158 95 { .name = "device", .base = 0x4ae07c00, .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, ··· 190 119 { .name = "per", .base = 0x44e00c00, .rstctrl = 0x0, .rstmap = am3_per_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp" }, 191 120 { .name = "wkup", .base = 0x44e00d00, .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, 192 121 { .name = "device", .base = 0x44e00f00, .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, 193 - { .name = "gfx", .base = 0x44e01100, .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3" }, 122 + { 123 + .name = "gfx", .base = 0x44e01100, 124 + .pwrstctrl = 0, .pwrstst = 0x10, .dmap = &omap_prm_noinact, 125 + .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3", 126 + }, 194 127 { }, 195 128 }; 196 129 ··· 210 135 }; 211 136 212 137 static const struct omap_prm_data am4_prm_data[] = { 213 - { .name = "gfx", .base = 0x44df0400, .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3" }, 138 + { 139 + .name = "gfx", .base = 0x44df0400, 140 + .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 141 + .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3", 142 + }, 214 143 { .name = "per", .base = 0x44df0800, .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map, .clkdm_name = "pruss_ocp" }, 215 144 { .name = "wkup", .base = 0x44df2000, .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map, .flags = OMAP_PRM_HAS_NO_CLKDM }, 216 145 { .name = "device", .base = 0x44df4000, .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map, .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM }, ··· 229 150 { .compatible = "ti,am4-prm-inst", .data = am4_prm_data }, 230 151 { }, 231 152 }; 153 + 154 + #ifdef DEBUG 155 + static void omap_prm_domain_show_state(struct omap_prm_domain *prmd, 156 + const char *desc) 157 + { 158 + dev_dbg(prmd->dev, "%s %s: %08x/%08x\n", 159 + prmd->pd.name, desc, 160 + readl_relaxed(prmd->prm->base + prmd->pwrstctrl), 161 + readl_relaxed(prmd->prm->base + prmd->pwrstst)); 162 + } 163 + #else 164 + static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd, 165 + const char *desc) 166 + { 167 + } 168 + #endif 169 + 170 + static int omap_prm_domain_power_on(struct generic_pm_domain *domain) 171 + { 172 + struct omap_prm_domain *prmd; 173 + int ret; 174 + u32 v; 175 + 176 + prmd = genpd_to_prm_domain(domain); 177 + if (!prmd->cap) 178 + return 0; 179 + 180 + omap_prm_domain_show_state(prmd, "on: previous state"); 181 + 182 + if (prmd->pwrstctrl_saved) 183 + v = prmd->pwrstctrl_saved; 184 + else 185 + v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl); 186 + 187 + writel_relaxed(v | OMAP_PRMD_ON_ACTIVE, 188 + prmd->prm->base + prmd->pwrstctrl); 189 + 190 + /* wait for the transition bit to get cleared */ 191 + ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst, 192 + v, !(v & PRM_ST_INTRANSITION), 1, 193 + PRM_STATE_MAX_WAIT); 194 + if (ret) 195 + dev_err(prmd->dev, "%s: %s timed out\n", 196 + prmd->pd.name, __func__); 197 + 198 + omap_prm_domain_show_state(prmd, "on: new state"); 199 + 200 + return ret; 201 + } 202 + 203 + /* No need to check for holes in the mask for the lowest mode */ 204 + static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd) 205 + { 206 + return __ffs(prmd->cap->usable_modes); 207 + } 208 + 209 + static int omap_prm_domain_power_off(struct generic_pm_domain *domain) 210 + { 211 + struct omap_prm_domain *prmd; 212 + int ret; 213 + u32 v; 214 + 215 + prmd = genpd_to_prm_domain(domain); 216 + if (!prmd->cap) 217 + return 0; 218 + 219 + omap_prm_domain_show_state(prmd, "off: previous state"); 220 + 221 + v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl); 222 + prmd->pwrstctrl_saved = v; 223 + 224 + v &= ~PRM_POWERSTATE_MASK; 225 + v |= omap_prm_domain_find_lowest(prmd); 226 + 227 + if (prmd->cap->statechange) 228 + v |= PRM_LOWPOWERSTATECHANGE; 229 + if (prmd->cap->logicretstate) 230 + v &= ~PRM_LOGICRETSTATE; 231 + else 232 + v |= PRM_LOGICRETSTATE; 233 + 234 + writel_relaxed(v, prmd->prm->base + prmd->pwrstctrl); 235 + 236 + /* wait for the transition bit to get cleared */ 237 + ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst, 238 + v, !(v & PRM_ST_INTRANSITION), 1, 239 + PRM_STATE_MAX_WAIT); 240 + if (ret) 241 + dev_warn(prmd->dev, "%s: %s timed out\n", 242 + __func__, prmd->pd.name); 243 + 244 + omap_prm_domain_show_state(prmd, "off: new state"); 245 + 246 + return 0; 247 + } 248 + 249 + static int omap_prm_domain_attach_dev(struct generic_pm_domain *domain, 250 + struct device *dev) 251 + { 252 + struct generic_pm_domain_data *genpd_data; 253 + struct of_phandle_args pd_args; 254 + struct omap_prm_domain *prmd; 255 + struct device_node *np; 256 + int ret; 257 + 258 + prmd = genpd_to_prm_domain(domain); 259 + np = dev->of_node; 260 + 261 + ret = of_parse_phandle_with_args(np, "power-domains", 262 + "#power-domain-cells", 0, &pd_args); 263 + if (ret < 0) 264 + return ret; 265 + 266 + if (pd_args.args_count != 0) 267 + dev_warn(dev, "%s: unusupported #power-domain-cells: %i\n", 268 + prmd->pd.name, pd_args.args_count); 269 + 270 + genpd_data = dev_gpd_data(dev); 271 + genpd_data->data = NULL; 272 + 273 + return 0; 274 + } 275 + 276 + static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain, 277 + struct device *dev) 278 + { 279 + struct generic_pm_domain_data *genpd_data; 280 + 281 + genpd_data = dev_gpd_data(dev); 282 + genpd_data->data = NULL; 283 + } 284 + 285 + static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm) 286 + { 287 + struct omap_prm_domain *prmd; 288 + struct device_node *np = dev->of_node; 289 + const struct omap_prm_data *data; 290 + const char *name; 291 + int error; 292 + 293 + if (!of_find_property(dev->of_node, "#power-domain-cells", NULL)) 294 + return 0; 295 + 296 + of_node_put(dev->of_node); 297 + 298 + prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL); 299 + if (!prmd) 300 + return -ENOMEM; 301 + 302 + data = prm->data; 303 + name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s", 304 + data->name); 305 + 306 + prmd->dev = dev; 307 + prmd->prm = prm; 308 + prmd->cap = prmd->prm->data->dmap; 309 + prmd->pwrstctrl = prmd->prm->data->pwrstctrl; 310 + prmd->pwrstst = prmd->prm->data->pwrstst; 311 + 312 + prmd->pd.name = name; 313 + prmd->pd.power_on = omap_prm_domain_power_on; 314 + prmd->pd.power_off = omap_prm_domain_power_off; 315 + prmd->pd.attach_dev = omap_prm_domain_attach_dev; 316 + prmd->pd.detach_dev = omap_prm_domain_detach_dev; 317 + 318 + pm_genpd_init(&prmd->pd, NULL, true); 319 + error = of_genpd_add_provider_simple(np, &prmd->pd); 320 + if (error) 321 + pm_genpd_remove(&prmd->pd); 322 + else 323 + prm->prmd = prmd; 324 + 325 + return error; 326 + } 232 327 233 328 static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id) 234 329 { ··· 604 351 const struct omap_prm_data *data; 605 352 struct omap_prm *prm; 606 353 const struct of_device_id *match; 354 + int ret; 607 355 608 356 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 609 357 if (!res) ··· 632 378 if (IS_ERR(prm->base)) 633 379 return PTR_ERR(prm->base); 634 380 635 - return omap_prm_reset_init(pdev, prm); 381 + ret = omap_prm_domain_init(&pdev->dev, prm); 382 + if (ret) 383 + return ret; 384 + 385 + ret = omap_prm_reset_init(pdev, prm); 386 + if (ret) 387 + goto err_domain; 388 + 389 + return 0; 390 + 391 + err_domain: 392 + of_genpd_del_provider(pdev->dev.of_node); 393 + pm_genpd_remove(&prm->prmd->pd); 394 + 395 + return ret; 636 396 } 637 397 638 398 static struct platform_driver omap_prm_driver = {