2009年3月24日 星期二

platform_device & platform_driver

porting PCI driver to platform driver

Function
PCI device & driver
platform device & driver
device structure struct pci_devstruct platform_device
device registration & enumerationN/A
(already defined by physical device, and enumerated by XXXX)
platform_device_register
platform_add_devices
driver structure struct pci_driverstruct platform_driver
driver registration pci_register_driverplatform_driver_registe
platform_driver_probe
device class specific data in single driverpci_driver -> (struct pci_device_id) pci_ids -> (kernel_ulong_t) driver_data N/A
(so there is no place in platform device to hold currently the driver_data carried by pci_device_id)
driver unregistration pci_unregister_driverplatform_driver_unregister
get driver private datapci_get_drvdataplatform_get_drvdata
set driver private datapci_set_drvdataplatform_set_drvdata
driver probeinclude/linux/pci.h: int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
Device ID specific data could be carried by id->device_data within the same pci driver.
include/linux/platform_device.h: int (*probe)(struct platform_device *);
get device resourceBAR0~5
pci_resource_flags
pci_resource_len
platform_get_resource
get device irqpdev -> irqplatform_get_irq

* one thing I think platform_device is not convenient is that, it has no way to take a device specific data, so I can't just write a generic platform_driver and uses different platform_device with only a small change. for example, sdhci_pci_fixes role in provided in pci_device_id -> driver_data of SDHCI PCI driver (sdhci-pci.c).


static struct resource xxxxx_resource[] = {
[0] = {
.start = 0x80000000,
.end = 0x80000000+0x100,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 41,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device xxxxx_device = {
.name = "xxxxx-i2c",
.num_resources = 2,
.resource = xxxxx_i2c_resource,
};


static struct platform_driver xxxxx_platform_driver = {
.remove = __exit_p(xxxxx_platform_remove),
.suspend = xxxxx_platform_suspend,
.resume = xxxxx_platform_resume,
.driver = {
.name = "xxxxx-platform",
.owner = THIS_MODULE,
},
};


platform_driver_probe(&xxxxx_platform_driver, xxxxx_platform_probe);
platform_driver_unregister(&xxxxx_platform_driver);

regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->regs = ioremap(regs->start, regs->end - regs->start + 1);
irq = platform_get_irq(pdev, 0);


Documentation/driver-model/platform.txt

platform_device和platform_driver(一)
http://blog.chinaunix.net/u1/57747/showart_1073860.html

platform_device和platform_driver(二)
http://blog.chinaunix.net/u1/57747/showart.php?id=1074059

linux resouce,platform_device和platform_driver驱动的关系
http://blog.chinaunix.net/u1/49507/showart_494193.html

linux kernel 2.6.24.3 platform device driver
http://top12345tw.blogspot.com/2008/03/linux-kernel-26243-platform-device.html

platform _device和platform_driver注册过程
http://blog.chinaunix.net/u2/60011/showart.php?id=1018999

沒有留言: