Linux Kernel Porting CPU 方法概要

Linux Kernel Porting CPU是什麼?


      Linux kernel發展至今,除了X86,代碼包中默認支持很多流行的CPU,arch\arm\下可以看到已支持的ARM 架構的CPU。 但是, Linux  kernel代碼包不能做到支持每個CPU, 但是系統提供了一套完整的interface,讓廠商可以更容易的在linux kernel上移植自家的CPU,  讓系統跑起來。


Porting CPU 涉及的重要的點


1. IO 地址映射

    IO地址(如GPIO地址)需要被映射爲虛擬地址,內核通過訪問虛擬地址去訪問IO。虛擬地址段建議處於第4G的頂部。

    比如某32位處理器某GPIO物理地址是0x25000000, 內核中不能用物理地址去訪問,value = *(volatile)(unsigned int *)0x25000000內核認爲是非法的地址訪問。 正確的訪問方法是,首先0x25000000 映射到第4G空間的一個虛擬地址,如0xf4000000,  通過虛擬地址訪問GPIO,value = *(volatile)(unsigned int *)0xf4000000是合法的。


2. 中斷系統初始化,重寫操作函數

     Linux是一個開源的os,  支持X86,ARM等架構。對於中斷,先對其抽象,然後設計出一套通用的框架,即中斷子系統。對外,爲驅動開發者提供統一的內核API;對內,子系統必須提供接口支持和具體的硬件操作相關聯,常用函數指針來實現。所以具體的CPU,都需要重寫操作函數,中斷系統才能正確的操作中斷相關的寄存器。


3. 註冊時鐘源

     linux 新版中有時鐘源的概念,總線時鐘多被抽象爲時鐘源,如果CPU核的clock, IIC,SPI的時鐘可以抽象爲時鐘源。


4.  CPU頻率調節,重寫操作函數

     頻率調節是CPU一個重要的功能,是通過設置reg實現的,需要重寫操作函數實現設置reg的具體方法


Porting CPU 涉及的重要的數據結構

1. IO 地址映射

(1) 填充關鍵數據結構

struct map_desc {
unsigned long virtual;                        //首個IO 物理地址對應的虛擬地址
unsigned long pfn;                             //首個IO 物理地址page frame num
unsigned long length;                         //映射總長度
unsigned int type;
};


(2) 註冊 map_desc數據結構

iotable_init(struct map_desc *io_desc, int nr)

       (1) map_desc可描述地址連續的IO地址空間,即一段IO地址

       (2) 內核空間可以通過virtual訪問 IO


2. 中斷系統初始化,設置回調函數

(1) 填充關鍵數據結構 struct irq_chip


根據CPU設計一貫方法看,下面的四個回調函數是最小集合

函數指針 功能描述
void(*irq_ack)(...) clear irq
void(*irq_mask)(...) mask irq
void(*irq_unmask)(...) unmask irq

 
int    (*irq_set_type)(struct irq_data *data, unsigned int flow_type);  //不是必須,但是常用(設置觸發方式)


(2) 註冊函數

irq_set_chip_and_handler(unsigned int irq, struct irq_chip *chip, irq_flow_handler_t handle)

     中斷號和中斷操作函數,中斷handle三者相關聯,並註冊。完成註冊後,調用set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);  系統才認爲irq是激活的


3. 註冊時鐘源

(1) 關鍵數據結構struct clk_lookup

(2) 向系統註冊struct clk_lookup

     clkdev_add(struct clk_lookup *cl)  //添加時鐘源 clk_lookup

     (1)  struct clk結構的定義請另外參考,不做說明。 需要什麼數據結構,就定義什麼,然後填充,linux 開發方法大多如此


4. 設置 CPU頻率調節回調函數


(1) 填充關鍵數據結構struct cpufreq_driver


下面的項是必須要填充(所謂必須,也未必,只是通常都會)的:

struct module           *owner;

u8                              flags

char                           name[cpufreq_name_len];

int  (*init)      (...)

int(*verify)    (...)

unsigned int  (*get)   (...)

int  (*target)  (...)

unsigned int  (*get)  (...)



(2) 向系統註冊數據結構struct cpufreq_driver

int cpufreq_register_driver(struct cpufreq_driver *driver_data)



發佈了32 篇原創文章 · 獲贊 7 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章