1.在board-am335xevm.c中有关于musb设备的定义

static struct omap_musb_board_data musb_board_data = {.interface_type = MUSB_INTERFACE_ULPI,/** mode[0:3] = USB0PORT's mode* mode[4:7] = USB1PORT's mode* AM335X beta EVM has USB0 in OTG mode and USB1 in host mode.*/// .mode = (MUSB_HOST << 4) | MUSB_OTG,.mode = (MUSB_HOST << 4) | MUSB_HOST,.power = 500,.instances = 1,};

然后对usb设备进行初始化

usb_musb_init(&musb_board_data);

该函数填充了设备名称name = "musb-ti81xx"

并且调用了omap_device_build();

进行USB设备注册

omap_device_buitd-->omap_device_build_ss()->omap_device_register(pdev)

2.ti81xx.c中有关于musb驱动的定义

static struct platform_driver ti81xx_musb_driver = {.remove = __exit_p(ti81xx_remove),.driver = {.name = "musb-ti81xx",.pm = DEV_PM_OPS,},};

以及一个函数指针操作集合

static struct musb_platform_ops ti81xx_ops = {.fifo_mode = 4,.flags = MUSB_GLUE_EP_ADDR_FLAT_MAPPING | MUSB_GLUE_DMA_CPPI41,.init = ti81xx_musb_init,.exit = ti81xx_musb_exit,.enable = ti81xx_musb_enable,.disable = ti81xx_musb_disable,.try_idle = ti81xx_musb_try_idle,.set_mode = ti81xx_musb_set_mode,.read_fifo = ti81xx_musb_read_fifo,.write_fifo = musb_write_fifo,.dma_controller_create = cppi41_dma_controller_create,.dma_controller_destroy = cppi41_dma_controller_destroy,.simulate_babble_intr = musb_simulate_babble,#ifdef CONFIG_USB_TI_CPPI41_DMA.txfifoempty_intr_enable = txfifoempty_intr_enable,.txfifoempty_intr_disable = txfifoempty_intr_disable,#endif.reinit = musb_reinit,.enable_sof = ti81xx_musb_enable_sof,.disable_sof = ti81xx_musb_disable_sof};

在ti81xx_glue_init(void)中填充probe函数到drv中

platform_driver_probe()-->drv->probe = probe-->platform_driver_register(drv)

3.ti81xx_probe()最后会调用ti81xx_create_musb_pdev()

这个函数有俩个变量较为重要

struct musb_hdrc_platform_data *pdata = dev->platform_data;struct platform_device *musb;

后面会为musb申请内存空间,以及填充内部数据结构需要注意的是操作函数集合的填充,就是上面我们定义的那些操作函数。pdata->platform_ops= &ti81xx_ops;后面会打印dev_info(dev, "musb%d, board_mode=0x%x, plat_mode=0x%x\n",id, bdata->mode, pdata->mode);就是我们在内核启动信息中看到的musb-ti81xx musb-ti81xx: musb0, board_mode=0x11, plat_mode=0x1,musb-ti81xx musb-ti81xx: musb1, board_mode=0x11, plat_mode=0x1。

最后调用 platform_device_add(musb)添加musb主控制器设备

4.在musb_core.c中会注册一个驱动

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 = __exit_p(musb_remove),.shutdown = musb_shutdown,};static int __init musb_init(void){if (usb_disabled())return 0;pr_info("%s: version " MUSB_VERSION ", ""?dma?"", ""otg (peripheral+host)",musb_driver_name);return platform_driver_register(&musb_driver);}

在musb_init中会首先判断usb的使能,然后输出一条打印信息。就是我们在内核打印中看到的

musb-hdrc: version 6.0, ?dma?, otg (peripheral+host),接着调用 platform_driver_register注册驱动程序,在总线上寻找对应的设备,匹配成功后调用对应的probe函数 musb_probe(),在musb_probe函数中首先会对device的部分属性进行判断填充然后会调用musb_init_controller(dev, irq, base)初始化musb主控制器。

musb_init_controller(dev, irq, base)首先是内存申请,以及电源管理的配置,接着填充musb的各项属性,需要关注的是musb->ops = plat->platform_ops这句赋值。这里的的platform_ops就是我们之前在设备初始化那边传进来的static struct musb_platform_ops ti81xx_ops。后面会输出打印信息dev_info (dev, "dma type: %s\n", get_dma_name(musb))就是我们在内核打印信息中看到的musb-hdrc musb-hdrc.0: dma type: dma-cppi41。

下面是中断函数的填充musb->isr = generic_interrupt。我们找到该中断函数的定义,通过config配置可以发现这个函数其实指向了NULL。接着是status = musb_platform_init(musb)。我们直接查看该函数的原型

static inline int musb_platform_init(struct musb *musb){if (!musb->ops->init)return -EINVAL;return musb->ops->init(musb);}

该函数调用了设备的操作集合中的初始化函数,而我们知道这个集合就是 ti81xx_ops,在ti81xx_ops里找到init函数ti81xx_musb_init(struct musb *musb)。该函数中前面可以看到pr_info("MUSB%d controller's USBSS revision = %08x\n", musb->id, rev),也就是我们在内核打印信息中看到的MUSB0 controller's USBSS revision = 4ea20800。id是驱动传递过来的第一个MUSB传的是0,第二个人传的是1,revision是通过读取SOC寄存器得到的。经过一系列的寄存器设置我们可以看到 musb->isr = ti81xx_interrupt。这里musb的中断函数被正式绑定。接着是data->set_phy_power,我们在usb_musb_init()中设置board_data->set_phy_power = ti81xx_musb_phy_power,这里就会运行

ti81xx_musb_phy_power(),该函数中打印了内核信息host-only。后面musb_platform_set_mode()中会调用ti81xx_musb_set_mode。我们在musb_board_data中定义了俩路usb均为host这里就会被设置为host模式。紧接着是musb->txfifo_intr_enable的判断,我们不深入分析,由内核的打印信息TxFifo Empty intr disabled,可知这里txfifo_intr_enable是有值的。最后是我们的babble_ctrl判断。在 usb_musb_init()我们对这个值进行了赋值。我们不详细研究,只从musb0: Enabled SW babble control打印信息中可以推测出这个值部不为0.

现在我们回到musb_init_controller()中,现在我们知道status = musb_platform_init(musb)执行成功后,它发生的结果中包含了我们向musb绑定了一个中断函数。接着经过一系列设置我们运行了下面这个函数musb_core_init();该函数内打印了一些我们在内核中看到的信息musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, bulk combine, bulk split, HB-ISO Rx, HB-ISO Tx, SoftConn)

musb-hdrc: MHDRC RTL version 2.0musb-hdrc: setup fifo_mode 4musb-hdrc: 28/31 max ep, 16384/16384 memorymusb-hdrc.0: bulk split disabledmusb-hdrc.0: bulk combine disabled。

里面主要涉及到的书mbus主控制器核心部分的初始化。

接着回到musb_init_controller()中,if (!is_otg_enabled(musb) && is_host_enabled(musb)),由于我们的设置这里判断条件成立,所以会运行status = usb_add_hcd(musb_to_hcd(musb), -1, 0)。注册我们的USB主机控制器。关于主机控制机hcd部分不详细说明,我们只注意到在这个函数中我们为USB主机控制器申请了数据缓存hcd_buffer_create(hcd),向USB总线驱动注册了USB主机控制器usb_register_bus(&hcd->self),并为USB主机控制器申请了内存usb_alloc_dev(NULL, &hcd->self, 0)。另外在刚进入usb_add_hcd()时,会打印hcd->product_desc。就是内核打印信息中的musb-hdrc musb-hdrc.0: MUSB HDRC host driver。它来自于musb_host.c中的const struct hc_driver musb_hc_driver 结构体中的product_desc,这里不详细说明。在执行usb_register_bus时会打印另一条信息dev_info (bus->controller, "new USB bus registered, assigned bus ""number %d\n", bus->busnum);就是我们在内核打印信息中看到的musb-hdrc musb-hdrc.0: new USB bus registered, assigned bus number 1。我们的USB主控制器有俩个所有busnum分别是1和2。这里打印的是第一个USB控制器加载的时候打印的信息。后面会调用retval = register_root_hub(hcd),root_hub的概念可以理解为与usb主机控制器绑定在一起的一种结构。他是该控制器控制的所有usb接口的源头。在register_root_hub中可以看到root_hub设备被真正注册的函数usb_new_device (usb_dev)。

从usb_add_hcd返回后,主机控制器就直接被USB总线识别(这里直接识别的原因还没有做详细分析),出现如下打印信息,这部分打印信息来自hub.c文件

usb usb2: New USB device found, idVendor=1d6b, idProduct=0002usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1usb usb2: Product: MUSB HDRC host driverusb usb2: Manufacturer: Linux 3.2.0-svn2045 musb-hcdusb usb2: SerialNumber: musb-hdrc.1hub 2-0:1.0: USB hub foundhub 2-0:1.0: 1 port detectedmusb_init_controller()再往下接着是有关于USB控制器的打印信息musb-hdrc musb-hdrc.1: USB Host mode controller at d083e800 using DMA, IRQ 19

5.设备如何被识别

usb_hub_init(void)-->hub_thread()-->hub_events()-->if (connect_change)-->hub_port_connect_change()

6.识别后要做那些事情

(1).usb_alloc_dev

(2).usb_set_device_state

这个函数用来设置设备的状态,struct usb_device 结

构体中,有一个成员,enum usb_device_state state,这一刻,会把这个设备的状态设置为

USB_STATE_POWERED,即上电状态.

(3).choose_devnum

为设备选择一个devnum,从1-128之间轮询选择

(4). hub_port_init

端口初始化,主要就是获取设备的描述符。该函数会输出打印信息dev_info(&udev->dev,"%s %s USB device number %d using %s\n",(udev->config) ? "reset" : "new", speed,devnum, udev->bus->controller->driver->name);也就是我们插入USB设备后在内核中看到的打印信息usb 2-1.1: new high-speed USB device number 3 using musb-hdrc。

(5).usb_get_status

(6).check_highspeed

如果设备当前是全速状态,但设备描述符中的bcdUSB有0200H(一个设备如果能够进行高速传输,那么它就应该在设备描述符里的bcdUSB 这一项写上0200H),且HUB口支持高速模式时,设备会检查自身是否支持高速运行,并切换到高速运行状态。

(7).usb_new_device

前半部分是和电源管理相关的部分然后是调用函数 usb_enumerate_device(udev)获取描述符枚举设备然后会调用announce_device(udev);打印调试信息,就是在插入USB设备时在内核空间看到的

usb 2-1.1: New USB device found, idVendor=14cd, idProduct=1212,usb 2-1.1: New USB device strings: Mfr=1, Product=3, SerialNumber=2最后调用device_add添加设备。这个函数执行后,系统里就真正有了这个设备,/sysfs 下面也能看到了,而且将会去遍历注册到usb 总线上的所有的驱动程序,如果找到合适的,就去调用该驱动的probe 函数

(8).hub_power_remaining

与电源管理相关的函数

7.关于hub_irq()

8.设备发现机制

am335x 的MUSB控制器解读相关推荐

  1. vxWorks PCIE控制器驱动解读

    PCI控制 目录 PCI控制器及桥关系解读 1.PCI控制器解读 1.1配置空间读 1.2配置空间写 1.3设备控制方法 1.4写中断向量 1.5内核提供的读取\设置配置空间的接口 1.6驱动初始化过 ...

  2. ti81xx_interrupt 1146: VBUS error workaround (delay coming)产生原因分析

    这几天用开发板来采集声音信号,接了一个24为的采集卡.开发板是TI的AM335X,运行内核是3.2版.整个系统用小米移动电源供电(因为要把整个系统拿到室外).但是在使用过程中,系统老是出问题,提示代码 ...

  3. Am3358增加Uboot的logo显示 增加Uboot自定义命令控制LCD

    本文的内容如下: 一. 简单介绍一下AM335x的时钟域的概念,然后讲解如何配置LCDC的时钟 二. 讲解LCDC的寄存器的内容和如何根据所选的LCD屏的特性进行时序上的配置 三. 介绍用bmpToR ...

  4. 12 模式的模式:复合模式

    1.引入 1.0 引入 使用模式最棒的方式,就是把它们从家里找出来同其他模式展开交互.你越多地使用模式就越容易发现它们一同现身在你的设计中.对于这些在设计中携手合作征服许多问题的模式,我们给它一个特别 ...

  5. 从经典的MVC模式到Web三层结构

    暑假这段时间,在海康这边实习,参与了海康iVMS-8700客户端的开发,对MVC有了新的认识,将之前写的这篇博客更新一下.有错误的地方,欢迎大家批评指正. 经典的MVC 什么是MVC? 先来说说MVC ...

  6. linux下虚拟lcd屏幕总线错误,mmap - 为什么BBB的LCD寄存器上的mmap()会导致总线错误? - 堆栈内存溢出...

    我试图在Beagle Bone Black上访问AM335X的LCD控制器. 我使用Linux debian. 下面是代码.如果我注释LCD代码部分中的" reg_value = * reg ...

  7. 嵌入式 Linux 内核驱动开发【The first day: 36093万字】

    嵌入式 Linux 内核驱动开发[1] 嵌入式 Linux 内核驱动开发前言 第1章 Linux 内核裁剪和定制 [1]Linux 内核开发简介 [2] Linux 源码阅读工具 [1.2.1]Sou ...

  8. 单片机知识点总结框图_单片机基础知识

    什么是单片机: 顾名思义,单片机中的"单片"就是只有一个芯片, "机"就是指计算机,只有有一个芯片,她却具有简单计算机的功能,这就叫做单片机,也教微处理器微控制 ...

  9. 《Headfirst设计模式》学习笔记

    策略模式 封装变化.找出应用中可能需要变化之处,把他们独立出来,不用和那些不需要变化的代码混在一起.把变化的行为单独建立一个抽象类及对应的派生类. 针对接口(抽象类)编程而不是针对实现编程.这里的接口 ...

最新文章

  1. Vbox共享文件夹不显示了
  2. c++ 查找文件夹下最新创建的文件_Linux文件查找进阶知识,find命令的用法及解读...
  3. 14.PHP_PHP与XML技术
  4. swiper去除滑动设置
  5. JS ES6中export和import详解
  6. 初入网络系列笔记(6)TFTP协议
  7. Java基础——Java IO详解
  8. css3 背景属性与边框属性的新增 200303
  9. php把服务器文件curl提交,php中使用curl进行文件上传的巨坑
  10. ie 打开后端发过来的pdf_JS如何下载资源文件,并且兼容IE、Edge
  11. msvcp140.dll缺失
  12. 自动运维化tools篇1:用expect完成用户密码的批量修改
  13. 如何在mysql命令窗口获取到程序正在执行的sql语句
  14. java中的POJO类
  15. HDU6070 Dirt Ratio
  16. 美国德保罗大学计算机排名,2018福布斯美国最佳大学排名德保罗大学排名第243...
  17. Chemistry Methods | Image2SMILES+: Transformer-Based Molecular Optical Recognition Engine
  18. Excel表格公式大全
  19. 含有未知中间变量同时需要传递其他中间变量的微分方程参数拟合
  20. 炒股软件周期分析怎么调,股票周期设置怎么设置

热门文章

  1. Vulnhub靶机:DC-8渗透详细过程
  2. 2017年最温暖的朋友圈:总有人在偷偷爱着你
  3. 接口自动化-用Jayway JsonPath对json文件进行读写操作,完成自定义传参
  4. 一言不合就起火 坐飞机时充电宝该怎么携带?
  5. 331 - Mapping the Swaps(回溯+ dfs)
  6. Pulsar 职位广场|BIGO、腾讯广告、微信、网易有道、StreamNative 等岗位机会
  7. 基于python的OCR图像识别,EasyOCR图像处理文字识别
  8. 微软正式提供免费杀毒软件公测版下载
  9. 【电脑技巧】开启联想电脑管家电池养护模式的操作步骤
  10. 武汉高性能计算大会2022举办,高性能计算生态发展再添新动力