public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Question: GPIO driver how to get irq_base
@ 2011-04-21  7:32 Tomoya MORINAGA
  2011-04-21  8:09 ` Lars-Peter Clausen
  0 siblings, 1 reply; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-04-21  7:32 UTC (permalink / raw)
  To: linux-kernel, 'Grant Likely'; +Cc: toshiharu-linux

Hi GPIO maintainer,

Need your help.
I want to add interrupt function to gpio/pch_gpio.c

According to other upstreamed GPIO driver, (e.g. pl061, langwell, etc...)
2 IRQs(irq, irq_base) are used.

I can get "irq" from (struct pci_dev *)pdev->irq.
However I can't understand where can I get the "irq_base".
Let me know how to get.

Thanks,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.


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

* Re: Question: GPIO driver how to get irq_base
  2011-04-21  7:32 Question: GPIO driver how to get irq_base Tomoya MORINAGA
@ 2011-04-21  8:09 ` Lars-Peter Clausen
  2011-04-21 13:45   ` Grant Likely
  0 siblings, 1 reply; 18+ messages in thread
From: Lars-Peter Clausen @ 2011-04-21  8:09 UTC (permalink / raw)
  To: Tomoya MORINAGA; +Cc: linux-kernel, 'Grant Likely', toshiharu-linux

On 04/21/2011 09:32 AM, Tomoya MORINAGA wrote:
> Hi GPIO maintainer,
> 
> Need your help.
> I want to add interrupt function to gpio/pch_gpio.c
> 
> According to other upstreamed GPIO driver, (e.g. pl061, langwell, etc...)
> 2 IRQs(irq, irq_base) are used.
> 
> I can get "irq" from (struct pci_dev *)pdev->irq.
> However I can't understand where can I get the "irq_base".
> Let me know how to get.
> 
> Thanks,
> -----------------------------------------
> Tomoya MORINAGA
> OKI SEMICONDUCTOR CO., LTD.

In my opinion the best option for expander chips is to allocate a new irq_desc
range by calling irq_alloc_descs. It will return the first irq number in the
newly allocated range, which will be your irq_base.
But be aware that this will require SPARSE_IRQ to work.

- Lars

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

* Re: Question: GPIO driver how to get irq_base
  2011-04-21  8:09 ` Lars-Peter Clausen
@ 2011-04-21 13:45   ` Grant Likely
  2011-04-21 14:08     ` Lars-Peter Clausen
  0 siblings, 1 reply; 18+ messages in thread
From: Grant Likely @ 2011-04-21 13:45 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: Tomoya MORINAGA, linux-kernel, toshiharu-linux

On Thu, Apr 21, 2011 at 10:09:14AM +0200, Lars-Peter Clausen wrote:
> On 04/21/2011 09:32 AM, Tomoya MORINAGA wrote:
> > Hi GPIO maintainer,
> > 
> > Need your help.
> > I want to add interrupt function to gpio/pch_gpio.c
> > 
> > According to other upstreamed GPIO driver, (e.g. pl061, langwell, etc...)
> > 2 IRQs(irq, irq_base) are used.

irq and irq_base are two different things.  irq is the irq number that
the gpio expander is wired up to.  irq_base is the starting range for
any irqs generated by the gpio expender.  Essentially, turning the
gpio controller into an irq controller.

> > 
> > I can get "irq" from (struct pci_dev *)pdev->irq.
> > However I can't understand where can I get the "irq_base".
> > Let me know how to get.
> > 
> > Thanks,
> > -----------------------------------------
> > Tomoya MORINAGA
> > OKI SEMICONDUCTOR CO., LTD.
> 
> In my opinion the best option for expander chips is to allocate a new irq_desc
> range by calling irq_alloc_descs. It will return the first irq number in the
> newly allocated range, which will be your irq_base.

Yes, irq_alloc_descs() will give you a range of irqs that the gpio
expander can use.  In many drivers, the irq_base is hard coded in the
board file and passed in via pdata, but as much as possible I
recommend avoiding that and letting Linux dynamically allocate the
irq_base for you.  Setting gpio_base to -1 will do this.

The ->to_irq() hook in your driver can translate
from a gpio number to an irq number for a specific gpio.

> But be aware that this will require SPARSE_IRQ to work.

Why?

g.

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

* Re: Question: GPIO driver how to get irq_base
  2011-04-21 13:45   ` Grant Likely
@ 2011-04-21 14:08     ` Lars-Peter Clausen
  2011-04-21 14:24       ` Grant Likely
  0 siblings, 1 reply; 18+ messages in thread
From: Lars-Peter Clausen @ 2011-04-21 14:08 UTC (permalink / raw)
  To: Grant Likely; +Cc: Tomoya MORINAGA, linux-kernel, toshiharu-linux

On 04/21/2011 03:45 PM, Grant Likely wrote:
> On Thu, Apr 21, 2011 at 10:09:14AM +0200, Lars-Peter Clausen wrote:
>> [...]
>>
>> In my opinion the best option for expander chips is to allocate a new irq_desc
>> range by calling irq_alloc_descs. It will return the first irq number in the
>> newly allocated range, which will be your irq_base.
> 
> Yes, irq_alloc_descs() will give you a range of irqs that the gpio
> expander can use.  In many drivers, the irq_base is hard coded in the
> board file and passed in via pdata, but as much as possible I
> recommend avoiding that and letting Linux dynamically allocate the
> irq_base for you.  Setting gpio_base to -1 will do this.
> 
> The ->to_irq() hook in your driver can translate
> from a gpio number to an irq number for a specific gpio.
> 
>> But be aware that this will require SPARSE_IRQ to work.
> 
> Why?
> 

Because in a non-SPARSE_IRQ setup all irq_descs will be allocated by default.
See early_irq_init for the non-SPARSE_IRQ case in kernel/irq/irq_desc.c.

Though platform code could make irq_descs explicitly available byfirst setting
NR_IRQS to a larger number then it actually requires and then call
irq_free_descs for those irqs which are not used by platform code, but using
SPARSE_IRQ is in my opinion the better alternative in this case.

- Lars


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

* Re: Question: GPIO driver how to get irq_base
  2011-04-21 14:08     ` Lars-Peter Clausen
@ 2011-04-21 14:24       ` Grant Likely
  2011-04-22  0:33         ` Tomoya MORINAGA
  2011-04-22  1:12         ` Tomoya MORINAGA
  0 siblings, 2 replies; 18+ messages in thread
From: Grant Likely @ 2011-04-21 14:24 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: Tomoya MORINAGA, linux-kernel, toshiharu-linux

On Thu, Apr 21, 2011 at 04:08:11PM +0200, Lars-Peter Clausen wrote:
> On 04/21/2011 03:45 PM, Grant Likely wrote:
> > On Thu, Apr 21, 2011 at 10:09:14AM +0200, Lars-Peter Clausen wrote:
> >> [...]
> >>
> >> In my opinion the best option for expander chips is to allocate a new irq_desc
> >> range by calling irq_alloc_descs. It will return the first irq number in the
> >> newly allocated range, which will be your irq_base.
> > 
> > Yes, irq_alloc_descs() will give you a range of irqs that the gpio
> > expander can use.  In many drivers, the irq_base is hard coded in the
> > board file and passed in via pdata, but as much as possible I
> > recommend avoiding that and letting Linux dynamically allocate the
> > irq_base for you.  Setting gpio_base to -1 will do this.
> > 
> > The ->to_irq() hook in your driver can translate
> > from a gpio number to an irq number for a specific gpio.
> > 
> >> But be aware that this will require SPARSE_IRQ to work.
> > 
> > Why?
> > 
> 
> Because in a non-SPARSE_IRQ setup all irq_descs will be allocated by default.
> See early_irq_init for the non-SPARSE_IRQ case in kernel/irq/irq_desc.c.

They'll be allocated, but not all need to be assigned.

> 
> Though platform code could make irq_descs explicitly available byfirst setting
> NR_IRQS to a larger number then it actually requires and then call
> irq_free_descs for those irqs which are not used by platform code, but using
> SPARSE_IRQ is in my opinion the better alternative in this case.

On the powerpc platforms, pretty much all irqs are dynamically
allocated and SPARSE_IRQ can be either on or off.  So, yes, you need
to make sure NR_IRQs is large enough if you don't want to use SPARSE,
but SPARSE is not a hard requirement.

g.


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

* RE: Question: GPIO driver how to get irq_base
  2011-04-21 14:24       ` Grant Likely
@ 2011-04-22  0:33         ` Tomoya MORINAGA
  2011-04-22  1:12         ` Tomoya MORINAGA
  1 sibling, 0 replies; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-04-22  0:33 UTC (permalink / raw)
  To: 'Grant Likely', 'Lars-Peter Clausen'
  Cc: linux-kernel, toshiharu-linux

Hi Grant, Lars-Peter Clausen

Thank you for your information.

It seems nothing driver uses irq_alloc_descs.
Thus, let me clarify my using.

int irq_base = irq_alloc_descs(-1, 0, 12, GFP_KERNEL)
(Intel-ET20T-PCH has GPIO~GPIO11)

Using the above, I can see "irq_base = 18d".
Is the above TRUE ?

Thanks,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.


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

* RE: Question: GPIO driver how to get irq_base
  2011-04-21 14:24       ` Grant Likely
  2011-04-22  0:33         ` Tomoya MORINAGA
@ 2011-04-22  1:12         ` Tomoya MORINAGA
  2011-04-23 10:14           ` Lars-Peter Clausen
  1 sibling, 1 reply; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-04-22  1:12 UTC (permalink / raw)
  To: 'Grant Likely', 'Lars-Peter Clausen'
  Cc: linux-kernel, toshiharu-linux

Hi Grant, Lars-Peter Clausen,

- Executing the following command,
  cd /sys/class/gpio/gpio244
  echo "falling" > edge

- I can see the following error message.
  IRQ handler type mismatch for IRQ 18
  current handler: spi_topcliff_pch
  Pid: 3269, comm: bash Not tainted 2.6.38.3.upstream_check+ #23
  Call Trace:
   [<c0470682>] ? __setup_irq+0x257/0x2a9
   [<c054a45f>] ? gpio_sysfs_irq+0x0/0x11
   [<c047077c>] ? request_threaded_irq+0xa8/0xce
   [<c04707fb>] ? request_any_context_irq+0x59/0x64
   [<c054a45f>] ? gpio_sysfs_irq+0x0/0x11
   [<c054a8f5>] ? gpio_setup_irq.clone.4+0x1fa/0x292
   [<c054ae2c>] ? gpio_edge_store+0xa3/0xd2
   [<c054ad89>] ? gpio_edge_store+0x0/0xd2
   [<c05bf270>] ? dev_attr_store+0x1b/0x23
   [<c04e90a5>] ? sysfs_write_file+0xae/0xe7
   [<c04e8ff7>] ? sysfs_write_file+0x0/0xe7
   [<c04a71a1>] ? vfs_write+0x82/0xd9
   [<c04a7366>] ? sys_write+0x3b/0x5d
   [<c0403018>] ? sysenter_do_call+0x12/0x28

> Using the above, I can see "irq_base = 18d".
- According to the following "/proc/interrupts" information,
  I suspect pch_gpio can't use IRQ18.

[morinaga@localhost ~]$ cat /proc/interrupts 
           CPU0       CPU1       
  0:      30881          0   IO-APIC-edge      timer
  1:          2          0   IO-APIC-edge      i8042
  4:          2          0   IO-APIC-edge    
  8:        128          0   IO-APIC-edge      rtc0
  9:          0          0   IO-APIC-fasteoi   acpi
 12:          4          0   IO-APIC-edge      i8042
 16:        385          0   IO-APIC-fasteoi   intel-eg20t-pch, ehci_hcd:usb2, ohci_hcd:usb6, ohci_hcd:usb7, ohci_hcd:usb8,
hda_intel
 17:          0          0   IO-APIC-fasteoi   eth1
 18:          0          0   IO-APIC-fasteoi   spi_topcliff_pch, i2c_eg20t, pch-dma, mmc0, mmc1
 19:       3599          0   IO-APIC-fasteoi   ehci_hcd:usb1, ohci_hcd:usb3, ohci_hcd:usb4, ohci_hcd:usb5, pch-dma,
mga@pci:0000:07:00.0
 40:      10298          0   PCI-MSI-edge      ahci
 42:         98          0   PCI-MSI-edge      eth0
NMI:          0          0   Non-maskable interrupts
LOC:      76268      72502   Local timer interrupts
SPU:          0          0   Spurious interrupts
PMI:          0          0   Performance monitoring interrupts
IWI:          0          0   IRQ work interrupts
RES:       1383       1842   Rescheduling interrupts
CAL:         67        108   Function call interrupts
TLB:        224        292   TLB shootdowns
TRM:          0          0   Thermal event interrupts
THR:          0          0   Threshold APIC interrupts
MCE:          0          0   Machine check exceptions
MCP:          1          1   Machine check polls
ERR:          0
MIS:          0

Let me know your opinion.

Thanks,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.

 

> -----Original Message-----
> From: Tomoya MORINAGA [mailto:tomoya-linux@dsn.okisemi.com] 
> Sent: Friday, April 22, 2011 9:33 AM
> To: 'Grant Likely'; 'Lars-Peter Clausen'
> Cc: 'linux-kernel@vger.kernel.org'; 'toshiharu-linux@dsn.okisemi.com'
> Subject: RE: Question: GPIO driver how to get irq_base
> 
> Hi Grant, Lars-Peter Clausen
> 
> Thank you for your information.
> 
> It seems nothing driver uses irq_alloc_descs.
> Thus, let me clarify my using.
> 
> int irq_base = irq_alloc_descs(-1, 0, 12, GFP_KERNEL) 
> (Intel-ET20T-PCH has GPIO~GPIO11)
> 
> Using the above, I can see "irq_base = 18d".
> Is the above TRUE ?
> 
> Thanks,
> -----------------------------------------
> Tomoya MORINAGA
> OKI SEMICONDUCTOR CO., LTD.
> 


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

* Re: Question: GPIO driver how to get irq_base
  2011-04-22  1:12         ` Tomoya MORINAGA
@ 2011-04-23 10:14           ` Lars-Peter Clausen
  2011-04-25  4:04             ` Tomoya MORINAGA
  0 siblings, 1 reply; 18+ messages in thread
From: Lars-Peter Clausen @ 2011-04-23 10:14 UTC (permalink / raw)
  To: Tomoya MORINAGA; +Cc: 'Grant Likely', linux-kernel, toshiharu-linux

On 04/22/2011 03:12 AM, Tomoya MORINAGA wrote:
> Hi Grant, Lars-Peter Clausen,
> 
> - Executing the following command,
>   cd /sys/class/gpio/gpio244
>   echo "falling" > edge
> 
> - I can see the following error message.
>   IRQ handler type mismatch for IRQ 18
>   current handler: spi_topcliff_pch
>   Pid: 3269, comm: bash Not tainted 2.6.38.3.upstream_check+ #23
>   Call Trace:
>    [<c0470682>] ? __setup_irq+0x257/0x2a9
>    [<c054a45f>] ? gpio_sysfs_irq+0x0/0x11
>    [<c047077c>] ? request_threaded_irq+0xa8/0xce
>    [<c04707fb>] ? request_any_context_irq+0x59/0x64
>    [<c054a45f>] ? gpio_sysfs_irq+0x0/0x11
>    [<c054a8f5>] ? gpio_setup_irq.clone.4+0x1fa/0x292
>    [<c054ae2c>] ? gpio_edge_store+0xa3/0xd2
>    [<c054ad89>] ? gpio_edge_store+0x0/0xd2
>    [<c05bf270>] ? dev_attr_store+0x1b/0x23
>    [<c04e90a5>] ? sysfs_write_file+0xae/0xe7
>    [<c04e8ff7>] ? sysfs_write_file+0x0/0xe7
>    [<c04a71a1>] ? vfs_write+0x82/0xd9
>    [<c04a7366>] ? sys_write+0x3b/0x5d
>    [<c0403018>] ? sysenter_do_call+0x12/0x28
> 
>> Using the above, I can see "irq_base = 18d".
> - According to the following "/proc/interrupts" information,
>   I suspect pch_gpio can't use IRQ18.
> 
> [morinaga@localhost ~]$ cat /proc/interrupts 
>            CPU0       CPU1       
>   0:      30881          0   IO-APIC-edge      timer
>   1:          2          0   IO-APIC-edge      i8042
>   4:          2          0   IO-APIC-edge    
>   8:        128          0   IO-APIC-edge      rtc0
>   9:          0          0   IO-APIC-fasteoi   acpi
>  12:          4          0   IO-APIC-edge      i8042
>  16:        385          0   IO-APIC-fasteoi   intel-eg20t-pch, ehci_hcd:usb2, ohci_hcd:usb6, ohci_hcd:usb7, ohci_hcd:usb8,
> hda_intel
>  17:          0          0   IO-APIC-fasteoi   eth1
>  18:          0          0   IO-APIC-fasteoi   spi_topcliff_pch, i2c_eg20t, pch-dma, mmc0, mmc1
>  19:       3599          0   IO-APIC-fasteoi   ehci_hcd:usb1, ohci_hcd:usb3, ohci_hcd:usb4, ohci_hcd:usb5, pch-dma,
> mga@pci:0000:07:00.0
>  40:      10298          0   PCI-MSI-edge      ahci
>  42:         98          0   PCI-MSI-edge      eth0
> NMI:          0          0   Non-maskable interrupts
> LOC:      76268      72502   Local timer interrupts
> SPU:          0          0   Spurious interrupts
> PMI:          0          0   Performance monitoring interrupts
> IWI:          0          0   IRQ work interrupts
> RES:       1383       1842   Rescheduling interrupts
> CAL:         67        108   Function call interrupts
> TLB:        224        292   TLB shootdowns
> TRM:          0          0   Thermal event interrupts
> THR:          0          0   Threshold APIC interrupts
> MCE:          0          0   Machine check exceptions
> MCP:          1          1   Machine check polls
> ERR:          0
> MIS:          0
> 
> Let me know your opinion.
> 
> Thanks,
> -----------------------------------------
> Tomoya MORINAGA
> OKI SEMICONDUCTOR CO., LTD.
> 

Hi

It looks as both your driver and IO-APIC have allocated the same IRQ. You could
try to add some debug code to alloc_irq_and_cfg_at to figure out what is going
wrong.

- Lars

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

* RE: Question: GPIO driver how to get irq_base
  2011-04-23 10:14           ` Lars-Peter Clausen
@ 2011-04-25  4:04             ` Tomoya MORINAGA
  2011-05-10  5:54               ` Tomoya MORINAGA
  0 siblings, 1 reply; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-04-25  4:04 UTC (permalink / raw)
  To: 'Lars-Peter Clausen'
  Cc: 'Grant Likely', linux-kernel, toshiharu-linux

Hi Lars,

On Saturday, April 23, 2011 7:15 PM, Lars-Peter Clausen wrote:
> It looks as both your driver and IO-APIC have allocated the 
> same IRQ. You could try to add some debug code to 
> alloc_irq_and_cfg_at to figure out what is going wrong.
> 
> - Lars

Adding debug code like below.

/////////////////////////////////////////////////////////////////////////////////////////////////
static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
{
	int res = irq_alloc_desc_at(at, node);
	struct irq_cfg *cfg;
printk("%s:1 at=%d node=%d res=%d\n", __func__, at, node, res);
	if (res < 0) {
printk("%s:2\n", __func__);
		if (res != -EEXIST)
			return NULL;
printk("%s:3\n", __func__);
		cfg = get_irq_chip_data(at);
printk("%s:4\n", __func__);
		if (cfg)
			return cfg;
	}

	cfg = alloc_irq_cfg(at, node);
printk("%s:5cfg=%p\n", __func__, cfg);
	if (cfg)
		set_irq_chip_data(at, cfg);
	else
		irq_free_desc(at);
printk("%s:6cfg=%p\n", __func__, cfg);
	return cfg;
}
/////////////////////////////////////////////////////////////////////////////////////////////////

The following is kernel boot log.

alloc_irq_and_cfg_at:1 at=1 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=0 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=3 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=4 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=5 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=6 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=7 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=8 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=9 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=10 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=11 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=12 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=13 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=14 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:1 at=15 node=0 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4

alloc_irq_and_cfg_at:1 at=4 node=-1 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4

alloc_irq_and_cfg_at:1 at=8 node=-1 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4

alloc_irq_and_cfg_at:1 at=13 node=-1 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4

alloc_irq_and_cfg_at:1 at=1 node=-1 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4

alloc_irq_and_cfg_at:1 at=12 node=-1 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4

alloc_irq_and_cfg_at:1 at=16 node=-1 res=16
alloc_irq_and_cfg_at:5cfg=f599c1b0
alloc_irq_and_cfg_at:6cfg=f599c1b0

alloc_irq_and_cfg_at:1 at=17 node=-1 res=17
alloc_irq_and_cfg_at:5cfg=f599c1a0
alloc_irq_and_cfg_at:6cfg=f599c1a0

alloc_irq_and_cfg_at:1 at=19 node=-1 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4
alloc_irq_and_cfg_at:5cfg=f5957dc0
alloc_irq_and_cfg_at:6cfg=f5957dc0

alloc_irq_and_cfg_at:1 at=18 node=-1 res=-17
alloc_irq_and_cfg_at:2
alloc_irq_and_cfg_at:3
alloc_irq_and_cfg_at:4


With Best Regards,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.


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

* RE: Question: GPIO driver how to get irq_base
  2011-04-25  4:04             ` Tomoya MORINAGA
@ 2011-05-10  5:54               ` Tomoya MORINAGA
  2011-05-11 19:20                 ` Lars-Peter Clausen
  0 siblings, 1 reply; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-05-10  5:54 UTC (permalink / raw)
  To: 'Lars-Peter Clausen'
  Cc: 'Grant Likely', linux-kernel, toshiharu-linux

Hi Lars,

Did you see this email ?
I'm waiting for your response.

Thanks,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.

> -----Original Message-----
> From: linux-kernel-owner@vger.kernel.org 
> [mailto:linux-kernel-owner@vger.kernel.org] On Behalf Of 
> Tomoya MORINAGA
> Sent: Monday, April 25, 2011 1:04 PM
> To: 'Lars-Peter Clausen'
> Cc: 'Grant Likely'; linux-kernel@vger.kernel.org; 
> toshiharu-linux@dsn.okisemi.com
> Subject: RE: Question: GPIO driver how to get irq_base
> 
> Hi Lars,
> 
> On Saturday, April 23, 2011 7:15 PM, Lars-Peter Clausen wrote:
> > It looks as both your driver and IO-APIC have allocated the 
> same IRQ. 
> > You could try to add some debug code to 
> alloc_irq_and_cfg_at to figure 
> > out what is going wrong.
> > 
> > - Lars
> 
> Adding debug code like below.
> 
> //////////////////////////////////////////////////////////////
> ///////////////////////////////////
> static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, 
> int node) {
> 	int res = irq_alloc_desc_at(at, node);
> 	struct irq_cfg *cfg;
> printk("%s:1 at=%d node=%d res=%d\n", __func__, at, node, res);
> 	if (res < 0) {
> printk("%s:2\n", __func__);
> 		if (res != -EEXIST)
> 			return NULL;
> printk("%s:3\n", __func__);
> 		cfg = get_irq_chip_data(at);
> printk("%s:4\n", __func__);
> 		if (cfg)
> 			return cfg;
> 	}
> 
> 	cfg = alloc_irq_cfg(at, node);
> printk("%s:5cfg=%p\n", __func__, cfg);
> 	if (cfg)
> 		set_irq_chip_data(at, cfg);
> 	else
> 		irq_free_desc(at);
> printk("%s:6cfg=%p\n", __func__, cfg);
> 	return cfg;
> }
> //////////////////////////////////////////////////////////////
> ///////////////////////////////////
> 
> The following is kernel boot log.
> 
> alloc_irq_and_cfg_at:1 at=1 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=0 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=3 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=4 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=5 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=6 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=7 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=8 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=9 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=10 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=11 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=12 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=13 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=14 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:1 at=15 node=0 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> 
> alloc_irq_and_cfg_at:1 at=4 node=-1 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> 
> alloc_irq_and_cfg_at:1 at=8 node=-1 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> 
> alloc_irq_and_cfg_at:1 at=13 node=-1 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> 
> alloc_irq_and_cfg_at:1 at=1 node=-1 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> 
> alloc_irq_and_cfg_at:1 at=12 node=-1 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> 
> alloc_irq_and_cfg_at:1 at=16 node=-1 res=16 
> alloc_irq_and_cfg_at:5cfg=f599c1b0
> alloc_irq_and_cfg_at:6cfg=f599c1b0
> 
> alloc_irq_and_cfg_at:1 at=17 node=-1 res=17 
> alloc_irq_and_cfg_at:5cfg=f599c1a0
> alloc_irq_and_cfg_at:6cfg=f599c1a0
> 
> alloc_irq_and_cfg_at:1 at=19 node=-1 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> alloc_irq_and_cfg_at:5cfg=f5957dc0
> alloc_irq_and_cfg_at:6cfg=f5957dc0
> 
> alloc_irq_and_cfg_at:1 at=18 node=-1 res=-17
> alloc_irq_and_cfg_at:2
> alloc_irq_and_cfg_at:3
> alloc_irq_and_cfg_at:4
> 
> 
> With Best Regards,
> -----------------------------------------
> Tomoya MORINAGA
> OKI SEMICONDUCTOR CO., LTD.
> 
> --
> To unsubscribe from this list: send the line "unsubscribe 
> linux-kernel" in the body of a message to 
> majordomo@vger.kernel.org More majordomo info at  
> http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 


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

* Re: Question: GPIO driver how to get irq_base
  2011-05-10  5:54               ` Tomoya MORINAGA
@ 2011-05-11 19:20                 ` Lars-Peter Clausen
  2011-05-12 12:01                   ` Tomoya MORINAGA
  0 siblings, 1 reply; 18+ messages in thread
From: Lars-Peter Clausen @ 2011-05-11 19:20 UTC (permalink / raw)
  To: Tomoya MORINAGA; +Cc: 'Grant Likely', linux-kernel, toshiharu-linux

On 05/09/2011 10:54 PM, Tomoya MORINAGA wrote:
> Hi Lars,
> 
> Did you see this email ?
> I'm waiting for your response.
> 

Hi

Well, it looks as if io-apic assumes that IRQ18 is reserved for itself, while
it actually is requested by your driver. But that's all I can say. I'm not
familiar with the x86 irq code, so I've no idea what the proper fix would be.

- Lars


