在跟踪reboot("recovery")到底层之后,发现有函数static void rk30_arch_reset(char mode, const char *cmd);
在此函数中有大量对writel_relaxed的调用。找到这个链接,学习一下。
以下内容转自: http://blog.youkuaiyun.com/hzpeterchen/article/details/7771795
因为对别的平台不了解,下面仅谈它们在ARM上的区别
__raw_writel: 因为有volatile关键字, 所以编译器不会打乱多个__raw_writel的执行顺序。
对于ARM而言,当多个写以代码的顺序到达相同设备时,执行的顺序也是被保证的,不过
对于不同的设备,执行的顺序就不被保证了。
write_relaxed: 在ARM平台上与__raw_writel一样,因为与__raw_writel相比,它只多做
了一个大端到小端转换。
writel: 当CONFIG_ARM_DMA_MEM_BUFFERABLE被定义时,在写之前,它会多做
一个DSB和L2的sync。 为什么需要这样呢? 因为,DMA buffer都是 bufferable了,
(详见加入CONFIG_ARM_DMA_MEM_BUFFERABLE的commit log)
在DMA进行之前要保证write buffer里的数据都到memory里。
所以说: 只有在有DMA操作的代码里,writel才是必须的,其实它是一个
当DMA buffer变成bufferable之后的一个补充品。因为要保证DMA buffer里的
内容在DMA开始之前都到memory里,所以开始DMA的指令(writel)里加了
sync memory的指令。
其实: writel也不能保证写的东西一定完成,它只能保证写的指令或写的内容
已经到了设备端,但具体有没有写完成是不知道的。如果有一定要设备端
写完成才能做下面的指令的要求,最好再用readl把它读回来。