arch\arm\mach-zynq\pl330.c#define DRIVER_NAME "pl330" /////////////static struct platform_driver pl330_platform_driver ={ .probe = pl330_platform_probe, //匹配到的时候调用 .remove =pl330_platform_remove, .driver = { .name = DRIVER_NAME, .owner =THIS_MODULE, },};////////////////////static int __initpl330_init(void){ int status; pl330_driver_init(); status =platform_driver_register(&pl330_platform_driver); PDEBUG("platform_driver_register:%d\n", status); return status;}module_init(pl330_init);/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////** *pl330_driver_init - Initialize the dma_struct array and store thepointer * to array */arch\arm\mach-zynq\pl330.cstatic void pl330_driver_init(void){ unsigned inti; PDEBUG("inside pl330_driver_init, dma_chan is %x\n", (unsignedint)dma_chan); driver_data.dma_chan = dma_chan; memset(dma_chan, 0, sizeof(dma_chan[MAX_DMA_CHANNELS])); for (i = 0; i dma_chan[i].d_ops =&pl330_ops; isa_dma_add(i, dma_chan+ i); }}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////** *pl330_platform_probe - Platform driver probe * @pdev: Pointer to theplatform device structure * * Returns 0 on success, negative errorotherwise */arch\arm\mach-zynq\pl330.cstatic int __devinit pl330_platform_probe(struct platform_device*pdev){ int pdev_id; if (!pdev) { dev_err(&pdev->dev, "pl330 probe calledwith NULL param.\n"); return -ENODEV; } PDEBUG("pl330 driver probing dev_id %d\n",pdev->id); pdev_id = 0; if (pdev->id pdev_id = 0; }else if (pdev->id pdev_id = pdev->id; }else { dev_err(&pdev->dev, "pl330 device id exceeds thesupported number.\n"); return -ENODEV; } pl330_init_device_data(pdev_id, pdev); /* assume the init_device_data is invoked before this point*/ pl330_init_channel_static_data(pdev_id); /* setup the default burst size*/ pl330_set_default_burst_size(pdev_id); /* request irq */ if (pl330_request_irq(pdev_id)) { pl330_release_io(pdev, pdev_id); return-1; } printk(KERN_INFO "pl330 dev %d probe success\n",pdev->id); return0;} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////** *pl330_request_irq - set up the interrupt handler for thecorresponding * device. It sets up all the interrupt for all the channels ofthat * device. It also sets the the fault interrupt handler for thedevice. * @dev_id: device id. * * Returns 0 on success, otherwise onfailure */int pl330_request_irq(unsigned int dev_id){ unsigned intirq; unsigned int irq2; struct pl330_channel_static_data*channel_static_data; struct pl330_device_data *device_data= driver_data.device_data + dev_id; int status; PDEBUG("PL330 requesting irq for device %d\n",dev_id); channel_static_data = driver_data.channel_static_data +device_data->starting_channel; irq = device_data->fault_irq; /* set up the fault irq */ status = request_irq(irq, pl330_fault_isr, IRQF_DISABLED, DRIVER_NAME, device_data);//irq是要申请的硬件中断号。handler是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。irqflags是中断处理的属性,若设置了IRQF_DISABLED(老版本中的SA_INTERRUPT,本版zhon已经不支持了),则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了IRQF_SHARED(老版本中的SA_SHIRQ),则表示多个设备共享中断,若设置了IRQF_SAMPLE_RANDOM(老版本中的SA_SAMPLE_RANDOM),表示对系统熵有贡献,对系统获取随机数有好处。(这几个flag是可以通过或的方式同时使用的)devname设置中断名称,通常是设备驱动程序的名称 在cat/proc/interrupts中可以看到此名称。 dev_id在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL。//// if (status) { printk(KERN_ERR "PL330 request fault irq %dfailed %d\n", irq, status); return -1; } else{ PDEBUG("PL330 request fault irq %d successful\n",irq); } for (irq = device_data->starting_irq; irq != 0&& irq ending_irq; irq++) { /* set up the done irq */ status = request_irq(irq,pl330_done_isr, IRQF_DISABLED, DRIVER_NAME, channel_static_data); if (status) { printk(KERN_ERR "PL330 request done irq%d failed %d\n", irq, status); gotoreq_done_irq_failed; } else { channel_static_data->irq =irq; PDEBUG("PL330 request done irq %d successful\n", irq); } channel_static_data++; } for (irq = device_data->starting_irq1; irq != 0 && irqending_irq1; irq++) { /* set up the done irq */ status = request_irq(irq,pl330_done_isr, IRQF_DISABLED, DRIVER_NAME, channel_static_data); if (status) { printk(KERN_ERR "PL330 request done irq%d failed %d\n", irq, status); gotoreq_done_irq1_failed; } else { channel_static_data->irq =irq; PDEBUG("PL330 request done irq %d successful\n", irq); } channel_static_data++; } return 0; req_done_irq1_failed: for (irq2 =device_data->starting_irq1; irq2 free_irq(irq2, channel_static_data); irq = device_data->ending_irq + 1; req_done_irq_failed: for (irq2 =device_data->starting_irq; irq2 free_irq(irq2, channel_static_data); free_irq(device_data->fault_irq, channel_static_data); return-1;} ///////////////////////////////////////////////////////** *pl330_platform_remove - called when the platform driver is unregistered *@pdev: Pointer to the platform device structure * * Returns 0 onsuccess, negative error otherwise */static int pl330_platform_remove(struct platform_device*pdev){ int pdev_id; if (!pdev) { dev_err(&pdev->dev, "pl330 remove calledwith NULL param.\n"); return -ENODEV; } PDEBUG("pl330 driver removing %d\n", pdev->id); pdev_id = 0; if (pdev->id pdev_id = 0; }else if (pdev->id pdev_id = pdev->id; }else { dev_err(&pdev->dev, "pl330 device id exceeds thesupported number.\n"); return -ENODEV; } pl330_free_irq(pdev_id); pl330_release_io(pdev, pdev_id); return0;} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ? 12-28 12:38