> Thanks,
> -----------------------------------------
> Tomoya MORINAGA
> OKI SEMICONDUCTOR CO., LTD.
> 
>> -----Original Message-----
>> From: linux-kernel-owner@vger.kernel.org 
>> [mailto:linux-kernel-owner@vger.kernel.org] On Behalf Of 
>> Tomoya MORINAGA
>> Sent: Monday, April 25, 2011 1:04 PM
>> To: 'Lars-Peter Clausen'
>> Cc: 'Grant Likely'; linux-kernel@vger.kernel.org; 
>> toshiharu-linux@dsn.okisemi.com
>> Subject: RE: Question: GPIO driver how to get irq_base
>>
>> Hi Lars,
>>
>> On Saturday, April 23, 2011 7:15 PM, Lars-Peter Clausen wrote:
>>> It looks as both your driver and IO-APIC have allocated the 
>> same IRQ. 
>>> You could try to add some debug code to 
>> alloc_irq_and_cfg_at to figure 
>>> out what is going wrong.
>>>
>>> - Lars
>>
>> Adding debug code like below.
>>
>> //////////////////////////////////////////////////////////////
>> ///////////////////////////////////
>> static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, 
>> int node) {
>> 	int res = irq_alloc_desc_at(at, node);
>> 	struct irq_cfg *cfg;
>> printk("%s:1 at=%d node=%d res=%d\n", __func__, at, node, res);
>> 	if (res < 0) {
>> printk("%s:2\n", __func__);
>> 		if (res != -EEXIST)
>> 			return NULL;
>> printk("%s:3\n", __func__);
>> 		cfg = get_irq_chip_data(at);
>> printk("%s:4\n", __func__);
>> 		if (cfg)
>> 			return cfg;
>> 	}
>>
>> 	cfg = alloc_irq_cfg(at, node);
>> printk("%s:5cfg=%p\n", __func__, cfg);
>> 	if (cfg)
>> 		set_irq_chip_data(at, cfg);
>> 	else
>> 		irq_free_desc(at);
>> printk("%s:6cfg=%p\n", __func__, cfg);
>> 	return cfg;
>> }
>> //////////////////////////////////////////////////////////////
>> ///////////////////////////////////
>>
>> The following is kernel boot log.
>>
>> alloc_irq_and_cfg_at:1 at=1 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=0 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=3 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=4 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=5 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=6 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=7 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=8 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=9 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=10 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=11 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=12 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=13 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=14 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:1 at=15 node=0 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>>
>> alloc_irq_and_cfg_at:1 at=4 node=-1 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>>
>> alloc_irq_and_cfg_at:1 at=8 node=-1 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>>
>> alloc_irq_and_cfg_at:1 at=13 node=-1 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>>
>> alloc_irq_and_cfg_at:1 at=1 node=-1 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>>
>> alloc_irq_and_cfg_at:1 at=12 node=-1 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>>
>> alloc_irq_and_cfg_at:1 at=16 node=-1 res=16 
>> alloc_irq_and_cfg_at:5cfg=f599c1b0
>> alloc_irq_and_cfg_at:6cfg=f599c1b0
>>
>> alloc_irq_and_cfg_at:1 at=17 node=-1 res=17 
>> alloc_irq_and_cfg_at:5cfg=f599c1a0
>> alloc_irq_and_cfg_at:6cfg=f599c1a0
>>
>> alloc_irq_and_cfg_at:1 at=19 node=-1 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>> alloc_irq_and_cfg_at:5cfg=f5957dc0
>> alloc_irq_and_cfg_at:6cfg=f5957dc0
>>
>> alloc_irq_and_cfg_at:1 at=18 node=-1 res=-17
>> alloc_irq_and_cfg_at:2
>> alloc_irq_and_cfg_at:3
>> alloc_irq_and_cfg_at:4
>>
>>
>> With Best Regards,
>> -----------------------------------------
>> Tomoya MORINAGA
>> OKI SEMICONDUCTOR CO., LTD.
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe 
>> linux-kernel" in the body of a message to 
>> majordomo@vger.kernel.org More majordomo info at  
>> http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>>
> 


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

* RE: Question: GPIO driver how to get irq_base
  2011-05-11 19:20                 ` Lars-Peter Clausen
@ 2011-05-12 12:01                   ` Tomoya MORINAGA
  2011-05-12 19:43                     ` Lars-Peter Clausen
  0 siblings, 1 reply; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-05-12 12:01 UTC (permalink / raw)
  To: 'Lars-Peter Clausen', 'Grant Likely'
  Cc: linux-kernel, toshiharu-linux

 Hi Lars, Grant

According to "/proc/interrupts", IRQ18 is not empty.
However, irq_alloc_descs returns "18".
I suspect irq_alloc_descs returns should not return "18".

> Grant,
Let me know your opinion.

With Best Regards,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.

> -----Original Message-----
> From: Lars-Peter Clausen [mailto:lars@metafoo.de] 
> Sent: Thursday, May 12, 2011 4:20 AM
> To: Tomoya MORINAGA
> Cc: 'Grant Likely'; linux-kernel@vger.kernel.org; 
> toshiharu-linux@dsn.okisemi.com
> Subject: Re: Question: GPIO driver how to get irq_base
> 
> On 05/09/2011 10:54 PM, Tomoya MORINAGA wrote:
> > Hi Lars,
> > 
> > Did you see this email ?
> > I'm waiting for your response.
> > 
> 
> Hi
> 
> Well, it looks as if io-apic assumes that IRQ18 is reserved 
> for itself, while it actually is requested by your driver. 
> But that's all I can say. I'm not familiar with the x86 irq 
> code, so I've no idea what the proper fix would be.
> 
> - Lars
> 


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

* Re: Question: GPIO driver how to get irq_base
  2011-05-12 12:01                   ` Tomoya MORINAGA
@ 2011-05-12 19:43                     ` Lars-Peter Clausen
  2011-05-13  2:40                       ` Tomoya MORINAGA
  0 siblings, 1 reply; 18+ messages in thread
From: Lars-Peter Clausen @ 2011-05-12 19:43 UTC (permalink / raw)
  To: Tomoya MORINAGA; +Cc: 'Grant Likely', linux-kernel, toshiharu-linux

On 05/12/2011 05:01 AM, Tomoya MORINAGA wrote:
>  Hi Lars, Grant
> 
> According to "/proc/interrupts", IRQ18 is not empty.
> However, irq_alloc_descs returns "18".
> I suspect irq_alloc_descs returns should not return "18".
> 
>> Grant,
> Let me know your opinion.
> 
> With Best Regards,

Is it already used at the time when you call irq_alloc_descs?

- Lars

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

* RE: Question: GPIO driver how to get irq_base
  2011-05-12 19:43                     ` Lars-Peter Clausen
@ 2011-05-13  2:40                       ` Tomoya MORINAGA
  2011-05-13  3:18                         ` Lars-Peter Clausen
  0 siblings, 1 reply; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-05-13  2:40 UTC (permalink / raw)
  To: 'Lars-Peter Clausen'
  Cc: 'Grant Likely', linux-kernel, toshiharu-linux

Hi  Lars,

On Friday, May 13, 2011 4:43 AM, Lars-Peter Clausen wrote:
> Is it already used at the time when you call irq_alloc_descs?

Since gpio driver with interrupt function must be integrated as built-in,
I don't know whether "18" is already used or NOT at that time.
If you have any information, let me know.

Thanks,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.


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

* Re: Question: GPIO driver how to get irq_base
  2011-05-13  2:40                       ` Tomoya MORINAGA
@ 2011-05-13  3:18                         ` Lars-Peter Clausen
  2011-05-13  5:42                           ` Tomoya MORINAGA
  2011-05-16 10:38                           ` Tomoya MORINAGA
  0 siblings, 2 replies; 18+ messages in thread
From: Lars-Peter Clausen @ 2011-05-13  3:18 UTC (permalink / raw)
  To: Tomoya MORINAGA; +Cc: 'Grant Likely', linux-kernel, toshiharu-linux

On 05/12/2011 07:40 PM, Tomoya MORINAGA wrote:
> Hi  Lars,
> 
> On Friday, May 13, 2011 4:43 AM, Lars-Peter Clausen wrote:
>> Is it already used at the time when you call irq_alloc_descs?
> 
> Since gpio driver with interrupt function must be integrated as built-in,
> I don't know whether "18" is already used or NOT at that time.
> If you have any information, let me know.
> 

Well, you should be able to figure that out with some debug printks, shouldn't you?

- Lars

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

* RE: Question: GPIO driver how to get irq_base
  2011-05-13  3:18                         ` Lars-Peter Clausen
@ 2011-05-13  5:42                           ` Tomoya MORINAGA
  2011-05-16 10:38                           ` Tomoya MORINAGA
  1 sibling, 0 replies; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-05-13  5:42 UTC (permalink / raw)
  To: 'Lars-Peter Clausen'
  Cc: 'Grant Likely', linux-kernel, toshiharu-linux

Friday, May 13, 2011 12:19 PM,  Lars-Peter Clausen wrote:
> Well, you should be able to figure that out with some debug 
> printks, shouldn't you?
I can confirm "18" is not assigned at that time.
After loading gpio driver, other modules are assigned to "IRQ18".
(IRQ numbers shared system)

Thanks,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.


> -----Original Message-----
> From: Lars-Peter Clausen [mailto:lars@metafoo.de] 
> Sent: Friday, May 13, 2011 12:19 PM
> To: Tomoya MORINAGA
> Cc: 'Grant Likely'; linux-kernel@vger.kernel.org; 
> toshiharu-linux@dsn.okisemi.com
> Subject: Re: Question: GPIO driver how to get irq_base
> 
> On 05/12/2011 07:40 PM, Tomoya MORINAGA wrote:
> > Hi  Lars,
> > 
> > On Friday, May 13, 2011 4:43 AM, Lars-Peter Clausen wrote:
> >> Is it already used at the time when you call irq_alloc_descs?
> > 
> > Since gpio driver with interrupt function must be integrated as 
> > built-in, I don't know whether "18" is already used or NOT 
> at that time.
> > If you have any information, let me know.
> > 
> 
> Well, you should be able to figure that out with some debug 
> printks, shouldn't you?
> 
> - Lars
> 


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

* RE: Question: GPIO driver how to get irq_base
  2011-05-13  3:18                         ` Lars-Peter Clausen
  2011-05-13  5:42                           ` Tomoya MORINAGA
@ 2011-05-16 10:38                           ` Tomoya MORINAGA
  2011-05-17  2:06                             ` Tomoya MORINAGA
  1 sibling, 1 reply; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-05-16 10:38 UTC (permalink / raw)
  To: 'Lars-Peter Clausen', 'Grant Likely'
  Cc: linux-kernel, toshiharu-linux

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

Hi,

Pch_gpio driver can become detecting falling/rising edge.
I attached the latest GPIO driver, usermode TP and the result.

However, "poll( )" of gpio_tp behavior is different than I anticipated. 
The "poll" is not blocked. (The returned value looks good)

My anticipated behavior is 
  Execute gpio_tp (blocked at poll( ))
  (Detect edge)
  Interrupt handler of pch_gpio is called
  Blocked poll( ) becomes released.

Let me know your opinion.

With Best Regards,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.

[-- Attachment #2: gpio_tp.c --]
[-- Type: text/plain, Size: 1186 bytes --]

#include <stdio.h>
#include <unistd.h>
#include <poll.h>
#include <fcntl.h>
#define GPIO_DIR "/sys/class/gpio"
#define GPIO_NAME "gpio246"
#define GPIO_PATH GPIO_DIR "/" GPIO_NAME "/"
int main(void)
{
	int fd;
	int i;
	int ret;
	fd = open(GPIO_PATH "direction", O_RDWR);
	printf("fd=%d\n", fd);
	ret = write(fd, "in", 2);
	printf("write=%d\n", ret);
	close(fd);
	fd = open(GPIO_PATH "edge", O_RDWR);
	printf("fd=%d\n", fd);
//	ret=write(fd, "rising", 6);
	ret=write(fd, "falling", 7);
	printf("write=%d\n", ret);
	close(fd);
	for (i=0; i < 3; i++) {
		char val;
		struct pollfd pfd;
		fd = open(GPIO_PATH "value", O_RDWR);
		printf("fd=%d\n", fd);

		ret=read(fd, &val, 1);
		printf("read=%d val=%c\n", ret, val);
		printf("waiting for interrupt..."); fflush(stdout);
		pfd.fd = fd;
		pfd.events = POLLIN;
		pfd.revents = 0;
		ret = poll(&pfd, 1, -1);
		printf("poll=%d revent=0x%x\n", ret, pfd.revents);
		ret=lseek(fd, 0, SEEK_SET);
		printf("lseek=%d\n", ret);
		ret = read(fd, &val, 1);
		printf("read=%d val=%c\n", ret, val);
		close(fd);
		printf("OK (%c, %s)\n", val, val == '0' ? "Low" : "High");
		usleep(100000);
	}
	return 0;
}

[-- Attachment #3: pch_gpio.c --]
[-- Type: text/plain, Size: 11490 bytes --]

/*
 * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
 *
 * 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; version 2 of the License.
 *
 * 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 <linux/kernel.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>

#define PCH_GPIO_ALL_PINS	0xfff /* Mask for GPIO pins 0 to 11 */
#define GPIO_NUM_PINS	12	/* Specifies number of GPIO PINS GPIO0-GPIO11 */

#define PCH_EDGE_FALLING	0
#define PCH_EDGE_RISING		BIT(0)
#define PCH_LEVEL_L		BIT(1)
#define PCH_LEVEL_H		(BIT(0) | BIT(1))
#define PCH_EDGE_BOTH		BIT(2)
#define PCH_IM_MASK		(BIT(0) | BIT(1) | BIT(2))

#define PCH_IRQ_BASE		20

struct pch_regs {
	u32	ien;
	u32	istatus;
	u32	idisp;
	u32	iclr;
	u32	imask;
	u32	imaskclr;
	u32	po;
	u32	pi;
	u32	pm;
	u32	im0;
	u32	im1;
	u32	reserved[4];
	u32	reset;
};

/**
 * struct pch_gpio_reg_data - The register store data.
 * @po_reg:	To store contents of PO register.
 * @pm_reg:	To store contents of PM register.
 */
struct pch_gpio_reg_data {
	u32 po_reg;
	u32 pm_reg;
};

/**
 * struct pch_gpio - GPIO private data structure.
 * @base:			PCI base address of Memory mapped I/O register.
 * @reg:			Memory mapped PCH GPIO register list.
 * @dev:			Pointer to device structure.
 * @gpio:			Data for GPIO infrastructure.
 * @pch_gpio_reg:		Memory mapped Register data is saved here
 *				when suspend.
 * @lock:			spin_lock variable
 */
struct pch_gpio {
	void __iomem *base;
	struct pch_regs __iomem *reg;
	struct device *dev;
	struct gpio_chip gpio;
	struct pch_gpio_reg_data pch_gpio_reg;
	struct mutex lock;
	int irq_base;
	spinlock_t spinlock;
};

static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
{
	u32 reg_val;
	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);

	mutex_lock(&chip->lock);
	reg_val = ioread32(&chip->reg->po);
	if (val)
		reg_val |= (1 << nr);
	else
		reg_val &= ~(1 << nr);

	iowrite32(reg_val, &chip->reg->po);
	mutex_unlock(&chip->lock);
}

static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
{
	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);

	return ioread32(&chip->reg->pi) & (1 << nr);
}

static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
				     int val)
{
	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
	u32 pm;
	u32 reg_val;

	mutex_lock(&chip->lock);
	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
	pm |= (1 << nr);
	iowrite32(pm, &chip->reg->pm);

	reg_val = ioread32(&chip->reg->po);
	if (val)
		reg_val |= (1 << nr);
	else
		reg_val &= ~(1 << nr);
	iowrite32(reg_val, &chip->reg->po);

	mutex_unlock(&chip->lock);

	return 0;
}

static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
{
	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
	u32 pm;

	mutex_lock(&chip->lock);
	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
	pm &= ~(1 << nr);
	iowrite32(pm, &chip->reg->pm);
	mutex_unlock(&chip->lock);

	return 0;
}

/*
 * Save register configuration and disable interrupts.
 */
static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
{
	chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
	chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
}

/*
 * This function restores the register configuration of the GPIO device.
 */
static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
{
	/* to store contents of PO register */
	iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
	/* to store contents of PM register */
	iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
}

static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
{
	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
	return chip->irq_base + offset;
}

static void pch_gpio_setup(struct pch_gpio *chip)
{
	struct gpio_chip *gpio = &chip->gpio;

	gpio->label = dev_name(chip->dev);
	gpio->owner = THIS_MODULE;
	gpio->direction_input = pch_gpio_direction_input;
	gpio->get = pch_gpio_get;
	gpio->direction_output = pch_gpio_direction_output;
	gpio->set = pch_gpio_set;
	gpio->dbg_show = NULL;
	gpio->base = -1;
	gpio->ngpio = GPIO_NUM_PINS;
	gpio->can_sleep = 0;
	gpio->to_irq = pch_gpio_to_irq;
}

static int pch_irq_type(unsigned irq, unsigned type)
{
	u32 im;
	u32 *im_reg;
	u32 ien;
	u32 im_pos;
	int ch;
	unsigned long flags;
	u32 val;
	struct pch_gpio *chip = get_irq_chip_data(irq);

	ch = irq - chip->irq_base;
	if (irq <= chip->irq_base + 7) {
		im_reg = &chip->reg->im0;
		im_pos = ch;
	} else {
		im_reg = &chip->reg->im1;
		im_pos = ch - 8;
	}
	dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n",
		__func__, irq, type, ch, im_pos);

	spin_lock_irqsave(&chip->spinlock, flags);

	if (type == IRQ_TYPE_EDGE_RISING)
		val = PCH_EDGE_RISING;
	else if (type == IRQ_TYPE_EDGE_FALLING)
		val = PCH_EDGE_FALLING;
	else if (type == IRQ_TYPE_EDGE_BOTH)
		val = PCH_EDGE_BOTH;
	else if (type == IRQ_TYPE_LEVEL_HIGH)
		val = PCH_LEVEL_L;
	else if (type == IRQ_TYPE_LEVEL_LOW)
		val = PCH_LEVEL_H;
	else if (type == IRQ_TYPE_PROBE)
		goto end;
	else {
		dev_warn(chip->dev, "%s: unknown type(%dd)", __func__, type);
		goto end;
	}

	/* Set interrupt mode */
	im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
	iowrite32(im | (val << (im_pos * 4)), im_reg);

	/* iclr */
	iowrite32(BIT(ch), &chip->reg->iclr);

	/* IMASKCLR */
	iowrite32(BIT(ch), &chip->reg->imaskclr);

	/* Enable interrupt */
	ien = ioread32(&chip->reg->ien);
	iowrite32(ien | BIT(ch), &chip->reg->ien);
end:
	spin_unlock_irqrestore(&chip->spinlock, flags);

	return 0;
}

static void pch_irq_unmask(unsigned irq)
{
}

static void pch_irq_mask(unsigned irq)
{
}

static struct irq_chip pch_irqchip = {
	.name		= "PCH-GPIO",
	.mask		= pch_irq_mask,
	.unmask		= pch_irq_unmask,
	.set_type	= pch_irq_type,
};

static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
{
	struct pch_gpio *chip = dev_id;
	u32 reg_val = ioread32(&chip->reg->istatus);
	int i;
	int ret = IRQ_NONE;

	for (i = 0; i < GPIO_NUM_PINS; i++) {
		if (reg_val & BIT(i)) {
			dev_dbg(chip->dev, "%s:[%d]:irq=%d  status=0x%x\n",
				__func__, i, irq, reg_val);
			iowrite32(BIT(i), &chip->reg->iclr);
			generic_handle_irq(chip->irq_base + i);
			ret = IRQ_HANDLED;
		}
	}
	return ret;
}

static int __devinit pch_gpio_probe(struct pci_dev *pdev,
				    const struct pci_device_id *id)
{
	s32 ret;
	struct pch_gpio *chip;
	int irq_base;
	int i;

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (chip == NULL)
		return -ENOMEM;

	chip->dev = &pdev->dev;
	ret = pci_enable_device(pdev);
	if (ret) {
		dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
		goto err_pci_enable;
	}

	ret = pci_request_regions(pdev, KBUILD_MODNAME);
	if (ret) {
		dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
		goto err_request_regions;
	}

	chip->base = pci_iomap(pdev, 1, 0);
	if (chip->base == 0) {
		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
		ret = -ENOMEM;
		goto err_iomap;
	}

	chip->reg = chip->base;
	pci_set_drvdata(pdev, chip);
	mutex_init(&chip->lock);
	pch_gpio_setup(chip);
	ret = gpiochip_add(&chip->gpio);
	if (ret) {
		dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
		goto err_gpiochip_add;
	}

	irq_base = irq_alloc_descs(-1, PCH_IRQ_BASE, GPIO_NUM_PINS, GFP_KERNEL);
	if (irq_base < 0) {
		dev_err(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
		goto err_irq_alloc_descs;
	}

	chip->irq_base = irq_base;

	ret = request_irq(pdev->irq, pch_gpio_handler,
			     IRQF_SHARED, KBUILD_MODNAME, chip);
	if (ret != 0) {
		dev_err(&pdev->dev,
			"%s request_irq failed\n", __func__);
		goto err_request_irq;
	}

	for (i = 0; i < GPIO_NUM_PINS; i++) {
		set_irq_chip_and_handler_name(i + irq_base, &pch_irqchip,
					handle_simple_irq, "pch");
		set_irq_chip_data(i + irq_base, chip);
	}

	/* Initialize interrupt ien register */
	iowrite32(0, &chip->reg->ien);

	return 0;

err_request_irq:
	irq_free_descs(irq_base, GPIO_NUM_PINS);

err_irq_alloc_descs:
	ret = gpiochip_remove(&chip->gpio);
	if (ret)
		dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);

err_gpiochip_add:
	pci_iounmap(pdev, chip->base);

err_iomap:
	pci_release_regions(pdev);

err_request_regions:
	pci_disable_device(pdev);

err_pci_enable:
	kfree(chip);
	dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
	return ret;
}

static void __devexit pch_gpio_remove(struct pci_dev *pdev)
{
	int err;
	struct pch_gpio *chip = pci_get_drvdata(pdev);

	err = gpiochip_remove(&chip->gpio);
	if (err)
		dev_err(&pdev->dev, "Failed gpiochip_remove\n");

	pci_iounmap(pdev, chip->base);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	kfree(chip);
}

#ifdef CONFIG_PM
static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
{
	s32 ret;
	struct pch_gpio *chip = pci_get_drvdata(pdev);

	pch_gpio_save_reg_conf(chip);
	pch_gpio_restore_reg_conf(chip);

	ret = pci_save_state(pdev);
	if (ret) {
		dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
		return ret;
	}
	pci_disable_device(pdev);
	pci_set_power_state(pdev, PCI_D0);
	ret = pci_enable_wake(pdev, PCI_D0, 1);
	if (ret)
		dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);

	return 0;
}

static int pch_gpio_resume(struct pci_dev *pdev)
{
	s32 ret;
	struct pch_gpio *chip = pci_get_drvdata(pdev);

	ret = pci_enable_wake(pdev, PCI_D0, 0);

	pci_set_power_state(pdev, PCI_D0);
	ret = pci_enable_device(pdev);
	if (ret) {
		dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
		return ret;
	}
	pci_restore_state(pdev);

	iowrite32(0x01, &chip->reg->reset);
	iowrite32(0x00, &chip->reg->reset);
	pch_gpio_restore_reg_conf(chip);

	return 0;
}
#else
#define pch_gpio_suspend NULL
#define pch_gpio_resume NULL
#endif

#define PCI_VENDOR_ID_ROHM             0x10DB
static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
	{ 0, }
};
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);

static struct pci_driver pch_gpio_driver = {
	.name = "pch_gpio",
	.id_table = pch_gpio_pcidev_id,
	.probe = pch_gpio_probe,
	.remove = __devexit_p(pch_gpio_remove),
	.suspend = pch_gpio_suspend,
	.resume = pch_gpio_resume
};

static int __init pch_gpio_pci_init(void)
{
	return pci_register_driver(&pch_gpio_driver);
}
module_init(pch_gpio_pci_init);

static void __exit pch_gpio_pci_exit(void)
{
	pci_unregister_driver(&pch_gpio_driver);
}
module_exit(pch_gpio_pci_exit);

MODULE_DESCRIPTION("PCH GPIO PCI Driver");
MODULE_LICENSE("GPL");

[-- Attachment #4: TP_result.txt --]
[-- Type: text/plain, Size: 373 bytes --]

[root@localhost morinaga]# ./a.out 
fd=3
write=2
fd=3
write=7
fd=3
read=1 val=1
waiting for interrupt...poll=1 revent=0x1
lseek=0
read=1 val=1
OK (1, High)
fd=3
read=1 val=1
waiting for interrupt...poll=1 revent=0x1
lseek=0
read=1 val=1
OK (1, High)
fd=3
read=1 val=1
waiting for interrupt...poll=1 revent=0x1
lseek=0
read=1 val=1
OK (1, High)
[root@localhost morinaga]# 


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

* RE: Question: GPIO driver how to get irq_base
  2011-05-16 10:38                           ` Tomoya MORINAGA
@ 2011-05-17  2:06                             ` Tomoya MORINAGA
  0 siblings, 0 replies; 18+ messages in thread
From: Tomoya MORINAGA @ 2011-05-17  2:06 UTC (permalink / raw)
  To: 'Lars-Peter Clausen', 'Grant Likely'
  Cc: linux-kernel, toshiharu-linux

Hi,

Modifying parameter of poll ( ) like below, poll ( ) becomes blocked correctly.
    pfd.events = POLLPRI | POLLERR
And I can confirm when GPIO driver detects edge changing,
the blocked poll  ( ) is released correctly. 

Thanks,
-----------------------------------------
Tomoya MORINAGA
OKI SEMICONDUCTOR CO., LTD.

> -----Original Message-----
> From: linux-kernel-owner@vger.kernel.org 
> [mailto:linux-kernel-owner@vger.kernel.org] On Behalf Of 
> Tomoya MORINAGA
> Sent: Monday, May 16, 2011 7:39 PM
> To: 'Lars-Peter Clausen'; 'Grant Likely'
> Cc: linux-kernel@vger.kernel.org; toshiharu-linux@dsn.okisemi.com
> Subject: RE: Question: GPIO driver how to get irq_base
> 
> Hi,
> 
> Pch_gpio driver can become detecting falling/rising edge.
> I attached the latest GPIO driver, usermode TP and the result.
> 
> However, "poll( )" of gpio_tp behavior is different than I 
> anticipated. 
> The "poll" is not blocked. (The returned value looks good)
> 
> My anticipated behavior is
>   Execute gpio_tp (blocked at poll( ))
>   (Detect edge)
>   Interrupt handler of pch_gpio is called
>   Blocked poll( ) becomes released.
> 
> Let me know your opinion.
> 
> With Best Regards,
> -----------------------------------------
> Tomoya MORINAGA
> OKI SEMICONDUCTOR CO., LTD.
> 


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

end of thread, other threads:[~2011-05-17  2:06 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-21  7:32 Question: GPIO driver how to get irq_base Tomoya MORINAGA
2011-04-21  8:09 ` Lars-Peter Clausen
2011-04-21 13:45   ` Grant Likely
2011-04-21 14:08     ` Lars-Peter Clausen
2011-04-21 14:24       ` Grant Likely
2011-04-22  0:33         ` Tomoya MORINAGA
2011-04-22  1:12         ` Tomoya MORINAGA
2011-04-23 10:14           ` Lars-Peter Clausen
2011-04-25  4:04             ` Tomoya MORINAGA
2011-05-10  5:54               ` Tomoya MORINAGA
2011-05-11 19:20                 ` Lars-Peter Clausen
2011-05-12 12:01                   ` Tomoya MORINAGA
2011-05-12 19:43                     ` Lars-Peter Clausen
2011-05-13  2:40                       ` Tomoya MORINAGA
2011-05-13  3:18                         ` Lars-Peter Clausen
2011-05-13  5:42                           ` Tomoya MORINAGA
2011-05-16 10:38                           ` Tomoya MORINAGA
2011-05-17  2:06                             ` Tomoya MORINAGA

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox