linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w)
@ 2006-12-17 19:30 Paul Sokolovsky
  2006-12-18  4:28 ` David Brownell
  0 siblings, 1 reply; 7+ messages in thread
From: Paul Sokolovsky @ 2006-12-17 19:30 UTC (permalink / raw)
  To: linux-kernel, kernel-discuss; +Cc: David Brownell, Richard Purdie

Hello linux-kernel,

Informal part
=============

    Small battery-powered systems, like PDAs, need a way to be
suspended most of the time and woken up just from time to time to
process pending tasks. Obvious way to achieve this is to use timer, or
alarm, wakeup. Unfortunately, this matter is bit confusing in Linux.
There's only one "good" "supported" way to set alarm - via ioctl() on
an RTC device fd. Unfortunately, this alarm is not persistent - as soon
as fd is closed, alarm id discharged. So, this calls for a daemon to
hold RTC fd all the time, IPC to it, etc. This may be just too
cumbersome for all tasks and for small devices, especially if we
talk solely about *wakeup* alarm.

    In this respect, I found insightful communication between David
Brownell and Russell King:

http://lkml.org/lkml/2006/11/20/311
http://lkml.org/lkml/2006/11/20/326
http://lkml.org/lkml/2006/11/20/371

    David's patch addresses exactly PDAs' need, so please count
another vote for it (except that I here have patch to address
his TODO, and which doesn't remove useful /proc data ;-) ).

    What's left after this is a nice way to set a wakeup alarm. The
patch below is initial try to implement it.

Formal part
===========

Implement "alarm" attribute group for RTC classdevs. At this time,
add "since_epoch", "wakeup_enabled", and "pending" attributes. First
two support both read and write.

Signed-off-by: Paul Sokolovsky <pmiscml@gmail.com>


Index: drivers/rtc/rtc-sysfs.c
===================================================================
RCS file: /cvs/linux/kernel26/drivers/rtc/rtc-sysfs.c,v
retrieving revision 1.3
diff -u -r1.3 rtc-sysfs.c
--- drivers/rtc/rtc-sysfs.c     17 Dec 2006 19:07:14 -0000      1.3
+++ drivers/rtc/rtc-sysfs.c     17 Dec 2006 19:09:49 -0000
@@ -66,6 +66,90 @@
 }
 static CLASS_DEVICE_ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL);
 
+
+static ssize_t rtc_sysfs_show_alarm_since_epoch(struct class_device *dev, char *buf)
+{
+       ssize_t retval;
+       struct rtc_wkalrm alrm;
+
+       retval = rtc_read_alarm(dev, &alrm);
+       if (retval == 0) {
+               unsigned long time;
+               rtc_tm_to_time(&alrm.time, &time);
+               retval = sprintf(buf, "%lu\n", time);
+       }
+
+       return retval;
+}
+
+static ssize_t rtc_sysfs_store_alarm_since_epoch(struct class_device *dev, const char *buf, size_t count)
+{
+       ssize_t retval;
+       struct rtc_wkalrm alrm;
+
+       unsigned long time = simple_strtoul(buf, NULL, 0);
+
+       retval = rtc_read_alarm(dev, &alrm);
+       if (retval)
+               return retval;
+       rtc_time_to_tm(time, &alrm.time);
+       retval = rtc_set_alarm(dev, &alrm);
+       if (retval)
+               return retval;
+
+       return count;
+}
+/* Use sysfs attribute name consistent with clock's */
+struct class_device_attribute class_device_attr_alarm_since_epoch = \
+       __ATTR(since_epoch, 0644 ,rtc_sysfs_show_alarm_since_epoch, rtc_sysfs_store_alarm_since_epoch);
+
+static ssize_t rtc_sysfs_show_alarm_wakeup_enabled(struct class_device *dev, char *buf)
+{
+       ssize_t retval;
+       struct rtc_wkalrm alrm;
+
+       retval = rtc_read_alarm(dev, &alrm);
+       if (retval == 0) {
+               retval = sprintf(buf, "%d\n", alrm.enabled);
+       }
+
+       return retval;
+}
+
+static ssize_t rtc_sysfs_store_alarm_wakeup_enabled(struct class_device *dev, const char *buf, size_t count)
+{
+       ssize_t retval;
+       struct rtc_wkalrm alrm;
+
+       unsigned long enabled = simple_strtoul(buf, NULL, 0);
+
+       retval = rtc_read_alarm(dev, &alrm);
+       if (retval)
+               return retval;
+       alrm.enabled = !!enabled;
+       retval = rtc_set_alarm(dev, &alrm);
+       if (retval)
+               return retval;
+
+       return count;
+}
+static CLASS_DEVICE_ATTR(wakeup_enabled, 0644, rtc_sysfs_show_alarm_wakeup_enabled, rtc_sysfs_store_alarm_wakeup_enabled);
+
+static ssize_t rtc_sysfs_show_alarm_pending(struct class_device *dev, char *buf)
+{
+       ssize_t retval;
+       struct rtc_wkalrm alrm;
+
+       retval = rtc_read_alarm(dev, &alrm);
+       if (retval == 0) {
+               retval = sprintf(buf, "%d\n", alrm.pending);
+       }
+
+       return retval;
+}
+static CLASS_DEVICE_ATTR(pending, S_IRUGO, rtc_sysfs_show_alarm_pending, NULL);
+
+
 static struct attribute *rtc_attrs[] = {
        &class_device_attr_name.attr,
        &class_device_attr_date.attr,
@@ -78,6 +162,19 @@
        .attrs = rtc_attrs,
 };
 
+static struct attribute *rtc_alarm_attrs[] = {
+       &class_device_attr_alarm_since_epoch.attr,
+       &class_device_attr_wakeup_enabled.attr,
+       &class_device_attr_pending.attr,
+       NULL,
+};
+
+static struct attribute_group rtc_alarm_attr_group = {
+       .name   = "alarm",
+       .attrs  = rtc_alarm_attrs,
+};
+
+
 static int __devinit rtc_sysfs_add_device(struct class_device *class_dev,
                                        struct class_interface *class_intf)
 {
@@ -86,10 +183,19 @@
        dev_dbg(class_dev->dev, "rtc intf: sysfs\n");
 
        err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
-       if (err)
+       if (err) {
                dev_err(class_dev->dev,
                        "failed to create sysfs attributes\n");
+               goto error;
+       }
+       err = sysfs_create_group(&class_dev->kobj, &rtc_alarm_attr_group);
+       if (err) {
+               sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
+               dev_err(class_dev->dev,
+                       "failed to create sysfs alarm attributes\n");
+       }
 
+error:
        return err;
 }
 
@@ -97,6 +203,7 @@
                                struct class_interface *class_intf)
 {
        sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
+       sysfs_remove_group(&class_dev->kobj, &rtc_alarm_attr_group);
 }
 
 /* interface registration */



-- 
Best regards,
 Paul                          mailto:pmiscml@gmail.com


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w)
  2006-12-17 19:30 [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w) Paul Sokolovsky
@ 2006-12-18  4:28 ` David Brownell
  2006-12-18 23:58   ` Paul Sokolovsky
  0 siblings, 1 reply; 7+ messages in thread
From: David Brownell @ 2006-12-18  4:28 UTC (permalink / raw)
  To: Paul Sokolovsky
  Cc: Alessandro Zummo, kernel-discuss, linux-kernel, Richard Purdie

On Sunday 17 December 2006 11:30 am, Paul Sokolovsky wrote:

>     Small battery-powered systems, like PDAs, need a way to be
> suspended most of the time and woken up just from time to time to
> process pending tasks. 

Sounds like you're thinking of this from a userspace perspective...

Could you share some examples of such "pending tasks"?  I suspect
beaconing once or twice a second in a wireless network isn't quite
what you mean, although it fits your description.  On some Linux
platforms with dynamic tick support, Linux can enter suspend modes
between periodic wakeups needed for such beaconing.


> Obvious way to achieve this is to use timer, or 
> alarm, wakeup. Unfortunately, this matter is bit confusing in Linux.
> There's only one "good" "supported" way to set alarm - via ioctl() on
> an RTC device fd. Unfortunately, this alarm is not persistent - as soon
> as fd is closed, alarm id discharged.

I don't think that's true in general.  Most RTCs don't even care
whether userspace did an open() or close().  I see the S3C one does,
and that explicitly leaves the alarm active. 

But I see that only the SA1100/PXA and SH RTCs turn off all IRQs
after RTC_WKALM_* requests ... that's a distinct minority.

So judging implementations as votes ... only two implementations
that implement the RTC_WKALM_* call follow that rule, and most
don't.  However, a few implementations ignore rtc_wkalrm.enabled,
or otherwise mistreat that flag (e.g. rtc-ds1553 doesn't disable
AIE when enabled==0), so it's clear there are some issues there.

My vote would be that closing the FD should not turn off the alarm.
It's supposed to be a one-shot deal anyway.

And also, that someone audits the drivers/rtc code to make sure that
alarm-capable drivers handle the rtc_wkalrm.enabled flag correctly;
your patch sort of presumes that will happen, anyway.  And hmm, it'd
be good to have rtctest.c (in Documentation/rtc.txt) test for that...
it doesn't actually use RTC_WKALM_* calls, so it's too easy for folk
to goof up their implementations.


> Formal part
> ===========
> 
> Implement "alarm" attribute group for RTC classdevs. At this time,
> add "since_epoch", "wakeup_enabled", and "pending" attributes. First
> two support both read and write.

I think you shouldn't add this group unless the RTC has methods
to read and write the alarm; there are RTCs that don't have that
feature.

Also, I'd rather see a much simpler interface.  Like a single
"alarm" attribute.  It would display as the empty string unless
it was enabled, in which case the alarm time wouhd show.  To
disable it, write an empty string; to enable an alarm, just write
a valid time (in the future).  The other parameters aren't needed;
"wakeup" is PM infrastructure (/sys/devices/.../power/wakeup),
since it's easy to have an alarm that's not wakeup-capable.

- Dave





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w)
  2006-12-18  4:28 ` David Brownell
