wake up k70 from VLPS deep sleep by GPIO interrupt - linux-kernel

I can not wake up k70 (Kinetis) from VLPS deep sleep by GPIO interrupt.
This is under uCLinux, where I enabled CONFIG_PM. After that, I can put K70 to deep sleep by "echo mem > /sys/power/state" and wake it up from UART debug console. But I can not wake up by triggering GPIO interrupt. I have confirmed that the interrupt works before and after the sleep by printing from the interrupt handler and I have also confirmed the GPIO pin value changes from 0 to 1 during sleep after I triggered the GPIO interrupt.
According to the K70 manual, I should be able to wake up VLPS by a GPIO interrupt. Does any have any insight why I could not?
Thanks

First of all, your GPIO driver should implement IRQ chip. (From the above description I have no clue what is the platform and what is the GPIO driver is used there).
Second, the IRQ chip implementation has to have ->irq_set_wake() callback to be present and properly implemented.
Third, the caller, which does get GPIO line via gpiod_get() has to perform:
struct gpio_desc *gd;
int irq;
gd = gpiod_get(...);
if (IS_ERR(gd))
return PTR_ERR(gd);
irq = gpiod_to_irq(gd);
if (irq < 0)
return irq;
/* Now! */
enable_irq_wake(irq); /* This does the trick */

Related

Userspace interrupt for gpio pins that don't have edge sysfs

In my platform, there is a PCA9555 CMOS device which has 16 GPIO pins and a separate INT pin for interrupts. So long, my application was periodically reading a particular gpio pin. I need to change it to an interrupt driven way. From the spec : It has an open-drain interrupt pin which is activated when one of the 16 port pins changes state and the pin is configured as an input. A pin configured as an output cannot cause an interrupt.
None of the 16 pins have interrupt support themselves and I don't see edge sysfs in /sys/class/gpio/gpio/[pin_no]. So poll() on value file is not blocking. And I infer from the spec that an interrupt would be triggered to CPU if state of any of the input pins change. How do I catch this interrupt in userspace?
I see in gpiolib-cdev.c about line events.
static irqreturn_t lineevent_irq_handler(int irq, void *p)
Can I use /dev/gpiochip<n> character device and poll() for interrupts? or is this only supported for a gpio pin that supports interrupt?

What steps are needed to detect a GPU interrupt on a Raspberry Pi3?

I am writing a bare-metal kernel, but an interrupt doesn't seem to be triggered when the EMMC INTERRUPT register becomes non-zero.
I have two cores idling, and one at EL3 with no data caches enabled continually displaying a page of memory, in order to see what the code I'm testing is up to. (The test code regularly flushes its cache, on the working QA7 millisecond interrupt.)
The code being tested is running at Secure EL0 on core 0, with interrupts enabled. Interrupts are routed to core 0:
QA7.GPU_interrupts_routing = 0; // IRQ and FIQ to Core 0
The EMMC interface is initialised, and a reset command sent to the card, at which point the INTERRUPT register becomes 1 (bit 0 set: command has finished), but no GPU interrupt seems to be signalled to the QA7 hardware (bit 8 in the Core 0 interrupt source register stays zero).
The EMMC registers IRPT_MASK and IRPT_EN are both set to 0x017f7137, which I think should enable all known interrupts from that peripheral, and certainly bit 0.
The BCM8235 interrupt registers have been written as so:
Enable_IRQs_1 = 0x20000000; // (1 << 29);
Enable_IRQs_2 = 0x02ff6800; // 0b00000010111111110110100000000000;
Enable_Basic_IRQs = 0x303;
But they read back as:
Enable_IRQs_1: 0x20000200 // (1 << 9) also set
Enable_IRQs_2: 0x02ff6800 // unchanged
Enable_Basic_IRQs: 0x3 // No interrupts from IRQs 1 or 2.
What have I missed?
(Tagged raspberry-pi2, since it also has the QA7 component.)
The simple answer is nothing more. The Arasan SD interface interrupt is number 62, bit 20 in the IRQ basic pending register. Enable bit 30 in IRQ pending 2, and the interrupt comes through.
Enable_IRQs_2 = 0x42ff6800;
I just had to ignore the advice: "The table above has many empty entries. These should not be enabled as they will interfere with the GPU operation." in the documentation.

Handle GPIO in Kernel and User Space ARM9 Embedded Linux AM1808

I have to handle (i.e. turn on and off) my LCD Power Pin kernel and userspace both side.
We have configured the gpio pin in Mux.h,da850.c and board-da850-evm.c properly.
The problem is that when we configure this pin in kernel then this pin is not access by /sys/class/gpio.
We have configured this in in board-da850-evm.c as below,
ret = gpio_request(DA850_LCD_GP3, "LCD GP3");
if (ret)
pr_warning("Cannot open GPIO %d\n", DA850_LCD_GP3);
gpio_direction_output(DA850_LCD_GP3, 1);
gpio_set_value(DA850_LCD_GP3,1);
If we comment this section.and export from userspace then we used this pin form userspace successfully.
Is it possible to handle gpio form kernel and userspace?
Or do we need to write the gpio drive ?

Detect USB Connection Event on STM32

I'm currently working with a USB-enabled low power device that I'm having a bit of trouble with. During normal operation, the system clock is set to a significantly slower speed (since this is a data logger only active once every few minutes, this isn't a problem). However, when the device is then plugged into a USB port on a computer, it needs to recognize this, initialize the USB stack (which I can do), and reset the system clock to full speed (I can do this, as well).
My problem, as you might have noticed, is the "USB Connected" event. I'm looking through the STM32 evaluation materials and they have in the IRQn table a "USB_FS_WKUP_IRQn", and the STM32 eval board also has USB-5V power routed to pin PE6, which can also act as WKUP3.
Do I need to enable an external interrupt for that pin, or is there a better way to detect such an event and set/reset the clocks as needed?
Thanks in advance.
Basing on the interrupt name you mentioned I found this implementation:
// Enable the USB Wake-up interrupt
NVICInit.NVIC_IRQChannel = USB_FS_WKUP_IRQn;
NVICInit.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_Init(&NVICInit);
It seems you don't need much more. The implementation can differ from the STM32 family you use.
I use the stm32l4
I set up an interrupt on the Vbus pin.
While not in USB mode, configure the pin as a pull-down (so it isn't floating).
Your pin and interrupt line would be different, but
//Configure the pin
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA9 */
GPIO_InitStruct.Pin = VBUS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(VBUS_GPIO_Port, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
//Configure the interrupt
EXTI_ConfigTypeDef exti_conf;
exti_conf.Line = EXTI_LINE_9;
exti_conf.GPIOSel = EXTI_GPIOA;
exti_conf.Mode = EXTI_MODE_INTERRUPT;
exti_conf.Trigger = EXTI_TRIGGER_RISING;
HAL_EXTI_SetConfigLine(&hexti_vbus, &exti_conf);
And make sure you have an interrupt handler taken care of. Set a flag for going to USB in the interrupt handler. And you should be set.

PCIe Interrupt number

I am trying to write a Kernel Module that I can use to service PCIe MSI interrupts. Right now I am having trouble trying to configure my interrupts and am trying to follow along with "Linux Device Drivers Ed. 3" The book states:
"The driver doesn't need to bother checking the interrupt number, because the value found in PCI_INTERRUPT_LINE is guaranteed to be the right one."
So of course this seems to be the logical way to setup my interrupts:
err = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &myirq);
if(err)
{
printk(KERN_WARNING "Could not get IRQ number\n");
return err;
}
err = request_irq(myirq, fpga_isr, IRQF_SHARED, fpga_driver.name, dev);
Now this registers me for interrupt 60. I then go about using jTag to manually trigger an interrupt and I get a Kernel message saying that the interrupt does not have a handler attatched to it (interrupt 576). If I hardcode irq_line to 576 I then fail the request_irq.
What is the best way to find out my interrupt line? and why can I not get the IRQ that I need?
One more thing, during boot, my device is automatically set to IRQ pin 1 (Legacy interrupt A) which correseponds to irq line 572 which is also the value stored in dev->irq. If the boot sequence automatically set the IRQ to pin 0 (Legacy interrupts disabled) would dev->irq point to my MSI interrupt # 576?
For MSI, you need to enable the MSI interrupt on your device first with pci_enable_msi. The MSI interrupt is not the same as the "standard PCI" interrupt. After calling pci_enable_msi, the interrupt number should be gotten from pci_dev->irq for calling request_irq. Look for an example in the kernel source tree.
More info in Documentation/PCI/MSI-HOWTO.txt

Resources