Loading arch/arm/mach-omap2/pm-debug.c +2 −2 Original line number Diff line number Diff line Loading @@ -551,7 +551,7 @@ static int __init pm_dbg_init(void) (void) debugfs_create_file("time", S_IRUGO, d, (void *)DEBUG_FILE_TIMERS, &debug_fops); pwrdm_for_each(pwrdms_setup, (void *)d); pwrdm_for_each_nolock(pwrdms_setup, (void *)d); pm_dbg_dir = debugfs_create_dir("registers", d); if (IS_ERR(pm_dbg_dir)) Loading arch/arm/mach-omap2/pm34xx.c +106 −81 Original line number Diff line number Diff line Loading @@ -51,97 +51,112 @@ static void (*_omap_sram_idle)(u32 *addr, int save_state); static struct powerdomain *mpu_pwrdm; /* PRCM Interrupt Handler for wakeups */ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) /* * PRCM Interrupt Handler Helper Function * * The purpose of this function is to clear any wake-up events latched * in the PRCM PM_WKST_x registers. It is possible that a wake-up event * may occur whilst attempting to clear a PM_WKST_x register and thus * set another bit in this register. A while loop is used to ensure * that any peripheral wake-up events occurring while attempting to * clear the PM_WKST_x are detected and cleared. */ static int prcm_clear_mod_irqs(s16 module, u8 regs) { u32 wkst, irqstatus_mpu; u32 fclk, iclk; /* WKUP */ wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST); u32 wkst, fclk, iclk, clken; u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1; u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1; u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1; u16 grpsel_off = (regs == 3) ? OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL; int c = 0; wkst = prm_read_mod_reg(module, wkst_off); wkst &= prm_read_mod_reg(module, grpsel_off); if (wkst) { iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN); fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN); cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN); cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN); prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST); while (prm_read_mod_reg(WKUP_MOD, PM_WKST)) cpu_relax(); cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN); cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN); } /* CORE */ wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1); if (wkst) { iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1); fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1); cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1); prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1); while (prm_read_mod_reg(CORE_MOD, PM_WKST1)) cpu_relax(); cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1); cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1); } wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3); if (wkst) { iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3); fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3); cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3); cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3); while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3)) cpu_relax(); cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3); cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); } /* PER */ wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST); if (wkst) { iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN); fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN); cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN); cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN); prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST); while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST)) cpu_relax(); cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN); cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN); iclk = cm_read_mod_reg(module, iclk_off); fclk = cm_read_mod_reg(module, fclk_off); while (wkst) { clken = wkst; cm_set_mod_reg_bits(clken, module, iclk_off); /* * For USBHOST, we don't know whether HOST1 or * HOST2 woke us up, so enable both f-clocks */ if (module == OMAP3430ES2_USBHOST_MOD) clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT; cm_set_mod_reg_bits(clken, module, fclk_off); prm_write_mod_reg(wkst, module, wkst_off); wkst = prm_read_mod_reg(module, wkst_off); c++; } cm_write_mod_reg(iclk, module, iclk_off); cm_write_mod_reg(fclk, module, fclk_off); } return c; } static int _prcm_int_handle_wakeup(void) { int c; c = prcm_clear_mod_irqs(WKUP_MOD, 1); c += prcm_clear_mod_irqs(CORE_MOD, 1); c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1); if (omap_rev() > OMAP3430_REV_ES1_0) { /* USBHOST */ wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST); if (wkst) { iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN); fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN); cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD, CM_ICLKEN); cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD, CM_FCLKEN); prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD, PM_WKST); while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST)) cpu_relax(); cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD, CM_ICLKEN); cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD, CM_FCLKEN); c += prcm_clear_mod_irqs(CORE_MOD, 3); c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1); } return c; } /* * PRCM Interrupt Handler * * The PRM_IRQSTATUS_MPU register indicates if there are any pending * interrupts from the PRCM for the MPU. These bits must be cleared in * order to clear the PRCM interrupt. The PRCM interrupt handler is * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU * register indicates that a wake-up event is pending for the MPU and * this bit can only be cleared if the all the wake-up events latched * in the various PM_WKST_x registers have been cleared. The interrupt * handler is implemented using a do-while loop so that if a wake-up * event occurred during the processing of the prcm interrupt handler * (setting a bit in the corresponding PM_WKST_x register and thus * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register) * this would be handled. */ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) { u32 irqstatus_mpu; int c = 0; do { irqstatus_mpu = prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); if (irqstatus_mpu & (OMAP3430_WKUP_ST | OMAP3430_IO_ST)) { c = _prcm_int_handle_wakeup(); /* * Is the MPU PRCM interrupt handler racing with the * IVA2 PRCM interrupt handler ? */ WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup " "but no wakeup sources are marked\n"); } else { /* XXX we need to expand our PRCM interrupt handler */ WARN(1, "prcm: WARNING: PRCM interrupt received, but " "no code to handle it (%08x)\n", irqstatus_mpu); } prm_write_mod_reg(irqstatus_mpu, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET)) cpu_relax(); } while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET)); return IRQ_HANDLED; } Loading Loading @@ -624,6 +639,16 @@ static void __init prcm_setup_regs(void) prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); /* Enable GPIO wakeups in PER */ prm_write_mod_reg(OMAP3430_EN_GPIO2 | OMAP3430_EN_GPIO3 | OMAP3430_EN_GPIO4 | OMAP3430_EN_GPIO5 | OMAP3430_EN_GPIO6, OMAP3430_PER_MOD, PM_WKEN); /* and allow them to wake up MPU */ prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2 | OMAP3430_EN_GPIO3 | OMAP3430_GRPSEL_GPIO4 | OMAP3430_EN_GPIO5 | OMAP3430_GRPSEL_GPIO6, OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL); /* Don't attach IVA interrupts */ prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL); prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1); Loading arch/arm/mach-omap2/powerdomain.c +27 −12 Original line number Diff line number Diff line Loading @@ -273,35 +273,50 @@ struct powerdomain *pwrdm_lookup(const char *name) } /** * pwrdm_for_each - call function on each registered clockdomain * pwrdm_for_each_nolock - call function on each registered clockdomain * @fn: callback function * * * Call the supplied function for each registered powerdomain. The * callback function can return anything but 0 to bail out early from * the iterator. The callback function is called with the pwrdm_rwlock * held for reading, so no powerdomain structure manipulation * functions should be called from the callback, although hardware * powerdomain control functions are fine. Returns the last return * value of the callback function, which should be 0 for success or * anything else to indicate failure; or -EINVAL if the function * pointer is null. * the iterator. Returns the last return value of the callback function, which * should be 0 for success or anything else to indicate failure; or -EINVAL if * the function pointer is null. */ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user), void *user) { struct powerdomain *temp_pwrdm; unsigned long flags; int ret = 0; if (!fn) return -EINVAL; read_lock_irqsave(&pwrdm_rwlock, flags); list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { ret = (*fn)(temp_pwrdm, user); if (ret) break; } return ret; } /** * pwrdm_for_each - call function on each registered clockdomain * @fn: callback function * * * This function is the same as 'pwrdm_for_each_nolock()', but keeps the * &pwrdm_rwlock locked for reading, so no powerdomain structure manipulation * functions should be called from the callback, although hardware powerdomain * control functions are fine. */ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), void *user) { unsigned long flags; int ret; read_lock_irqsave(&pwrdm_rwlock, flags); ret = pwrdm_for_each_nolock(fn, user); read_unlock_irqrestore(&pwrdm_rwlock, flags); return ret; Loading arch/arm/plat-omap/include/mach/powerdomain.h +2 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,8 @@ struct powerdomain *pwrdm_lookup(const char *name); int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), void *user); int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user), void *user); int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); Loading Loading
arch/arm/mach-omap2/pm-debug.c +2 −2 Original line number Diff line number Diff line Loading @@ -551,7 +551,7 @@ static int __init pm_dbg_init(void) (void) debugfs_create_file("time", S_IRUGO, d, (void *)DEBUG_FILE_TIMERS, &debug_fops); pwrdm_for_each(pwrdms_setup, (void *)d); pwrdm_for_each_nolock(pwrdms_setup, (void *)d); pm_dbg_dir = debugfs_create_dir("registers", d); if (IS_ERR(pm_dbg_dir)) Loading
arch/arm/mach-omap2/pm34xx.c +106 −81 Original line number Diff line number Diff line Loading @@ -51,97 +51,112 @@ static void (*_omap_sram_idle)(u32 *addr, int save_state); static struct powerdomain *mpu_pwrdm; /* PRCM Interrupt Handler for wakeups */ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) /* * PRCM Interrupt Handler Helper Function * * The purpose of this function is to clear any wake-up events latched * in the PRCM PM_WKST_x registers. It is possible that a wake-up event * may occur whilst attempting to clear a PM_WKST_x register and thus * set another bit in this register. A while loop is used to ensure * that any peripheral wake-up events occurring while attempting to * clear the PM_WKST_x are detected and cleared. */ static int prcm_clear_mod_irqs(s16 module, u8 regs) { u32 wkst, irqstatus_mpu; u32 fclk, iclk; /* WKUP */ wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST); u32 wkst, fclk, iclk, clken; u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1; u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1; u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1; u16 grpsel_off = (regs == 3) ? OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL; int c = 0; wkst = prm_read_mod_reg(module, wkst_off); wkst &= prm_read_mod_reg(module, grpsel_off); if (wkst) { iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN); fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN); cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN); cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN); prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST); while (prm_read_mod_reg(WKUP_MOD, PM_WKST)) cpu_relax(); cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN); cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN); } /* CORE */ wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1); if (wkst) { iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1); fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1); cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1); prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1); while (prm_read_mod_reg(CORE_MOD, PM_WKST1)) cpu_relax(); cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1); cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1); } wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3); if (wkst) { iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3); fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3); cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3); cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3); while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3)) cpu_relax(); cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3); cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); } /* PER */ wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST); if (wkst) { iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN); fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN); cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN); cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN); prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST); while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST)) cpu_relax(); cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN); cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN); iclk = cm_read_mod_reg(module, iclk_off); fclk = cm_read_mod_reg(module, fclk_off); while (wkst) { clken = wkst; cm_set_mod_reg_bits(clken, module, iclk_off); /* * For USBHOST, we don't know whether HOST1 or * HOST2 woke us up, so enable both f-clocks */ if (module == OMAP3430ES2_USBHOST_MOD) clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT; cm_set_mod_reg_bits(clken, module, fclk_off); prm_write_mod_reg(wkst, module, wkst_off); wkst = prm_read_mod_reg(module, wkst_off); c++; } cm_write_mod_reg(iclk, module, iclk_off); cm_write_mod_reg(fclk, module, fclk_off); } return c; } static int _prcm_int_handle_wakeup(void) { int c; c = prcm_clear_mod_irqs(WKUP_MOD, 1); c += prcm_clear_mod_irqs(CORE_MOD, 1); c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1); if (omap_rev() > OMAP3430_REV_ES1_0) { /* USBHOST */ wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST); if (wkst) { iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN); fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN); cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD, CM_ICLKEN); cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD, CM_FCLKEN); prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD, PM_WKST); while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST)) cpu_relax(); cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD, CM_ICLKEN); cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD, CM_FCLKEN); c += prcm_clear_mod_irqs(CORE_MOD, 3); c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1); } return c; } /* * PRCM Interrupt Handler * * The PRM_IRQSTATUS_MPU register indicates if there are any pending * interrupts from the PRCM for the MPU. These bits must be cleared in * order to clear the PRCM interrupt. The PRCM interrupt handler is * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU * register indicates that a wake-up event is pending for the MPU and * this bit can only be cleared if the all the wake-up events latched * in the various PM_WKST_x registers have been cleared. The interrupt * handler is implemented using a do-while loop so that if a wake-up * event occurred during the processing of the prcm interrupt handler * (setting a bit in the corresponding PM_WKST_x register and thus * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register) * this would be handled. */ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) { u32 irqstatus_mpu; int c = 0; do { irqstatus_mpu = prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); if (irqstatus_mpu & (OMAP3430_WKUP_ST | OMAP3430_IO_ST)) { c = _prcm_int_handle_wakeup(); /* * Is the MPU PRCM interrupt handler racing with the * IVA2 PRCM interrupt handler ? */ WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup " "but no wakeup sources are marked\n"); } else { /* XXX we need to expand our PRCM interrupt handler */ WARN(1, "prcm: WARNING: PRCM interrupt received, but " "no code to handle it (%08x)\n", irqstatus_mpu); } prm_write_mod_reg(irqstatus_mpu, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET)) cpu_relax(); } while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET)); return IRQ_HANDLED; } Loading Loading @@ -624,6 +639,16 @@ static void __init prcm_setup_regs(void) prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); /* Enable GPIO wakeups in PER */ prm_write_mod_reg(OMAP3430_EN_GPIO2 | OMAP3430_EN_GPIO3 | OMAP3430_EN_GPIO4 | OMAP3430_EN_GPIO5 | OMAP3430_EN_GPIO6, OMAP3430_PER_MOD, PM_WKEN); /* and allow them to wake up MPU */ prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2 | OMAP3430_EN_GPIO3 | OMAP3430_GRPSEL_GPIO4 | OMAP3430_EN_GPIO5 | OMAP3430_GRPSEL_GPIO6, OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL); /* Don't attach IVA interrupts */ prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL); prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1); Loading
arch/arm/mach-omap2/powerdomain.c +27 −12 Original line number Diff line number Diff line Loading @@ -273,35 +273,50 @@ struct powerdomain *pwrdm_lookup(const char *name) } /** * pwrdm_for_each - call function on each registered clockdomain * pwrdm_for_each_nolock - call function on each registered clockdomain * @fn: callback function * * * Call the supplied function for each registered powerdomain. The * callback function can return anything but 0 to bail out early from * the iterator. The callback function is called with the pwrdm_rwlock * held for reading, so no powerdomain structure manipulation * functions should be called from the callback, although hardware * powerdomain control functions are fine. Returns the last return * value of the callback function, which should be 0 for success or * anything else to indicate failure; or -EINVAL if the function * pointer is null. * the iterator. Returns the last return value of the callback function, which * should be 0 for success or anything else to indicate failure; or -EINVAL if * the function pointer is null. */ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user), void *user) { struct powerdomain *temp_pwrdm; unsigned long flags; int ret = 0; if (!fn) return -EINVAL; read_lock_irqsave(&pwrdm_rwlock, flags); list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { ret = (*fn)(temp_pwrdm, user); if (ret) break; } return ret; } /** * pwrdm_for_each - call function on each registered clockdomain * @fn: callback function * * * This function is the same as 'pwrdm_for_each_nolock()', but keeps the * &pwrdm_rwlock locked for reading, so no powerdomain structure manipulation * functions should be called from the callback, although hardware powerdomain * control functions are fine. */ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), void *user) { unsigned long flags; int ret; read_lock_irqsave(&pwrdm_rwlock, flags); ret = pwrdm_for_each_nolock(fn, user); read_unlock_irqrestore(&pwrdm_rwlock, flags); return ret; Loading
arch/arm/plat-omap/include/mach/powerdomain.h +2 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,8 @@ struct powerdomain *pwrdm_lookup(const char *name); int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), void *user); int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user), void *user); int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); Loading