本来这些是在上一篇文章的,写着写着感觉太多了,所以单独出来。这篇太基于平台了。
我的是mini2440,如果你不用这个,你就看一下platform_suspend_ops解释。
源码对它解释很详细。简单说一下。
struct platform_suspend_ops {
int (*valid)(suspend_state_tstate);//告诉系统平台是否可以睡眠,enter_state()开始就判断了,我没细说。
int(*begin)(suspend_state_t state);// 睡眠前的一个初始过渡,suspend_devices_and_enter()开始时调用了,这个接口让我们可以把一些需要在系统睡眠前要先睡眠的设备先执行睡眠。
int (*prepare)(void);//就是在begin之后prepare_late之前要做的一些事
int(*prepare_late)(void);//在设备驱动suspend之后,关nonboot-cpus之后执行
int(*enter)(suspend_state_t state);//进入suspend
void (*wake)(void);//唤醒,在开nonboot-cpus之后,设备驱动resume之前执行,对应prepare_late.
void (*finish)(void);//一些系统唤醒后要唤醒的设备,和begin或prepare对应。
bool(*suspend_again)(void);//判断是否要再次睡眠
void (*end)(void);//唤醒设备后通知PM核
void (*recover)(void);//恢复平台如果suspend失败。
};
你可以根据这些给你的系统添加一些关于suspend的硬件操作。
看我的平台
arch/arm/plat-samsung/pm.c
static const struct platform_suspend_opss3c_pm_ops = {
.enter = s3c_pm_enter,
.prepare = s3c_pm_prepare,
.finish = s3c_pm_finish,
.valid =suspend_valid_only_mem,
};
从platform_suspend_ops顺序看
valid:用的是系统提供的。
int suspend_valid_only_mem(suspend_state_tstate)
{
return state == PM_SUSPEND_MEM;
}
简单不说了
prepare:会调用s3c_pm_check_prepare()
arch/arm/plat-samsung/pm-check.c
void s3c_pm_check_prepare(void)
{
crc_size = 0;
s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
S3C_PMDBG("s3c_pm_prepare_check: %uchecks needed\n", crc_size);
crcs = kmalloc(crc_size+4, GFP_KERNEL);
if (crcs == NULL)
printk(KERN_ERR "Cannotallocated CRC save area\n");
}
s3c_pm_run_sysram会调用
staticvoid s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
{
/*
ptr为&iomem_resource
struct resource iomem_resource = {
.name = "PCI mem",
.start = 0,
.end = -1,
.flags = IORESOURCE_MEM,
};
*/
while (ptr != NULL) {
if (ptr->child != NULL)
s3c_pm_run_res(ptr->child, fn, arg);//递归调用
if ((ptr->flags & IORESOURCE_MEM) &&
strcmp(ptr->name, "System RAM") == 0) {
S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
(unsignedlong)ptr->start,
(unsigned long)ptr->end);
arg = (fn)(ptr, arg);
/*
(fn)(ptr, arg);
就是
static u32 *s3c_pm_countram(struct resource *res, u32 *val)
res为
for_each_memblock(memory, region) {
res =alloc_bootmem_low(sizeof(*res));
res->name = "SystemRAM";
res->start =__pfn_to_phys(memblock_region_memory_base_pfn(region));
res->end =__pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
res->flags = IORESOURCE_MEM |IORESOURCE_BUSY;
有很多块mem
val为&crc_size