rv1126 rv1109系统关机功能的分析与实现

rv1126 rv1109系统关机功能的分析与实现

关机代码分析

代码在./kernel/reboot.c 中

void kernel_power_off(void)
{
	kernel_shutdown_prepare(SYSTEM_POWER_OFF);
	if (pm_power_off_prepare)
		pm_power_off_prepare();
	migrate_to_reboot_cpu();
	syscore_shutdown();
	pr_emerg("Power down\n");
	kmsg_dump(KMSG_DUMP_POWEROFF);
	machine_power_off();
}

kernel_power_off 的调用关系图如下
在这里插入图片描述调用kernel_power_off 的有几个地方,一是do_poweroff Sys-Rq 用,一个是温度过高时关机,另一个是reboot.c中处理poweroff 命令行的系统调用。

//SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
//		void __user *, arg)
	case LINUX_REBOOT_CMD_POWER_OFF:
		kernel_power_off();
		do_exit(0);
		break;

跟踪kernel_power_off -> syscore_shutdown

void syscore_shutdown(void)
{
	struct syscore_ops *ops;

	mutex_lock(&syscore_ops_lock);

	list_for_each_entry_reverse(ops, &syscore_ops_list, node)
		if (ops->shutdown) {
			if (initcall_debug)
				pr_info("PM: Calling %pF\n", ops->shutdown);
			ops->shutdown();
		}

	mutex_unlock(&syscore_ops_lock);
}

查看syscore_ops_list 到底有哪些,
在这里插入图片描述其它地方的不影响关机断电,主要是挂起等相关的一些操作。

rk808.c中

static struct syscore_ops rk808_syscore_ops = {
	.shutdown = rk8xx_syscore_shutdown,
};
static void rk8xx_syscore_shutdown(void)
{
	int ret;
	struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);

	if (!rk808) {
		dev_warn(&rk808_i2c_client->dev,
			 "have no rk808, so do nothing here\n");
		return;
	}

	/* close rtc int when power off */
	regmap_update_bits(rk808->regmap,
			   RK808_INT_STS_MSK_REG1,
			   (0x3 << 5), (0x3 << 5));
	regmap_update_bits(rk808->regmap,
			   RK808_RTC_INT_REG,
			   (0x3 << 2), (0x0 << 2));
	/*
	 * For PMIC that power off supplies by write register via i2c bus,
	 * it's better to do power off at syscore shutdown here.
	 *
	 * Because when run to kernel's "pm_power_off" call, i2c may has
	 * been stopped or PMIC may not be able to get i2c transfer while
	 * there are too many devices are competiting.
	 */
	if (system_state == SYSTEM_POWER_OFF) {
		if (rk808->variant == RK809_ID || rk808->variant == RK817_ID) {
			ret = regmap_update_bits(rk808->regmap,
						 RK817_SYS_CFG(3),
						 RK817_SLPPIN_FUNC_MSK,
						 SLPPIN_DN_FUN);
			if (ret) {
				dev_warn(&rk808_i2c_client->dev,
					 "Cannot switch to power down function\n");
			}
		}

		if (pm_shutdown) {
			dev_info(&rk808_i2c_client->dev, "System power off\n");
			pm_shutdown();
			mdelay(10);
			dev_info(&rk808_i2c_client->dev,
				 "Power off failed !\n");
			while (1)
				;
		}
	}
}

rv1109 使用的是rk809的PMIC,驱动与rk808共用。给PMIC 通过IIC发送关机指令。
machine_power_off 在这里其实没起作用,代码分析如下:

void machine_power_off(void)
{
	local_irq_disable();
	smp_send_stop();

	if (pm_power_off)
		pm_power_off();
}
static int rk808_probe(struct i2c_client *client,
		       const struct i2c_device_id *id)
{
		............
		if (!pm_power_off)
		pm_power_off = rk808_pm_power_off_dummy;
		............
}
static void rk808_pm_power_off_dummy(void)
{
	pr_info("Dummy power off for RK8xx PMICs, should never reach here!\n");

	while (1)
		;
}

硬件关联

关机实现

驱动实现

直接调用kernel_power_off 函数

应用程序实现

直接运行命令poweroff

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值