[Linux:Kernel] Linux CPUFreq CPU Drivers

이 문서의 저작권은 GPL 라이센스를 따릅니다.(This document is released under the GPL license.)

             리눅스(TM) 커널 내의 CPU 주파수와 전압 조정 코드


                         L i n u x    C P U F r e q

                           C P U   D r i v e r s 

                           – 개발자를 위한 정보 –


                    Dominik Brodowski  <linux@brodo.de>
                번역: 양정석 <dasomoli@gmailREMOVETHIS.com>



   Clock scaling allows you to change the clock speed of the CPUs on the
    fly. This is a nice method to save battery power, because the lower
            the clock speed, the less power the CPU consumes.


차례:
—–
1.   뭘 해야 하나요?
1.1  초기화
1.2  Per-CPU 초기화
1.3  검증
1.4  target을 쓸까, setpolicy를 쓸까?
1.5  target 호출
1.6  setpolicy 호출
2.   주파수 테이블 헬퍼



1. 뭘 해야 하나요?
==================

그래, 여러분이 막 새 브랜드의 CPU / 칩셋을 데이터 시트와 함께 얻게 됐고,
이 CPU / 칩셋을 위한 cpufreq 지원을 추가하고 싶다고요? 좋습니다. 여기에
필요한 것들에 대한 몇 가지 힌트들이 있어요:


1.1 초기화
———-

무엇보다 먼저, __initcall 레벨 7 (module_init()) 이나 그 이후의 함수 안에서
이 커널이 맞는 CPU와 맞는 칩셋 상에서 실행되는지를 확인하세요. 그렇다면,
struct cpufreq_driver 를 CPUfreq 코어와 함께 cpufreq_register_driver()를
사용해서 등록하세요.

이 struct cpufreq_driver 는 무엇을 포함해야 할까요?

cpufreq_driver.name –           이 드라이버의 이름.

cpufreq_driver.owner –          THIS_MODULE;

cpufreq_driver.init –           per-CPU 초기화 함수로의 포인터.

cpufreq_driver.verify –         “검증” 함수로의 포인터.

cpufreq_driver.setpolicy _또는_ 
cpufreq_driver.target –         아래에서 차이에 대해 살펴보세요.

그리고 옵션으로

cpufreq_driver.exit –           per-CPU 클린업 함수로의 포인터.

cpufreq_driver.resume –         A pointer to a per-CPU resume function
                                which is called with interrupts disabled
                                and _before_ the pre-suspend frequency
                                and/or policy is restored by a call to
                                ->target or ->setpolicy.

cpufreq_driver.resume –         pre-suspend 주파수와(또는) 정책이 ->target
                                이나 ->setpolicy 호출로 복구되기 _전에_
                                인터럽트가 꺼진 상태에서 호출되는 per-CPU
                                resume 함수의 포인터.

cpufreq_driver.attr –           sysfs 로 값을 노출시킬 “struct freq_attr”의
                                NULL로 끝나는 리스트의 포인터.


1.2 Per-CPU 초기화
——————

새 CPU가 디바이스 모델과 등록될 때, 또는 cpufreq 드라이버가 그 스스로를
등록한 후에, per-CPU 초기화 함수 cpufreq_driver.init이 호출됩니다.
그건 struct cpufreq_poliy *policy를 인자로 가져옵니다. 이제 뭘 하죠?

필요하면, 여러분의 CPU 상의 CPUfreq 지원을 활성화하세요.

그러면, 그 드라이버가 다음 값들을 채워넣어야만 합니다:

policy->cpuinfo.min_freq _와_
policy->cpuinfo.max_freq –      이 CPU 가 지원하는 최저/최고 주파수(kHZ)
policy->cpuinfo.transition_latency   이 CPU 상에서 두 주파수 사이에
                                변환되는데 걸리는 나노초 시간(적절하다면
                                맞지만, 아니면 CPUFREQ_ETERNAL 지정).

policy->cur                     (적절하다면) 이 CPU의 현재 동작 주파수
policy->min, 
policy->max, 
policy->policy 그리고, 필요하다면,
policy->governor                이 CPU를 위한 “기본 정책”을 반드시 포함해야
                                함. 조금 지나면, cpufreq_driver.verify와
                                다음 둘 cpufreq_driver.setpolicy 나
                                cpufreq_driver.target 중 하나가 이 값들과
                                함께 호출됩니다.

이들 값들 중 몇을 셋팅하기 위해서 주파수 테이블 헬퍼가 도움이 될 겁니다.
자세한 사항은 섹션 2를 보시면 됩니다.

1.3 검증
——–

사용자가 셋팅하려는 (“policy,governor,min,max”로 구성된) 새로운 정책을
결정하면, 이 정책은 맞지않는 값들이 교정될 수 있도록, 반드시 유효성이
검사되어야 합니다. 이들 값의 검증을 위해서 주파수 테이블 헬퍼와(또는)
cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned
int min_freq, unsigned int max_freq) 함수가 도움이 될 겁니다. 주파수
테이블 헬퍼에 대한 자세항 사항은 섹션 2를 보시면 됩니다.

