/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void __init
smdk6410_machine_init(void)
{
spi_register_board_info(
sam_spi_devs, ARRAY_SIZE(
sam_spi_devs));
platform_add_devices(
smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
第12章:和platform_driver对应这一个platform_device一样,spi_driver也对应着一个
spi_device;platform_device需要在BSP的板文件中添加板信息数据,而spi_device也同样需要。spi_device
的板信息用spi_board_info结构体描述,该结构记录着spi外设使用的主机控制器(spi_master)序号,片选序号,数据比特
率,spi传输模式(CPOL,CPHA)
static struct spi_board_info __initdata
sam_spi_devs[] = {
[0] = {
////设备与驱动匹配的唯一标识
.modalias = "
spidev", /* Test Interface */
.mode = SPI_MODE_2, /* CPOL=1, CPHA=0 */
.max_speed_hz = 2468013,
/* Connected to SPI-0 as 1st Slave */
.bus_num = 0,
.irq = IRQ_SPI0,
.chip_select = 0,
// .controller_data = (void *)&spidev_b0_cs0,
},
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*---------------------------------------------------------------------------*/
/*
* INTERFACE between board init code and SPI infrastructure.
*
* No SPI driver ever sees these SPI device table segments, but
* it's how the SPI core (or adapters that get hotplugged) grows
* the driver model tree.
*
* As a rule, SPI devices can't be probed. Instead, board init code
* provides a table listing the devices which are present, with enough
* information to bind and set up the device's driver. There's basic
* support for nonstatic configurations too; enough to handle adding
* parport adapters, or microcontrollers acting as USB-to-SPI bridges.
*/
/**
* struct spi_board_info - board-specific template for a SPI device
* @modalias: Initializes spi_device.modalias; identifies the driver.
* @platform_data: Initializes spi_device.platform_data; the particular
* data stored there is driver-specific.
* @controller_data: Initializes spi_device.controller_data; some
* controllers need hints about hardware setup, e.g. for DMA.
* @irq: Initializes spi_device.irq; depends on how the board is wired.
* @max_speed_hz: Initializes spi_device.max_speed_hz; based on limits
* from the chip datasheet and board-specific signal quality issues.
* @bus_num: Identifies which spi_master parents the spi_device; unused
* by spi_new_device(), and otherwise depends on board wiring.
* @chip_select: Initializes spi_device.chip_select; depends on how
* the board is wired.
* @mode: Initializes spi_device.mode; based on the chip datasheet, board
* wiring (some devices support both 3WIRE and standard modes), and
* possibly presence of an inverter in the chipselect path.
*
* When adding new SPI devices to the device tree, these structures serve
* as a partial device template. They hold information which can't always
* be determined by drivers. Information that probe() can establish (such
* as the default transfer wordsize) is not included here.
*
* These structures are used in two places. Their primary role is to
* be stored in tables of board-specific device descriptors, which are
* declared early in board initialization and then used (much later) to
* populate a controller's device tree after the that controller's driver
* initializes. A secondary (and atypical) role is as a parameter to
* spi_new_device() call, which happens after those controller drivers
* are active in some dynamic board configuration models.
*/
struct spi_board_info {
/* the device name and module name are coupled, like platform_bus;
* "modalias" is normally the driver name.
*
* platform_data goes to spi_device.dev.platform_data,
* controller_data goes to spi_device.controller_data,
* irq is copied too
*/
//
//设备与驱动匹配的唯一标识
char modalias[32];
const void *platform_data;
void *controller_data;
int irq;
/* slower signaling on noisy or low voltage boards */
u32 max_speed_hz;
/* bus_num is board specific and matches the bus_num of some
* spi_master that will probably be registered later.
*
* chip_select reflects how this chip is wired to that master;
* it's less than num_chipselect.
*/
//
//设备所归属的总线编号
u16 bus_num;
u16 chip_select;
/* mode becomes spi_device.mode, and is essential for chips
* where the default of SPI_CS_HIGH = 0 is wrong.
*/
u8 mode;
/* ... may need additional spi_device chip config data here.
* avoid stuff protocol drivers can set; but include stuff
* needed to behave without being bound to a driver:
* - quirks like clock rate mattering when not selected
*/
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static struct
platform_device *smdk6410_devices[] __initdata = {
&s3c_device_i2c0,
&s3c_device_spi0,
&s3c_device_spi1,
&s3c_device_keypad,
&s3c_device_ts,
&s3c_device_dm9000_cs1,
&s3c_device_nand,
&s3c_device_usb,
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* SPI (0) */
static struct resource
s3c_spi0_resource[] = {
[0] = {
.start = S3C_PA_SPI0,
.end = S3C_PA_SPI0 + S3C_SZ_SPI0 - 1,
.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 = "
sam-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);
/* SPI (1) */
static struct resource s3c_spi1_resource[] = {
[0] = {
.start = S3C_PA_SPI1,
.end = S3C_PA_SPI1 + S3C_SZ_SPI1 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_SPI1,
.end = IRQ_SPI1,
.flags = IORESOURCE_IRQ,
}
};
static u64 s3c_device_spi1_dmamask = 0xffffffffUL;
struct platform_device
s3c_device_spi1 = {
.name = "sam-spi",
.id = 1,
.num_resources = ARRAY_SIZE(
s3c_spi1_resource),
.resource = s3c_spi1_resource,
.dev = {
.dma_mask = &s3c_device_spi1_dmamask,
.coherent_dma_mask = 0xffffffffUL
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define S3C_PA_SPI S3C64XX_PA_SPI
#define S3C_PA_SPI0 S3C64XX_PA_SPI0
#define S3C_PA_SPI1 S3C64XX_PA_SPI1
#define S3C_SZ_SPI S3C64XX_SZ_SPI
#define S3C_SZ_SPI0 S3C64XX_SZ_SPI0
#define S3C_SZ_SPI1 S3C64XX_SZ_SPI1
/* SPI */
#define S3C64XX_PA_SPI (0x7F00B000)
#define S3C64XX_PA_SPI0 (0x7F00B000)
#define S3C64XX_PA_SPI1 (0x7F00C000)
#define S3C64XX_SZ_SPI SZ_8K
#define S3C64XX_SZ_SPI0 SZ_4K
#define S3C64XX_SZ_SPI1 SZ_4K
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////