⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 amd5536udc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		ep->num = tmp;		/* txfifo size is calculated at enable time */		ep->txfifo = dev->txfifo;		/* fifo size */		if (tmp < UDC_EPIN_NUM) {			ep->fifo_depth = UDC_TXFIFO_SIZE;			ep->in = 1;		} else {			ep->fifo_depth = UDC_RXFIFO_SIZE;			ep->in = 0;		}		ep->regs = &dev->ep_regs[tmp];		/*		 * ep will be reset only if ep was not enabled before to avoid		 * disabling ep interrupts when ENUM interrupt occurs but ep is		 * not enabled by gadget driver		 */		if (!ep->desc) {			ep_init(dev->regs, ep);		}		if (use_dma) {			/*			 * ep->dma is not really used, just to indicate that			 * DMA is active: remove this			 * dma regs = dev control regs			 */			ep->dma = &dev->regs->ctl;			/* nak OUT endpoints until enable - not for ep0 */			if (tmp != UDC_EP0IN_IX && tmp != UDC_EP0OUT_IX						&& tmp > UDC_EPIN_NUM) {				/* set NAK */				reg = readl(&dev->ep[tmp].regs->ctl);				reg |= AMD_BIT(UDC_EPCTL_SNAK);				writel(reg, &dev->ep[tmp].regs->ctl);				dev->ep[tmp].naking = 1;			}		}	}	/* EP0 max packet */	if (dev->gadget.speed == USB_SPEED_FULL) {		dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_FS_EP0IN_MAX_PKT_SIZE;		dev->ep[UDC_EP0OUT_IX].ep.maxpacket =						UDC_FS_EP0OUT_MAX_PKT_SIZE;	} else if (dev->gadget.speed == USB_SPEED_HIGH) {		dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;		dev->ep[UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;	}	/*	 * with suspend bug workaround, ep0 params for gadget driver	 * are set at gadget driver bind() call	 */	dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep;	dev->ep[UDC_EP0IN_IX].halted = 0;	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);	/* init cfg/alt/int */	dev->cur_config = 0;	dev->cur_intf = 0;	dev->cur_alt = 0;}/* Bringup after Connect event, initial bringup to be ready for ep0 events */static void usb_connect(struct udc *dev){	dev_info(&dev->pdev->dev, "USB Connect\n");	dev->connected = 1;	/* put into initial config */	udc_basic_init(dev);	/* enable device setup interrupts */	udc_enable_dev_setup_interrupts(dev);}/* * Calls gadget with disconnect event and resets the UDC and makes * initial bringup to be ready for ep0 events */static void usb_disconnect(struct udc *dev){	dev_info(&dev->pdev->dev, "USB Disconnect\n");	dev->connected = 0;	/* mask interrupts */	udc_mask_unused_interrupts(dev);	/* REVISIT there doesn't seem to be a point to having this	 * talk to a tasklet ... do it directly, we already hold	 * the spinlock needed to process the disconnect.	 */	tasklet_schedule(&disconnect_tasklet);}/* Tasklet for disconnect to be outside of interrupt context */static void udc_tasklet_disconnect(unsigned long par){	struct udc *dev = (struct udc *)(*((struct udc **) par));	u32 tmp;	DBG(dev, "Tasklet disconnect\n");	spin_lock_irq(&dev->lock);	if (dev->driver) {		spin_unlock(&dev->lock);		dev->driver->disconnect(&dev->gadget);		spin_lock(&dev->lock);		/* empty queues */		for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {			empty_req_queue(&dev->ep[tmp]);		}	}	/* disable ep0 */	ep_init(dev->regs,			&dev->ep[UDC_EP0IN_IX]);	if (!soft_reset_occured) {		/* init controller by soft reset */		udc_soft_reset(dev);		soft_reset_occured++;	}	/* re-enable dev interrupts */	udc_enable_dev_setup_interrupts(dev);	/* back to full speed ? */	if (use_fullspeed) {		tmp = readl(&dev->regs->cfg);		tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);		writel(tmp, &dev->regs->cfg);	}	spin_unlock_irq(&dev->lock);}/* Reset the UDC core */static void udc_soft_reset(struct udc *dev){	unsigned long	flags;	DBG(dev, "Soft reset\n");	/*	 * reset possible waiting interrupts, because int.	 * status is lost after soft reset,	 * ep int. status reset	 */	writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqsts);	/* device int. status reset */	writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts);	spin_lock_irqsave(&udc_irq_spinlock, flags);	writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);	readl(&dev->regs->cfg);	spin_unlock_irqrestore(&udc_irq_spinlock, flags);}/* RDE timer callback to set RDE bit */static void udc_timer_function(unsigned long v){	u32 tmp;	spin_lock_irq(&udc_irq_spinlock);	if (set_rde > 0) {		/*		 * open the fifo if fifo was filled on last timer call		 * conditionally		 */		if (set_rde > 1) {			/* set RDE to receive setup data */			tmp = readl(&udc->regs->ctl);			tmp |= AMD_BIT(UDC_DEVCTL_RDE);			writel(tmp, &udc->regs->ctl);			set_rde = -1;		} else if (readl(&udc->regs->sts)				& AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {			/*			 * if fifo empty setup polling, do not just			 * open the fifo			 */			udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;			if (!stop_timer) {				add_timer(&udc_timer);			}		} else {			/*			 * fifo contains data now, setup timer for opening			 * the fifo when timer expires to be able to receive			 * setup packets, when data packets gets queued by			 * gadget layer then timer will forced to expire with			 * set_rde=0 (RDE is set in udc_queue())			 */			set_rde++;			/* debug: lhadmot_timer_start = 221070 */			udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;			if (!stop_timer) {				add_timer(&udc_timer);			}		}	} else		set_rde = -1; /* RDE was set by udc_queue() */	spin_unlock_irq(&udc_irq_spinlock);	if (stop_timer)		complete(&on_exit);}/* Handle halt state, used in stall poll timer */static void udc_handle_halt_state(struct udc_ep *ep){	u32 tmp;	/* set stall as long not halted */	if (ep->halted == 1) {		tmp = readl(&ep->regs->ctl);		/* STALL cleared ? */		if (!(tmp & AMD_BIT(UDC_EPCTL_S))) {			/*			 * FIXME: MSC spec requires that stall remains			 * even on receivng of CLEAR_FEATURE HALT. So			 * we would set STALL again here to be compliant.			 * But with current mass storage drivers this does			 * not work (would produce endless host retries).			 * So we clear halt on CLEAR_FEATURE.			 *			DBG(ep->dev, "ep %d: set STALL again\n", ep->num);			tmp |= AMD_BIT(UDC_EPCTL_S);			writel(tmp, &ep->regs->ctl);*/			/* clear NAK by writing CNAK */			tmp |= AMD_BIT(UDC_EPCTL_CNAK);			writel(tmp, &ep->regs->ctl);			ep->halted = 0;			UDC_QUEUE_CNAK(ep, ep->num);		}	}}/* Stall timer callback to poll S bit and set it again after */static void udc_pollstall_timer_function(unsigned long v){	struct udc_ep *ep;	int halted = 0;	spin_lock_irq(&udc_stall_spinlock);	/*	 * only one IN and OUT endpoints are handled	 * IN poll stall	 */	ep = &udc->ep[UDC_EPIN_IX];	udc_handle_halt_state(ep);	if (ep->halted)		halted = 1;	/* OUT poll stall */	ep = &udc->ep[UDC_EPOUT_IX];	udc_handle_halt_state(ep);	if (ep->halted)		halted = 1;	/* setup timer again when still halted */	if (!stop_pollstall_timer && halted) {		udc_pollstall_timer.expires = jiffies +					HZ * UDC_POLLSTALL_TIMER_USECONDS					/ (1000 * 1000);		add_timer(&udc_pollstall_timer);	}	spin_unlock_irq(&udc_stall_spinlock);	if (stop_pollstall_timer)		complete(&on_pollstall_exit);}/* Inits endpoint 0 so that SETUP packets are processed */static void activate_control_endpoints(struct udc *dev){	u32 tmp;	DBG(dev, "activate_control_endpoints\n");	/* flush fifo */	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);	tmp |= AMD_BIT(UDC_EPCTL_F);	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);	/* set ep0 directions */	dev->ep[UDC_EP0IN_IX].in = 1;	dev->ep[UDC_EP0OUT_IX].in = 0;	/* set buffer size (tx fifo entries) of EP0_IN */	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);	if (dev->gadget.speed == USB_SPEED_FULL)		tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE,					UDC_EPIN_BUFF_SIZE);	else if (dev->gadget.speed == USB_SPEED_HIGH)		tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE,					UDC_EPIN_BUFF_SIZE);	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);	/* set max packet size of EP0_IN */	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);	if (dev->gadget.speed == USB_SPEED_FULL)		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE,					UDC_EP_MAX_PKT_SIZE);	else if (dev->gadget.speed == USB_SPEED_HIGH)		tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE,				UDC_EP_MAX_PKT_SIZE);	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);	/* set max packet size of EP0_OUT */	tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);	if (dev->gadget.speed == USB_SPEED_FULL)		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,					UDC_EP_MAX_PKT_SIZE);	else if (dev->gadget.speed == USB_SPEED_HIGH)		tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,					UDC_EP_MAX_PKT_SIZE);	writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);	/* set max packet size of EP0 in UDC CSR */	tmp = readl(&dev->csr->ne[0]);	if (dev->gadget.speed == USB_SPEED_FULL)		tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,					UDC_CSR_NE_MAX_PKT);	else if (dev->gadget.speed == USB_SPEED_HIGH)		tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,					UDC_CSR_NE_MAX_PKT);	writel(tmp, &dev->csr->ne[0]);	if (use_dma) {		dev->ep[UDC_EP0OUT_IX].td->status |=			AMD_BIT(UDC_DMA_OUT_STS_L);		/* write dma desc address */		writel(dev->ep[UDC_EP0OUT_IX].td_stp_dma,			&dev->ep[UDC_EP0OUT_IX].regs->subptr);		writel(dev->ep[UDC_EP0OUT_IX].td_phys,			&dev->ep[UDC_EP0OUT_IX].regs->desptr);		/* stop RDE timer */		if (timer_pending(&udc_timer)) {			set_rde = 0;			mod_timer(&udc_timer, jiffies - 1);		}		/* stop pollstall timer */		if (timer_pending(&udc_pollstall_timer)) {			mod_timer(&udc_pollstall_timer, jiffies - 1);		}		/* enable DMA */		tmp = readl(&dev->regs->ctl);		tmp |= AMD_BIT(UDC_DEVCTL_MODE)				| AMD_BIT(UDC_DEVCTL_RDE)				| AMD_BIT(UDC_DEVCTL_TDE);		if (use_dma_bufferfill_mode) {			tmp |= AMD_BIT(UDC_DEVCTL_BF);		} else if (use_dma_ppb_du) {			tmp |= AMD_BIT(UDC_DEVCTL_DU);		}		writel(tmp, &dev->regs->ctl);	}	/* clear NAK by writing CNAK for EP0IN */	tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);	tmp |= AMD_BIT(UDC_EPCTL_CNAK);	writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);	dev->ep[UDC_EP0IN_IX].naking = 0;	UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);	/* clear NAK by writing CNAK for EP0OUT */	tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);	tmp |= AMD_BIT(UDC_EPCTL_CNAK);	writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);	dev->ep[UDC_EP0OUT_IX].naking = 0;	UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);}/* Make endpoint 0 ready for control traffic */static int setup_ep0(struct udc *dev){	activate_control_endpoints(dev);	/* enable ep0 interrupts */	udc_enable_ep0_interrupts(dev);	/* enable device setup interrupts */	udc_enable_dev_setup_interrupts(dev);	return 0;}/* Called by gadget driver to register itself */int usb_gadget_register_driver(struct usb_gadget_driver *driver){	struct udc		*dev = udc;	int			retval;	u32 tmp;	if (!driver || !driver->bind || !driver->setup			|| driver->speed != USB_SPEED_HIGH)		return -EINVAL;	if (!dev)		return -ENODEV;	if (dev->driver)		return -EBUSY;	driver->driver.bus = NULL;	dev->driver = driver;	dev->gadget.dev.driver = &driver->driver;	retval = driver->bind(&dev->gadget);	/* Some gadget drivers use both ep0 directions.	 * NOTE: to gadget driver, ep0 is just one endpoint...	 */	dev->ep[UDC_EP0OUT_IX].ep.driver_data =		dev->ep[UDC_EP0IN_IX].ep.driver_data;	if (retval) {		DBG(dev, "binding to %s returning %d\n",				driver->driver.name, retval);		dev->driver = NULL;		dev->gadget.dev.driver = NULL;		return retval;	}	/* get ready for ep0 traffic */	setup_ep0(dev);	/* clear SD */	tmp = readl(&dev->regs->ctl);	tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD);	writel(tmp, &dev->regs->ctl);	usb_connect(dev);	return 0;}EXPORT_SYMBOL(usb_gadget_register_driver);/* shutdown requests and disconnect from gadget */static voidshutdown(struct udc *dev, struct usb_gadget_driver *driver)__releases(dev->lock)__acquires(dev->lock){	int tmp;	/* empty queues and init hardware */	udc_basic_init(dev);	for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {		empty_req_queue(&dev->ep[tmp]);	}	if (dev->gadget.speed != USB_SPEED_UNKNOWN) {		spin_unlock(&dev->lock);		driver->disconnect(&dev->gadget);		spin_lock(&dev->lock);	}	/* init */	udc_setup_endpoints(dev);}/* Called by gadget driver to unregister itself */int usb_gadget_unregister_driver(struct usb_gadget_driver *driver){	struct udc	*dev = udc;	unsigned long	flags;	u32 tmp;	if (!dev)		return -ENODEV;	if (!driver || driver != dev->driver || !driver->unbind)		return -EINVAL;	spin_lock_irqsave(&dev->lock, flags);	udc_mask_unused_interrupts(dev);	shutdown(dev, driver);	spin_unlock_irqrestore(&dev->lock, flags);	driver->unbind(&dev->gadget);	dev->driver = NULL;	/* set SD */	tmp = readl(&dev->regs->ctl);	tmp |= AMD_BIT(UDC_DEVCTL_SD);	writel(tmp, &dev->regs->ctl);	DBG(dev, "%s: unregistered\n", driver->driver.name);	return 0;}EXPORT_SYMBOL(usb_gadget_unregister_driver);/* Clear pending NAK bits */static void udc_process_cnak_queue(struct udc *dev){	u32 tmp;	u32 reg;	/* check epin's */	DBG(dev, "CNAK pending queue processing\n");	for (tmp = 0; tmp < UDC_EPIN_NUM_USED; tmp++) {		if (cnak_pending & (1 << tmp)) {			DBG(dev, "CNAK pending for ep%d\n", tmp);			/* clear NAK by writing CNAK */			reg = readl(&dev->ep[tmp].regs->ctl);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -