1 /* 2 * OMAP2+ common Power & Reset Management (PRM) IP block functions 3 * 4 * Copyright (C) 2011 Texas Instruments, Inc. 5 * Tero Kristo <t-kristo@ti.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * 12 * For historical purposes, the API used to configure the PRM 13 * interrupt handler refers to it as the "PRCM interrupt." The 14 * underlying registers are located in the PRM on OMAP3/4. 15 * 16 * XXX This code should eventually be moved to a PRM driver. 17 */ 18 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/init.h> 22 #include <linux/io.h> 23 #include <linux/irq.h> 24 #include <linux/interrupt.h> 25 #include <linux/slab.h> 26 27 #include "soc.h" 28 #include "prm2xxx_3xxx.h" 29 #include "prm2xxx.h" 30 #include "prm3xxx.h" 31 #include "prm44xx.h" 32 #include "common.h" 33 34 /* 35 * OMAP_PRCM_MAX_NR_PENDING_REG: maximum number of PRM_IRQ*_MPU regs 36 * XXX this is technically not needed, since 37 * omap_prcm_register_chain_handler() could allocate this based on the 38 * actual amount of memory needed for the SoC 39 */ 40 #define OMAP_PRCM_MAX_NR_PENDING_REG 2 41 42 /* 43 * prcm_irq_chips: an array of all of the "generic IRQ chips" in use 44 * by the PRCM interrupt handler code. There will be one 'chip' per 45 * PRM_{IRQSTATUS,IRQENABLE}_MPU register pair. (So OMAP3 will have 46 * one "chip" and OMAP4 will have two.) 47 */ 48 static struct irq_chip_generic **prcm_irq_chips; 49 50 /* 51 * prcm_irq_setup: the PRCM IRQ parameters for the hardware the code 52 * is currently running on. Defined and passed by initialization code 53 * that calls omap_prcm_register_chain_handler(). 54 */ 55 static struct omap_prcm_irq_setup *prcm_irq_setup; 56 57 /* prm_base: base virtual address of the PRM IP block */ 58 void __iomem *prm_base; 59 60 /* 61 * prm_ll_data: function pointers to SoC-specific implementations of 62 * common PRM functions 63 */ 64 static struct prm_ll_data null_prm_ll_data; 65 static struct prm_ll_data *prm_ll_data = &null_prm_ll_data; 66 67 /* Private functions */ 68 69 /* 70 * Move priority events from events to priority_events array 71 */ 72 static void omap_prcm_events_filter_priority(unsigned long *events, 73 unsigned long *priority_events) 74 { 75 int i; 76 77 for (i = 0; i < prcm_irq_setup->nr_regs; i++) { 78 priority_events[i] = 79 events[i] & prcm_irq_setup->priority_mask[i]; 80 events[i] ^= priority_events[i]; 81 } 82 } 83 84 /* 85 * PRCM Interrupt Handler 86 * 87 * This is a common handler for the OMAP PRCM interrupts. Pending 88 * interrupts are detected by a call to prcm_pending_events and 89 * dispatched accordingly. Clearing of the wakeup events should be 90 * done by the SoC specific individual handlers. 91 */ 92 static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc) 93 { 94 unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG]; 95 unsigned long priority_pending[OMAP_PRCM_MAX_NR_PENDING_REG]; 96 struct irq_chip *chip = irq_desc_get_chip(desc); 97 unsigned int virtirq; 98 int nr_irq = prcm_irq_setup->nr_regs * 32; 99 100 /* 101 * If we are suspended, mask all interrupts from PRCM level, 102 * this does not ack them, and they will be pending until we 103 * re-enable the interrupts, at which point the 104 * omap_prcm_irq_handler will be executed again. The 105 * _save_and_clear_irqen() function must ensure that the PRM 106 * write to disable all IRQs has reached the PRM before 107 * returning, or spurious PRCM interrupts may occur during 108 * suspend. 109 */ 110 if (prcm_irq_setup->suspended) { 111 prcm_irq_setup->save_and_clear_irqen(prcm_irq_setup->saved_mask); 112 prcm_irq_setup->suspend_save_flag = true; 113 } 114 115 /* 116 * Loop until all pending irqs are handled, since 117 * generic_handle_irq() can cause new irqs to come 118 */ 119 while (!prcm_irq_setup->suspended) { 120 prcm_irq_setup->read_pending_irqs(pending); 121 122 /* No bit set, then all IRQs are handled */ 123 if (find_first_bit(pending, nr_irq) >= nr_irq) 124 break; 125 126 omap_prcm_events_filter_priority(pending, priority_pending); 127 128 /* 129 * Loop on all currently pending irqs so that new irqs 130 * cannot starve previously pending irqs 131 */ 132 133 /* Serve priority events first */ 134 for_each_set_bit(virtirq, priority_pending, nr_irq) 135 generic_handle_irq(prcm_irq_setup->base_irq + virtirq); 136 137 /* Serve normal events next */ 138 for_each_set_bit(virtirq, pending, nr_irq) 139 generic_handle_irq(prcm_irq_setup->base_irq + virtirq); 140 } 141 if (chip->irq_ack) 142 chip->irq_ack(&desc->irq_data); 143 if (chip->irq_eoi) 144 chip->irq_eoi(&desc->irq_data); 145 chip->irq_unmask(&desc->irq_data); 146 147 prcm_irq_setup->ocp_barrier(); /* avoid spurious IRQs */ 148 } 149 150 /* Public functions */ 151 152 /** 153 * omap_prcm_event_to_irq - given a PRCM event name, returns the 154 * corresponding IRQ on which the handler should be registered 155 * @name: name of the PRCM interrupt bit to look up - see struct omap_prcm_irq 156 * 157 * Returns the Linux internal IRQ ID corresponding to @name upon success, 158 * or -ENOENT upon failure. 159 */ 160 int omap_prcm_event_to_irq(const char *name) 161 { 162 int i; 163 164 if (!prcm_irq_setup || !name) 165 return -ENOENT; 166 167 for (i = 0; i < prcm_irq_setup->nr_irqs; i++) 168 if (!strcmp(prcm_irq_setup->irqs[i].name, name)) 169 return prcm_irq_setup->base_irq + 170 prcm_irq_setup->irqs[i].offset; 171 172 return -ENOENT; 173 } 174 175 /** 176 * omap_prcm_irq_cleanup - reverses memory allocated and other steps 177 * done by omap_prcm_register_chain_handler() 178 * 179 * No return value. 180 */ 181 void omap_prcm_irq_cleanup(void) 182 { 183 int i; 184 185 if (!prcm_irq_setup) { 186 pr_err("PRCM: IRQ handler not initialized; cannot cleanup\n"); 187 return; 188 } 189 190 if (prcm_irq_chips) { 191 for (i = 0; i < prcm_irq_setup->nr_regs; i++) { 192 if (prcm_irq_chips[i]) 193 irq_remove_generic_chip(prcm_irq_chips[i], 194 0xffffffff, 0, 0); 195 prcm_irq_chips[i] = NULL; 196 } 197 kfree(prcm_irq_chips); 198 prcm_irq_chips = NULL; 199 } 200 201 kfree(prcm_irq_setup->saved_mask); 202 prcm_irq_setup->saved_mask = NULL; 203 204 kfree(prcm_irq_setup->priority_mask); 205 prcm_irq_setup->priority_mask = NULL; 206 207 irq_set_chained_handler(prcm_irq_setup->irq, NULL); 208 209 if (prcm_irq_setup->base_irq > 0) 210 irq_free_descs(prcm_irq_setup->base_irq, 211 prcm_irq_setup->nr_regs * 32); 212 prcm_irq_setup->base_irq = 0; 213 } 214 215 void omap_prcm_irq_prepare(void) 216 { 217 prcm_irq_setup->suspended = true; 218 } 219 220 void omap_prcm_irq_complete(void) 221 { 222 prcm_irq_setup->suspended = false; 223 224 /* If we have not saved the masks, do not attempt to restore */ 225 if (!prcm_irq_setup->suspend_save_flag) 226 return; 227 228 prcm_irq_setup->suspend_save_flag = false; 229 230 /* 231 * Re-enable all masked PRCM irq sources, this causes the PRCM 232 * interrupt to fire immediately if the events were masked 233 * previously in the chain handler 234 */ 235 prcm_irq_setup->restore_irqen(prcm_irq_setup->saved_mask); 236 } 237 238 /** 239 * omap_prcm_register_chain_handler - initializes the prcm chained interrupt 240 * handler based on provided parameters 241 * @irq_setup: hardware data about the underlying PRM/PRCM 242 * 243 * Set up the PRCM chained interrupt handler on the PRCM IRQ. Sets up 244 * one generic IRQ chip per PRM interrupt status/enable register pair. 245 * Returns 0 upon success, -EINVAL if called twice or if invalid 246 * arguments are passed, or -ENOMEM on any other error. 247 */ 248 int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup) 249 { 250 int nr_regs; 251 u32 mask[OMAP_PRCM_MAX_NR_PENDING_REG]; 252 int offset, i; 253 struct irq_chip_generic *gc; 254 struct irq_chip_type *ct; 255 256 if (!irq_setup) 257 return -EINVAL; 258 259 nr_regs = irq_setup->nr_regs; 260 261 if (prcm_irq_setup) { 262 pr_err("PRCM: already initialized; won't reinitialize\n"); 263 return -EINVAL; 264 } 265 266 if (nr_regs > OMAP_PRCM_MAX_NR_PENDING_REG) { 267 pr_err("PRCM: nr_regs too large\n"); 268 return -EINVAL; 269 } 270 271 prcm_irq_setup = irq_setup; 272 273 prcm_irq_chips = kzalloc(sizeof(void *) * nr_regs, GFP_KERNEL); 274 prcm_irq_setup->saved_mask = kzalloc(sizeof(u32) * nr_regs, GFP_KERNEL); 275 prcm_irq_setup->priority_mask = kzalloc(sizeof(u32) * nr_regs, 276 GFP_KERNEL); 277 278 if (!prcm_irq_chips || !prcm_irq_setup->saved_mask || 279 !prcm_irq_setup->priority_mask) { 280 pr_err("PRCM: kzalloc failed\n"); 281 goto err; 282 } 283 284 memset(mask, 0, sizeof(mask)); 285 286 for (i = 0; i < irq_setup->nr_irqs; i++) { 287 offset = irq_setup->irqs[i].offset; 288 mask[offset >> 5] |= 1 << (offset & 0x1f); 289 if (irq_setup->irqs[i].priority) 290 irq_setup->priority_mask[offset >> 5] |= 291 1 << (offset & 0x1f); 292 } 293 294 irq_set_chained_handler(irq_setup->irq, omap_prcm_irq_handler); 295 296 irq_setup->base_irq = irq_alloc_descs(-1, 0, irq_setup->nr_regs * 32, 297 0); 298 299 if (irq_setup->base_irq < 0) { 300 pr_err("PRCM: failed to allocate irq descs: %d\n", 301 irq_setup->base_irq); 302 goto err; 303 } 304 305 for (i = 0; i < irq_setup->nr_regs; i++) { 306 gc = irq_alloc_generic_chip("PRCM", 1, 307 irq_setup->base_irq + i * 32, prm_base, 308 handle_level_irq); 309 310 if (!gc) { 311 pr_err("PRCM: failed to allocate generic chip\n"); 312 goto err; 313 } 314 ct = gc->chip_types; 315 ct->chip.irq_ack = irq_gc_ack_set_bit; 316 ct->chip.irq_mask = irq_gc_mask_clr_bit; 317 ct->chip.irq_unmask = irq_gc_mask_set_bit; 318 319 ct->regs.ack = irq_setup->ack + i * 4; 320 ct->regs.mask = irq_setup->mask + i * 4; 321 322 irq_setup_generic_chip(gc, mask[i], 0, IRQ_NOREQUEST, 0); 323 prcm_irq_chips[i] = gc; 324 } 325 326 if (of_have_populated_dt()) { 327 int irq = omap_prcm_event_to_irq("io"); 328 if (cpu_is_omap34xx()) 329 omap_pcs_legacy_init(irq, 330 omap3xxx_prm_reconfigure_io_chain); 331 else 332 omap_pcs_legacy_init(irq, 333 omap44xx_prm_reconfigure_io_chain); 334 } 335 336 return 0; 337 338 err: 339 omap_prcm_irq_cleanup(); 340 return -ENOMEM; 341 } 342 343 /** 344 * omap2_set_globals_prm - set the PRM base address (for early use) 345 * @prm: PRM base virtual address 346 * 347 * XXX Will be replaced when the PRM/CM drivers are completed. 348 */ 349 void __init omap2_set_globals_prm(void __iomem *prm) 350 { 351 prm_base = prm; 352 } 353 354 /** 355 * prm_read_reset_sources - return the sources of the SoC's last reset 356 * 357 * Return a u32 bitmask representing the reset sources that caused the 358 * SoC to reset. The low-level per-SoC functions called by this 359 * function remap the SoC-specific reset source bits into an 360 * OMAP-common set of reset source bits, defined in 361 * arch/arm/mach-omap2/prm.h. Returns the standardized reset source 362 * u32 bitmask from the hardware upon success, or returns (1 << 363 * OMAP_UNKNOWN_RST_SRC_ID_SHIFT) if no low-level read_reset_sources() 364 * function was registered. 365 */ 366 u32 prm_read_reset_sources(void) 367 { 368 u32 ret = 1 << OMAP_UNKNOWN_RST_SRC_ID_SHIFT; 369 370 if (prm_ll_data->read_reset_sources) 371 ret = prm_ll_data->read_reset_sources(); 372 else 373 WARN_ONCE(1, "prm: %s: no mapping function defined for reset sources\n", __func__); 374 375 return ret; 376 } 377 378 /** 379 * prm_was_any_context_lost_old - was device context lost? (old API) 380 * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION) 381 * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST) 382 * @idx: CONTEXT register offset 383 * 384 * Return 1 if any bits were set in the *_CONTEXT_* register 385 * identified by (@part, @inst, @idx), which means that some context 386 * was lost for that module; otherwise, return 0. XXX Deprecated; 387 * callers need to use a less-SoC-dependent way to identify hardware 388 * IP blocks. 389 */ 390 bool prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx) 391 { 392 bool ret = true; 393 394 if (prm_ll_data->was_any_context_lost_old) 395 ret = prm_ll_data->was_any_context_lost_old(part, inst, idx); 396 else 397 WARN_ONCE(1, "prm: %s: no mapping function defined\n", 398 __func__); 399 400 return ret; 401 } 402 403 /** 404 * prm_clear_context_lost_flags_old - clear context loss flags (old API) 405 * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION) 406 * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST) 407 * @idx: CONTEXT register offset 408 * 409 * Clear hardware context loss bits for the module identified by 410 * (@part, @inst, @idx). No return value. XXX Deprecated; callers 411 * need to use a less-SoC-dependent way to identify hardware IP 412 * blocks. 413 */ 414 void prm_clear_context_loss_flags_old(u8 part, s16 inst, u16 idx) 415 { 416 if (prm_ll_data->clear_context_loss_flags_old) 417 prm_ll_data->clear_context_loss_flags_old(part, inst, idx); 418 else 419 WARN_ONCE(1, "prm: %s: no mapping function defined\n", 420 __func__); 421 } 422 423 /** 424 * prm_register - register per-SoC low-level data with the PRM 425 * @pld: low-level per-SoC OMAP PRM data & function pointers to register 426 * 427 * Register per-SoC low-level OMAP PRM data and function pointers with 428 * the OMAP PRM common interface. The caller must keep the data 429 * pointed to by @pld valid until it calls prm_unregister() and 430 * it returns successfully. Returns 0 upon success, -EINVAL if @pld 431 * is NULL, or -EEXIST if prm_register() has already been called 432 * without an intervening prm_unregister(). 433 */ 434 int prm_register(struct prm_ll_data *pld) 435 { 436 if (!pld) 437 return -EINVAL; 438 439 if (prm_ll_data != &null_prm_ll_data) 440 return -EEXIST; 441 442 prm_ll_data = pld; 443 444 return 0; 445 } 446 447 /** 448 * prm_unregister - unregister per-SoC low-level data & function pointers 449 * @pld: low-level per-SoC OMAP PRM data & function pointers to unregister 450 * 451 * Unregister per-SoC low-level OMAP PRM data and function pointers 452 * that were previously registered with prm_register(). The 453 * caller may not destroy any of the data pointed to by @pld until 454 * this function returns successfully. Returns 0 upon success, or 455 * -EINVAL if @pld is NULL or if @pld does not match the struct 456 * prm_ll_data * previously registered by prm_register(). 457 */ 458 int prm_unregister(struct prm_ll_data *pld) 459 { 460 if (!pld || prm_ll_data != pld) 461 return -EINVAL; 462 463 prm_ll_data = &null_prm_ll_data; 464 465 return 0; 466 } 467