/////* 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,};///////////////////////////////////////////////////////////////////
09-08 03:19
查看更多