Jump to content


Photo

GPIO2/INTX0 pin


  • Please log in to reply
8 replies to this topic

#1 heron

heron

    Newbie

  • Members
  • Pip
  • 4 posts

Posted 23 October 2008 - 08:05 PM

Hi,

Would anyone here know whether GPIO2 pin (150) is used by Omnima board? I've been thinking about cutting it and connecting to an IR receiver but first I need to make sure I'm not going to brick the board if I cut the pin.
Any info you can send is much appreciated.


Thanks in advance.
Heron

#2 Slammer

Slammer

    Member

  • Members
  • PipPip
  • 29 posts
  • Location:Greece
  • Interests:Linux based embedded control systems

Posted 24 October 2008 - 06:20 AM

Go to page 9 for GPIO description.
http://www.sunspot.c...weexproject.htm

GPIO2 is connected to reset switch. Actually is free because is a software button :-)

#3 heron

heron

    Newbie

  • Members
  • Pip
  • 4 posts

Posted 24 October 2008 - 10:08 PM

QUOTE (Slammer @ Oct 24 2008, 07:20 AM) <{POST_SNAPBACK}>
Go to page 9 for GPIO description.
http://www.sunspot.c...weexproject.htm

GPIO2 is connected to reset switch. Actually is free because is a software button :-)


Thanks Slammer. I guess that setting a new interrupt handler for INTX0 will prevent the board from resetting when my IR receiver is active.



#4 Slammer

Slammer

    Member

  • Members
  • PipPip
  • 29 posts
  • Location:Greece
  • Interests:Linux based embedded control systems

Posted 25 October 2008 - 02:12 PM

I think that GPIO2 is simply connected to the switch. The software can use this switch for reset, it is not hardwired to the real Reset. In my system (using Openwrt svn) I dont include GPIO Input module and the switch does nothing at all. I think that you can use the input for anything you like, keep in mind only that input is connected to the switch and if someone press this button you will get false signal (or you can remove it and connect anything you like there)

#5 heron

heron

    Newbie

  • Members
  • Pip
  • 4 posts

Posted 25 October 2008 - 07:01 PM

I just finished playing with INTX0 for today and apparently I do something wrong since I don't get expected results. I wrote a simple kernel module which is supposed to request INTX0 irq and wake up a thread when interrupt is triggered. Well, everything goes well with the setup - I can request the irq and disable/enable it (as it is disabled by default I think). But then my handler never gets called. I tried to trigger it by pressing down the reset switch. I assume I don't need any GPIO input module as I handle everything (or intend so) by myself. Apparently I'm missing something.
Do you see any obvious (or less so) reason why my approach wouldn't work?

That GPIO Input module that you mentioned - which one is it exactly? I will take a look and maybe get some hints fro there, too.

Thanks in advance.

Heron

#6 heron

heron

    Newbie

  • Members
  • Pip
  • 4 posts

Posted 26 October 2008 - 11:31 PM

Finally made it work :-)

All that needed to be done apart from requesting irq was to:
- set the active level of INTX0 to high
- enable INTX0 interface (as they call it in the ADM5120 documentation) - switch register 0xBC

And all of that under big kernel lock smile.gif

Now when I press reset switch I trigger the interrupt and that prints a message thru my thread. Cool stuff. Now that basic things can be setup I will start working on lirc driver.

Heron

#7 Sunspot

Sunspot

    Newbie

  • Members
  • Pip
  • 4 posts

Posted 25 November 2008 - 04:10 PM

1) I can confirm that in the Midge-Sunspot "distro" the reset pin acts like any other CPU line.

2) I have wanted an interrupt feature for some time!

I am not a Linux expert - just a user.
Can you spell out how to build a firmware that does that - can I use Midge (2.4) or do I need Squidge (2.6) or similar?

My site is -
http://www.sunspot.c...weexproject.htm

QUOTE (heron @ Oct 26 2008, 11:31 PM) <{POST_SNAPBACK}>
Finally made it work :-)

All that needed to be done apart from requesting irq was to:
- set the active level of INTX0 to high
- enable INTX0 interface (as they call it in the ADM5120 documentation) - switch register 0xBC

And all of that under big kernel lock smile.gif

Now when I press reset switch I trigger the interrupt and that prints a message thru my thread. Cool stuff. Now that basic things can be setup I will start working on lirc driver.

Heron



#8 AlG

AlG

    Newbie

  • Members
  • Pip
  • 3 posts

Posted 14 September 2009 - 02:32 PM

Did anyone else manage to get interrupts going on GPIO2/INTX0? I have tried to reproduce herons steps but with no luck. My module loads OK and I can see it registered in /proc/interrupts, but when I press the interrupt button nothing happens.

My code looks like:
CODE
#include <linux/module.h>
#include <linux/init.h>
#include <asm-mips/mach-adm5120/adm5120_info.h>
#include <asm-mips/mach-adm5120/adm5120_intc.h>
#include <asm-mips/mach-adm5120/adm5120_switch.h>
#include <asm-mips/mach-adm5120/adm5120_defs.h>
#include <linux/interrupt.h>

#define INTC_IRQ_INTX0 INTC_IRQ_GPIO2
#define GPIO_IRQ INTC_IRQ_INTX0


static inline void intc_write_reg(unsigned int reg, u32 val)
{
        void __iomem *base = (void __iomem *)KSEG1ADDR(ADM5120_INTC_BASE);

        __raw_writel(val, base + reg);
}

