musb_core.c 是usb_general.c 调用进musb模块的核心函数,

musb_core.c 是usb_general.c 调用进musb模块的核心函数,

里面有usb,musb,dma,platform模块等内容。

1. musb_init():

  1. /* make us init after usbcore and i2c (transceivers, regulators, etc) 
  2.  * and before usb gadget and host-side drivers start to register 
  3.  */  
  4. fs_initcall(musb_init);  

  1. static int __init musb_init(void)  
  2. {  
  3. #ifdef CONFIG_USB_MUSB_HDRC_HCD  
  4.     if (usb_disabled())  
  5.         return 0;  
  6. #endif  
  7.   
  8.     pr_info("%s: version " MUSB_VERSION ", "  
  9. #ifdef CONFIG_MUSB_PIO_ONLY               //这些宏由内核配置选项中来  
  10.         "pio"  
  11. #elif defined(CONFIG_USB_TI_CPPI_DMA)  
  12.         "cppi-dma"  
  13. #elif defined(CONFIG_USB_INVENTRA_DMA)  
  14.         "musb-dma"  
  15. #elif defined(CONFIG_USB_TUSB_OMAP_DMA)  
  16.         "tusb-omap-dma"  
  17. #elif defined(CONFIG_USB_CARTESIO_DMA)  
  18.         "pl080-dma"  
  19. #else  
  20.         "?dma?"  
  21. #endif  
  22.         ", "  
  23. #ifdef CONFIG_USB_MUSB_OTG  
  24.         "otg (peripheral+host)"  
  25. #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)  
  26.         "peripheral"  
  27. #elif defined(CONFIG_USB_MUSB_HDRC_HCD)  
  28.         "host"  
  29. #endif  
  30.         ", debug=%d\n",  
  31.         musb_driver_name, musb_debug);  
  32.     return platform_driver_probe(&musb_driver, musb_probe);  //这里调用了platform 平台函数,注册进platform类型队列中。  
  33. }  

musb_driver:

  1. static struct platform_driver musb_driver = {  
  2.     .driver = {  
  3.         .name       = (char *)musb_driver_name,   
  4.         .bus        = &platform_bus_type,   //platform bus类型  
  5.         .owner      = THIS_MODULE,  
  6.         .pm     = MUSB_DEV_PM_OPS,    //PM OPS, suspend+resume  
  7.     },  
  8.     .remove     = __exit_p(musb_remove),    
  9.     .shutdown   = musb_shutdown,  
  10. };  

1.1 musb_driver_name 定义:

  1. #define MUSB_DRIVER_NAME "musb_hdrc"  
  2. const char musb_driver_name[] = MUSB_DRIVER_NAME;  
1.2 MUSB_DEV_PM_OPS 定义:

  1. #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops)  
  2. #else  
  3. #define MUSB_DEV_PM_OPS NULL  
  4. #endif  
  1. static const struct dev_pm_ops musb_dev_pm_ops = {  
  2.     .suspend    = musb_suspend,  
  3.     .resume         = musb_resume_noirq,  
  4. };  
static int musb_suspend(struct device *dev)

  1. static int musb_suspend(struct device *dev)  
  2. {  
  3.     struct platform_device *pdev = to_platform_device(dev);  
  4.     unsigned long   flags;  
  5.     struct musb *musb = dev_to_musb(&pdev->dev);  
  6.   
  7.     if (!musb->clock)  
  8.         return 0;  
  9.   
  10.     spin_lock_irqsave(&musb->lock, flags);  
  11.   
  12.     if (is_peripheral_active(musb)) {  
  13.         /* FIXME force disconnect unless we know USB will wake 
  14.          * the system up quickly enough to respond ... 
  15.          */  
  16.     } else if (is_host_active(musb)) {  
  17.         /* we know all the children are suspended; sometimes 
  18.          * they will even be wakeup-enabled. 
  19.          */  
  20.     }  
  21.   
  22.     musb_save_context(musb);  
  23.   
  24.     if (musb->set_clock)  
  25.         musb->set_clock(musb->clock, 0);  
  26.     else  
  27.         clk_disable(musb->clock);  
  28.     spin_unlock_irqrestore(&musb->lock, flags);  
  29.     return 0;  
  30. }  
static int musb_resume_noirq(struct device *dev):

  1. static int musb_resume_noirq(struct device *dev)  
  2. {  
  3.     struct platform_device *pdev = to_platform_device(dev);  
  4.     struct musb *musb = dev_to_musb(&pdev->dev);  
  5. #ifdef MUSB_RESTORE_REG  
  6.     int status;  
  7. #endif  
  8.     if (!musb->clock)  
  9.         return 0;  
  10.   
  11.     if (musb->set_clock)  
  12.         musb->set_clock(musb->clock, 1);  
  13.     else  
  14.         clk_enable(musb->clock);  
  15.   
  16.     musb_restore_context(musb);  
  17.   
  18. #ifdef MUSB_RESTORE_REG  
  19.     status = musb_core_init(musb->is_multipoint  
  20.                 ? MUSB_CONTROLLER_MHDRC  
  21.                 : MUSB_CONTROLLER_HDRC, musb);  
  22.     if (status < 0)  
  23.         return status;  
  24.   
  25.     /* we need to apply the DEV_CTRL SESSION bit to initialize the VBUS. 
  26.      * This should be generally called through root hub POWERON feature, 
  27.      * but it is needed also  here if autosuspend is disabled. 
  28.          */  
  29.     musb_start(musb);  
  30.   
  31.     /* wait for the connect interrupt */  
  32.     mdelay(200);  
  33. #endif  
  34.     return 0;  
  35. }  
1.4  static int __exit musb_remove(struct platform_device *pdev)
  1. static int __exit musb_remove(struct platform_device *pdev)  
  2. {  
  3.     struct musb *musb = dev_to_musb(&pdev->dev);  
  4.     void __iomem    *ctrl_base = musb->ctrl_base;  
  5.   
  6.     /* this gets called on rmmod. 
  7.      *  - Host mode: host may still be active 
  8.      *  - Peripheral mode: peripheral is deactivated (or never-activated) 
  9.      *  - OTG mode: both roles are deactivated (or never-activated) 
  10.      */  
  11.     musb_shutdown(pdev);  
  12. #ifdef CONFIG_USB_MUSB_HDRC_HCD  
  13.     if (musb->board_mode == MUSB_HOST)  
  14.         usb_remove_hcd(musb_to_hcd(musb));  
  15. #endif  
  16.     musb_writeb(musb->mregs, MUSB_DEVCTL, 0);  
  17.     musb_platform_exit(musb);  
  18.     musb_writeb(musb->mregs, MUSB_DEVCTL, 0);  
  19.   
  20.     musb_free(musb);  
  21.     iounmap(ctrl_base);  
  22.     device_init_wakeup(&pdev->dev, 0);  
  23. #ifndef CONFIG_MUSB_PIO_ONLY  
  24.     pdev->dev.dma_mask = orig_dma_mask;  
  25. #endif  
  26.     return 0;  
  27. }  
1.5 static void musb_shutdown(struct platform_device *pdev)
  1. static void musb_shutdown(struct platform_device *pdev)  
  2. {  
  3.     struct musb *musb = dev_to_musb(&pdev->dev);  
  4.     unsigned long   flags;  
  5.   
  6.     spin_lock_irqsave(&musb->lock, flags);  
  7.     musb_platform_disable(musb);  
  8.     musb_generic_disable(musb);  
  9.     if (musb->clock)  
  10.         clk_put(musb->clock);  
  11.     spin_unlock_irqrestore(&musb->lock, flags);  
  12.   
  13.     /* FIXME power down */  
  14. }  
2.  musb_cleanup():

  1. static void __exit musb_cleanup(void)  
  2. {  
  3.     platform_driver_unregister(&musb_driver);  
  4. }  
  5. module_exit(musb_cleanup);  
3. static int __init musb_probe(struct platform_device *pdev)
  1. static int __init musb_probe(struct platform_device *pdev)  
  2. {  
  3.     struct device   *dev = &pdev->dev;  
  4.     int     irq = platform_get_irq(pdev, 0);  
  5.     int     status;  
  6.     struct resource *iomem;  
  7.     void __iomem    *base;  
  8.   
  9.     iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  //获取 platform 资源  
  10.     if (!iomem || irq == 0)  
  11.         return -ENODEV;  
  12.   
  13.     base = ioremap(iomem->start, resource_size(iomem));    //映射内存  
  14.     if (!base) {  
  15.         dev_err(dev, "ioremap failed\n");  
  16.         return -ENOMEM;  
  17.     }  
  18.   
  19. #ifndef CONFIG_MUSB_PIO_ONLY  
  20.     /* clobbered by use_dma=n */  
  21.     orig_dma_mask = dev->dma_mask;         //如果内核配置了CONFIG_MUSB_PIO_ONLY,则屏蔽DMA  
  22. #endif  
  23.     status = musb_init_controller(dev, irq, base);   //这个才是主要的函数  
  24.     if (status < 0)  
  25.         iounmap(base);  
  26.   
  27.     return status;  
  28. }  
4. static int __init
musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
  1. /* 
  2.  * Perform generic per-controller initialization. 
  3.  * 
  4.  * @pDevice: the controller (already clocked, etc) 
  5.  * @nIrq: irq 
  6.  * @mregs: virtual address of controller registers, 
  7.  *  not yet corrected for platform-specific offsets 
  8.  */  
  9. static int __init  
  10. musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)  
  11. {  
  12.     int         status;  
  13.     struct musb     *musb;  
  14.     struct musb_hdrc_platform_data *plat = dev->platform_data;  
  15.   
  16.     /* The driver might handle more features than the board; OK. 
  17.      * Fail when the board needs a feature that's not enabled. 
  18.      */  
  19.     if (!plat) {  
  20.         dev_dbg(dev, "no platform_data?\n");  
  21.         status = -ENODEV;  
  22.         goto fail0;  
  23.     }  
  24.   
  25.     switch (plat->mode) {  
  26.     case MUSB_HOST:  
  27. #ifdef CONFIG_USB_MUSB_HDRC_HCD  
  28.         break;  
  29. #else  
  30.         goto bad_config;  
  31. #endif  
  32.     case MUSB_PERIPHERAL:  
  33. #ifdef CONFIG_USB_GADGET_MUSB_HDRC  
  34.         break;  
  35. #else  
  36.         goto bad_config;  
  37. #endif  
  38.     case MUSB_OTG:  
  39. #ifdef CONFIG_USB_MUSB_OTG  
  40.         break;  
  41. #else  
  42. bad_config:  
  43. #endif  
  44.     default:  
  45.         dev_err(dev, "incompatible Kconfig role setting\n");  
  46.         status = -EINVAL;  
  47.         goto fail0;  
  48.     }  
  49.   
  50.     /* allocate */  
  51.     musb = allocate_instance(dev, plat->config, ctrl);    //分配实例  
  52.     if (!musb) {  
  53.         status = -ENOMEM;  
  54.         goto fail0;  
  55.     }  
  56.   
  57.     spin_lock_init(&musb->lock);  
  58.     musb->board_mode = plat->mode;  
  59.     musb->board_set_power = plat->set_power;  
  60.     musb->set_clock = plat->set_clock;  
  61.     musb->min_power = plat->min_power;  
  62.   
  63.     /* Clock usage is chip-specific ... functional clock (DaVinci, 
  64.      * OMAP2430), or PHY ref (some TUSB6010 boards).  All this core 
  65.      * code does is make sure a clock handle is available; platform 
  66.      * code manages it during start/stop and suspend/resume. 
  67.      */  
  68.     if (plat->clock) {  
  69.         musb->clock = clk_get(dev, plat->clock);  
  70.         if (IS_ERR(musb->clock)) {  
  71.             status = PTR_ERR(musb->clock);  
  72.             musb->clock = NULL;  
  73.             goto fail1;  
  74.         }  
  75.     }  
  76.   
  77.     /* The musb_platform_init() call: 
  78.      *   - adjusts musb->mregs and musb->isr if needed, 
  79.      *   - may initialize an integrated tranceiver 
  80.      *   - initializes musb->xceiv, usually by otg_get_transceiver() 
  81.      *   - activates clocks. 
  82.      *   - stops powering VBUS 
  83.      *   - assigns musb->board_set_vbus if host mode is enabled 
  84.      * 
  85.      * There are various transciever configurations.  Blackfin, 
  86.      * DaVinci, TUSB60x0, and others integrate them.  OMAP3 uses 
  87.      * external/discrete ones in various flavors (twl4030 family, 
  88.      * isp1504, non-OTG, etc) mostly hooking up through ULPI. 
  89.      */  
  90.     musb->isr = generic_interrupt;                                 //赋值 musb->irq  
  91.     status = musb_platform_init(musb);                             //初始化 musb  
  92.     if (status < 0)  
  93.         goto fail2;  
  94.   
  95.     if (!musb->isr) {  
  96.         status = -ENODEV;  
  97.         goto fail3;  
  98.     }  
  99.   
  100. #ifndef CONFIG_MUSB_PIO_ONLY  
  101.     if (use_dma && dev->dma_mask) {                  //屏蔽DMA  
  102.         struct dma_controller   *c;  
  103.   
  104.         c = dma_controller_create(musb, musb->mregs);  
  105.         musb->dma_controller = c;  
  106.         if (c)  
  107.             (void) c->start(c);  
  108.     }  
  109. #endif  
  110.     /* ideally this would be abstracted in platform setup */  
  111.     if (!is_dma_capable() || !musb->dma_controller)  
  112.         dev->dma_mask = NULL;  
  113.   
  114.     /* be sure interrupts are disabled before connecting ISR */       //先关闭中断  
  115.     musb_platform_disable(musb);  
  116.     musb_generic_disable(musb);  
  117.   
  118.     /* setup musb parts of the core (especially endpoints) */  
  119.     status = musb_core_init(plat->config->multipoint                     //这个是主要函数  
  120.             ? MUSB_CONTROLLER_MHDRC  
  121.             : MUSB_CONTROLLER_HDRC, musb);  
  122.     if (status < 0)  
  123.         goto fail3;  
  124.   
  125. #ifdef CONFIG_USB_MUSB_OTG  
  126.     setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);  
  127. #endif  
  128.   
  129.     /* Init IRQ workqueue before request_irq */  
  130.     INIT_WORK(&musb->irq_work, musb_irq_work);                  //初始化工作队列  
  131.   
  132.     /* attach to the IRQ */  
  133.     if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {    //申请中断号  
  134.         dev_err(dev, "request_irq %d failed!\n", nIrq);  
  135.         status = -ENODEV;  
  136.         goto fail3;  
  137.     }  
  138.     musb->nIrq = nIrq;  
  139. /* FIXME this handles wakeup irqs wrong */  
  140.     if (enable_irq_wake(nIrq) == 0) {  
  141.         musb->irq_wake = 1;  
  142.         device_init_wakeup(dev, 1);  
  143.     } else {  
  144.         musb->irq_wake = 0;  
  145.     }  
  146.   
  147.     /* host side needs more setup */                   //使能host模式  
  148.     if (is_host_enabled(musb)) {  
  149.         struct usb_hcd  *hcd = musb_to_hcd(musb);  
  150.   
  151.         otg_set_host(musb->xceiv, &hcd->self);  
  152.   
  153.         if (is_otg_enabled(musb))  
  154.             hcd->self.otg_port = 1;  
  155.         musb->xceiv->host = &hcd->self;  
  156.         hcd->power_budget = 2 * (plat->power ? : 250);  
  157.   
  158.         /* program PHY to use external vBus if required */  
  159.         if (plat->extvbus) {  
  160.             u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);  
  161.             busctl |= MUSB_ULPI_USE_EXTVBUS;  
  162.             musb_write_ulpi_buscontrol(musb->mregs, busctl);  
  163.         }  
  164.     }  
  165.   
  166.     /* For the host-only role, we can activate right away. 
  167.      * (We expect the ID pin to be forcibly grounded!!) 
  168.      * Otherwise, wait till the gadget driver hooks up. 
  169.      */  
  170.     if (!is_otg_enabled(musb) && is_host_enabled(musb)) {         //如果使能了 OTG 模式或 host 模式  
  171.         MUSB_HST_MODE(musb);  
  172.         musb->xceiv->default_a = 1;  
  173.         musb->xceiv->state = OTG_STATE_A_IDLE;  
  174.   
  175.         status = usb_add_hcd(musb_to_hcd(musb), -1, 0);       //把 musb 添加到 hcd(host controller driver)中  
  176.   
  177.         DBG(1, "%s mode, status %d, devctl %02x %c\n",  
  178.             "HOST", status,  
  179.             musb_readb(musb->mregs, MUSB_DEVCTL),  
  180.             (musb_readb(musb->mregs, MUSB_DEVCTL)  
  181.                     & MUSB_DEVCTL_BDEVICE  
  182.                 ? 'B' : 'A'));  
  183.   
  184.     } else /* peripheral is enabled */ {                         //如果使能了 Peripheral 模式  
  185.         MUSB_DEV_MODE(musb);  
  186.         musb->xceiv->default_a = 0;  
  187.         musb->xceiv->state = OTG_STATE_B_IDLE;  
  188.    
  189.         status = musb_gadget_setup(musb);                    //则建立 gadget  
  190.   
  191.         DBG(1, "%s mode, status %d, dev%02x\n",  
  192.             is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",  
  193.             status,  
  194.             musb_readb(musb->mregs, MUSB_DEVCTL));  
  195.   
  196.     }  
  197.     if (status < 0)  
  198.         goto fail3;  
  199.   
  200. #ifdef CONFIG_SYSFS  
  201.     status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);     //在 /sys 下建立目录  
  202.     if (status)  
  203.         goto fail4;  
  204. #endif  
  205.   
  206.     dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",            //dmesg中打印消息  
  207.             ({char *s;  
  208.              switch (musb->board_mode) {  
  209.              case MUSB_HOST:        s = "Host"break;  
  210.              case MUSB_PERIPHERAL:  s = "Peripheral"break;  
  211.              default:       s = "OTG"break;  
  212.              }; s; }),  
  213.             ctrl,  
  214.             (is_dma_capable() && musb->dma_controller)  
  215.             ? "DMA" : "PIO",  
  216.             musb->nIrq);  
  217.   
  218.     return 0;  
  219.   
  220. fail4:  
  221.     if (!is_otg_enabled(musb) && is_host_enabled(musb))       
  222.         usb_remove_hcd(musb_to_hcd(musb));  
  223.     else  
  224.         musb_gadget_cleanup(musb);  
  225.   
  226. fail3:  
  227.     if (musb->irq_wake)  
  228.         device_init_wakeup(dev, 0);  
  229.     musb_platform_exit(musb);  
  230.   
  231. fail2:  
  232.     if (musb->clock)  
  233.         clk_put(musb->clock);  
  234.   
  235. fail1:  
  236.     dev_err(musb->controller,  
  237.         "musb_init_controller failed with status %d\n", status);  
  238.   
  239.     musb_free(musb);  
  240.   
  241. fail0:  
  242.   
  243.     return status;  
  244.   
  245. }  
static struct musb *__init
allocate_instance(struct device *dev,
        struct musb_hdrc_config *config, void __iomem *mbase)

  1. /* -------------------------------------------------------------------------- 
  2.  * Init support 
  3.  */  
  4.   
  5. static struct musb *__init  
  6. allocate_instance(struct device *dev,  
  7.         struct musb_hdrc_config *config, void __iomem *mbase)  
  8. {  
  9.     struct musb     *musb;  
  10.     struct musb_hw_ep   *ep;  
  11.     int         epnum;  
  12. #ifdef CONFIG_USB_MUSB_HDRC_HCD  
  13.     struct usb_hcd  *hcd;  
  14.   
  15.     hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev));       //建立 host controller 端的驱动,这个会在musb_host.c中介绍  
  16.     if (!hcd)  
  17.         return NULL;  
  18.     /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */  
  19.   
  20.     musb = hcd_to_musb(hcd);  
  21.     INIT_LIST_HEAD(&musb->control);  
  22.     INIT_LIST_HEAD(&musb->in_bulk);  
  23.     INIT_LIST_HEAD(&musb->out_bulk);  
  24.   
  25.     hcd->uses_new_polling = 1;  
  26.     hcd->has_tt = 1;  
  27.   
  28.     musb->vbuserr_retry = VBUSERR_RETRY_COUNT;  
  29.     musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;  
  30. #else  
  31.     musb = kzalloc(sizeof *musb, GFP_KERNEL);  
  32.     if (!musb)  
  33.         return NULL;  
  34.     dev_set_drvdata(dev, musb);  
  35.   
  36. #endif  
  37.   
  38.     musb->mregs = mbase;  
  39.     musb->ctrl_base = mbase;  
  40.     musb->nIrq = -ENODEV;  
  41.     musb->config = config;  
  42.     BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS);  
  43.     for (epnum = 0, ep = musb->endpoints;  
  44.             epnum < musb->config->num_eps;  
  45.             epnum++, ep++) {  
  46.         ep->musb = musb;  
  47.         ep->epnum = epnum;  
  48.     }  
  49.   
  50.     musb->controller = dev;  
  51.     return musb;  
  52. }  
int __init musb_platform_init(struct musb *musb)   --- 这个函数定义于 /driver/usb/musb/cartesio.c 中,是ULPI的实现初始化了。
  1. int __init musb_platform_init(struct musb *musb)  
  2. {  
  3.     int ret;  
  4.   
  5.     if (!musb->clock)  
  6.         return 0;  
  7.   
  8.     if (musb->set_clock)  
  9.         musb->set_clock(musb->clock, 1);  
  10.     else  
  11.         clk_enable(musb->clock);  
  12.   
  13.     /* 
  14.      * This is a custom implementation of nop-usb-xceiv, introduced 
  15.      * because the original one does not support multiple instances. 
  16.      * This will be replaced by ulpi trainsceiver after moving to 
  17.      * kernel 2.6.33 
  18.      */  
  19.     musb->xceiv = cartesio_nop_xceiv_register();  
  20.     if (!musb->xceiv) {  
  21.         dev_err(musb->controller, "No transceiver configured\n");  
  22.         return -ENODEV;  
  23.     }  
  24.   
  25.     if (is_host_enabled(musb))  
  26.         musb->board_set_vbus = cartesio_set_vbus;  
  27.   
  28.     setup_timer(&musb->idle_timer, musb_do_idle, (unsigned long)musb);  
  29.   
  30.     if (musb_controller_is(musb, "musb_sta2062_ulpi") ||  
  31.         musb_controller_is(musb, "musb_sta2065_ulpi")) {  
  32.         ret = musb_cartesio_ulpi_init(musb);  
  33.         if (ret)  
  34.             return ret;  
  35.     }  
  36.     if (musb_controller_is(musb, "musb_sta2065_ephyfs"))  
  37.         musb_sta2065_ephyfs_init(musb);  
  38.   
  39.     if (musb_controller_is(musb, "musb_sta2062_ephy"))  
  40.         musb_sta2062_ephy_enable(musb);  
  41.   
  42.     return 0;  
  43. }  
static void musb_generic_disable(struct musb *musb)   --- 关闭中断
  1. static void musb_generic_disable(struct musb *musb)  
  2. {  
  3.     void __iomem    *mbase = musb->mregs;  
  4.     u16 temp;  
  5.   
  6.     /* disable interrupts */  
  7.     musb_writeb(mbase, MUSB_INTRUSBE, 0);  
  8.     musb_writew(mbase, MUSB_INTRTXE, 0);  
  9.     musb_writew(mbase, MUSB_INTRRXE, 0);  
  10.   
  11.     /* off */  
  12.     musb_writeb(mbase, MUSB_DEVCTL, 0);  
  13.   
  14.     /*  flush pending interrupts */  
  15.     temp = musb_readb(mbase, MUSB_INTRUSB);  
  16.     temp = musb_readw(mbase, MUSB_INTRTX);  
  17.     temp = musb_readw(mbase, MUSB_INTRRX);  
  18.   
  19. }  
void musb_otg_timer_func(unsigned long data)    
  1. /* 
  2.  * Handles OTG hnp timeouts, such as b_ase0_brst 
  3.  */  
  4. void musb_otg_timer_func(unsigned long data)  
  5. {  
  6.     struct musb *musb = (struct musb *)data;  
  7.     unsigned long   flags;  
  8.   
  9.     spin_lock_irqsave(&musb->lock, flags);  
  10.     switch (musb->xceiv->state) {  
  11.     case OTG_STATE_B_WAIT_ACON:  
  12.         DBG(1, "HNP: b_wait_acon timeout; back to b_peripheral\n");  
  13.         musb_g_disconnect(musb);  
  14.         musb->xceiv->state = OTG_STATE_B_PERIPHERAL;  
  15.         musb->is_active = 0;  
  16.         break;  
  17.     case OTG_STATE_A_SUSPEND:  
  18.     case OTG_STATE_A_WAIT_BCON:  
  19.         DBG(1, "HNP: %s timeout\n", otg_state_string(musb));  
  20.         musb_set_vbus(musb, 0);  
  21.         musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;  
  22.         break;  
  23.     default:  
  24.         DBG(1, "HNP: Unhandled mode %s\n", otg_state_string(musb));  
  25.     }  
  26.     musb->ignore_disconnect = 0;  
  27.     spin_unlock_irqrestore(&musb->lock, flags);  
  28. }  
5. static int MUSB_INIT musb_core_init(u16 musb_type, struct musb *musb)
  1. /* Initialize MUSB (M)HDRC part of the USB hardware subsystem; 
  2.  * configure endpoints, or take their config from silicon 
  3.  */  
  4. static int MUSB_INIT musb_core_init(u16 musb_type, struct musb *musb)  
  5. {  
  6.     u8 reg;  
  7.     char *type;  
  8.     char aInfo[90], aRevision[32], aDate[12];  
  9.     void __iomem    *mbase = musb->mregs;  
  10.     int     status = 0;  
  11.     int     i;  
  12.   
  13.     /* log core options (read using indexed model) */  
  14.     reg = musb_read_configdata(mbase);                  
  15.   
  16.     strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");  //在aInfo中添加一堆后缀  
  17.     if (reg & MUSB_CONFIGDATA_DYNFIFO) {  
  18.         strcat(aInfo, ", dyn FIFOs");  
  19.         musb->dyn_fifo = true;  
  20.     }  
  21.     if (reg & MUSB_CONFIGDATA_MPRXE) {  
  22.         strcat(aInfo, ", bulk combine");  
  23.         musb->bulk_combine = true;  
  24.     }  
  25.     if (reg & MUSB_CONFIGDATA_MPTXE) {  
  26.         strcat(aInfo, ", bulk split");  
  27.         musb->bulk_split = true;  
  28.     }  
  29.     if (reg & MUSB_CONFIGDATA_HBRXE) {  
  30.         strcat(aInfo, ", HB-ISO Rx");  
  31.         musb->hb_iso_rx = true;  
  32.     }  
  33.     if (reg & MUSB_CONFIGDATA_HBTXE) {  
  34.         strcat(aInfo, ", HB-ISO Tx");  
  35.         musb->hb_iso_tx = true;  
  36.     }  
  37.     if (reg & MUSB_CONFIGDATA_SOFTCONE)  
  38.         strcat(aInfo, ", SoftConn");  
  39.   
  40.     printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)\n",  
  41.             musb_driver_name, reg, aInfo);  
  42.   
  43.     aDate[0] = 0;  
  44.     if (MUSB_CONTROLLER_MHDRC == musb_type) {  
  45.         musb->is_multipoint = 1;  
  46.         type = "M";  
  47.     } else {  
  48.         musb->is_multipoint = 0;  
  49.         type = "";  
  50. #ifdef CONFIG_USB_MUSB_HDRC_HCD  
  51. #ifndef CONFIG_USB_OTG_BLACKLIST_HUB  
  52.         printk(KERN_ERR  
  53.             "%s: kernel must blacklist external hubs\n",  
  54.             musb_driver_name);  
  55. #endif  
  56. #endif  
  57.     }  
  58.   
  59.     /* log release info */  
  60.     musb->hwvers = musb_read_hwvers(mbase);  
  61.     snprintf(aRevision, 32, "%d.%d%s", MUSB_HWVERS_MAJOR(musb->hwvers),  
  62.         MUSB_HWVERS_MINOR(musb->hwvers),  
  63.         (musb->hwvers & MUSB_HWVERS_RC) ? "RC" : "");  
  64.     printk(KERN_DEBUG "%s: %sHDRC RTL version %s %s\n",                     //打印出 hdrc 内容  
  65.             musb_driver_name, type, aRevision, aDate);  
  66.   
  67.     /* configure ep0 */  
  68.     musb_configure_ep0(musb);       //configure musb 的 ep0  
  69.   
  70.     /* discover endpoint configuration */  
  71.     musb->nr_endpoints = 1;  
  72.     musb->epmask = 1;  
  73.   
  74.     if (musb->dyn_fifo)  
  75.         status = ep_config_from_table(musb);    //from table  
  76.     else  
  77.         status = ep_config_from_hw(musb);       // hardware config  
  78.   
  79.     if (status < 0)  
  80.         return status;  
  81.   
  82.     /* finish init, and print endpoint config */  
  83.     for (i = 0; i < musb->nr_endpoints; i++) {  
  84.         struct musb_hw_ep   *hw_ep = musb->endpoints + i;  
  85.   
  86.         hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;  
  87. #ifdef CONFIG_USB_TUSB6010  
  88.         hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);  
  89.         hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);  
  90.         hw_ep->fifo_sync_va =  
  91.             musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i);  
  92.   
  93.         if (i == 0)  
  94.             hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF;  
  95.         else  
  96.             hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2);  
  97. #endif  
  98.   
  99.         hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;  
  100. #ifdef CONFIG_USB_MUSB_HDRC_HCD  
  101.         hw_ep->target_regs = musb_read_target_reg_base(i, mbase);  
  102.         hw_ep->rx_reinit = 1;  
  103.         hw_ep->tx_reinit = 1;  
  104. #endif  
  105.   
  106.         if (hw_ep->max_packet_sz_tx) {  
  107.             DBG(1,  
  108.                 "%s: hw_ep %d%s, %smax %d\n",  
  109.                 musb_driver_name, i,  
  110.                 hw_ep->is_shared_fifo ? "shared" : "tx",  
  111.                 hw_ep->tx_double_buffered  
  112.                     ? "doublebuffer, " : "",  
  113.                 hw_ep->max_packet_sz_tx);  
  114.         }  
  115.         if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) {  
  116.             DBG(1,  
  117.                 "%s: hw_ep %d%s, %smax %d\n",  
  118.                 musb_driver_name, i,  
  119.                 "rx",  
  120.                 hw_ep->rx_double_buffered  
  121.                     ? "doublebuffer, " : "",  
  122.                 hw_ep->max_packet_sz_rx);  
  123.         }  
  124.         if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx))  
  125.             DBG(1, "hw_ep %d not configured\n", i);  
  126.     }  
  127.   
  128.     return 0;  
  129. }  
static inline void musb_configure_ep0(struct musb *musb)
  1. static inline void musb_configure_ep0(struct musb *musb)  
  2. {  
  3.     musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;  
  4.     musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;  
  5.     musb->endpoints[0].is_shared_fifo = true;  
  6. }  
6. static int MUSB_INIT ep_config_from_table(struct musb *musb)  --- 配置endpoint

  1. static int MUSB_INIT ep_config_from_table(struct musb *musb)  
  2. {  
  3.     const struct fifo_cfg   *cfg;  
  4.     unsigned        i, n;  
  5.     int         offset;  
  6.     struct musb_hw_ep   *hw_ep = musb->endpoints;  
  7.   
  8.     switch (fifo_mode) {  
  9.     default:  
  10.         fifo_mode = 0;  
  11.         /* FALLTHROUGH */  
  12.     case 0:  
  13.         cfg = mode_0_cfg;  
  14.         n = ARRAY_SIZE(mode_0_cfg);  
  15.         break;  
  16.     case 1:  
  17.         cfg = mode_1_cfg;  
  18.         n = ARRAY_SIZE(mode_1_cfg);  
  19.         break;  
  20.     case 2:  
  21.         cfg = mode_2_cfg;  
  22.         n = ARRAY_SIZE(mode_2_cfg);  
  23.         break;  
  24.     case 3:  
  25.         cfg = mode_3_cfg;  
  26.         n = ARRAY_SIZE(mode_3_cfg);  
  27.         break;  
  28.     case 4:  
  29.         cfg = mode_4_cfg;  
  30.         n = ARRAY_SIZE(mode_4_cfg);  
  31.         break;  
  32.     case 5:  
  33.         cfg = mode_5_cfg;  
  34.         n = ARRAY_SIZE(mode_5_cfg);  
  35.         break;  
  36.     }  
  37.   
  38.     printk(KERN_DEBUG "%s: setup fifo_mode %d\n",  
  39.             musb_driver_name, fifo_mode);  
  40.   
  41.     offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);  
  42.     /* assert(offset > 0) */  
  43.   
  44.     /* NOTE:  for RTL versions >= 1.400 EPINFO and RAMINFO would 
  45.      * be better than static musb->config->num_eps and DYN_FIFO_SIZE... 
  46.      */  
  47.   
  48.     for (i = 0; i < n; i++) {  
  49.         u8  epn = cfg->hw_ep_num;  
  50.   
  51.         if (epn >= musb->config->num_eps) {  
  52.             pr_debug("%s: invalid ep %d\n",  
  53.                     musb_driver_name, epn);  
  54.             return -EINVAL;  
  55.         }  
  56.         offset = fifo_setup(musb, hw_ep + epn, cfg++, offset);  
  57.         if (offset < 0) {  
  58.             pr_debug("%s: mem overrun, ep %d\n",  
  59.                     musb_driver_name, epn);  
  60.             return -EINVAL;  
  61.         }  
  62.         epn++;  
  63.         musb->nr_endpoints = max(epn, musb->nr_endpoints);  
  64.     }  
  65.   
  66.     printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memory\n",  
  67.             musb_driver_name,  
  68.             n + 1, musb->config->num_eps * 2 - 1,  
  69.             offset, (1 << (musb->config->ram_bits + 2)));  
  70.   
  71. #ifdef CONFIG_USB_MUSB_HDRC_HCD  
  72.     if (!musb->bulk_ep) {  
  73.         pr_debug("%s: missing bulk\n", musb_driver_name);  
  74.         return -EINVAL;  
  75.     }  
  76. #endif  
  77.   
  78.     return 0;  
  79. }  

fifo_mode 定义:

  1. #if defined(CONFIG_USB_TUSB6010) || \  
  2.     defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)  
  3. static ushort MUSB_INITDATA fifo_mode = 4;  
  4. #elif defined(CONFIG_ARCH_CARTESIO)  
  5. static ushort MUSB_INITDATA fifo_mode = 5;  
  6. #else  
  7. static ushort MUSB_INITDATA fifo_mode = 2;  
  8. #endif  
static int MUSB_INIT
fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,    
        const struct fifo_cfg *cfg, u16 offset)
                     ------------- 给endpoint 配置性能
  1. /* 
  2.  * configure a fifo; for non-shared endpoints, this may be called 
  3.  * once for a tx fifo and once for an rx fifo. 
  4.  * 
  5.  * returns negative errno or offset for next fifo. 
  6.  */  
  7. static int MUSB_INIT  
  8. fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,  
  9.         const struct fifo_cfg *cfg, u16 offset)  
  10. {  
  11.     void __iomem    *mbase = musb->mregs;  
  12.     int size = 0;  
  13.     u16 maxpacket = cfg->maxpacket;  
  14.     u16 c_off = offset >> 3;  
  15.     u8  c_size;  
  16.   
  17.     /* expect hw_ep has already been zero-initialized */  
  18.   
  19.     size = ffs(max(maxpacket, (u16) 8)) - 1;  
  20.     maxpacket = 1 << size;  
  21.   
  22.     c_size = size - 3;  
  23.     if (cfg->mode == BUF_DOUBLE) {  
  24.         if ((offset + (maxpacket << 1)) >  
  25.                 (1 << (musb->config->ram_bits + 2)))  
  26.             return -EMSGSIZE;  
  27.         c_size |= MUSB_FIFOSZ_DPB;  
  28.     } else {  
  29.         if ((offset + maxpacket) > (1 << (musb->config->ram_bits + 2)))  
  30.             return -EMSGSIZE;  
  31.     }  
  32.   
  33.     /* configure the FIFO */  
  34.     musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum);  
  35.   
  36. #ifdef CONFIG_USB_MUSB_HDRC_HCD  
  37.     /* EP0 reserved endpoint for control, bidirectional; 
  38.      * EP1 reserved for bulk, two unidirection halves. 
  39.      */  
  40.     if (hw_ep->epnum == 1)  
  41.         musb->bulk_ep = hw_ep;  
  42.     /* REVISIT error check:  be sure ep0 can both rx and tx ... */  
  43. #endif  
  44.     switch (cfg->style) {  
  45.     case FIFO_TX:  
  46.         musb_write_txfifosz(mbase, c_size);  
  47.         musb_write_txfifoadd(mbase, c_off);  
  48.         hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);  
  49.         hw_ep->max_packet_sz_tx = maxpacket;  
  50.         break;  
  51.     case FIFO_RX:  
  52.         musb_write_rxfifosz(mbase, c_size);  
  53.         musb_write_rxfifoadd(mbase, c_off);  
  54.         hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);  
  55.         hw_ep->max_packet_sz_rx = maxpacket;  
  56.         break;  
  57.     case FIFO_RXTX:  
  58.         musb_write_txfifosz(mbase, c_size);  
  59.         musb_write_txfifoadd(mbase, c_off);  
  60.         hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);  
  61.         hw_ep->max_packet_sz_rx = maxpacket;  
  62.   
  63.         musb_write_rxfifosz(mbase, c_size);  
  64.         musb_write_rxfifoadd(mbase, c_off);  
  65.         hw_ep->tx_double_buffered = hw_ep->rx_double_buffered;  
  66.         hw_ep->max_packet_sz_tx = maxpacket;  
  67.   
  68.         hw_ep->is_shared_fifo = true;  
  69.         break;  
  70.     }  
  71.   
  72.     /* NOTE rx and tx endpoint irqs aren't managed separately, 
  73.      * which happens to be ok 
  74.      */  
  75.     musb->epmask |= (1 << hw_ep->epnum);  
  76.   
  77.     return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));  
  78. }  
各种 fifo_cfg mode_*cfg[] :

  1. /* 
  2.  * tables defining fifo_mode values.  define more if you like. 
  3.  * for host side, make sure both halves of ep1 are set up. 
  4.  */  
  5.   
  6. /* mode 0 - fits in 2KB */  
  7. static struct fifo_cfg MUSB_INITDATA mode_0_cfg[] = {  
  8. { .hw_ep_num = 1, .><br>  
  9. <p></p>  

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值