All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai] ipipe bug in gpio/irq for mx6
@ 2016-03-18 10:43 Johann Obermayr
  2016-03-18 11:10 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 6+ messages in thread
From: Johann Obermayr @ 2016-03-18 10:43 UTC (permalink / raw)
  To: xenomai

Hello,

in the the git branch ipipe-3.0-imx6q
in the file arch/arm/plat-mxc/gpio.c

there is follow function.

void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
{
     struct irq_desc *desc = irq_to_desc(irq);
     struct irq_data *idata = irq_desc_get_irq_data(desc);
     struct irq_chip *chip = irq_data_get_irq_chip(idata);

     if (chip == &gpio_irq_chip) {
         /* It is a gpio. */
         u32 gpio = irq_to_gpio(irq);
         struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];

         if (ipd != &ipipe_root) {
             port->nonroot_gpios |= (1 << (gpio % 32));
             if (port->nonroot_gpios == (1 << (gpio % 32))) {
                 __ipipe_irqbits[(port->irq / 32)]
                     &= ~(1 << (port->irq % 32));
                 set_irq_prio(port->irq, 1);
             }
         }
     } else
         set_irq_prio(irq, ipd != &ipipe_root);
}

But there is missing  set_irq_prio for the port->irq_high.
to add
                 if (port->irq_high > 0)
                     set_irq_prio(port->irq_high, 1);
is not my problem.

my problem is, that i don't known if  __ipipe_irqbits is handled correct.

regards
   Johann




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

* Re: [Xenomai] ipipe bug in gpio/irq for mx6
  2016-03-18 10:43 [Xenomai] ipipe bug in gpio/irq for mx6 Johann Obermayr
@ 2016-03-18 11:10 ` Gilles Chanteperdrix
  2016-03-18 12:15   ` Johann Obermayr
  0 siblings, 1 reply; 6+ messages in thread
From: Gilles Chanteperdrix @ 2016-03-18 11:10 UTC (permalink / raw)
  To: Johann Obermayr; +Cc: xenomai

On Fri, Mar 18, 2016 at 11:43:26AM +0100, Johann Obermayr wrote:
> Hello,
> 
> in the the git branch ipipe-3.0-imx6q

This I-pipe patch is really old now. Any chance to use a current
version of Xenomai?

> in the file arch/arm/plat-mxc/gpio.c
> 
> there is follow function.
> 
> void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
> {
>      struct irq_desc *desc = irq_to_desc(irq);
>      struct irq_data *idata = irq_desc_get_irq_data(desc);
>      struct irq_chip *chip = irq_data_get_irq_chip(idata);
> 
>      if (chip == &gpio_irq_chip) {
>          /* It is a gpio. */
>          u32 gpio = irq_to_gpio(irq);
>          struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
> 
>          if (ipd != &ipipe_root) {
>              port->nonroot_gpios |= (1 << (gpio % 32));
>              if (port->nonroot_gpios == (1 << (gpio % 32))) {
>                  __ipipe_irqbits[(port->irq / 32)]
>                      &= ~(1 << (port->irq % 32));
>                  set_irq_prio(port->irq, 1);
>              }
>          }
>      } else
>          set_irq_prio(irq, ipd != &ipipe_root);
> }
> 
> But there is missing  set_irq_prio for the port->irq_high.
> to add
>                  if (port->irq_high > 0)
>                      set_irq_prio(port->irq_high, 1);
> is not my problem.
> 
> my problem is, that i don't known if  __ipipe_irqbits is handled
> correct.

Well, if you want to set port->irq_high, you have to clear the
corresponding bit in __ipipe_irqbits, as is done for port->irq.

-- 
					    Gilles.
https://click-hack.org


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

