捕获i.MX6UL(linux内核)的断电中断



上下文

我使用的是I.MX6(IMXULL(应用程序处理器,想知道软件中何时按下了关机按钮:

幸运的是,IMX6ULL参考手册解释说这应该是可能的:


第10.5节:ONOFF按钮

芯片支持使用按钮输入信号请求PMU更改主SoC电源状态(即接通或断开(。SNVS_LP内部的ONOFF逻辑允许直接连接到PMIC或其他电压调节器设备。逻辑获取按钮输入信号,然后输出pmic_en_bset_pwr_off_irq信号。[…]逻辑有两种不同的操作模式(Dumb和Smart模式(。Dumb PMIC模式使用pmic_en_b发出开启和关闭的电平信号。Dumb PMIC模式有许多不同的配置选项,包括(去抖动、关闭到开启时间和最大超时(。

(也可在第18页以浓缩形式提供(


尝试

因此,我构建了一个非常简单的内核模块来尝试捕获这个中断:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/syscalls.h>
#include <linux/interrupt.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Doe <j.doe@acme.inc>");

// Forward declaration
irqreturn_t irq_handler (int, void *);

// Number of interrupt to capture
#define INTERRUPT_NO        36

static int __init pwr_ctl_init (void)
{
pr_err("init()n");
return request_irq(INTERRUPT_NO, irq_handler, IRQF_SHARED, "onoff-button",
(void *)irq_handler);
}
static void __exit pwr_ctl_exit (void)
{
pr_err("exit()n");
free_irq(INTERRUPT_NO, NULL);
}

irqreturn_t irq_handler (int irq, void *dev_irq)
{
pr_err("interrupt!n");
return IRQ_HANDLED;
}
module_init(pwr_ctl_init);
module_exit(pwr_ctl_exit);

问题

然而,我找不到任何关于中断次数的信息。当在互联网上搜索时,我得到的只是这篇NXP论坛帖子:

  • ONOFF按钮不中断

这暗示它应该是36。然而,我发现在我的平台上并非如此。当我检查/proc/interrupts36已经被20b4000.ethernet占用时。因为应用手册中也提到它是由SNVS低功率系统生成的,所以我查看了设备树,发现了以下信息:

snvs_poweroff: snvs-poweroff {
compatible = "syscon-poweroff";
regmap = <&snvs>;
offset = <0x38>;
value = <0x60>;
mask = <0x60>;
status = "disabled";
};
snvs_pwrkey: snvs-powerkey {
compatible = "fsl,sec-v4.0-pwrkey";
regmap = <&snvs>;
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
linux,keycode = <KEY_POWER>;
wakeup-source;
status = "disabled";
};

这个信息对于知道SNVS是中断控制器似乎很有用,但对于如何捕获这个set_pwr_off_irq信号却不有用。


结论

  • 如何捕获SNVS生成的ON/OFF中断
  • 如何从设备树中确定中断次数(如果适用(
  • 我是否误解了ONOFF功能的工作原理?是否有可能从内核模块中获取这些信息

编辑

这个编辑回答了一些用户的问题,然后进入了关于我后来发现的问题的新信息:

用户问题

  • 处理器:处理器是NXP i.MX 6UltraLite / 6ULL / 6ULZARM Cortex A7

新信息

  • SNVS驱动程序:使用我的构建系统内核配置,我修改并验证了snvs_pwrkey驱动程序(请参阅此处(已启用。我的修改包括在中断例程中添加一个单个kprint语句,看看按钮是否触发它
  • 我尝试将驱动程序更新到一个新版本,该版本声称支持更新的I.MX6处理器。这也不起作用
  • 我尝试将驱动程序加载为内核模块,以便于调试。这是不可能的,因为内核配置需要启用它,并且我无法将它从静态构建到内核中删除

答案相当虎头蛇尾。简言之,有一个设备树覆盖层禁用了我对snvs_pwrkey的更改,即使我已经启用了它。一旦我找到并删除了覆盖层,驱动程序(snvs_pwrkey.c(就可以正常工作了。

至于IRQ编号,原来电源按钮的IRQ是通过Linux解释的45。中断没有配置为共享,所以我的内核模块无法加载。

如果您想捕捉电源按钮切换事件,我建议修改驱动程序以添加一些输出,然后可能添加udev规则来捕捉按钮按下。我会尽快用一个例子更新我的答案。

最新更新