On Sat, May 14, 2011 at 6:24 PM, mark gross <markgross@xxxxxxxxxxx> wrote: > On Thu, May 12, 2011 at 07:11:01PM +0200, Raffaele Recalcati wrote: >> What happen normally in runtime pm implementation is that every devices >> are switched off and are enabled only when needed. >> In our case instead we have a completely functional embedded system and, >> when an asyncrhonous event appear, we have only some tens milliseconds >> before the actual power failure takes place. > > Very interesting! ÂI've been worried about a similar failure on battery > driven devices that can experience significant voltage droops when > battery gets old, or low, and we turn on the flashlight led, vibrator > and make the screen bright while a high volume ring tone gets played. > > I think 10ms is a bit unrealistic. ÂI think its more like 300uSec before > you hit brown out. In our circuit it is the real timing, but I can understand your situation. Are you sure about 300usec? >> This patchset add a support in order to switch off not vital part of the system, >> in order to allow the board to survive longer. >> This allow the possibility to save important data. >> >> The implementation has been written by Davide Ciminaghi. >> My work instead was about analyzing different previuos implementation, >> a first completely custom one, a second using runtime pm, arriving >> finally to that one. >> >> I have tested PM loss in our DaVinci dm365 basi board and I write here below a >> piece of code showing a possible usage. >> >> ------------------- >> >> static int powerfail_status; >> >> static irqreturn_t basi_powerfail_stop(int irq, void *dev_id); >> >> static irqreturn_t basi_powerfail_quick_check_start(int irq, void *dev_id) >> { >> Â Â Â Â basi_mask_irq_gpio0(IRQ_DM365_GPIO0_2); >> Â Â Â Â basi_unmask_irq_gpio0(IRQ_DM365_GPIO0_0); >> >> Â Â Â Â /* PowerFail situation - START: power is going away */ >> Â Â Â Â return IRQ_WAKE_THREAD; >> } >> >> static irqreturn_t basi_powerfail_start(int irq, void *dev_id) >> { >> Â Â Â Â if (powerfail_status) >> Â Â Â Â Â Â Â Â return IRQ_HANDLED; >> Â Â Â Â powerfail_status = 1; >> Â Â Â Â pm_loss_power_changed(SYS_PWR_FAILING); >> Â Â Â Â return IRQ_HANDLED; >> } >> >> >> static irqreturn_t basi_powerfail_quick_check_stop(int irq, void *dev_id) >> { >> Â Â Â Â basi_mask_irq_gpio0(IRQ_DM365_GPIO0_0); >> Â Â Â Â basi_unmask_irq_gpio0(IRQ_DM365_GPIO0_2); >> >> Â Â Â Â /* PowerFail situation - STOP: power is coming back */ >> Â Â Â Â return IRQ_WAKE_THREAD; >> } >> >> static irqreturn_t basi_powerfail_stop(int irq, void *dev_id) >> { >> Â Â Â Â if (!powerfail_status) >> Â Â Â Â Â Â Â Â return IRQ_HANDLED; >> Â Â Â Â powerfail_status = 0; >> Â Â Â Â pm_loss_power_changed(SYS_PWR_GOOD); >> Â Â Â Â return IRQ_HANDLED; >> } >> >> enum basi_pwrfail_prio { >> Â Â Â Â BASI_PWR_FAIL_PRIO_0, >> Â Â Â Â BASI_PWR_FAIL_MIN_PRIO = BASI_PWR_FAIL_PRIO_0, >> Â Â Â Â BASI_PWR_FAIL_PRIO_1, >> Â Â Â Â BASI_PWR_FAIL_PRIO_2, >> Â Â Â Â BASI_PWR_FAIL_PRIO_3, >> Â Â Â Â BASI_PWR_FAIL_MAX_PRIO = BASI_PWR_FAIL_PRIO_3, >> }; >> >> struct pm_loss_default_policy_item basi_pm_loss_policy_items[] = { >> Â Â Â Â { >> Â Â Â Â Â Â Â Â .bus_name = "mmc", >> Â Â Â Â Â Â Â Â .bus_priority = BASI_PWR_FAIL_PRIO_1, >> Â Â Â Â }, >> Â Â Â Â { >> Â Â Â Â Â Â Â Â .bus_name = "platform", >> Â Â Â Â Â Â Â Â .bus_priority = BASI_PWR_FAIL_PRIO_2, >> Â Â Â Â }, >> }; >> >> #define BASI_POLICY_NAME "basi-default" >> >> struct pm_loss_default_policy_table basi_pm_loss_policy_table = { >> Â Â Â Â .name = BASI_POLICY_NAME, >> Â Â Â Â .items = basi_pm_loss_policy_items, >> Â Â Â Â .nitems = ARRAY_SIZE(basi_pm_loss_policy_items), >> }; >> >> static void basi_powerfail_configure(void) >> { >> Â Â Â Â int stat; >> Â Â Â Â struct pm_loss_policy *p; >> Â Â Â Â stat = request_threaded_irq(IRQ_DM365_GPIO0_2, > Is this some comparator device that tugs on this gpio when the voltage > drops or goes to 0? ÂIs threaded irq fast enough? yes, there is a comparator. I need more data about timing, I'll try to add this info in some days. > Could we consider something that includes a hot path ISR based > notification call back to do stuff like blink off devices that don't > need to save state; Âbacklights, vibrators, flashlight LEDs, audio > output drivers <-- I'm not sure about audio HW, and then a slower path > for other things that can be put into lower power states? > > the all-clear notification that power is good again should be on a > slower path I would assume. First I get data, afterwards we can see if your need can be seen as an extension or something else. > > --mark > >> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â basi_powerfail_quick_check_start, >> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â basi_powerfail_start, >> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, >> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â "pwrfail-on", NULL); >> Â Â Â Â if (stat < 0) >> Â Â Â Â Â Â Â Â printk(KERN_ERR "request_threaded_irq for IRQ%d (pwrfail-on) " >> Â Â Â Â Â Â Â Â Â Â Â Â"failed\n", IRQ_DM365_GPIO0_2); >> Â Â Â Â stat = request_threaded_irq(IRQ_DM365_GPIO0_0, >> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â basi_powerfail_quick_check_stop, >> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â basi_powerfail_stop, 0, >> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â "pwrfail-off", NULL); >> Â Â Â Â if (stat < 0) >> Â Â Â Â Â Â Â Â printk(KERN_ERR "request_threaded_irq for IRQ%d (pwrfail-off) " >> Â Â Â Â Â Â Â Â Â Â Â Â"failed\n", IRQ_DM365_GPIO0_0); >> Â Â Â Â basi_mask_irq_gpio0(IRQ_DM365_GPIO0_0); >> Â Â Â Â p = pm_loss_setup_default_policy(&basi_pm_loss_policy_table); >> >> Â Â Â Â if (!p) >> Â Â Â Â Â Â Â Â printk(KERN_ERR "Could not register pwr change policy\n"); >> >> Â Â Â Â if (pm_loss_set_policy(BASI_POLICY_NAME) < 0) >> Â Â Â Â Â Â Â Â printk(KERN_ERR "Could not set %s power loss policy\n", >> Â Â Â Â Â Â Â Â Â Â Â ÂBASI_POLICY_NAME); >> } >> >> int platform_pm_loss_power_changed(struct device *dev, >> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âenum sys_power_state s) >> { >> Â Â Â Â int ret = 0; >> >> Â Â Â Â /* Calling platform bus pm_loss functions */ >> Â Â Â Â pr_debug_pm_loss("platform_pm_loss_power_changed(%d)\n", s); >> >> Â Â Â Â if (dev->driver && dev->driver->pm && >> Â Â Â Â Â Â Â Â dev->driver->pm->power_changed) >> Â Â Â Â Â Â Â Â ret = dev->driver->pm->power_changed(dev, s); >> Â Â Â Â return ret; >> } >> >> >> >> >> _______________________________________________ >> linux-pm mailing list >> linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx >> https://lists.linux-foundation.org/mailman/listinfo/linux-pm > Bye, Raffaele _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm