平台:OMAP4470,linix3.4,Android4.2平台。
问题:
1. usb host/otg模式切换的时候容易导致系统卡顿,甚至死机。
2. omap4470的usb接了一个usb-Ethernet,正常情况下,omap4470的usb模式应该是host,但是有时候会工作模式不对,重新设置host mode也可让usb-Ethernet工作正常,需要排除是usb模式切换导致的这个问题。
3. 偶尔触发usb dongle无论怎么插拔,omap4470都没检测出usb事件儿。这个可能原因:
a.usb 模式不对。
b.vbus设置有问题。
c.omap4470 usb host 某些寄存器的值设置不对。

要想解决以上三个问题,都跟usb模式和vbus有关,那么就需要深度分析一下usb模式和vbus设置的代码。

一、首先分析一下平台相关的。
看arch/arm/mach-omap2/目录下;

jizhao@star:~/omap/kernel/android-3.4/arch/arm/mach-omap2$ ls *usb*
usb-dwc3.c  usb-fs.c    usb-host.o  usb-musb.o
usb-dwc3.o  usb-host.c  usb-musb.c  usb-tusb6010.c

在usb-musb.c中定义了usb_musb_init。

void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
{struct omap_hwmod       *oh;struct platform_device      *pdev;struct device           *dev;int             bus_id = -1;const char          *oh_name, *name;struct omap_musb_board_data *board_data;if (musb_board_data)board_data = musb_board_data;elseboard_data = &musb_default_board_data;/** REVISIT: This line can be removed once all the platforms using* musb_core.c have been converted to use use clkdev.*/musb_plat.clock = "ick";musb_plat.board_data = board_data;musb_plat.power = board_data->power>> 1;//why ?musb_plat.mode = board_data->mode;musb_plat.extvbus = board_data->extvbus;printk("%s %s %d musb_plat.power is %d\n",__FILE__,__func__,__LINE__,musb_plat.power);if (cpu_is_omap3517() || cpu_is_omap3505()) {oh_name = "am35x_otg_hs";name = "musb-am35x";} else if (cpu_is_ti81xx()) {oh_name = "usb_otg_hs";name = "musb-ti81xx";} else {oh_name = "usb_otg_hs";name = "musb-omap2430";}oh = omap_hwmod_lookup(oh_name);if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",__func__, oh_name))return;pdev = omap_device_build(name, bus_id, oh, &musb_plat,sizeof(musb_plat), NULL, 0, false);if (IS_ERR(pdev)) {pr_err("Could not build omap_device for %s %s\n",name, oh_name);return;}dev = &pdev->dev;get_device(dev);dev->dma_mask = &musb_dmamask;dev->coherent_dma_mask = musb_dmamask;put_device(dev);
}
在board-44xx-tablet.c中定义了
**omap_tablet_init--->  usb_musb_init(&musb_board_data);**
而omap_table_init则是有machine_desc定义的。
MACHINE_START(OMAP_BLAZE, "OMAP44XX Tablet board").atag_offset    = 0x100,.reserve    = omap_tablet_reserve,.map_io     = omap4_map_io,.init_early = omap_tablet_init_early,.init_irq   = gic_init_irq,.handle_irq = gic_handle_irq,**.init_machine = omap_tablet_init**,.timer      = &omap4_timer,.restart    = omap_prcm_restart,
MACHINE_END

它的参数定义在本文件内:

static struct omap_musb_board_data musb_board_data = {.interface_type     = MUSB_INTERFACE_UTMI,.mode           = MUSB_OTG,.power          = 500,
};

在usb_musb_init中的最后执行了omap_device_build,这个函数是干啥呢?进去看一下:

struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id,struct omap_hwmod *oh, void *pdata,int pdata_len,struct omap_device_pm_latency *pm_lats,int pm_lats_cnt, int is_early_device)
{struct omap_hwmod *ohs[] = { oh };if (!oh)return ERR_PTR(-EINVAL);return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,pdata_len, pm_lats, pm_lats_cnt,is_early_device);
}
struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id,struct omap_hwmod **ohs, int oh_cnt,void *pdata, int pdata_len,struct omap_device_pm_latency *pm_lats,int pm_lats_cnt, int is_early_device)
{int ret = -ENOMEM;struct platform_device *pdev;struct omap_device *od;if (!ohs || oh_cnt == 0 || !pdev_name)return ERR_PTR(-EINVAL);if (!pdata && pdata_len > 0)return ERR_PTR(-EINVAL);pdev = platform_device_alloc(pdev_name, pdev_id);if (!pdev) {ret = -ENOMEM;goto odbs_exit;}/* Set the dev_name early to allow dev_xxx in omap_device_alloc */if (pdev->id != -1)dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);elsedev_set_name(&pdev->dev, "%s", pdev->name);od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);if (!od)goto odbs_exit1;ret = platform_device_add_data(pdev, pdata, pdata_len);if (ret)goto odbs_exit2;if (is_early_device)ret = omap_early_device_register(pdev);elseret = omap_device_register(pdev);if (ret)goto odbs_exit2;omap_opp_register(&pdev->dev, ohs[0]->name);return pdev;odbs_exit2:omap_device_delete(od);
odbs_exit1:platform_device_put(pdev);
odbs_exit:pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);return ERR_PTR(ret);
}

不用继续看了吧,继续看也没啥意思,浪费时间,其实就是执行platform_device_register。
重点关心传递的参数:

    pdev = omap_device_build(name, bus_id, oh, &musb_plat,sizeof(musb_plat), NULL, 0, false);/*其中第一个参数name为oh_name = "usb_otg_hs";name = "musb-omap2430";第四个参数musb_plat。被platform_device_add_data设置为pdev->dev.platform_data。即名字为musb-omap2430的platform_devices的dev.platform_data.稍后看看这个有什么作用。
*/
static struct musb_hdrc_config musb_config = {.multipoint = 1,.dyn_fifo   = 1,.num_eps    = 16,.ram_bits   = 12,
};
static struct musb_hdrc_platform_data musb_plat = {
#ifdef CONFIG_USB_MUSB_OTG.mode       = MUSB_OTG,
#elif defined(CONFIG_USB_MUSB_HDRC_HCD).mode       = MUSB_HOST,//内核配置为host。
#elif defined(CONFIG_USB_GADGET_MUSB_HDRC).mode       = MUSB_PERIPHERAL,
#endif/* .clock is set dynamically */.config     = &musb_config,/* REVISIT charge pump on TWL4030 can supply up to* 100 mA ... but this value is board-specific, like* "mode", and should be passed to usb_musb_init().*/.power      = 50,           /* up to 100 mA */ **//为什么要设置为50?**
};

对上述流程做个总结:

在arch/arm/mach-omap2/usb_musb.c.。
通过usb_musb_init注册了一个platform_device。这个platform_device的内容可以看做是如下的形式:
struct platform_device  omap2_usb_musb_devices={
.name="musb-omap2430",
.dev.platform_data=musb_plat,
};其中musb_plat为:
static struct musb_hdrc_platform_data musb_plat = {.mode       = MUSB_HOST,.config     = &musb_config,.power      = 50>>1,            /* up to 100 mA */.clock = "ick";.board_data=&musb_plat,.extvbus=//暂时不知道等于什么。.platform_ops=//这里没有初始化,应该在driver的probe有赋值,稍后再看。
};
static struct musb_hdrc_config musb_config = {.multipoint = 1,.dyn_fifo   = 1,.num_eps    = 16,.ram_bits   = 12,
};

*以上仅仅是注册了一个Platform_device,而且这个过程是在内核早期初始化完成的。它初始化了一些usb模式、电流、fifo,clk寄存器地址等变量,并没有真正的操作usb host的寄存器。通常情况下,这些变量会在platform_driver中被使用,稍后要分析一下同名的platform_driver的probe函数。
搜索内核代码”musb-omap2430”*
搜索结果发现,在driver/usb/musb/omap2430.c中定义了。

