概述
musb_core.c 是usb_general.c 调用进musb模块的核心函数,
里面有usb,musb,dma,platform模块等内容。
1. musb_init():
- /* make us init after usbcore and i2c (transceivers, regulators, etc)
- * and before usb gadget and host-side drivers start to register
- */
- fs_initcall(musb_init);
- static int __init musb_init(void)
- {
- #ifdef CONFIG_USB_MUSB_HDRC_HCD
- if (usb_disabled())
- return 0;
- #endif
- pr_info("%s: version " MUSB_VERSION ", "
- #ifdef CONFIG_MUSB_PIO_ONLY //这些宏由内核配置选项中来
- "pio"
- #elif defined(CONFIG_USB_TI_CPPI_DMA)
- "cppi-dma"
- #elif defined(CONFIG_USB_INVENTRA_DMA)
- "musb-dma"
- #elif defined(CONFIG_USB_TUSB_OMAP_DMA)
- "tusb-omap-dma"
- #elif defined(CONFIG_USB_CARTESIO_DMA)
- "pl080-dma"
- #else
- "?dma?"
- #endif
- ", "
- #ifdef CONFIG_USB_MUSB_OTG
- "otg (peripheral+host)"
- #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
- "peripheral"
- #elif defined(CONFIG_USB_MUSB_HDRC_HCD)
- "host"
- #endif
- ", debug=%dn",
- musb_driver_name, musb_debug);
- return platform_driver_probe(&musb_driver, musb_probe); //这里调用了platform 平台函数,注册进platform类型队列中。
- }
musb_driver:
- static struct platform_driver musb_driver = {
- .driver = {
- .name = (char *)musb_driver_name,
- .bus = &platform_bus_type, //platform bus类型
- .owner = THIS_MODULE,
- .pm = MUSB_DEV_PM_OPS, //PM OPS, suspend+resume
- },
- .remove = __exit_p(musb_remove),
- .shutdown = musb_shutdown,
- };
1.1 musb_driver_name 定义:
- #define MUSB_DRIVER_NAME "musb_hdrc"
- const char musb_driver_name[] = MUSB_DRIVER_NAME;
- #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops)
- #else
- #define MUSB_DEV_PM_OPS NULL
- #endif
- static const struct dev_pm_ops musb_dev_pm_ops = {
- .suspend = musb_suspend,
- .resume = musb_resume_noirq,
- };
- static int musb_suspend(struct device *dev)
- {
- struct platform_device *pdev = to_platform_device(dev);
- unsigned long flags;
- struct musb *musb = dev_to_musb(&pdev->dev);
- if (!musb->clock)
- return 0;
- spin_lock_irqsave(&musb->lock, flags);
- if (is_peripheral_active(musb)) {
- /* FIXME force disconnect unless we know USB will wake
- * the system up quickly enough to respond ...
- */
- } else if (is_host_active(musb)) {
- /* we know all the children are suspended; sometimes
- * they will even be wakeup-enabled.
- */
- }
- musb_save_context(musb);
- if (musb->set_clock)
- musb->set_clock(musb->clock, 0);
- else
- clk_disable(musb->clock);
- spin_unlock_irqrestore(&musb->lock, flags);
- return 0;
- }
- static int musb_resume_noirq(struct device *dev)
- {
- struct platform_device *pdev = to_platform_device(dev);
- struct musb *musb = dev_to_musb(&pdev->dev);
- #ifdef MUSB_RESTORE_REG
- int status;
- #endif
- if (!musb->clock)
- return 0;
- if (musb->set_clock)
- musb->set_clock(musb->clock, 1);
- else
- clk_enable(musb->clock);
- musb_restore_context(musb);
- #ifdef MUSB_RESTORE_REG
- status = musb_core_init(musb->is_multipoint
- ? MUSB_CONTROLLER_MHDRC
- : MUSB_CONTROLLER_HDRC, musb);
- if (status < 0)
- return status;
- /* we need to apply the DEV_CTRL SESSION bit to initialize the VBUS.
- * This should be generally called through root hub POWERON feature,
- * but it is needed also here if autosuspend is disabled.
- */
- musb_start(musb);
- /* wait for the connect interrupt */
- mdelay(200);
- #endif
- return 0;
- }
- static int __exit musb_remove(struct platform_device *pdev)
- {
- struct musb *musb = dev_to_musb(&pdev->dev);
- void __iomem *ctrl_base = musb->ctrl_base;
- /* this gets called on rmmod.
- * - Host mode: host may still be active
- * - Peripheral mode: peripheral is deactivated (or never-activated)
- * - OTG mode: both roles are deactivated (or never-activated)
- */
- musb_shutdown(pdev);
- #ifdef CONFIG_USB_MUSB_HDRC_HCD
- if (musb->board_mode == MUSB_HOST)
- usb_remove_hcd(musb_to_hcd(musb));
- #endif
- musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
- musb_platform_exit(musb);
- musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
- musb_free(musb);
- iounmap(ctrl_base);
- device_init_wakeup(&pdev->dev, 0);
- #ifndef CONFIG_MUSB_PIO_ONLY
- pdev->dev.dma_mask = orig_dma_mask;
- #endif
- return 0;
- }
- static void musb_shutdown(struct platform_device *pdev)
- {
- struct musb *musb = dev_to_musb(&pdev->dev);
- unsigned long flags;
- spin_lock_irqsave(&musb->lock, flags);
- musb_platform_disable(musb);
- musb_generic_disable(musb);
- if (musb->clock)
- clk_put(musb->clock);
- spin_unlock_irqrestore(&musb->lock, flags);
- /* FIXME power down */
- }
- static void __exit musb_cleanup(void)
- {
- platform_driver_unregister(&musb_driver);
- }
- module_exit(musb_cleanup);
- static int __init musb_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- int irq = platform_get_irq(pdev, 0);
- int status;
- struct resource *iomem;
- void __iomem *base;
- iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取 platform 资源
- if (!iomem || irq == 0)
- return -ENODEV;
- base = ioremap(iomem->start, resource_size(iomem)); //映射内存
- if (!base) {
- dev_err(dev, "ioremap failedn");
- return -ENOMEM;
- }
- #ifndef CONFIG_MUSB_PIO_ONLY
- /* clobbered by use_dma=n */
- orig_dma_mask = dev->dma_mask; //如果内核配置了CONFIG_MUSB_PIO_ONLY,则屏蔽DMA
- #endif
- status = musb_init_controller(dev, irq, base); //这个才是主要的函数
- if (status < 0)
- iounmap(base);
- return status;
- }
musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
- /*
- * Perform generic per-controller initialization.
- *
- * @pDevice: the controller (already clocked, etc)
- * @nIrq: irq
- * @mregs: virtual address of controller registers,
- * not yet corrected for platform-specific offsets
- */
- static int __init
- musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
- {
- int status;
- struct musb *musb;
- struct musb_hdrc_platform_data *plat = dev->platform_data;
- /* The driver might handle more features than the board; OK.
- * Fail when the board needs a feature that's not enabled.
- */
- if (!plat) {
- dev_dbg(dev, "no platform_data?n");
- status = -ENODEV;
- goto fail0;
- }
- switch (plat->mode) {
- case MUSB_HOST:
- #ifdef CONFIG_USB_MUSB_HDRC_HCD
- break;
- #else
- goto bad_config;
- #endif
- case MUSB_PERIPHERAL:
- #ifdef CONFIG_USB_GADGET_MUSB_HDRC
- break;
- #else
- goto bad_config;
- #endif
- case MUSB_OTG:
- #ifdef CONFIG_USB_MUSB_OTG
- break;
- #else
- bad_config:
- #endif
- default:
- dev_err(dev, "incompatible Kconfig role settingn");
- status = -EINVAL;
- goto fail0;
- }
- /* allocate */
- musb = allocate_instance(dev, plat->config, ctrl); //分配实例
- if (!musb) {
- status = -ENOMEM;
- goto fail0;
- }
- spin_lock_init(&musb->lock);
- musb->board_mode = plat->mode;
- musb->board_set_power = plat->set_power;
- musb->set_clock = plat->set_clock;
- musb->min_power = plat->min_power;
- /* Clock usage is chip-specific ... functional clock (DaVinci,
- * OMAP2430), or PHY ref (some TUSB6010 boards). All this core
- * code does is make sure a clock handle is available; platform
- * code manages it during start/stop and suspend/resume.
- */
- if (plat->clock) {
- musb->clock = clk_get(dev, plat->clock);
- if (IS_ERR(musb->clock)) {
- status = PTR_ERR(musb->clock);
- musb->clock = NULL;
- goto fail1;
- }
- }
- /* The musb_platform_init() call:
- * - adjusts musb->mregs and musb->isr if needed,
- * - may initialize an integrated tranceiver
- * - initializes musb->xceiv, usually by otg_get_transceiver()
- * - activates clocks.
- * - stops powering VBUS
- * - assigns musb->board_set_vbus if host mode is enabled
- *
- * There are various transciever configurations. Blackfin,
- * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses
- * external/discrete ones in various flavors (twl4030 family,
- * isp1504, non-OTG, etc) mostly hooking up through ULPI.
- */
- musb->isr = generic_interrupt; //赋值 musb->irq
- status = musb_platform_init(musb); //初始化 musb
- if (status < 0)
- goto fail2;
- if (!musb->isr) {
- status = -ENODEV;
- goto fail3;
- }
- #ifndef CONFIG_MUSB_PIO_ONLY
- if (use_dma && dev->dma_mask) { //屏蔽DMA
- struct dma_controller *c;
- c = dma_controller_create(musb, musb->mregs);
- musb->dma_controller = c;
- if (c)
- (void) c->start(c);
- }
- #endif
- /* ideally this would be abstracted in platform setup */
- if (!is_dma_capable() || !musb->dma_controller)
- dev->dma_mask = NULL;
- /* be sure interrupts are disabled before connecting ISR */ //先关闭中断
- musb_platform_disable(musb);
- musb_generic_disable(musb);
- /* setup musb parts of the core (especially endpoints) */
- status = musb_core_init(plat->config->multipoint //这个是主要函数
- ? MUSB_CONTROLLER_MHDRC
- : MUSB_CONTROLLER_HDRC, musb);
- if (status < 0)
- goto fail3;
- #ifdef CONFIG_USB_MUSB_OTG
- setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
- #endif
- /* Init IRQ workqueue before request_irq */
- INIT_WORK(&musb->irq_work, musb_irq_work); //初始化工作队列
- /* attach to the IRQ */
- if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) { //申请中断号
- dev_err(dev, "request_irq %d failed!n", nIrq);
- status = -ENODEV;
- goto fail3;
- }
- musb->nIrq = nIrq;
- /* FIXME this handles wakeup irqs wrong */
- if (enable_irq_wake(nIrq) == 0) {
- musb->irq_wake = 1;
- device_init_wakeup(dev, 1);
- } else {
- musb->irq_wake = 0;
- }
- /* host side needs more setup */ //使能host模式
- if (is_host_enabled(musb)) {
- struct usb_hcd *hcd = musb_to_hcd(musb);
- otg_set_host(musb->xceiv, &hcd->self);
- if (is_otg_enabled(musb))
- hcd->self.otg_port = 1;
- musb->xceiv->host = &hcd->self;
- hcd->power_budget = 2 * (plat->power ? : 250);
- /* program PHY to use external vBus if required */
- if (plat->extvbus) {
- u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
- busctl |= MUSB_ULPI_USE_EXTVBUS;
- musb_write_ulpi_buscontrol(musb->mregs, busctl);
- }
- }
- /* For the host-only role, we can activate right away.
- * (We expect the ID pin to be forcibly grounded!!)
- * Otherwise, wait till the gadget driver hooks up.
- */
- if (!is_otg_enabled(musb) && is_host_enabled(musb)) { //如果使能了 OTG 模式或 host 模式
- MUSB_HST_MODE(musb);
- musb->xceiv->default_a = 1;
- musb->xceiv->state = OTG_STATE_A_IDLE;
- status = usb_add_hcd(musb_to_hcd(musb), -1, 0); //把 musb 添加到 hcd(host controller driver)中
- DBG(1, "%s mode, status %d, devctl %02x %cn",
- "HOST", status,
- musb_readb(musb->mregs, MUSB_DEVCTL),
- (musb_readb(musb->mregs, MUSB_DEVCTL)
- & MUSB_DEVCTL_BDEVICE
- ? 'B' : 'A'));
- } else /* peripheral is enabled */ { //如果使能了 Peripheral 模式
- MUSB_DEV_MODE(musb);
- musb->xceiv->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
- status = musb_gadget_setup(musb); //则建立 gadget
- DBG(1, "%s mode, status %d, dev%02xn",
- is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
- status,
- musb_readb(musb->mregs, MUSB_DEVCTL));
- }
- if (status < 0)
- goto fail3;
- #ifdef CONFIG_SYSFS
- status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); //在 /sys 下建立目录
- if (status)
- goto fail4;
- #endif
- dev_info(dev, "USB %s mode controller at %p using %s, IRQ %dn", //dmesg中打印消息
- ({char *s;
- switch (musb->board_mode) {
- case MUSB_HOST: s = "Host"; break;
- case MUSB_PERIPHERAL: s = "Peripheral"; break;
- default: s = "OTG"; break;
- }; s; }),
- ctrl,
- (is_dma_capable() && musb->dma_controller)
- ? "DMA" : "PIO",
- musb->nIrq);
- return 0;
- fail4:
- if (!is_otg_enabled(musb) && is_host_enabled(musb))
- usb_remove_hcd(musb_to_hcd(musb));
- else
- musb_gadget_cleanup(musb);
- fail3:
- if (musb->irq_wake)
- device_init_wakeup(dev, 0);
- musb_platform_exit(musb);
- fail2:
- if (musb->clock)
- clk_put(musb->clock);
- fail1:
- dev_err(musb->controller,
- "musb_init_controller failed with status %dn", status);
- musb_free(musb);
- fail0:
- return status;
- }
allocate_instance(struct device *dev,
struct musb_hdrc_config *config, void __iomem *mbase)
- /* --------------------------------------------------------------------------
- * Init support
- */
- static struct musb *__init
- allocate_instance(struct device *dev,
- struct musb_hdrc_config *config, void __iomem *mbase)
- {
- struct musb *musb;
- struct musb_hw_ep *ep;
- int epnum;
- #ifdef CONFIG_USB_MUSB_HDRC_HCD
- struct usb_hcd *hcd;
- hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); //建立 host controller 端的驱动,这个会在musb_host.c中介绍
- if (!hcd)
- return NULL;
- /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */
- musb = hcd_to_musb(hcd);
- INIT_LIST_HEAD(&musb->control);
- INIT_LIST_HEAD(&musb->in_bulk);
- INIT_LIST_HEAD(&musb->out_bulk);
- hcd->uses_new_polling = 1;
- hcd->has_tt = 1;
- musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
- musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
- #else
- musb = kzalloc(sizeof *musb, GFP_KERNEL);
- if (!musb)
- return NULL;
- dev_set_drvdata(dev, musb);
- #endif
- musb->mregs = mbase;
- musb->ctrl_base = mbase;
- musb->nIrq = -ENODEV;
- musb->config = config;
- BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS);
- for (epnum = 0, ep = musb->endpoints;
- epnum < musb->config->num_eps;
- epnum++, ep++) {
- ep->musb = musb;
- ep->epnum = epnum;
- }
- musb->controller = dev;
- return musb;
- }
- int __init musb_platform_init(struct musb *musb)
- {
- int ret;
- if (!musb->clock)
- return 0;
- if (musb->set_clock)
- musb->set_clock(musb->clock, 1);
- else
- clk_enable(musb->clock);
- /*
- * This is a custom implementation of nop-usb-xceiv, introduced
- * because the original one does not support multiple instances.
- * This will be replaced by ulpi trainsceiver after moving to
- * kernel 2.6.33
- */
- musb->xceiv = cartesio_nop_xceiv_register();
- if (!musb->xceiv) {
- dev_err(musb->controller, "No transceiver configuredn");
- return -ENODEV;
- }
- if (is_host_enabled(musb))
- musb->board_set_vbus = cartesio_set_vbus;
- setup_timer(&musb->idle_timer, musb_do_idle, (unsigned long)musb);
- if (musb_controller_is(musb, "musb_sta2062_ulpi") ||
- musb_controller_is(musb, "musb_sta2065_ulpi")) {
- ret = musb_cartesio_ulpi_init(musb);
- if (ret)
- return ret;
- }
- if (musb_controller_is(musb, "musb_sta2065_ephyfs"))
- musb_sta2065_ephyfs_init(musb);
- if (musb_controller_is(musb, "musb_sta2062_ephy"))
- musb_sta2062_ephy_enable(musb);
- return 0;
- }
- static void musb_generic_disable(struct musb *musb)
- {
- void __iomem *mbase = musb->mregs;
- u16 temp;
- /* disable interrupts */
- musb_writeb(mbase, MUSB_INTRUSBE, 0);
- musb_writew(mbase, MUSB_INTRTXE, 0);
- musb_writew(mbase, MUSB_INTRRXE, 0);
- /* off */
- musb_writeb(mbase, MUSB_DEVCTL, 0);
- /* flush pending interrupts */
- temp = musb_readb(mbase, MUSB_INTRUSB);
- temp = musb_readw(mbase, MUSB_INTRTX);
- temp = musb_readw(mbase, MUSB_INTRRX);
- }
- /*
- * Handles OTG hnp timeouts, such as b_ase0_brst
- */
- void musb_otg_timer_func(unsigned long data)
- {
- struct musb *musb = (struct musb *)data;
- unsigned long flags;
- spin_lock_irqsave(&musb->lock, flags);
- switch (musb->xceiv->state) {
- case OTG_STATE_B_WAIT_ACON:
- DBG(1, "HNP: b_wait_acon timeout; back to b_peripheraln");
- musb_g_disconnect(musb);
- musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
- musb->is_active = 0;
- break;
- case OTG_STATE_A_SUSPEND:
- case OTG_STATE_A_WAIT_BCON:
- DBG(1, "HNP: %s timeoutn", otg_state_string(musb));
- musb_set_vbus(musb, 0);
- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
- break;
- default:
- DBG(1, "HNP: Unhandled mode %sn", otg_state_string(musb));
- }
- musb->ignore_disconnect = 0;
- spin_unlock_irqrestore(&musb->lock, flags);
- }
- /* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
- * configure endpoints, or take their config from silicon
- */
- static int MUSB_INIT musb_core_init(u16 musb_type, struct musb *musb)
- {
- u8 reg;
- char *type;
- char aInfo[90], aRevision[32], aDate[12];
- void __iomem *mbase = musb->mregs;
- int status = 0;
- int i;
- /* log core options (read using indexed model) */
- reg = musb_read_configdata(mbase);
- strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8"); //在aInfo中添加一堆后缀
- if (reg & MUSB_CONFIGDATA_DYNFIFO) {
- strcat(aInfo, ", dyn FIFOs");
- musb->dyn_fifo = true;
- }
- if (reg & MUSB_CONFIGDATA_MPRXE) {
- strcat(aInfo, ", bulk combine");
- musb->bulk_combine = true;
- }
- if (reg & MUSB_CONFIGDATA_MPTXE) {
- strcat(aInfo, ", bulk split");
- musb->bulk_split = true;
- }
- if (reg & MUSB_CONFIGDATA_HBRXE) {
- strcat(aInfo, ", HB-ISO Rx");
- musb->hb_iso_rx = true;
- }
- if (reg & MUSB_CONFIGDATA_HBTXE) {
- strcat(aInfo, ", HB-ISO Tx");
- musb->hb_iso_tx = true;
- }
- if (reg & MUSB_CONFIGDATA_SOFTCONE)
- strcat(aInfo, ", SoftConn");
- printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)n",
- musb_driver_name, reg, aInfo);
- aDate[0] = 0;
- if (MUSB_CONTROLLER_MHDRC == musb_type) {
- musb->is_multipoint = 1;
- type = "M";
- } else {
- musb->is_multipoint = 0;
- type = "";
- #ifdef CONFIG_USB_MUSB_HDRC_HCD
- #ifndef CONFIG_USB_OTG_BLACKLIST_HUB
- printk(KERN_ERR
- "%s: kernel must blacklist external hubsn",
- musb_driver_name);
- #endif
- #endif
- }
- /* log release info */
- musb->hwvers = musb_read_hwvers(mbase);
- snprintf(aRevision, 32, "%d.%d%s", MUSB_HWVERS_MAJOR(musb->hwvers),
- MUSB_HWVERS_MINOR(musb->hwvers),
- (musb->hwvers & MUSB_HWVERS_RC) ? "RC" : "");
- printk(KERN_DEBUG "%s: %sHDRC RTL version %s %sn", //打印出 hdrc 内容
- musb_driver_name, type, aRevision, aDate);
- /* configure ep0 */
- musb_configure_ep0(musb); //configure musb 的 ep0
- /* discover endpoint configuration */
- musb->nr_endpoints = 1;
- musb->epmask = 1;
- if (musb->dyn_fifo)
- status = ep_config_from_table(musb); //from table
- else
- status = ep_config_from_hw(musb); // hardware config
- if (status < 0)
- return status;
- /* finish init, and print endpoint config */
- for (i = 0; i < musb->nr_endpoints; i++) {
- struct musb_hw_ep *hw_ep = musb->endpoints + i;
- hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
- #ifdef CONFIG_USB_TUSB6010
- hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);
- hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);
- hw_ep->fifo_sync_va =
- musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i);
- if (i == 0)
- hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF;
- else
- hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2);
- #endif
- hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;
- #ifdef CONFIG_USB_MUSB_HDRC_HCD
- hw_ep->target_regs = musb_read_target_reg_base(i, mbase);
- hw_ep->rx_reinit = 1;
- hw_ep->tx_reinit = 1;
- #endif
- if (hw_ep->max_packet_sz_tx) {
- DBG(1,
- "%s: hw_ep %d%s, %smax %dn",
- musb_driver_name, i,
- hw_ep->is_shared_fifo ? "shared" : "tx",
- hw_ep->tx_double_buffered
- ? "doublebuffer, " : "",
- hw_ep->max_packet_sz_tx);
- }
- if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) {
- DBG(1,
- "%s: hw_ep %d%s, %smax %dn",
- musb_driver_name, i,
- "rx",
- hw_ep->rx_double_buffered
- ? "doublebuffer, " : "",
- hw_ep->max_packet_sz_rx);
- }
- if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx))
- DBG(1, "hw_ep %d not configuredn", i);
- }
- return 0;
- }
- static inline void musb_configure_ep0(struct musb *musb)
- {
- musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
- musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
- musb->endpoints[0].is_shared_fifo = true;
- }
- static int MUSB_INIT ep_config_from_table(struct musb *musb)
- {
- const struct fifo_cfg *cfg;
- unsigned i, n;
- int offset;
- struct musb_hw_ep *hw_ep = musb->endpoints;
- switch (fifo_mode) {
- default:
- fifo_mode = 0;
- /* FALLTHROUGH */
- case 0:
- cfg = mode_0_cfg;
- n = ARRAY_SIZE(mode_0_cfg);
- break;
- case 1:
- cfg = mode_1_cfg;
- n = ARRAY_SIZE(mode_1_cfg);
- break;
- case 2:
- cfg = mode_2_cfg;
- n = ARRAY_SIZE(mode_2_cfg);
- break;
- case 3:
- cfg = mode_3_cfg;
- n = ARRAY_SIZE(mode_3_cfg);
- break;
- case 4:
- cfg = mode_4_cfg;
- n = ARRAY_SIZE(mode_4_cfg);
- break;
- case 5:
- cfg = mode_5_cfg;
- n = ARRAY_SIZE(mode_5_cfg);
- break;
- }
- printk(KERN_DEBUG "%s: setup fifo_mode %dn",
- musb_driver_name, fifo_mode);
- offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);
- /* assert(offset > 0) */
- /* NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would
- * be better than static musb->config->num_eps and DYN_FIFO_SIZE...
- */
- for (i = 0; i < n; i++) {
- u8 epn = cfg->hw_ep_num;
- if (epn >= musb->config->num_eps) {
- pr_debug("%s: invalid ep %dn",
- musb_driver_name, epn);
- return -EINVAL;
- }
- offset = fifo_setup(musb, hw_ep + epn, cfg++, offset);
- if (offset < 0) {
- pr_debug("%s: mem overrun, ep %dn",
- musb_driver_name, epn);
- return -EINVAL;
- }
- epn++;
- musb->nr_endpoints = max(epn, musb->nr_endpoints);
- }
- printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memoryn",
- musb_driver_name,
- n + 1, musb->config->num_eps * 2 - 1,
- offset, (1 << (musb->config->ram_bits + 2)));
- #ifdef CONFIG_USB_MUSB_HDRC_HCD
- if (!musb->bulk_ep) {
- pr_debug("%s: missing bulkn", musb_driver_name);
- return -EINVAL;
- }
- #endif
- return 0;
- }
fifo_mode 定义:
- #if defined(CONFIG_USB_TUSB6010) ||
- defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
- static ushort MUSB_INITDATA fifo_mode = 4;
- #elif defined(CONFIG_ARCH_CARTESIO)
- static ushort MUSB_INITDATA fifo_mode = 5;
- #else
- static ushort MUSB_INITDATA fifo_mode = 2;
- #endif
fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
const struct fifo_cfg *cfg, u16 offset) ------------- 给endpoint 配置性能
- /*
- * configure a fifo; for non-shared endpoints, this may be called
- * once for a tx fifo and once for an rx fifo.
- *
- * returns negative errno or offset for next fifo.
- */
- static int MUSB_INIT
- fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
- const struct fifo_cfg *cfg, u16 offset)
- {
- void __iomem *mbase = musb->mregs;
- int size = 0;
- u16 maxpacket = cfg->maxpacket;
- u16 c_off = offset >> 3;
- u8 c_size;
- /* expect hw_ep has already been zero-initialized */
- size = ffs(max(maxpacket, (u16) 8)) - 1;
- maxpacket = 1 << size;
- c_size = size - 3;
- if (cfg->mode == BUF_DOUBLE) {
- if ((offset + (maxpacket << 1)) >
- (1 << (musb->config->ram_bits + 2)))
- return -EMSGSIZE;
- c_size |= MUSB_FIFOSZ_DPB;
- } else {
- if ((offset + maxpacket) > (1 << (musb->config->ram_bits + 2)))
- return -EMSGSIZE;
- }
- /* configure the FIFO */
- musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum);
- #ifdef CONFIG_USB_MUSB_HDRC_HCD
- /* EP0 reserved endpoint for control, bidirectional;
- * EP1 reserved for bulk, two unidirection halves.
- */
- if (hw_ep->epnum == 1)
- musb->bulk_ep = hw_ep;
- /* REVISIT error check: be sure ep0 can both rx and tx ... */
- #endif
- switch (cfg->style) {
- case FIFO_TX:
- musb_write_txfifosz(mbase, c_size);
- musb_write_txfifoadd(mbase, c_off);
- hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
- hw_ep->max_packet_sz_tx = maxpacket;
- break;
- case FIFO_RX:
- musb_write_rxfifosz(mbase, c_size);
- musb_write_rxfifoadd(mbase, c_off);
- hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
- hw_ep->max_packet_sz_rx = maxpacket;
- break;
- case FIFO_RXTX:
- musb_write_txfifosz(mbase, c_size);
- musb_write_txfifoadd(mbase, c_off);
- hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
- hw_ep->max_packet_sz_rx = maxpacket;
- musb_write_rxfifosz(mbase, c_size);
- musb_write_rxfifoadd(mbase, c_off);
- hw_ep->tx_double_buffered = hw_ep->rx_double_buffered;
- hw_ep->max_packet_sz_tx = maxpacket;
- hw_ep->is_shared_fifo = true;
- break;
- }
- /* NOTE rx and tx endpoint irqs aren't managed separately,
- * which happens to be ok
- */
- musb->epmask |= (1 << hw_ep->epnum);
- return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
- }
- /*
- * tables defining fifo_mode values. define more if you like.
- * for host side, make sure both halves of ep1 are set up.
- */
- /* mode 0 - fits in 2KB */
- static struct fifo_cfg MUSB_INITDATA mode_0_cfg[] = {
- { .hw_ep_num = 1, .><br>
- <p></p>
最后
以上就是热情小伙为你收集整理的musb_core.c 是usb_general.c 调用进musb模块的核心函数,的全部内容,希望文章能够帮你解决musb_core.c 是usb_general.c 调用进musb模块的核心函数,所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复