Re: Question about GPIO Lib

2012-02-01 Thread Bill Gatliff
Mark:

On Wed, Feb 1, 2012 at 6:32 AM, Mark Brown  wrote:
>
> Just to expand on this a bit: lots of people would prefer not to have a
> userspace component at all due to the same hardware safety concerns that
> you have, or to have the userspace component be a driver using gpiolib
> which needs to be explicitly connected to the GPIOs.

... which I think is a spectacularly bad idea. :)

Diversion from the original theme of this thread notwithstanding, I
don't see the point in the additional complexity of implementing such
a heavy-handed lockout when it's pretty darned easy to just do a
gpio_request() in kernel space to take the pin entirely away from
users.  I do that pretty routinely, but then in the relevant
kernel-side driver I almost always offer a sysfs attribute of my own
that lets me grant users controlled access to the functionality
provided by the pin.

For example, if it's a RESET-type pin for an external chip, then I'll
have a /sys/.../assert_reset attribute such that when root writes to
it, my store() method sends a timed pulse to the physical GPIO pin. Or
not, depending on what mood the device is in at the time--- which the
driver always knows.

I won't let the user kill anyone, of course, but I WILL grant them
tools like the above to bring the platform under control and
investigate problems during hardware integration.  The productivity
improvement more than offsets the thought and code investment
required.

I have often considered a gpiolib patch that just makes sysfs
attributes read-only when kernel-side does a gpio_request(), rather
than taking the pin attributes away entirely.  That way I can have
simple tools in userspace to silently log GPIO activity for
troubleshooting.  The blocking reads that some versions of gpiolib
offer today make this work even better.



b.g.
-- 
Bill Gatliff
b...@billgatliff.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Question about GPIO Lib

2012-01-31 Thread Bill Gatliff
Bruce:

On Mon, Jan 30, 2012 at 6:06 PM,   wrote:
> Bill Gatliff  wrote on 01/27/2012 10:42:57 AM:
>> Sounds like you DON'T want to merely export that GPIO pin to userspace.
>>
>
> Well, yes I do want to just export to userspace

I misunderstood your message, then.  I was thinking that you were
already using certain pins in kernel space, and didn't want THOSE pins
exported to userspace due to the risks that users might invoke them
and cause Bad Things to happen.

> I just want to restrict
> the pins that get exported to only those that are defined in the device
> tree.  I don't want or need to access any of the exported pins from kernel
> space and I don't want user space to access any pin not explicitly called
> out in the device tree.  I want it to behave like gpio-leds only with
> input as well as output capabilities.

I glanced at gpiolib.c, and I don't immediately see a way to achieve
this with the current code.

Again, you could get the same net effect by doing a gpio_request() in
kernel space on the pins you DON'T want exported, which would prevent
those pins being exportable.  But that's still different from what you
are actually asking for.

> If I understand this correctly you're basically saying that gpiolib is a
> waste of time and I should just write my own driver?

I'm DEFINITELY not saying that gpiolib is generally a waste of time!  :)

I'm just saying that, sadly, in many ways gpiolib is still a
work-in-progress.  The userspace component has been somewhat
controversial in general over the years, and definitely lacks several
key features in addition to the one you are asking for.

Since I know others will ask :), note that the userspace component
won't give you a direction attribute for pins whose directions cannot
be changed from userspace.  That's a pretty important omission, since
it prevents me from conveniently verifying (apart from debugfs, I
mean) that a pin is in fact configured in the direction I want it to
be.  Whether I can change its direction is a different issue entirely.

Another omission that has struck me over the years is that it's not
straightforward for gpio_chip authors to add custom attributes in
sysfs for either the chip itself, or for the pins the chip exports.
Within /sys/class/gpio/gpio/ I mean.

But even in its current state, gpiolib is awesome.  Maybe someday I or
someone else will find time to make it awesomer.  :)


b.g.
-- 
Bill Gatliff
b...@billgatliff.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Question about GPIO Lib

2012-01-27 Thread Bill Gatliff
Bruce:

On Fri, Jan 27, 2012 at 5:31 AM,   wrote:
>
> The problem is we've got a number of other things hooked up to the GPIO
> pins that it would be very bad if someone from user space played with
> them, like our FPGA configuration pin.  Some one toggles that and our box
> goes stupid.  So what I'm wondering is if there's a way, preferably via
> the device tree, to limit the GPIOs that GPIO Lib exposes to user space?

Sounds like you DON'T want to merely export that GPIO pin to userspace.

If you have anything in kernel space doing a gpio_request() on that
pin, it won't be exportable to userspace anyway.  Regardless, you are
probably better off implement a DEVICE_ATTR that, in its store()
method, treads lightly on said pin.  And then do a gpio_request() in
kernel space so that users can't ever see the pin directly.

Just my $0.02.


b.g.
-- 
Bill Gatliff
b...@billgatliff.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Question on supporting multiple HW versions with a single driver (warning: long post)

2011-02-07 Thread Bill Gatliff
Guys:


I think the Silicon Motion SM501 driver might provide a useful
example, since the chip comes in both memory-mapped and PCI versions.
Unfortunately the chip is implemented as a multi-function driver
(mfd), so the code is not un-complicated.  Still fairly
straightforward and well-written once you learn your way around it,
though.

Basically, it implements a core set of functionality to talk to the
actual chip registers, which is bus-agnostic.  Then the bus-specific
drivers use these functions when they actually want to touch the chip
itself.  In other words, exactly what David suggested.


b.g.


On Mon, Feb 7, 2011 at 8:37 PM,   wrote:
>>
>> There are a number of drivers which already have this sort of dual bus
>> binding.
>>
>
> Thanks for the feedback David, I appreciate it.  Could you point me to one
> of those drivers that has "this sort of dual bus binding" so can see an
> example of what I'm trying to do?
>
> Bruce
> ___
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>



-- 
Bill Gatliff
b...@billgatliff.com
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Xorg on Fujitsu "Lime" with MPC5200b?

2010-04-15 Thread Bill Gatliff
Roman Fietze wrote:
> Yes. I added a routine like
>
> /* Swap frame buffer bytes in 32 bit value.  */
> static __inline unsigned int
> fbbits_swap32(unsigned int __bsx)
> {
> return __bsx) & 0xff00) >> 8) | (((__bsx) & 0x00ff) << 8) |
>   (((__bsx) & 0xff00) >> 8) | (((__bsx) & 0x00ff) << 8));
> }
>   

I baked the above code into shadowUpdatePacked(), and it didn't seem to
help anything--- my icewm mouse cursor was still quite jagged, as was
all the text on the screen (clock widget, etc).  So I replaced the above
code with a return 0, and the icewm desktop went completely black--- and
everything else remained unchanged.

Apparently, there are several similar modifications that need to be
made, i.e. the shadowUpdatePacked() function isn't the only way to the
framebuffer memory?  I'm really looking forward to seeing your code, as
I have no idea how to even identify the places that need hacking.  I
understand the utility of the hack, however.

Makes me think that we're all just soldering this chip down to the wrong
data lines, and makes me wonder if there isn't an "endianness bit" in
the memory bus controller that can undo this damage for us.  I know I've
seen such a bit in other SoCs...


Thanks!


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Xorg on Fujitsu "Lime" with MPC5200b?

2010-04-15 Thread Bill Gatliff
Roman Fietze wrote:
> Then I added void shadowUpdatePackedSwapped16() and
> shadowUpdatePackedSwapped32() which I was using instead of the
> original *Weak functions, which in turn uses the above swap routine
> when copying from shadow to the device.
>   

I'm not sure what the *Weak stuff is doing.  Can I just hack
shadowUpdatePacked() itself?


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Xorg on Fujitsu "Lime" with MPC5200b?

2010-04-15 Thread Bill Gatliff
I would love it if you posted your code! Thanks!!

b.g.

On Apr 15, 2010 8:53 AM, "Roman Fietze"  wrote:

Hello Bill,


On Thursday 15 April 2010 15:01:59 Bill Gatliff wrote:

> Are you talking about this code here?
>
...
Yes. I added a routine like

/* Swap frame buffer bytes in 32 bit value.  */
static __inline unsigned int
fbbits_swap32(unsigned int __bsx)
{
   return __bsx) & 0xff00) >> 8) | (((__bsx) & 0x00ff) << 8) |
   (((__bsx) & 0xff00) >> 8) | (((__bsx) & 0x00ff) << 8));
}


Then I added void shadowUpdatePackedSwapped16() and
shadowUpdatePackedSwapped32() which I was using instead of the
original *Weak functions, which in turn uses the above swap routine
when copying from shadow to the device.

If you want I can post (in the ML) or mail you the files that I
changed. A diff probably won't help a lot, because I think we changed
more than that, and we are using a pretty old XFree version.



Roman

-- 
Roman Fietze Telemotive AG Büro Mühlhausen
Breitwiesen ...
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: Xorg on Fujitsu "Lime" with MPC5200b?

2010-04-15 Thread Bill Gatliff
Roman Fietze wrote:
> Hallo Bill,
>
> On Thursday 15 April 2010 05:07:08 Bill Gatliff wrote:
>
>   
>> Actually, I *have* Debian squeeze's xorg running on the platform just
>> fine, with a 2.6.34-rc1 kernel (kernel.org).  Problem is, every single
>> diagonal line is very blocky--- not smooth at all.
>> 
>
> I'm 95% sure it's an endianess problem, on our boards we had to modify
> the X11 driver. What I did was swapping bytes when updating the device
> from the shadowfb inside programs/Xserver/miext/shadow/shpacked.c
>   

Are you talking about this code here?

void
shadowUpdatePacked (ScreenPtr pScreen,
shadowBufPtr pBuf)
{
...
while (i--)
*win++ = *sha++;



Do I endian-swap each *sha?  Or, do I reorder the sha array before
dereferencing it (e.g. each *sha is right, but adjacent ones are in the
wrong order)?


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Xorg on Fujitsu "Lime" with MPC5200b?

2010-04-14 Thread Bill Gatliff
Guys:


I'm not quite sure where to ask this question, but all my attempts
elsewhere have come up short, so...

Put simply, I have an MPC5200b platform with a Fujitsu "Lime" GDC, and
I'm trying to run Debian squeeze's xorg on it.

Actually, I *have* Debian squeeze's xorg running on the platform just
fine, with a 2.6.34-rc1 kernel (kernel.org).  Problem is, every single
diagonal line is very blocky--- not smooth at all.  I used to think this
was a problem with X's fonts, but now I don't think so because the mouse
cursor's diagonal lines also look equally bad.

It's almost as if any time the platform tries to draw a diagonal line,
truncation/rounding errors are causing it problems in figuring out which
pixels to turn on and off.

A non-Linux kernel on this hardware, running a non-X GUI, seems to work
fine so I think the hardware isn't the problem.

Anyone have any suggestions on where to start with this one?  Anyone
else running a similar configuration with any success?  I'm completely
lost, and running out of hair *fast*...


Thanks!


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


kernel BUG at kernel/timer.c:643!

2010-04-12 Thread Bill Gatliff
Is anyone seeing this message on an MPC5200 platform with the current
HEAD from Linus Torvalds' git repo?  I just did a rebase, and started
seeing it...


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: A better way to sequence driver initialization?

2010-04-10 Thread Bill Gatliff
Paul Mundt wrote:
> In some cases that might be valid, but there are many cases where drivers
> can reconfigure their capability sets based on which GPIOs are and aren't
> available. Just because a pin isn't available doesn't make it a
> show-stopper for the probe path..
>   

Understood.

I just tweaked my kernel to run all probe()s  in their own kthreads. 
The results were a mixed bag, as expected.

On the one hand, it's pretty cool to see everything running in parallel!

On the other hand, I can see now yet another big reason why a probe
free-for-all won't work.  Busses are also devices, so there are plenty
of places where a device for a particular bus type won't be able to
probe because the target bus simply doesn't exist yet.  That's yet
another dependency that I hadn't thought about.

Were I to rewrite Linux :), I would make probing parallel from the
beginning.  But I think I'm going to have to settle for now with
kthreading my probes that might want to sleep, and adding a wait queue
to gpio_request() and a few others.  It ain't perfect, but it is
achieveable.  *sigh*


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: A better way to sequence driver initialization?

2010-04-10 Thread Bill Gatliff
Grant Likely wrote:
> On Sat, Apr 10, 2010 at 5:39 PM, Paul Mundt  wrote:
>   
>> In cases where you can specifically note that dependencies, doing so will
>> save you a world of pain. Despite that, it's simply not possible to do
>> this as a free-for-all. Devices or busses that can tolerate multi-threaded
>> probing need to be converted over one at a time, but even then you still
>> need the dependency tracking for those that depend on link order today.
>> 

Who's to say a function like gpio_request_wait_for_it(GPIO_NUMBER,
"dependent-driver") isn't the way to do the dependency tracking?  I
can't even implement that without a context that can sleep...

b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: A better way to sequence driver initialization?

2010-04-10 Thread Bill Gatliff
Paul Mundt wrote:
>
> In cases where you can specifically note that dependencies, doing so will
> save you a world of pain. Despite that, it's simply not possible to do
> this as a free-for-all. Devices or busses that can tolerate multi-threaded
> probing need to be converted over one at a time, but even then you still
> need the dependency tracking for those that depend on link order today.
>   

Right now I'm thinking mostly about GPIO devices which need to register
before things like gpio-leds can use them.  Sometimes the GPIO expansion
chip of interest is on i2c, other times it's spi, and still others it's
a platform or USB device.  Linking the gpio-led driver late helps that
specific situation.

But what about when I want to use a pin on a GPIO expansion device as
the card-detect for an MMC slot?  Or, as I've just recently noticed in
one hardware platform I'm working on, using a pin on a SPI GPIO expander
as a chip-select for another SPI device, but through gpiolib? 
Eventually, the dependencies don't become circular but changing the link
order will break some and fix others.  Ugh.

Definitely, a free-for-all isn't going to work.  But I don't think that
having every driver do its own kthread_run() is a solution, either. 
I'll keep tinkering.  :)


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: A better way to sequence driver initialization?

