Browse Source

UMS for Vybrid.

Got USB mass storage functionality to work on Vybrid. Started by
using the 'ums 0' command. The micro SD card will show up on the
host as a storage device. Still need to fix cache misalign errors
that will print out to console.

Signed-off-by: Trace Russell <b45800@freescale.com>
Trace Russell 12 years ago
parent
commit
cdfff67d2b
3 changed files with 96 additions and 8 deletions
  1. 49 0
      arch/arm/cpu/armv7/vf610/generic.c
  2. 45 8
      drivers/usb/gadget/arcotg_udc.c
  3. 2 0
      include/configs/vf610twr.h

+ 49 - 0
arch/arm/cpu/armv7/vf610/generic.c

@@ -392,3 +392,52 @@ void enable_usb_phy1_clk(unsigned char enable)
     }
 }
 
+#define USB_USBCMD		(OTG_BASE_ADDR + 0x0140)
+#define USB_CMD_RUN_STOP	(0x00000001)
+#define USB_CMD_CTRL_RESET	(0x00000002)
+#define PORTSC_PHCD		(1 << 23)
+#define USB_PORTSC1		(OTG_BASE_ADDR + 0x0184)
+void usb_phy_enable(void)
+{
+	u32 tmp;
+	void *phy_reg = USB_PHY0_BASE_ADDR;
+	void *phy_ctrl;
+
+	/* Stop then Reset */
+	writel(readl(USB_USBCMD) & ~USB_CMD_RUN_STOP, USB_USBCMD);
+	writel(readl(USB_USBCMD) | USB_CMD_CTRL_RESET, USB_USBCMD);
+
+	/* Reset USBPHY module */
+	phy_ctrl = HW_USBPHY_CTRL;
+	writel(readl(phy_ctrl) | BM_USBPHY_CTRL_SFTRST, phy_ctrl);
+	udelay(10);
+
+	/* Remove CLKGATE and SFTRST */
+	tmp = readl(phy_ctrl);
+	tmp &= ~(BM_USBPHY_CTRL_CLKGATE | BM_USBPHY_CTRL_SFTRST);
+	writel(tmp, phy_ctrl);
+	udelay(10);
+
+	/* Power up the PHY */
+	writel(0, phy_reg + HW_USBPHY_PWD);
+	/* enable FS/LS device */
+	tmp = readl(phy_reg + HW_USBPHY_CTRL);
+	tmp |= (BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3);
+	writel(tmp, phy_reg + HW_USBPHY_CTRL);
+
+	if(readl(USB_PORTSC1) & PORTSC_PHCD) {
+		writel(readl(USB_PORTSC1) & ~PORTSC_PHCD, USB_PORTSC1);
+		mdelay(1);
+	}
+	writel(BM_USBPHY_CTRL_CLKGATE, phy_reg + HW_USBPHY_CTRL_CLR);
+	tmp = (BM_USBPHY_PWD_TXPWDFS
+		| BM_USBPHY_PWD_TXPWDIBIAS
+		| BM_USBPHY_PWD_TXPWDV2I
+		| BM_USBPHY_PWD_RXPWDENV
+		| BM_USBPHY_PWD_RXPWD1PT1
+		| BM_USBPHY_PWD_RXPWDDIFF
+		| BM_USBPHY_PWD_RXPWDRX);
+	writel(tmp, phy_reg + HW_USBPHY_PWD_CLR);
+
+	mdelay(3);
+}

+ 45 - 8
drivers/usb/gadget/arcotg_udc.c

@@ -40,6 +40,7 @@ typedef int pm_message_t;
 #define __devinit
 #define pr_warning printf
 #define pr_debug(args...)
+//#define VDBG(str, args...) printf(str "\n", ## args)
 
 #define	DRIVER_DESC	"ARC USBOTG Device Controller driver"
 #define	DRIVER_AUTHOR	"Freescale Semiconductor"
@@ -193,6 +194,31 @@ fsl_platform_pullup_disable(struct fsl_usb2_platform_data *pdata)
                 pdata->xcvr_ops->pullup(0);
 } 
 
+static void *malloc_dma_buffer(u32 *dmaaddr, int size, int align)
+{
+	void *mem;
+	mem = memalign(align, size);
+	*dmaaddr = mem;
+	return mem;
+
+	int msize = (size + align  - 1);
+	u32 vir, vir_align;
+
+	vir = (u32)malloc(msize);
+#ifdef CONFIG_ARCH_MMU
+	vir = ioremap_nocache(iomem_to_phys(vir), msize);
+#endif
+	memset((void *)vir, 0, msize);
+	vir_align = (vir + align - 1) & (~(align - 1));
+#ifdef CONFIG_ARCH_MMU
+	*dmaaddr = (u32)iomem_to_phys(vir_align);
+#else
+	*dmaaddr = vir_align;
+#endif
+	DBG("vir addr %x, dma addr %x\n", vir_align, *dmaaddr);
+	return (void *)vir_align;
+}
+
 /*-----------------------------------------------------------------
  * done() - retire a request; caller blocked irqs
  * @status : request status to be set, only works when
@@ -214,7 +240,6 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
 		req->req.status = status;
 	else
 		status = req->req.status;
-
 	/* Free dtd for the request */
 	next_td = req->head;
 	for (j = 0; j < req->dtd_count; j++) {
@@ -234,11 +259,14 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
 		free(curr_td);
 #endif
 	}
-
 	if (USE_MSC_WR(req->req.length)) {
 		memmove(req->req.buf, req->req.buf + 1, MSC_BULK_CB_WRAP_LEN);
 	}
 
+	if (req->mapped) {
+		req->req.dma = DMA_ADDR_INVALID;
+		req->mapped = 0;
+	}
 	if (status && (status != -ESHUTDOWN))
 		VDBG("complete %s req %p stat %d len %u/%u",
 			ep->ep.name, &req->req, status,
@@ -500,6 +528,8 @@ static void dr_controller_run(struct fsl_udc *udc)
 		/* disable pulldown dp and dm */
 		dr_discharge_line(udc->pdata, false);
 		udc->vbus_active = true;
+		fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
+			&dr_regs->usbcmd);
 	}
 
 	return;
@@ -929,6 +959,7 @@ out:
 static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
 		dma_addr_t *dma, int *is_last)
 {
+	//VDBG("top of build_dtd\n");
 	u32 swap_temp;
 	struct ep_td_struct *dtd;
 
@@ -937,7 +968,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
 			(unsigned)EP_MAX_LENGTH_TRANSFER);
 	if (NEED_IRAM(req->ep))
 		*length = min(*length, g_iram_size);
-	dtd = malloc(sizeof(*dtd));
+	dtd = malloc_dma_buffer(dma, sizeof(struct ep_td_struct), DTD_ALIGNMENT);
 	if (dtd == NULL)
 		return dtd;
 
@@ -1402,6 +1433,7 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active)
  */
 static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
+	VDBG("in vbus_draw\n");
 	struct fsl_udc *udc;
 	struct fsl_usb2_platform_data *pdata;
 
@@ -1459,6 +1491,7 @@ static struct usb_gadget_ops fsl_gadget_ops = {
    on new transaction */
 static void ep0stall(struct fsl_udc *udc)
 {
+	VDBG("in ep0stall");
 	u32 tmp;
 
 	/* must set tx and rx to stall at the same time */
@@ -1598,6 +1631,7 @@ static void setup_received_irq(struct fsl_udc *udc,
 	unsigned mA = 500;
 	udc_reset_ep_queue(udc, 0);
 
+	VDBG("request: %x", setup->bRequest);
 	/* We process some stardard setup requests here */
 	switch (setup->bRequest) {
 	case USB_REQ_GET_STATUS:
@@ -1621,7 +1655,7 @@ static void setup_received_irq(struct fsl_udc *udc,
 		return;
 	case USB_REQ_SET_CONFIGURATION:
 		spin_unlock(&udc->lock);
-		fsl_vbus_draw(gadget, mA);
+		//fsl_vbus_draw(gadget, mA);
 		spin_lock(&udc->lock);
 	     break;
 	case USB_REQ_CLEAR_FEATURE:
@@ -1722,6 +1756,7 @@ static void setup_received_irq(struct fsl_udc *udc,
 		}
 	} else {
 		/* No data phase, IN status from gadget */
+		VDBG("in else branch");
 		udc->ep0_dir = USB_DIR_IN;
 		spin_unlock(&udc->lock);
 		if (udc->driver->setup(&udc->gadget,
@@ -1729,6 +1764,7 @@ static void setup_received_irq(struct fsl_udc *udc,
 			ep0stall(udc);
 	}
 	spin_lock(&udc->lock);
+	VDBG("end of setup_received_irq");
 }
 
 /* Process request for Data or Status phase of ep0
@@ -2280,7 +2316,7 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
 	if (irq_src == 0x0)
 		goto irq_end;
 
-	VDBG("0x%x\n", irq_src);
+	VDBG("IRQ: 0x%x\n", irq_src);
 
 	/* Need to resume? */
 	if (udc->usb_state == USB_STATE_SUSPENDED)
@@ -2375,7 +2411,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 	/* bind udc driver to gadget driver */
 	retval = driver->bind(&udc_controller->gadget);
 	if (retval) {
-		VDBG("bind to %s --> %d", driver->driver.name, retval);
+		VDBG("bind udc driver to gadget driver --> %d", retval);
 		//udc_controller->gadget.dev.driver = 0;
 		udc_controller->driver = 0;
 		dr_clk_gate(false);
@@ -2514,7 +2550,7 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
 		size += QH_ALIGNMENT + 1;
 		size &= ~(QH_ALIGNMENT - 1);
 	}
-	udc->ep_qh = malloc(size);
+	udc->ep_qh = malloc_dma_buffer(&udc->ep_qh_dma, size, QH_ALIGNMENT);
 	if (!udc->ep_qh) {
 		ERR("malloc QHs for udc failed\n");
 		kfree(udc->eps);
@@ -2628,7 +2664,7 @@ struct usb_dr_device *get_dr_regs(void)
  * all intialization operations implemented here except enabling usb_intr reg
  * board setup should have been done in the platform code
  */
-int __devinit fsl_udc_probe(struct fsl_usb2_platform_data *pdata)
+int fsl_udc_probe(struct fsl_usb2_platform_data *pdata)
 {
 	int ret = -ENODEV;
 	unsigned int i;
@@ -2665,6 +2701,7 @@ int __devinit fsl_udc_probe(struct fsl_usb2_platform_data *pdata)
 	set_usb_phy1_clk();
 	enable_usboh3_clk(1);
 	enable_usb_phy1_clk(1);
+	//usb_phy_enable();
 #if 0
 	if (pdata->init && pdata->init(pdata)) {
 		pdata->lowpower = false;

+ 2 - 0
include/configs/vf610twr.h

@@ -28,6 +28,7 @@
 #define CONFIG_VF610
 
 #define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_DUALSPEED
 #define CONFIG_USB_GADGET_ARCOTG_UDC
 #define CONFIG_USB_GADGET_MASS_STORAGE
 #define CONFIG_USBDOWNLOAD_GADGET
@@ -38,6 +39,7 @@
 #define CONFIG_G_DNL_PRODUCT_NUM 0x37ff
 #define CONFIG_G_DNL_MANUFACTURER "Freescale"
 #define CONFIG_DFU_FUNCTION
+//#define CONFIG_FSL_UTP
 #if 0
 #define CONFIG_USB_DEVICE
 #define CONFIG_IMX_UDC                 1