Android OrangePi 4G IOT(五) - MTK电源管理驱动(一)

一、MTK电源管理组成

这里讲的电源管理驱动主要是SPM驱动,CPU idle驱动,CPU Hotplug驱动,CPU Frequency驱动等,代码主要集中在以下目录。

1:/home/ubuntu/Mediatek/code/kernel-3.18/drivers/misc/mediatek/base/power/

2:/home/ubuntu/Mediatek/code/kernel-3.18/drivers/base/power

3:/home/ubuntu/Mediatek/code/kernel-3.18/kernel/power/

4:/home/ubuntu/Mediatek/code/kernel-3.18/drivers/cpufreq/

5:/home/ubuntu/Mediatek/code/kernel-3.18/drivers/cpuidle/

二、Linux kernel Generic Power

1:Linux power初始化,首先使用pm_init初始化power manager工作队列,设置休眠镜像大小,创建attribute属性等。

/home/ubuntu/Mediatek/code/kernel-3.18/kernel/power/main.c

static struct attribute * g[] = {
	&state_attr.attr,
#ifdef CONFIG_PM_TRACE
	&pm_trace_attr.attr,
	&pm_trace_dev_match_attr.attr,
#endif
#ifdef CONFIG_PM_SLEEP
	&pm_async_attr.attr,
	&wakeup_count_attr.attr,
#ifdef CONFIG_PM_AUTOSLEEP
	&autosleep_attr.attr,
#endif
#ifdef CONFIG_PM_WAKELOCKS
	&wake_lock_attr.attr,
	&wake_unlock_attr.attr,
#endif
#ifdef CONFIG_PM_DEBUG
	&pm_test_attr.attr,
#endif
#ifdef CONFIG_PM_SLEEP_DEBUG
	&pm_print_times_attr.attr,
#endif
#endif
#ifdef CONFIG_FREEZER
	&pm_freeze_timeout_attr.attr,
#endif
//CodeSwitching start
#if 1// HIGUA
        &custom_changelogo_attr.attr,
#endif
//CodeSwitching end
	NULL,
};

static struct attribute_group attr_group = {
	.attrs = g,
};

struct workqueue_struct *pm_wq;
EXPORT_SYMBOL_GPL(pm_wq);

static int __init pm_start_workqueue(void)
{
	pm_wq = alloc_workqueue("pm", WQ_FREEZABLE, 0);

	return pm_wq ? 0 : -ENOMEM;
}

static int __init pm_init(void)
{
	int error = pm_start_workqueue();
	if (error)
		return error;
	hibernate_image_size_init();
	hibernate_reserved_size_init();
	power_kobj = kobject_create_and_add("power", NULL);
	if (!power_kobj)
		return -ENOMEM;
	error = sysfs_create_group(power_kobj, &attr_group);
	if (error)
		return error;
	pm_print_times_init();
	return pm_autosleep_init();
}

core_initcall(pm_init);

2:Android用户层通过按键按钮触发 ‘echo mem > /sys/power/state’进行休眠相关的一些列流程

用户层这个命令是通过上述命令进行触发,处理代码为

/home/ubuntu/Mediatek/code/kernel-3.18/kernel/power/main.c

static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
			   const char *buf, size_t n)
{
	suspend_state_t state;
	int error;

#ifdef CONFIG_MTK_HIBERNATION
	char *p;
	int len;
#endif

	error = pm_autosleep_lock();
	if (error)
		return error;

	if (pm_autosleep_state() > PM_SUSPEND_ON) {
		error = -EBUSY;
		goto out;
	}

	state = decode_state(buf, n);

#ifdef CONFIG_MTK_HIBERNATION
	p = memchr(buf, '\n', n);
	len = p ? p - buf : n;
	if (len == 8 && !strncmp(buf, "hibabort", len)) {
		hib_log("abort hibernation...\n");
		error = mtk_hibernate_abort();
		goto out;
	}
#endif

	pr_warn("[%s]: state = (%d)\n", __func__, state);

	if (state < PM_SUSPEND_MAX) {
		error = pm_suspend(state);
		pr_warn("[%s]: pm_suspend() return (%d)\n", __func__, error);
	} else if (state == PM_SUSPEND_MAX) {
#ifdef CONFIG_MTK_HIBERNATION
		hib_log("trigger hibernation...\n");
		if (!pre_hibernate()) {
			error = 0;
			error = mtk_hibernate();
		}
#else /* !CONFIG_MTK_HIBERNATION */
		error = hibernate();
#endif /* CONFIG_MTK_HIBERNATION */
	} else {
		error = -EINVAL;
	}

 out:
	pm_autosleep_unlock();
	return error ? error : n;
}