2010-04-10 Thread Bill Gatliff
Grant Likely wrote:
> On Fri, Apr 9, 2010 at 1:23 PM, Bill Gatliff  wrote:
>   
>> Guys:
>>
>>
>> My recent post, "Requesting a GPIO that hasn't been registered yet", and
>> Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking
>> about the problem of dependencies between devices in different  classes,
>> and/or between drivers/devices in general.  I'd like to float an idea to
>> see if it's worth pursuing.
>>
>> Changing the link order to get drivers to initialize in the right order
>> will always be a problem for someone--- the order will be right for some
>> people, but exactly wrong for others.  And the problem is made worse for
>> Device Tree-based systems, where just about everything including IRQ
>> descriptors are created on a demand and/or as-available basis.  What if
>> we let the kernel sort those dependencies out for us, at runtime?  I
>> think it's possible, and I can't be the only one who would like to see
>> this happen.
>>
>> There are two parts to my idea for a solution.  First part is to modify
>> do_initcalls() so that it launches each initcall function in its own
>> kernel thread.  Wait, don't panic yet!
>> 
>
> Is initcall the right granularity?  Shouldn't it be that each .probe()
> hook gets its own thread?  Otherwise one device missing its resources
> could block another device using the same driver (whose resources are
> available) from probing.

Good point, one that I missed.  Yea, I guess I really want multithreaded
probing.

> Regardless, parallel probe has be attempted and failed before.  There are 
> lots of fiddly bits to get right.
>   

Yep.  I wasnt aware of any specific attempts before, but I did suspect
that there were fiddly bits lurking about.  :)

> In fact, there *used* to be code in the kernel that does exactly that.
>  It was put in 2.6.20, but removed in 2.6.21-rc1.  Here's the relevant
> commits, and a very interesting thread discussing the issues:
>
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=21c7f30b1d3f8a3de3128478daca3ce203fc8733
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=5adc55da4a7758021bcc374904b0f8b076508a11
> http://lkml.indiana.edu/hypermail/linux/kernel/0705.1/0205.html
>
> It is pointed out in that thread that a big part of the problem is
> that a large number of drivers in the tree just aren't safe for
> multithreaded probing which is kind of a showstopper.  Now, maybe
> doing it at the initcall level makes it less scary and more sane, but
> I suspect that it will still expose a lot of broken code that assumes
> things are already set up because it has always been that way.
>   

Yep.

> Not quite the same model that you are talking about here, but it would
> solve the problem on a per-driver basis.
>   

Yea, but it's the per-driver part that I'm trying to avoid.


> Have you dug into the Arjan's asynchronous function call infrastructure?
>
> http://lwn.net/Articles/314808/
>   

No, but I think I will now.  :)


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: A better way to sequence driver initialization?

2010-04-10 Thread Bill Gatliff
Benjamin Herrenschmidt wrote:
> On Fri, 2010-04-09 at 14:23 -0500, Bill Gatliff wrote:
>   
>> My recent post, "Requesting a GPIO that hasn't been registered yet", and
>> Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking
>> about the problem of dependencies between devices in different  classes,
>> and/or between drivers/devices in general.  I'd like to float an idea to
>> see if it's worth pursuing. 
>> 
>
> I'd rather do things a bit more explicitely and less prone to break
> existing stuff... something along the lines of, first defining a variant
> of the initcalls to enable that "multithreaded" stuff, along with an
> explicit wait_for_service("subsys:hid"); for example.
>
> One could also expose service deps via the module info, thus delaying
> module init, or things like that (in fact, initcalls could even come
> with a list of dependencies).
>   

The general problem with your approach is that the module in question
might not know what services it needs to wait for.

Specific to my situation, the gpio-led code doesn't have any way of
knowing that it needs to wait until my pca953x i2c devices have all been
installed so that the gpio pin I have specified even exists.  And short
of setting up some kind of table in the board-specific code (or device
tree, actually), I don't know how to communicate such a dependency
without touching the generic gpio-led code--- which I'm trying to avoid.

I just want gpio-led to try again if the gpio pin it has been provided
can't be requested yet.  And I can see the need for similar behavior in
several other of my drivers, hence the desire to generalize things a
bit.  I'm pretty sure my approach is only half-baked, but it does seem
to avoid the need to touch a bunch of existing code--- especially to add
board-specific dependencies.  It just give the system a tool to sort
things out on its own.

I do think your overall criticism is valid, though.


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: A better way to sequence driver initialization?

2010-04-09 Thread Bill Gatliff
Bill Gatliff wrote:
>
> ... and kset_register() might be the only place that calls
> wake_up_interruptible().  Wow.
>   

Wow, indeed.  With just the attached patch, I get exactly one OOPS
now--- in ssc_free(), which I think is getting called because
atmel_ssc_modinit() is racing with something.

I wasn't able to get all the way to mounting my NFS rootfs, I think
because I'm getting to ip_auto_config() before my ethernet controller
has registered!  :)


$ git diff lib/kobject.c
diff --git a/lib/kobject.c b/lib/kobject.c
index b512b74..e75556c 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -18,6 +18,10 @@
 #include 
 #include 

+#include 
+#include 
+DECLARE_WAIT_QUEUE_HEAD(kset_wait);
+
 /*
  * populate_dir - populate directory with attributes.
  * @kobj: object we're working on.
@@ -721,6 +725,7 @@ int kset_register(struct kset *k)
if (err)
return err;
kobject_uevent(&k->kobj, KOBJ_ADD);
+   wake_up_interruptible(&kset_wait);
return 0;
 }

@@ -744,7 +749,7 @@ void kset_unregister(struct kset *k)
  * looking for a matching kobject. If matching object is found
  * take a reference and return the object.
  */
-struct kobject *kset_find_obj(struct kset *kset, const char *name)
+struct kobject *__kset_find_obj(struct kset *kset, const char *name)
 {
struct kobject *k;
struct kobject *ret = NULL;
@@ -760,6 +765,14 @@ struct kobject *kset_find_obj(struct kset *kset,
const char *name)
return ret;
 }

+struct kobject *kset_find_obj(struct kset *kset, const char *name)
+{
+   struct kobject *ret = NULL;
+   wait_event_interruptible(kset_wait, (ret = __kset_find_obj(kset,
name)));
+   return ret;
+}
+
 static void kset_release(struct kobject *kobj)
 {
struct kset *kset = container_of(kobj, struct kset, kobj);


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: A better way to sequence driver initialization?

2010-04-09 Thread Bill Gatliff
Bill Gatliff wrote:
> Maybe there are fewer places that would need wait queues than I
> originally thought!  At least for drivers that use the device API,
> kset_find_obj() might be the only place that needs to wait until a
> device or bus appears.

... and kset_register() might be the only place that calls
wake_up_interruptible().  Wow.


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: A better way to sequence driver initialization?

2010-04-09 Thread Bill Gatliff
Bill Gatliff wrote:
> If someone doesn't tell me this is a stupid idea, I might post it to
> lkml.  Now's your chance!  :)
>   

So I went ahead and tried it anyway:


$ git diff init/main.c
diff --git a/init/main.c b/init/main.c
index dac44a9..1461d09 100644
--- a/init/main.c
+++ b/init/main.c
@@ -753,7 +753,11 @@ static void __init do_initcalls(void)
initcall_t *fn;

for (fn = __early_initcall_end; fn < __initcall_end; fn++)
+#if 1
+   kthread_run(do_one_initcall, *fn, "do_initcalls");
+#else
do_one_initcall(*fn);
+#endif

/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();

Interestingly, things didn't blow up as quickly as I had expected they
would.  :)

Booting with initcall_debug=1 both with and without the kthread_run()
mod has proven insightful.  The first OOPS I get with the mod looks like
this:

...
calling  ch_init+0x0/0x18 @ 325
Unable to handle kernel NULL pointer dereference at virtual address

pgd = c0004000
[] *pgd= 
Internal error: Oops: 5 [#4] PREEMPT 
last sysfs file:
Modules linked in: 
CPU: 0 Tainted: GD  (2.6.33-rc5-csb737-00010-gaba040a-dirty #59)
PC is at kset_find_obj+0x18/0x98
LR is at kset_find_obj+0x18/0x98
pc : [] lr : [] psr: 2013
sp : c3937f68  ip : c3937f68  fp : 
r10:   r9 :   r8 : 
r7 : c0396a6f  r6 :   r5 : 0005  r4 : c03f03b0
r3 : 0003  r2 : c3936000  r1 :   r0 : 0001
Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 0005317f  Table: 20004000  DAC: 0017
Process do_initcalls (pid: 325, stack limit = 0xc3936270) 
Stack: (0xc3937f68 to 0xc3938000) 
7f60: c03fc050 c03f03b0 0005 c03f03b0  c01c471c
7f80: c03f03b0 0005 c001e62c   c024007c 
1b58d32c
7fa0: 0005 c002c39c c381bfac c001e62c 1b58d32c 0005 
c3937fd4
7fc0: c381bfac c001e62c c002c340 c005cb3c   c3937fd8
c3937fd8
7fe0:      c002df78 

[] (kset_find_obj+0x18/0x98) from []
(driver_register+0x88/0x150)
[] (driver_register+0x88/0x150) from []
(__hid_register_driver+0x38/0x70) 
[] (__hid_register_driver+0x38/0x70) from []
(do_one_initcall+0x5c/0x1c4) 
[] (do_one_initcall+0x5c/0x1c4) from []
(kthread+0x78/0x80)
[] (kthread+0x78/0x80) from []
(kernel_thread_exit+0x0/0x8)
Code: e24dd004 e3a1 e1a07001 ebfaf76c (e5963000)
---[ end trace f9bb68fd55862436 ]--- 
note: do_initcalls[325] exited with preempt_count 1
...

There is a ch_init() function in drivers/hid/hid-cherry.c.  I think that
function is calling hid_register_driver() before hid_init() has set up
hid_bus_type.  That causes kset_find_obj() to die because the kset
structure it gets passed in ch_init() refers to a bus that doesn't exist
yet.  It's a plain 'ole initialization race.

Maybe there are fewer places that would need wait queues than I
originally thought!  At least for drivers that use the device API,
kset_find_obj() might be the only place that needs to wait until a
device or bus appears.  If I get a second next week, I might hack one in
there and see how much farther I get...


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


A better way to sequence driver initialization?

2010-04-09 Thread Bill Gatliff
Guys:


My recent post, "Requesting a GPIO that hasn't been registered yet", and
Anton's reply thereto (thanks, Anton!) on linuxppc-dev got me thinking
about the problem of dependencies between devices in different  classes,
and/or between drivers/devices in general.  I'd like to float an idea to
see if it's worth pursuing.

Changing the link order to get drivers to initialize in the right order
will always be a problem for someone--- the order will be right for some
people, but exactly wrong for others.  And the problem is made worse for
Device Tree-based systems, where just about everything including IRQ
descriptors are created on a demand and/or as-available basis.  What if
we let the kernel sort those dependencies out for us, at runtime?  I
think it's possible, and I can't be the only one who would like to see
this happen.

There are two parts to my idea for a solution.  First part is to modify
do_initcalls() so that it launches each initcall function in its own
kernel thread.  Wait, don't panic yet!

Second, we create/modify functions like gpio_request() so that if they
fail, they can optionally stop in a wait queue until the call could
succeed.  Then gpiochip_add() would signal that queue each time a new
gpiochip was added. Functions like request_irq() and clk_get()--- and
probably many others--- would do the same thing, but with their own wait
queues.

Something like this:

static wait_queue_head_t requestor_wq;

int gpiochip_add(struct gpio_chip *chip)
{
...
wake_up_interruptible(&requestor_wq);
return status;
}

int gpio_request_wait(unsigned gpio, const char *label)
{
return wait_event_interruptible(&requestor_wq,
!gpio_request(gpio, label));
}


Or we might want to make the above code be the actual gpio_request(),
and bury the wait_event_interruptible() inside of that.  Doing so would
prevent having to touch a lot of code, but would definitely change the
behavior of gpio_request().  Not sure which approach is best.

Finally, I think that do_initcalls() would turn into something like this:

static void __init do_initcalls(void)
{
initcall_t *fn;

for (fn = __early_initcall_end; fn < __initcall_end; fn++)
kthread_create(do_one_initcall, *fn, "do_initcalls");

flush_scheduled_work();
}


If someone doesn't tell me this is a stupid idea, I might post it to
lkml.  Now's your chance!  :)


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Requesting a GPIO that hasn't been registered yet

2010-03-30 Thread Bill Gatliff
Guys:


I'm sure this is a FAQ, but I can't seem to find the answer.  I'm happy
to RTFM, if someone can please tell me where the FM is.  :)

I'm adding device table support to gpio_keys.  The target is an
MPC5200B.  I have statements in my dts file that look like this:

...
i...@3d40 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
reg = <0x3d40 0x40>;
interrupts = <2 16 0>;
...
lext60: max7...@60 {
compatible = "maxim,max7314","phillips,pca953x";
reg = <0x60>;
gpio-controller;
#gpio-cells = <2>;
};
};
...
gpio-keys {
  compatible = "gpio-keys";
  encoder_button {
 gpios = <&lext60 12 0>;
 code = <28>;
 type = <1>;
 active-low = <0>;
 wakeup = <0>;
 debounce-interval = <0>;
 rep = <0>;
 };
 };

In other words, the GPIO pin I'm using for the key is one of the bits on
my pca953x GPIO expander chip.

The above would all be great, except that I haven't come up with a way
to make sure that my encoder_button doesn't try to probe before lext60
is available.  In fact, I'm consistently getting initialization in the
wrong order!

Eventually the GPIO expander chip gets plugged in, because I can see it
show up in sysfs.  And what's really odd is, I recently made similar
mods to gpio_leds and they are working fine--- although the GPIO pin is
on a pca953x at address 20, instead of 60.  I'm at a loss to explain why
one works, but the other doesn't.  And I don't know how to really fix
this problem for good!

Any suggestions?  Thanks!!


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Sleep-capable GPIO slave-selects on MPC52xx?

2010-01-12 Thread Bill Gatliff
Bill Gatliff wrote:
>
> It looks like the current version of the MPC52xx SPI driver won't work
> with sleep-capable GPIOs for slave-selects.  In particular, it looks
> like mpc52xx_spi_fsmstate_transfer() is an interrupt handler that calls
> mpc52xx_spi_chipsel(), which itself calls gpio_set_value().  Or, at
> least my kernel thinks so, since I get a barrage of oops-type output
> screaming at me whenever I hit the SPI device.  :)
>
> Am I missing something, or is this a known (or at least now-identified)
> limitation of the current mpc52xx_spi.c?
>   