* Re: [Xenomai] ipipe bug in gpio/irq for mx6
  2016-03-18 11:10 ` Gilles Chanteperdrix
@ 2016-03-18 12:15   ` Johann Obermayr
  2016-03-18 12:28     ` Gilles Chanteperdrix
  0 siblings, 1 reply; 6+ messages in thread
From: Johann Obermayr @ 2016-03-18 12:15 UTC (permalink / raw)
  To: xenomai

Am 18.03.2016 um 12:10 schrieb Gilles Chanteperdrix:
> On Fri, Mar 18, 2016 at 11:43:26AM +0100, Johann Obermayr wrote:
>> Hello,
>>
>> in the the git branch ipipe-3.0-imx6q
> This I-pipe patch is really old now. Any chance to use a current
> version of Xenomai?
Not now. but we have started to change to 3.10.x with newer xenomai
>> in the file arch/arm/plat-mxc/gpio.c
>>
>> there is follow function.
>>
>> void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
>> {
>>       struct irq_desc *desc = irq_to_desc(irq);
>>       struct irq_data *idata = irq_desc_get_irq_data(desc);
>>       struct irq_chip *chip = irq_data_get_irq_chip(idata);
>>
>>       if (chip == &gpio_irq_chip) {
>>           /* It is a gpio. */
>>           u32 gpio = irq_to_gpio(irq);
>>           struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
>>
>>           if (ipd != &ipipe_root) {
>>               port->nonroot_gpios |= (1 << (gpio % 32));
>>               if (port->nonroot_gpios == (1 << (gpio % 32))) {
>>                   __ipipe_irqbits[(port->irq / 32)]
>>                       &= ~(1 << (port->irq % 32));
>>                   set_irq_prio(port->irq, 1);
>>               }
>>           }
>>       } else
>>           set_irq_prio(irq, ipd != &ipipe_root);
>> }
>>
>> But there is missing  set_irq_prio for the port->irq_high.
>> to add
>>                   if (port->irq_high > 0)
>>                       set_irq_prio(port->irq_high, 1);
>> is not my problem.
>>
>> my problem is, that i don't known if  __ipipe_irqbits is handled
>> correct.
> Well, if you want to set port->irq_high, you have to clear the
> corresponding bit in __ipipe_irqbits, as is done for port->irq.
>
Thank you Gilles.

i've also take a part from newer version.
void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
{
     struct irq_desc *desc = irq_to_desc(irq);
     struct irq_data *idata = irq_desc_get_irq_data(desc);
     struct irq_chip *chip = irq_data_get_irq_chip(idata);

     if (chip == &gpio_irq_chip) {
         /* It is a gpio. */
         u32 gpio = irq_to_gpio(irq);
         struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];

         if (ipd == &ipipe_root) {
             port->nonroot_gpios &= ~(1 << (gpio % 32));
             if (port->nonroot_gpios == 0) {
                 __ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq 
% 32));
                 __ipipe_irqbits[(port->irq_high / 32)] &= ~(1 << 
(port->irq_high % 32));
                 set_irq_prio(port->irq, 0);
                 if (port->irq_high > 0)
                     set_irq_prio(port->irq_high, 0);
             }
         } else {
             port->nonroot_gpios |= (1 << (gpio % 32));
             if (port->nonroot_gpios == (1 << (gpio % 32))) {
                 __ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq 
% 32));
                 __ipipe_irqbits[(port->irq_high / 32)] &= ~(1 << 
(port->irq_high % 32));
                 set_irq_prio(port->irq, 1);
                 if (port->irq_high > 0)
                     set_irq_prio(port->irq_high, 1);
             }
         }
     } else
         set_irq_prio(irq, ipd != &ipipe_root);
}

is this correct to clear the the bit in __ipipe_irqbits also for ipd == 
ipipe_root ?

Regards
   Johann



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

* Re: [Xenomai] ipipe bug in gpio/irq for mx6
  2016-03-18 12:15   ` Johann Obermayr
@ 2016-03-18 12:28     ` Gilles Chanteperdrix
  2016-03-23 11:01       ` Johann Obermayr
  0 siblings, 1 reply; 6+ messages in thread
From: Gilles Chanteperdrix @ 2016-03-18 12:28 UTC (permalink / raw)
  To: Johann Obermayr; +Cc: xenomai

On Fri, Mar 18, 2016 at 01:15:17PM +0100, Johann Obermayr wrote:
> Am 18.03.2016 um 12:10 schrieb Gilles Chanteperdrix:
> > On Fri, Mar 18, 2016 at 11:43:26AM +0100, Johann Obermayr wrote:
> >> Hello,
> >>
> >> in the the git branch ipipe-3.0-imx6q
> > This I-pipe patch is really old now. Any chance to use a current
> > version of Xenomai?
> Not now. but we have started to change to 3.10.x with newer xenomai
> >> in the file arch/arm/plat-mxc/gpio.c
> >>
> >> there is follow function.
> >>
> >> void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
> >> {
> >>       struct irq_desc *desc = irq_to_desc(irq);
> >>       struct irq_data *idata = irq_desc_get_irq_data(desc);
> >>       struct irq_chip *chip = irq_data_get_irq_chip(idata);
> >>
> >>       if (chip == &gpio_irq_chip) {
> >>           /* It is a gpio. */
> >>           u32 gpio = irq_to_gpio(irq);
> >>           struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
> >>
> >>           if (ipd != &ipipe_root) {
> >>               port->nonroot_gpios |= (1 << (gpio % 32));
> >>               if (port->nonroot_gpios == (1 << (gpio % 32))) {
> >>                   __ipipe_irqbits[(port->irq / 32)]
> >>                       &= ~(1 << (port->irq % 32));
> >>                   set_irq_prio(port->irq, 1);
> >>               }
> >>           }
> >>       } else
> >>           set_irq_prio(irq, ipd != &ipipe_root);
> >> }
> >>
> >> But there is missing  set_irq_prio for the port->irq_high.
> >> to add
> >>                   if (port->irq_high > 0)
> >>                       set_irq_prio(port->irq_high, 1);
> >> is not my problem.
> >>
> >> my problem is, that i don't known if  __ipipe_irqbits is handled
> >> correct.
> > Well, if you want to set port->irq_high, you have to clear the
> > corresponding bit in __ipipe_irqbits, as is done for port->irq.
> >
> Thank you Gilles.
> 
> i've also take a part from newer version.
> void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
> {
>      struct irq_desc *desc = irq_to_desc(irq);
>      struct irq_data *idata = irq_desc_get_irq_data(desc);
>      struct irq_chip *chip = irq_data_get_irq_chip(idata);
> 
>      if (chip == &gpio_irq_chip) {
>          /* It is a gpio. */
>          u32 gpio = irq_to_gpio(irq);
>          struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
> 
>          if (ipd == &ipipe_root) {
>              port->nonroot_gpios &= ~(1 << (gpio % 32));
>              if (port->nonroot_gpios == 0) {
>                  __ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq 
> % 32));
>                  __ipipe_irqbits[(port->irq_high / 32)] &= ~(1 << 
> (port->irq_high % 32));
>                  set_irq_prio(port->irq, 0);
>                  if (port->irq_high > 0)
>                      set_irq_prio(port->irq_high, 0);
>              }
>          } else {
>              port->nonroot_gpios |= (1 << (gpio % 32));
>              if (port->nonroot_gpios == (1 << (gpio % 32))) {
>                  __ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq 
> % 32));
>                  __ipipe_irqbits[(port->irq_high / 32)] &= ~(1 << 
> (port->irq_high % 32));
>                  set_irq_prio(port->irq, 1);
>                  if (port->irq_high > 0)
>                      set_irq_prio(port->irq_high, 1);
>              }
>          }
>      } else
>          set_irq_prio(irq, ipd != &ipipe_root);
> }
> 
> is this correct to clear the the bit in __ipipe_irqbits also for ipd == 
> ipipe_root ?

It is useless, __ipipe_mach_enable_irqdesc for root irqs is called
only once at boot time, when the bits are already cleared.

-- 
					    Gilles.
https://click-hack.org


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

