리눅스 spi 장치 드라이버에서 프로브 기능은 언제 호출됩니까?
지난 이틀 동안 기기 파일에 미쳐 있었는데, 그것에 대해 많이 알지 못했다고 자책했습니다. 며칠 동안 작업한 끝에 마침내 정리할 수 있었습니다. 장치 등록이 조금 필요합니다. 잊지 않도록 spi 하위 장치 등록을 예로 들어 요약해 보겠습니다.
먼저 spidev 장치 등록을 예로 들어 보겠습니다.
static struct spi_board_info imx5_spi_printer_device[] __initdata =
{
{
p>
.modalias = "spidev",
.max_speed_hz = 8000000,
.bus_num = 1,
. Chip_select = 1,
p>.mode = SPI_MODE_0,
},
};
spi_register_board_info(imx5_spi_printer_device,ARRAY_SIZE(imx5_spi_printer_device) ));
mx5_loco.c 파일에 위의 구조 spi_board_info를 추가합니다. Modalias는 기존 드라이버를 지정해야 합니다. 여기에는 상위 드라이버의 Bus_num이 있어야 합니다. 이는 상위 클래스의 bus_num과 일치해야 합니다. 그렇지 않으면 장치 파일을 생성할 수 없습니다. spi에 클럭 신호가 없으면 버스 번호가 잘못되었을 가능성이 높습니다.
시스템이 시작되면 spidev1.1이라는 장치 파일이 /dev 디렉터리에 나타납니다. 이 파일을 읽고 쓰면 spi 작업을 구현할 수 있습니다.
다음과 같은 경우도 있습니다. :
static struct spi_board_info prt_spi_device[] __initdata = {
{
.modalias = "HotPRT",
.max_speed_hz = 12500000 , /* 최대 spi 클럭(SCK) 속도(HZ) */
.bus_num = 1,
.chip_select = 1,
// . SPI_MODE_0,
.platform_data = 0,
},
};
spi_register_board_info(prt_spi_device, ARRAY_SIZE(prt_spi_device)) ;
Spi 드라이버를 직접 구현한 후 장치 파일을 생성해야 했습니다. 프로브에서 장치 파일 생성이 완료되었습니다.
static struct spi_driver prt_driver = {
.driver = {
.name = "HotPRT",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = prt_probe,
.remove = __devexit_p(prt_remove),
p>
p>
};
spi_register_driver(&prt_driver);
그런데 처음에 프로브를 촉발할 수가 없어서 계속 검색하다가 결국 나는 다음과 같이 프로브의 호출 프로세스를 알고 있었습니다:
int spi_register_driver(struct spi_driver *sdrv)
{
sdrv->driver.bus = &spi_bus_type ;
if (sdrv-> 프로브)
sdrv->driver.probe = spi_drv_probe;
if (sdrv->remove)
sdrv->driver.remove = spi_drv_remove;
p>if (sdrv->종료)
sdrv->driver.shutdown = spi_drv_shutdown;
return driver_register(&sdrv->driver);
}
그런 다음 drivers_register를 호출하세요
intdriver_register( struct device_driver *drv){ p>
int ret;
struct device_driver *other;
BUG_ON(!drv->bus- >p);
if ((drv ->버스->탐색 && drv->탐색) ||
(drv->버스->제거 && drv->제거) ||
(drv->bus- >shutdown && drv->shutdown))
printk(KERN_WARNING "'%s' 드라이버를 업데이트해야 합니다 - 다음을 사용하십시오. "
"bus_type 메소드\n", drv->name) ;
other = 드라이버_find(drv->name, drv->bus);
if (other) {
put_driver(other);
printk(KERN_ERR "오류: '%s' 드라이버가 이미 등록되었습니다. "
"중단하는 중...\n" , drv->이름);
return -EBUSY;
}
ret =bus_add_driver(drv);
if (ret )
ret 반환;
ret = 드라이버_추가_그룹(drv, drv->그룹);
if (ret)
버스_제거_드라이버( drv);
return ret;
p>}
bus_add_driver를 직접 살펴보세요
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = 버스->p- >drivers_kset;
error = kobject_init_and_add(&priv->kobj , &driver_ktype, NULL,
"%s", drv->name);
if ( error)
goto out_unregister;
if (drv->bus->p->drivers_autoprobe) {
error = drivers_attach(drv);
if (오류)
goto out_unregister;
}
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
module_add_driver(drv->owner, drv);
p>
여기서 일부만 가로채고 마지막 호출은 driver_attach입니다.
intdriver_attach( struct device_driver * drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
실제로 작동하는 것은 __driver_attach:
static int __driver_attach(struct device * dev, void * data)
{
입니다. . .
if (!dev->driver)
driver_probe_device(drv, dev);
. . .
}
intdriver_probe_device(struct device_driver * drv, struct device * dev)
{
. . .
//1. 먼저 버스가 일치하는지 확인합니다:
if (drv->bus->match && !drv->bus->match(dev, drv))< / p>
완료;
//2. 구체적으로 프로브를 실행합니다:
ret = really_probe(dev, drv);
. . .
}
really_probe는 우리가 찾고 있는 함수입니다:
static int really_probe(struct device *dev, struct device_driver *drv)
{
. . .
//1. 먼저 드라이버가 속한 버스의 프로브 기능을 호출합니다:
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto|probe_failed;
} else if (drv->probe) {
//2. 그런 다음 드라이버에서 프로브 기능을 호출합니다:
ret = drv->probe(dev);
if (ret)
probe_failed로 이동;
}
. . .
}
그 중 drv->probe(dev)는 실제로 드라이버 구현을 호출하는 특정 프로브 함수입니다. 이 시점에서 프로브 함수가 호출됩니다.
보드 파일에 spi_board_info를 추가하고, 보드 파일에 spi_board_info를 추가하세요