@ 2006-12-18 23:58   ` Paul Sokolovsky
  2006-12-19  0:54     ` David Brownell
  0 siblings, 1 reply; 7+ messages in thread
From: Paul Sokolovsky @ 2006-12-18 23:58 UTC (permalink / raw)
  To: David Brownell; +Cc: Alessandro Zummo, kernel-discuss, linux-kernel

Hello David,

Monday, December 18, 2006, 6:28:58 AM, you wrote:

> On Sunday 17 December 2006 11:30 am, Paul Sokolovsky wrote:

>>     Small battery-powered systems, like PDAs, need a way to be
>> suspended most of the time and woken up just from time to time to
>> process pending tasks. 

> Sounds like you're thinking of this from a userspace perspective...

> Could you share some examples of such "pending tasks"?

  Well, the actual usecase, which triggered me to hack that, was a
need to write a "burn out" test script for suspend/resume for a
battery-powered ARM device (PDA), which would do suspend/resume cycle
thousands of times. And wakeup alarm is obvious, if not only, source of
automated resume events.

  Of course, I started by trying existing solutions - e.g. there's an
"atd" implementation which uses /dev/rtc, but I found it having awful
latency (>2s), then I tried to write simple C app to set alarm via
ioctl(), just to find alarm IRQs are shutdown on its exit.

  But anyway, I'm that kind of guy who think that debugging and
