All of lore.kernel.org
 help / color / mirror / Atom feed
* How to use mpc8xxx_gpio.c device driver
@ 2010-08-11 13:27 Ravi Gupta
  2010-08-11 14:19 ` Ravi Gupta
  2010-08-11 16:15 ` MJ embd
  0 siblings, 2 replies; 11+ messages in thread
From: Ravi Gupta @ 2010-08-11 13:27 UTC (permalink / raw)
  To: linuxppc-dev, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 3156 bytes --]

Hi,

I am new to device driver development. I am trying to access the GPIO of
MPC837xERDB eval board. I have upgraded its kernel to linux-2.6.28.9 and
enable support for mpc8xxx_gpio.c. On boot up, it successfully detect two
gpio controllers. Now my question is how I am going to use it to communicate
with the gpio pins? Do I have to modify the code in mpc8xxx_gpio.c file to
do whatever I want to do with gpios or I can use the standard gpio API
provided in kernel ( gpio_request()/gpio_free() ). I also tries the standard
kernel API, but it fails. Here is my code :

#include <linux/module.h>
#include <linux/errno.h>  /* error codes */
#include <linux/gpio.h>

static __init int sample_module_init(void)
{
  int ret;

  int i;
  for (i=1; i<32; i++) {
    ret = gpio_request(i, "Sample Driver");
    if (ret) {
      printk(KERN_WARNING "sample_driver: unable to request GPIO_PG%d\n",
i);
      //return ret;
    }
  }

  return 0;
}

static __exit void sample_module_exit(void)
{
  gpio_free(9);
}

MODULE_LICENSE("GPL");

module_init(sample_module_init);
module_exit(sample_module_exit);

It give the following O/P:

[  617.075329] sample_driver: unable to request GPIO_PG1
[  617.080418] sample_driver: unable to request GPIO_PG2
[  617.085470] sample_driver: unable to request GPIO_PG3
[  617.090522] sample_driver: unable to request GPIO_PG4
[  617.095574] sample_driver: unable to request GPIO_PG5
[  617.100625] sample_driver: unable to request GPIO_PG6
[  617.105676] sample_driver: unable to request GPIO_PG7
[  617.110727] sample_driver: unable to request GPIO_PG8
[  617.115779] sample_driver: unable to request GPIO_PG9
[  617.120830] sample_driver: unable to request GPIO_PG10
[  617.125968] sample_driver: unable to request GPIO_PG11
[  617.131106] sample_driver: unable to request GPIO_PG12
[  617.136245] sample_driver: unable to request GPIO_PG13
[  617.141383] sample_driver: unable to request GPIO_PG14
[  617.146521] sample_driver: unable to request GPIO_PG15
[  617.151660] sample_driver: unable to request GPIO_PG16
[  617.156798] sample_driver: unable to request GPIO_PG17
[  617.161936] sample_driver: unable to request GPIO_PG18
[  617.167074] sample_driver: unable to request GPIO_PG19
[  617.172213] sample_driver: unable to request GPIO_PG20
[  617.177351] sample_driver: unable to request GPIO_PG21
[  617.182489] sample_driver: unable to request GPIO_PG22
[  617.187628] sample_driver: unable to request GPIO_PG23
[  617.192767] sample_driver: unable to request GPIO_PG24
[  617.197905] sample_driver: unable to request GPIO_PG25
[  617.203042] sample_driver: unable to request GPIO_PG26
[  617.208182] sample_driver: unable to request GPIO_PG27
[  617.213319] sample_driver: unable to request GPIO_PG28
[  617.218458] sample_driver: unable to request GPIO_PG29
[  617.223597] sample_driver: unable to request GPIO_PG30
[  617.228735] sample_driver: unable to request GPIO_PG31
[  617.233873] sample_driver: unable to request GPIO_PG32

Can someone provide me a sample code or something else. Actually I am trying
to set the GPIO pin no. 9 to active low as it is connected to a LED on
board.

Thanks in advance
Ravi Gupta

[-- Attachment #2: Type: text/html, Size: 3457 bytes --]

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-11 13:27 How to use mpc8xxx_gpio.c device driver Ravi Gupta
@ 2010-08-11 14:19 ` Ravi Gupta
  2010-08-11 16:25   ` Ira W. Snyder
  2010-08-11 16:45   ` Anton Vorontsov
  2010-08-11 16:15 ` MJ embd
  1 sibling, 2 replies; 11+ messages in thread
From: Ravi Gupta @ 2010-08-11 14:19 UTC (permalink / raw)
  To: linuxppc-dev, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 619 bytes --]

Also, when I try to export a gpio in sysfs

echo 9 > /sys/class/gpio/export

It gives me an error in dmesg
gpio_request: gpio-9 (sysfs) status -22
export_store: status -22

Here is a look of sysfs on my machine

# ls /sys/class/gpio/ -la
drwxr-xr-x    4 root     root            0 Jan  1 00:00 .
drwxr-xr-x   24 root     root            0 Jan  1 00:00 ..
--w-------    1 root     root         4096 Jan  1 00:10 export
drwxr-xr-x    3 root     root            0 Jan  1 00:00 gpiochip192
drwxr-xr-x    3 root     root            0 Jan  1 00:00 gpiochip224
--w-------    1 root     root         4096 Jan  1 00:00 unexport

