platform机制将本身的资源注册进内核,由内核统一管理,在驱动程序中使用这些资源时通过platform_device提供的标准接口进行申请并使用。
开发环境:ubuntu 12.04
开发板:龙芯1B开发板
交叉编译工具:gcc-4.3-ls232-softfloat
内核版本:3.0.0
platform的设备可以有两种形式,一种是将设备编译在内核中,在内核初始化的时候,将资源注册到内核里;一种是以加载的方式,将设备资源注册在内核中。
如果是编译在内核中的,就要修改内核中,对应cpu型号的platform.c,以我现在用的龙芯1b开发板为例,打开linux3.0.0/arch/mips/loongson/ls1x/ls1x-board/platform.c,里面的代码大致上分为两大部分,一部分用于定义各个设备结构和资源,以龙芯1b里的pwm设备为例
//分别定义pwm寄存器的首地址,此处地址是物理地址
#define LS1B_PWM0_BASE 0x1fe5c000
#define LS1B_PWM1_BASE 0x1fe5c010
#define LS1B_PWM2_BASE 0x1fe5c020
#define LS1B_PWM3_BASE 0x1fe5c030
//设备的变量
static struct platform_device ls1b_pwm_device = { //定义一个ls1b的pwm的设备
.name = "ls1b-pwm", //设备名称
.id = -1,
.num_resources = ARRAY_SIZE(ls1b_pwm0_resource), //资源数量
.resource = ls1b_pwm0_resource, //资源名称
};
//设备资源
static struct resource ls1b_pwm0_resource[] = { //定义一个ls1b的pwm的资源
[0]={ //因为龙芯1b系列内置四路pwm输出,所以要将每路的资源分别定义
.start = LS1B_PWM0_BASE, //这是pwm0第一个寄存器的物理地址,在这里用的是物理地址而不是
//虚拟地址是因为platform机制是CPU直接寻址设备的寄存器空间
.end = (LS1B_PWM0_BASE + 0x0f), //这是pwm0最后一个寄存器的物理地址
.flags = IORESOURCE_MEM, //标识资源的类型,在这是可直接寻址空间
},
[1]={
.start = LS1B_PWM1_BASE,
.end = (LS1B_PWM1_BASE + 0x0f),
.flags = IORESOURCE_MEM,
},
[2]={
.start = LS1B_PWM2_BASE,
.end = (LS1B_PWM2_BASE + 0x0f),
.flags = IORESOURCE_MEM,
},
[3]={
.start = LS1B_PWM3_BASE,
.end = (LS1B_PWM3_BASE + 0x0f),
.flags = IORESOURCE_MEM,
},
};
第二部分是将定义好的设备添加到platform设备数组里,然后注册到内核中,由内核统一管理。
static struct platform_device *ls1b_platform_devices[] __initdata = {
//将定义好的设备结构添加到该数组中
&ls1b_pwm0_device,
&ls1x_fb0_device,
&ls1b_nand_device,
&ls1b_ohci_device,
&ls1b_ehci_device,
&ls1b_gmac0_mac,
&ls1b_gmac0_phy,
//以下省略其他的设备
};
int __init ls1b_platform_init(void)
{
//在此可以添加一些简单的初始化
return platform_add_devices(ls1b_platform_devices, ARRAY_SIZE(ls1b_platf