1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * OMAP2+ PRM driver 4 * 5 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ 6 * Tero Kristo <t-kristo@ti.com> 7 */ 8 9 #include <linux/kernel.h> 10 #include <linux/clk.h> 11 #include <linux/device.h> 12 #include <linux/io.h> 13 #include <linux/iopoll.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 #include <linux/pm_clock.h> 18 #include <linux/pm_domain.h> 19 #include <linux/reset-controller.h> 20 #include <linux/delay.h> 21 22 #include <linux/platform_data/ti-prm.h> 23 24 enum omap_prm_domain_mode { 25 OMAP_PRMD_OFF, 26 OMAP_PRMD_RETENTION, 27 OMAP_PRMD_ON_INACTIVE, 28 OMAP_PRMD_ON_ACTIVE, 29 }; 30 31 struct omap_prm_domain_map { 32 unsigned int usable_modes; /* Mask of hardware supported modes */ 33 unsigned long statechange:1; /* Optional low-power state change */ 34 unsigned long logicretstate:1; /* Optional logic off mode */ 35 }; 36 37 struct omap_prm_domain { 38 struct device *dev; 39 struct omap_prm *prm; 40 struct generic_pm_domain pd; 41 u16 pwrstctrl; 42 u16 pwrstst; 43 const struct omap_prm_domain_map *cap; 44 u32 pwrstctrl_saved; 45 unsigned int uses_pm_clk:1; 46 }; 47 48 struct omap_rst_map { 49 s8 rst; 50 s8 st; 51 }; 52 53 struct omap_prm_data { 54 u32 base; 55 const char *name; 56 const char *clkdm_name; 57 u16 pwrstctrl; 58 u16 pwrstst; 59 const struct omap_prm_domain_map *dmap; 60 u16 rstctrl; 61 u16 rstst; 62 const struct omap_rst_map *rstmap; 63 u8 flags; 64 }; 65 66 struct omap_prm { 67 const struct omap_prm_data *data; 68 void __iomem *base; 69 struct omap_prm_domain *prmd; 70 }; 71 72 struct omap_reset_data { 73 struct reset_controller_dev rcdev; 74 struct omap_prm *prm; 75 u32 mask; 76 spinlock_t lock; 77 struct clockdomain *clkdm; 78 struct device *dev; 79 }; 80 81 #define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd) 82 #define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev) 83 84 #define OMAP_MAX_RESETS 8 85 #define OMAP_RESET_MAX_WAIT 10000 86 87 #define OMAP_PRM_HAS_RSTCTRL BIT(0) 88 #define OMAP_PRM_HAS_RSTST BIT(1) 89 #define OMAP_PRM_HAS_NO_CLKDM BIT(2) 90 #define OMAP_PRM_RET_WHEN_IDLE BIT(3) 91 92 #define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST) 93 94 #define PRM_STATE_MAX_WAIT 10000 95 #define PRM_LOGICRETSTATE BIT(2) 96 #define PRM_LOWPOWERSTATECHANGE BIT(4) 97 #define PRM_POWERSTATE_MASK OMAP_PRMD_ON_ACTIVE 98 99 #define PRM_ST_INTRANSITION BIT(20) 100 101 static const struct omap_prm_domain_map omap_prm_all = { 102 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) | 103 BIT(OMAP_PRMD_RETENTION) | BIT(OMAP_PRMD_OFF), 104 .statechange = 1, 105 .logicretstate = 1, 106 }; 107 108 static const struct omap_prm_domain_map omap_prm_noinact = { 109 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION) | 110 BIT(OMAP_PRMD_OFF), 111 .statechange = 1, 112 .logicretstate = 1, 113 }; 114 115 static const struct omap_prm_domain_map omap_prm_nooff = { 116 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) | 117 BIT(OMAP_PRMD_RETENTION), 118 .statechange = 1, 119 .logicretstate = 1, 120 }; 121 122 static const struct omap_prm_domain_map omap_prm_onoff_noauto = { 123 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_OFF), 124 .statechange = 1, 125 }; 126 127 static const struct omap_prm_domain_map omap_prm_alwon = { 128 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE), 129 }; 130 131 static const struct omap_prm_domain_map omap_prm_reton = { 132 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION), 133 .statechange = 1, 134 .logicretstate = 1, 135 }; 136 137 static const struct omap_rst_map rst_map_0[] = { 138 { .rst = 0, .st = 0 }, 139 { .rst = -1 }, 140 }; 141 142 static const struct omap_rst_map rst_map_01[] = { 143 { .rst = 0, .st = 0 }, 144 { .rst = 1, .st = 1 }, 145 { .rst = -1 }, 146 }; 147 148 static const struct omap_rst_map rst_map_012[] = { 149 { .rst = 0, .st = 0 }, 150 { .rst = 1, .st = 1 }, 151 { .rst = 2, .st = 2 }, 152 { .rst = -1 }, 153 }; 154 155 static const struct omap_prm_data omap4_prm_data[] = { 156 { 157 .name = "mpu", .base = 0x4a306300, 158 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, 159 }, 160 { 161 .name = "tesla", .base = 0x4a306400, 162 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, 163 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 164 }, 165 { 166 .name = "abe", .base = 0x4a306500, 167 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_all, 168 }, 169 { 170 .name = "always_on_core", .base = 0x4a306600, 171 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 172 }, 173 { 174 .name = "core", .base = 0x4a306700, 175 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, 176 .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati", 177 .rstmap = rst_map_012, 178 .flags = OMAP_PRM_RET_WHEN_IDLE, 179 }, 180 { 181 .name = "ivahd", .base = 0x4a306f00, 182 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, 183 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 184 }, 185 { 186 .name = "cam", .base = 0x4a307000, 187 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 188 }, 189 { 190 .name = "dss", .base = 0x4a307100, 191 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact 192 }, 193 { 194 .name = "gfx", .base = 0x4a307200, 195 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto 196 }, 197 { 198 .name = "l3init", .base = 0x4a307300, 199 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton 200 }, 201 { 202 .name = "l4per", .base = 0x4a307400, 203 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, 204 .flags = OMAP_PRM_RET_WHEN_IDLE, 205 }, 206 { 207 .name = "cefuse", .base = 0x4a307600, 208 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto 209 }, 210 { 211 .name = "wkup", .base = 0x4a307700, 212 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon 213 }, 214 { 215 .name = "emu", .base = 0x4a307900, 216 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto 217 }, 218 { 219 .name = "device", .base = 0x4a307b00, 220 .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, 221 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM 222 }, 223 { }, 224 }; 225 226 static const struct omap_prm_data omap5_prm_data[] = { 227 { 228 .name = "mpu", .base = 0x4ae06300, 229 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, 230 }, 231 { 232 .name = "dsp", .base = 0x4ae06400, 233 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, 234 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 235 }, 236 { 237 .name = "abe", .base = 0x4ae06500, 238 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_nooff, 239 }, 240 { 241 .name = "coreaon", .base = 0x4ae06600, 242 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon 243 }, 244 { 245 .name = "core", .base = 0x4ae06700, 246 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, 247 .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu", 248 .rstmap = rst_map_012 249 }, 250 { 251 .name = "iva", .base = 0x4ae07200, 252 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, 253 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012 254 }, 255 { 256 .name = "cam", .base = 0x4ae07300, 257 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto 258 }, 259 { 260 .name = "dss", .base = 0x4ae07400, 261 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact 262 }, 263 { 264 .name = "gpu", .base = 0x4ae07500, 265 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto 266 }, 267 { 268 .name = "l3init", .base = 0x4ae07600, 269 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton 270 }, 271 { 272 .name = "custefuse", .base = 0x4ae07700, 273 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto 274 }, 275 { 276 .name = "wkupaon", .base = 0x4ae07800, 277 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon 278 }, 279 { 280 .name = "emu", .base = 0x4ae07a00, 281 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto 282 }, 283 { 284 .name = "device", .base = 0x4ae07c00, 285 .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01, 286 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM 287 }, 288 { }, 289 }; 290 291 static const struct omap_prm_data dra7_prm_data[] = { 292 { 293 .name = "mpu", .base = 0x4ae06300, 294 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, 295 }, 296 { 297 .name = "dsp1", .base = 0x4ae06400, 298 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 299 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01, 300 }, 301 { 302 .name = "ipu", .base = 0x4ae06500, 303 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 304 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012, 305 .clkdm_name = "ipu1" 306 }, 307 { 308 .name = "coreaon", .base = 0x4ae06628, 309 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 310 }, 311 { 312 .name = "core", .base = 0x4ae06700, 313 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 314 .rstctrl = 0x210, .rstst = 0x214, .rstmap = rst_map_012, 315 .clkdm_name = "ipu2" 316 }, 317 { 318 .name = "iva", .base = 0x4ae06f00, 319 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 320 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012, 321 }, 322 { 323 .name = "cam", .base = 0x4ae07000, 324 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 325 }, 326 { 327 .name = "dss", .base = 0x4ae07100, 328 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 329 }, 330 { 331 .name = "gpu", .base = 0x4ae07200, 332 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 333 }, 334 { 335 .name = "l3init", .base = 0x4ae07300, 336 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 337 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01, 338 .clkdm_name = "pcie" 339 }, 340 { 341 .name = "l4per", .base = 0x4ae07400, 342 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 343 }, 344 { 345 .name = "custefuse", .base = 0x4ae07600, 346 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 347 }, 348 { 349 .name = "wkupaon", .base = 0x4ae07724, 350 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 351 }, 352 { 353 .name = "emu", .base = 0x4ae07900, 354 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 355 }, 356 { 357 .name = "dsp2", .base = 0x4ae07b00, 358 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 359 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 360 }, 361 { 362 .name = "eve1", .base = 0x4ae07b40, 363 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 364 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 365 }, 366 { 367 .name = "eve2", .base = 0x4ae07b80, 368 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 369 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 370 }, 371 { 372 .name = "eve3", .base = 0x4ae07bc0, 373 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 374 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 375 }, 376 { 377 .name = "eve4", .base = 0x4ae07c00, 378 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 379 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01 380 }, 381 { 382 .name = "rtc", .base = 0x4ae07c60, 383 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 384 }, 385 { 386 .name = "vpe", .base = 0x4ae07c80, 387 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 388 }, 389 { }, 390 }; 391 392 static const struct omap_rst_map am3_per_rst_map[] = { 393 { .rst = 1 }, 394 { .rst = -1 }, 395 }; 396 397 static const struct omap_rst_map am3_wkup_rst_map[] = { 398 { .rst = 3, .st = 5 }, 399 { .rst = -1 }, 400 }; 401 402 static const struct omap_prm_data am3_prm_data[] = { 403 { 404 .name = "per", .base = 0x44e00c00, 405 .pwrstctrl = 0xc, .pwrstst = 0x8, .dmap = &omap_prm_noinact, 406 .rstctrl = 0x0, .rstmap = am3_per_rst_map, 407 .flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp" 408 }, 409 { 410 .name = "wkup", .base = 0x44e00d00, 411 .pwrstctrl = 0x4, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 412 .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map, 413 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM 414 }, 415 { 416 .name = "mpu", .base = 0x44e00e00, 417 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, 418 }, 419 { 420 .name = "device", .base = 0x44e00f00, 421 .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01, 422 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM 423 }, 424 { 425 .name = "rtc", .base = 0x44e01000, 426 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 427 }, 428 { 429 .name = "gfx", .base = 0x44e01100, 430 .pwrstctrl = 0, .pwrstst = 0x10, .dmap = &omap_prm_noinact, 431 .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3", 432 }, 433 { 434 .name = "cefuse", .base = 0x44e01200, 435 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 436 }, 437 { }, 438 }; 439 440 static const struct omap_rst_map am4_per_rst_map[] = { 441 { .rst = 1, .st = 0 }, 442 { .rst = -1 }, 443 }; 444 445 static const struct omap_rst_map am4_device_rst_map[] = { 446 { .rst = 0, .st = 1 }, 447 { .rst = 1, .st = 0 }, 448 { .rst = -1 }, 449 }; 450 451 static const struct omap_prm_data am4_prm_data[] = { 452 { 453 .name = "mpu", .base = 0x44df0300, 454 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, 455 }, 456 { 457 .name = "gfx", .base = 0x44df0400, 458 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 459 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3", 460 }, 461 { 462 .name = "rtc", .base = 0x44df0500, 463 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 464 }, 465 { 466 .name = "tamper", .base = 0x44df0600, 467 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 468 }, 469 { 470 .name = "cefuse", .base = 0x44df0700, 471 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto, 472 }, 473 { 474 .name = "per", .base = 0x44df0800, 475 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact, 476 .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map, 477 .clkdm_name = "pruss_ocp" 478 }, 479 { 480 .name = "wkup", .base = 0x44df2000, 481 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, 482 .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map, 483 .flags = OMAP_PRM_HAS_NO_CLKDM 484 }, 485 { 486 .name = "device", .base = 0x44df4000, 487 .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map, 488 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM 489 }, 490 { }, 491 }; 492 493 static const struct of_device_id omap_prm_id_table[] = { 494 { .compatible = "ti,omap4-prm-inst", .data = omap4_prm_data }, 495 { .compatible = "ti,omap5-prm-inst", .data = omap5_prm_data }, 496 { .compatible = "ti,dra7-prm-inst", .data = dra7_prm_data }, 497 { .compatible = "ti,am3-prm-inst", .data = am3_prm_data }, 498 { .compatible = "ti,am4-prm-inst", .data = am4_prm_data }, 499 { }, 500 }; 501 502 #ifdef DEBUG 503 static void omap_prm_domain_show_state(struct omap_prm_domain *prmd, 504 const char *desc) 505 { 506 dev_dbg(prmd->dev, "%s %s: %08x/%08x\n", 507 prmd->pd.name, desc, 508 readl_relaxed(prmd->prm->base + prmd->pwrstctrl), 509 readl_relaxed(prmd->prm->base + prmd->pwrstst)); 510 } 511 #else 512 static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd, 513 const char *desc) 514 { 515 } 516 #endif 517 518 static int omap_prm_domain_power_on(struct generic_pm_domain *domain) 519 { 520 struct omap_prm_domain *prmd; 521 int ret; 522 u32 v, mode; 523 524 prmd = genpd_to_prm_domain(domain); 525 if (!prmd->cap) 526 return 0; 527 528 omap_prm_domain_show_state(prmd, "on: previous state"); 529 530 if (prmd->pwrstctrl_saved) 531 v = prmd->pwrstctrl_saved; 532 else 533 v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl); 534 535 if (prmd->prm->data->flags & OMAP_PRM_RET_WHEN_IDLE) 536 mode = OMAP_PRMD_RETENTION; 537 else 538 mode = OMAP_PRMD_ON_ACTIVE; 539 540 writel_relaxed((v & ~PRM_POWERSTATE_MASK) | mode, 541 prmd->prm->base + prmd->pwrstctrl); 542 543 /* wait for the transition bit to get cleared */ 544 ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst, 545 v, !(v & PRM_ST_INTRANSITION), 1, 546 PRM_STATE_MAX_WAIT); 547 if (ret) 548 dev_err(prmd->dev, "%s: %s timed out\n", 549 prmd->pd.name, __func__); 550 551 omap_prm_domain_show_state(prmd, "on: new state"); 552 553 return ret; 554 } 555 556 /* No need to check for holes in the mask for the lowest mode */ 557 static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd) 558 { 559 return __ffs(prmd->cap->usable_modes); 560 } 561 562 static int omap_prm_domain_power_off(struct generic_pm_domain *domain) 563 { 564 struct omap_prm_domain *prmd; 565 int ret; 566 u32 v; 567 568 prmd = genpd_to_prm_domain(domain); 569 if (!prmd->cap) 570 return 0; 571 572 omap_prm_domain_show_state(prmd, "off: previous state"); 573 574 v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl); 575 prmd->pwrstctrl_saved = v; 576 577 v &= ~PRM_POWERSTATE_MASK; 578 v |= omap_prm_domain_find_lowest(prmd); 579 580 if (prmd->cap->statechange) 581 v |= PRM_LOWPOWERSTATECHANGE; 582 if (prmd->cap->logicretstate) 583 v &= ~PRM_LOGICRETSTATE; 584 else 585 v |= PRM_LOGICRETSTATE; 586 587 writel_relaxed(v, prmd->prm->base + prmd->pwrstctrl); 588 589 /* wait for the transition bit to get cleared */ 590 ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst, 591 v, !(v & PRM_ST_INTRANSITION), 1, 592 PRM_STATE_MAX_WAIT); 593 if (ret) 594 dev_warn(prmd->dev, "%s: %s timed out\n", 595 __func__, prmd->pd.name); 596 597 omap_prm_domain_show_state(prmd, "off: new state"); 598 599 return 0; 600 } 601 602 /* 603 * Note that ti-sysc already manages the module clocks separately so 604 * no need to manage those. Interconnect instances need clocks managed 605 * for simple-pm-bus. 606 */ 607 static int omap_prm_domain_attach_clock(struct device *dev, 608 struct omap_prm_domain *prmd) 609 { 610 struct device_node *np = dev->of_node; 611 int error; 612 613 if (!of_device_is_compatible(np, "simple-pm-bus")) 614 return 0; 615 616 if (!of_property_read_bool(np, "clocks")) 617 return 0; 618 619 error = pm_clk_create(dev); 620 if (error) 621 return error; 622 623 error = of_pm_clk_add_clks(dev); 624 if (error < 0) { 625 pm_clk_destroy(dev); 626 return error; 627 } 628 629 prmd->uses_pm_clk = 1; 630 631 return 0; 632 } 633 634 static int omap_prm_domain_attach_dev(struct generic_pm_domain *domain, 635 struct device *dev) 636 { 637 struct generic_pm_domain_data *genpd_data; 638 struct of_phandle_args pd_args; 639 struct omap_prm_domain *prmd; 640 struct device_node *np; 641 int ret; 642 643 prmd = genpd_to_prm_domain(domain); 644 np = dev->of_node; 645 646 ret = of_parse_phandle_with_args(np, "power-domains", 647 "#power-domain-cells", 0, &pd_args); 648 if (ret < 0) 649 return ret; 650 651 if (pd_args.args_count != 0) 652 dev_warn(dev, "%s: unusupported #power-domain-cells: %i\n", 653 prmd->pd.name, pd_args.args_count); 654 655 genpd_data = dev_gpd_data(dev); 656 genpd_data->data = NULL; 657 658 ret = omap_prm_domain_attach_clock(dev, prmd); 659 if (ret) 660 return ret; 661 662 return 0; 663 } 664 665 static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain, 666 struct device *dev) 667 { 668 struct generic_pm_domain_data *genpd_data; 669 struct omap_prm_domain *prmd; 670 671 prmd = genpd_to_prm_domain(domain); 672 if (prmd->uses_pm_clk) 673 pm_clk_destroy(dev); 674 genpd_data = dev_gpd_data(dev); 675 genpd_data->data = NULL; 676 } 677 678 static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm) 679 { 680 struct omap_prm_domain *prmd; 681 struct device_node *np = dev->of_node; 682 const struct omap_prm_data *data; 683 const char *name; 684 int error; 685 686 if (!of_property_present(dev->of_node, "#power-domain-cells")) 687 return 0; 688 689 of_node_put(dev->of_node); 690 691 prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL); 692 if (!prmd) 693 return -ENOMEM; 694 695 data = prm->data; 696 name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s", 697 data->name); 698 699 prmd->dev = dev; 700 prmd->prm = prm; 701 prmd->cap = prmd->prm->data->dmap; 702 prmd->pwrstctrl = prmd->prm->data->pwrstctrl; 703 prmd->pwrstst = prmd->prm->data->pwrstst; 704 705 prmd->pd.name = name; 706 prmd->pd.power_on = omap_prm_domain_power_on; 707 prmd->pd.power_off = omap_prm_domain_power_off; 708 prmd->pd.attach_dev = omap_prm_domain_attach_dev; 709 prmd->pd.detach_dev = omap_prm_domain_detach_dev; 710 prmd->pd.flags = GENPD_FLAG_PM_CLK; 711 712 pm_genpd_init(&prmd->pd, NULL, true); 713 error = of_genpd_add_provider_simple(np, &prmd->pd); 714 if (error) 715 pm_genpd_remove(&prmd->pd); 716 else 717 prm->prmd = prmd; 718 719 return error; 720 } 721 722 static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id) 723 { 724 if (reset->mask & BIT(id)) 725 return true; 726 727 return false; 728 } 729 730 static int omap_reset_get_st_bit(struct omap_reset_data *reset, 731 unsigned long id) 732 { 733 const struct omap_rst_map *map = reset->prm->data->rstmap; 734 735 while (map->rst >= 0) { 736 if (map->rst == id) 737 return map->st; 738 739 map++; 740 } 741 742 return id; 743 } 744 745 static int omap_reset_status(struct reset_controller_dev *rcdev, 746 unsigned long id) 747 { 748 struct omap_reset_data *reset = to_omap_reset_data(rcdev); 749 u32 v; 750 int st_bit = omap_reset_get_st_bit(reset, id); 751 bool has_rstst = reset->prm->data->rstst || 752 (reset->prm->data->flags & OMAP_PRM_HAS_RSTST); 753 754 /* Check if we have rstst */ 755 if (!has_rstst) 756 return -ENOTSUPP; 757 758 /* Check if hw reset line is asserted */ 759 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); 760 if (v & BIT(id)) 761 return 1; 762 763 /* 764 * Check reset status, high value means reset sequence has been 765 * completed successfully so we can return 0 here (reset deasserted) 766 */ 767 v = readl_relaxed(reset->prm->base + reset->prm->data->rstst); 768 v >>= st_bit; 769 v &= 1; 770 771 return !v; 772 } 773 774 static int omap_reset_assert(struct reset_controller_dev *rcdev, 775 unsigned long id) 776 { 777 struct omap_reset_data *reset = to_omap_reset_data(rcdev); 778 u32 v; 779 unsigned long flags; 780 781 /* assert the reset control line */ 782 spin_lock_irqsave(&reset->lock, flags); 783 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); 784 v |= 1 << id; 785 writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl); 786 spin_unlock_irqrestore(&reset->lock, flags); 787 788 return 0; 789 } 790 791 static int omap_reset_deassert(struct reset_controller_dev *rcdev, 792 unsigned long id) 793 { 794 struct omap_reset_data *reset = to_omap_reset_data(rcdev); 795 u32 v; 796 int st_bit; 797 bool has_rstst; 798 unsigned long flags; 799 struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev); 800 int ret = 0; 801 802 /* Nothing to do if the reset is already deasserted */ 803 if (!omap_reset_status(rcdev, id)) 804 return 0; 805 806 has_rstst = reset->prm->data->rstst || 807 (reset->prm->data->flags & OMAP_PRM_HAS_RSTST); 808 809 if (has_rstst) { 810 st_bit = omap_reset_get_st_bit(reset, id); 811 812 /* Clear the reset status by writing 1 to the status bit */ 813 v = 1 << st_bit; 814 writel_relaxed(v, reset->prm->base + reset->prm->data->rstst); 815 } 816 817 if (reset->clkdm) 818 pdata->clkdm_deny_idle(reset->clkdm); 819 820 /* de-assert the reset control line */ 821 spin_lock_irqsave(&reset->lock, flags); 822 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); 823 v &= ~(1 << id); 824 writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl); 825 spin_unlock_irqrestore(&reset->lock, flags); 826 827 /* wait for the reset bit to clear */ 828 ret = readl_relaxed_poll_timeout_atomic(reset->prm->base + 829 reset->prm->data->rstctrl, 830 v, !(v & BIT(id)), 1, 831 OMAP_RESET_MAX_WAIT); 832 if (ret) 833 pr_err("%s: timedout waiting for %s:%lu\n", __func__, 834 reset->prm->data->name, id); 835 836 /* wait for the status to be set */ 837 if (has_rstst) { 838 ret = readl_relaxed_poll_timeout_atomic(reset->prm->base + 839 reset->prm->data->rstst, 840 v, v & BIT(st_bit), 1, 841 OMAP_RESET_MAX_WAIT); 842 if (ret) 843 pr_err("%s: timedout waiting for %s:%lu\n", __func__, 844 reset->prm->data->name, id); 845 } 846 847 if (reset->clkdm) 848 pdata->clkdm_allow_idle(reset->clkdm); 849 850 return ret; 851 } 852 853 static const struct reset_control_ops omap_reset_ops = { 854 .assert = omap_reset_assert, 855 .deassert = omap_reset_deassert, 856 .status = omap_reset_status, 857 }; 858 859 static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev, 860 const struct of_phandle_args *reset_spec) 861 { 862 struct omap_reset_data *reset = to_omap_reset_data(rcdev); 863 864 if (!_is_valid_reset(reset, reset_spec->args[0])) 865 return -EINVAL; 866 867 return reset_spec->args[0]; 868 } 869 870 static int omap_prm_reset_init(struct platform_device *pdev, 871 struct omap_prm *prm) 872 { 873 struct omap_reset_data *reset; 874 const struct omap_rst_map *map; 875 struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev); 876 char buf[32]; 877 u32 v; 878 879 /* 880 * Check if we have controllable resets. If either rstctrl is non-zero 881 * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register 882 * for the domain. 883 */ 884 if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL)) 885 return 0; 886 887 /* Check if we have the pdata callbacks in place */ 888 if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle || 889 !pdata->clkdm_allow_idle) 890 return -EINVAL; 891 892 map = prm->data->rstmap; 893 if (!map) 894 return -EINVAL; 895 896 reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL); 897 if (!reset) 898 return -ENOMEM; 899 900 reset->rcdev.owner = THIS_MODULE; 901 reset->rcdev.ops = &omap_reset_ops; 902 reset->rcdev.of_node = pdev->dev.of_node; 903 reset->rcdev.nr_resets = OMAP_MAX_RESETS; 904 reset->rcdev.of_xlate = omap_prm_reset_xlate; 905 reset->rcdev.of_reset_n_cells = 1; 906 reset->dev = &pdev->dev; 907 spin_lock_init(&reset->lock); 908 909 reset->prm = prm; 910 911 sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name : 912 prm->data->name); 913 914 if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) { 915 reset->clkdm = pdata->clkdm_lookup(buf); 916 if (!reset->clkdm) 917 return -EINVAL; 918 } 919 920 while (map->rst >= 0) { 921 reset->mask |= BIT(map->rst); 922 map++; 923 } 924 925 /* Quirk handling to assert rst_map_012 bits on reset and avoid errors */ 926 if (prm->data->rstmap == rst_map_012) { 927 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl); 928 if ((v & reset->mask) != reset->mask) { 929 dev_dbg(&pdev->dev, "Asserting all resets: %08x\n", v); 930 writel_relaxed(reset->mask, reset->prm->base + 931 reset->prm->data->rstctrl); 932 } 933 } 934 935 return devm_reset_controller_register(&pdev->dev, &reset->rcdev); 936 } 937 938 static int omap_prm_probe(struct platform_device *pdev) 939 { 940 struct resource *res; 941 const struct omap_prm_data *data; 942 struct omap_prm *prm; 943 int ret; 944 945 data = of_device_get_match_data(&pdev->dev); 946 if (!data) 947 return -ENOTSUPP; 948 949 prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL); 950 if (!prm) 951 return -ENOMEM; 952 953 prm->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 954 if (IS_ERR(prm->base)) 955 return PTR_ERR(prm->base); 956 957 while (data->base != res->start) { 958 if (!data->base) 959 return -EINVAL; 960 data++; 961 } 962 963 prm->data = data; 964 965 ret = omap_prm_domain_init(&pdev->dev, prm); 966 if (ret) 967 return ret; 968 969 ret = omap_prm_reset_init(pdev, prm); 970 if (ret) 971 goto err_domain; 972 973 return 0; 974 975 err_domain: 976 of_genpd_del_provider(pdev->dev.of_node); 977 pm_genpd_remove(&prm->prmd->pd); 978 979 return ret; 980 } 981 982 static struct platform_driver omap_prm_driver = { 983 .probe = omap_prm_probe, 984 .driver = { 985 .name = KBUILD_MODNAME, 986 .of_match_table = omap_prm_id_table, 987 }, 988 }; 989 builtin_platform_driver(omap_prm_driver); 990