Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1148299
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2016-08-17 14:47:23

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 __init pl330_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 the pointer
 * to array
 */
arch\arm\mach-zynq\pl330.c
static void pl330_driver_init(void)
{
 unsigned int i;
 PDEBUG("inside pl330_driver_init, dma_chan is %x\n",
        (unsigned int)dma_chan);
 driver_data.dma_chan = dma_chan;
 memset(dma_chan, 0, sizeof(dma_chan[MAX_DMA_CHANNELS]));
 for (i = 0; i < MAX_DMA_CHANNELS; i++) {
  dma_chan[i].d_ops = &pl330_ops;
  isa_dma_add(i, dma_chan + i);
 }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 * pl330_platform_probe - Platform driver probe
 * @pdev: Pointer to the platform device structure
 *
 * Returns 0 on success, negative error otherwise
 */
arch\arm\mach-zynq\pl330.c
static int __devinit pl330_platform_probe(struct platform_device *pdev)
{
 int pdev_id;
 if (!pdev) {
  dev_err(&pdev->dev, "pl330 probe called with NULL param.\n");
  return -ENODEV;
 }
 PDEBUG("pl330 driver probing dev_id %d\n", pdev->id);
 pdev_id = 0;
 if (pdev->id < 0) {
  pdev_id = 0;
 } else if (pdev->id < MAX_DMA_DEVICES) {
  pdev_id = pdev->id;
 } else {
  dev_err(&pdev->dev,
   "pl330 device id exceeds the supported 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);
 return 0;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 * pl330_request_irq - set up the interrupt handler for the corresponding
 * device. It sets up all the interrupt for all the channels of that
 * device. It also sets the the fault interrupt handler for the device.
 * @dev_id: device id.
 *
 * Returns 0 on success, otherwise on failure
 */
int pl330_request_irq(unsigned int dev_id)
{
 unsigned int irq;
 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 %d failed %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 <= device_data->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);
   goto req_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 && irq <= device_data->ending_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);
   goto req_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 < irq; irq2++)
  free_irq(irq2, channel_static_data);
 irq = device_data->ending_irq + 1;
 req_done_irq_failed:
 for (irq2 = device_data->starting_irq;
      irq2 < 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 on success, negative error otherwise
 */
static int pl330_platform_remove(struct platform_device *pdev)
{
 int pdev_id;
 if (!pdev) {
  dev_err(&pdev->dev, "pl330 remove called with NULL param.\n");
  return -ENODEV;
 }
 PDEBUG("pl330 driver removing %d\n", pdev->id);
 pdev_id = 0;
 if (pdev->id < 0) {
  pdev_id = 0;
 } else if (pdev->id < MAX_DMA_DEVICES) {
  pdev_id = pdev->id;
 } else {
  dev_err(&pdev->dev,
   "pl330 device id exceeds the supported number.\n");
  return -ENODEV;
 }

 pl330_free_irq(pdev_id);
 pl330_release_io(pdev, pdev_id);
 return 0;


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ?
阅读(1703) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~