/////* USB High Spped 2.0 Device (Gadget) */#ifdef CONFIG_PLAT_S3C24XXstatic struct resource s3c_hsudc_resource[] = { [0] = DEFINE_RES_MEM(S3C2416_PA_HSUDC, S3C2416_SZ_HSUDC), [1] = DEFINE_RES_IRQ(IRQ_USBD),};struct platform_device s3c_device_usb_hsudc = { .name = "s3c-hsudc", .id = -1, .num_resources = ARRAY_SIZE(s3c_hsudc_resource), .resource = s3c_hsudc_resource, .dev = { .dma_mask = &samsung_device_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), },};void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd){ s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);}#endif /* CONFIG_PLAT_S3C24XX *//////////static void __init smdk2416_machine_init(void)----> s3c24xx_hsudc_set_platdata(&smdk2416_hsudc_platdata); platform_add_devices(smdk2416_devices, ARRAY_SIZE(smdk2416_devices));static struct s3c24xx_hsudc_platdata smdk2416_hsudc_platdata = { .epnum = 9, .gpio_init = smdk2416_hsudc_gpio_init, .gpio_uninit = smdk2416_hsudc_gpio_uninit,};static void smdk2416_hsudc_gpio_init(void){ s3c_gpio_setpull(S3C2410_GPH(14), S3C_GPIO_PULL_UP); s3c_gpio_setpull(S3C2410_GPF(2), S3C_GPIO_PULL_NONE); s3c_gpio_cfgpin(S3C2410_GPH(14), S3C_GPIO_SFN(1)); s3c2410_modify_misccr(S3C2416_MISCCR_SEL_SUSPND, 0);}static struct platform_device *smdk2416_devices[] __initdata = { &s3c_device_fb, &s3c_device_wdt, &s3c_device_ohci, &s3c_device_i2c0, &s3c_device_hsmmc0, &s3c_device_hsmmc1, &s3c_device_usb_hsudc, &s3c2443_device_dma,};/////////////////////////////////////////////////////////////////////////////////MODULE_DESCRIPTION("Samsung S3C24XX USB high-speed controller driver");static struct platform_driver s3c_hsudc_driver = { .driver = { .name = "s3c-hsudc", }, .probe = s3c_hsudc_probe,};module_platform_driver(s3c_hsudc_driver);///////////////////////////** * struct s3c_hsudc - Driver's abstraction of the device controller. * @gadget: Instance of usb_gadget which is referenced by gadget driver. * @driver: Reference to currenty active gadget driver. * @dev: The device reference used by probe function. * @lock: Lock to synchronize the usage of Endpoints (EP's are indexed). * @regs: Remapped base address of controller's register space. * irq: IRQ number used by the controller. * uclk: Reference to the controller clock. * ep0state: Current state of EP0. * ep: List of endpoints supported by the controller. */struct s3c_hsudc { struct usb_gadget gadget; struct usb_gadget_driver *driver; struct device *dev; struct s3c24xx_hsudc_platdata *pd; struct usb_phy *transceiver; struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)]; spinlock_t lock; void __iomem *regs; int irq; struct clk *uclk; int ep0state; struct s3c_hsudc_ep ep[]; //端点};/////////////////////////////////////////////////很重要static int s3c_hsudc_probe(struct platform_device *pdev){ struct device *dev = &pdev->dev; struct resource *res; struct s3c_hsudc *hsudc; struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev); int ret, i; hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) + sizeof(struct s3c_hsudc_ep) * pd->epnum, GFP_KERNEL); if (!hsudc) return -ENOMEM; platform_set_drvdata(pdev, dev); hsudc->dev = dev; hsudc->pd = dev_get_platdata(&pdev->dev); hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); for (i = 0; i supplies); i++) hsudc->supplies[i].supply = s3c_hsudc_supply_names[i]; ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies), hsudc->supplies); if (ret != 0) { dev_err(dev, "failed to request supplies: %d\n", ret); goto err_supplies; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hsudc->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(hsudc->regs)) { ret = PTR_ERR(hsudc->regs); goto err_res; } spin_lock_init(&hsudc->lock); hsudc->gadget.max_speed = USB_SPEED_HIGH;//OPS操作集合 hsudc->gadget.ops = &s3c_hsudc_gadget_ops; hsudc->gadget.name = dev_name(dev); hsudc->gadget.ep0 = &hsudc->ep[0].ep; hsudc->gadget.is_otg = 0; hsudc->gadget.is_a_peripheral = 0; hsudc->gadget.speed = USB_SPEED_UNKNOWN; s3c_hsudc_setup_ep(hsudc); ret = platform_get_irq(pdev, 0); if (ret dev_err(dev, "unable to obtain IRQ number\n"); goto err_res; } hsudc->irq = ret;//很重要//这个申请的中断函数是用来接收数据的。//这里申请的中断处理函数是 s3c_hsudc_irq,这是这个驱动的核心,该USB device驱动的正常工作都围绕它展开。 ret = devm_request_irq(&pdev->dev, hsudc->irq, s3c_hsudc_irq, 0, driver_name, hsudc); if (ret dev_err(dev, "irq request failed\n"); goto err_res; } hsudc->uclk = devm_clk_get(&pdev->dev, "usb-device"); if (IS_ERR(hsudc->uclk)) { dev_err(dev, "failed to find usb-device clock source\n"); ret = PTR_ERR(hsudc->uclk); goto err_res; } clk_enable(hsudc->uclk); local_irq_disable(); disable_irq(hsudc->irq); local_irq_enable();//usb_add_gadget_udc - adds a new gadget to the udc class driver list//hsudc->gadget可以认为是USB设备控制器 ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget); if (ret) goto err_add_udc; pm_runtime_enable(dev); return 0;err_add_udc: clk_disable(hsudc->uclk);err_res: if (!IS_ERR_OR_NULL(hsudc->transceiver)) usb_put_phy(hsudc->transceiver);err_supplies: return ret;}///////////////////////////////////////////////////////物理层的核心/** * s3c_hsudc_irq - Interrupt handler for device controller. * @irq: Not used. * @_dev: Reference to the device controller. * * Interrupt handler for the device controller. This handler handles controller * interrupts and endpoint interrupts. *///接收到数据处理的函数//次函数即为 linux板子作为usb从设备时的irq中断接收usb数据的开始函数static irqreturn_t s3c_hsudc_irq(int irq, void *_dev){ struct s3c_hsudc *hsudc = _dev; struct s3c_hsudc_ep *hsep; u32 ep_intr; u32 sys_status; u32 ep_idx; spin_lock(&hsudc->lock);//读System Status寄存器 sys_status = readl(hsudc->regs + S3C_SSR);//读EP Intr Status寄存器 ep_intr = readl(hsudc->regs + S3C_EIR) & 0x3FF; if (!ep_intr && !(sys_status & S3C_SSR_DTZIEN_EN)) { spin_unlock(&hsudc->lock); return IRQ_HANDLED; } if (sys_status) { if (sys_status & S3C_SSR_VBUSON) writel(S3C_SSR_VBUSON, hsudc->regs + S3C_SSR); if (sys_status & S3C_SSR_ERR) writel(S3C_SSR_ERR, hsudc->regs + S3C_SSR); if (sys_status & S3C_SSR_SDE) { writel(S3C_SSR_SDE, hsudc->regs + S3C_SSR); hsudc->gadget.speed = (sys_status & S3C_SSR_HSP) ? USB_SPEED_HIGH : USB_SPEED_FULL; } if (sys_status & S3C_SSR_SUSPEND) { writel(S3C_SSR_SUSPEND, hsudc->regs + S3C_SSR); if (hsudc->gadget.speed != USB_SPEED_UNKNOWN && hsudc->driver && hsudc->driver->suspend) hsudc->driver->suspend(&hsudc->gadget); } if (sys_status & S3C_SSR_RESUME) { writel(S3C_SSR_RESUME, hsudc->regs + S3C_SSR); if (hsudc->gadget.speed != USB_SPEED_UNKNOWN && hsudc->driver && hsudc->driver->resume) hsudc->driver->resume(&hsudc->gadget); } if (sys_status & S3C_SSR_RESET) { writel(S3C_SSR_RESET, hsudc->regs + S3C_SSR); for (ep_idx = 0; ep_idx pd->epnum; ep_idx++) { hsep = &hsudc->ep[ep_idx]; hsep->stopped = 1; s3c_hsudc_nuke_ep(hsep, -ECONNRESET); } s3c_hsudc_reconfig(hsudc); hsudc->ep0state = WAIT_FOR_SETUP; } } if (ep_intr & S3C_EIR_EP0) { writel(S3C_EIR_EP0, hsudc->regs + S3C_EIR); set_index(hsudc, 0); //此处应该是端点0有数据 Handle endpoint 0 interrupt //EP0 interrupt could occur when a stall handshake is sent to host //or data is sent/received on endpoint 0 s3c_hsudc_handle_ep0_intr(hsudc); } ep_intr >>= 1; ep_idx = 1; while (ep_intr) { if (ep_intr & 1) { hsep = &hsudc->ep[ep_idx]; set_index(hsudc, ep_idx); writel(1 regs + S3C_EIR); if (ep_is_in(hsep)) s3c_hsudc_epin_intr(hsudc, ep_idx); else s3c_hsudc_epout_intr(hsudc, ep_idx); } ep_intr >>= 1; ep_idx++; } spin_unlock(&hsudc->lock); return IRQ_HANDLED;}////////////////////////////////// /** s3c_hsudc_handle_ep0_intr - Handle endpoint 0 interrupt. * @hsudc: Device controller on which endpoint 0 interrupt has occured. * * Handle endpoint 0 interrupt when it occurs. EP0 interrupt could occur * when a stall handshake is sent to host or data is sent/received on * endpoint 0. */static void s3c_hsudc_handle_ep0_intr(struct s3c_hsudc *hsudc){ struct s3c_hsudc_ep *hsep = &hsudc->ep[0]; struct s3c_hsudc_req *hsreq;//读EP0 Status寄存器 u32 csr = readl(hsudc->regs + S3C_EP0SR); u32 ecr; if (csr & S3C_EP0SR_STALL) { ecr = readl(hsudc->regs + S3C_EP0CR); ecr &= ~(S3C_ECR_STALL | S3C_ECR_FLUSH); writel(ecr, hsudc->regs + S3C_EP0CR); writel(S3C_EP0SR_STALL, hsudc->regs + S3C_EP0SR); hsep->stopped = 0; s3c_hsudc_nuke_ep(hsep, -ECONNABORTED); hsudc->ep0state = WAIT_FOR_SETUP; hsep->bEndpointAddress &= ~USB_DIR_IN; return; } if (csr & S3C_EP0SR_TX_SUCCESS) { writel(S3C_EP0SR_TX_SUCCESS, hsudc->regs + S3C_EP0SR); if (ep_is_in(hsep)) { if (list_empty(&hsep->queue)) return; hsreq = list_entry(hsep->queue.next, struct s3c_hsudc_req, queue); s3c_hsudc_write_fifo(hsep, hsreq); } }//端点0接收到数据 if (csr & S3C_EP0SR_RX_SUCCESS) { //属于SETUP建立令牌包,SETUP令牌包只用在控制传输中,USB设备的枚举过程都使用控制传输模式,保证数据正确性。 if (hsudc->ep0state == WAIT_FOR_SETUP) s3c_hsudc_process_setup(hsudc); else { if (!ep_is_in(hsep)) { if (list_empty(&hsep->queue)) return; hsreq = list_entry(hsep->queue.next, struct s3c_hsudc_req, queue); s3c_hsudc_read_fifo(hsep, hsreq); } } }}/////////////////////////////////////////** * s3c_hsudc_process_setup - Process control request received on endpoint 0. * @hsudc: Device controller on which control request has been received. * * Read the control request received on endpoint 0, decode it and handle * the request. *///USB建立令牌包,枚举过程,可以细看,按照USB协议来看是如何握手static void s3c_hsudc_process_setup(struct s3c_hsudc *hsudc){ struct s3c_hsudc_ep *hsep = &hsudc->ep[0]; struct usb_ctrlrequest ctrl = {0}; int ret; s3c_hsudc_nuke_ep(hsep, -EPROTO); s3c_hsudc_read_setup_pkt(hsudc, (u16 *)&ctrl); if (ctrl.bRequestType & USB_DIR_IN) { hsep->bEndpointAddress |= USB_DIR_IN; hsudc->ep0state = DATA_STATE_XMIT; } else { hsep->bEndpointAddress &= ~USB_DIR_IN; hsudc->ep0state = DATA_STATE_RECV; } switch (ctrl.bRequest) { case USB_REQ_SET_ADDRESS: if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) break; hsudc->ep0state = WAIT_FOR_SETUP; return; case USB_REQ_GET_STATUS: if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) break; s3c_hsudc_process_req_status(hsudc, &ctrl); return; case USB_REQ_SET_FEATURE: case USB_REQ_CLEAR_FEATURE: if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) break; s3c_hsudc_handle_reqfeat(hsudc, &ctrl); hsudc->ep0state = WAIT_FOR_SETUP; return; } if (hsudc->driver) { spin_unlock(&hsudc->lock); ret = hsudc->driver->setup(&hsudc->gadget, &ctrl); spin_lock(&hsudc->lock); if (ctrl.bRequest == USB_REQ_SET_CONFIGURATION) { hsep->bEndpointAddress &= ~USB_DIR_IN; hsudc->ep0state = WAIT_FOR_SETUP; } if (ret dev_err(hsudc->dev, "setup failed, returned %d\n", ret); s3c_hsudc_set_halt(&hsep->ep, 1); hsudc->ep0state = WAIT_FOR_SETUP; hsep->bEndpointAddress &= ~USB_DIR_IN; } }}/////////////////////////////////////////////////////////////////////usb操作static const struct usb_gadget_ops s3c_hsudc_gadget_ops = { .get_frame = s3c_hsudc_gadget_getframe, .udc_start = s3c_hsudc_start, .udc_stop = s3c_hsudc_stop, .vbus_draw = s3c_hsudc_vbus_draw,};///////////////////////////////////////////////////////////////////