So, nobody has any feedback on this?  :)

Would using a threaded handler for the SPI interrupts be likely to work
here?


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Sleep-capable GPIO slave-selects on MPC52xx?

2010-01-11 Thread Bill Gatliff
Guys:


A platform I have inherited utilizes a GPIO on an I2C expander chip
(MAX7314) as a SPI slave-select.  I'm using the actual MPC52xx SPI
peripheral, not a PSC.

It looks like the current version of the MPC52xx SPI driver won't work
with sleep-capable GPIOs for slave-selects.  In particular, it looks
like mpc52xx_spi_fsmstate_transfer() is an interrupt handler that calls
mpc52xx_spi_chipsel(), which itself calls gpio_set_value().  Or, at
least my kernel thinks so, since I get a barrage of oops-type output
screaming at me whenever I hit the SPI device.  :)

Am I missing something, or is this a known (or at least now-identified)
limitation of the current mpc52xx_spi.c?


Thanks!


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 0/2] Create an of_i2c_gpiochip_add()

2010-01-06 Thread Bill Gatliff
Wolfram Sang wrote:
>> Does the lack of response mean I'll be seeing these in an upcoming
>> kernel release?  I'd like to, because then I could more easily push
>> 
>
> As long as nobody said "I picked it up", it will probably not. Patches
> regarding GPIO sometimes need a bit of time. Also, of_platform was in the
> discussion of being removed, this might complicate things, too.
>   

Is this the right mailing list for such patches, though?


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 0/2] Create an of_i2c_gpiochip_add()

2010-01-06 Thread Bill Gatliff
Bill Gatliff wrote:
> This patch series creates an of_i2c_gpiochip_add() function, to allow
> i2c-based GPIO expanders to work with device tree gpio specifications.
>   

So nobody has any yays or nays on this?  I was expecting at least
_something_!  :)

Does the lack of response mean I'll be seeing these in an upcoming
kernel release?  I'd like to, because then I could more easily push
through related updates to a few i2c device drivers that I have in my
local repo.


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: How to set GPIO state in the dts or in platform

2010-01-06 Thread Bill Gatliff
Ayman El-Khashab wrote:
> On 1/5/2010 10:38 PM, Bill Gatliff wrote:
>> Ayman El-Khashab wrote:
>>  
>>> I've got a custom board akin to the walnut.  I've successfully got
>>> u-boot,
>>> the kernel, and a working filesystem.  The only thing I lack is a
>>> clear idea
>>> of how to set a GPIO.
>>> 
>>
>> Isn't that the "flags" parameter, e.g.:
>>
>> gpios = 
>>
>> ?
>>
>> If you are passing a 0 for the flags, try a 1.  I know of at least one
>> driver that interprets that to mean a polarity inversion.  Maybe you'll
>> get lucky.  :)
>>
>>   
> Possibly, I saw that in the documentation directory, but didn't quite
> follow the explanation that
> was given.  Below is what I was using as  a reference, but is it as
> simple as that?  Do the flags encode
> just the state or also, the open drain, hi-z and everything else?  In
> my case, I want the GPIO 3 actively
> driven high.

The flags can encode everything, or nothing.  It all depends on what the
caller of of_get_gpio_flags() does with them.  (Note that I'm not an
authority on this topic, I'm just telling what I've learned about it
recently).

For example, in of_mpc8xxx_spi_get_chipselects(), the flag is tested
against OF_GPIO_ACTIVE_LOW, and the result is passed to
gpio_direction_output() as the initial value.  So it both inverts the
sense of the pin, and sets its initial state.

In of_gpio_leds_probe(), the flag is tested against OF_GPIO_ACTIVE_LOW
as well.

In both of the above examples, the drivers can make assumptions about
things like the pin must be an output, will be actively driven in either
direction, and so on.  The convention is for the flag to be a bitmap of
values from the of_gpio_flags enumeration, but the only value there
is--- you guessed it--- OF_GPIO_ACTIVE_LOW.  :)

If you provide your own xlate() function in a of_gpio_chip driver, you
can make the flags mean anything you want.  As for anywhere you call
of_gpio_get_flags().  For now, the only established interpretation is
the OF_GPIO_ACTIVE_LOW one.


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: How to set GPIO state in the dts or in platform

2010-01-05 Thread Bill Gatliff
Ayman El-Khashab wrote:
> I've got a custom board akin to the walnut.  I've successfully got
> u-boot,
> the kernel, and a working filesystem.  The only thing I lack is a
> clear idea
> of how to set a GPIO.

Isn't that the "flags" parameter, e.g.:

gpios = 

?

If you are passing a 0 for the flags, try a 1.  I know of at least one
driver that interprets that to mean a polarity inversion.  Maybe you'll
get lucky.  :)


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 0/2] *** SUBJECT HERE ***

2010-01-05 Thread Bill Gatliff
Bill Gatliff wrote:
> *** BLURB HERE ***
>   

Dangit, sometimes I really hate it when emacs leaves its backup files
around...  :(

Like now, for example.  Please disregard the noise generated by my
careless use of filename wildcards...


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[RFC/PATCH 0/2] Updates to improve device tree support

2010-01-05 Thread Bill Gatliff
This patch series updates the pca953x GPIO driver to take advantage
of the new of_i2c_gpiochip_add() function, which registers i2c GPIO
devices with the device tree API.  These changes allow i2c-based GPIO
expanders to be properly referenced from the proper entries in a
device tree.

The of_i2c_gpiochip_add() function has been posted for review on the
linuxppc-dev mailing list.

Bill Gatliff (2):
  Use struct of_i2c_gpio_chip instead of raw struct gpio_chip
  Reorder initialization to better support device tree data

 drivers/gpio/pca953x.c |  168 +---
 1 files changed, 88 insertions(+), 80 deletions(-)

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/2] Reorder initialization to better support device tree data

2010-01-05 Thread Bill Gatliff
This patch changes the initialization sequence implemented in
pca953x_probe(), so as to simplify the retrieval of device tree
data when device trees are used.  Incorporates the new
of_i2c_gpiochip_add() function to register the newly-added GPIOs.

Signed-off-by: Bill Gatliff 
---
 drivers/gpio/pca953x.c |  130 +--
 1 files changed, 58 insertions(+), 72 deletions(-)

diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 9c70963..3a20e2f 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2005 Ben Gardner 
  *  Copyright (C) 2007 Marvell International Ltd.
+ *  Copyright (C) 2010 Bill Gatliff 
  *
  *  Derived from drivers/i2c/chips/pca9539.c
  *
@@ -53,13 +54,13 @@ static const struct i2c_device_id pca953x_id[] = {
 MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
 struct pca953x_chip {
-   unsigned gpio_start;
uint16_t reg_output;
uint16_t reg_direction;
+   uint16_t reg_invert;
struct gpio_chip *gpio_chip;
 
struct i2c_client *client;
-   struct pca953x_platform_data *dyn_pdata;
+   struct pca953x_platform_data *pdata;
char **names;
 
 #ifdef CONFIG_OF_GPIO
@@ -214,7 +215,6 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, 
int gpios)
gc->set = pca953x_gpio_set_value;
gc->can_sleep = 1;
 
-   gc->base = chip->gpio_start;
gc->ngpio = gpios;
gc->label = chip->client->name;
gc->dev = &chip->client->dev;
@@ -222,119 +222,107 @@ static void pca953x_setup_gpio(struct pca953x_chip 
*chip, int gpios)
gc->names = chip->names;
 }
 
-/*
- * Handlers for alternative sources of platform_data
- */
 #ifdef CONFIG_OF_GPIO
-/*
- * Translate OpenFirmware node properties into platform_data
- */
-static struct pca953x_platform_data *
-pca953x_get_alt_pdata(struct i2c_client *client)
+static int __devinit pca953x_get_of_pdata(struct pca953x_chip *chip)
 {
-   struct pca953x_platform_data *pdata;
struct device_node *node;
const uint16_t *val;
 
-   node = dev_archdata_get_node(&client->dev.archdata);
-   if (node == NULL)
-   return NULL;
+   node = dev_archdata_get_node(&chip->client->dev.archdata);
+   if (!node)
+   return -EINVAL;
 
-   pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL);
-   if (pdata == NULL) {
-   dev_err(&client->dev, "Unable to allocate platform_data\n");
-   return NULL;
-   }
-
-   pdata->gpio_base = -1;
-   val = of_get_property(node, "linux,gpio-base", NULL);
-   if (val) {
-   if (*val < 0)
-   dev_warn(&client->dev,
-"invalid gpio-base in device tree\n");
-   else
-   pdata->gpio_base = *val;
-   }
+   chip->gpio_chip->base = -1;
+   chip->i2c_gc.of_gc.gpio_cells = 2;
 
val = of_get_property(node, "polarity", NULL);
if (val)
-   pdata->invert = *val;
+   chip->reg_invert = *val;
 
-   return pdata;
+   return 0;
 }
-#else
-static struct pca953x_platform_data *
-pca953x_get_alt_pdata(struct i2c_client *client)
+
+static int __devinit pca953x_gpiochip_add(struct pca953x_chip *chip)
 {
-   return NULL;
+   struct device_node *node;
+   node = dev_archdata_get_node(&chip->client->dev.archdata);
+   return of_i2c_gpiochip_add(node, &chip->i2c_gc);
 }
 #endif
 
+static int __devinit pca953x_get_pdata(struct pca953x_chip *chip)
+{
+   struct pca953x_platform_data *pdata;
+
+   pdata = dev_get_platdata(&chip->client->dev);
+   if (!pdata)
+   return -EINVAL;
+
+   chip->pdata = pdata;
+   chip->gpio_chip->base = pdata->gpio_base;
+   chip->reg_invert = pdata->invert;
+
+   return 0;
+}
+
 static int __devinit pca953x_probe(struct i2c_client *client,
   const struct i2c_device_id *id)
 {
-   struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
int ret;
 
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
+   chip->client = client;
 
 #ifdef CONFIG_OF_GPIO
chip->gpio_chip = &chip->i2c_gc.of_gc.gc;
+   if (!dev_get_platdata(&client->dev))
+   pca953x_get_of_pdata(chip);
 #else
chip->gpio_chip = &chip->gc;
-#endif
-
-   pdata = client->dev.platform_data;
-   if (pdata == NULL) {
-   pdata = pca953x_get_alt_pdata(client);
-   /*
-* Unlike normal platform_data, this is allocated
-* dynamically and must be freed

[PATCH 1/2] Use struct of_i2c_gpio_chip instead of raw struct gpio_chip

2010-01-05 Thread Bill Gatliff
This patch is the first in a series that improves the pca953x driver's
support for CONFIG_OF_GPIO a.k.a. device trees.  It modifies the driver's
chip structure definition to use a struct gpio_chip contained in a struct
of_i2c_gpio_chip when CONFIG_OF_GPIO is set.  If OF_GPIO is not used,
an ordinary struct gpio_chip is employed.

Signed-off-by: Bill Gatliff 
---
 drivers/gpio/pca953x.c |   50 ++-
 1 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index b097043..9c70963 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -56,18 +56,34 @@ struct pca953x_chip {
unsigned gpio_start;
uint16_t reg_output;
uint16_t reg_direction;
+   struct gpio_chip *gpio_chip;
 
struct i2c_client *client;
struct pca953x_platform_data *dyn_pdata;
-   struct gpio_chip gpio_chip;
char **names;
+
+#ifdef CONFIG_OF_GPIO
+   struct of_i2c_gpio_chip i2c_gc;
+#else
+   struct gpio_chip gc;
+#endif
 };
 
+static inline struct pca953x_chip *to_pca953x_chip(struct gpio_chip *gc)
+{
+#ifdef CONFIG_OF_GPIO
+   return container_of(gc, struct pca953x_chip, i2c_gc.of_gc.gc);
+#else
+   return container_of(gc, struct pca953x_chip, gc);
+#endif
+}
+
+
 static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
 {
int ret;
 
-   if (chip->gpio_chip.ngpio <= 8)
+   if (chip->gpio_chip->ngpio <= 8)
ret = i2c_smbus_write_byte_data(chip->client, reg, val);
else
ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
@@ -84,7 +100,7 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int 
reg, uint16_t *val)
 {
int ret;
 
-   if (chip->gpio_chip.ngpio <= 8)
+   if (chip->gpio_chip->ngpio <= 8)
ret = i2c_smbus_read_byte_data(chip->client, reg);
else
ret = i2c_smbus_read_word_data(chip->client, reg << 1);
@@ -104,7 +120,7 @@ static int pca953x_gpio_direction_input(struct gpio_chip 
*gc, unsigned off)
uint16_t reg_val;
int ret;
 
-   chip = container_of(gc, struct pca953x_chip, gpio_chip);
+   chip = to_pca953x_chip(gc);
 
reg_val = chip->reg_direction | (1u << off);
ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
@@ -122,7 +138,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip 
*gc,
uint16_t reg_val;
int ret;
 
-   chip = container_of(gc, struct pca953x_chip, gpio_chip);
+   chip = to_pca953x_chip(gc);
 
/* set output level */
if (val)
@@ -152,7 +168,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, 
unsigned off)
uint16_t reg_val;
int ret;
 
-   chip = container_of(gc, struct pca953x_chip, gpio_chip);
+   chip = to_pca953x_chip(gc);
 
ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val);
if (ret < 0) {
@@ -172,7 +188,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, 
unsigned off, int val)
uint16_t reg_val;
int ret;
 
-   chip = container_of(gc, struct pca953x_chip, gpio_chip);
+   chip = to_pca953x_chip(gc);
 
