TI中文支持网
TI专业的中文技术问题搜集分享网站

关于dm365/dm368对deepsleep支持

我阅读手册发现dm368是对deepsleep支持的,我用的内核是2.6.32版本,在mach-davinci没有sleep.S和pm.c文件,请问是dm368平台在2.6版本内核不支持deepsleep吗,我根据3.2版本关于da850对于deepsleep实现的sleep.S和pm.c修改,想实现dm368休眠,但是suspend_devices_and_enter–>dpm_suspend_start()–>dpm_suspend–>device_suspend()失败。我想问dm368支持RAM to suspend吗,关于sleep.S pm.c 需要自己编写吗,还是已经实现,如果已经实现在哪里,怎么配置,如何实现 深度休眠

Chris Meng:

Shi Yanlong,

硬件上是支持的。但软件上没有官方支持。

我建议你阅读一下dm36x deepsleep的相关章节,了解进入和退出的流程,重要的是,进入后退出的时候代码必须在芯片内部RAM里面,因为DDR也会需要进入自刷新模式。

user4722282:

回复 Chris Meng:

我已经根据相关文档进行配置,并添加了pm.c和sleep.S,分别实现代码拷贝到sram 和ddr自刷新等,并最为suspend->enter实现函数,但是当进行休眠操作时,内核完成准备,进行挂起时失败,我打开console打印如下

# echo mem > /sys/power/state[ 14.510000] PM: Syncing filesystems … IRQs on FIQs on Mode SVC_32 ISA ARM Segment user[ 14.580000] Control: 0005317f Table: 828a0000 DAC: 00000015[ 14.580000] Process sh (pid: 1003, stack limit = 0xc28d4270)[ 14.580000] Stack: (0xc28d5e48 to 0xc28d6000)[ 14.580000] 5e40: c28d5e6c c28d5e58 c022927c c0226e20 c03ec910 c03f5770[ 14.580000] 5e60: c28d5e9c c28d5e70 c02297f0 c0229254 c2195e60 c21a6858 c0304cac 00000000[ 14.580000] 5e80: 00000003 00000003 c0309610 c292f000 c28d5ebc c28d5ea0 c00d3410 c0229468[ 14.580000] 5ea0: 00000000 00000003 00000003 c0309610 c28d5ed4 c28d5ec0 c00d360c c00d33e0[ 14.580000] 5ec0: c037bcc1 00000003 c28d5efc c28d5ed8 c00d2d60 c00d3570 00000004 c201a570[ 14.580000] 5ee0: c29bc140 c2019640 c03e7d44 c28d5f70 c28d5f0c c28d5f00 c01d5f10 c00d2cd8[ 14.580000] 5f00: c28d5f3c c28d5f10 c014d014 c01d5f00 c28d5f70 c28a5300 4001f000 c28d5f70[ 14.580000] 5f20: 00000004 00000004 c28d4000 00000000 c28d5f6c c28d5f40 c0102f74 c014cf14f50 c00a9020 00000000 00000000 c28a5300 00000004 4001f000[ 14.580000] 5f60: c28d5fa4 c28d5f70 c01030e4 c0102ecc 00000000 00000000 c28d5fa4 00000000[ 14.580000] 5f80: c0110168 00000004 4001f000 401fa5e8 00000004 c008d0c4 00000000 c28d5fa8[ 14.580000] 5fa0: c008cf40 c01030b0 00000004 4001f000 00000001 4001f000 00000004 00000000[ 14.580000] 5fc0: 00000004 4001f000 401fa5e8 00000004 00000004 000dc29c 00000000 00000000[ 14.580000] 5fe0: 4001f000 bea765f0 40138c70 40188abc 60000010 00000001 e59f0b0c ebfe84b4[ 14.580000] Backtrace:[ 14.580000] [<c0226e10>] (platform_pm_suspend+0x0/0x64) from [<c022927c>] (pm_op+0x38/0x7c)[ 14.580000] [<c0229244>] (pm_op+0x0/0x7c) from [<c02297f0>] (dpm_suspend_start+0x398/0x4c8)[ 14.580000] r5:c03f5770 r4:c03ec910[ 14.580000] [<c0229458>] (dpm_suspend_start+0x0/0x4c8) from [<c00d3410>] (suspend_devices_and_enter+0x40/0x190)[ 14.580000] r8:c292f000 r7:c0309610 r6:00000003 r5:00000003 r4:00000000[ 14.580000] [<c00d33d0>] (suspend_devices_and_enter+0x0/0x190) from [<c00d360c>] (enter_state+0xac/0xe8)[ 14.580000] r7:c0309610 r6:00000003 r5:00000003 r4:00000000[ 14.580000] [<c00d3560>] (enter_state+0x0/0xe8) from [<c00d2d60>] (state_store+0x98/0xc0)[ 14.580000] r5:00000003 r4:c037bcc1[ 14.580000] [<c00d2cc8>] (state_store+0x0/0xc0) from [<c01d5f10>] (kobj_attr_store+0x20/0x24)[ 14.580000] [<c01d5ef0>] (kobj_attr_store+0x0/0x24) from [<c014d014>] (sysfs_write_file+0x110/0x148)[ 14.580000] [<c014cf04>] (sysfs_write_file+0x0/0x148) from [<c0102f74>] (vfs_write+0xb8/0x164)[ 14.580000] [<c0102ebc>] (vfs_write+0x0/0x164) from [<c01030e4>] (sys_write+0x44/0x70)[ 14.580000] r8:4001f000 r7:00000004 r6:c28a5300 r5:00000000 r4:00000000[ 14.580000] [<c01030a0>] (sys_write+0x0/0x70) from [<c008cf40>] (ret_fast_syscall+0x0/0x28)[ 14.580000] r8:c008d0c4 r7:00000004 r6:401fa5e8 r5:4001f000 r4:00000004[ 14.580000] Code: bad PC value[ 14.900000] —[ end trace 32fb04b6b288923f ]—

定位代码是在

static int device_suspend(struct device *dev, pm_message_t state){ int error = 0;

down(&dev->sem);

if (dev->class) { if (dev->class->pm) { pm_dev_dbg(dev, state, "class "); error = pm_op(dev, dev->class->pm, state); } else if (dev->class->suspend) { pm_dev_dbg(dev, state, "legacy class "); error = dev->class->suspend(dev, state); suspend_report_result(dev->class->suspend, error); } if (error) goto End; }

if (dev->type) { if (dev->type->pm) { pm_dev_dbg(dev, state, "type "); error = pm_op(dev, dev->type->pm, state); } if (error) goto End; }

if (dev->bus) { if (dev->bus->pm) { pm_dev_dbg(dev, state, ""); error = pm_op(dev, dev->bus->pm, state); } else if (dev->bus->suspend) { pm_dev_dbg(dev, state, "legacy "); error = dev->bus->suspend(dev, state); suspend_report_result(dev->bus->suspend, error); } } End: up(&dev->sem);

return error;}

这个函数出错,当执行if (dev->bus) {if (dev->bus->pm) {pm_dev_dbg(dev, state, "");error = pm_op(dev, dev->bus->pm, state);}这里调用 pm_op(dev, dev->bus->pm, state);

函数代码如下

static int pm_op(struct device *dev, const struct dev_pm_ops *ops, pm_message_t state){ int error = 0;

switch (state.event) {#ifdef CONFIG_SUSPEND case PM_EVENT_SUSPEND: if (ops->suspend) { error = ops->suspend(dev); suspend_report_result(ops->suspend, error); } break; case PM_EVENT_RESUME: if (ops->resume) { error = ops->resume(dev); suspend_report_result(ops->resume, error); } break;#endif /* CONFIG_SUSPEND */#ifdef CONFIG_HIBERNATION case PM_EVENT_FREEZE: case PM_EVENT_QUIESCE: if (ops->freeze) { error = ops->freeze(dev); suspend_report_result(ops->freeze, error); } break; case PM_EVENT_HIBERNATE: if (ops->poweroff) { error = ops->poweroff(dev); suspend_report_result(ops->poweroff, error); } break; case PM_EVENT_THAW: case PM_EVENT_RECOVER: if (ops->thaw) { error = ops->thaw(dev); suspend_report_result(ops->thaw, error); } break; case PM_EVENT_RESTORE: if (ops->restore) { error = ops->restore(dev); suspend_report_result(ops->restore, error); } break;#endif /* CONFIG_HIBERNATION */ default: error = -EINVAL; } return error;}

执行这个函数出错error = ops->suspend(dev);

请问知道为什么吗

Chris Meng:

回复 user4722282:

你好,

抱歉,我没有调试过这部分。

你已经发现执行这个函数出错error = ops->suspend(dev);,你能否再跟进去看看,看看为什么返回错误?

user4722282:

回复 Chris Meng:

你好,我调试休眠过程中发现当suspend davinci_v4l2驱动时出错,于是我不编译/driver/media/davinc/vedio/davinci_dispaly.c可以suspend继续执行,这里我怀疑是空指针,继续运行至davinci_mmc suspend失败,不编译可通过,继续suspend时,驱动vpfe_capture suspend 返回错误,我找到/drive/media/video/davinci/目录,打开vpfe_capture.c 发现关于suspend resume 函数体什么都没写返回值为 -1 ,二高版本返回值为0.于是我改为0,suspend都可以筒过,执行我写的enter函数时,我根据手册设置DDR,然后检测状态判断MCLK是否关闭,总是检测未关闭,导致不能向下执行deepsleep使能。我想请问,我已上方法有什么错误,导致DDR自刷新失败。还有vpfe_capture.c 的suspend为何直接返回0 ,为何没有进行suspend相关操作,这样可以吗,还有davinci_v4l2 及 DaVinci_mmc 为何出现错误?

Chris Meng:

回复 user4722282:

Shi Yanlong,

suspend前,要把所有访问DDR的操作都停止。例如,display如果使能是会自动从你配置的DDR地址拿数据的。capture如果使能写DDR,也是会自动写到DDR相关位置。你能否再检查一下是否还有其他对DDR操作的地方?

user4722282:

回复 Chris Meng:

你好,对于这里我研究并不深,我在通过mem触发休眠时,包括一些准备工作至挂起,是否就是在这些是能禁掉也就是将所有DDR操作停止。可能理解有误,不是的话,请问如何操作在suspend前,要把所有访问DDR的操作都停止,谢谢。期待您的回复!

                                                                                                                                

Chris Meng:

回复 user4722282:

你好,

我没有尝试过suspend,但就原理上讲,suspend前,要把所有访问DDR的操作都停止。

我之前的帖子已经提到了,要关闭display,显示等读写ddr的操作,至于你的系统里面是否还有其他ddr的访问,就需要你来判断了。

user4722282:

回复 Chris Meng:

你好,我理解你的意思,但我不清楚你所说的如display关闭DDR操作如何实现?谢谢!

Chris Meng:

回复 user4722282:

Shi Yanlong,

关闭所有的显示窗口。硬件上就是所有的osd bitmap window/video window都disable。

user4722282:

回复 Chris Meng:

你好,我理解这样可以实现。但是有两个问题,首先可能有很多这类外设,不能一一disable,其次我需要唤醒后可以继续执行我的当前程序,我参考平台下DA850代码好像并未如此(内核3.2以上版本),还有我认为这些DDR进程读写的相管操作,应该由Linux内核源码在suspend准备阶段应该已经实现了,只是我未找到。

还有就是我看dm368官方代码提供了部分平台驱动的suspend resume 相关代码,但是这些代码如果要被调用需要在平台文件调用PM设备操作,但是官方未提供PM 及deepsleep代码,那么那些平台驱动的suspend resume 相关代码,是不是有一些是不可用的,还有一些只提供接口了。如下

在 /driver/media/vedio/davinci/vpfe_capture.c文件

2007 static int vpfe_suspend(struct device *dev)
2008 {
2009return -1;
2010 }
20112012 static int vpfe_resume(struct device *dev)
2013 {
2014return -1;
2015 }
20162017 static const struct dev_pm_ops vpfe_dev_pm_ops = {
2018.suspend = vpfe_suspend,
2019.resume = vpfe_resume,
2020 };
20212022 static struct platform_driver vpfe_driver = {
2023.driver = {
2024.name = CAPTURE_DRV_NAME,
2025.pm = &vpfe_dev_pm_ops,
2026},
2027.probe = vpfe_probe,
2028.remove = vpfe_remove,
2029 };

赞(0)
未经允许不得转载:TI中文支持网 » 关于dm365/dm368对deepsleep支持
分享到: 更多 (0)