mxc_udc: add workaround for ENGcm09152 for i.MX35
authorEric Bénard <eric@eukrea.com>
Fri, 15 Oct 2010 12:30:58 +0000 (14:30 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 22 Oct 2010 17:22:17 +0000 (10:22 -0700)
this patch gives the possibility to workaround bug ENGcm09152
on i.MX35 when the hardware workaround is also implemented on
the board.
It covers the workaround described on page 25 of the following Errata :
http://cache.freescale.com/files/dsp/doc/errata/IMX35CE.pdf

Signed-off-by: Eric Bénard <eric@eukrea.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/arm/mach-mx3/mach-cpuimx35.c
drivers/usb/gadget/fsl_mxc_udc.c
include/linux/fsl_devices.h

index 2a4f8b781ba4c60a4d66f554d860953fcafe1cf0..4d161b3fca6505b9a5dcb8aa5ba3ea5d92c60462 100644 (file)
@@ -155,6 +155,7 @@ static struct mxc_usbh_platform_data usbh1_pdata = {
 static struct fsl_usb2_platform_data otg_device_pdata = {
        .operating_mode = FSL_USB2_DR_DEVICE,
        .phy_mode       = FSL_USB2_PHY_UTMI,
+       .workaround     = FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
 static int otg_mode_host;
index eafa6d2c5ed734b278eaf1d34c69ab8f3290e383..5bdbfe6198537d76da36d6077e9d1ac786c5a7fc 100644 (file)
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_usb_clk;
 
+/* workaround ENGcm09152 for i.MX35 */
+#define USBPHYCTRL_OTGBASE_OFFSET      0x608
+#define USBPHYCTRL_EVDO                        (1 << 23)
+
 int fsl_udc_clk_init(struct platform_device *pdev)
 {
        struct fsl_usb2_platform_data *pdata;
@@ -84,6 +88,17 @@ eenahb:
 void fsl_udc_clk_finalize(struct platform_device *pdev)
 {
        struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+#if defined(CONFIG_ARCH_MX35)
+       unsigned int v;
+
+       /* workaround ENGcm09152 for i.MX35 */
+       if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
+               v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+                               USBPHYCTRL_OTGBASE_OFFSET));
+               writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+                               USBPHYCTRL_OTGBASE_OFFSET));
+       }
+#endif
 
        /* ULPI transceivers don't need usbpll */
        if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
index d5f9a7431bd0516da252d0ca316fde7a63cbbf9e..4eb56ed75fbceec07dce3a92cbd5a81b9c150a78 100644 (file)
@@ -66,6 +66,7 @@ struct fsl_usb2_platform_data {
        enum fsl_usb2_operating_modes   operating_mode;
        enum fsl_usb2_phy_modes         phy_mode;
        unsigned int                    port_enables;
+       unsigned int                    workaround;
 
        int             (*init)(struct platform_device *);
        void            (*exit)(struct platform_device *);
@@ -84,6 +85,8 @@ struct fsl_usb2_platform_data {
 #define FSL_USB2_PORT0_ENABLED 0x00000001
 #define FSL_USB2_PORT1_ENABLED 0x00000002
 
+#define FLS_USB2_WORKAROUND_ENGCM09152 (1 << 0)
+
 struct spi_device;
 
 struct fsl_spi_platform_data {