if (val)
reg_val = chip->reg_output | (1u << off);
@@ -190,7 +206,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, 
int gpios)
 {
struct gpio_chip *gc;
 
-   gc = &chip->gpio_chip;
+   gc = chip->gpio_chip;
 
gc->direction_input  = pca953x_gpio_direction_input;
gc->direction_output = pca953x_gpio_direction_output;
@@ -265,6 +281,12 @@ static int __devinit pca953x_probe(struct i2c_client 
*client,
if (chip == NULL)
return -ENOMEM;
 
+#ifdef CONFIG_OF_GPIO
+   chip->gpio_chip = &chip->i2c_gc.of_gc.gc;
+#else
+   chip->gpio_chip = &chip->gc;
+#endif
+
pdata = client->dev.platform_data;
if (pdata == NULL) {
pdata = pca953x_get_alt_pdata(client);
@@ -306,13 +328,13 @@ static int __devinit pca953x_probe(struct i2c_client 
*client,
goto out_failed;
 
 
-   ret = gpiochip_add(&chip->gpio_chip);
+   ret = gpiochip_add(chip->gpio_chip);
if (ret)
goto out_failed;
 
if (pdata->setup) {
-   ret = pdata->setup(client, chip->gpio_chip.base,
-   chip->gpio_chip.ngpio, pdata->context);
+   ret = pdata->setup(client, chip->gpio_chip->base,
+   chip->gpio_chip->ngpio, pdata->context);
if (ret < 0)
dev_warn(&client->dev, "setup failed, %d\n", ret);
}
@@ -333,8 +355,8 @@ static int pca953x_remove(struct i2c_client *client)
int ret = 0;
 
   

[PATCH 0/2] *** SUBJECT HERE ***

2010-01-05 Thread Bill Gatliff
*** BLURB HERE ***

Bill Gatliff (2):
  Use struct of_i2c_gpio_chip instead of raw struct gpio_chip
  Reorder initialization to better support device tree data

 drivers/gpio/pca953x.c |  168 +---
 1 files changed, 88 insertions(+), 80 deletions(-)

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/2] Create a struct of_i2c_gpio_chip, for i2c-based GPIO devices

2010-01-05 Thread Bill Gatliff

Signed-off-by: Bill Gatliff 
---
 include/linux/of_gpio.h |   23 +++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index fc2472c..0c39242 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -102,4 +102,27 @@ static inline int of_get_gpio(struct device_node *np, int 
index)
return of_get_gpio_flags(np, index, NULL);
 }
 
+
+
+
+/*
+ * OF GPIO chip for I2C-based devices
+ */
+struct of_i2c_gpio_chip {
+   struct of_gpio_chip of_gc;
+};
+
+static inline struct of_i2c_gpio_chip *to_of_i2c_gpio_chip(struct gpio_chip 
*gc)
+{
+   struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
+
+   return container_of(of_gc, struct of_i2c_gpio_chip, of_gc);
+}
+
+extern int of_i2c_gpiochip_add(struct device_node *np,
+  struct of_i2c_gpio_chip *gc);
+
+
+
+
 #endif /* __LINUX_OF_GPIO_H */
-- 
1.6.5

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 0/2] Create an of_i2c_gpiochip_add()

2010-01-05 Thread Bill Gatliff
This patch series creates an of_i2c_gpiochip_add() function, to allow
i2c-based GPIO expanders to work with device tree gpio specifications.

Bill Gatliff (2):
  Create a struct of_i2c_gpio_chip, for i2c-based GPIO devices
  Create an of_i2c_gpiochip_add()

 drivers/of/gpio.c   |   55 +++
 include/linux/of_gpio.h |   23 +++
 2 files changed, 78 insertions(+), 0 deletions(-)

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 2/2] Create an of_i2c_gpiochip_add()

2010-01-05 Thread Bill Gatliff

Signed-off-by: Bill Gatliff 
---
 drivers/of/gpio.c |   55 +
 1 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 6eea601..56b438a 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -217,3 +217,58 @@ err0:
return ret;
 }
 EXPORT_SYMBOL(of_mm_gpiochip_add);
+
+/**
+ * of_i2c_gpiochip_add - Add memory I2C-based GPIO chip
+ * @np:device node of the GPIO chip
+ * @gc:pointer to the of_i2c_gpio_chip allocated structure
+ *
+ * To use this function you should allocate and fill gc with:
+ *
+ * 1) In the gpio_chip structure:
+ *- all the callbacks
+ *
+ * 2) In the of_gpio_chip structure:
+ *- gpio_cells
+ *- xlate callback (optional)
+ *
+ * If succeeded, this function will do something useful...
+ */
+int of_i2c_gpiochip_add(struct device_node *np,
+   struct of_i2c_gpio_chip *i2c_gc)
+{
+   int ret = -ENOMEM;
+   struct of_gpio_chip *of_gc = &i2c_gc->of_gc;
+   struct gpio_chip *gc = &of_gc->gc;
+
+   gc->label = kstrdup(np->full_name, GFP_KERNEL);
+   if (!gc->label)
+   goto err0;
+
+   gc->base = -1;
+
+   if (!of_gc->xlate)
+   of_gc->xlate = of_gpio_simple_xlate;
+
+   np->data = of_gc;
+
+   ret = gpiochip_add(gc);
+   if (ret)
+   goto err2;
+
+   /* We don't want to lose the node and its ->data */
+   of_node_get(np);
+
+   pr_debug("%s: registered as generic GPIO chip, base is %d\n",
+np->full_name, gc->base);
+   return 0;
+err2:
+   np->data = NULL;
+err1:
+   kfree(gc->label);
+err0:
+   pr_err("%s: GPIO chip registration failed with status %d\n",
+  np->full_name, ret);
+   return ret;
+}
+EXPORT_SYMBOL(of_i2c_gpiochip_add);
-- 
1.6.5

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Trouble specifying dts gpio-leds with GPIO expander chip

2009-12-31 Thread Bill Gatliff
Anton Vorontsov wrote:
> Though, soon there will be an easier way to register I2C/SPI chips
> with the OF GPIO infrastructure.
>   

Should this make me hesitate to update the pca953x driver, or clone it?


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Question on MPC52xx IRQ[123] pins

2009-12-31 Thread Bill Gatliff
Grant Likely wrote:
> Correct.  IRQ2 can only be used as IRQ2.  It cannot be used a GPIO.
> (Well, I suppose you *could* try to hack into the interrupt controller
> driver and fetch the pin state that way; but I don't know if you can
> read the state of masked out IRQ pins, and it sure would be ugly.)
>   

Actually, I did think of a way you could do this.  You could register an
interrupt handler on the line, and set the irq type to level-low or
level-high.  Depending on whether the handler fires right away, you know
what the state of the pin must be.  And when the interrupt handler does
fire, you switch the irq type to the opposite setting.

I think that approach rates pretty high on the "ugly scale" too, but
perhaps tolerably so.  In fact, were I to actually need to interface one
of the IRQ lines to gpiolib, I might attempt this...


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 1/1] Adds gpio_to_irq() and related support to the mpc52xx_gpio WKUP peripheral driver

2009-12-30 Thread Bill Gatliff
Bill Gatliff wrote:
> Second, the previously-unimplemented gpio_to_irq() function was added,
> using __gpio_to_irq().  The author does not know why this code was previously
> left out of arch/powerpc/include/asm/gpio.h.  It seems to work.  The generic
> irq_to_gpio() function was not tested.
>   

Actually, I just noticed that this patch was already committed but I
hadn't pulled it in to my repo so I ended up re-discovering and
duplicating it.

The rest of the comments for this patch are accurate.


b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 1/1] Adds gpio_to_irq() and related support to the mpc52xx_gpio WKUP peripheral driver

2009-12-30 Thread Bill Gatliff
This patch cascades the GPIO_WKUP peripheral's eight pins into separate,
virtual interrupt descriptors.  This demultiplexing relieves driver authors
of having to demultiplex and manage the pins on their own.

Several important changes were necessary to implement this support, beyond
just the addition of the cascading and irq_host functions.  First, the
gpiochip devices are now registered during arch_initcall.  Without this
modification, the virtual interrupt mapping changes during startup in ways
that cause drivers to "lose" their interrupt-to-handler mappings.  The
mpc52xx FEC driver, for example, will fail to receive interrupts if the
gpiochip and irq_host registrations happen at subsys_initcall as was done
in the previous version of the driver.

Second, the previously-unimplemented gpio_to_irq() function was added,
using __gpio_to_irq().  The author does not know why this code was previously
left out of arch/powerpc/include/asm/gpio.h.  It seems to work.  The generic
irq_to_gpio() function was not tested.

Finally, the interrupt-controller property was added to the mpc52xx_gpio device
tree entry for the WKUP peripheral.  The interrupt demultiplexing code is
installed only when this property is present.  The author's device tree node
for the GPIO_WKUP peripheral looks like this:

gpio_wkup: g...@c00 {
compatible = 
"fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
#gpio-cells = <2>;
#address-cells = <0>;
reg = <0xc00 0x40>;

interrupt-parent = <&mpc5200_pic>;
interrupts = <1 8 0  0 3 0>;

gpio-controller;
interrupt-controller;
#interrupt-cells = <3>;
};

The author generally refrains from modifying working code.  However, there were 
a large
number of redundant statements in the existing gpiolib implementation code to 
compute
bit masks for pins, and these masks needed to be consistent throughout the gpio 
and interrupt
cascading implementation.  The redundant statements were replaced with a new
mpc52xx_wkup_gpio_to_mask() helper function.

The gpio-to-irq mapping follows the convention established by the gpiolib 
driver.
Specifically, gpio pin 0 is GPIO_WKUP_7, pin 1 is GPIO_WKUP_6, and so on.  An 
example of
a device tree node that attaches to GPIO_WKUP_7 looks like this (the associated 
driver is
a modified version of the existing drivers/misc/input/rotary_encoder.c):

rotary-encoder {
compatible = "linux,rotary-encoder","rotary-encoder";
interrupts = <&mpc5200_pic 1 2 3>;
gpios = <&gpio_wkup 0 0>;

type = <1>;
val-ccw = <0x4a>;
val-cw = <78>;
};

The three values in the "gpios =" statement are the phandle for the gpio 
controller,
the peripheral pin number, and a flag that is currently ignored.  The 
rotary-encoder
driver uses of_get_gpio_flags() to get the gpiolib value for the pin:

cfg->gpio[wchan] = of_get_gpio_flags(ofdev->node, ngpio++, 
NULL);

The value returned by of_get_gpio_flags() can be passed to gpio_to_irq(), and 
then
on to request_irq().

The GPIO_WKUP peripheral supports limited options for interrupt types, 
including:

IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_BOTH

The driver emulates IRQ_TYPE_LEVEL_LOW and IRQ_TYPE_LEVEL_HIGH types using 
falling
and rising edges, respectively, but this code has not been extensively tested.  
The
GPIO_WKUP peripheral's "pulse" interrupt type is not supported.

This driver does not currently support Deep Sleep wakeups, only non-Deep Sleep 
ones.
The Deep Sleep wakeups appear to be most suited for support under power 
management
functionality, and not gpio-related operations.

Signed-off-by: Bill Gatliff 
---
 arch/powerpc/platforms/52xx/mpc52xx_gpio.c |  328 ++-
 1 files changed, 267 insertions(+), 61 deletions(-)

diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c 
b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
index 2b8d8ef..67d91d2 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
@@ -1,6 +1,7 @@
 /*
  * MPC52xx gpio driver
  *
+ * Copyright (c) 2010 Bill Gatliff 
  * Copyright (c) 2008 Sascha Hauer , Pengutronix
  *
  * This program is free software; you can redistribute it and/or modify
@@ -22,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -34,8 +36,18 @@ struct mpc52xx_gpiochip {
unsigned int shadow_dvo;
unsigned int shadow_gpioe;
unsigned int shadow_ddr;
+   unsigned int shadow_iinten;

Re: Does gpio_to_irq() work for MPC52xx gpios?

2009-12-29 Thread Bill Gatliff
Peter Korsgaard wrote:
>>>>>> "Bill" == Bill Gatliff  writes:
>>>>>> 
>
>  Bill> Guys:
>  Bill> Is it possible to specify an individual GPIO pin as an interrupt source
>  Bill> with the current MPC52xx code?
>
> No (not yet). In Ben's latest pull request there's a patch from me to
> add basic infrastructure for gpio_to_irq(). I've recently added irq
> support to the mpc8xxx driver, but so far nothing has been written for
> 52xx.
>
> http://patchwork.ozlabs.org/patch/41550/
>   

Ok, after looking at your code for a few days I'm even more lost than
when I started!

On the MPC5200, all the GPIO_WKUP pins are multiplexed into a single
interrupt line, which is Main_Mask8. As currently defined by
mpc52xx_pic.c, that's a virtual interrupt number of 72. So generally
speaking, if I do a request_irq() on 72, I'll get an interrupt any time
an enabled GPIO_WKUP pin changes state.

What I want to be able to do is a request_irq(gpio_to_irq(GPIO_WKUP_7),
...), so that I can have a single interrupt handler for each GPIO_WKUP
pin. To do this, I think the general idea is as follows:

1. create a virtual interrupt number for each GPIO_WKUP line
2. install a chained interrupt handler on interrupt 72
3. inside the chained handler, map each active GPIO_WKUP pin to its
associated virtual interrupt number, and invoke the associated interrupt
handler by passing that virtual interrupt number to generic_handle_irq()
4. provide a gpio_to_irq that can map GPIO offsets to their associated
virtual interrupt numbers

I'm trying to implement the above, but I'm getting lost in all the IRQ
mapping and virtualization. Can someone show me what I'm doing wrong in
my code?

I've put a complete copy of my modified mpc52xx_gpio.c on pastebin, with
my portions highlighted:

http://pastebin.com/f4c074ab8

A kernel message buffer log is here, also with the interesting lines
highlighted:

http://pastebin.com/f378d3c61

I get a mapping from hwirq 72 to a virq of 16. That seems fine. But
that's the extent of the good news. :)

The two GPIO pins I'm interested in are 222 and 223, which are
GPIO_WKUP_6 and GPIO_WKUP_7. In my gpio_to_irq() I'm doing this:

static int mpc52xx_wkup_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc52xx_gpiochip *c = to_mpc52xx_gpiochip(mm);

pr_err("%s mapping offset %d\n", __func__, offset);

if (c->irqhost && offset < MPC52XX_WKUP_GPIO_PINS)
return irq_create_mapping(c->irqhost, c->irq);
return -ENXIO;
}

That's not giving me what I want, it's just creating another mapping to
virtual irq 16. I know that code is wrong, I just don't know what the
right code should be...

Help, I'm lost! :)



Kindest regards,

b.g.

-- 
Bill Gatliff
Embedded systems training and consulting
http://billgatliff.com
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Does gpio_to_irq() work for MPC52xx gpios?

2009-12-23 Thread Bill Gatliff
Bill Gatliff wrote:
> Guys:
>
>
> Ok, I have gpio_to_irq() more-or-less showing signs of life for the
> MPC5200.  But I'm having some trouble using it the way I want to.
>   

I think I've got the idea all of a sudden.

In order to describe the inputs to my rotary encoder using the syntax I
want, I have to implement something similar to of_get_gpio_flags(), right?


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Does gpio_to_irq() work for MPC52xx gpios?

2009-12-23 Thread Bill Gatliff
Guys:


Ok, I have gpio_to_irq() more-or-less showing signs of life for the
MPC5200.  But I'm having some trouble using it the way I want to.

Recall that I have a rotary encoder that's tied to IRQ2 and
GPIO_WKUP_7.  I want to be able to describe it something like this:

rotary-encoder {
compatible = "linux,rotary-encoder","rotary-encoder";
interrupts = <&mpc5200_pic 2 3 &gpio_wkup 0 1>; // "IRQ2 on the
MPC5200 PIC,

   
// and pin 0 on GPIO_WKUP"
type = <1>; // what event signal to generate
val-ccw = <0x4a>; // what code to use for counter-clockwise rotation
val-cw = <78>; // what code to use for clockwise rotation
};

I've had some limited success with this, but not for any good reason. 
It turns out that the explanation for why I was getting a valid number
for the first interrupt specification was because the device tree
compiler was assuming that the interrupt-parent was the mpc5200_pic; my
reference to the node in that list was utterly meaningless.  The dtc
also appears to have ignored the &gpio_wkup word, and interpreted the
following zero as being the zero-th interrupt channel in the
mpc5200_pic.  Or something like that.  Clearly, I don't understand the
device tree syntax at all yet.

Anyway, when I change the statement to this:

rotary-encoder {
compatible = "linux,rotary-encoder","rotary-encoder";
interrupt-parent = <&gpio_wkup>;
interrupts = <0 0>;
type = <1>;
val-ccw = <0x4a>;
val-cw = <78>;
};

... then the magic number that the dtc comes up with is causing my new
chained interrupt handler for the gpio_wkup peripheral to come alive. 
(Of course it doesn't actually work yet, but that's not the point!)

So here's my question: does the device tree compiler/syntax limit you to
only one interrupt parent?

I think the answer is no, because what I'm trying to do doesn't seem
that much different from how one specifies GPIO pins coming from
different controllers.

Any suggestions?


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Does gpio_to_irq() work for MPC52xx gpios?

2009-12-23 Thread Bill Gatliff
Bill Gatliff wrote:
> Peter Korsgaard wrote:
>   
>> No (not yet). In Ben's latest pull request there's a patch from me to
>> add basic infrastructure for gpio_to_irq(). I've recently added irq
>> support to the mpc8xxx driver, but so far nothing has been written for
>> 52xx.
>>
>> http://patchwork.ozlabs.org/patch/41550/
>>   
>> 
>
> Ok.  I'm taking a look at that code now, planning to adapt it for the
> MPC52xx unless someone raises any objections.
>   

Ok, working on this now.  I'm pretty far along, but I'm stopped at what
I think is a device tree source file problem.

I have an external device that generates two interrupt outputs.  One of
them is connected to IRQ2, the other to GPIO_WKUP_7.  I'm describing the
device like this:

...
soc5...@f000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,mpc5200b-immr","simple-bus";
ranges = <0 0xf000 0xc000>;
reg = <0xf000 0x0100>;
bus-frequency = <0>;// from bootloader
system-frequency = <0>;// from bootloader
...
mpc5200_pic: interrupt-control...@500 {
// 5200 interrupts are encoded into two levels;
interrupt-controller;
gpio-controller;
#interrupt-cells = <3>;
#address-cells = <0>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
reg = <0x500 0x80>;
interrupts = < 0 0 3  1 1 3  2 2 2  3 3 2 >;
};
gpio_wkup: g...@c00 {
compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
#gpio-cells = <2>;
#interrupt-cells = <2>;
#address-cells = <0>;
#size-cells = <0>;
reg = <0xc00 0x40>;
interrupts = <1 8 0  0 3 0>;
interrupt-parent = <&mpc5200_pic>;
gpio-controller;
interrupt-controller;
};
...
};
...
system {
compatible = "simple-bus";

rotary-encoder {
compatible = "linux,rotary-encoder","rotary-encoder";
interrupts = <&mpc5200_pic 2 3  &gpio_wkup 0 0>;
//interrupts = <&mpc5200_pic 2 3>;
//gpios = <&gpio_wkup 0 0>;
type = <1>;
val-ccw = <0x4a>;
val-cw = <78>;
};
};

When I use the "gpios" property instead of the above, I get a useful
gpio number and I can see the signal using sys/class/gpio.  And I also
know the hardware is working because an ancient, pre-device-tree kernel
is working fine.  :)

The problem is that I'm not getting a valid number out for the second
interrupt specification, presumably because the dts compiler doesn't
have any idea how to generate the data--- and I have no idea how to fix
that.

I captured some dmesg information which shows the problem.  The first
line is for IRQ2, which is correct.  The second is for GPIO_WKUP_7,
which the kernel chokes on:

...
irq: irq_create_mapping(0xcf814000,
0x42) 
irq: -> using host
@cf814000  
  alloc irq_desc for 66 on node
0 
  alloc kstat_irqs on node
0  
mpc52xx_irqhost_map: External IRQ2 virq=42, hw=42.
type=8 
irq: irq 66 on host /soc5...@f000/interrupt-control...@500 mapped to
virtual irq
66  

mpc52xx_extirq_set_type: irq=42. l2=2
flow_type=8 
linux,rotary-encoder rotary-encoder.3: irq[0] 66 gpio[0] -2  <- my
driver's output, the "magic number" was 66
return 0, l1=4,
l2=0  
irq: irq_create_mapping(0xcf814000,
0x0)  
irq: -> using host
@cf814000  
  alloc irq_desc for 16 on node
0 
  alloc kstat_irqs on node
0  
mpc52xx_irqhost_map: External IRQ0 virq=10, hw=0.
type=8  
irq: irq 0 on host /soc5...@f000/interrupt-control...@500 mapped to
virtual irq
16  
 

mpc52xx_extirq_set_type: irq=0. l2=0
flow_type=8  
linux,rotary-encoder rotary-encoder.3: irq[1] 16 gpio[1] -2 <-
my

Re: Does gpio_to_irq() work for MPC52xx gpios?

2009-12-23 Thread Bill Gatliff
Peter Korsgaard wrote:
>
> No (not yet). In Ben's latest pull request there's a patch from me to
> add basic infrastructure for gpio_to_irq(). I've recently added irq
> support to the mpc8xxx driver, but so far nothing has been written for
> 52xx.
>
> http://patchwork.ozlabs.org/patch/41550/
>   

Ok.  I'm taking a look at that code now, planning to adapt it for the
MPC52xx unless someone raises any objections.


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Does gpio_to_irq() work for MPC52xx gpios?

2009-12-22 Thread Bill Gatliff
Guys:


Is it possible to specify an individual GPIO pin as an interrupt source
with the current MPC52xx code?

I don't see anything in mpc52xx_gpio.c that registers an interrupt
handler, which I think would be a necessary step towards demultiplexing
the GPIO interrupt event.  So I'm thinking that code to allow me to
register an interrupt handler for a specific GPIO pin just isn't there...


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Question on MPC52xx IRQ[123] pins

2009-12-21 Thread Bill Gatliff
Guys:


I think I already know the answer to this, having read most of the
MPC52xx manual.  But I'll ask anyway, just to be sure I'm not missing
something obvious...  :)

Is it possible to treat the external IRQ[123] pins on the MPC52xx as
GPIO inputs?  And if so, how do I tweak my dts file and other code, if
necessary, to make that happen?

Reason I ask is, I'm trying to enhance
drivers/input/misc/rotary-encoder.c to use device trees, and one of the
encoder inputs is on IRQ2.  My strategy so far is to just provide an
of_probe() function that builds a rotary_encoder_platform_data structure
and then calls platform_device_register().  And that ain't working.  :)

First off, the rotary-encoder driver assumes that both of its inputs are
both known to gpiolib, so that they can do both gpio_to_irq() and
gpio_get_value() on them.  There isn't any existing code that I can find
that allows you to read the states of IRQ pins, be it under gpiolib or
otherwise.  And I think the reason for that is that there's no way to
actually read the states of those pins at all--- the hardware just
doesn't work that way.

Or am I missing something?

Second, if I get all this working then my rotary encoders won't be
platform devices--- they'll be openfirmware devices, which means I'll
have to do other work in the code as well.  That's a subtle point I
know, but rotary-encoder's assumption that all rotary encoder devices
are also platform devices is kind of like mixing policy with
implementation, it turns out.  Almost like trying to reuse a PCI driver
as a platform driver.  I didn't spot how important that was until I
started hacking on the code itself...



Thanks!


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Trouble specifying dts gpio-leds with GPIO expander chip

2009-12-21 Thread Bill Gatliff
Guys:


I'm trying to come up with the right stuff for my dts file to assign a
Linux "heartbeat" trigger to an I2C GPIO expansion device (MAX7314). 
I'm running on a platform that is very similar to the lite5200b, with
linux-2.6.32.  I'm a bit new to the device tree concept, having come
most recently from an ARM world, so please be gentle...  :)

I have this so far:

soc5...@f000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,mpc5200b-immr","simple-bus";
ranges = <0 0xf000 0xc000>;
reg = <0xf000 0x0100>;
bus-frequency = <0>;// from bootloader
system-frequency = <0>;// from bootloader
...
i...@3d40 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
reg = <0x3d40 0x40>;
interrupts = <2 16 0>;
   
lext20: max7...@20 {
   #gpio-cells = <2>;
   compatible = "maxim,max7314","phillips,pca953x";
   reg = <0x20>;
   linux,phandle = <0x20>;
   gpio-controller;
};
...
};
};
...
system {
compatible = "simple-bus";
   
gpio-leds {
compatible = "gpio-leds";
   
heartbeat {
gpios = <&lext20 3 0>;
linux,default-trigger = "heartbeat";
};
};
};
...


The MAX7314 chip is showing up under /debug/gpio:

# cat /debug/gpio
...
GPIOs 198-213, i2c/1-0020, max7314, can sleep:

And, indeed, I can twiddle the LED by hand:

# echo 201 > /sys/class/gpio/export
# while true; do for led in high low; \
do echo $led > /sys/class/gpio/gpio201/direction; \
sleep 1; done; done
   (observe blinking)

But I see this at boot:

Skipping unavailable LED gpio -19 (heartbeat)

That error code is -ENODEV.  I double-checked that gpio-leds is showing
up on of_platform:

# ls /sys/bus/of_platform/devices/
...
gpio-leds.2
...


I'm stumped.  Could it be that the startup code is trying to register
the heartbeat device before it has registered the MAX7314, so it doesn't
know yet that the GPIO line exists?

Anyone have any suggestions?


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Accessing flash directly from User Space

2009-10-27 Thread Bill Gatliff
Jonathan Haws wrote:
>>> How can I get that pointer?  Unfortunately I cannot simply use the
>>>   
>> address of the flash.  Is there some magical function call that
>> gives me access to that portion of the memory space?
>> 
>> $ man 2 mmap
>>
>> You want MAP_SHARED and O_SYNC.
>> 
>
>
> To use that I need to have a file descriptor to a device, do I not?  However, 
> I do not have a base flash driver to give me that file descriptor.  Am I 
> missing something with that call?
>   

/dev/mem


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: Accessing flash directly from User Space

2009-10-27 Thread Bill Gatliff
Jonathan Haws wrote:
>
> How can I get that pointer?  Unfortunately I cannot simply use the address of 
> the flash.  Is there some magical function call that gives me access to that 
> portion of the memory space?
>   

$ man 2 mmap

You want MAP_SHARED and O_SYNC.


b.g.

-- 
Bill Gatliff
b...@billgatliff.com

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages

2008-11-25 Thread Bill Gatliff
Matt Sealey wrote:
> Yes, there's FirmWorks, CodeGen SmartFirmware, IBM SLOF and OpenBIOS..
> they're all linked from the OpenBIOS website (along with a bunch of the
> documentation from http://www.openfirmware.org in more-readable formats
> like PDF)
> 
> http://www.openbios.org/
> 
> 
> But here's the real question; why do you need an opensource
> implementation? Curiosity?

That, and I prefer Free *ware whenever that's an option.  :)

Nothing against the commercial alternatives, of course.  But I'm
already doing my own heavy lifting, because my platforms are all
full-custom with very limited production runs.  Since I'm into the
guts of all my code anyway, I'm not inclined to outsource a bootloader
development effort.

Just trying to figure out where the walls of this "sandbox" are.  I've
been aware of the concept of Open Firmware for a while, but haven't
really looked into it before now--- mostly because my impression until
now was that the available implementations were both closed-source,
and not supporting embedded, non-PPC targets like ARM.


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH/RFC] Add Alternative Log Buffer Support for printk Messages

2008-11-25 Thread Bill Gatliff
Matt Sealey wrote:

> I can think of a bunch of reasons why it's a good idea.. 

Can you point to a GPL/LGPL/BSD/etc. source code for an OpenFirmware
implementation?


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Proposal for a Generic PWM Device API posted on linux-embedded

2008-10-15 Thread Bill Gatliff
Greetings, all!


I just posted code to implement a Generic PWM Device API to linux-embedded.  If
you need them, archives of that mailing list are available at the following link
(and elsewhere):

http://www.mail-archive.com/[EMAIL PROTECTED]/

Previous versions of this code were posted on linux-arm-kernel, linuxppc-dev,
avr32linux.org and elsewhere.  It's an API that cuts across machine
architectures--- not unlike the GPIO API--- and I really appreciate the
constructive feedback I have received from all corners of the architecture 
globe.

Multiple reviewers suggested that the best place to review the final code is
linux-embedded, rather than cross-posting all over the place.  I encourage you
to submit your feedback there.

I would love to see this code included in the mainline kernel at some point in
the not-too-distant future.  It has proven very useful to me, I think it will be
useful for many others as well.


Kindest regards,


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Floating inputs on unused GPIO pins

2008-10-13 Thread Bill Gatliff
Laurent Pinchart wrote:

> 
> There are no internal pull-up or pull-down resistors on the MPC8248 GPIO 
> pins. I know our hardware engineer has a valid point theoretically. Does the 
> point stand practically, or does the MPC8248 
> "state-of-the-art"(tm)(c)(whatever) technology make floating inputs safe ?

Well, Freescale's own layout recommendations recommend pullups or pulldowns for
all input pins, but it's isn't clear what motivates that suggestion.

The block diagram, Figure 37-21, is less than helpful.  :)  I recall a doc
somewhere that showed the input protection circuitry ends up providing a modest
pullup/down, so the line never truly "floats".  But it's a very high-impedance
path, and I can't seem to find the doc anyway so it could be for a completely
different chip altogether.

The part isn't going to blow up if you leave inputs unconnected, at least if you
avoid high-EMI/RFI environments.  But I can imagine the possibility of increased
power consumption if I try hard enough.  I would think that the magnitude would
be completely swamped by the consumption of the rest of the chip, however...

The technical answer might not be the best political one, at least not without
Freescale-branded docs to back you up.  I say, write the code and make everyone
else happy.  :)

At least until someone plugs in that expansion module!


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 0/6] Proposal for a Generic PWM Device API

2008-10-10 Thread Bill Gatliff
Paul Mundt wrote:
>> Hasn't been a problem so far.  I posted the first version of the code on 
>> l-a-k,
>> and got some feedback on the pwm_device API and a lot of feedback on the way
>> users wanted to use the API to realize applications.  I incorporated all of 
>> it,
>> and in this "release" I broadened the exposure per recommendations received 
>> from
>> l-a-k.
>>
> This is precisely the problem. Stuff that gets "reviewed" on
> linux-arm-kernel gets reviewed for ARM only. There has been way too much
> crap that has been pushed into the kernel under the guise of being
> generic and "reviewed" that has broken _every_ architecture _except_ ARM.
> If you want to refute this, go look at the recent fiasco with musb, which
> still hasn't been solved properly, primarily because the ARM people
> couldn't be bothered using grep. This crap happens all the time, because
> stuff is reviewed and merged in private, and the only time anyone else
> notices is when their platform suddenly stops building.

I'll note for the record that I didn't post on linux-arm-kernel only.
Otherwise, we wouldn't be having this discussion.  :)

> Your first version should have been to linux-embedded and linux-kernel.
> If you want to alert the linux-arm-kernel people to the fact that a
> discussion is going on in this area, then feel free to post a
> notification to the list with references to the relevant lists. There is
> no reason why public lists should have to dig in to private archives to
> try and play catch up.

I'm not asking anyone to do that.  Just review the patches posted to the list of
your choice.  Or, don't review them.  Up to you.

My next update will be the one where I formally request a review with intent to
merge into mainline.  That one will go to linux-embedded only, with
notifications sent elsewhere as indicated per community request.  I don't have a
problem with that.  I can't change history, but I'm doing what you are asking of
me otherwise.

> If you're trying to pitch a generic API and doing your review on a
> private list, you've already lost. If you're talking about things that
> only effect arch/arm, feel free to do whatever you want. As soon as you
> step outside of that structure, you have to follow common convention, or
> you risk breaking things all over the place. I can't remember the last
> time I saw a "generic" API reviewed on linux-arm-kernel that didn't end
> up breaking every other architecture in existence. This is true for
> drivers, also. Better yet, don't bother dropping the ARM depedency until
> you've posted to a public list.

Again, we wouldn't be having this exchange if I was pitching a generic API on a
private list because I sense that you aren't an l-a-k subscriber.  :)

It's true that the early posts were on the ARM list, but you can see that I
didn't stop there.  I started there because the platform that supports the API
right now is ARM, and so I wanted that part to be right before moving upstream.
 That process worked: I received feedback on the ARM-specific bits which
improved the API as a whole.  The diversity of ARM machines plus Blackfin, PPC,
MIPS, X, Y, Z and PDQ machines was more than I could deal with until now.

Right, enough of that.  I really don't want to get distracted from the code.
I'll readily admit to not handing the mailing list submissions right, and I
resolve to do a better job effective immediately.  But I think that's the last
that I need to say on the subject.

If it makes you feel any better, I'll stop responding to your replies unless
they come to me via linux-embedded.  :)

> Some of us are pretty damn tired of cleaning up after the ARM people.

Sounds like the ARM people need you to drop by and help them do a better job.
Sounds like you could directly benefit from their doing a better job, too.  
Win-win.




b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 0/6] Proposal for a Generic PWM Device API

2008-10-10 Thread Bill Gatliff
Paul Mundt wrote:
> On Fri, Oct 10, 2008 at 09:03:34AM -0500, Bill Gatliff wrote:
>> Paul Mundt wrote:
>>> This is likely because some of those lists are subscribers only, so cross
>>> posting is poor form. It makes sense to keep the discussion in one place,
>>> and to send notification messages with a pointer to the list archives to
>>> the other lists so folks can jump in if they really care. Splitting it
>>> out doesn't help matters in the least, but unfortunately this is what
>>> seems to happen the most when subscribers only lists are involved.
>> Alright, then maybe I can do this when I post the "final" changeset for 
>> review:
>> cross-post to lkml and linux-embedded, and then post one short note on l-a-k,
>> linuxppc-dev and elsewhere that refers those interested to the actual 
>> content.
>> I can live with that.
>>
> linux-arm-kernel is the only one that is subscribers only out of that
> list, according to MAINTAINERS. If rmk wants to mandate a broken policy,
> that's perfectly fine, just don't expect the rest of the kernel community
> to tolerate it.

Problem is, the rest of the kernel community is the one who takes it in the,
ahem, server when I cross-post.  And since my reference platform is currently
ARM, I can't leave l-a-k out.



b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 1/6] [PWM] Generic PWM API implementation

2008-10-10 Thread Bill Gatliff
Benjamin Herrenschmidt wrote:
> On Wed, 2008-10-08 at 11:43 -0500, Bill Gatliff wrote:
>> Signed-off-by: Bill Gatliff <[EMAIL PROTECTED]>
>> ---
> 
> And you haven't provided -any- changeset comment. That isn't good :-)

What's the easiest way to do that with git?

I'm using git-format-patch and git-send-email to produce the changeset emails
themselves, after extensive use of git-add --interactive and git-rebase
--interactive to get rid of the "mundane" commit stuff that I do because of my
highly interrupt-driven workflow.

Should I just edit the files that come out of git-format-patch?


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 0/6] Proposal for a Generic PWM Device API

2008-10-10 Thread Bill Gatliff
Jon Smirl wrote:

> What do the device tree deities have to say about PWM support?

Dunno.  What lists are they on?  :)


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 0/6] Proposal for a Generic PWM Device API

2008-10-10 Thread Bill Gatliff
Paul Mundt wrote:
> This is likely because some of those lists are subscribers only, so cross
> posting is poor form. It makes sense to keep the discussion in one place,
> and to send notification messages with a pointer to the list archives to
> the other lists so folks can jump in if they really care. Splitting it
> out doesn't help matters in the least, but unfortunately this is what
> seems to happen the most when subscribers only lists are involved.

Alright, then maybe I can do this when I post the "final" changeset for review:
cross-post to lkml and linux-embedded, and then post one short note on l-a-k,
linuxppc-dev and elsewhere that refers those interested to the actual content.
I can live with that.


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 0/6] Proposal for a Generic PWM Device API

2008-10-10 Thread Bill Gatliff
David Woodhouse wrote:
> Subscriber-only lists are broken. Just don't use them.

You owe me a new keyboard!  :)


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 0/6] Proposal for a Generic PWM Device API

2008-10-10 Thread Bill Gatliff
Geert Uytterhoeven wrote:
> 
> Were did you actually sent them to?  Apparently you sent them to each mailing
> list (at least linux-embedded and linuxppc-dev) _separately_ (or using bcc).

I sent them separately to linux-embedded, linuxppc-dev, and linux-arm-kernel.
Those three groups seemed to have the developers who were most likely to provide
a motivated review and constructive response; unfortunately, some are
subscriber-only and so I couldn't just cross-post.  I was expecting some
criticism for this, but I'm not sure there's a good alternative.

I don't like the idea of posting in so many places, but PWM is a pretty
expansive topic: just about every SoC under the sun has some ability to do PWM,
and people use the signals for all sorts of things.  Both have to be taken into
consideration by the API, hence I need lots of review and feedback.

There isn't a lot of traffic on linux-embedded, and I'm not sure how many people
who read linux-arm-kernel also read linuxppc-dev.  Lkml's topic coverage is
huge, so I don't know how many hardcore embedded developers I would encounter
there.  I was hoping for a round of feedback at a lower level before pushing
anything upstream like that.

> Hence different people may give the same comments without knowing about each
> other, and you may have to explain everything multiple times.

Hasn't been a problem so far.  I posted the first version of the code on l-a-k,
and got some feedback on the pwm_device API and a lot of feedback on the way
users wanted to use the API to realize applications.  I incorporated all of it,
and in this "release" I broadened the exposure per recommendations received from
l-a-k.

> I would go for lkml and linux-embedded, _together_.

So, you're saying the same thing as me, basically.  But leaving out the lists
with very high ratios of device-specific domain knowledge, which is important
for the backend parts of what I'm proposing.  Blackfin's PWM-capable peripherals
work differently from those commonly found in ARM and PPC, for example.  I
haven't run anything by the MIPS or AVR guys, but I'm guessing they would have
something to add, too.

I'm beginning to appreciate what everyone must have had to deal with for GPIO.  
:)


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 1/6] [PWM] Generic PWM API implementation

2008-10-09 Thread Bill Gatliff
Benjamin Herrenschmidt wrote:
> On Wed, 2008-10-08 at 11:43 -0500, Bill Gatliff wrote:
>> Signed-off-by: Bill Gatliff <[EMAIL PROTECTED]>
>> ---
> 
> And you haven't provided -any- changeset comment. That isn't good :-)

Apparently not.  :)


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 0/6] Proposal for a Generic PWM Device API

2008-10-09 Thread Bill Gatliff
Benjamin Herrenschmidt wrote:
> On Wed, 2008-10-08 at 11:43 -0500, Bill Gatliff wrote:
>> This series proposes a "generic PWM" driver API.
>>
>> This proposed API is motivated by the author's need to support
>> pluggable devices; a secondary objective is to consolidate the
>> existing PWM implementations behind an agreeable, consistent,
>> redundancy-reducing interface.
> 
>  .../...
> 
> You should send your patches to the main linux kernel list !

Perhaps.  But it seemed more relevant to this crowd, and the linux-embedded
crowd, and the linux-arm-kernel crowd.

At the very least, it made sense to present it in this sort of venue first.
Given that it's a "global" API proposal, I suppose I'll have to run it by lkml
at some point--- unless one of the aforementioned groups can mainline it 
themselves.



b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [RFC 0/6] Proposal for a Generic PWM Device API

2008-10-09 Thread Bill Gatliff
Matt Sealey wrote:
> I'm all for this if you manage it.
> 
> The code and API looks good. We have some projects which involve PWM
> and having a nice clean standard API like the GPIO API was on the
> wishlist.. this will make it so much easier to do fan control,
> backlight control, drive motors, audio output, and the billion
> other things..

/me blushes

Aw, shucks.  I'm just glad I could help.  :)


b.g.
-- 
Bill Gatliff
[EMAIL PROTECTED]
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[RFC 4/6] [PWM] Driver for Atmel PWMC peripheral

2008-10-08 Thread Bill Gatliff

Signed-off-by: Bill Gatliff <[EMAIL PROTECTED]>
---
 drivers/pwm/atmel-pwm.c |  631 +++
 1 files changed, 631 insertions(+), 0 deletions(-)
 create mode 100644 drivers/pwm/atmel-pwm.c

diff --git a/drivers/pwm/atmel-pwm.c b/drivers/pwm/atmel-pwm.c
new file mode 100644
index 000..b65e84f
--- /dev/null
+++ b/drivers/pwm/atmel-pwm.c
@@ -0,0 +1,631 @@
+/*
+ * drivers/pwm/atmel-pwm.c
+ *
+ * Copyright (C) 2008 Bill Gatliff
+ * Copyright (C) 2007 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+enum {
+   /* registers common to the PWMC peripheral */
+   PWMC_MR = 0,
+   PWMC_ENA = 4,
+   PWMC_DIS = 8,
+   PWMC_SR = 0xc,
+   PWMC_IER = 0x10,
+   PWMC_IDR = 0x14,
+   PWMC_IMR = 0x18,
+   PWMC_ISR = 0x1c,
+
+   /* registers per each PWMC channel */
+   PWMC_CMR = 0,
+   PWMC_CDTY = 4,
+   PWMC_CPRD = 8,
+   PWMC_CCNT = 0xc,
+   PWMC_CUPD = 0x10,
+
+   /* how to find each channel */
+   PWMC_CHAN_BASE = 0x200,
+   PWMC_CHAN_STRIDE = 0x20,
+
+   /* CMR bits of interest */
+   PWMC_CMR_CPD = 10,
+   PWMC_CMR_CPOL = 9,
+   PWMC_CMR_CALG = 8,
+   PWMC_CMR_CPRE_MASK = 0xf,
+};
+
+struct atmel_pwm {
+   struct pwm_device pwm;
+   spinlock_t lock;
+   void __iomem *iobase;
+   struct clk *clk;
+   u32 *sync_mask;
+   int irq;
+   u32 ccnt_mask;
+};
+
+
+static inline void
+pwmc_writel(const struct atmel_pwm *p,
+   unsigned offset, u32 val)
+{
+   __raw_writel(val, p->iobase + offset);
+}
+
+
+static inline u32
+pwmc_readl(const struct atmel_pwm *p,
+  unsigned offset)
+{
+   return __raw_readl(p->iobase + offset);
+}
+
+
+static inline void
+pwmc_chan_writel(const struct pwm_channel *p,
+u32 offset, u32 val)
+{
+   const struct atmel_pwm *ap
+   = container_of(p->pwm, struct atmel_pwm, pwm);
+
+   if (PWMC_CMR == offset)
+   val &= ((1 << PWMC_CMR_CPD)
+   | (1 << PWMC_CMR_CPOL)
+   | (1 << PWMC_CMR_CALG)
+   | (PWMC_CMR_CPRE_MASK));
+   else
+   val &= ap->ccnt_mask;
+
+   pwmc_writel(ap, offset + PWMC_CHAN_BASE
+   + (p->chan * PWMC_CHAN_STRIDE), val);
+}
+
+
+static inline u32
+pwmc_chan_readl(const struct pwm_channel *p,
+   u32 offset)
+{
+   const struct atmel_pwm *ap
+   = container_of(p->pwm, struct atmel_pwm, pwm);
+
+   return pwmc_readl(ap, offset + PWMC_CHAN_BASE
+ + (p->chan * PWMC_CHAN_STRIDE));
+}
+
+
+static inline int
+__atmel_pwm_is_on(struct pwm_channel *p)
+{
+   struct atmel_pwm *ap = container_of(p->pwm, struct atmel_pwm, pwm);
+   return (pwmc_readl(ap, PWMC_SR) & (1 << p->chan)) ? 1 : 0;
+}
+
+
+static inline void
+__atmel_pwm_unsynchronize(struct pwm_channel *p,
+ struct pwm_channel *to_p)
+{
+   const struct atmel_pwm *ap
+   = container_of(p->pwm, struct atmel_pwm, pwm);
+   int wchan;
+
+   if (to_p) {
+   ap->sync_mask[p->chan] &= ~(1 << to_p->chan);
+   ap->sync_mask[to_p->chan] &= ~(1 << p->chan);
+   goto done;
+   }
+
+   ap->sync_mask[p->chan] = 0;
+   for (wchan = 0; wchan < ap->pwm.nchan; wchan++)
+   ap->sync_mask[wchan] &= ~(1 << p->chan);
+done:
+   pr_debug("%s:%d sync_mask %x\n",
+p->pwm->bus_id, p->chan, ap->sync_mask[p->chan]);
+}
+
+
+static inline void
+__atmel_pwm_synchronize(struct pwm_channel *p,
+   struct pwm_channel *to_p)
+{
+   const struct atmel_pwm *ap
+   = container_of(p->pwm, struct atmel_pwm, pwm);
+
+   if (!to_p)
+   return;
+
+   ap->sync_mask[p->chan] |= (1 << to_p->chan);
+   ap->sync_mask[to_p->chan] |= (1 << p->chan);
+
+   pr_debug("%s:%d sync_mask %x\n",
+p->pwm->bu

[RFC 1/6] [PWM] Generic PWM API implementation

2008-10-08 Thread Bill Gatliff

Signed-off-by: Bill Gatliff <[EMAIL PROTECTED]>
---
 drivers/pwm/pwm.c |  667 +
 1 files changed, 667 insertions(+), 0 deletions(-)
 create mode 100644 drivers/pwm/pwm.c

diff --git a/drivers/pwm/pwm.c b/drivers/pwm/pwm.c
new file mode 100644
index 000..2f28c20
--- /dev/null
+++ b/drivers/pwm/pwm.c
@@ -0,0 +1,667 @@
+/*
+ * drivers/pwm/pwm.c
+ *
+ * Copyright (C) 2008 Bill Gatliff
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int __pwm_create_sysfs(struct pwm_device *pwm);
+
+static LIST_HEAD(pwm_device_list);
+static DEFINE_MUTEX(device_list_mutex);
+static struct class pwm_class;
+static struct workqueue_struct *pwm_handler_workqueue;
+
+
+int pwm_register(struct pwm_device *pwm)
+{
+   struct pwm_channel *p;
+   int wchan;
+   int ret = 0;
+
+   spin_lock_init(&pwm->list_lock);
+
+   p = kcalloc(pwm->nchan, sizeof(struct pwm_channel), GFP_KERNEL);
+   if (!p)
+   return -ENOMEM;
+
+   for (wchan = 0; wchan < pwm->nchan; wchan++) {
+   spin_lock_init(&p[wchan].lock);
+   init_completion(&p[wchan].complete);
+   p[wchan].chan = wchan;
+   p[wchan].pwm = pwm;
+   }
+
+   pwm->channels = p;
+
+   mutex_lock(&device_list_mutex);
+
+   list_add_tail(&pwm->list, &pwm_device_list);
+   ret = __pwm_create_sysfs(pwm);
+   if (ret) {
+   mutex_unlock(&device_list_mutex);
+   goto err_create_sysfs;
+   }
+
+   mutex_unlock(&device_list_mutex);
+
+   pr_info("%s: %d channels\n", pwm->bus_id, pwm->nchan);
+   return 0;
+
+err_create_sysfs:
+   kfree(p);
+
+   return ret;
+}
+EXPORT_SYMBOL(pwm_register);
+
+
+static int __match_device(struct device *dev, void *data)
+{
+   return dev_get_drvdata(dev) == data;
+}
+
+
+int pwm_unregister(struct pwm_device *pwm)
+{
+   int wchan;
+   struct device *dev;
+
+   mutex_lock(&device_list_mutex);
+
+   for (wchan = 0; wchan < pwm->nchan; wchan++) {
+   if (pwm->channels[wchan].flags & FLAG_REQUESTED) {
+   mutex_unlock(&device_list_mutex);
+   return -EBUSY;
+   }
+   }
+
+   for (wchan = 0; wchan < pwm->nchan; wchan++) {
+   dev = class_find_device(&pwm_class, NULL,
+   &pwm->channels[wchan],
+   __match_device);
+   if (dev) {
+   put_device(dev);
+   device_unregister(dev);
+   }
+   }
+
+   kfree(pwm->channels);
+   list_del(&pwm->list);
+   mutex_unlock(&device_list_mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL(pwm_unregister);
+
+
+static struct pwm_device *
+__pwm_find_device(const char *bus_id)
+{
+   struct pwm_device *p;
+
+   list_for_each_entry(p, &pwm_device_list, list)
+   {
+   if (!strcmp(bus_id, p->bus_id))
+   return p;
+   }
+   return NULL;
+}
+
+
+static int
+__pwm_request_channel(struct pwm_channel *p,
+ const char *requester)
+{
+   int ret;
+
+   if (test_and_set_bit(FLAG_REQUESTED, &p->flags))
+   return -EBUSY;
+
+   if (p->pwm->request) {
+   ret = p->pwm->request(p);
+   if (ret) {
+   clear_bit(FLAG_REQUESTED, &p->flags);
+   return ret;
+   }
+   }
+
+   p->requester = requester;
+   return 0;
+}
+
+
+struct pwm_channel *
+pwm_request(const char *bus_id,
+   int chan,
+   const char *requester)
+{
+   struct pwm_device *p;
+   int ret;
+
+   mutex_lock(&device_list_mutex);
+
+   p = __pwm_find_device(bus_id);
+   if (!p || chan >= p->nchan)
+   goto err_no_device;
+
+   if (!try_module_get(p->owner))
+   goto err_module_get_failed;
+
+   ret = __pwm_request_channel(&p->cha

[RFC 5/6] [PWM] Install new Atmel PWMC driver in Kconfig, expunge old one

2008-10-08 Thread Bill Gatliff

Signed-off-by: Bill Gatliff <[EMAIL PROTECTED]>
---
 arch/arm/Kconfig |2 +
 drivers/Makefile |2 +
 drivers/misc/Kconfig |9 -
 drivers/misc/Makefile|1 -
 drivers/misc/atmel_pwm.c |  409 --
 drivers/pwm/Kconfig  |   24 +++
 drivers/pwm/Makefile |6 +
 7 files changed, 34 insertions(+), 419 deletions(-)
 delete mode 100644 drivers/misc/atmel_pwm.c
 create mode 100644 drivers/pwm/Kconfig
 create mode 100644 drivers/pwm/Makefile

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 70dba16..fed3eef 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1196,6 +1196,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/gpio/Kconfig"
 
+source "drivers/pwm/Kconfig"
+
 source "drivers/w1/Kconfig"
 
 source "drivers/power/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 2735bde..f242fc6 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -6,6 +6,8 @@
 #
 
 obj-y  += gpio/
+obj-$(CONFIG_GENERIC_PWM)  += pwm/
+
 obj-$(CONFIG_PCI)  += pci/
 obj-$(CONFIG_PARISC)   += parisc/
 obj-$(CONFIG_RAPIDIO)  += rapidio/
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index a726f3b..cdea0bb 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -13,15 +13,6 @@ menuconfig MISC_DEVICES
 
 if MISC_DEVICES
 
-config ATMEL_PWM
-   tristate "Atmel AT32/AT91 PWM support"
-   depends on AVR32 || ARCH_AT91
-   help
- This option enables device driver support for the PWM channels
- on certain Atmel prcoessors.  Pulse Width Modulation is used for
- purposes including software controlled power-efficent backlights
- on LCD displays, motor control, and waveform generation.
-
 config ATMEL_TCLIB
bool "Atmel AT32/AT91 Timer/Counter Library"
depends on (AVR32 || ARCH_AT91)
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c6c13f6..9e67012 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_EEEPC_LAPTOP)+= eeepc-laptop.o
 obj-$(CONFIG_MSI_LAPTOP)   += msi-laptop.o
 obj-$(CONFIG_COMPAL_LAPTOP)+= compal-laptop.o
 obj-$(CONFIG_ACER_WMI) += acer-wmi.o
-obj-$(CONFIG_ATMEL_PWM)+= atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)  += atmel_tclib.o
 obj-$(CONFIG_HP_WMI)   += hp-wmi.o
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
deleted file mode 100644
index 6aa5294..000
--- a/drivers/misc/atmel_pwm.c
+++ /dev/null
@@ -1,409 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-
-/*
- * This is a simple driver for the PWM controller found in various newer
- * Atmel SOCs, including the AVR32 series and the AT91sam9263.
- *
- * Chips with current Linux ports have only 4 PWM channels, out of max 32.
- * AT32UC3A and AT32UC3B chips have 7 channels (but currently no Linux).
- * Docs are inconsistent about the width of the channel counter registers;
- * it's at least 16 bits, but several places say 20 bits.
- */
-#definePWM_NCHAN   4   /* max 32 */
-
-struct pwm {
-   spinlock_t  lock;
-   struct platform_device  *pdev;
-   u32 mask;
-   int irq;
-   void __iomem*base;
-   struct clk  *clk;
-   struct pwm_channel  *channel[PWM_NCHAN];
-   void(*handler[PWM_NCHAN])(struct pwm_channel *);
-};
-
-
-/* global PWM controller registers */
-#define PWM_MR 0x00
-#define PWM_ENA0x04
-#define PWM_DIS0x08
-#define PWM_SR 0x0c
-#define PWM_IER0x10
-#define PWM_IDR0x14
-#define PWM_IMR0x18
-#define PWM_ISR0x1c
-
-static inline void pwm_writel(const struct pwm *p, unsigned offset, u32 val)
-{
-   __raw_writel(val, p->base + offset);
-}
-
-static inline u32 pwm_readl(const struct pwm *p, unsigned offset)
-{
-   return __raw_readl(p->base + offset);
-}
-
-static inline void __iomem *pwmc_regs(const struct pwm *p, int index)
-{
-   return p->base + 0x200 + index * 0x20;
-}
-
-static struct pwm *pwm;
-
-static void pwm_dumpregs(struct pwm_channel *ch, char *tag)
-{
-   struct device   *dev = &pwm->pdev->dev;
-
-   dev_dbg(dev, "%s: mr %08x, sr %08x, imr %08x\n",
-   tag,
-   pwm_readl(pwm, PWM_MR),
-   pwm_readl(pwm, PWM_SR),
-   pwm_readl(pwm, PWM_IMR));
-   dev_dbg(dev,
-   "pwm ch%d - mr %08x, dty %u, prd %u, cnt %u\n",
-   ch->index,
-   pwm_channel_readl(ch, PWM_CMR),
-   pwm_channel_readl(ch, PWM_CDTY),
-

[RFC 2/6] [PWM] Changes to existing include/linux/pwm.h to adapt to generic PWM API

2008-10-08 Thread Bill Gatliff

Signed-off-by: Bill Gatliff <[EMAIL PROTECTED]>
---
 include/linux/pwm.h |  168 --
 1 files changed, 147 insertions(+), 21 deletions(-)

diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 3945f80..d3d18f7 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -1,31 +1,157 @@
 #ifndef __LINUX_PWM_H
 #define __LINUX_PWM_H
 
-struct pwm_device;
-
 /*
- * pwm_request - request a PWM device
+ * include/linux/pwm.h
+ *
+ * Copyright (C) 2008 Bill Gatliff
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-struct pwm_device *pwm_request(int pwm_id, const char *label);
 
-/*
- * pwm_free - free a PWM device
- */
-void pwm_free(struct pwm_device *pwm);
+enum {
+   PWM_CONFIG_DUTY_TICKS = BIT(0),
+   PWM_CONFIG_PERIOD_TICKS = BIT(1),
+   PWM_CONFIG_POLARITY = BIT(2),
+   PWM_CONFIG_START = BIT(3),
+   PWM_CONFIG_STOP = BIT(4),
 
-/*
- * pwm_config - change a PWM device configuration
- */
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
+   PWM_CONFIG_HANDLER = BIT(5),
 
-/*
- * pwm_enable - start a PWM output toggling
- */
-int pwm_enable(struct pwm_device *pwm);
+   PWM_CONFIG_DUTY_NS = BIT(6),
+   PWM_CONFIG_DUTY_PERCENT = BIT(7),
+   PWM_CONFIG_PERIOD_NS = BIT(8),
+};
+
+struct pwm_channel;
+struct work_struct;
+
+typedef int (*pwm_handler_t)(struct pwm_channel *p, void *data);
+typedef void (*pwm_callback_t)(struct pwm_channel *p);
+
+struct pwm_channel_config {
+   int config_mask;
+   unsigned long duty_ticks;
+   unsigned long period_ticks;
+   int polarity;
+
+   pwm_handler_t handler;
+
+   unsigned long duty_ns;
+   unsigned long period_ns;
+   int duty_percent;
+};
+
+struct pwm_device {
+   struct list_head list;
+   spinlock_t list_lock;
+   struct device *dev;
+   struct module *owner;
+   struct pwm_channel *channels;
+
+   const char *bus_id;
+   int nchan;
+
+   int (*request)  (struct pwm_channel *p);
+   void(*free) (struct pwm_channel *p);
+   int (*config)   (struct pwm_channel *p,
+struct pwm_channel_config *c);
+   int (*config_nosleep)(struct pwm_channel *p,
+ struct pwm_channel_config *c);
+   int (*synchronize)  (struct pwm_channel *p,
+struct pwm_channel *to_p);
+   int (*unsynchronize)(struct pwm_channel *p,
+struct pwm_channel *from_p);
+   int (*set_callback) (struct pwm_channel *p,
+pwm_callback_t callback);
+};
+
+int pwm_register(struct pwm_device *pwm);
+int pwm_unregister(struct pwm_device *pwm);
+
+enum {
+   FLAG_REQUESTED = 0,
+   FLAG_STOP = 1,
+};
+
+struct pwm_channel {
+   struct list_head list;
+   struct pwm_device *pwm;
+   const char *requester;
+   int chan;
+   unsigned long flags;
+   unsigned long tick_hz;
+
+   spinlock_t lock;
+   struct completion complete;
+
+   pwm_callback_t callback;
+
+   struct work_struct handler_work;
+   pwm_handler_t handler;
+   void *handler_data;
+
+   int active_low;
+   unsigned long period_ticks;
+   unsigned long duty_ticks;
+};
+
+struct pwm_channel *
+pwm_request(const char *bus_id, int chan,
+   const char *requester);
+
+void pwm_free(struct pwm_channel *pwm);
+
+int pwm_config_nosleep(struct pwm_channel *pwm,
+  struct pwm_channel_config *c);
+
+int pwm_config(struct pwm_channel *pwm,
+  struct pwm_channel_config *c);
+
+unsigned long pwm_ns_to_ticks(struct pwm_channel *pwm,
+ unsigned long nsecs);
+
+unsigned long pwm_ticks_to_ns(struct pwm_channel *pwm,
+ unsigned long ticks);
+
+int pwm_period_ns(struct pwm_channel *pwm,
+ unsigned long period_ns);
+
+int pwm_duty_ns(struct pwm_channel *pwm,
+   unsigned long duty_ns);
+
+int pwm_duty_percent(struct pwm_channel *pwm,
+int percent);
+
+int pwm_polarity(struct pwm_channel *pwm,
+int active_high);
+
+int pwm_start(struct pwm_channel *pwm);
+
+int pwm_stop(struct pwm_c

[RFC 3/6] [PWM] Documentation

2008-10-08 Thread Bill Gatliff

Signed-off-by: Bill Gatliff <[EMAIL PROTECTED]>
---
 Documentation/pwm.txt |  258 +
 1 files changed, 258 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/pwm.txt

diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt
new file mode 100644
index 000..b8932dd
--- /dev/null
+++ b/Documentation/pwm.txt
@@ -0,0 +1,258 @@
+   Generic PWM Device API
+
+  October 8, 2008
+   Bill Gatliff
+   <[EMAIL PROTECTED]>
+
+
+
+The code in drivers/pwm and include/linux/pwm.h implements an API for
+applications involving pulse-width-modulation signals.  This document
+describes how the API implementation facilitates both PWM-generating
+devices, and users of those devices.
+
+
+
+Motivation
+
+The primary goals for implementing the "generic PWM API" are to
+consolidate the various PWM implementations within a consistent and
+redundancy-reducing framework, and to facilitate the use of
+hotpluggable PWM devices.
+
+Previous PWM-related implementations within the Linux kernel achieved
+their consistency via cut-and-paste, but did not need to (and didn't)
+facilitate more than one PWM-generating device within the system---
+hotplug or otherwise.  The Generic PWM Device API might be most
+appropriately viewed as an update to those implementations, rather
+than a complete rewrite.
+
+
+
+Challenges
+
+One of the difficulties in implementing a generic PWM framework is the
+fact that pulse-width-modulation applications involve real-world
+signals, which often must be carefully managed to prevent destruction
+of hardware that is linked to those signals.  A DC motor that
+experiences a brief interruption in the PWM signal controlling it
+might destructively overheat; it could change speed, losing
+synchronization with a sensor; it could even suddenly change direction
+or torque, breaking the mechanical device connected to it.
+
+(A generic PWM device framework is not directly responsible for
+preventing the above scenarios: that responsibility lies with the
+hardware designer and the application and driver authors.  But it must
+to the greatest extent possible make it easy to avoid such problems).
+
+A generic PWM device framework must accomodate the substantial
+differences between available PWM-generating hardware devices, without
+becoming sub-optimal for any of them.
+
+Finally, a generic PWM device framework must be relatively
+lightweight, computationally speaking.  Some PWM users demand
+high-speed outputs, plus the ability to regulate those outputs
+quickly.  A device framework must be able to "keep up" with such
+hardware, while still leaving time to do real work.
+
+The Generic PWM Device API is an attempt to meet all of the above
+requirements.  At its initial publication, the API was already in use
+managing small DC motors through a custom-designed, optically-isolated
+H-bridge driver.
+
+
+
+Functional Overview
+
+The Generic PWM Device API framework is implemented in
+include/linux/pwm.h and drivers/pwm/pwm.c.  The functions therein use
+information from pwm_device, pwm_channel and pwm_channel_config
+structures to invoke services in PWM peripheral device drivers.
+Consult drivers/pwm/atmel-pwm.c for an example driver.
+
+There are two classes of adopters of the PWM framework:
+
+  "Users" -- those wishing to employ the API merely to produce PWM
+  signals; once they have identified the appropriate physical output
+  on the platform in question, they don't care about the details of
+  the underlying hardware
+
+  "Driver authors" -- those wishing to bind devices that can generate
+  PWM signals to the Generic PWM Device API, so that the services of
+  those devices become available to users; assuming the hardware can
+  support the needs of a user, driver authors don't care about the
+  details of the user's application
+
+Generally speaking, users will first invoke pwm_request() to obtain a
+handle to a PWM device.  They will then pass that handle to functions
+like pwm_duty_ns() and pwm_period_ns() to set the duty cycle and
+period of the PWM signal, respectively.  They will also invoke
+pwm_start() and pwm_stop() to turn the signal on and off.
+
+The framework also provides a sysfs interface to PWM devices, which is
+adequate for basic needs and testing.
+
+Driver authors fill out a pwm_device structure, which describes the
+capabilities of the PWM hardware being driven--- including the number
+of distinct output "channels" the peripheral offers.  They then invoke
+pwm_register() (usually from within their device's probe() handler) to
+make the PWM API aware of their device.  The framework will call back
+to the methods described in the pwm_device structure to configure and
+use the hardware.
+
+Note that PWM signals can be produced by a variety of peripherals,
+beyo

[RFC 6/6] [PWM] New LED driver and trigger that use PWM API

2008-10-08 Thread Bill Gatliff

Signed-off-by: Bill Gatliff <[EMAIL PROTECTED]>
---
 drivers/leds/Kconfig   |   21 --
 drivers/leds/Makefile  |2 +
 drivers/leds/leds-pwm.c|  141 
 drivers/leds/ledtrig-dim.c |   95 +
 include/linux/pwm-led.h|   34 +++
 5 files changed, 286 insertions(+), 7 deletions(-)
 create mode 100644 drivers/leds/leds-pwm.c
 create mode 100644 drivers/leds/ledtrig-dim.c
 create mode 100644 include/linux/pwm-led.h

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 9556262..019c2e8 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -17,13 +17,6 @@ config LEDS_CLASS
 
 comment "LED drivers"
 
-config LEDS_ATMEL_PWM
-   tristate "LED Support using Atmel PWM outputs"
-   depends on LEDS_CLASS && ATMEL_PWM
-   help
- This option enables support for LEDs driven using outputs
- of the dedicated PWM controller found on newer Atmel SOCs.
-
 config LEDS_CORGI
tristate "LED Support for the Sharp SL-C7x0 series"
depends on LEDS_CLASS && PXA_SHARP_C7xx
@@ -119,6 +112,12 @@ config LEDS_GPIO
  outputs. To be useful the particular board must have LEDs
  and they must be connected to the GPIO lines.
 
+config LEDS_PWM
+   tristate "LED Support for PWM connected LEDs"
+   depends on LEDS_CLASS && GENERIC_PWM
+   help
+ Enables support for LEDs connected to PWM outputs.
+
 config LEDS_CM_X270
tristate "LED Support for the CM-X270 LEDs"
depends on LEDS_CLASS && MACH_ARMCORE
@@ -190,6 +189,14 @@ config LEDS_TRIGGER_IDE_DISK
  This allows LEDs to be controlled by IDE disk activity.
  If unsure, say Y.
 
+config LEDS_TRIGGER_DIM
+   tristate "LED Dimmer Trigger"
+   depends on LEDS_TRIGGERS
+   help
+ Regulates the brightness of an LED based on the 1-minute CPU
+ load average.  Ideal for PWM-driven LEDs.
+ If unsure, say Y.
+
 config LEDS_TRIGGER_HEARTBEAT
tristate "LED Heartbeat Trigger"
depends on LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index ff7982b..1031086 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_COBALT_QUBE)+= 
leds-cobalt-qube.o
 obj-$(CONFIG_LEDS_COBALT_RAQ)  += leds-cobalt-raq.o
 obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
 obj-$(CONFIG_LEDS_GPIO)+= leds-gpio.o
+obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
 obj-$(CONFIG_LEDS_CM_X270)  += leds-cm-x270.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)  += leds-clevo-mail.o
 obj-$(CONFIG_LEDS_HP6XX)   += leds-hp6xx.o
@@ -27,5 +28,6 @@ obj-$(CONFIG_LEDS_PCA955X)+= leds-pca955x.o
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)   += ledtrig-timer.o
 obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)+= ledtrig-ide-disk.o
+obj-$(CONFIG_LEDS_TRIGGER_DIM) += ledtrig-dim.o
 obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)   += ledtrig-heartbeat.o
 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)  += ledtrig-default-on.o
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
new file mode 100644
index 000..3bd9afb
--- /dev/null
+++ b/drivers/leds/leds-pwm.c
@@ -0,0 +1,141 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+struct led_pwm {
+   struct led_classdev led;
+   struct pwm_channel  *pwm;
+   int percent;
+};
+
+
+static void
+led_pwm_brightness_set(struct led_classdev *c,
+  enum led_brightness b)
+{
+   struct led_pwm *led;
+   int percent;
+
+   percent = (b * 100) / (LED_FULL - LED_OFF);
+   led = container_of(c, struct led_pwm, led);
+   led->percent = percent;
+   pwm_duty_percent(led->pwm, percent);
+}
+
+
+static enum led_brightness
+led_pwm_brightness_get(struct led_classdev *c)
+{
+   struct led_pwm *led;
+   led = container_of(c, struct led_pwm, led);
+   return led->percent;
+}
+
+
+static int __init
+led_pwm_probe(struct platform_device *pdev)
+{
+   struct pwm_led_platform_data *pdata = pdev->dev.platform_data;
+   struct led_pwm *led;
+   struct device *d = &pdev->dev;
+   int ret;
+
+   if (!pdata || !pdata->led_info)
+   return -EINVAL;
+
+   if (!try_module_get(d->driver->owner))
+   return -ENODEV;
+
+   led = kzalloc(sizeof(*led), GFP_KERNEL);
+   if (!led)
+   return -ENOMEM;
+
+   led->pwm = pwm_request(pdata->bus_id, pdata->chan,
+  pdata->led_info->name);
+   if (!led->pwm) {
+   ret = -EINVAL;
+   goto err_pwm_request;
+   }
+
+   platform_set_drvdata(pdev, led);
+
+   led->led.name = pdat

[RFC 0/6] Proposal for a Generic PWM Device API

2008-10-08 Thread Bill Gatliff
This series proposes a "generic PWM" driver API.

This proposed API is motivated by the author's need to support
pluggable devices; a secondary objective is to consolidate the
existing PWM implementations behind an agreeable, consistent,
redundancy-reducing interface.

The code included in this patch draws heavily from the existing PWM
infrastructure and driver for the AT91SAM9263 PWMC.  The author is
grateful to Russell King, Eric Miao, David Brownell and others for
providing such tall "shoulders" to stand upon.  The proposed updates
to that code should not be interpreted as attempts to address
shortcomings, but rather to extend functionality in ways that were not
originally required.

The implementation of the proposed API is structurally similar to the
generic GPIO API, except that the PWM code uses platform bus_id
strings instead of integers to identify devices.  A configuration
structure is also provided, so that the API can be extended in a
source-code-compatible way to accomodate devices with features not
anticipated by the current code.

Pulse width modulated signals are used in an astounding number and
range of applications, and there is no "one true way" of either
realizing them or employing them to accomplish real work.  The current
proposal attempts to provide a useful feature set for the most basic
users, packaged in such a way as to allow the API to be extended in a
backwards-compatible way as new needs are identified.  Some of these
needs have already been identified.

The proposed code has been run-tested on a Cogent CSB737
(AT91SAM9263), mated to a custom circuit that drives multiple DC
motors and sensors.


Feedback is welcome!



b.g.
--
Bill Gatliff
<[EMAIL PROTECTED]>


==========

Bill Gatliff (6):
  [PWM] Generic PWM API implementation
  [PWM] Changes to existing pwm.h to adapt to generic PWM API
  [PWM] Documentation
  [PWM] Driver for Atmel PWMC peripheral
  [PWM] Install new Atmel PWMC driver in Kconfig, expunge old one
  [PWM] New LED driver and trigger that use PWM API

 Documentation/pwm.txt  |  258 +
 arch/arm/Kconfig   |2 +
 drivers/Makefile   |2 +
 drivers/leds/Kconfig   |   21 +-
 drivers/leds/Makefile  |2 +
 drivers/leds/leds-pwm.c|  141 ++
 drivers/leds/ledtrig-dim.c |   95 +++
 drivers/misc/Kconfig   |9 -
 drivers/misc/Makefile  |1 -
 drivers/misc/atmel_pwm.c   |  409 ---
 drivers/pwm/Kconfig|   24 ++
 drivers/pwm/Makefile   |6 +
 drivers/pwm/atmel-pwm.c|  631 +
 drivers/pwm/pwm.c  |  667 
 include/linux/pwm-led.h|   34 +++
 include/linux/pwm.h|  168 ++--
 16 files changed, 2023 insertions(+), 447 deletions(-)
 create mode 100644 Documentation/pwm.txt
 create mode 100644 drivers/leds/leds-pwm.c
 create mode 100644 drivers/leds/ledtrig-dim.c
 delete mode 100644 drivers/misc/atmel_pwm.c
 create mode 100644 drivers/pwm/Kconfig
 create mode 100644 drivers/pwm/Makefile
 create mode 100644 drivers/pwm/atmel-pwm.c
 create mode 100644 drivers/pwm/pwm.c
 create mode 100644 include/linux/pwm-led.h

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev