0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/clk.h>
0011 #include <linux/device.h>
0012 #include <linux/io.h>
0013 #include <linux/iopoll.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/of_device.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/pm_clock.h>
0019 #include <linux/pm_domain.h>
0020 #include <linux/reset-controller.h>
0021 #include <linux/delay.h>
0022
0023 #include <linux/platform_data/ti-prm.h>
0024
0025 enum omap_prm_domain_mode {
0026 OMAP_PRMD_OFF,
0027 OMAP_PRMD_RETENTION,
0028 OMAP_PRMD_ON_INACTIVE,
0029 OMAP_PRMD_ON_ACTIVE,
0030 };
0031
0032 struct omap_prm_domain_map {
0033 unsigned int usable_modes;
0034 unsigned long statechange:1;
0035 unsigned long logicretstate:1;
0036 };
0037
0038 struct omap_prm_domain {
0039 struct device *dev;
0040 struct omap_prm *prm;
0041 struct generic_pm_domain pd;
0042 u16 pwrstctrl;
0043 u16 pwrstst;
0044 const struct omap_prm_domain_map *cap;
0045 u32 pwrstctrl_saved;
0046 unsigned int uses_pm_clk:1;
0047 };
0048
0049 struct omap_rst_map {
0050 s8 rst;
0051 s8 st;
0052 };
0053
0054 struct omap_prm_data {
0055 u32 base;
0056 const char *name;
0057 const char *clkdm_name;
0058 u16 pwrstctrl;
0059 u16 pwrstst;
0060 const struct omap_prm_domain_map *dmap;
0061 u16 rstctrl;
0062 u16 rstst;
0063 const struct omap_rst_map *rstmap;
0064 u8 flags;
0065 };
0066
0067 struct omap_prm {
0068 const struct omap_prm_data *data;
0069 void __iomem *base;
0070 struct omap_prm_domain *prmd;
0071 };
0072
0073 struct omap_reset_data {
0074 struct reset_controller_dev rcdev;
0075 struct omap_prm *prm;
0076 u32 mask;
0077 spinlock_t lock;
0078 struct clockdomain *clkdm;
0079 struct device *dev;
0080 };
0081
0082 #define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd)
0083 #define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev)
0084
0085 #define OMAP_MAX_RESETS 8
0086 #define OMAP_RESET_MAX_WAIT 10000
0087
0088 #define OMAP_PRM_HAS_RSTCTRL BIT(0)
0089 #define OMAP_PRM_HAS_RSTST BIT(1)
0090 #define OMAP_PRM_HAS_NO_CLKDM BIT(2)
0091 #define OMAP_PRM_RET_WHEN_IDLE BIT(3)
0092
0093 #define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST)
0094
0095 #define PRM_STATE_MAX_WAIT 10000
0096 #define PRM_LOGICRETSTATE BIT(2)
0097 #define PRM_LOWPOWERSTATECHANGE BIT(4)
0098 #define PRM_POWERSTATE_MASK OMAP_PRMD_ON_ACTIVE
0099
0100 #define PRM_ST_INTRANSITION BIT(20)
0101
0102 static const struct omap_prm_domain_map omap_prm_all = {
0103 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
0104 BIT(OMAP_PRMD_RETENTION) | BIT(OMAP_PRMD_OFF),
0105 .statechange = 1,
0106 .logicretstate = 1,
0107 };
0108
0109 static const struct omap_prm_domain_map omap_prm_noinact = {
0110 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION) |
0111 BIT(OMAP_PRMD_OFF),
0112 .statechange = 1,
0113 .logicretstate = 1,
0114 };
0115
0116 static const struct omap_prm_domain_map omap_prm_nooff = {
0117 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
0118 BIT(OMAP_PRMD_RETENTION),
0119 .statechange = 1,
0120 .logicretstate = 1,
0121 };
0122
0123 static const struct omap_prm_domain_map omap_prm_onoff_noauto = {
0124 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_OFF),
0125 .statechange = 1,
0126 };
0127
0128 static const struct omap_prm_domain_map omap_prm_alwon = {
0129 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE),
0130 };
0131
0132 static const struct omap_prm_domain_map omap_prm_reton = {
0133 .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION),
0134 .statechange = 1,
0135 .logicretstate = 1,
0136 };
0137
0138 static const struct omap_rst_map rst_map_0[] = {
0139 { .rst = 0, .st = 0 },
0140 { .rst = -1 },
0141 };
0142
0143 static const struct omap_rst_map rst_map_01[] = {
0144 { .rst = 0, .st = 0 },
0145 { .rst = 1, .st = 1 },
0146 { .rst = -1 },
0147 };
0148
0149 static const struct omap_rst_map rst_map_012[] = {
0150 { .rst = 0, .st = 0 },
0151 { .rst = 1, .st = 1 },
0152 { .rst = 2, .st = 2 },
0153 { .rst = -1 },
0154 };
0155
0156 static const struct omap_prm_data omap4_prm_data[] = {
0157 {
0158 .name = "mpu", .base = 0x4a306300,
0159 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
0160 },
0161 {
0162 .name = "tesla", .base = 0x4a306400,
0163 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
0164 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
0165 },
0166 {
0167 .name = "abe", .base = 0x4a306500,
0168 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_all,
0169 },
0170 {
0171 .name = "always_on_core", .base = 0x4a306600,
0172 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0173 },
0174 {
0175 .name = "core", .base = 0x4a306700,
0176 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
0177 .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati",
0178 .rstmap = rst_map_012,
0179 .flags = OMAP_PRM_RET_WHEN_IDLE,
0180 },
0181 {
0182 .name = "ivahd", .base = 0x4a306f00,
0183 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
0184 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012
0185 },
0186 {
0187 .name = "cam", .base = 0x4a307000,
0188 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0189 },
0190 {
0191 .name = "dss", .base = 0x4a307100,
0192 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact
0193 },
0194 {
0195 .name = "gfx", .base = 0x4a307200,
0196 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
0197 },
0198 {
0199 .name = "l3init", .base = 0x4a307300,
0200 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton
0201 },
0202 {
0203 .name = "l4per", .base = 0x4a307400,
0204 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
0205 .flags = OMAP_PRM_RET_WHEN_IDLE,
0206 },
0207 {
0208 .name = "cefuse", .base = 0x4a307600,
0209 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
0210 },
0211 {
0212 .name = "wkup", .base = 0x4a307700,
0213 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
0214 },
0215 {
0216 .name = "emu", .base = 0x4a307900,
0217 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
0218 },
0219 {
0220 .name = "device", .base = 0x4a307b00,
0221 .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01,
0222 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
0223 },
0224 { },
0225 };
0226
0227 static const struct omap_prm_data omap5_prm_data[] = {
0228 {
0229 .name = "mpu", .base = 0x4ae06300,
0230 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
0231 },
0232 {
0233 .name = "dsp", .base = 0x4ae06400,
0234 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
0235 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
0236 },
0237 {
0238 .name = "abe", .base = 0x4ae06500,
0239 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_nooff,
0240 },
0241 {
0242 .name = "coreaon", .base = 0x4ae06600,
0243 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
0244 },
0245 {
0246 .name = "core", .base = 0x4ae06700,
0247 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
0248 .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu",
0249 .rstmap = rst_map_012
0250 },
0251 {
0252 .name = "iva", .base = 0x4ae07200,
0253 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
0254 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012
0255 },
0256 {
0257 .name = "cam", .base = 0x4ae07300,
0258 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
0259 },
0260 {
0261 .name = "dss", .base = 0x4ae07400,
0262 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact
0263 },
0264 {
0265 .name = "gpu", .base = 0x4ae07500,
0266 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
0267 },
0268 {
0269 .name = "l3init", .base = 0x4ae07600,
0270 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton
0271 },
0272 {
0273 .name = "custefuse", .base = 0x4ae07700,
0274 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
0275 },
0276 {
0277 .name = "wkupaon", .base = 0x4ae07800,
0278 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
0279 },
0280 {
0281 .name = "emu", .base = 0x4ae07a00,
0282 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
0283 },
0284 {
0285 .name = "device", .base = 0x4ae07c00,
0286 .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01,
0287 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
0288 },
0289 { },
0290 };
0291
0292 static const struct omap_prm_data dra7_prm_data[] = {
0293 {
0294 .name = "mpu", .base = 0x4ae06300,
0295 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
0296 },
0297 {
0298 .name = "dsp1", .base = 0x4ae06400,
0299 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0300 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01,
0301 },
0302 {
0303 .name = "ipu", .base = 0x4ae06500,
0304 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0305 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012,
0306 .clkdm_name = "ipu1"
0307 },
0308 {
0309 .name = "coreaon", .base = 0x4ae06628,
0310 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0311 },
0312 {
0313 .name = "core", .base = 0x4ae06700,
0314 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0315 .rstctrl = 0x210, .rstst = 0x214, .rstmap = rst_map_012,
0316 .clkdm_name = "ipu2"
0317 },
0318 {
0319 .name = "iva", .base = 0x4ae06f00,
0320 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0321 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012,
0322 },
0323 {
0324 .name = "cam", .base = 0x4ae07000,
0325 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0326 },
0327 {
0328 .name = "dss", .base = 0x4ae07100,
0329 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0330 },
0331 {
0332 .name = "gpu", .base = 0x4ae07200,
0333 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0334 },
0335 {
0336 .name = "l3init", .base = 0x4ae07300,
0337 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0338 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01,
0339 .clkdm_name = "pcie"
0340 },
0341 {
0342 .name = "l4per", .base = 0x4ae07400,
0343 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0344 },
0345 {
0346 .name = "custefuse", .base = 0x4ae07600,
0347 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0348 },
0349 {
0350 .name = "wkupaon", .base = 0x4ae07724,
0351 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0352 },
0353 {
0354 .name = "emu", .base = 0x4ae07900,
0355 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0356 },
0357 {
0358 .name = "dsp2", .base = 0x4ae07b00,
0359 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0360 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
0361 },
0362 {
0363 .name = "eve1", .base = 0x4ae07b40,
0364 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0365 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
0366 },
0367 {
0368 .name = "eve2", .base = 0x4ae07b80,
0369 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0370 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
0371 },
0372 {
0373 .name = "eve3", .base = 0x4ae07bc0,
0374 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0375 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
0376 },
0377 {
0378 .name = "eve4", .base = 0x4ae07c00,
0379 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0380 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
0381 },
0382 {
0383 .name = "rtc", .base = 0x4ae07c60,
0384 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0385 },
0386 {
0387 .name = "vpe", .base = 0x4ae07c80,
0388 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0389 },
0390 { },
0391 };
0392
0393 static const struct omap_rst_map am3_per_rst_map[] = {
0394 { .rst = 1 },
0395 { .rst = -1 },
0396 };
0397
0398 static const struct omap_rst_map am3_wkup_rst_map[] = {
0399 { .rst = 3, .st = 5 },
0400 { .rst = -1 },
0401 };
0402
0403 static const struct omap_prm_data am3_prm_data[] = {
0404 {
0405 .name = "per", .base = 0x44e00c00,
0406 .pwrstctrl = 0xc, .pwrstst = 0x8, .dmap = &omap_prm_noinact,
0407 .rstctrl = 0x0, .rstmap = am3_per_rst_map,
0408 .flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp"
0409 },
0410 {
0411 .name = "wkup", .base = 0x44e00d00,
0412 .pwrstctrl = 0x4, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0413 .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map,
0414 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
0415 },
0416 {
0417 .name = "mpu", .base = 0x44e00e00,
0418 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
0419 },
0420 {
0421 .name = "device", .base = 0x44e00f00,
0422 .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01,
0423 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
0424 },
0425 {
0426 .name = "rtc", .base = 0x44e01000,
0427 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0428 },
0429 {
0430 .name = "gfx", .base = 0x44e01100,
0431 .pwrstctrl = 0, .pwrstst = 0x10, .dmap = &omap_prm_noinact,
0432 .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
0433 },
0434 {
0435 .name = "cefuse", .base = 0x44e01200,
0436 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0437 },
0438 { },
0439 };
0440
0441 static const struct omap_rst_map am4_per_rst_map[] = {
0442 { .rst = 1, .st = 0 },
0443 { .rst = -1 },
0444 };
0445
0446 static const struct omap_rst_map am4_device_rst_map[] = {
0447 { .rst = 0, .st = 1 },
0448 { .rst = 1, .st = 0 },
0449 { .rst = -1 },
0450 };
0451
0452 static const struct omap_prm_data am4_prm_data[] = {
0453 {
0454 .name = "mpu", .base = 0x44df0300,
0455 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
0456 },
0457 {
0458 .name = "gfx", .base = 0x44df0400,
0459 .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0460 .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
0461 },
0462 {
0463 .name = "rtc", .base = 0x44df0500,
0464 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0465 },
0466 {
0467 .name = "tamper", .base = 0x44df0600,
0468 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0469 },
0470 {
0471 .name = "cefuse", .base = 0x44df0700,
0472 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
0473 },
0474 {
0475 .name = "per", .base = 0x44df0800,
0476 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
0477 .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map,
0478 .clkdm_name = "pruss_ocp"
0479 },
0480 {
0481 .name = "wkup", .base = 0x44df2000,
0482 .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
0483 .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map,
0484 .flags = OMAP_PRM_HAS_NO_CLKDM
0485 },
0486 {
0487 .name = "device", .base = 0x44df4000,
0488 .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map,
0489 .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
0490 },
0491 { },
0492 };
0493
0494 static const struct of_device_id omap_prm_id_table[] = {
0495 { .compatible = "ti,omap4-prm-inst", .data = omap4_prm_data },
0496 { .compatible = "ti,omap5-prm-inst", .data = omap5_prm_data },
0497 { .compatible = "ti,dra7-prm-inst", .data = dra7_prm_data },
0498 { .compatible = "ti,am3-prm-inst", .data = am3_prm_data },
0499 { .compatible = "ti,am4-prm-inst", .data = am4_prm_data },
0500 { },
0501 };
0502
0503 #ifdef DEBUG
0504 static void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
0505 const char *desc)
0506 {
0507 dev_dbg(prmd->dev, "%s %s: %08x/%08x\n",
0508 prmd->pd.name, desc,
0509 readl_relaxed(prmd->prm->base + prmd->pwrstctrl),
0510 readl_relaxed(prmd->prm->base + prmd->pwrstst));
0511 }
0512 #else
0513 static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
0514 const char *desc)
0515 {
0516 }
0517 #endif
0518
0519 static int omap_prm_domain_power_on(struct generic_pm_domain *domain)
0520 {
0521 struct omap_prm_domain *prmd;
0522 int ret;
0523 u32 v, mode;
0524
0525 prmd = genpd_to_prm_domain(domain);
0526 if (!prmd->cap)
0527 return 0;
0528
0529 omap_prm_domain_show_state(prmd, "on: previous state");
0530
0531 if (prmd->pwrstctrl_saved)
0532 v = prmd->pwrstctrl_saved;
0533 else
0534 v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
0535
0536 if (prmd->prm->data->flags & OMAP_PRM_RET_WHEN_IDLE)
0537 mode = OMAP_PRMD_RETENTION;
0538 else
0539 mode = OMAP_PRMD_ON_ACTIVE;
0540
0541 writel_relaxed((v & ~PRM_POWERSTATE_MASK) | mode,
0542 prmd->prm->base + prmd->pwrstctrl);
0543
0544
0545 ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
0546 v, !(v & PRM_ST_INTRANSITION), 1,
0547 PRM_STATE_MAX_WAIT);
0548 if (ret)
0549 dev_err(prmd->dev, "%s: %s timed out\n",
0550 prmd->pd.name, __func__);
0551
0552 omap_prm_domain_show_state(prmd, "on: new state");
0553
0554 return ret;
0555 }
0556
0557
0558 static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd)
0559 {
0560 return __ffs(prmd->cap->usable_modes);
0561 }
0562
0563 static int omap_prm_domain_power_off(struct generic_pm_domain *domain)
0564 {
0565 struct omap_prm_domain *prmd;
0566 int ret;
0567 u32 v;
0568
0569 prmd = genpd_to_prm_domain(domain);
0570 if (!prmd->cap)
0571 return 0;
0572
0573 omap_prm_domain_show_state(prmd, "off: previous state");
0574
0575 v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
0576 prmd->pwrstctrl_saved = v;
0577
0578 v &= ~PRM_POWERSTATE_MASK;
0579 v |= omap_prm_domain_find_lowest(prmd);
0580
0581 if (prmd->cap->statechange)
0582 v |= PRM_LOWPOWERSTATECHANGE;
0583 if (prmd->cap->logicretstate)
0584 v &= ~PRM_LOGICRETSTATE;
0585 else
0586 v |= PRM_LOGICRETSTATE;
0587
0588 writel_relaxed(v, prmd->prm->base + prmd->pwrstctrl);
0589
0590
0591 ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
0592 v, !(v & PRM_ST_INTRANSITION), 1,
0593 PRM_STATE_MAX_WAIT);
0594 if (ret)
0595 dev_warn(prmd->dev, "%s: %s timed out\n",
0596 __func__, prmd->pd.name);
0597
0598 omap_prm_domain_show_state(prmd, "off: new state");
0599
0600 return 0;
0601 }
0602
0603
0604
0605
0606
0607
0608 static int omap_prm_domain_attach_clock(struct device *dev,
0609 struct omap_prm_domain *prmd)
0610 {
0611 struct device_node *np = dev->of_node;
0612 int error;
0613
0614 if (!of_device_is_compatible(np, "simple-pm-bus"))
0615 return 0;
0616
0617 if (!of_property_read_bool(np, "clocks"))
0618 return 0;
0619
0620 error = pm_clk_create(dev);
0621 if (error)
0622 return error;
0623
0624 error = of_pm_clk_add_clks(dev);
0625 if (error < 0) {
0626 pm_clk_destroy(dev);
0627 return error;
0628 }
0629
0630 prmd->uses_pm_clk = 1;
0631
0632 return 0;
0633 }
0634
0635 static int omap_prm_domain_attach_dev(struct generic_pm_domain *domain,
0636 struct device *dev)
0637 {
0638 struct generic_pm_domain_data *genpd_data;
0639 struct of_phandle_args pd_args;
0640 struct omap_prm_domain *prmd;
0641 struct device_node *np;
0642 int ret;
0643
0644 prmd = genpd_to_prm_domain(domain);
0645 np = dev->of_node;
0646
0647 ret = of_parse_phandle_with_args(np, "power-domains",
0648 "#power-domain-cells", 0, &pd_args);
0649 if (ret < 0)
0650 return ret;
0651
0652 if (pd_args.args_count != 0)
0653 dev_warn(dev, "%s: unusupported #power-domain-cells: %i\n",
0654 prmd->pd.name, pd_args.args_count);
0655
0656 genpd_data = dev_gpd_data(dev);
0657 genpd_data->data = NULL;
0658
0659 ret = omap_prm_domain_attach_clock(dev, prmd);
0660 if (ret)
0661 return ret;
0662
0663 return 0;
0664 }
0665
0666 static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain,
0667 struct device *dev)
0668 {
0669 struct generic_pm_domain_data *genpd_data;
0670 struct omap_prm_domain *prmd;
0671
0672 prmd = genpd_to_prm_domain(domain);
0673 if (prmd->uses_pm_clk)
0674 pm_clk_destroy(dev);
0675 genpd_data = dev_gpd_data(dev);
0676 genpd_data->data = NULL;
0677 }
0678
0679 static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
0680 {
0681 struct omap_prm_domain *prmd;
0682 struct device_node *np = dev->of_node;
0683 const struct omap_prm_data *data;
0684 const char *name;
0685 int error;
0686
0687 if (!of_find_property(dev->of_node, "#power-domain-cells", NULL))
0688 return 0;
0689
0690 of_node_put(dev->of_node);
0691
0692 prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL);
0693 if (!prmd)
0694 return -ENOMEM;
0695
0696 data = prm->data;
0697 name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s",
0698 data->name);
0699
0700 prmd->dev = dev;
0701 prmd->prm = prm;
0702 prmd->cap = prmd->prm->data->dmap;
0703 prmd->pwrstctrl = prmd->prm->data->pwrstctrl;
0704 prmd->pwrstst = prmd->prm->data->pwrstst;
0705
0706 prmd->pd.name = name;
0707 prmd->pd.power_on = omap_prm_domain_power_on;
0708 prmd->pd.power_off = omap_prm_domain_power_off;
0709 prmd->pd.attach_dev = omap_prm_domain_attach_dev;
0710 prmd->pd.detach_dev = omap_prm_domain_detach_dev;
0711 prmd->pd.flags = GENPD_FLAG_PM_CLK;
0712
0713 pm_genpd_init(&prmd->pd, NULL, true);
0714 error = of_genpd_add_provider_simple(np, &prmd->pd);
0715 if (error)
0716 pm_genpd_remove(&prmd->pd);
0717 else
0718 prm->prmd = prmd;
0719
0720 return error;
0721 }
0722
0723 static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id)
0724 {
0725 if (reset->mask & BIT(id))
0726 return true;
0727
0728 return false;
0729 }
0730
0731 static int omap_reset_get_st_bit(struct omap_reset_data *reset,
0732 unsigned long id)
0733 {
0734 const struct omap_rst_map *map = reset->prm->data->rstmap;
0735
0736 while (map->rst >= 0) {
0737 if (map->rst == id)
0738 return map->st;
0739
0740 map++;
0741 }
0742
0743 return id;
0744 }
0745
0746 static int omap_reset_status(struct reset_controller_dev *rcdev,
0747 unsigned long id)
0748 {
0749 struct omap_reset_data *reset = to_omap_reset_data(rcdev);
0750 u32 v;
0751 int st_bit = omap_reset_get_st_bit(reset, id);
0752 bool has_rstst = reset->prm->data->rstst ||
0753 (reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
0754
0755
0756 if (!has_rstst)
0757 return -ENOTSUPP;
0758
0759
0760 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
0761 if (v & BIT(id))
0762 return 1;
0763
0764
0765
0766
0767
0768 v = readl_relaxed(reset->prm->base + reset->prm->data->rstst);
0769 v >>= st_bit;
0770 v &= 1;
0771
0772 return !v;
0773 }
0774
0775 static int omap_reset_assert(struct reset_controller_dev *rcdev,
0776 unsigned long id)
0777 {
0778 struct omap_reset_data *reset = to_omap_reset_data(rcdev);
0779 u32 v;
0780 unsigned long flags;
0781
0782
0783 spin_lock_irqsave(&reset->lock, flags);
0784 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
0785 v |= 1 << id;
0786 writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
0787 spin_unlock_irqrestore(&reset->lock, flags);
0788
0789 return 0;
0790 }
0791
0792 static int omap_reset_deassert(struct reset_controller_dev *rcdev,
0793 unsigned long id)
0794 {
0795 struct omap_reset_data *reset = to_omap_reset_data(rcdev);
0796 u32 v;
0797 int st_bit;
0798 bool has_rstst;
0799 unsigned long flags;
0800 struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev);
0801 int ret = 0;
0802
0803
0804 if (!omap_reset_status(rcdev, id))
0805 return 0;
0806
0807 has_rstst = reset->prm->data->rstst ||
0808 (reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
0809
0810 if (has_rstst) {
0811 st_bit = omap_reset_get_st_bit(reset, id);
0812
0813
0814 v = 1 << st_bit;
0815 writel_relaxed(v, reset->prm->base + reset->prm->data->rstst);
0816 }
0817
0818 if (reset->clkdm)
0819 pdata->clkdm_deny_idle(reset->clkdm);
0820
0821
0822 spin_lock_irqsave(&reset->lock, flags);
0823 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
0824 v &= ~(1 << id);
0825 writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
0826 spin_unlock_irqrestore(&reset->lock, flags);
0827
0828
0829 ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
0830 reset->prm->data->rstctrl,
0831 v, !(v & BIT(id)), 1,
0832 OMAP_RESET_MAX_WAIT);
0833 if (ret)
0834 pr_err("%s: timedout waiting for %s:%lu\n", __func__,
0835 reset->prm->data->name, id);
0836
0837
0838 if (has_rstst) {
0839 ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
0840 reset->prm->data->rstst,
0841 v, v & BIT(st_bit), 1,
0842 OMAP_RESET_MAX_WAIT);
0843 if (ret)
0844 pr_err("%s: timedout waiting for %s:%lu\n", __func__,
0845 reset->prm->data->name, id);
0846 }
0847
0848 if (reset->clkdm)
0849 pdata->clkdm_allow_idle(reset->clkdm);
0850
0851 return ret;
0852 }
0853
0854 static const struct reset_control_ops omap_reset_ops = {
0855 .assert = omap_reset_assert,
0856 .deassert = omap_reset_deassert,
0857 .status = omap_reset_status,
0858 };
0859
0860 static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev,
0861 const struct of_phandle_args *reset_spec)
0862 {
0863 struct omap_reset_data *reset = to_omap_reset_data(rcdev);
0864
0865 if (!_is_valid_reset(reset, reset_spec->args[0]))
0866 return -EINVAL;
0867
0868 return reset_spec->args[0];
0869 }
0870
0871 static int omap_prm_reset_init(struct platform_device *pdev,
0872 struct omap_prm *prm)
0873 {
0874 struct omap_reset_data *reset;
0875 const struct omap_rst_map *map;
0876 struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev);
0877 char buf[32];
0878 u32 v;
0879
0880
0881
0882
0883
0884
0885 if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL))
0886 return 0;
0887
0888
0889 if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle ||
0890 !pdata->clkdm_allow_idle)
0891 return -EINVAL;
0892
0893 map = prm->data->rstmap;
0894 if (!map)
0895 return -EINVAL;
0896
0897 reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
0898 if (!reset)
0899 return -ENOMEM;
0900
0901 reset->rcdev.owner = THIS_MODULE;
0902 reset->rcdev.ops = &omap_reset_ops;
0903 reset->rcdev.of_node = pdev->dev.of_node;
0904 reset->rcdev.nr_resets = OMAP_MAX_RESETS;
0905 reset->rcdev.of_xlate = omap_prm_reset_xlate;
0906 reset->rcdev.of_reset_n_cells = 1;
0907 reset->dev = &pdev->dev;
0908 spin_lock_init(&reset->lock);
0909
0910 reset->prm = prm;
0911
0912 sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name :
0913 prm->data->name);
0914
0915 if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) {
0916 reset->clkdm = pdata->clkdm_lookup(buf);
0917 if (!reset->clkdm)
0918 return -EINVAL;
0919 }
0920
0921 while (map->rst >= 0) {
0922 reset->mask |= BIT(map->rst);
0923 map++;
0924 }
0925
0926
0927 if (prm->data->rstmap == rst_map_012) {
0928 v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
0929 if ((v & reset->mask) != reset->mask) {
0930 dev_dbg(&pdev->dev, "Asserting all resets: %08x\n", v);
0931 writel_relaxed(reset->mask, reset->prm->base +
0932 reset->prm->data->rstctrl);
0933 }
0934 }
0935
0936 return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
0937 }
0938
0939 static int omap_prm_probe(struct platform_device *pdev)
0940 {
0941 struct resource *res;
0942 const struct omap_prm_data *data;
0943 struct omap_prm *prm;
0944 int ret;
0945
0946 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0947 if (!res)
0948 return -ENODEV;
0949
0950 data = of_device_get_match_data(&pdev->dev);
0951 if (!data)
0952 return -ENOTSUPP;
0953
0954 prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL);
0955 if (!prm)
0956 return -ENOMEM;
0957
0958 while (data->base != res->start) {
0959 if (!data->base)
0960 return -EINVAL;
0961 data++;
0962 }
0963
0964 prm->data = data;
0965
0966 prm->base = devm_ioremap_resource(&pdev->dev, res);
0967 if (IS_ERR(prm->base))
0968 return PTR_ERR(prm->base);
0969
0970 ret = omap_prm_domain_init(&pdev->dev, prm);
0971 if (ret)
0972 return ret;
0973
0974 ret = omap_prm_reset_init(pdev, prm);
0975 if (ret)
0976 goto err_domain;
0977
0978 return 0;
0979
0980 err_domain:
0981 of_genpd_del_provider(pdev->dev.of_node);
0982 pm_genpd_remove(&prm->prmd->pd);
0983
0984 return ret;
0985 }
0986
0987 static struct platform_driver omap_prm_driver = {
0988 .probe = omap_prm_probe,
0989 .driver = {
0990 .name = KBUILD_MODNAME,
0991 .of_match_table = omap_prm_id_table,
0992 },
0993 };
0994 builtin_platform_driver(omap_prm_driver);