只需要知道一点 usb设备控制器处理的是一个trb结构体指针,控制器自己分析里面数据启动传输
在ioctl qbuf的时候调用到__dwc3_gadget_ep_queue—>usb_gadget_map_request
int usb_gadget_map_request_by_dev(struct device *dev,
struct usb_request *req, int is_in)
{
if (req->length == 0)
return 0;
if (req->num_sgs) {
int mapped;
mapped = dma_map_sg(dev, req->sg, req->num_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (mapped == 0) {
dev_err(dev, "failed to map SGs\n");
return -EFAULT;
}
req->num_mapped_sgs = mapped;
} else {
req->dma = dma_map_single(dev, req->buf, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);在这映射到dma内存种
if (dma_mapping_error(dev, req->dma)) {
dev_err(dev, "failed to map buffer\n");
return -EFAULT;
}
}
return 0;
}
传输函数 准备工作__dwc3_gadget_ep_queue—>__dwc3_gadget_kick_transfer—>dwc3_prepare_trbs—>dwc3_prepare_one_trb_linear—>dwc3_prepare_one_trb
static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
struct dwc3_request *req, dma_addr_t dma,
unsigned length, unsigned chain, unsigned node)
{
struct dwc3_trb *trb;
struct dwc3 *dwc = dep->dwc;
struct usb_gadget *gadget = &dwc->gadget;
enum usb_device_speed speed = gadget->speed;
trb = &dep->trb_pool[dep->trb_enqueue];
if (!req->trb) {
dwc3_gadget_move_started_request(req);
req->trb = trb; //trb虚拟地址
req->trb_dma = dwc3_trb_dma_offset(dep, trb); //dma地址实际指向上面trb结构体
req->first_trb_index = dep->trb_enqueue;
dep->queued_requests++;
}
dwc3_ep_inc_enq(dep);
trb->size = DWC3_TRB_SIZE_LENGTH(length);
trb->bpl = lower_32_bits(dma); //将前面需要传输数据的dma映射地址赋值给trb低32位
trb->bph = upper_32_bits(dma);
switch (usb_endpoint_type(dep->endpoint.desc)) {
case USB_ENDPOINT_XFER_CONTROL:
trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP;
break;
省略代码。。。。
}
启动传输
static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param)
{
struct dwc3_gadget_ep_cmd_params params;
struct dwc3_request *req;
struct dwc3 *dwc = dep->dwc;
int starting;
int ret;
u32 cmd;
starting = !(dep->flags & DWC3_EP_BUSY);
dwc3_prepare_trbs(dep);//dma相关准备工作 将数据dma地址赋值给dma指向的传输的trb结构体中的地址变量
req = next_request(&dep->started_list);
if (!req) {
dep->flags |= DWC3_EP_PENDING_REQUEST;
return 0;
}
memset(¶ms, 0, sizeof(params));
if (starting && !(dep->flags&DWC3_EP_UPDATE)) {
//这里将指向trb结构体的dma地址赋值给参数,后面分别写进两个寄存器中。然后控制器通过该地址拿到直接存储数据的dma地址以及数据长度,一包数据调用一次,后面都是走else的update
params.param0 = upper_32_bits(req->trb_dma);
params.param1 = lower_32_bits(req->trb_dma);
cmd = DWC3_DEPCMD_STARTTRANSFER |
DWC3_DEPCMD_PARAM(cmd_param);
if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
dep->flags |= DWC3_EP_UPDATE;
} else {
cmd = DWC3_DEPCMD_UPDATETRANSFER |
DWC3_DEPCMD_PARAM(dep->resource_index);
}
ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms);
省略代码。。。
}
使能发送数据
int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
struct dwc3_gadget_ep_cmd_params *params)
{
struct dwc3 *dwc = dep->dwc;
u32 timeout = 5000;
u32 reg;
int cmd_status = 0;
int susphy = false;
int ret = -EINVAL;
/*
* Synopsys Databook 2.60a states, on section 6.3.2.5.[1-8], that if
* we're issuing an endpoint command, we must check if
* GUSB2PHYCFG.SUSPHY bit is set. If it is, then we need to clear it.
*
* We will also set SUSPHY bit to what it was before returning as stated
* by the same section on Synopsys databook.
*/
if (dwc->gadget.speed <= USB_SPEED_HIGH) {
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) {
susphy = true;
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
}
}
if (cmd == DWC3_DEPCMD_STARTTRANSFER) {
int needs_wakeup;
needs_wakeup = (dwc->link_state == DWC3_LINK_STATE_U1 ||
dwc->link_state == DWC3_LINK_STATE_U2 ||
dwc->link_state == DWC3_LINK_STATE_U3);
if (unlikely(needs_wakeup)) {
ret = __dwc3_gadget_wakeup(dwc);
dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n",
ret);
}
}
dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);将dma地址写入寄存器
dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1);
dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2);
dwc3_writel(dep->regs, DWC3_DEPCMD, cmd | DWC3_DEPCMD_CMDACT);使能usb传输
省略代码。。。
}