内核版本:linux-2.6.32.2 实验平台:mini2440
1. 添加平台设备支持
s3c2440有两个SPI主控制器,这里只以SPI0为例,平台设备定义如下(plat-s3c24xx/devs.c):
/* SPI (0) */
static struct resource s3c_spi0_resource[] = {
[0] = {
.start = S3C24XX_PA_SPI,
.end = S3C24XX_PA_SPI + 0x1f,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_SPI0,
.end = IRQ_SPI0,
.flags = IORESOURCE_IRQ,
}
};
static u64 s3c_device_spi0_dmamask = 0xffffffffUL;
struct platform_device s3c_device_spi0 = {
.name = "s3c2410-spi",
.id = 0,
.num_resources = ARRAY_SIZE(s3c_spi0_resource),
.resource = s3c_spi0_resource,
.dev = {
.dma_mask = &s3c_device_spi0_dmamask,
.coherent_dma_mask = 0xffffffffUL
}
};
EXPORT_SYMBOL(s3c_device_spi0);
那么在注册这个平台设备之前,需要为平台设备定义好一组数据,定义如下(mach-s3c2440/mach-mini2440.c):
static struct s3c2410_spi_info mini2440_spi0_platdata = {
.pin_cs = S3C2410_GPG(2),
.num_cs = 1,
.bus_num = 0,
.gpio_setup = s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,
};
结构struct s3c2410_spi_info定义在文件mach-s3c2410/include/mach/spi.h中,定义如下:
struct s3c2410_spi_info {
int pin_cs; /* simple gpio cs */
unsigned int num_cs; /* total chipselects */
int bus_num; /* bus number to use. */
void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable);
void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
};
pin_cs:从设备片选信号线,由主控制器决定从设备是否可用,从而使得一个SPI主控制器对应多个从设备成为可能,但是不清楚为什么定义在该结构中,而且只有一个。
num_cs:片选信号线数量。
bus_num:SPI控制器总线号。
gpio_setup:配置gpio口的函数指针。
set_cs:用于使能片选的函数指针。
再来看mini2440中对spi0的定义。
pin_cs:使用的GPG2引脚。
num_cs:片选信号线数量为1。
bus_num:使用的是总线SPI0。
gpio_setup,使用的函数是s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,函数如下(plat-s3c24xx/spi-bus0-gpe11_12_13.c):
void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi,
int enable)
{
if (enable) {
s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
s3c2410_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
s3c2410_gpio_pullup(S3C2410_GPE(11), 0);
s3c2410_gpio_pullup(S3C2410_GPE(13), 0);
} else {
s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT);
s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT);
s3c2410_gpio_pullup(S3C2410_GPE(11), 1);
s3c2410_gpio_pullup(S3C2410_GPE(12), 1);
s3c2410_gpio_pullup(S3C2410_GPE(13), 1);
}
}
因为GPE11、GPE12和GPE13是多功能引脚,即可作为普通GPIO口来使用,也可作为SPI控制来使用,所以需要对其做配置。这里在使能配置时,首先将GPIO口配置成SPI控制器,然后取消GPE11和GPE13的上拉。
set_cs未被设置。
将这组平台设备数据赋值给平台设备:
s3c_device_spi0.dev.platform_data = &mini2440_spi0_platdata;
将s3c_device_spi0这个平台设备添加到mini2440_devices这个数组中,以便完成平台设备的注册:
static struct platform_device *mini2440_devices[] __initdata = {
/* ... */
&s3c_device_spi0,
/* ... */
};
最后别忘了需要包含头文件<mach/spi.h>
2. 内核配置
在配置之前,需要先修改plat-s3c24xx/Kconfig,patch如下:
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index 9c7aca4..b877cd9 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -129,7 +129,7 @@ config S3C24XX_ADC
# SPI default pin configuration code
config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13
- bool
+ bool "SPI0 pin configuration"
help
SPI GPIO configuration code for BUS0 when connected to
GPE11, GPE12 and GPE13.
然后配置内核:
System Type ---> [*] SPI0 pin configuration Device Drivers ---> [*] SPI support ---> <*> Samsung S3C24XX series SPI