static struct platform_driver omap2430_driver = {.probe      = omap2430_probe,.remove     = __devexit_p(omap2430_remove),.driver     = {.name   = "musb-omap2430",.pm = DEV_PM_OPS,},
};

那么我们就分析一下这个probe函数。

static int __devinit omap2430_probe(struct platform_device *pdev)
{struct musb_hdrc_platform_data  *pdata = pdev->dev.platform_data;//这正是usb-musb.c中定义的 musb_hdrc_platform_data musb_plat。struct platform_device      *musb;struct omap2430_glue        *glue;int             ret = -ENOMEM;glue = kzalloc(sizeof(*glue), GFP_KERNEL);if (!glue) {dev_err(&pdev->dev, "failed to allocate glue context\n");goto err0;}musb = platform_device_alloc("musb-hdrc", -1);if (!musb) {dev_err(&pdev->dev, "failed to allocate musb device\n");goto err1;}musb->dev.parent        = &pdev->dev;musb->dev.dma_mask      = &omap2430_dmamask;musb->dev.coherent_dma_mask = omap2430_dmamask;glue->dev           = &pdev->dev;glue->musb          = musb;glue->status            = OMAP_MUSB_UNKNOWN;glue->control_dev       = omap_control_get();pdata->platform_ops     = &omap2430_ops;platform_set_drvdata(pdev, glue);/** REVISIT if we ever have two instances of the wrapper, we will be* in big trouble*/_glue   = glue;INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);ret = platform_device_add_resources(musb, pdev->resource,pdev->num_resources);if (ret) {dev_err(&pdev->dev, "failed to add resources\n");goto err2;}ret = platform_device_add_data(musb, pdata, sizeof(*pdata));if (ret) {dev_err(&pdev->dev, "failed to add platform_data\n");goto err2;}pm_runtime_enable(&pdev->dev);ret = platform_device_add(musb);if (ret) {dev_err(&pdev->dev, "failed to register musb device\n");goto err2;}wake_lock_init(&glue->omap_musb_wakelock, WAKE_LOCK_SUSPEND,"omap_musb_wakelock");return 0;err2:platform_device_put(musb);err1:kfree(glue);err0:return ret;
}

这个probe函数又注册了一个platform_device,它的名字为musb-hdrc,稍后再分析musb-hdrc对于的platform_driver.
在这个probe函数中,申请了两个非常重要的变量。 struct omap2430_glue *glue;struct platform_device 。
上述的 struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
正是usb_musb_init中的musb_plat.

在omap2430_probe中对musb_plat的platform_ops进行了赋值。pdata->platform_ops     = &omap2430_ops,musb->dev->p->driver_data=glue.musb->dev.platform_data=pdata=pdev->dev.platform_data=arch/arm/mach-omap2/usb-musb.c中定义的musb_plat 所以musb_plat的platform_ops=omap2430_ops.
    ret = platform_device_add_resources(musb, pdev->resource,pdev->num_resources);
/*musb的资源都被定义在了platform_device中,跟踪一下这个resource。名字为"musb-omap2430"的platform_device定义了哪些资源呢?*/

回过头来看arch/arm/mach-omap2目录下的代码,在omap_device_build_ss有个参数omap_hwmod,omap_device_alloc使用参数omap_hwmod来初始化了资源。

void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
{......oh = omap_hwmod_lookup(oh_name);if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",__func__, oh_name))return;pdev = omap_device_build(name, bus_id, oh, &musb_plat,sizeof(musb_plat), NULL, 0, false);......
}
接着分析一下omap_hwmod_lookup.
struct omap_hwmod *omap_hwmod_lookup(const char *name)
{struct omap_hwmod *oh;if (!name)return NULL;oh = _lookup(name);/* check access flag */if (oh && oh->flags & HWMOD_ACCESS_DISABLED) {pr_warning("omap_hwmod: %s: access denied\n", oh->name);oh = NULL;}return oh;
}
static struct omap_hwmod *_lookup(const char *name)
{struct omap_hwmod *oh, *temp_oh;oh = NULL;list_for_each_entry(temp_oh, &omap_hwmod_list, node) {if (!strcmp(name, temp_oh->name)) {oh = temp_oh;break;}}return oh;
}

原来是从链表omap_hwmod_list中取出来的,那么什么时候添加这个链表呢?一路追踪。发现了omap_hwmod_register函数。这个函数就在omap44xx_hwmod_init中被调用。

现在总结一下建立usb platform资源的过程:
MACHINE_START(OMAP_BLAZE, "OMAP44XX Tablet board").atag_offset    = 0x100,.reserve    = omap_tablet_reserve,.map_io     = omap4_map_io,.init_early = omap_tablet_init_early,.init_irq   = gic_init_irq,.handle_irq = gic_handle_irq,.init_machine   = omap_tablet_init,.timer      = &omap4_timer,.restart    = omap_prcm_restart,
MACHINE_END
这里面有个omap_tablet_init_early---->omap4430_init_early---->omap44xx_hwmod_init---->omap_hwmod_register(omap44xx_hwmods);
其中static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
......
omap44xx_usb_otg_hs_hwmod
......
};

omap44xx_usb_otg_hs_hwmod的内容如下:

static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {.name       = "usb_otg_hs",.class      = &omap44xx_usb_otg_hs_hwmod_class,.clkdm_name = "l3_init_clkdm",.flags      = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,.mpu_irqs   = omap44xx_usb_otg_hs_irqs,.main_clk   = "usb_otg_hs_ick",.prcm = {.omap4 = {.clkctrl_offs = OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET,.context_offs = OMAP4_RM_L3INIT_USB_OTG_CONTEXT_OFFSET,.modulemode   = MODULEMODE_HWCTRL,},},.opt_clks   = usb_otg_hs_opt_clks,.opt_clks_cnt   = ARRAY_SIZE(usb_otg_hs_opt_clks),.slaves     = omap44xx_usb_otg_hs_slaves,.slaves_cnt = ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),//这里就是资源.masters    = omap44xx_usb_otg_hs_masters,.masters_cnt    = ARRAY_SIZE(omap44xx_usb_otg_hs_masters),
};
static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {{.pa_start   = 0x4a0ab000,.pa_end     = 0x4a0ab003,.flags      = ADDR_TYPE_RT},{ }
};

到此
omap2430_probe
—–>platform_device_add_resources(musb, pdev->resource,
pdev->num_resources);
—–>这里面的resource,在内核早期初始化的时候已经被赋值了,其中断资源、地址资源都定义在了omap44xx_usb_otg_hs_hwmod ,其中IO地址资源就是

    .pa_start   = 0x4a0ab000,.pa_end     = 0x4a0ab003,

综上分析,在omap2430_probe中主要完成下列功能:

1. 申请一个名字为musb-hdrc的platform_device。    musb = platform_device_alloc("musb-hdrc", -1);
2.musb的dev->p-driver_data=glue.//glue是个很关键的变量。它记录了usb的模式,包含了usb的工作队列,和wake_lock。
3.musb的dev.platform_data=musb_plat
4.把上述musb 用platform_device_register注册到系统中。

到此为止,我们分析了名字为”musb-omap2430”的platform_devices和platform_driver的probe函数。并且在这个probe函数里注册了名字为
“musb-hdrc”的platform_devices.且,这个platform_device的内容为:


简单地说就是platform_device_register一个platform_device,这个devices的内容如下:
struct platform_device  musb={.name= "musb-hdrc".id= -1,.dev.parent= 名字为"musb-omap2430"platform_devices的dev//这就意味着/sys/devices/platform/.../musb_omap2430目录下将会出现一个musb-hdrc的文件夹。.dev.dma_mask= &omap2430_dmamask,.dev.coherent_dma_mask  = omap2430_dmamask,.dev->p->driver_data=glue,//glue.dev.platform_data=musb_plat.//platform_data..resouce={.start=0x4a0ab000,.end=0x4a0ab003}
};
其中:musb_plat
static struct musb_hdrc_platform_data musb_plat = {.mode       = MUSB_HOST,.config     = &musb_config,.power      = 50>>1,            /* up to 100 mA */.clock = "ick";.board_data=&musb_plat,.extvbus=//暂时不知道等于什么。.platform_ops= &omap2430_ops;
};
static struct musb_hdrc_config musb_config = {.multipoint = 1,.dyn_fifo   = 1,.num_eps    = 16,.ram_bits   = 12,
};
glue的内容为:glue->dev           = &pdev->dev;glue->musb          = musb;glue->status            = OMAP_MUSB_UNKNOWN;
INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);wake_lock_init(&glue->omap_musb_wakelock, WAKE_LOCK_SUSPEND,"omap_musb_wakelock");

很显然,系统中应该还存在一个名字为”musb-hdrc”的platform_driver.
搜索”musb-hdrc”。
在driver/usb/musb/musb_core.c中发现了

在musb_core.c中

#define MUSB_DRIVER_NAME "musb-hdrc"
const char musb_driver_name[] = MUSB_DRIVER_NAME;
static struct platform_driver musb_driver = {.driver = {.name       = (char *)musb_driver_name,.bus        = &platform_bus_type,.owner      = THIS_MODULE,.pm     = MUSB_DEV_PM_OPS,},.probe      = musb_probe,.remove     = __devexit_p(musb_remove),.shutdown   = musb_shutdown,
};module_init(musb_init);
static int __init musb_init(void)
{if (usb_disabled())return 0;musb_power_gpio = gpio_request(MUSB_POWER_EN, "usb_power_en");if (musb_power_gpio != 0) {printk("not able to acquire gpio %d\n", MUSB_POWER_EN);} else {gpio_direction_output(MUSB_POWER_EN, 1);}pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",musb_driver_name);return platform_driver_register(&musb_driver);
}

下面看一下它的probe函数。

static int __devinit musb_probe(struct platform_device *pdev)
{struct device   *dev = &pdev->dev;int     irq = platform_get_irq_byname(pdev, "mc");int     status;struct resource *iomem;void __iomem    *base;iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (!iomem || irq <= 0)return -ENODEV;base = ioremap(iomem->start, resource_size(iomem));if (!base) {dev_err(dev, "ioremap failed\n");return -ENOMEM;}printk("%s %s %d musb iomem->start is %p,base is %p,MUSB_DEVCTL=%d\n",__FILE__,__func__,__LINE__,iomem->start,base,MUSB_DEVCTL);//0x4a0ab000
#ifndef CONFIG_MUSB_PIO_ONLY/* clobbered by use_dma=n */orig_dma_mask = dev->dma_mask;
#endifstatus = musb_init_controller(dev, irq, base);if (status < 0){printk("musb_probe Failure\n");iounmap(base);}else if(status==0){printk("musb_probe success\n");}return status;
}

最重要的一个函数

static int __devinit
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;}/* allocate */musb = allocate_instance(dev, plat->config, ctrl);if (!musb) {status = -ENOMEM;goto fail0;}pm_runtime_use_autosuspend(musb->controller);pm_runtime_set_autosuspend_delay(musb->controller, 200);pm_runtime_enable(musb->controller);spin_lock_init(&musb->lock);musb->board_mode = plat->mode;musb->board_set_power = plat->set_power;musb->min_power = plat->min_power;musb->ops = plat->platform_ops;/* 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_phy()*   - stops powering VBUS** There are various transceiver 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;status = musb_platform_init(musb);if (status < 0)goto fail1;if (!musb->isr) {status = -ENODEV;goto fail2;}if (!musb->xceiv->io_ops) {musb->xceiv->io_dev = musb->controller;musb->xceiv->io_priv = musb->mregs;musb->xceiv->io_ops = &musb_ulpi_access;}pm_runtime_get_sync(musb->controller);#ifndef CONFIG_MUSB_PIO_ONLYif (use_dma && dev->dma_mask) {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;setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);setup_timer(&musbmode_cuttimer,modecut_delay_ms, (unsigned long)musb);/* 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 */if (is_host_enabled(musb)) {struct usb_hcd  *hcd = musb_to_hcd(musb);otg_set_host(musb->xceiv->otg, &hcd->self);if (is_otg_enabled(musb))hcd->self.otg_port = 1;musb->xceiv->otg->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)) {struct usb_hcd  *hcd = musb_to_hcd(musb);MUSB_HST_MODE(musb);musb->xceiv->otg->default_a = 1;musb->xceiv->state = OTG_STATE_A_IDLE;status = usb_add_hcd(musb_to_hcd(musb), 0, 0);hcd->self.uses_pio_for_control = 1;dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n","HOST", status,musb_readb(musb->mregs, MUSB_DEVCTL),(musb_readb(musb->mregs, MUSB_DEVCTL)& MUSB_DEVCTL_BDEVICE? 'B' : 'A'));} else /* peripheral is enabled */ {MUSB_DEV_MODE(musb);musb->xceiv->otg->default_a = 0;musb->xceiv->state = OTG_STATE_B_IDLE;status = musb_gadget_setup(musb);dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n",is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",status,musb_readb(musb->mregs, MUSB_DEVCTL));}if (status < 0)goto fail3;if (is_otg_enabled(musb) || is_host_enabled(musb))wake_lock_init(&musb->musb_wakelock, WAKE_LOCK_SUSPEND,"musb_autosuspend_wake_lock");status = musb_init_debugfs(musb);if (status < 0)goto fail4;#ifdef CONFIG_SYSFSstatus = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);if (status)goto fail5;
#endifpm_runtime_put(musb->controller);dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",({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;fail5:musb_exit_debugfs(musb);fail4:if (!is_otg_enabled(musb) && is_host_enabled(musb))usb_remove_hcd(musb_to_hcd(musb));elsemusb_gadget_cleanup(musb);if (is_otg_enabled(musb) || is_host_enabled(musb))wake_lock_destroy(&musb->musb_wakelock);fail3:pm_runtime_put_sync(musb->controller);fail2:if (musb->irq_wake)device_init_wakeup(dev, 0);musb_platform_exit(musb);fail1:dev_err(musb->controller,"musb_init_controller failed with status %d\n", status);musb_free(musb);fail0:return status;}

其中注册中断,otg的timer,musb_irq_work,debugfs、文件结点都在这个函数里面:

    musb->isr = generic_interrupt;status = musb_platform_init(musb);setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);setup_timer(&musbmode_cuttimer,modecut_delay_ms, (unsigned long)musb);/* 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;status = musb_init_debugfs(musb);if (status < 0)goto fail4;#ifdef CONFIG_SYSFSstatus = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);if (status)goto fail5;
#endif

上面说的有点乱,现在总结一下:

最终注册了一个platform_device。
|
|
|

接下来在omap2430.c中定义了同name的platform_driver
并且在它的probe函数中又创建了一个platform_device。


接下来的章节要研究这几个timer以及中断函数generic_interrupt。

Omap4470 USB驱动分析之注册过程相关推荐

  1. Uboot Beaglebone Black Usb驱动分析

    在驱动开发中,USB驱动是比较难以理解的部分,也是令驱动开发者比较头疼的,不仅是因为USB包括host端和设备端:USB的协议类型也非常多:数据传输的协议,控制协议,主控制器协议,设备相关的协议,硬件 ...

  2. USB驱动分析(三)

    分类: LINUX 需要注意的是,这些调试信息得是我们打开了编译选项CONFIG_USB_STORAGE_DEBUG才有意义的,这里也看出来了,如果这个选项为0,那么这几个宏就什么也不干,因为它们被赋 ...

  3. USB驱动分析(一)

    原文:http://blog.chinaunix.net/space.php?uid=12051988&do=blog&id=2963109 这个故事中使用的是2.6.10的内核代码. ...

  4. linux dwc3 usb驱动分析

    基于linux 4.9内核 源码: drivers/usb/dw3/core.c 主要完成DesignWare USB3.0 Controller phy初始化,以及模式选择. static stru ...

  5. Linux USB驱动分析(一)----USB2.0协议分析

    原文地址:http://blog.chinaunix.net/uid-25445243-id-4040449.html 一.USB硬件介绍 1.1.概述 一条USB传输线分别由地线.电源线.D+和D- ...

  6. 【linux驱动】USB子系统分析

    本文针对Linux内核下USB子系统进行分析,主要会涉及一下几个方面: USB基础知识:介绍USB设备相关的基础知识 Linux USB子系统分析:分析USB系统框架,USB HCD/ROOT HUB ...

  7. USB驱动及其源码分析

    一.USB理论部分 1.USB概述 USB1.0版本速度1.5Mbps(低速USB). USB1.1版本速度12Mbps(全速USB). USB2.0版本速度480Mbps(高速USB).USB3.0 ...

  8. linux设备驱动之USB主机控制器驱动分析

    http://www.cnblogs.com/sdphome/archive/2011/09/29/2195791.html 一:前言 Usb是一个很复杂的系统.在usb2.0规范中,将其定义成了一个 ...

  9. Linux USB驱动框架分析 【转】

    转自:http://blog.chinaunix.net/uid-11848011-id-96188.html 初次接触与OS相关的设备驱动编写,感觉还挺有意思的,为了不至于忘掉看过的东西,笔记跟总结 ...

最新文章

  1. js中json的添加和指定位置的删除
  2. 关闭虚拟机提示“正在处理另一个任务”解决方法
  3. Yoda 表示法错在哪里
  4. 计算机学的语数英大概是那些,职高如果选电子商务专业那是不是要学语数英
  5. Sharepoint2007个人网站不能同步域信息的处理方法
  6. 关于模拟器Hyper-v中的Wp8网络连接问题
  7. Struts2.3.4.1 + Spring3.1.2 + Hibernate4.1.6整合
  8. Linux CentOS7 下安装 TeamViewer
  9. C#学习常用类(1003)---Timer类(System.Timers.Timer)
  10. Android开发之SharedPreferences
  11. mtk屏幕背光默认时间修改
  12. Android 文字转语音之TextToSpeech
  13. 暗影精灵4电脑win10系统重装+linux双系统安装
  14. python自行实现支付宝证书签名验签全流程
  15. 20个案例掌握PL/SQL 基础
  16. npm login报错:npm notice Beginning October 4, 2021, all connections to the npm registry.......
  17. 软件工程之PERT图 (AOA与AON)
  18. Java_常瑞鹏 java_网络编程实现一个 聊天程序
  19. Linux中TCP listen()的参数
  20. 房屋租赁合同中押金的法律性质分析

热门文章

  1. excel制作文件夹侧标签
  2. Android平台体验分析报告
  3. 【SSL1607】没有上司的晚会【树形DP】
  4. 最#全#的#海#淘#网#址#大#全
  5. 换钱计划调用函数c语言编程,CCF NOI1034 钞票兑换
  6. 2022年种子行业分析
  7. vscode如何自定义背景图片
  8. 再传捷报!人大金仓获2022年中国信创产业拳头奖“最佳数据库品牌”大奖
  9. 力扣707设计链表(单链表,JavaScript)
  10. word小技巧--怎么去掉Word文档封面页码的方法