여러분은 적어도 한 유효한 주파수(또는 동작 범위)를 policy->min 과
policy->max 안에서 확인할 필요가 있습니다. 필요하다면 policy->max 를
먼저 증가시키고, 이게 해결 방법이 아닐 때만 policy->min 을 감소시키세요.


1.4 target을 쓸까, setpolicy를 쓸까?
————————————

대부분의 cpufreq 드라이버나 대부분의 CPU 주파수 조정 알고리즘조차도
한 주파수로만 CPU를 셋팅할 수 있습니다. 이를 위해서 여러분은
->target 함수를 사용합니다.

어떤 cpufreq 가능한 프로세서들은 주파수를 확실한 그들만의 제약사항 사이에서
변환합니다. 이들은 ->setpolicy 함수를 사용하는 것이 좋습니다.

1.4. target 호출
—————-

target 호출은 세가지 인자를 가집니다: struct cpufreq_policy *policy,
unsigned int target_frequency, unsigned int relation.

CPUfreq 드라이버는 여기에서 불려지는 때에 새 주파수를 반드시 셋팅해야
합니다. 실제 주파수는 다음 규칙을 사용해서 결정되어야만 합니다:

– “target_freq” 에 가깝게 유지
– policy->min <= new_freq <= policy->max (이건 반드시 유효해야 합니다!!!)
– relation==CPUFREQ_REL_L 라면, new_freq를 target_freq와 같거나 더 높게 선택
  하도록 시도합니다. (“더 낮은 이 아닌, 최저(lowest)를 위한 L”)
– relation==CPUFREQ_REL_H 라면, new_freq를 target_freq와 같거나 더 낮게 선택
  하도록 시도합니다. (“더 높은 이 아닌, 최고(highest)를 위한 H”)

여기서 다시, 주파수 테이블 헬퍼는 여러분을 도와줄 수 있습니다 – 자세한
사항은 섹션 2를 보세요.


1.5 setpolicy 호출
——————

setpolicy 호출은 오직 struct cpufreq_policy *policy 만 인자로 가집니다.
여러분은 가장 낮은 프로세서 내부나 칩셋 내부 동적 주파수 변환의 더 낮은
제약사항을 policy->min으로, 더 높은 제약사항을 policy->max로, 그리고
-만약 지원한다면- policy->policy 가 CPUFREQ_POLICY_PERFORMANCE 일 때,
성능 지향형 셋팅을, 그리고 CPUFREQ_POLICY_POWERSAVE 일 때, 전력 절약
형 셋팅을 설정할 필요가 있습니다. 또한 drivers/cpufreq/longrun.c 안의
참고 구현을 확인하세요.



2. 주파수 테이블 헬퍼
=====================

대부분의 cpufreq 프로세서들이 몇 가지 지정된 주파수만 셋팅할 수 있는
것처럼, 이런 동작의 “주파수 테이블”은 그 프로세서 드라이버의 어떤 동작에
도움이 될 것입니다. 앞에서 언급된 “주파수 테이블”은 여러분이 사용하길
원하는 “index”내에 어떤 값을, 그리고 “frequency” 안에 해당하는 주파수로 된
struct cpufreq_freq_table 항목의 배열로 구성되어 있습니다. 테이블의 끝에,
여러분은 cpufreq_freq_table 항목의 frequency에 CPUFREQ_TABLE_END로 셋팅할
필요가 있습니다. 그리고 테이블 안의 한 항목을 그냥 넘기길 원한다면,
frequency를 CPUFREQ_ENTRY_INVALID로 셋팅하면 됩니다. 그 항목이 증가하는
순서로 있을 필요는 없습니다.

cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
                                struct cpufreq_frequency_table *table); 의
호출을 통해 cpuinfo.min_freq와 cpuinfo.max_freq 값들이 검출됩니다. 그리고
policy->min 과 policy->max로 같은 값이 셋팅됩니다. 이것은 per-CPU 초기화
단계에서 유용합니다.

int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table);
는 적어도 한 개의 유효한 주파수가 policy->min과 policy->max 안에 있고,
모든 다른 조건들을 만족한다는 것입니다. 이것은 ->verify 호출에서
유용합니다.

int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table,
                                   unsigned int target_freq,
                                   unsigned int relation,
                                   unsigned int *index);

는 ->target 단계를 위한 맞는 주파수 테이블 헬퍼입니다. 그냥 값들을
이 함수로 넘기면 되고, 그 CPU가 셋팅될 주파수를 포함하는 주파수
테이블 항목의 번호를 unsigned int index로 반환합니다. 알림: 이것은
이 cpufreq_table_entry.index 안의 “index”가 아니고,
cpufreq_table[index] 대신입니다. 그래서 새로운 주파수는
cpufreq_table[index].frequency 이고, 여러분이 주파수 테이블 “index”
필드로 저장한 그 값은 cpufreq_table[index].index 입니다. [*]

* 역자 주: 주파수 테이블의 index 라는 이름이 혼동스러워서 driver_data 로
이름이 변경되었습니다. 그래서 이 줄은 문서에서 삭제되었습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다