(1) 首先需要定义一个驱动设备的资源信息:
struct platform_device { const char * name; u32 id; struct device dev; u32 num_resources; struct resource * resource; }; struct resource { resource_size_t start; resource_size_t end; const char *name; unsigned long flags; struct resource *parent, *sibling, *child; };
例如定义at91网络设备:
static struct resource eth_resources[] = { [0] = { .start = AT91SAM9260_BASE_EMAC, .end = AT91SAM9260_BASE_EMAC + SZ_16K - 1, .flags = IORESOURCE_MEM, }, [1] = { .start = AT91SAM9260_ID_EMAC, .end = AT91SAM9260_ID_EMAC, .flags = IORESOURCE_IRQ, }, }; static struct platform_device at91sam9260_eth_device = { .name = "macb", .id = -1, .dev = { .dma_mask = ð_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = ð_data, }, .resource = eth_resources, .num_resources = ARRAY_SIZE(eth_resources), };
这里定义了IORESOURCE_MEM(IO地址范围)和IORESOURCE_IRQ(中断号)两个资源。这两个资源可以通过调用platform_get_resource和platform_get_irq获取,如:
/* Get I/O base address and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //res是指向struct resource结构的指针。 irq = platform_get_irq(pdev, 0); //irq即是中断号。 //注:platform_get_resource和platform_get_irq的第二个参数是资源的序号。
(2) 添加Platform_device到驱动:
platform_device_register(&at91sam9260_eth_device);
(3) 定义Platform_driver
static struct platform_driver at91ether_driver = { .probe = at91ether_probe, .remove = __devexit_p(at91ether_remove), .suspend = at91ether_suspend, .resume = at91ether_resume, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, }, };
这里指定的DRV_NAME必须和platform_device结构中的name一致,否则不能找到驱动。
(4) 注册platform_driver
static int __init at91ether_init(void) { return platform_driver_register(&at91ether_driver); } static void __exit at91ether_exit(void) { platform_driver_unregister(&at91ether_driver); } module_init(at91ether_init) module_exit(at91ether_exit)
platform_driver_register成功执行后将执行at91ether_probe。
(5) 在at91ether_probe中做驱动的初始化工作。如在at91的mac驱动中初始化一个net_device并调用register_netdev(dev):
static const struct net_device_ops at91ether_netdev_ops = { .ndo_open = at91ether_open, .ndo_stop = at91ether_close, .ndo_start_xmit = at91ether_start_xmit, .ndo_get_stats = at91ether_stats, .ndo_set_multicast_list = at91ether_set_multicast_list, .ndo_set_mac_address = set_mac_address, .ndo_do_ioctl = at91ether_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = at91ether_poll_controller, #endif }; static int __init at91ether_setup( … { struct net_device *dev; … ether_setup(dev); dev->netdev_ops = &at91ether_netdev_ops; /* Register the network interface */ ret = register_netdev(dev); … }