📄 hal_pci.c
字号:
/* PCI cleanup function of ISP1362 * This function is called from PCI Driver as an removal function * in the absence of PCI device or a de-registration of driver. * This functions checks the registerd drivers (HCD, DCD, OTG) and calls * the corresponding removal functions. Also initializes the local variables * to zero. */static void __devexitisp1362_pci_remove (struct pci_dev *dev){ struct isp1362_dev *loc_dev; int index; func_debug(("isp1362_pci_remove(dev=%p)\n",dev)) /* For each controller check whether driver is registerd * or not. If registerd call the removal function if it is * present */ for(index=ISP1362_1ST_DEV;index<ISP1362_LAST_DEV;index++) { loc_dev = &isp1362_loc_dev[index]; if(loc_dev->driver) { loc_dev->driver->remove(loc_dev); loc_dev->driver = NULL; return; } } /* Clear the local variables */ hal_data.io_usage = 0; hal_data.irq_usage = 0; return;} /* End of isp1362_pci_remove *//* PCI suspend function of ISP1362 * This function is called from PCI Driver. * This functions checks the registerd drivers (HCD, DCD, OTG) and calls * the corresponding suspend functions if present. */static int isp1362_pci_suspend (struct pci_dev *dev, __u32 state) { struct isp1362_dev *loc_dev; int index; func_debug(("isp1362_pci_suspend(dev=%p, state = %x)\n",dev, state)) loc_dev = (struct isp1362_dev *)pci_get_drvdata(dev); /* For each controller check whether driver is registerd * or not. If registerd call the suspend function if it is * present */ for(index=ISP1362_1ST_DEV;index<ISP1362_LAST_DEV;(index++,loc_dev++)) { if(loc_dev->driver && loc_dev->driver->suspend) { loc_dev->driver->suspend(loc_dev); } } return 0;} /* End of isp1362_pci_suspend *//* PCI resume function of ISP1362 * This function is called from PCI Driver. * This functions checks the registerd drivers (HCD, DCD, OTG) and calls * the corresponding resume functions if present. */static int isp1362_pci_resume (struct pci_dev *dev){ struct isp1362_dev *loc_dev; int index; func_debug(("isp1362_pci_resume(dev=%p)\n",dev)) loc_dev = (struct isp1362_dev *)pci_get_drvdata(dev); /* For each controller check whether driver is registerd * or not. If registerd call the resume function if it is * present */ for(index=ISP1362_1ST_DEV;index<ISP1362_LAST_DEV;(index++,loc_dev++)) { if(loc_dev->driver && loc_dev->driver->resume) { loc_dev->driver->resume(loc_dev); } } return 0;} /* End of isp1362_pci_resume *//*--------------------------------------------------------------* * Top Drivers (HCD, DCD, OTG) interface functions *--------------------------------------------------------------*//*--------------------------------------------------------------* * hardware register initialization *--------------------------------------------------------------*//* This fuction initializes the ISP1362 device hardware configuration * register for PCI interface. */void isp1362_set_hw_config(struct isp1362_dev *dev){ __u32 hw_cnfg; func_debug(("isp1362_set_hw_config(dev=%p)\n",dev)) switch(dev->index) { case ISP1362_HC: isp1362_reg_read16(dev, HC_HW_CNFG_REG,hw_cnfg); /* Enable HC interrupt Pin * Use only one interrupt for HC and DC * Connect the 15K pulldown registers on port1&2 * Level triggering, Active low polarity */ hw_cnfg |= (HC_INT_PIN_ENABLE | HC_ONE_INT); hw_cnfg |= (HC_CONNECT_PLDN_15K_DS2 | HC_CONNECT_PLDN_15K_DS1);#ifdef CONFIG_USB_PHCD_DMA hw_cnfg |= (HC_DREQ_OUT_POLARITY | HC_DATA_BUS_16BIT_WIDTH);#endif /* CONFIG_USB_PHCD_DMA */ isp1362_reg_write16(dev,(HC_HW_CNFG_REG|0x80),hw_cnfg); break; case ISP1362_DC: isp1362_reg_read16(dev, DC_HW_CNFG_REG, hw_cnfg); /* No Clock Division, Clock is always running * Level triggering, Active low polarity */ hw_cnfg &= ~(DC_CLK_DIV); /* No clock division */ hw_cnfg |= (DC_CLK_RUN); /* Clock is always running */ isp1362_reg_write16(dev,(DC_HW_CNFG_REG&0xFE),hw_cnfg); break; default: break; }} /* End of isp1362_set_hw_config() *//*--------------------------------------------------------------* * IO PORT Management Functions *--------------------------------------------------------------*//* This fuction checks whether the IO region is free for use or not * The IO region is specified in the dev structure fields. * Since OTG uses same IO ports as Host Controller and OTG driver * depends on HCD, by the time OTG is loaded HCD has already been loaded * and if HC is using IO resources, we say OTG can access the IO resources * for HCD and DCD we use system call check_region() */int isp1362_check_io_region(struct isp1362_dev *dev){ func_debug(("isp1362_check_io_region(dev=%p)\n",dev)) /* If OTG driver, check the IO resources of HCD */ if(dev->index == ISP1362_OTG) { if(isp1362_loc_dev[ISP1362_HC].io_res) return 0; else return -EBUSY; } return check_region(dev->io_base, dev->io_len);} /* End of isp1362_check_io_region *//* This fuction assigns IO region to the driver * The IO region is specified in the "dev" structure fields. * Since OTG uses same IO ports as Host Controller and OTG driver * depends on HCD, for OTG driver the HCD io resources are returned * for HCD and DCD we use system call request_region() */struct resource* isp1362_request_io_region(struct isp1362_dev *dev){ func_debug(("isp1362_request_io_region(dev=%p)\n",dev)) hal_data.io_usage++; if(dev->index == ISP1362_OTG) { /* If OTG return the HCD io resources */ dev->io_res = isp1362_loc_dev[ISP1362_HC].io_res; } else { /* Store the IO resources */ dev->io_res = request_region(dev->io_base, dev->io_len, isp1362_driver_name); } return dev->io_res;} /* End of isp1362_request_io_region *//* This fuction releases IO region for the driver * The IO region is specified in the "dev" structure fields. * Since OTG uses same IO ports as Host Controller and OTG driver * depends on HCD, for OTG driver nothing is done * for HCD and DCD we use system call release_region() */void isp1362_release_io_region(struct isp1362_dev *dev){ func_debug(("isp1362_release_io_region(dev=%p)\n",dev)) hal_data.io_usage--; dev->io_res = NULL; if(dev->index == ISP1362_OTG) return; return release_region(dev->io_base, dev->io_len); } /* End of isp1362_release_io_region *//*--------------------------------------------------------------* * Interrupt Management Functions *--------------------------------------------------------------*//* This function registers the ISR of driver with this driver. * Since there is only one interrupt line, when the first driver * is registerd, will call the system function request_irq. The PLX * bridge needs enabling of interrupt in the interrupt control register to * pass the local interrupts to the PCI (cpu). * For later registrations will just update the variables. On ISR, this driver * will look for registered handlers and calls the corresponding driver's * ISR "handler" function with "isr_data" as parameter. */int isp1362_request_irq(void (*handler)(struct isp1362_dev *, void *), struct isp1362_dev *dev, void *isr_data) { int result = 0; __u16 intcsr; func_debug(("isp1362_request_irq(handler=%p,dev=%p,isr_data=%p)\n",handler,dev,isr_data)) if(!(hal_data.irq_usage)) { /* If this is the first request */ result= request_irq(dev->irq,isp1362_pci_isr, SA_SHIRQ, isp1362_driver_name, (void*)isp1362_loc_dev); } hal_data.irq_usage++; if(result >= 0) { if(hal_data.irq_usage == 1) { /* If this is the first request */ intcsr = inb(pci_io_base + PLX_INT_CSR_REG+1); intcsr |= 0x09; outb(intcsr,(pci_io_base + PLX_INT_CSR_REG+1)); func_debug(("Enabling PLX bridge local/cpu interrupts\n")) } dev->handler = handler; dev->isr_data = isr_data; } return result;} /* End of isp1362_request_irq *//* This function de-registers the ISR of driver with this driver. * Since there is only one interrupt line, when the last driver * is de-registerd, will call the system function free_irq. The PLX * bridge needs disabling of interrupt in the interrupt control register to * block the local interrupts to the PCI (cpu). */void isp1362_free_irq(struct isp1362_dev *dev, void *isr_data){ __u16 intcsr; func_debug(("isp1362_free_irq(dev=%p,isr_data=%p)\n",dev,isr_data)) hal_data.irq_usage--; if(!hal_data.irq_usage) { /* If this is the last free request */ free_irq(dev->irq,isp1362_loc_dev); intcsr = inb(pci_io_base + PLX_INT_CSR_REG+1); intcsr &= 0xF6; outb(intcsr,(pci_io_base + PLX_INT_CSR_REG+1)); detail_debug(("disabling PLX bridge local/PCI interrupts")) } } /* isp1362_free_irq *//*--------------------------------------------------------------* * Driver Registration Functions *--------------------------------------------------------------*//* This function is used by top driver (OTG, HCD, DCD) to register * their communication functions (probe, remove, suspend, resume) using * the drv data structure. * This function will call the probe function of the driver if the ISP1362 * corresponding to the driver is enabled */int isp1362_register_driver(struct isp1362_driver *drv) { struct isp1362_dev *dev; int result; func_debug(("isp1362_register_driver(drv=%p)\n",drv)) if(!drv) return -EINVAL; dev = &isp1362_loc_dev[drv->index]; if(dev->active) result = drv->probe(dev); else result = -ENODEV; if(result >= 0 ) { dev->driver = drv; } return result;} /* End of isp1362_register_driver *//* This function is used by top driver (OTG, HCD, DCD) to de-register * their communication functions (probe, remove, suspend, resume) using * the drv data structure. * This function will check whether the driver is registered or not and * call the remove function of the driver if registered */void isp1362_unregister_driver(struct isp1362_driver *drv){ struct isp1362_dev *dev; func_debug(("isp1362_unregister_driver(drv=%p)\n",drv)) dev = &isp1362_loc_dev[drv->index]; if(dev->driver == drv) { /* driver registered is same as the requestig driver */ drv->remove(dev); dev->driver = NULL; return; }} /* End of isp1362_unregister_driver *//*--------------------------------------------------------------* * Module Management Functions *--------------------------------------------------------------*//* This is the module initialization function. It registers to * PCI driver for a PLX PCI bridge device. And also resets the * internal data structures before registering to PCI driver. */static int __init isp1362_pci_module_init (void) { int result = 0; func_debug(("isp1362_pci_module_init(void)\n")) memset(isp1362_loc_dev,0,sizeof(isp1362_loc_dev)); if((result = pci_module_init(&isp1362_pci_driver)) < 0) { detail_debug(("%s: Initialization Failed %d",isp1362_driver_name,result)) return result; } return result;}/* This is the module eleanup function. It de-registers from * PCI driver and resets the internal data structures. */static void __exit isp1362_pci_module_cleanup (void) { func_debug(("isp1362_pci_module_cleanup(void)\n")) pci_unregister_driver (&isp1362_pci_driver); memset(isp1362_loc_dev,0,sizeof(isp1362_loc_dev));} module_init (isp1362_pci_module_init);module_exit (isp1362_pci_module_cleanup);MODULE_AUTHOR (DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -