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