您的位置:首页 > 运维架构 > Linux

Linux Kernel Porting CPU 方法概要

2013-11-21 12:58 281 查看
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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: