我已经试的汗流浃背了,但总是觉得不是很清楚。
芯片还没买回来,但又总是感觉不那么对劲。
撇开具体的设备,抽象一点,照我的理解,:
以这个SPI设备为例,
系统初始化时,
(1)向内核注册这些板级信息体
spi_register_board_info(devices, nr_devices);
(2)然后是platform_device注册
platform_device_register(&at91sam9260_spi1_device);
因为用的是atmel的SPI控制器,所以有如下代码
static struct platform_driver atmel_spi_driver = {
.driver = {
.name = "atmel_spi",
.owner = THIS_MODULE,
},
.suspend = atmel_spi_suspend,
.resume = atmel_spi_resume,
.remove = __exit_p(atmel_spi_remove),
};
static int __init atmel_spi_init(void)
{
return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe);
}
module_init(atmel_spi_init);
static void __exit atmel_spi_exit(void)
{
platform_driver_unregister(&atmel_spi_driver);
}
这里主要是针对主控制器的,它的probe函数
static int __init atmel_spi_probe(struct platform_device *pdev)
{
------------------省略-----------------------
ret = spi_register_master(master);
if (ret)
goto out_reset_hw;
return 0;
out_reset_hw:
spi_writel(as, CR, SPI_BIT(SWRST));
clk_disable(clk);
free_irq(irq, master);
out_unmap_regs:
iounmap(as->regs);
out_free_buffer:
dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
as->buffer_dma);
out_free:
clk_put(clk);
spi_master_put(master);
return ret;
}
看下它的调用过程
atmel_spi_probe----->spi_register_master----->scan_boardinfo---->spi_new_device,相应的注释如下:
****************************************************************************
/**
* spi_register_master - register SPI master controller
* @master: initialized master, originally from spi_alloc_master()
* Context: can sleep
*
* SPI master controllers connect to their drivers using some non-SPI bus,
* such as the platform bus. The final stage of probe() in that code
* includes calling spi_register_master() to hook up to this SPI bus glue.
*
* SPI controllers use board specific (often SOC specific) bus numbers,
* and board-specific addressing for SPI devices combines those numbers
* with chip select numbers. Since SPI does not directly support dynamic
* device identification, boards need configuration tables telling which
* chip is at which address.
*
* This must be called from context that can sleep. It returns zero on
* success, else a negative error code (dropping the master's refcount).
* After a successful return, the caller is responsible for calling
* spi_unregister_master().
*/
int spi_register_master(struct spi_master *master)
***************************************************************************
/* FIXME someone should add support for a __setup("spi", ...) that
* creates board info from kernel command lines
*/
static void scan_boardinfo(struct spi_master *master)
{
struct boardinfo *bi;
mutex_lock(&board_lock);
list_for_each_entry(bi, &board_list, list) {
struct spi_board_info *chip = bi->board_info;
unsigned n;
for (n = bi->n_board_info; n > 0; n--, chip++) {
if (chip->bus_num != master->bus_num)
continue;
/* NOTE: this relies on spi_new_device to
* issue diagnostics when given bogus inputs
*/
(void) spi_new_device(master, chip);
}
}
mutex_unlock(&board_lock);
}
****************************************************************************
/**
* spi_new_device - instantiate one new SPI device
* @master: Controller to which device is connected
* @chip: Describes the SPI device
* Context: can sleep
*
* On typical mainboards, this is purely internal; and it's not needed
* after board init creates the hard-wired devices. Some development
* platforms may not be able to use spi_register_board_info though, and
* this is exported so that for example a USB or parport based adapter
* driver could add devices (which it would learn about out-of-band).
*
* Returns the new device, or NULL.
*/
struct spi_device *spi_new_device(struct spi_master *master,
struct spi_board_info *chip)
{
struct spi_device *proxy;
int status;
/* NOTE: caller did any chip->bus_num checks necessary.
*
* Also, unless we change the return value convention to use
* error-or-pointer (not NULL-or-pointer), troubleshootability
* suggests syslogged diagnostics are best here (ugh).
*/
proxy = spi_alloc_device(master);
if (!proxy)
return NULL;
WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
proxy->chip_select = chip->chip_select;
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
proxy->irq = chip->irq;
strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
proxy->dev.platform_data = (void *) chip->platform_data;
proxy->controller_data = chip->controller_data;
proxy->controller_state = NULL;
status = spi_add_device(proxy);
if (status < 0) {
spi_dev_put(proxy);
return NULL;
}
return proxy;
}
******************************************************************************
/**
* spi_add_device - Add spi_device allocated with spi_alloc_device
* @spi: spi_device to register
*
* Companion function to spi_alloc_device. Devices allocated with
* spi_alloc_device can be added onto the spi bus with this function.
*
* Returns 0 on success; negative errno on failure
*/
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
struct device *dev = spi->master->dev.parent;
int status;
/* Chipselects are numbered 0..max; validate. */
if (spi->chip_select >= spi->master->num_chipselect) {
dev_err(dev, "cs%d >= max %d\n",
spi->chip_select,
spi->master->num_chipselect);
return -EINVAL;
}
/* Set the bus ID string */
snprintf(spi->dev.bus_id, sizeof spi->dev.bus_id,
"%s.%u", spi->master->dev.bus_id,
spi->chip_select);
/* We need to make sure there's no other device with this
* chipselect **BEFORE** we call setup(), else we'll trash
* its configuration. Lock against concurrent add() calls.
*/
mutex_lock(&spi_add_lock);
if (bus_find_device_by_name(&spi_bus_type, NULL, spi->dev.bus_id)
!= NULL) {
dev_err(dev, "chipselect %d already in use\n",
spi->chip_select);
status = -EBUSY;
goto done;
}
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
*/
status = spi->master->setup(spi);
if (status < 0) {
dev_err(dev, "can't %s %s, status %d\n",
"setup", spi->dev.bus_id, status);
goto done;
}
/* Device may be bound to an active driver when this returns */
status = device_add(&spi->dev);
if (status < 0)
dev_err(dev, "can't %s %s, status %d\n",
"add", spi->dev.bus_id, status);
else
dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
done:
mutex_unlock(&spi_add_lock);
return status;
}
*******************************************************************************
有如下几个疑问:
(1)设备已经增加到平台设备里面了,平台设备和平台驱动都已经注册,并且在这个主控制器的probe函数里面已经把具体的device设备加进去了,那么我写spi 设备驱动时,比如这里的AD7888,只需要注册driver就行了,不知道我理解的是否对不?但是我对比了其他具体的设备驱动,发现那些设备又注册了一次设备。
(2)按照这样写驱动的话,一些读写及控制函数怎么加进去,我看了一些其他的驱动,
比如一个eeprom驱动
/*
* NOTE: this is an *EEPROM* driver. The vagaries of product naming
* mean that some AT25 products are EEPROMs, and others are FLASH.
* Handle FLASH chips with the drivers/mtd/devices/m25p80.c driver,
* not this one!
*/
struct at25_data {
struct spi_device *spi;
struct mutex lock;
struct spi_eeprom chip;
struct bin_attribute bin;
unsigned addrlen;
};
就把读写函数都放在struct bin_attribute bin;
一个SPI扩展IO芯片MAX7301是这样定义结构体的:
/*
* Some registers must be read back to modify.
* To save time we cache them here in memory
*/
struct max7301 {
struct mutex lock;
u8 port_config[8]; /* field 0 is unused */
u32 out_level; /* cached output levels */
struct gpio_chip chip;
struct spi_device *spi;
};
把控制都放在struct gpio_chip chip;里面了。
而DS1305呢
/* register RTC ... from here on, ds1305->ctrl needs locking */
rtc = rtc_device_register("ds1305", &spi->dev,
&ds1305_ops, THIS_MODULE);
这个比较好理解,就放在ds1305_ops里面了。
于是我打算把这个读写函数放在
struct ad7888_data {
struct spi_device *spi;
struct mutex lock;
};
这个结构体,
我对驱动理解很肤浅,各位提提建议 |