static inline u32 intc_read_reg(unsigned int reg)
{
        void __iomem *base = (void __iomem *)KSEG1ADDR(ADM5120_INTC_BASE);

        return __raw_readl(base + reg);
}


static irqreturn_t gpio_reset_interrupt(int irq, void* dev_id)
{
        printk(KERN_ERR "gpio_reset_interrupt called!");
        return(IRQ_HANDLED);

}


static int __init mymodule_init(void)
{
        if ( request_irq(GPIO_IRQ, gpio_reset_interrupt, IRQF_TRIGGER_HIGH, "gpio_reset", NULL) )
        {
                printk(KERN_ERR "GPIO_RESET: trouble requesting IRQ");
                return(-EIO);
        }

        // enable interrupt on GPIO 2
        // pp37 ADM5120 manual
        {
                uint ire = intc_read_reg(INTC_REG_IRQ_ENABLE);

                ire |= BIT(4);

                intc_write_reg(INTC_REG_IRQ_ENABLE, ire);
        }

        // Enable CSX0/INTX0 processing as described on pp131 of ADM5120 manual
        SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, GPIO_CONF2_CSX0);

        // sets GPIO4 and 2 as active high
        // pp41/42 of ADM5120 manual
        intc_write_reg(INTC_REG_INT_LEVEL, 0);

        printk ("gpio_reset module loaded\n");

        return 0;
}


static void __exit mymodule_exit(void)
{
        free_irq(GPIO_IRQ, NULL);
        printk ("gpio_reset module unloaded\n");
        return;
}

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");



#9 AlG

AlG

    Newbie

  • Members
  • Pip
  • 3 posts

Posted 17 September 2009 - 08:55 AM

I got this going (see revised code below). It seems that the correct IRQ number to use for GPIO2 (the reset button) is 12, not 4 as I had previously thought. As I understand it, some interrupts are handled directly by the MIPS cpu and others are handled by an interrupt controller built into the ADM5120 SoC. It appears that the interrupt controller IRQ numbers need to be offset by the 8 interrupts handled by the core cpu.

I've corrected and cleaned up the code here:
CODE

#include <linux/module.h>
#include <linux/init.h>
#include <asm-mips/mach-adm5120/adm5120_info.h>
#include <asm-mips/mach-adm5120/adm5120_intc.h>
#include <asm-mips/mach-adm5120/adm5120_switch.h>
#include <asm-mips/mach-adm5120/adm5120_defs.h>
#include <linux/interrupt.h>

#define GPIO_IRQ 12

static inline void intc_write_reg(unsigned int reg, u32 val)
{
        void __iomem *base = (void __iomem *)KSEG1ADDR(ADM5120_INTC_BASE);

        __raw_writel(val, base + reg);
}

static inline u32 intc_read_reg(unsigned int reg)
{
        void __iomem *base = (void __iomem *)KSEG1ADDR(ADM5120_INTC_BASE);

        return __raw_readl(base + reg);
}

static spinlock_t level_register_lock = SPIN_LOCK_UNLOCKED;

static irqreturn_t gpio_reset_interrupt(int irq, void* dev_id)
{
        unsigned long flags;
        uint intc_reg_int_level;

        spin_lock_irqsave(&level_register_lock, flags);
        {
                intc_reg_int_level = BIT(4) ^ intc_read_reg(INTC_REG_INT_LEVEL);

                intc_write_reg(INTC_REG_INT_LEVEL, intc_reg_int_level);
        }
        spin_unlock_irqrestore(&level_register_lock, flags);

        printk(BIT(4) & intc_reg_int_level ? "released\n" : "pressed\n");

        return(IRQ_HANDLED);
}


static int __init mymodule_init(void)
{
        unsigned long flags;

        spin_lock_irqsave(&level_register_lock, flags);
        {
                // enable interrupt on GPIO 2
                // pp37 ADM5120 manual
                {
                        uint ire = intc_read_reg(INTC_REG_IRQ_ENABLE);

                        ire |= BIT(4) | BIT(9); // II0E | SWIE
        
                        intc_write_reg(INTC_REG_IRQ_ENABLE, ire);
                        printk("INTC_REG_IRQ_ENABLE = %u\n", ire);
                }
        
                // Enable CSX0/INTX0 processing as described on pp131 of ADM5120 manual
                 SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, GPIO_CONF2_CSX0);

                // sets GPIO4 and 2 as active low
                // pp41/42 of ADM5120 manual.
                // NB: The register diagram and description conflict and I don't think either is 100% correct.
                 // I can only toggle BITS 4 and 5. BIT 4 controls GPIO2 and BIT 5 controls GPIO4.
                intc_write_reg(INTC_REG_INT_LEVEL, BIT(4) | intc_read_reg(INTC_REG_INT_LEVEL));
        }
        spin_unlock_irqrestore(&level_register_lock, flags);

        if ( request_irq(GPIO_IRQ, gpio_reset_interrupt, IRQF_TRIGGER_NONE, "gpio_reset", NULL) )
        {
                printk(KERN_ERR "GPIO_RESET: trouble requesting IRQ");
                return(-EIO);
        }

        return 0;
}

static void __exit mymodule_exit(void)
{
        free_irq(GPIO_IRQ, NULL);
        printk ("gpio_reset module unloaded\n");
        return;
}

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users