网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
static const struct spi_device_id spidev_spi_ids[] = {
{ .name = "dh2228fv" },
{ .name = "ltc2488" },
{ .name = "sx1301" },
{ .name = "bk4" },
{ .name = "dhcom-board" },
{ .name = "m53cpld" },
{ .name = "spi-petra" },
{ .name = "spi-authenta" },
{},
};
MODULE_DEVICE_TABLE(spi, spidev_spi_ids);
匹配成功后spidev.c里面的spidev_probe就会被调用。
spidev_spi_driver源码分析
spidev_spi_driver源码具体实现如下:
static struct spi_driver spidev_spi_driver = {
.driver = {
.name = "spidev",
.of_match_table = spidev_dt_ids,
.acpi_match_table = spidev_acpi_ids,
},
.probe = spidev_probe,
.remove = spidev_remove,
.id_table = spidev_spi_ids,
/* NOTE: suspend/resume methods are not necessary here.
* We don't do anything except pass the requests to/from
* the underlying controller. The refrigerator handles
* most issues; the controller driver handles the rest.
*/
};
其中spidev_probe的具体实现如下:
static int spidev_probe(struct spi_device *spi)
{
int (*match)(struct device *dev);
struct spidev_data *spidev;
int status;
unsigned long minor;
match = device_get_match_data(&spi->dev);
if (match) {
status = match(&spi->dev);
if (status)
return status;
}
/* Allocate driver data */
spidev = kzalloc(sizeof(*spidev), GFP_KERNEL); /* 分配结构体 */
if (!spidev)
return -ENOMEM;
/* Initialize the driver data */
spidev->spi = spi; /* spidev_data里面记录spi-device结构体 */
spin_lock_init(&spidev->spi_lock);
mutex_init(&spidev->buf_lock);
INIT_LIST_HEAD(&spidev->device_entry);
/* If we can allocate a minor number, hook up this device.
* Reusing minors is fine so long as udev or mdev is working.
*/
mutex_lock(&device_list_lock);
minor = find_first_zero_bit(minors, N_SPI_MINORS); /* 找到一个空闲的次设备号 */
if (minor < N_SPI_MINORS) {
struct device *dev;
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
dev = device_create