diagnostics are important things for *production* system, so such
sysfs alarm support just as precious as /proc/interrupts and /proc/dma
(ah, ARM Linux maintainer declined to fix broken /proc/dma support for
ARM, I forgot ;-( ).

[]

>> Obvious way to achieve this is to use timer, or 
>> alarm, wakeup. Unfortunately, this matter is bit confusing in Linux.
>> There's only one "good" "supported" way to set alarm - via ioctl() on
>> an RTC device fd. Unfortunately, this alarm is not persistent - as soon
>> as fd is closed, alarm id discharged.

> I don't think that's true in general.  Most RTCs don't even care
> whether userspace did an open() or close().  I see the S3C one does,
> and that explicitly leaves the alarm active. 

> But I see that only the SA1100/PXA and SH RTCs turn off all IRQs
> after RTC_WKALM_* requests ... that's a distinct minority.

  Oh my! I couldn't even think this can be idiosyncrasy of specific
implementation. Oh, what a world... ;-)

> So judging implementations as votes ... only two implementations
> that implement the RTC_WKALM_* call follow that rule, and most
> don't.  However, a few implementations ignore rtc_wkalrm.enabled,
> or otherwise mistreat that flag (e.g. rtc-ds1553 doesn't disable
> AIE when enabled==0), so it's clear there are some issues there.

> My vote would be that closing the FD should not turn off the alarm.
> It's supposed to be a one-shot deal anyway.

  I would agree with such behavior. But what's clear that the
behavior, whatever it is, should be consistent across implementations,
or its just a mess ;-(.

> And also, that someone audits the drivers/rtc code to make sure that
> alarm-capable drivers handle the rtc_wkalrm.enabled flag correctly;
> your patch sort of presumes that will happen, anyway.

  Yes, I mentioned, that for PXA/SA, my patch becomes actually useful
only after applying your patch (plus, with fixed TODO: here's what
I applied to handhelds.org tree:
http://handhelds.org/cgi-bin/cvsweb.cgi/linux/kernel26/drivers/rtc/rtc-sa1100.c.diff?r1=1.5&r2=1.6&f=h
).

  That of course doesn't mean sysfs alarm support patch depends on
rtc-sa1100.c patch in any way (it's just PXA/SA won't actually wake up,
but sysfs patch for showing/storing alarm properties obviously doesn't
depend on any specific implementation).

>   And hmm, it'd
> be good to have rtctest.c (in Documentation/rtc.txt) test for that...
> it doesn't actually use RTC_WKALM_* calls, so it's too easy for folk
> to goof up their implementations.


>> Formal part
>> ===========
>> 
>> Implement "alarm" attribute group for RTC classdevs. At this time,
>> add "since_epoch", "wakeup_enabled", and "pending" attributes. First
>> two support both read and write.

> I think you shouldn't add this group unless the RTC has methods
> to read and write the alarm; there are RTCs that don't have that
> feature.

> Also, I'd rather see a much simpler interface.  Like a single
> "alarm" attribute.  It would display as the empty string unless
> it was enabled, in which case the alarm time wouhd show.  To
> disable it, write an empty string; to enable an alarm, just write
> a valid time (in the future).  The other parameters aren't needed;
> "wakeup" is PM infrastructure (/sys/devices/.../power/wakeup),
> since it's easy to have an alarm that's not wakeup-capable.

  Yes, both of these are, or may be, true. That was really a draft,
initial version. I probably don't have knowledge/resources to make it
"right", but it would be nice if it prompted someone with more
experience/resources to tweak in such support, as well as the problems
outlined above...

> - Dave



-- 
Best regards,
 Paul                            mailto:pmiscml@gmail.com


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w)
  2006-12-18 23:58   ` Paul Sokolovsky
@ 2006-12-19  0:54     ` David Brownell
  2006-12-19  0:59       ` David Brownell
  0 siblings, 1 reply; 7+ messages in thread
From: David Brownell @ 2006-12-19  0:54 UTC (permalink / raw)
  To: Paul Sokolovsky; +Cc: Alessandro Zummo, kernel-discuss, linux-kernel

Hi Paul,

On Monday 18 December 2006 3:58 pm, Paul Sokolovsky wrote:
> Monday, December 18, 2006, 6:28:58 AM, you wrote:
> > On Sunday 17 December 2006 11:30 am, Paul Sokolovsky wrote:
> 
> >>     Small battery-powered systems, like PDAs, need a way to be
> >> suspended most of the time and woken up just from time to time to
> >> process pending tasks. 
> 
> > Sounds like you're thinking of this from a userspace perspective...
> 
> > Could you share some examples of such "pending tasks"?
> 
>   Well, the actual usecase, which triggered me to hack that, was a
> need to write a "burn out" test script for suspend/resume for a
> battery-powered ARM device (PDA), which would do suspend/resume cycle
> thousands of times. And wakeup alarm is obvious, if not only, source of
> automated resume events.

I like how you think ... SCRIPTED TESTING for suspend/resume!!
Can you clone yourself?  Soon, and massively?  :)

Though I confess I've used that example myself.  I think if you scan LKML
you'll find an "rtcwake" program (userspace) I've used on several different
ARMs (not PXA though), and even x86 PCs (using a new RTC driver, but getting
the usual headaches from ACPI S3 resume failures on most systems).


>   Of course, I started by trying existing solutions - e.g. there's an
> "atd" implementation which uses /dev/rtc, but I found it having awful
> latency (>2s), then I tried to write simple C app to set alarm via
> ioctl(), just to find alarm IRQs are shutdown on its exit.
> 
>   But anyway, I'm that kind of guy who think that debugging and
> diagnostics are important things for *production* system,

You'd find violent agreement from anyone who's spent time trying
to support all this fancy technology.  Heck, even toasters have
problems sometimes.


> >> Obvious way to achieve this is to use timer, or 
> >> alarm, wakeup. Unfortunately, this matter is bit confusing in Linux.
> >> There's only one "good" "supported" way to set alarm - via ioctl() on
> >> an RTC device fd. Unfortunately, this alarm is not persistent - as soon
> >> as fd is closed, alarm id discharged.
> 
> > I don't think that's true in general.  Most RTCs don't even care
> > whether userspace did an open() or close().  I see the S3C one does,
> > and that explicitly leaves the alarm active. 
> 
> > But I see that only the SA1100/PXA and SH RTCs turn off all IRQs
> > after RTC_WKALM_* requests ... that's a distinct minority.
> 
>   Oh my! I couldn't even think this can be idiosyncrasy of specific
> implementation. Oh, what a world... ;-)

Yeah, just think how bad it was _before_ the RTC class framework
existed.   I think I counted at least half a dozen implementations,
with minimal API overlap.

One thing we're missing now is RTC conformance tests.  They'd have
turned up some of these issues pretty quickly, if thery were at all
good.

 
> > So judging implementations as votes ... only two implementations
> > that implement the RTC_WKALM_* call follow that rule, and most
> > don't.  However, a few implementations ignore rtc_wkalrm.enabled,
> > or otherwise mistreat that flag (e.g. rtc-ds1553 doesn't disable
> > AIE when enabled==0), so it's clear there are some issues there.
> 
> > My vote would be that closing the FD should not turn off the alarm.
> > It's supposed to be a one-shot deal anyway.
> 
>   I would agree with such behavior. But what's clear that the
> behavior, whatever it is, should be consistent across implementations,
> or its just a mess ;-(.

Yep.  I've been known to submit patches to improve that, even ones
to the RTC framework.  :)

 
> > And also, that someone audits the drivers/rtc code to make sure that
> > alarm-capable drivers handle the rtc_wkalrm.enabled flag correctly;
> > your patch sort of presumes that will happen, anyway.
> 
>   Yes, I mentioned, that for PXA/SA, my patch becomes actually useful
> only after applying your patch (plus, with fixed TODO: here's what
> I applied to handhelds.org tree:
> http://handhelds.org/cgi-bin/cvsweb.cgi/linux/kernel26/drivers/rtc/rtc-sa1100.c.diff?r1=1.5&r2=1.6&f=h
> ).
> 
>   That of course doesn't mean sysfs alarm support patch depends on
> rtc-sa1100.c patch in any way (it's just PXA/SA won't actually wake up,
> but sysfs patch for showing/storing alarm properties obviously doesn't
> depend on any specific implementation).

Hmm, you're in a position to test, so I may send you an update to try.

That patch you applied looks right to me -- why don't you forward it
to Alessandro as a bugfix for 2.6.20-rc2, and save me the effort?

 
> >> Implement "alarm" attribute group for RTC classdevs. At this time,
> >> add "since_epoch", "wakeup_enabled", and "pending" attributes. First
> >> two support both read and write.
> 
> > I think you shouldn't add this group unless the RTC has methods
> > to read and write the alarm; there are RTCs that don't have that
> > feature.
> 
> > Also, I'd rather see a much simpler interface.  Like a single
> > "alarm" attribute.  It would display as the empty string unless
> > it was enabled, in which case the alarm time wouhd show.  To
> > disable it, write an empty string; to enable an alarm, just write
> > a valid time (in the future).  The other parameters aren't needed;
> > "wakeup" is PM infrastructure (/sys/devices/.../power/wakeup),
> > since it's easy to have an alarm that's not wakeup-capable.
> 
>   Yes, both of these are, or may be, true. That was really a draft,
> initial version. I probably don't have knowledge/resources to make it
> "right", but it would be nice if it prompted someone with more
> experience/resources to tweak in such support, as well as the problems
> outlined above...

You have enough knowledge to implement those suggestions though,
that seems clear to me.  :)

- Dave


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w)
  2006-12-19  0:54     ` David Brownell
@ 2006-12-19  0:59       ` David Brownell
  2006-12-19  6:41         ` Paul Sokolovsky
  0 siblings, 1 reply; 7+ messages in thread
From: David Brownell @ 2006-12-19  0:59 UTC (permalink / raw)
  To: Paul Sokolovsky; +Cc: Alessandro Zummo, kernel-discuss, linux-kernel

On Monday 18 December 2006 4:54 pm, David Brownell wrote:

> > http://handhelds.org/cgi-bin/cvsweb.cgi/linux/kernel26/drivers/rtc/rtc-sa1100.c.diff?r1=1.5&r2=1.6&f=h
> 
> That patch you applied looks right to me -- why don't you forward it
> to Alessandro as a bugfix for 2.6.20-rc2, and save me the effort?

Actually, correction:  it'd be correct if you ripped out the buggy
calls to manage the irq wake mechanism.  A later message will show
how those need to work.  (The IRQ framework will give one helpful
hint when it warns about mismatched enable/disable calls ...)

- Dave

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w)
  2006-12-19  0:59       ` David Brownell
@ 2006-12-19  6:41         ` Paul Sokolovsky
  2006-12-19  9:06           ` David Brownell
  0 siblings, 1 reply; 7+ messages in thread
From: Paul Sokolovsky @ 2006-12-19  6:41 UTC (permalink / raw)
  To: David Brownell; +Cc: kernel-discuss, linux-kernel, linux-arm-kernel

Hello David,

Tuesday, December 19, 2006, 2:59:11 AM, you wrote:

> On Monday 18 December 2006 4:54 pm, David Brownell wrote:

>> > http://handhelds.org/cgi-bin/cvsweb.cgi/linux/kernel26/drivers/rtc/rtc-sa1100.c.diff?r1=1.5&r2=1.6&f=h
>> 
>> That patch you applied looks right to me -- why don't you forward it
>> to Alessandro as a bugfix for 2.6.20-rc2, and save me the effort?

> Actually, correction:  it'd be correct if you ripped out the buggy
> calls to manage the irq wake mechanism.  A later message will show
> how those need to work.  (The IRQ framework will give one helpful
> hint when it warns about mismatched enable/disable calls ...)

  Do you mean enable_irq_wake()/disable_irq_wake() calls? In what way
they are buggy? The only "bug" with them I see is that they are not
implemented for PXA, which just once again reminds that mach-pxa is
real misfit in ARM family (own DMA API instead of fitting with generic
ARM one, no cpufreq support in mainline, and few other not implemented
APIs). That's of course pretty sad, as apparently PXA was/still is
the most popular CPU for consumer market (well, at least in "something
like real computer" caregory) ;-(.

  But those calls are apparently still needed, even if you say that
wakeup stuff should be handled in generic manner, as PM feature, and
on device level. After all, what drivers will do to actually enable
wakeup for a given device? I hope we don't speak about using
CPU-specific registers in reusable device drivers for that.

  This is pretty interesting topic for us, and so far in handhelds.org
ports we don't handle dynamic wakeup configuration at all, so I would
eagerly expect your samples. In the meantime, I went and hacked
.set_wake methods for PXA's irq_chips. And that's when I got idea why
it might haven't been implemented at all - PXA27x's model of wakeup
sources is a bit weird comparing with nice and clean PXA25x's ;-).
It's still not the reason to give up on those calls at all - after
all, even "least common denominator" implementation will give good
value. I yet need to test what I've put together, though.


> - Dave


-- 
Best regards,
 Paul                            mailto:pmiscml@gmail.com


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w)
  2006-12-19  6:41         ` Paul Sokolovsky
@ 2006-12-19  9:06           ` David Brownell
  0 siblings, 0 replies; 7+ messages in thread
From: David Brownell @ 2006-12-19  9:06 UTC (permalink / raw)
  To: Paul Sokolovsky; +Cc: kernel-discuss, linux-kernel, linux-arm-kernel

On Monday 18 December 2006 10:41 pm, Paul Sokolovsky wrote:

> 
>   Do you mean enable_irq_wake()/disable_irq_wake() calls? In what way
> they are buggy? The only "bug" with them I see is that they are not
> implemented for PXA,

Notice how the number of enables and disables don't balance, and then
how the genirq framework handles such unbalanced calls.  Appended see
a "should make it all work" patch.  Test with the "rtcwake.c" program;
I'd expect pxa2[1567]x and sa1100 to work ... but obviously, there are
many more wakeup event sources that could be supported.


>   This is pretty interesting topic for us, and so far in handhelds.org
> ports we don't handle dynamic wakeup configuration at all, so I would
> eagerly expect your samples. In the meantime, I went and hacked
> .set_wake methods for PXA's irq_chips. And that's when I got idea why
> it might haven't been implemented at all - PXA27x's model of wakeup
> sources is a bit weird comparing with nice and clean PXA25x's ;-).

The appended patch is for pxa25x; maybe it needs to be #ifdeffed.

- Dave

==============	CUT HERE

This updates the SA-1100/PXA RTC support:

 - For PXA, copy the sa1100 irqchip set_wake handler; now this RTC
   should be a wakeup event source.  (GPIOs still not supported,
   and the comment is correct for pxa2[156]x not pxa27x.)
 
 - For both PXA and SA1100, mark the RTC platform device as capable
   of being a system wakeup event source before registration.

 - Bugfix the (shared) RTC driver to properly manage wakeup irqs, by
   adding new suspend/resume methods.  The previous code was deeply
   broken, and would generate error messages from the genirq framework.

 - Bugfix the (shared) RTC driver to handle the rtc_wkalrm.enable flag
   properly, reporting it when the alarm is read and setting it as
   requested when the alarm is set.

 - Add a missing MODULE_ALIAS so this driver can hotplug; "rtc-sa1100.c"
   would normally hold a driver named "rtc-sa1100", not "sa1100-rtc".

Compile-tested.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>

---
 arch/arm/mach-pxa/generic.c    |    2 ++
 arch/arm/mach-pxa/irq.c        |   16 ++++++++++++++++
 arch/arm/mach-sa1100/generic.c |    2 ++
 drivers/rtc/rtc-sa1100.c       |   31 ++++++++++++++++++++++++++-----
 4 files changed, 46 insertions(+), 5 deletions(-)
 
Index: at91/arch/arm/mach-pxa/irq.c
===================================================================
--- at91.orig/arch/arm/mach-pxa/irq.c	2006-12-07 21:22:59.000000000 -0800
+++ at91/arch/arm/mach-pxa/irq.c	2006-12-19 00:33:06.000000000 -0800
@@ -39,11 +39,27 @@ static void pxa_unmask_low_irq(unsigned 
 	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
 }
 
+/*
+ * Apart from GPIOs 0-15, only the RTC alarm can be a wakeup event.
+ */
+static int pxa_set_wake(unsigned int irq, unsigned int on)
+{
+	if (irq == IRQ_RTCAlrm) {
+		if (on)
+			PWER |= PWER_RTC;
+		else
+			PWER &= ~PWER_RTC;
+		return 0;
+	}
+	return -EINVAL;
+}
+
 static struct irq_chip pxa_internal_chip_low = {
 	.name		= "SC",
 	.ack		= pxa_mask_low_irq,
 	.mask		= pxa_mask_low_irq,
 	.unmask		= pxa_unmask_low_irq,
+	.set_wake	= pxa_set_wake,
 };
 
 #if PXA_INTERNAL_IRQS > 32
Index: at91/arch/arm/mach-pxa/generic.c
===================================================================
--- at91.orig/arch/arm/mach-pxa/generic.c	2006-12-07 21:22:59.000000000 -0800
+++ at91/arch/arm/mach-pxa/generic.c	2006-12-19 00:34:21.000000000 -0800
@@ -398,6 +398,8 @@ static int __init pxa_init(void)
 {
 	int cpuid, ret;
 
+	device_init_wakeup(&pxartc_device.dev, 1);
+
 	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	if (ret)
 		return ret;
Index: at91/arch/arm/mach-sa1100/generic.c
===================================================================
--- at91.orig/arch/arm/mach-sa1100/generic.c	2006-12-07 21:23:00.000000000 -0800
+++ at91/arch/arm/mach-sa1100/generic.c	2006-12-19 00:25:21.000000000 -0800
@@ -354,6 +354,8 @@ static int __init sa1100_init(void)
 	if (sa11x0ir_device.dev.platform_data)
 		platform_device_register(&sa11x0ir_device);
 
+	device_init_wakeup(&sa11x0rtc_device.dev, 1);
+
 	return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices));
 }
 
Index: at91/drivers/rtc/rtc-sa1100.c
===================================================================
--- at91.orig/drivers/rtc/rtc-sa1100.c	2006-12-18 23:32:22.000000000 -0800
+++ at91/drivers/rtc/rtc-sa1100.c	2006-12-19 00:09:46.000000000 -0800
@@ -263,8 +263,12 @@ static int sa1100_rtc_set_time(struct de
 
 static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
+	u32 rtsr;
+
 	memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
-	alrm->pending = RTSR & RTSR_AL ? 1 : 0;
+	rtsr = RTSR;
+	alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
+	alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
 	return 0;
 }
 
@@ -275,12 +279,10 @@ static int sa1100_rtc_set_alarm(struct d
 	spin_lock_irq(&sa1100_rtc_lock);
 	ret = rtc_update_alarm(&alrm->time);
 	if (ret == 0) {
-		memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time));
-
 		if (alrm->enabled)
-			enable_irq_wake(IRQ_RTCAlrm);
+			RTSR |= RTSR_ALE;
 		else
-			disable_irq_wake(IRQ_RTCAlrm);
+			RTSR &= ~RTSR_ALE;
 	}
 	spin_unlock_irq(&sa1100_rtc_lock);
 
@@ -350,9 +352,28 @@ static int sa1100_rtc_remove(struct plat
 	return 0;
 }
 
+static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	if (device_may_wakeup(&pdev->dev))
+		enable_irq_wake(IRQ_RTCAlrm);
+	return 0;
+}
+
+static int sa1100_rtc_resume(struct platform_device *pdev)
+{
+	if (device_may_wakeup(&pdev->dev))
+		disable_irq_wake(IRQ_RTCAlrm);
+	return 0;
+}
+
+/* alias needed so hotplug behaves ("modprobe $MODALIAS") */
+MODULE_ALIAS("sa1100-rtc");
+
 static struct platform_driver sa1100_rtc_driver = {
 	.probe		= sa1100_rtc_probe,
 	.remove		= sa1100_rtc_remove,
+	.suspend	= sa1100_rtc_suspend,
+	.resume		= sa1100_rtc_resume,
 	.driver		= {
 		.name		= "sa1100-rtc",
 	},

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2006-12-19  9:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-17 19:30 [PATCH] RTC classdev: Add sysfs support for wakeup alarm (r/w) Paul Sokolovsky
2006-12-18  4:28 ` David Brownell
2006-12-18 23:58   ` Paul Sokolovsky
2006-12-19  0:54     ` David Brownell
2006-12-19  0:59       ` David Brownell
2006-12-19  6:41         ` Paul Sokolovsky
2006-12-19  9:06           ` David Brownell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).