有人可以解释一下 exynos ARM 中的电源控制寄存器吗? [英] Can someone explain the power control register in exynos ARM?

查看:14
本文介绍了有人可以解释一下 exynos ARM 中的电源控制寄存器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Linux内核中,更准确的/arch/arm/mach-exynos/cpuidle.c 在 3.9-rc6 上,这些行是

static unsigned int g_pwr_ctrl, g_diag_reg;静态无效 save_cpu_arch_register(void){/*读取功率控制寄存器*/asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : "cc");/*读取诊断寄存器*/asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");返回;}

研究该问题后,这似乎是gcc 内联 程序集.考虑到它是一个关键组件,asm 正在读取它,因为它要么是

  1. 更快,因此效率更高
  2. 在 C 中不可用

我检查了 ARMMCR 的手册,因为我正在学习汇编,但我可以告诉 MCR 是一个协处理器,因为它的三个字母长度.内联汇编似乎访问 电源控制寄存器并将结果(来自寄存器)保存到第一行的无符号整数中(我希望在某个时候调用).

关于功率控制寄存器,arm手册列出,

  • 实现 Cortex-A9 处理器的时钟延迟
  • 动态时钟门控.

我无法理解为什么需要这样做,这可以在函数中即时访问.

最后,ARM 手册列出了 32 位宽寄存器的设计.基本时钟似乎设置在那里,我们是在从空闲上下文进程启动时读取此信息吗?

我还发现了一个 类似问题 - 这也可能对您有所帮助.

解决方案

您的问题确实缺乏重点,请考虑更新.我假设您正在尝试了解 Linux 内核中的 exynos 挂起/恢复机制.

为什么使用内联汇编器

<块引用>

...这似乎是 gcc 内联 程序集.考虑到它是一个关键组件,asm 正在阅读它,因为它要么
a) 更快,因此更高效;
b) 在 C 中不可用

我们选择选项b,在C中没有办法表达mcr/mrc.>

内联破坏者列表

<块引用>

其次... : : "cc");

这是一个 gcc 破坏列表.它说条件代码将被指令改变.这可能只是为了确保 gcc 决定不丢弃该指令.您可以在gcc 手册中阅读更多内容.

这是在做什么

<块引用>

我无法理解为什么需要这样做,这可以在函数中即时访问.

您需要查看的部分是exynos4_enter_core0_aftr().这使用了 save_cpu_arch_register()restore_cpu_arch_register().因此,有一组双重函数,我们注意到这些值存储在 globals 中.另一件需要注意的是cpu_suspend(0, idle_finisher);.这个函数告诉 Linux cpu 挂起,然后调用 cpu_do_idle(); 这通常是一个 ARM WFI (等待中断) 指令.这使得 CPU 在该指令处冻结,直到触发启用的中断.全速挂起 CPU 时钟的问题是这会浪费一些电流/功率.通常,在这种模式下,SDRAM 和平台时钟可能会自动进入低功耗状态.

您必须查阅 CPU/SOC 上的数据表以了解更多信息.然而,回到问题.这种低功耗模式很可能会破坏/更改这些协处理器寄存器,因此需要 save_cpu_arch_register()restore_cpu_arch_register() 以确保它们保持原样电话.代码可能会在 exynos4_enter_core0_aftr() 中使用局部变量.它们确实需要保存和恢复,否则 CPU 可能会以奇怪的电源/电压/时钟恢复.也可能是 cpu_do_idle() 被你的机器覆盖了,它正在改变这些寄存器.

简单来说,这个函数是为了保存一些状态,当 CPU 进入暂停等待中断模式时,这些状态会被破坏.

In the Linux kernel, more accurately /arch/arm/mach-exynos/cpuidle.c on 3.9-rc6, the lines reads

static unsigned int g_pwr_ctrl, g_diag_reg;

static void save_cpu_arch_register(void)
{
    /*read power control register*/
    asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
    /*read diagnostic register*/
    asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
    return;
}

After researching the issue, this appears to be gcc inline assembly. Considering it's a critical component, the asm is reading this as it's either

  1. Faster, and therefore more efficient
  2. Not available in C

I checked the ARM Manual for MCR as I'm learning assembly, but I could tell MCR was a Coprocessor due to its three letter length. The inline asm appears to access the power control register and save the result (from the register) into an unsigned integer in the first line (to be called up at some point, I expect).

In regards to the power control register, the arm manual lists,

  • the clock latency for your implementation of the Cortex-A9 processor
  • dynamic clock gating.

I'm having trouble understanding why this is needed at-all, this can be accessed on the fly, in a function.

Lastly, the ARM Manual lists the design of the 32bit wide register. The base-clock appears to be set there, are we reading this while starting up from an idle context process?

I have also found a similar question - this may also help you.

解决方案

Your question does lack focus, please consider updating it. I will assume that you are trying to understand the exynos suspend/resume mechanism in the Linux kernel.

Why Inline assembler

... this appears to be gcc inline assembly. Considering it's a critical component, the asm is reading this as it's either
a) faster, and therefore more efficient;
b) not available in C

We choose option b, there is no way to express mcr/mrc in C.

Inline clobber list

Secondly, ... : : "cc");

This is a gcc clobber list. It says that the condition codes will be altered by the instruction. This maybe just to ensure that gcc decides not to discard this instruction. You can read more in the gcc manual.

What is this doing

I'm having trouble understanding why this is needed at-all, this can be accessed on the fly, in a function.

The portion you need to look at is exynos4_enter_core0_aftr(). This uses both save_cpu_arch_register() and restore_cpu_arch_register(). So, there is a dual set of functions and we note that the values are stored in globals. The other thing to note is the cpu_suspend(0, idle_finisher);. This function tells Linux the cpu is suspended and then calls cpu_do_idle(); which is usually an ARM WFI (wait for interrupt) instruction. This makes the CPU freeze at that instruction until an enabled interrupt triggers. The issue with suspending a CPU clock at full speed, is this can waste some current/power. Typically, SDRAM and platform clocks maybe automatically put to in low power states in this mode.

You will have to consult the data sheets on your CPU/SOC for more. However, back to the question. It is most likely that this low power mode destroys/alters these co-processor registers, so save_cpu_arch_register() and restore_cpu_arch_register() are needed to ensure they remain as they were before the call. The code could probably use locals in exynos4_enter_core0_aftr(). They do need to be saved and restored or the CPU may resume with weird power/voltage/clocks. It could also be that cpu_do_idle() is over-ridden for your machine and it is altering these registers.

So briefly, this function is to save some state that will be destroyed when the CPU goes to suspend or wait for interrupt mode.

这篇关于有人可以解释一下 exynos ARM 中的电源控制寄存器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