接着上一篇看,第三大设备控制器的注册:
//Devices-msm8x60.c (arch\arm\mach-msm)
//udc设备控制器注册
static u64 dma_mask = 0xffffffffULL;
struct platform_device msm_device_gadget_peripheral = {//usb设备控制器平台设备
.name = "msm_hsusb",
.id = -1,
.dev = {
.dma_mask = &dma_mask,
.coherent_dma_mask = 0xffffffffULL,
},
};
//Board-msm8x60.c (arch\arm\mach-msm)
//usb设备控制器平台数据
static struct msm_hsusb_gadget_platform_data msm_gadget_pdata = {
.is_phy_status_timer_on = 1,
};
//挂载usb设备控制器平台数据
msm_device_gadget_peripheral.dev.platform_data = &msm_gadget_pdata;
static struct platform_device *surf_devices[] __initdata = {
.............
&msm_device_gadget_peripheral,
}
//注册平台设备
static void __init msm8x60_init(struct msm_board_data *board_data)
{
platform_add_devices(surf_devices,ARRAY_SIZE(surf_devices));//把usb设备控制器加入到系统中
}
//Msm72k_udc.c (drivers\usb\gadget)
//udc设备控制器平台驱动注册
static struct platform_driver usb_driver = {
.probe = msm72k_probe,
.driver = { .name = "msm_hsusb",
.pm = &msm72k_udc_dev_pm_ops, },
};
static int __init init(void)
{
return platform_driver_register(&usb_driver);//注册usb平台驱动
}
module_init(init);
//设备控制器和设备控制器驱动匹配成功后,调用msm72k_probe
/*在分析前先看下udc设备控制器所使用的结构,一个udc控制器所用的资源都放在该结构中*/
struct usb_info {
/* lock for register/queue/device state changes */
spinlock_t lock;
/* single request used for handling setup transactions */
struct usb_request *setup_req;//处理枚举用的request
struct platform_device *pdev;//存放注册的usb设备控制器平台设备结构体
int irq;
void *addr;
unsigned state;
unsigned flags;
atomic_t configured;
atomic_t running;
struct dma_pool *pool;//dma池
/* dma page to back the queue heads and items */
unsigned char *buf;//传输用的buf
dma_addr_t dma;//该buf对应的dma
struct ept_queue_head *head;
/* used for allocation */
unsigned next_item;
unsigned next_ifc_num;
/* endpoints are ordered based on their status bits, so they are OUT0, OUT1, ... OUT15, IN0, IN1, ... IN15*/
struct msm_endpoint ept[32];//该usb设备控制器所拥有的端点
/* max power requested by selected configuration */
unsigned b_max_pow;
unsigned chg_current;
struct delayed_work chg_det;
struct delayed_work chg_stop;
struct msm_hsusb_gadget_platform_data *pdata;//存放对应usb平台设备的平台数据
struct work_struct phy_status_check;
struct work_struct work;//重要的work
unsigned phy_status;
unsigned phy_fail_count;
unsigned prime_fail_count;
unsigned long dTD_update_fail_count;
struct usb_gadget gadget;//支持的gadget
struct usb_gadget_driver *driver;//该gadget的driver
struct switch_dev sdev;
/*下面是该gadget的0端点*/
#define ep0out ept[0]
#define ep0in ept[16]
atomic_t ep0_dir;
atomic_t test_mode;
atomic_t offline_pending;
atomic_t softconnect;
..............
atomic_t remote_wakeup;
atomic_t self_powered;
struct delayed_work rw_work;
struct otg_transceiver *xceiv;
enum usb_device_state usb_state;
struct wake_lock wlock;
};
static int msm72k_probe(struct platform_device *pdev)
{
struct usb_info *ui;
struct msm_otg *otg;
int retval;
dev_dbg(&pdev->dev, "msm72k_probe\n");
ui = kzalloc(sizeof(struct usb_info), GFP_KERNEL);//分配usb_info结构体
ui->pdev = pdev;//存放注册的usb设备控制器平台设备结构体
ui->pdata = pdev->dev.platform_data;//usb平台设备的平台数据
ui->buf = dma_alloc_coherent(&pdev->dev, 4096, &ui->dma, GFP_KERNEL);//分配dma buf返回虚拟地址赋给buf
ui->pool = dma_pool_create("msm72k_udc", NULL, 32, 32, 0);//创建dma池
ui->xceiv = otg_get_transceiver();//获得otg transceiver
otg = to_msm_otg(ui->xceiv);
ui->addr = otg->regs;//取出otg设备的寄存器
ui->gadget.ops = &msm72k_ops;//gadget的操作函数
ui->gadget.is_dualspeed = 1;//设置支持双速full/high speed
device_initialize(&ui->gadget.dev);
dev_set_name(&ui->gadget.dev, "gadget");
ui->gadget.dev.parent = &pdev->dev;
ui->gadget.dev.dma_mask = pdev->dev.dma_mask;
/*switch work初始化和注册*/
ui->sdev.name = DRIVER_NAME;//#define DRIVER_NAME "MSM72K_UDC"
ui->sdev.print_name = print_switch_name;
ui->sdev.print_state = print_switch_state;
retval = switch_dev_register(&ui->sdev);
the_usb_info = ui;//保存到全局变量the_usb_info
wake_lock_init(&ui->wlock,WAKE_LOCK_SUSPEND, "usb_bus_active");//初始化wakelake
usb_prepare(ui);//下面分析1
retval = otg_set_peripheral(ui->xceiv, &ui->gadget);//设置otg收发器的gadget成员,调用otg的回调函数
pm_runtime_enable(&pdev->dev);
/* Setup phy stuck timer */
if (ui->pdata && ui->pdata->is_phy_status_timer_on)//起一个定时器,以防phy挂掉
setup_timer(&phy_status_timer, usb_phy_status_check_timer, 0);
return 0;
}
1.下面看下usb_prepare()函数
static void usb_prepare(struct usb_info *ui)
{
spin_lock_init(&ui->lock);//初始化ui的自旋锁
memset(ui->buf, 0, 4096);//重置分配的dma buffer
ui->head = (void *) (ui->buf + 0);//usb传输用的head头
/* only important for reset/reinit */
memset(ui->ept, 0, sizeof(ui->ept));
ui->next_item = 0;
ui->next_ifc_num = 0;
init_endpoints(ui);//初始化端点,1.1
/*初始化默认端点的最大包大小*/
ui->ep0in.ep.maxpacket = 64;
ui->ep0out.ep.maxpacket = 64;
//#define SETUP_BUF_SIZE 8。分析见下面1.2
ui->setup_req = usb_ept_alloc_req(&ui->ep0in, SETUP_BUF_SIZE, GFP_KERNEL);
/*初始化后面要用到的work*/
INIT_WORK(&ui->work, usb_do_work);//重要的work
INIT_DELAYED_WORK(&ui->chg_det, usb_chg_detect);
INIT_DELAYED_WORK(&ui->chg_stop, usb_chg_stop);
INIT_DELAYED_WORK(&ui->rw_work, usb_do_remote_wakeup);
if (ui->pdata && ui->pdata->is_phy_status_timer_on)//监视phy是否挂掉的定时器,初始化为1
INIT_WORK(&ui->phy_status_check, usb_phy_stuck_recover);//如果phy挂掉,则reset硬件恢复
}
1.1 初始化端点
static void init_endpoints(struct usb_info *ui)
{
unsigned n;
for (n = 0; n < 32; n++) {
struct msm_endpoint *ept = ui->ept + n;//初始化每个端点
ept->ui = ui;//把ui设备控制器的信息保存到端点,方便以后用
ept->bit = n;//每个端点的bit总编号
ept->num = n & 15;//每个端点的端点号
ept->ep.name = ep_name[n];//每个端点的名字
ept->ep.ops = &msm72k_ep_ops;//端点操作函数
//buf的顺序为ep1in,ep1out
if (ept->bit > 15) {
/* IN endpoint */
ept->head = ui->head + (ept->num << 1) + 1;//初始化端点真实传输的buffer队列
ept->flags = EPT_FLAG_IN;//是in端点
} else {
/* OUT endpoint */
ept->head = ui->head + (ept->num << 1);//分配传输buf
ept->flags = 0;//是out端点
}
//设定timer,处理endpoint数据是否发送成功
setup_timer(&ept->prime_timer, ept_prime_timer_func, (unsigned long) ept);
}
}
//下面分析该请求结构体的关系
struct msm_request {
struct usb_request req;//下面该结构体(5)
/* saved copy of req.complete */
void (*gadget_complete)(struct usb_ep *ep,struct usb_request *req);
struct usb_info *ui;
struct msm_request *next;
struct msm_request *prev;
unsigned busy:1;
unsigned live:1;
unsigned alloced:1;//是否分配过req.buf内存
dma_addr_t dma;
/*从dma池中分配item结构体,对应的item dma放在item_dma变量中*/
dma_addr_t item_dma;
struct ept_queue_item *item;
};
//上接上面的(5)
struct usb_request {
void *buf;
unsigned length;
dma_addr_t dma;
unsigned no_interrupt:1;
unsigned zero:1;
unsigned short_not_ok:1;
void (*complete)(struct usb_ep *ep, struct usb_request *req);
void *context;
struct list_head list;
int status;
unsigned actual;
unsigned udc_priv;
};
1.2 为端点分配req
struct usb_request *usb_ept_alloc_req(struct msm_endpoint *ept, unsigned bufsize, gfp_t gfp_flags)
{
struct usb_info *ui = ept->ui;
struct msm_request *req;
req = kzalloc(sizeof(*req), gfp_flags);//分配req
req->item = dma_pool_alloc(ui->pool, gfp_flags, &req->item_dma);//从前面的dma池中分配dma内存
if (bufsize) {
req->req.buf = kmalloc(bufsize, gfp_flags);
req->alloced = 1;
}
return &req->req;
}
2.设置otg收发器的gadget成员
dev->otg.set_peripheral = msm_otg_set_peripheral;//初始化otg控制器的回调函数
otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph)
{
return otg->set_peripheral(otg, periph);
}
static int msm_otg_set_peripheral(struct otg_transceiver *xceiv, struct usb_gadget *gadget)
{
struct msm_otg *dev = container_of(xceiv, struct msm_otg, otg);
....................
dev->otg.gadget = gadget;//初始化收发器
pr_info("peripheral driver registered w/ tranceiver\n");
wake_lock(&dev->wlock);
queue_work(dev->wq, &dev->sm_work);//调度msm_otg_sm_work,otg状态机第一个调用的地方,开启一个新的时代
return 0;
}
现在三大设备控制器都注册完了,下一节看下如何配合。