我已经成功使用pm_power_off函数指针使我的自定义Linux板通过i2c调用其电源管理芯片(以关闭电源).
我也希望Linux halt命令也能关闭电源.
我该如何实现?
machine_halt的(ARM)代码没有类似于machine_power_off的pm_power_off的指针.
arch / arm / kernel / reboot.c:
/*
* Halting simply requires that the secondary CPUs stop performing any
* activity (executing tasks, handling interrupts). smp_send_stop()
* achieves this.
*/
void machine_halt(void)
{
local_irq_disable();
smp_send_stop();
local_irq_disable();
while (1);
}
/*
* Power-off simply requires that the secondary CPUs stop performing any
* activity (executing tasks, handling interrupts). smp_send_stop()
* achieves this. When the system power is turned off, it will take all CPUs
* with it.
*/
void machine_power_off(void)
{
local_irq_disable();
smp_send_stop();
if (pm_power_off)
pm_power_off();
}
显然,我可以只hack machine_halt,但如果可能的话,我想“适当地”做到这一点.
我是否错过了某些(可能在用户空间中)可能导致暂停命令执行“关闭电源”的操作?
更新:感谢您的回答和您的所有评论,它们帮助我意识到了实际的问题所在.
我的问题是:
我有一个输入边缘,可用于定制电源管理单元.可以将其视为启动按钮,没有停止或重置功能.我完全控制PMU代码(这是一个ATMEGA,作为i2c从设备运行).
>如果Linux内核正在运行,我希望忽略边缘.
>如果CPU电源已关闭,我希望边缘电源打开CPU.
>如果Linux内核停止运行,我希望边缘重新设置CPU.
情况1很简单,无事可做.
情况2很简单,请在驱动程序中定义pm_power_off,以向PMU发送i2c消息.幸运的是,当调用pm_power_off时,i2c子系统仍处于工作状态.
情况3是问题-我正在寻找pm_halt进行定义,以将i2c消息发送到PMU.
也许还有另一种方式,如0andriy评论?
除非机器停止运行,内核中是否还有地方可以以几赫兹的频率向i2c消息发送PMU?
https://unix.stackexchange.com/a/42576/17288的答案是:
“ *这些天的停顿足够聪明,如果启用了ACPI,则可以自动关闭电源.实际上,它们现在在功能上等效.”
也许有某种方法可以提供或吸引ACPI-我将不得不继续阅读.
解决方法:
您应该使用poweroff命令或暂停-p.根据man 8 halt,halt命令(不带参数)不能保证关闭计算机电源.原因描述为here:
halt
was used before ACPI (which today will turn off the power for you)*. It would halt the system and then print a message to the effect of “it’s ok to power off now”. Back then there were physical on/off switches, rather than the combo ACPI controlled power button of modern computers.*These days
halt
is smart enough to automatically call poweroff if ACPI is enabled. In fact, they are functionally equivalent now.
从停止工具的源代码中可以看到,它发出reboot()系统调用,其中cmd = RB_POWER_OFF = LINUX_REBOOT_CMD_POWER_OFF.
在内核中,该系统调用实现为here,在cmd = LINUX_REBOOT_CMD_POWER_OFF上,它调用:
-> kernel_power_off()
-> machine_power_off()
-> pm_power_off()