This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

wake up processor and android on gpio interrupt

Other Parts Discussed in Thread: SYSCONFIG

Hi All,

We have one custom board with omap4460. We have ported android on it. Now i want to wakeup the processor and android on gpio interrupt. like when external peripheral give interrupt on gpio of processor, board should be wake up if it is in stand by.


What should i write in interrupt handler of gpio to achieve this.?

i have tried to make it wake capable irq through enable_wake_irq(), but nothing is working.


Thanks,

Jags VG

  • Hello Jags,

    For wake up you can use the corresponding bits in each pad configuration registers:

    The I/O pad wake-up scheme must be enabled (WUEN signal) globally by setting the PRM_IO_PMCTRL[16] GLOBAL_WUEN bit and by also setting I/O pad wake-up enabled/disabled individually (WUEN signal) by writing to the following bit fields in the control module:
    CONTROL.CONTROL_(CORE/WKUP)_PAD0_X_PAD1_Y [14] WAKEUPENABLE
    CONTROL.CONTROL_(CORE/WKUP)_PAD0_X_PAD1_Y [30] WAKEUPENABLE

    See section 3.9.4 I/O Management in PRCM chapter on OMAP4460 TRM.

    Best regards,

    Yanko

  • Hi Yanko,

    Thanks for your reply.

    By above method, only processor will be waken up or Android will also be waken up(display will come from standby)?

    Thanks,

    Jags VG

  • Hello Jags,

    When occurs a wake-up event on the OMAP's GPIO, it will generate wake-up request to the corresponding module.

    You can see GPIO driver in the Android drivers/gpio/gpio-omap.c:

    /*
     * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
     * 1510 does not seem to have a wake-up register. If JTAG is connected
     * to the target, system will wake up always on GPIO events. While
     * system is running all registered GPIO interrupts need to have wake-up
     * enabled. When system is suspended, only selected GPIO interrupts need
     * to have wake-up enabled.
     */
    static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
    {
        u32 gpio_bit = GPIO_BIT(bank, gpio);
        unsigned long flags;

        if (bank->non_wakeup_gpios & gpio_bit) {
            dev_err(bank->dev,
                "Unable to modify wakeup on non-wakeup GPIO%d\n", gpio);
            return -EINVAL;
        }

        spin_lock_irqsave(&bank->lock, flags);
        if (enable)
            bank->context.wake_en |= gpio_bit;
        else
            bank->context.wake_en &= ~gpio_bit;

        __raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en);
        spin_unlock_irqrestore(&bank->lock, flags);

        return 0;
    }

    static void _reset_gpio(struct gpio_bank *bank, int gpio)
    {
        _set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
        _set_gpio_irqenable(bank, gpio, 0);
        _clear_gpio_irqstatus(bank, gpio);
        _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
        _clear_gpio_debounce(bank, gpio);
    }

    /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
    static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
    {
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
        unsigned int gpio = irq_to_gpio(bank, d->irq);

        return _set_gpio_wakeup(bank, gpio, enable);
    }

    static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
    {
        struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
        unsigned long flags;

        /*
         * If this is the first gpio_request for the bank,
         * enable the bank module.
         */
        if (!bank->mod_usage)
            pm_runtime_get_sync(bank->dev);

        spin_lock_irqsave(&bank->lock, flags);
        /* Set trigger to none. You need to enable the desired trigger with
         * request_irq() or set_irq_type().
         */
        _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);

        if (bank->regs->pinctrl) {
            void __iomem *reg = bank->base + bank->regs->pinctrl;

            /* Claim the pin for MPU */
            __raw_writel(__raw_readl(reg) | (1 << offset), reg);
        }

        if (bank->regs->ctrl && !bank->mod_usage) {
            void __iomem *reg = bank->base + bank->regs->ctrl;
            u32 ctrl;

            ctrl = __raw_readl(reg);
            /* Module is enabled, clocks are not gated */
            ctrl &= ~GPIO_MOD_CTRL_BIT;
            __raw_writel(ctrl, reg);
            bank->context.ctrl = ctrl;
        }

        bank->mod_usage |= 1 << offset;

        spin_unlock_irqrestore(&bank->lock, flags);

        return 0;
    }

    Module wake-up request:
    In IDLE state, a slave module may have to wake up to generate an interrupt or a DMA request. This may be the result of an external request (for example, to the I/O port of a general-purpose input/output [GPIO] module) or an internally generated event (for example, WDTIMER time-up). The slave module, with wake-up capability, sends a wake-up request to the PRCM module. The PRCM module then activates the module clocks and acknowledges the module wake-up request.
    In IDLE state, some slave modules may require functional clock(s) to generate a wake-up event. Such requests are called synchronous wake-up events on the PRCM module side, while the events generated when the functional or interface module clocks are gated are called asynchronous wake-up events.

    Yes, you can wake-up Display if you configure a GPIO to generate wake-up event. This must be set in the display driver for Android.

    You must see CD_DSS Wake-Up Dependency in the PRCM. For more information see table CD_DSS Wake-Up Dependency Association Parameters.

    Best regards,

    Yanko