* Re: [Xenomai] ipipe bug in gpio/irq for mx6
  2016-03-18 12:28     ` Gilles Chanteperdrix
@ 2016-03-23 11:01       ` Johann Obermayr
  2016-03-23 11:12         ` Gilles Chanteperdrix
  0 siblings, 1 reply; 6+ messages in thread
From: Johann Obermayr @ 2016-03-23 11:01 UTC (permalink / raw)
  To: xenomai

Am 18.03.2016 um 13:28 schrieb Gilles Chanteperdrix:
> On Fri, Mar 18, 2016 at 01:15:17PM +0100, Johann Obermayr wrote:
>> Am 18.03.2016 um 12:10 schrieb Gilles Chanteperdrix:
>>> On Fri, Mar 18, 2016 at 11:43:26AM +0100, Johann Obermayr wrote:
>>>> Hello,
>>>>
>>>> in the the git branch ipipe-3.0-imx6q
>>> This I-pipe patch is really old now. Any chance to use a current
>>> version of Xenomai?
>> Not now. but we have started to change to 3.10.x with newer xenomai
>>>> in the file arch/arm/plat-mxc/gpio.c
>>>>
>>>> there is follow function.
>>>>
>>>> void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
>>>> {
>>>>        struct irq_desc *desc = irq_to_desc(irq);
>>>>        struct irq_data *idata = irq_desc_get_irq_data(desc);
>>>>        struct irq_chip *chip = irq_data_get_irq_chip(idata);
>>>>
>>>>        if (chip == &gpio_irq_chip) {
>>>>            /* It is a gpio. */
>>>>            u32 gpio = irq_to_gpio(irq);
>>>>            struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
>>>>
>>>>            if (ipd != &ipipe_root) {
>>>>                port->nonroot_gpios |= (1 << (gpio % 32));
>>>>                if (port->nonroot_gpios == (1 << (gpio % 32))) {
>>>>                    __ipipe_irqbits[(port->irq / 32)]
>>>>                        &= ~(1 << (port->irq % 32));
>>>>                    set_irq_prio(port->irq, 1);
>>>>                }
>>>>            }
>>>>        } else
>>>>            set_irq_prio(irq, ipd != &ipipe_root);
>>>> }
>>>>
>>>> But there is missing  set_irq_prio for the port->irq_high.
>>>> to add
>>>>                    if (port->irq_high > 0)
>>>>                        set_irq_prio(port->irq_high, 1);
>>>> is not my problem.
>>>>
>>>> my problem is, that i don't known if  __ipipe_irqbits is handled
>>>> correct.
>>> Well, if you want to set port->irq_high, you have to clear the
>>> corresponding bit in __ipipe_irqbits, as is done for port->irq.
>>>
>> Thank you Gilles.
>>
>> i've also take a part from newer version.
>> void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
>> {
>>       struct irq_desc *desc = irq_to_desc(irq);
>>       struct irq_data *idata = irq_desc_get_irq_data(desc);
>>       struct irq_chip *chip = irq_data_get_irq_chip(idata);
>>
>>       if (chip == &gpio_irq_chip) {
>>           /* It is a gpio. */
>>           u32 gpio = irq_to_gpio(irq);
>>           struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
>>
>>           if (ipd == &ipipe_root) {
>>               port->nonroot_gpios &= ~(1 << (gpio % 32));
>>               if (port->nonroot_gpios == 0) {
>>                   __ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq
>> % 32));
>>                   __ipipe_irqbits[(port->irq_high / 32)] &= ~(1 <<
>> (port->irq_high % 32));
>>                   set_irq_prio(port->irq, 0);
>>                   if (port->irq_high > 0)
>>                       set_irq_prio(port->irq_high, 0);
>>               }
>>           } else {
>>               port->nonroot_gpios |= (1 << (gpio % 32));
>>               if (port->nonroot_gpios == (1 << (gpio % 32))) {
>>                   __ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq
>> % 32));
>>                   __ipipe_irqbits[(port->irq_high / 32)] &= ~(1 <<
>> (port->irq_high % 32));
>>                   set_irq_prio(port->irq, 1);
>>                   if (port->irq_high > 0)
>>                       set_irq_prio(port->irq_high, 1);
>>               }
>>           }
>>       } else
>>           set_irq_prio(irq, ipd != &ipipe_root);
>> }
>>
>> is this correct to clear the the bit in __ipipe_irqbits also for ipd ==
>> ipipe_root ?
> It is useless, __ipipe_mach_enable_irqdesc for root irqs is called
> only once at boot time, when the bits are already cleared.
>
Here are my patches for imx.6 gpio irq handling.
also add patch for using edge select bit (irq raise/fall detection) on 
imx.6

Regards
    Johann

-------------- next part --------------
>From b806dcf59ec3cf1abc18318cce090b78e396dec6 Mon Sep 17 00:00:00 2001
From: Johann Obermayr <johann.obermayr@sigmatek.at>
Date: Fri, 18 Mar 2016 16:04:38 +0100
Subject: [PATCH] high irq for GPIO input not working.

---
 arch/arm/plat-mxc/gpio.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 87b643e..3f5925a 100755
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -426,9 +426,12 @@ void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
 		if (ipd != &ipipe_root) {
 			port->nonroot_gpios |= (1 << (gpio % 32));
 			if (port->nonroot_gpios == (1 << (gpio % 32))) {
-				__ipipe_irqbits[(port->irq / 32)]
-					&= ~(1 << (port->irq % 32));
+				__ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq % 32));
 				set_irq_prio(port->irq, 1);
+				if (port->irq_high > 0) {
+					__ipipe_irqbits[(port->irq_high / 32)] &= ~(1 << (port->irq_high % 32));
+					set_irq_prio(port->irq_high, 1);
+				}
 			}
 		}
 	} else
@@ -450,8 +453,11 @@ void __ipipe_mach_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
 			port->nonroot_gpios &= ~(1 << (gpio % 32));
 			if (!port->nonroot_gpios) {
 				set_irq_prio(port->irq, 0);
-				__ipipe_irqbits[(port->irq / 32)]
-					|= (1 << (port->irq % 32));
+				__ipipe_irqbits[(port->irq / 32)] |= (1 << (port->irq % 32));
+				if (port->irq_high > 0) {
+					set_irq_prio(port->irq_high, 0);
+					__ipipe_irqbits[(port->irq_high / 32)] |= (1 << (port->irq_high % 32));
+				}
 			}
 		}
 	} else if (ipd != &ipipe_root)
-- 
1.7.9.5

-------------- next part --------------
>From 962417f6870aec76188f391a708fc05d54f6d94c Mon Sep 17 00:00:00 2001
From: Johann Obermayr <johann.obermayr@sigmatek.at>
Date: Mon, 21 Mar 2016 17:14:18 +0100
Subject: [PATCH] use edge select bit to activate raise/fall irq detection.

---
 arch/arm/plat-mxc/gpio.c |   51 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 3f5925a..c1caa6b 100755
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -31,6 +31,7 @@
 
 static struct mxc_gpio_port *mxc_gpio_ports;
 static int gpio_table_size;
+static int GPIO_EDGE_SEL = -1;
 
 #define cpu_is_mx1_mx2()	(cpu_is_mx1() || cpu_is_mx2())
 
@@ -46,7 +47,7 @@ static int gpio_table_size;
 #define GPIO_INT_HIGH_LEV	(cpu_is_mx1_mx2() ? 0x2 : 0x1)
 #define GPIO_INT_RISE_EDGE	(cpu_is_mx1_mx2() ? 0x0 : 0x2)
 #define GPIO_INT_FALL_EDGE	(cpu_is_mx1_mx2() ? 0x1 : 0x3)
-#define GPIO_INT_NONE		0x4
+#define GPIO_INT_BOTH_EDGES	0x4
 
 /* Note: This driver assumes 32 GPIOs are handled in one register */
 
@@ -93,8 +94,9 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 	u32 bit, val;
 	int edge;
 	void __iomem *reg = port->base;
+	u32 gpio_idx = gpio & 31;
 
-	port->both_edges &= ~(1 << (gpio & 31));
+	port->both_edges &= ~(1 << gpio_idx);
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
 		edge = GPIO_INT_RISE_EDGE;
@@ -103,15 +105,19 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 		edge = GPIO_INT_FALL_EDGE;
 		break;
 	case IRQ_TYPE_EDGE_BOTH:
-		val = mxc_gpio_get(&port->chip, gpio & 31);
-		if (val) {
-			edge = GPIO_INT_LOW_LEV;
-			pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
+		if (GPIO_EDGE_SEL >= 0) {
+			edge = GPIO_INT_BOTH_EDGES;
 		} else {
-			edge = GPIO_INT_HIGH_LEV;
-			pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
+			val = mxc_gpio_get(&port->chip, gpio_idx);
+			if (val) {
+				edge = GPIO_INT_LOW_LEV;
+				pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
+			} else {
+				edge = GPIO_INT_HIGH_LEV;
+				pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
+			}
+			port->both_edges |= (1 << gpio_idx);
 		}
-		port->both_edges |= 1 << (gpio & 31);
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
 		edge = GPIO_INT_LOW_LEV;
@@ -124,11 +130,22 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 	}
 
 	spin_lock_irqsave(&port->lock, flags);
-	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
-	bit = gpio & 0xf;
-	val = __raw_readl(reg) & ~(0x3 << (bit << 1));
-	__raw_writel(val | (edge << (bit << 1)), reg);
-	_clear_gpio_irqstatus(port, gpio & 0x1f);
+	if (GPIO_EDGE_SEL >= 0) {
+		void __iomem *regsel = port->base + GPIO_EDGE_SEL;
+		val = __raw_readl(regsel);
+		if (edge == GPIO_INT_BOTH_EDGES)
+			__raw_writel(val | (1 << gpio_idx), regsel);
+		else
+			__raw_writel(val & ~(1 << gpio_idx), regsel);
+	}
+
+	if (edge != GPIO_INT_BOTH_EDGES) {
+		reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
+		bit = gpio & 0xf;
+		val = __raw_readl(reg) & ~(0x3 << (bit << 1));
+		__raw_writel(val | (edge << (bit << 1)), reg);
+	}
+	_clear_gpio_irqstatus(port, gpio_idx);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	return 0;
@@ -330,7 +347,7 @@ int mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
 	mxc_gpio_ports = port;
 	gpio_table_size = cnt;
 
-	printk(KERN_INFO "MXC GPIO hardware\n");
+	printk(KERN_INFO "MXC (%u) GPIO hardware\n", mxc_cpu_type);
 
 	for (i = 0; i < cnt; i++) {
 		/* disable the interrupt and clear the status */
@@ -381,6 +398,10 @@ int mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
 		irq_set_handler_data(port[0].irq, port);
 	}
 
+	/* mx35 or newer support edge select */
+	if (mxc_cpu_type >= MXC_CPU_MX35)
+		GPIO_EDGE_SEL = 0x1C;
+
 	return 0;
 }
 
-- 
1.7.9.5


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

* Re: [Xenomai] ipipe bug in gpio/irq for mx6
  2016-03-23 11:01       ` Johann Obermayr
@ 2016-03-23 11:12         ` Gilles Chanteperdrix
  0 siblings, 0 replies; 6+ messages in thread
From: Gilles Chanteperdrix @ 2016-03-23 11:12 UTC (permalink / raw)
  To: Johann Obermayr; +Cc: xenomai

On Wed, Mar 23, 2016 at 12:01:01PM +0100, Johann Obermayr wrote:
> Am 18.03.2016 um 13:28 schrieb Gilles Chanteperdrix:
> > On Fri, Mar 18, 2016 at 01:15:17PM +0100, Johann Obermayr wrote:
> >> Am 18.03.2016 um 12:10 schrieb Gilles Chanteperdrix:
> >>> On Fri, Mar 18, 2016 at 11:43:26AM +0100, Johann Obermayr wrote:
> >>>> Hello,
> >>>>
> >>>> in the the git branch ipipe-3.0-imx6q
> >>> This I-pipe patch is really old now. Any chance to use a current
> >>> version of Xenomai?
> >> Not now. but we have started to change to 3.10.x with newer xenomai
> >>>> in the file arch/arm/plat-mxc/gpio.c
> >>>>
> >>>> there is follow function.
> >>>>
> >>>> void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
> >>>> {
> >>>>        struct irq_desc *desc = irq_to_desc(irq);
> >>>>        struct irq_data *idata = irq_desc_get_irq_data(desc);
> >>>>        struct irq_chip *chip = irq_data_get_irq_chip(idata);
> >>>>
> >>>>        if (chip == &gpio_irq_chip) {
> >>>>            /* It is a gpio. */
> >>>>            u32 gpio = irq_to_gpio(irq);
> >>>>            struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
> >>>>
> >>>>            if (ipd != &ipipe_root) {
> >>>>                port->nonroot_gpios |= (1 << (gpio % 32));
> >>>>                if (port->nonroot_gpios == (1 << (gpio % 32))) {
> >>>>                    __ipipe_irqbits[(port->irq / 32)]
> >>>>                        &= ~(1 << (port->irq % 32));
> >>>>                    set_irq_prio(port->irq, 1);
> >>>>                }
> >>>>            }
> >>>>        } else
> >>>>            set_irq_prio(irq, ipd != &ipipe_root);
> >>>> }
> >>>>
> >>>> But there is missing  set_irq_prio for the port->irq_high.
> >>>> to add
> >>>>                    if (port->irq_high > 0)
> >>>>                        set_irq_prio(port->irq_high, 1);
> >>>> is not my problem.
> >>>>
> >>>> my problem is, that i don't known if  __ipipe_irqbits is handled
> >>>> correct.
> >>> Well, if you want to set port->irq_high, you have to clear the
> >>> corresponding bit in __ipipe_irqbits, as is done for port->irq.
> >>>
> >> Thank you Gilles.
> >>
> >> i've also take a part from newer version.
> >> void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
> >> {
> >>       struct irq_desc *desc = irq_to_desc(irq);
> >>       struct irq_data *idata = irq_desc_get_irq_data(desc);
> >>       struct irq_chip *chip = irq_data_get_irq_chip(idata);
> >>
> >>       if (chip == &gpio_irq_chip) {
> >>           /* It is a gpio. */
> >>           u32 gpio = irq_to_gpio(irq);
> >>           struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
> >>
> >>           if (ipd == &ipipe_root) {
> >>               port->nonroot_gpios &= ~(1 << (gpio % 32));
> >>               if (port->nonroot_gpios == 0) {
> >>                   __ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq
> >> % 32));
> >>                   __ipipe_irqbits[(port->irq_high / 32)] &= ~(1 <<
> >> (port->irq_high % 32));
> >>                   set_irq_prio(port->irq, 0);
> >>                   if (port->irq_high > 0)
> >>                       set_irq_prio(port->irq_high, 0);
> >>               }
> >>           } else {
> >>               port->nonroot_gpios |= (1 << (gpio % 32));
> >>               if (port->nonroot_gpios == (1 << (gpio % 32))) {
> >>                   __ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq
> >> % 32));
> >>                   __ipipe_irqbits[(port->irq_high / 32)] &= ~(1 <<
> >> (port->irq_high % 32));
> >>                   set_irq_prio(port->irq, 1);
> >>                   if (port->irq_high > 0)
> >>                       set_irq_prio(port->irq_high, 1);
> >>               }
> >>           }
> >>       } else
> >>           set_irq_prio(irq, ipd != &ipipe_root);
> >> }
> >>
> >> is this correct to clear the the bit in __ipipe_irqbits also for ipd ==
> >> ipipe_root ?
> > It is useless, __ipipe_mach_enable_irqdesc for root irqs is called
> > only once at boot time, when the bits are already cleared.
> >
> Here are my patches for imx.6 gpio irq handling.
> also add patch for using edge select bit (irq raise/fall detection) on 
> imx.6
> 
> Regards
>     Johann
> 
> -------------- next part --------------
> From b806dcf59ec3cf1abc18318cce090b78e396dec6 Mon Sep 17 00:00:00 2001
> From: Johann Obermayr <johann.obermayr@sigmatek.at>
> Date: Fri, 18 Mar 2016 16:04:38 +0100
> Subject: [PATCH] high irq for GPIO input not working.
> 
> ---
>  arch/arm/plat-mxc/gpio.c |   14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
> index 87b643e..3f5925a 100755
> --- a/arch/arm/plat-mxc/gpio.c
> +++ b/arch/arm/plat-mxc/gpio.c
> @@ -426,9 +426,12 @@ void __ipipe_mach_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
>  		if (ipd != &ipipe_root) {
>  			port->nonroot_gpios |= (1 << (gpio % 32));
>  			if (port->nonroot_gpios == (1 << (gpio % 32))) {
> -				__ipipe_irqbits[(port->irq / 32)]
> -					&= ~(1 << (port->irq % 32));
> +				__ipipe_irqbits[(port->irq / 32)] &= ~(1 << (port->irq % 32));
>  				set_irq_prio(port->irq, 1);
> +				if (port->irq_high > 0) {
> +					__ipipe_irqbits[(port->irq_high / 32)] &= ~(1 << (port->irq_high % 32));
> +					set_irq_prio(port->irq_high, 1);
> +				}
>  			}
>  		}
>  	} else
> @@ -450,8 +453,11 @@ void __ipipe_mach_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
>  			port->nonroot_gpios &= ~(1 << (gpio % 32));
>  			if (!port->nonroot_gpios) {
>  				set_irq_prio(port->irq, 0);
> -				__ipipe_irqbits[(port->irq / 32)]
> -					|= (1 << (port->irq % 32));
> +				__ipipe_irqbits[(port->irq / 32)] |= (1 << (port->irq % 32));
> +				if (port->irq_high > 0) {
> +					set_irq_prio(port->irq_high, 0);
> +					__ipipe_irqbits[(port->irq_high / 32)] |= (1 << (port->irq_high % 32));
> +				}
>  			}
>  		}
>  	} else if (ipd != &ipipe_root)
> -- 
> 1.7.9.5

I am fine with this patch. Will merge it in recent kernels if
possible.

> 
> -------------- next part --------------
> From 962417f6870aec76188f391a708fc05d54f6d94c Mon Sep 17 00:00:00 2001
> From: Johann Obermayr <johann.obermayr@sigmatek.at>
> Date: Mon, 21 Mar 2016 17:14:18 +0100
> Subject: [PATCH] use edge select bit to activate raise/fall irq detection.
> 
> ---
>  arch/arm/plat-mxc/gpio.c |   51 ++++++++++++++++++++++++++++++++--------------
>  1 file changed, 36 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
> index 3f5925a..c1caa6b 100755
> --- a/arch/arm/plat-mxc/gpio.c
> +++ b/arch/arm/plat-mxc/gpio.c
> @@ -31,6 +31,7 @@
>  
>  static struct mxc_gpio_port *mxc_gpio_ports;
>  static int gpio_table_size;
> +static int GPIO_EDGE_SEL = -1;

All capital names are reserved to macros.

I am fine with this patch patch though I do not understand why it is
needed, if Linux is able to detect both edges so should Xenomai with
the same code. Also, if the patch is for the 3.0-imx6q branch, this
branch has been abandoned a long time ago. The 3.0 kernel has been
EOL for a long time now (last release dates back from october 2013).
So, I do not plan to issue any new patches for this kernel.

-- 
					    Gilles.
https://click-hack.org


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

end of thread, other threads:[~2016-03-23 11:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-18 10:43 [Xenomai] ipipe bug in gpio/irq for mx6 Johann Obermayr
2016-03-18 11:10 ` Gilles Chanteperdrix
2016-03-18 12:15   ` Johann Obermayr
2016-03-18 12:28     ` Gilles Chanteperdrix
2016-03-23 11:01       ` Johann Obermayr
2016-03-23 11:12         ` Gilles Chanteperdrix

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.