[-- Attachment #2: Type: text/html, Size: 687 bytes --]

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-11 13:27 How to use mpc8xxx_gpio.c device driver Ravi Gupta
  2010-08-11 14:19 ` Ravi Gupta
@ 2010-08-11 16:15 ` MJ embd
  2010-08-12 10:25   ` Ravi Gupta
  1 sibling, 1 reply; 11+ messages in thread
From: MJ embd @ 2010-08-11 16:15 UTC (permalink / raw)
  To: Ravi Gupta; +Cc: linuxppc-dev, linuxppc-dev

u can directly access GPIO registers in kernel, by ioremap of GPIO
memory mapped registers.
you might need to check
- muxing of gpio

-mj

On Wed, Aug 11, 2010 at 6:57 PM, Ravi Gupta <dceravigupta@gmail.com> wrote:
> Hi,
>
> I am new to device driver development. I am trying to access the GPIO of
> MPC837xERDB eval board. I have upgraded its kernel to linux-2.6.28.9 and
> enable support for mpc8xxx_gpio.c. On boot up, it successfully detect two
> gpio controllers. Now my question is how I am going to use it to communic=
ate
> with the gpio pins? Do I have to modify the code in mpc8xxx_gpio.c file t=
o
> do whatever I want to do with gpios or I can use the standard gpio API
> provided in kernel ( gpio_request()/gpio_free() ). I also tries the stand=
ard
> kernel API, but it fails. Here is my code :
>
> #include <linux/module.h>
> #include <linux/errno.h>=A0 /* error codes */
> #include <linux/gpio.h>
>
> static __init int sample_module_init(void)
> {
> =A0 int ret;
>
> =A0 int i;
> =A0 for (i=3D1; i<32; i++) {
> =A0=A0=A0 ret =3D gpio_request(i, "Sample Driver");
> =A0=A0=A0 if (ret) {
> =A0=A0=A0=A0=A0 printk(KERN_WARNING "sample_driver: unable to request GPI=
O_PG%d\n",
> i);
> =A0=A0=A0=A0=A0 //return ret;
> =A0=A0=A0 }
> =A0 }
>
> =A0 return 0;
> }
>
> static __exit void sample_module_exit(void)
> {
> =A0 gpio_free(9);
> }
>
> MODULE_LICENSE("GPL");
>
> module_init(sample_module_init);
> module_exit(sample_module_exit);
>
> It give the following O/P:
>
> [=A0 617.075329] sample_driver: unable to request GPIO_PG1
> [=A0 617.080418] sample_driver: unable to request GPIO_PG2
> [=A0 617.085470] sample_driver: unable to request GPIO_PG3
> [=A0 617.090522] sample_driver: unable to request GPIO_PG4
> [=A0 617.095574] sample_driver: unable to request GPIO_PG5
> [=A0 617.100625] sample_driver: unable to request GPIO_PG6
> [=A0 617.105676] sample_driver: unable to request GPIO_PG7
> [=A0 617.110727] sample_driver: unable to request GPIO_PG8
> [=A0 617.115779] sample_driver: unable to request GPIO_PG9
> [=A0 617.120830] sample_driver: unable to request GPIO_PG10
> [=A0 617.125968] sample_driver: unable to request GPIO_PG11
> [=A0 617.131106] sample_driver: unable to request GPIO_PG12
> [=A0 617.136245] sample_driver: unable to request GPIO_PG13
> [=A0 617.141383] sample_driver: unable to request GPIO_PG14
> [=A0 617.146521] sample_driver: unable to request GPIO_PG15
> [=A0 617.151660] sample_driver: unable to request GPIO_PG16
> [=A0 617.156798] sample_driver: unable to request GPIO_PG17
> [=A0 617.161936] sample_driver: unable to request GPIO_PG18
> [=A0 617.167074] sample_driver: unable to request GPIO_PG19
> [=A0 617.172213] sample_driver: unable to request GPIO_PG20
> [=A0 617.177351] sample_driver: unable to request GPIO_PG21
> [=A0 617.182489] sample_driver: unable to request GPIO_PG22
> [=A0 617.187628] sample_driver: unable to request GPIO_PG23
> [=A0 617.192767] sample_driver: unable to request GPIO_PG24
> [=A0 617.197905] sample_driver: unable to request GPIO_PG25
> [=A0 617.203042] sample_driver: unable to request GPIO_PG26
> [=A0 617.208182] sample_driver: unable to request GPIO_PG27
> [=A0 617.213319] sample_driver: unable to request GPIO_PG28
> [=A0 617.218458] sample_driver: unable to request GPIO_PG29
> [=A0 617.223597] sample_driver: unable to request GPIO_PG30
> [=A0 617.228735] sample_driver: unable to request GPIO_PG31
> [=A0 617.233873] sample_driver: unable to request GPIO_PG32
>
> Can someone provide me a sample code or something else. Actually I am try=
ing
> to set the GPIO pin no. 9 to active low as it is connected to a LED on
> board.
>
> Thanks in advance
> Ravi Gupta
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>



--=20
-mj

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-11 14:19 ` Ravi Gupta
@ 2010-08-11 16:25   ` Ira W. Snyder
  2010-08-11 16:45   ` Anton Vorontsov
  1 sibling, 0 replies; 11+ messages in thread
From: Ira W. Snyder @ 2010-08-11 16:25 UTC (permalink / raw)
  To: Ravi Gupta; +Cc: linuxppc-dev, linuxppc-dev

On Wed, Aug 11, 2010 at 07:49:40PM +0530, Ravi Gupta wrote:
> Also, when I try to export a gpio in sysfs
> 
> echo 9 > /sys/class/gpio/export
> 
> It gives me an error in dmesg
> gpio_request: gpio-9 (sysfs) status -22
> export_store: status -22
> 
> Here is a look of sysfs on my machine
> 
> # ls /sys/class/gpio/ -la
> drwxr-xr-x    4 root     root            0 Jan  1 00:00 .
> drwxr-xr-x   24 root     root            0 Jan  1 00:00 ..
> --w-------    1 root     root         4096 Jan  1 00:10 export
> drwxr-xr-x    3 root     root            0 Jan  1 00:00 gpiochip192
> drwxr-xr-x    3 root     root            0 Jan  1 00:00 gpiochip224
> --w-------    1 root     root         4096 Jan  1 00:00 unexport


Your GPIO pins are numbered from 192-223 on one GPIO chip, and 224-255
on the next GPIO chip. You should be exporting GPIO pin 200 or 201
(192+8 or 192+9), depending on whether your pins are numbered from zero
or one.

"status -22" is -EINVAL: Invalid Argument. You're doing something which
is invalid, so this makes sense. There is no "pin 9".

Ira

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-11 14:19 ` Ravi Gupta
  2010-08-11 16:25   ` Ira W. Snyder
@ 2010-08-11 16:45   ` Anton Vorontsov
  2010-08-13  9:59     ` Ravi Gupta
  1 sibling, 1 reply; 11+ messages in thread
From: Anton Vorontsov @ 2010-08-11 16:45 UTC (permalink / raw)
  To: Ravi Gupta; +Cc: linuxppc-dev, MJ embd, linuxppc-dev

Hi,

On Wed, Aug 11, 2010 at 06:57:16PM +0530, Ravi Gupta wrote:
> I am new to device driver development. I am trying to access the GPIO of
> MPC837xERDB eval board. I have upgraded its kernel to linux-2.6.28.9 and
> enable support for mpc8xxx_gpio.c. On boot up, it successfully detect two
> gpio controllers. Now my question is how I am going to use it to communicate
> with the gpio pins? Do I have to modify the code in mpc8xxx_gpio.c file to
> do whatever I want to do with gpios or I can use the standard gpio API
> provided in kernel ( gpio_request()/gpio_free() ). I also tries the standard
> kernel API, but it fails. Here is my code :

No, you don't have to modify anything, and yes, you can
use standard kernel GPIO API.

> #include <linux/module.h>
> #include <linux/errno.h>  /* error codes */
> #include <linux/gpio.h>
>
> static __init int sample_module_init(void)
> {
>   int ret;
>
>   int i;
>   for (i=1; i<32; i++) {
>     ret = gpio_request(i, "Sample Driver");

Before issing gpio_request() you must get GPIO number from the
of_get_gpio() or of_get_gpio_flags() calls (the _flags variant
will also retreive flags such as 'active-low').

The calls assume that you have gpio = <> specifier in the
device tree, see arch/powerpc/boot/dts/mpc8377_rdb.dts's
"leds" node as an example.

As you want GPIO LEDs, you can use drivers/leds/leds-gpio.c
(see of_gpio_leds_probe() call, it gets gpio numbers via
of_get_gpio_flags() and then requests them via gpio_request()).

Also see

Documentation/powerpc/dts-bindings/gpio/gpio.txt
Documentation/powerpc/dts-bindings/gpio/led.txt

>     if (ret) {
>       printk(KERN_WARNING "sample_driver: unable to request GPIO_PG%d\n",
> i);
>       //return ret;
>     }
>   }
>
>   return 0;
> }


On Wed, Aug 11, 2010 at 07:49:40PM +0530, Ravi Gupta wrote:
> Also, when I try to export a gpio in sysfs
> 
> echo 9 > /sys/class/gpio/export

The gpio numbers are global, i.e. GPIO controller base + GPIO
number within the controller.

[...]
> drwxr-xr-x    3 root     root            0 Jan  1 00:00 gpiochip192

So, if you want GPIO9 within gpiochip192, you should issue
"echo 201 > export".

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-11 16:15 ` MJ embd
@ 2010-08-12 10:25   ` Ravi Gupta
  2010-08-12 15:36     ` Ira W. Snyder
  0 siblings, 1 reply; 11+ messages in thread
From: Ravi Gupta @ 2010-08-12 10:25 UTC (permalink / raw)
  To: MJ embd; +Cc: linuxppc-dev, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 3086 bytes --]

On Wed, Aug 11, 2010 at 9:45 PM, MJ embd <mj.embd@gmail.com> wrote:

> u can directly access GPIO registers in kernel, by ioremap of GPIO
> memory mapped registers.
> you might need to check
> - muxing of gpio
>
> -mj
>

Hi MJ,

Thanks for the reply.
I tried memory mapping but it fails, here is my code :

#include <linux/module.h>
#include <linux/errno.h>    /* error codes */
#include <linux/mm.h>

void __iomem *ioaddr = NULL;

static __init int sample_module_init(void)
{
    ioaddr = ioremap(0xFF400C00, 0x24);
    if(ioaddr == NULL) {
        printk(KERN_WARNING "ioremap failed\n");
    }
    printk(KERN_WARNING "ioremap successed\n");
    printk(KERN_WARNING "GP1DIR = %u\n", ioread32(ioaddr));
    return 0;
}

static __exit void sample_module_exit(void)
{
    iounmap(ioaddr);
}

MODULE_LICENSE("GPL");
module_init(sample_module_init);
module_exit(sample_module_exit);

As per the MPC8377ERDB data sheet default IMMRBAR address is 0xFF40_0000 and
offset of GPIO1 is 0C00 and each GPIO has programmable registers that occupy
24 bytes of memory-mapped space, so I mapped from 24bytes (0x18) starting
from 0xFF40_0C00 address. But when I tried to read the values from the
mapped memory I get the following errors. Is there something I am missing.
Any help with reference to MPC8377ERDB board will be highly appreciable.

# tftp -l ~/immrbar.ko -r immrbar.ko -g 10.20.50.70
# insmod ./immrbar.ko
[  717.825241] ioremap successed
[  717.849215] Machine check in kernel mode.
[  717.853220] Caused by (from SRR1=41000): Transfer error ack signal
[  717.859405] Oops: Machine check, sig: 7 [#1]
[  717.863668] MPC837x RDB
[  717.866106] Modules linked in: immrbar(+)
[  717.870119] NIP: 00000900 LR: d1034054 CTR: c0014d50
[  717.875079] REGS: cf895d00 TRAP: 0200   Not tainted  (2.6.28.9)
[  717.880992] MSR: 00041000 <ME>  CR: 24000082  XER: 20000000
[  717.886578] TASK = cf8e8640[647] 'insmod' THREAD: cf894000
[  717.891882] GPR00: d103404c cf895db0 cf8e8640 00000000 000023d5 ffffffff
c01e
04f4 00020000
[  717.900265] GPR08: 00000001 c0383f3c 000023d5 c0014d50 4c72ff56 10019100
1007
77e0 1007ea98
[  717.908650] GPR16: 10077834 100a0000 100a0000 100a0000 bfaf4828 00000000
1009
f23c 10000cfc
[  717.917034] GPR24: 10000d00 10000d24 10012008 c03650e8 00000000 d1034000
1001
2018 d1030000
[  717.925598] NIP [00000900] 0x900
[  717.928828] LR [d1034054] sample_module_init+0x54/0xc0 [immrbar]
[  717.934828] Call Trace:
[  717.937273] [cf895db0] [d103404c] sample_module_init+0x4c/0xc0 [immrbar]
(unr
eliable)
[  717.945115] [cf895dc0] [c00038a0] do_one_initcall+0x64/0x18c
[  717.950780] [cf895f20] [c004d7b8] sys_init_module+0xac/0x19c
[  717.956441] [cf895f40] [c00122f0] ret_from_syscall+0x0/0x38
[  717.962013] --- Exception: c01 at 0x48043f6c
[  717.962017]     LR = 0x100009cc
[  717.969407] Instruction dump:
[  717.972370] 00000000 XXXXXXXX XXXXXXXX XXXXXXXX 00000000 XXXXXXXX
XXXXXXXX XX
XXXXXX
[  717.980140] 00000000 XXXXXXXX XXXXXXXX XXXXXXXX 7d5043a6 XXXXXXXX
XXXXXXXX XX
XXXXXX
[  717.987919] ---[ end trace a47be794e2873cef ]---

Thanks in advance
Ravi Gupta

[-- Attachment #2: Type: text/html, Size: 3680 bytes --]

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-12 10:25   ` Ravi Gupta
@ 2010-08-12 15:36     ` Ira W. Snyder
  2010-08-13 10:01       ` Ravi Gupta
  0 siblings, 1 reply; 11+ messages in thread
From: Ira W. Snyder @ 2010-08-12 15:36 UTC (permalink / raw)
  To: Ravi Gupta; +Cc: linuxppc-dev, MJ embd, linuxppc-dev

On Thu, Aug 12, 2010 at 03:55:49PM +0530, Ravi Gupta wrote:
> On Wed, Aug 11, 2010 at 9:45 PM, MJ embd <mj.embd@gmail.com> wrote:
> 
> > u can directly access GPIO registers in kernel, by ioremap of GPIO
> > memory mapped registers.
> > you might need to check
> > - muxing of gpio
> >
> > -mj
> >
> 
> Hi MJ,
> 
> Thanks for the reply.
> I tried memory mapping but it fails, here is my code :
> 
> #include <linux/module.h>
> #include <linux/errno.h>    /* error codes */
> #include <linux/mm.h>
> 
> void __iomem *ioaddr = NULL;
> 
> static __init int sample_module_init(void)
> {
>     ioaddr = ioremap(0xFF400C00, 0x24);
>     if(ioaddr == NULL) {
>         printk(KERN_WARNING "ioremap failed\n");
>     }
>     printk(KERN_WARNING "ioremap successed\n");
>     printk(KERN_WARNING "GP1DIR = %u\n", ioread32(ioaddr));
>     return 0;
> }
> 
> static __exit void sample_module_exit(void)
> {
>     iounmap(ioaddr);
> }
> 
> MODULE_LICENSE("GPL");
> module_init(sample_module_init);
> module_exit(sample_module_exit);
> 
> As per the MPC8377ERDB data sheet default IMMRBAR address is 0xFF40_0000 and
> offset of GPIO1 is 0C00 and each GPIO has programmable registers that occupy
> 24 bytes of memory-mapped space, so I mapped from 24bytes (0x18) starting
> from 0xFF40_0C00 address. But when I tried to read the values from the
> mapped memory I get the following errors. Is there something I am missing.
> Any help with reference to MPC8377ERDB board will be highly appreciable.
> 
> # tftp -l ~/immrbar.ko -r immrbar.ko -g 10.20.50.70
> # insmod ./immrbar.ko
> [  717.825241] ioremap successed
> [  717.849215] Machine check in kernel mode.
> [  717.853220] Caused by (from SRR1=41000): Transfer error ack signal
> [  717.859405] Oops: Machine check, sig: 7 [#1]
> [  717.863668] MPC837x RDB
> [  717.866106] Modules linked in: immrbar(+)
> [  717.870119] NIP: 00000900 LR: d1034054 CTR: c0014d50
> [  717.875079] REGS: cf895d00 TRAP: 0200   Not tainted  (2.6.28.9)
> [  717.880992] MSR: 00041000 <ME>  CR: 24000082  XER: 20000000
> [  717.886578] TASK = cf8e8640[647] 'insmod' THREAD: cf894000
> [  717.891882] GPR00: d103404c cf895db0 cf8e8640 00000000 000023d5 ffffffff
> c01e
> 04f4 00020000
> [  717.900265] GPR08: 00000001 c0383f3c 000023d5 c0014d50 4c72ff56 10019100
> 1007
> 77e0 1007ea98
> [  717.908650] GPR16: 10077834 100a0000 100a0000 100a0000 bfaf4828 00000000
> 1009
> f23c 10000cfc
> [  717.917034] GPR24: 10000d00 10000d24 10012008 c03650e8 00000000 d1034000
> 1001
> 2018 d1030000
> [  717.925598] NIP [00000900] 0x900
> [  717.928828] LR [d1034054] sample_module_init+0x54/0xc0 [immrbar]
> [  717.934828] Call Trace:
> [  717.937273] [cf895db0] [d103404c] sample_module_init+0x4c/0xc0 [immrbar]
> (unr
> eliable)
> [  717.945115] [cf895dc0] [c00038a0] do_one_initcall+0x64/0x18c
> [  717.950780] [cf895f20] [c004d7b8] sys_init_module+0xac/0x19c
> [  717.956441] [cf895f40] [c00122f0] ret_from_syscall+0x0/0x38
> [  717.962013] --- Exception: c01 at 0x48043f6c
> [  717.962017]     LR = 0x100009cc
> [  717.969407] Instruction dump:
> [  717.972370] 00000000 XXXXXXXX XXXXXXXX XXXXXXXX 00000000 XXXXXXXX
> XXXXXXXX XX
> XXXXXX
> [  717.980140] 00000000 XXXXXXXX XXXXXXXX XXXXXXXX 7d5043a6 XXXXXXXX
> XXXXXXXX XX
> XXXXXX
> [  717.987919] ---[ end trace a47be794e2873cef ]---
> 

Looking at the device tree for this board, it appears U-Boot remaps the
IMMR registers to 0xe0000000. They are no longer accessible at
0xff400000.

I would recommend studying arch/powerpc/boot/dts/mpc8377_rdb.dts in the
Linux source code. That describes the device layout on your board after
U-Boot has run.

A wonderful tool for testing devices from userspace is "busybox devmem".
It allows you to poke any physical address with any value. The output of
"busybox devmem --help" should get you started. As a quick example,
"busybox devmem 0xe0000c00 w 0x1" will write the 32-bit value 0x1 to
address 0xe0000c00.

I would also recommend using the built-in Linux GPIO API. It works, you
just need to figure out how to use it. It will be much easier to get
your code upstream if you use the provided APIs.

The Documentation/gpio.txt file should help you in understanding the
in-kernel Linux GPIO API. I'm afraid I don't have much experience other
than accessing it via sysfs from userspace.

Ira

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-11 16:45   ` Anton Vorontsov
@ 2010-08-13  9:59     ` Ravi Gupta
  2010-08-13 13:16       ` Anton Vorontsov
  0 siblings, 1 reply; 11+ messages in thread
From: Ravi Gupta @ 2010-08-13  9:59 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linuxppc-dev, MJ embd, linuxppc-dev, Ira W. Snyder


[-- Attachment #1.1: Type: text/plain, Size: 5563 bytes --]

On Wed, Aug 11, 2010 at 10:15 PM, Anton Vorontsov <cbouatmailru@gmail.com>wrote:

> Hi,
>
> On Wed, Aug 11, 2010 at 06:57:16PM +0530, Ravi Gupta wrote:
> > I am new to device driver development. I am trying to access the GPIO of
> > MPC837xERDB eval board. I have upgraded its kernel to linux-2.6.28.9 and
> > enable support for mpc8xxx_gpio.c. On boot up, it successfully detect two
> > gpio controllers. Now my question is how I am going to use it to
> communicate
> > with the gpio pins? Do I have to modify the code in mpc8xxx_gpio.c file
> to
> > do whatever I want to do with gpios or I can use the standard gpio API
> > provided in kernel ( gpio_request()/gpio_free() ). I also tries the
> standard
> > kernel API, but it fails. Here is my code :
>
> No, you don't have to modify anything, and yes, you can
> use standard kernel GPIO API.
>
> > #include <linux/module.h>
> > #include <linux/errno.h>  /* error codes */
> > #include <linux/gpio.h>
> >
> > static __init int sample_module_init(void)
> > {
> >   int ret;
> >
> >   int i;
> >   for (i=1; i<32; i++) {
> >     ret = gpio_request(i, "Sample Driver");
>
> Before issing gpio_request() you must get GPIO number from the
> of_get_gpio() or of_get_gpio_flags() calls (the _flags variant
> will also retreive flags such as 'active-low').
>
> The calls assume that you have gpio = <> specifier in the
> device tree, see arch/powerpc/boot/dts/mpc8377_rdb.dts's
> "leds" node as an example.
>
> As you want GPIO LEDs, you can use drivers/leds/leds-gpio.c
> (see of_gpio_leds_probe() call, it gets gpio numbers via
> of_get_gpio_flags() and then requests them via gpio_request()).
>
> Also see
>
> Documentation/powerpc/dts-bindings/gpio/gpio.txt
> Documentation/powerpc/dts-bindings/gpio/led.txt
>
> >     if (ret) {
> >       printk(KERN_WARNING "sample_driver: unable to request GPIO_PG%d\n",
> > i);
> >       //return ret;
> >     }
> >   }
> >
> >   return 0;
> > }
>
>
> On Wed, Aug 11, 2010 at 07:49:40PM +0530, Ravi Gupta wrote:
> > Also, when I try to export a gpio in sysfs
> >
> > echo 9 > /sys/class/gpio/export
>
> The gpio numbers are global, i.e. GPIO controller base + GPIO
> number within the controller.
>
> [...]
> > drwxr-xr-x    3 root     root            0 Jan  1 00:00 gpiochip192
>
> So, if you want GPIO9 within gpiochip192, you should issue
> "echo 201 > export".
>
> Thanks,
>
> --
> Anton Vorontsov
> email: cbouatmailru@gmail.com
> irc://irc.freenode.net/bd2
>

Hi Anton,

Thanks for the reply.
I had added the entries for gpio pin 9 for both controllers(I was not sure
with controller's pin is connected to LED, but now I know it is pin no. 233
i.e 224+9) in the mpc8377_rdb.dts file. Below is a portion of my dts file, I
have attached the complete dts file as attachment.

immr@e0000000 {
    #address-cells = <1>;
    #size-cells = <1>;
    device_type = "soc";
    compatible = "simple-bus";
    ranges = <0x0 0xe0000000 0x00100000>;
    reg = <0xe0000000 0x00000200>;
    bus-frequency = <0>;

    wdt@200 {
        device_type = "watchdog";
        compatible = "mpc83xx_wdt";
        reg = <0x200 0x100>;
    };

    gpio1: gpio-controller@c00 {
        #gpio-cells = <2>;
        compatible = "fsl,mpc8377-gpio", "fsl,mpc8349-gpio";
        reg = <0xc00 0x100>;
        interrupts = <74 0x8>;
        interrupt-parent = <&ipic>;
        gpio-controller;
    };

    gpio2: gpio-controller@d00 {
        #gpio-cells = <2>;
        compatible = "fsl,mpc8377-gpio", "fsl,mpc8349-gpio";
        reg = <0xd00 0x100>;
        interrupts = <75 0x8>;
        interrupt-parent = <&ipic>;
        gpio-controller;
    };

   * led@0 {
        compatible = "gpio-leds";
        label = "hdd";
        gpios = <&gpio1 9 0>;
    };

    led@1 {
        compatible = "gpio-leds";
        label = "rom";
        gpios = <&gpio2 9 0>;
    };*
    .
    .
    .
    .
};


Also I have enabled drivers/leds/leds-gpio.c in my kernel. To test whether
the leds entires in dts file get attached to leds-gpio driver, I added
printks in the probe function of the driver.

static int gpio_led_probe(struct platform_device *pdev)
{
  struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
  struct gpio_led *cur_led;
  struct gpio_led_data *leds_data, *led_dat;
  int i, ret = 0;

  *printk(KERN_INFO "led: inside gpio_led_probe.\n");*

  ....
}

But I couldn't see "led: inside gpio_led_probe." message in dmesg. I checked
sysfs and I can see entries of leds. Here is contents of sysfs on my
machine.

# ls /sys/devices/ -la
drwxr-xr-x    7 root     root            0 Jan  1 01:58 .
drwxr-xr-x   12 root     root            0 Jan  1 00:00 ..
drwxr-xr-x   22 root     root            0 Jan  1 01:58 *e0000000.immr*
drwxr-xr-x    5 root     root            0 Jan  1 01:58 e0005000.localbus
drwxr-xr-x    4 root     root            0 Jan  1 01:58 pci0000:00
drwxr-xr-x    9 root     root            0 Jan  1 01:58 platform
drwxr-xr-x    8 root     root            0 Jan  1 01:58 system


# ls /sys/devices/e0000000.immr/
bus                           e0004600.serial       *led1.0*
devspec                    e0007000.spi           *led2.1*
e0000200.wdt            e00082a8.dma         modalias
e0000700.interrupt-    e0018000.sata         name
e0000b00.power        e0019000.sata         power
e0000c00.gpio-contr  e0023000.usb          sleep-nexus.2
e0000d00.gpio-contr  e0024000.ethernet    subsystem
e0003100.i2c            e0025000.ethernet    uevent
e0004500.serial        e0030000.crypto

Is there something that I am doing wrong? Please suggest.

Thanks in Advance
Ravi Gupta

[-- Attachment #1.2: Type: text/html, Size: 7119 bytes --]

[-- Attachment #2: mpc8377_rdb.dts --]
[-- Type: application/octet-stream, Size: 11597 bytes --]

/*
 * MPC8377E RDB Device Tree Source
 *
 * Copyright 2007, 2008 Freescale Semiconductor Inc.
 *
 * 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.
 */

/dts-v1/;

/ {
	compatible = "fsl,mpc8377rdb";
	#address-cells = <1>;
	#size-cells = <1>;

	aliases {
		ethernet0 = &enet0;
		ethernet1 = &enet1;
		serial0 = &serial0;
		serial1 = &serial1;
		pci0 = &pci0;
		pci1 = &pci1;
		pci2 = &pci2;
	};

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;

		PowerPC,8377@0 {
			device_type = "cpu";
			reg = <0x0>;
			d-cache-line-size = <32>;
			i-cache-line-size = <32>;
			d-cache-size = <32768>;
			i-cache-size = <32768>;
			timebase-frequency = <0>;
			bus-frequency = <0>;
			clock-frequency = <0>;
		};
	};

	memory {
		device_type = "memory";
		reg = <0x00000000 0x10000000>;	// 256MB at 0
	};

	localbus@e0005000 {
		#address-cells = <2>;
		#size-cells = <1>;
		compatible = "fsl,mpc8377-elbc", "fsl,elbc", "simple-bus";
		reg = <0xe0005000 0x1000>;
		interrupts = <77 0x8>;
		interrupt-parent = <&ipic>;

		// CS0 and CS1 are swapped when
		// booting from nand, but the
		// addresses are the same.
		ranges = <0x0 0x0 0xfe000000 0x00800000
		          0x1 0x0 0xe0600000 0x00008000
		          0x2 0x0 0xf0000000 0x00020000
		          0x3 0x0 0xfa000000 0x00008000>;

		flash@0,0 {
			#address-cells = <1>;
			#size-cells = <1>;
			compatible = "cfi-flash";
			reg = <0x0 0x0 0x800000>;
			bank-width = <2>;
			device-width = <1>;
		};

		nand@1,0 {
			#address-cells = <1>;
			#size-cells = <1>;
			compatible = "fsl,mpc8377-fcm-nand",
			             "fsl,elbc-fcm-nand";
			reg = <0x1 0x0 0x8000>;

			u-boot@0 {
				reg = <0x0 0x100000>;
				read-only;
			};

			kernel@100000 {
				reg = <0x100000 0x300000>;
			};
			fs@400000 {
				reg = <0x400000 0x1c00000>;
			};
		};
	};

	immr@e0000000 {
		#address-cells = <1>;
		#size-cells = <1>;
		device_type = "soc";
		compatible = "simple-bus";
		ranges = <0x0 0xe0000000 0x00100000>;
		reg = <0xe0000000 0x00000200>;
		bus-frequency = <0>;

		wdt@200 {
			device_type = "watchdog";
			compatible = "mpc83xx_wdt";
			reg = <0x200 0x100>;
		};

		gpio1: gpio-controller@c00 {
			#gpio-cells = <2>;
			compatible = "fsl,mpc8377-gpio", "fsl,mpc8349-gpio";
			reg = <0xc00 0x100>;
			interrupts = <74 0x8>;
			interrupt-parent = <&ipic>;
			gpio-controller;
			
		
		};

		gpio2: gpio-controller@d00 {
			#gpio-cells = <2>;
			compatible = "fsl,mpc8377-gpio", "fsl,mpc8349-gpio";
			reg = <0xd00 0x100>;
			interrupts = <75 0x8>;
			interrupt-parent = <&ipic>;
			gpio-controller;
		};

		led@0 {
			compatible = "gpio-leds";
			label = "hdd";
			gpios = <&gpio1 9 0>; 
		};

		led@1 {
			compatible = "gpio-leds";
			label = "rom";
			gpios = <&gpio2 9 0>; 
		};

		sleep-nexus {
			#address-cells = <1>;
			#size-cells = <1>;
			compatible = "simple-bus";
			sleep = <&pmc 0x0c000000>;
			ranges;

			i2c@3000 {
				#address-cells = <1>;
				#size-cells = <0>;
				cell-index = <0>;
				compatible = "fsl-i2c";
				reg = <0x3000 0x100>;
				interrupts = <14 0x8>;
				interrupt-parent = <&ipic>;
				dfsrr;

				dtt@48 {
					compatible = "national,lm75";
					reg = <0x48>;
				};

				at24@50 {
					compatible = "at24,24c256";
					reg = <0x50>;
				};

				rtc@68 {
					compatible = "dallas,ds1339";
					reg = <0x68>;
				};

				mcu_pio: mcu@a {
					#gpio-cells = <2>;
					compatible = "fsl,mc9s08qg8-mpc8377erdb",
						     "fsl,mcu-mpc8349emitx";
					reg = <0x0a>;
					gpio-controller;
				};
			};

			sdhci@2e000 {
				compatible = "fsl,mpc8377-esdhc", "fsl,esdhc";
				reg = <0x2e000 0x1000>;
				interrupts = <42 0x8>;
				interrupt-parent = <&ipic>;
				sdhci,wp-inverted;
				/* Filled in by U-Boot */
				clock-frequency = <111111111>;
			};
		};

		i2c@3100 {
			#address-cells = <1>;
			#size-cells = <0>;
			cell-index = <1>;
			compatible = "fsl-i2c";
			reg = <0x3100 0x100>;
			interrupts = <15 0x8>;
			interrupt-parent = <&ipic>;
			dfsrr;
		};

		spi@7000 {
			cell-index = <0>;
			compatible = "fsl,spi";
			reg = <0x7000 0x1000>;
			interrupts = <16 0x8>;
			interrupt-parent = <&ipic>;
			mode = "cpu";
		};

		dma@82a8 {
			#address-cells = <1>;
			#size-cells = <1>;
			compatible = "fsl,mpc8377-dma", "fsl,elo-dma";
			reg = <0x82a8 4>;
			ranges = <0 0x8100 0x1a8>;
			interrupt-parent = <&ipic>;
			interrupts = <71 8>;
			cell-index = <0>;
			dma-channel@0 {
				compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
				reg = <0 0x80>;
				cell-index = <0>;
				interrupt-parent = <&ipic>;
				interrupts = <71 8>;
			};
			dma-channel@80 {
				compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
				reg = <0x80 0x80>;
				cell-index = <1>;
				interrupt-parent = <&ipic>;
				interrupts = <71 8>;
			};
			dma-channel@100 {
				compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
				reg = <0x100 0x80>;
				cell-index = <2>;
				interrupt-parent = <&ipic>;
				interrupts = <71 8>;
			};
			dma-channel@180 {
				compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
				reg = <0x180 0x28>;
				cell-index = <3>;
				interrupt-parent = <&ipic>;
				interrupts = <71 8>;
			};
		};

		usb@23000 {
			compatible = "fsl-usb2-dr";
			reg = <0x23000 0x1000>;
			#address-cells = <1>;
			#size-cells = <0>;
			interrupt-parent = <&ipic>;
			interrupts = <38 0x8>;
			phy_type = "ulpi";
			sleep = <&pmc 0x00c00000>;
		};

		enet0: ethernet@24000 {
			#address-cells = <1>;
			#size-cells = <1>;
			cell-index = <0>;
			device_type = "network";
			model = "eTSEC";
			compatible = "gianfar";
			reg = <0x24000 0x1000>;
			ranges = <0x0 0x24000 0x1000>;
			local-mac-address = [ 00 00 00 00 00 00 ];
			interrupts = <32 0x8 33 0x8 34 0x8>;
			phy-connection-type = "mii";
			interrupt-parent = <&ipic>;
			tbi-handle = <&tbi0>;
			phy-handle = <&phy2>;
			sleep = <&pmc 0xc0000000>;
			fsl,magic-packet;

			mdio@520 {
				#address-cells = <1>;
				#size-cells = <0>;
				compatible = "fsl,gianfar-mdio";
				reg = <0x520 0x20>;

				phy2: ethernet-phy@2 {
					interrupt-parent = <&ipic>;
					interrupts = <17 0x8>;
					reg = <0x2>;
					device_type = "ethernet-phy";
				};

				tbi0: tbi-phy@11 {
					reg = <0x11>;
					device_type = "tbi-phy";
				};
			};
		};

		enet1: ethernet@25000 {
			#address-cells = <1>;
			#size-cells = <1>;
			cell-index = <1>;
			device_type = "network";
			model = "eTSEC";
			compatible = "gianfar";
			reg = <0x25000 0x1000>;
			ranges = <0x0 0x25000 0x1000>;
			local-mac-address = [ 00 00 00 00 00 00 ];
			interrupts = <35 0x8 36 0x8 37 0x8>;
			phy-connection-type = "mii";
			interrupt-parent = <&ipic>;
			fixed-link = <1 1 1000 0 0>;
			tbi-handle = <&tbi1>;
			sleep = <&pmc 0x30000000>;
			fsl,magic-packet;

			mdio@520 {
				#address-cells = <1>;
				#size-cells = <0>;
				compatible = "fsl,gianfar-tbi";
				reg = <0x520 0x20>;

				tbi1: tbi-phy@11 {
					reg = <0x11>;
					device_type = "tbi-phy";
				};
			};
		};

		serial0: serial@4500 {
			cell-index = <0>;
			device_type = "serial";
			compatible = "ns16550";
			reg = <0x4500 0x100>;
			clock-frequency = <0>;
			interrupts = <9 0x8>;
			interrupt-parent = <&ipic>;
		};

		serial1: serial@4600 {
			cell-index = <1>;
			device_type = "serial";
			compatible = "ns16550";
			reg = <0x4600 0x100>;
			clock-frequency = <0>;
			interrupts = <10 0x8>;
			interrupt-parent = <&ipic>;
		};

		crypto@30000 {
			compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2",
				     "fsl,sec2.1", "fsl,sec2.0";
			reg = <0x30000 0x10000>;
			interrupts = <11 0x8>;
			interrupt-parent = <&ipic>;
			fsl,num-channels = <4>;
			fsl,channel-fifo-len = <24>;
			fsl,exec-units-mask = <0x9fe>;
			fsl,descriptor-types-mask = <0x3ab0ebf>;
			sleep = <&pmc 0x03000000>;
		};

		sata@18000 {
			compatible = "fsl,mpc8377-sata", "fsl,pq-sata";
			reg = <0x18000 0x1000>;
			interrupts = <44 0x8>;
			interrupt-parent = <&ipic>;
			sleep = <&pmc 0x000000c0>;
		};

		sata@19000 {
			compatible = "fsl,mpc8377-sata", "fsl,pq-sata";
			reg = <0x19000 0x1000>;
			interrupts = <45 0x8>;
			interrupt-parent = <&ipic>;
			sleep = <&pmc 0x00000030>;
		};

		/* IPIC
		 * interrupts cell = <intr #, sense>
		 * sense values match linux IORESOURCE_IRQ_* defines:
		 * sense == 8: Level, low assertion
		 * sense == 2: Edge, high-to-low change
		 */
		ipic: interrupt-controller@700 {
			compatible = "fsl,ipic";
			interrupt-controller;
			#address-cells = <0>;
			#interrupt-cells = <2>;
			reg = <0x700 0x100>;
		};

		pmc: power@b00 {
			compatible = "fsl,mpc8377-pmc", "fsl,mpc8349-pmc";
			reg = <0xb00 0x100 0xa00 0x100>;
			interrupts = <80 0x8>;
			interrupt-parent = <&ipic>;
		};
	};

	pci0: pci@e0008500 {
		interrupt-map-mask = <0xf800 0 0 7>;
		interrupt-map = <
				/* IRQ5 = 21 = 0x15, IRQ6 = 0x16, IRQ7 = 23 = 0x17 */

				/* IDSEL AD14 IRQ6 inta */
				 0x7000 0x0 0x0 0x1 &ipic 22 0x8

				/* IDSEL AD15 IRQ5 inta, IRQ6 intb, IRQ7 intd */
				 0x7800 0x0 0x0 0x1 &ipic 21 0x8
				 0x7800 0x0 0x0 0x2 &ipic 22 0x8
				 0x7800 0x0 0x0 0x4 &ipic 23 0x8

				/* IDSEL AD28 IRQ7 inta, IRQ5 intb IRQ6 intc*/
				 0xE000 0x0 0x0 0x1 &ipic 23 0x8
				 0xE000 0x0 0x0 0x2 &ipic 21 0x8
				 0xE000 0x0 0x0 0x3 &ipic 22 0x8>;
		interrupt-parent = <&ipic>;
		interrupts = <66 0x8>;
		bus-range = <0 0>;
		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
		          0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
		sleep = <&pmc 0x00010000>;
		clock-frequency = <66666666>;
		#interrupt-cells = <1>;
		#size-cells = <2>;
		#address-cells = <3>;
		reg = <0xe0008500 0x100		/* internal registers */
		       0xe0008300 0x8>;		/* config space access registers */
		compatible = "fsl,mpc8349-pci";
		device_type = "pci";
	};

	pci1: pcie@e0009000 {
		#address-cells = <3>;
		#size-cells = <2>;
		#interrupt-cells = <1>;
		device_type = "pci";
		compatible = "fsl,mpc8377-pcie", "fsl,mpc8314-pcie";
		reg = <0xe0009000 0x00001000>;
		ranges = <0x02000000 0 0xa8000000 0xa8000000 0 0x10000000
		          0x01000000 0 0x00000000 0xb8000000 0 0x00800000>;
		bus-range = <0 255>;
		interrupt-map-mask = <0xf800 0 0 7>;
		interrupt-map = <0 0 0 1 &ipic 1 8
				 0 0 0 2 &ipic 1 8
				 0 0 0 3 &ipic 1 8
				 0 0 0 4 &ipic 1 8>;
		sleep = <&pmc 0x00300000>;
		clock-frequency = <0>;

		pcie@0 {
			#address-cells = <3>;
			#size-cells = <2>;
			device_type = "pci";
			reg = <0 0 0 0 0>;
			ranges = <0x02000000 0 0xa8000000
				  0x02000000 0 0xa8000000
				  0 0x10000000
				  0x01000000 0 0x00000000
				  0x01000000 0 0x00000000
				  0 0x00800000>;
		};
	};

	pci2: pcie@e000a000 {
		#address-cells = <3>;
		#size-cells = <2>;
		#interrupt-cells = <1>;
		device_type = "pci";
		compatible = "fsl,mpc8377-pcie", "fsl,mpc8314-pcie";
		reg = <0xe000a000 0x00001000>;
		ranges = <0x02000000 0 0xc8000000 0xc8000000 0 0x10000000
			  0x01000000 0 0x00000000 0xd8000000 0 0x00800000>;
		bus-range = <0 255>;
		interrupt-map-mask = <0xf800 0 0 7>;
		interrupt-map = <0 0 0 1 &ipic 2 8
				 0 0 0 2 &ipic 2 8
				 0 0 0 3 &ipic 2 8
				 0 0 0 4 &ipic 2 8>;
		sleep = <&pmc 0x000c0000>;
		clock-frequency = <0>;

		pcie@0 {
			#address-cells = <3>;
			#size-cells = <2>;
			device_type = "pci";
			reg = <0 0 0 0 0>;
			ranges = <0x02000000 0 0xc8000000
				  0x02000000 0 0xc8000000
				  0 0x10000000
				  0x01000000 0 0x00000000
				  0x01000000 0 0x00000000
				  0 0x00800000>;
		};
	};
};

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-12 15:36     ` Ira W. Snyder
@ 2010-08-13 10:01       ` Ravi Gupta
  0 siblings, 0 replies; 11+ messages in thread
From: Ravi Gupta @ 2010-08-13 10:01 UTC (permalink / raw)
  To: Ira W. Snyder; +Cc: linuxppc-dev, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 1160 bytes --]

> Looking at the device tree for this board, it appears U-Boot remaps the
> IMMR registers to 0xe0000000. They are no longer accessible at
> 0xff400000.
>
> I would recommend studying arch/powerpc/boot/dts/mpc8377_rdb.dts in the
> Linux source code. That describes the device layout on your board after
> U-Boot has run.
>
> A wonderful tool for testing devices from userspace is "busybox devmem".
> It allows you to poke any physical address with any value. The output of
> "busybox devmem --help" should get you started. As a quick example,
> "busybox devmem 0xe0000c00 w 0x1" will write the 32-bit value 0x1 to
> address 0xe0000c00.
>
> I would also recommend using the built-in Linux GPIO API. It works, you
> just need to figure out how to use it. It will be much easier to get
> your code upstream if you use the provided APIs.
>
> The Documentation/gpio.txt file should help you in understanding the
> in-kernel Linux GPIO API. I'm afraid I don't have much experience other
> than accessing it via sysfs from userspace.
>
> Ira
>

Hi Ira,

Thanks for another great reply. Now I can also access gpio memory map
registers.

Thanks and Regards,
Ravi Gupta

[-- Attachment #2: Type: text/html, Size: 1476 bytes --]

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-13  9:59     ` Ravi Gupta
@ 2010-08-13 13:16       ` Anton Vorontsov
  2010-08-18 12:45         ` Ravi Gupta
  0 siblings, 1 reply; 11+ messages in thread
From: Anton Vorontsov @ 2010-08-13 13:16 UTC (permalink / raw)
  To: Ravi Gupta; +Cc: linuxppc-dev, MJ embd, linuxppc-dev, Ira W. Snyder

Hi,

On Fri, Aug 13, 2010 at 03:29:11PM +0530, Ravi Gupta wrote:
[...]
> Thanks for the reply.
> I had added the entries for gpio pin 9 for both controllers(I was not sure
> with controller's pin is connected to LED, but now I know it is pin no. 233
> i.e 224+9) in the mpc8377_rdb.dts file. Below is a portion of my dts file, I
> have attached the complete dts file as attachment.
> 
> immr@e0000000 {
[...]
>    * led@0 {
>         compatible = "gpio-leds";
>         label = "hdd";
>         gpios = <&gpio1 9 0>;
>     };

What kernel version you look at? Please see the latest kernel,
it has MCU GPIO LED nodes already, and you can just add some
additional nodes.

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=arch/powerpc/boot/dts/mpc8377_rdb.dts#l490

[...]
> Also I have enabled drivers/leds/leds-gpio.c in my kernel. To test whether
> the leds entires in dts file get attached to leds-gpio driver, I added
> printks in the probe function of the driver.
> 
> static int gpio_led_probe(struct platform_device *pdev)
> {
>   struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
>   struct gpio_led *cur_led;
>   struct gpio_led_data *leds_data, *led_dat;
>   int i, ret = 0;
> 
>   *printk(KERN_INFO "led: inside gpio_led_probe.\n");*

You have put the printk into the wrong function. It should
have been of_gpio_leds_probe():

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/leds/leds-gpio.c#l227

If you don't have that function then you use too old kernel.

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

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

* Re: How to use mpc8xxx_gpio.c device driver
  2010-08-13 13:16       ` Anton Vorontsov
@ 2010-08-18 12:45         ` Ravi Gupta
  0 siblings, 0 replies; 11+ messages in thread
From: Ravi Gupta @ 2010-08-18 12:45 UTC (permalink / raw)
  To: Anton Vorontsov, Ira W. Snyder, MJ embd; +Cc: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 4111 bytes --]

Hi,

Thanks for all your replies. Now I want to enable interrupts on some GPIO
pins(GPIO pins number 224, 225, 226, 227, 228 and 229 i.e gpiochip224's pins
0 to 5). I configured these pins as input(GPIOF_IN) during gpio request. I
am able to request gpio pins successfully.

#define GPIO_CHIP0_BASE    192
#define GPIO_CHIP0_COUNT   32

#define GPIO_CHIP1_BASE    224
#define GPIO_CHIP1_COUNT   32

#define GPIO(chip, pin) (GPIO_CHIP##chip##_BASE + (pin))

/* Initial GPIO pins setting. */
static struct gpio gpio_pins[] = {
  { GPIO(1,  0), GPIOF_IN,            "Chip 1, Pin 0"  },
  { GPIO(1,  1), GPIOF_IN,            "Chip 1, Pin 1"  },
  { GPIO(1,  2), GPIOF_IN,            "Chip 1, Pin 2"  },
  { GPIO(1,  3), GPIOF_IN,            "Chip 1, Pin 3"  },
  { GPIO(1,  4), GPIOF_IN,            "Chip 1, Pin 4"  },
  { GPIO(1,  5), GPIOF_IN,            "Chip 1, Pin 5"  },
};

static __init int gpio_module_init(void)
{
  int err;
  dev_t devno = 0;

  printk(KERN_INFO "GPIO Driver Version 0.1\n");

  /* resuest the gpio pin */
  err = gpio_request_array(gpio_pins, ARRAY_SIZE(gpio_pins));
  if (err) {
      printk(KERN_WARNING "gpio: unable to request gpio pins\n");
      return -EBUSY;
  }

  /* register interrupts handlers */
  err = gpio_request_irq_array(gpio_irq_pins, ARRAY_SIZE(gpio_irq_pins));
  if (err) {
      printk(KERN_WARNING "gpio: unable to register interrupt handler.\n");
      goto interrupt_fail;
  }
.
.
.
}

Now in order to enable interrupts I have to set the bits corresponding to
these pins in gpiochp Interrupt Mask Register.

My first question is that is there any gpio API call available for doing
this? OR I have to manually memory map the gpio IMR register and set bit
manually? For the time being I have manually set the IMR bit(using memory
map).

Second, in order to register an interrupt handler on a gpio pin, I need a
IRQ number, so how am I going to get that number? From the
Documentation/gpio.txt, it looks to me that gpio_to_irq() function should
give me the irq number, but when I tried to use it, it gives me an error.

#define GPIO_CHIP0_BASE    192
#define GPIO_CHIP0_COUNT   32

#define GPIO_CHIP1_BASE    224
#define GPIO_CHIP1_COUNT   32

#define GPIO(chip, pin) (GPIO_CHIP##chip##_BASE + (pin))

static struct gpio_irq gpio_irq_pins[] = {
  { GPIO(1, 0), IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW },
  { GPIO(1, 1), IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW },
  { GPIO(1, 2), IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW },
  { GPIO(1, 3), IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW },
  { GPIO(1, 4), IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW },
  { GPIO(1, 5), IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW },
};

int gpio_request_irq_array(struct gpio_irq *array, size_t num)
{
  int i, err, irq;

  for (i = 0; i < num; i++, array++) {
    /* get the irq number corresponding to the gpio pin */
    irq = gpio_to_irq(array->gpio);
    if (irq < 0) {
      printk(KERN_ERR "gpio: Trying to get irq number for GPIO%d\n",
array->gpio);
      err = -EINVAL;
      goto err_free;
    }
    printd("gpio: irq number for GPIO%d = %d(i=%d)\n", array->gpio, irq, i);


    /* set the irq type for the gpio pin */
    err = set_irq_type(irq, array->type);
    if (err)
      goto err_free;

    /* register irq handler */
    err = request_irq(irq, gpio_irq_handler, IRQF_SHARED, "GPIO Driver",
NULL);
    if (err) {
      printk(KERN_ERR "gpio: can't get assigned irq for GPIO%d\n",
array->gpio);
      goto err_free;
    }
  }
  return 0;

err_free:
  while (i--)
    free_irq(gpio_to_irq((--array)->gpio), NULL);
  return err;
}

Given above is my driver code, I have implemented a function named
"gpio_request_irq_array" which works in same manner as that of
"gpio_request_array". I am calling in the init function, see the init code
given initially. Now when I load it on my MPC837xERDB board, it gives the
following errors.

[ 1812.776420] GPIO Driver Version 0.1
[ 1812.779985] gpio: Trying to get irq number for GPIO224
[ 1812.785126] gpio: unable to register interrupt handler.
insmod: error inserting './gpio.ko': -1 Invalid parameters

Thanks in advance
Ravi Gupta

[-- Attachment #2: Type: text/html, Size: 4701 bytes --]

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

end of thread, other threads:[~2010-08-18 12:45 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-11 13:27 How to use mpc8xxx_gpio.c device driver Ravi Gupta
2010-08-11 14:19 ` Ravi Gupta
2010-08-11 16:25   ` Ira W. Snyder
2010-08-11 16:45   ` Anton Vorontsov
2010-08-13  9:59     ` Ravi Gupta
2010-08-13 13:16       ` Anton Vorontsov
2010-08-18 12:45         ` Ravi Gupta
2010-08-11 16:15 ` MJ embd
2010-08-12 10:25   ` Ravi Gupta
2010-08-12 15:36     ` Ira W. Snyder
2010-08-13 10:01       ` Ravi Gupta

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.