Re: [linux-pm] pm loss development

From: Raffaele Recalcati
Date: Sat May 14 2011 - 16:30:40 EST


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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/