power_attr(state);

3:进入pm_suspend流程,进入enter_state处理,然后进行相关的suspend_syssync_enqueue,suspend_prepare,suspend_devices_and_enter。

代码如下

/**
 * pm_suspend - Externally visible function for suspending the system.
 * @state: System sleep state to enter.
 *
 * Check if the value of @state represents one of the supported states,
 * execute enter_state() and update system suspend statistics.
 */
int pm_suspend(suspend_state_t state)
{
	int error;

	if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
		return -EINVAL;

	pm_suspend_marker("entry");
	error = enter_state(state);
	if (error) {
		suspend_stats.fail++;
		dpm_save_failed_errno(error);
	} else {
		suspend_stats.success++;
	}
	pm_suspend_marker("exit");
	return error;
}
EXPORT_SYMBOL(pm_suspend);
/**
 * enter_state - Do common work needed to enter system sleep state.
 * @state: System sleep state to enter.
 *
 * Make sure that no one else is trying to put the system into a sleep state.
 * Fail if that's not the case.  Otherwise, prepare for system suspend, make the
 * system enter the given sleep state and clean up after wakeup.
 */
static int enter_state(suspend_state_t state)
{
	int error;

	trace_suspend_resume(TPS("suspend_enter"), state, true);
	if (state == PM_SUSPEND_FREEZE) {
#ifdef CONFIG_PM_DEBUG
		if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) {
			pr_warning("PM: Unsupported test mode for freeze state,"
				   "please choose none/freezer/devices/platform.\n");
			return -EAGAIN;
		}
#endif
	} else if (!valid_state(state)) {
		return -EINVAL;
	}
	if (!mutex_trylock(&pm_mutex))
		return -EBUSY;

	if (state == PM_SUSPEND_FREEZE)
		freeze_begin();

	trace_suspend_resume(TPS("sync_filesystems"), 0, true);
	printk(KERN_INFO "PM: Syncing filesystems ... ");
#if MTK_SOLUTION
	error = suspend_syssync_enqueue();
	if (error) {
		pr_err("sys_sync timeout.\n");
		goto Unlock;
	}
#else
	sys_sync();
#endif
	printk("done.\n");
	trace_suspend_resume(TPS("sync_filesystems"), 0, false);

	pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
	error = suspend_prepare(state);
	if (error)
		goto Unlock;

	if (suspend_test(TEST_FREEZER))
		goto Finish;

	trace_suspend_resume(TPS("suspend_enter"), state, false);
	pr_debug("PM: Entering %s sleep\n", pm_states[state]);
	pm_restrict_gfp_mask();
	error = suspend_devices_and_enter(state);
	pm_restore_gfp_mask();

 Finish:
	pr_debug("PM: Finishing wakeup.\n");
	suspend_finish();
 Unlock:
	mutex_unlock(&pm_mutex);
	return error;
}

三、suspend和resume流程

流程图如下所示:

 在suspend中最终进入到syscore_suspend中最后调用到ops->suspend,反之在suspend流程在代码中同样suspend后执行逆向的过程

	
	syscore_resume();
	}

	arch_suspend_enable_irqs();
	BUG_ON(irqs_disabled());

 Enable_cpus:
	enable_nonboot_cpus();

 Platform_wake:
	platform_resume_noirq(state);
	dpm_resume_noirq(PMSG_RESUME);

 Platform_early_resume:
	platform_resume_early(state);

 Devices_early_resume:
	dpm_resume_early(PMSG_RESUME);

 Platform_finish:
	platform_resume_finish(state);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值