diff options
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r-- | drivers/usb/dwc2/core.h | 15 | ||||
-rw-r--r-- | drivers/usb/dwc2/platform.c | 19 |
2 files changed, 32 insertions, 2 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index ae8534bed884..cc9c93affa14 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -857,6 +857,7 @@ struct dwc2_hregs_backup { * @gr_backup: Backup of global registers during suspend * @dr_backup: Backup of device registers during suspend * @hr_backup: Backup of host registers during suspend + * @needs_byte_swap: Specifies whether the opposite endianness. * * These are for host mode: * @@ -1046,6 +1047,7 @@ struct dwc2_hsotg { struct dentry *debug_root; struct debugfs_regset32 *regset; + bool needs_byte_swap; /* DWC OTG HW Release versions */ #define DWC2_CORE_REV_2_71a 0x4f54271a @@ -1164,12 +1166,21 @@ struct dwc2_hsotg { /* Normal architectures just use readl/write */ static inline u32 dwc2_readl(struct dwc2_hsotg *hsotg, u32 offset) { - return readl(hsotg->regs + offset); + u32 val; + + val = readl(hsotg->regs + offset); + if (hsotg->needs_byte_swap) + return swab32(val); + else + return val; } static inline void dwc2_writel(struct dwc2_hsotg *hsotg, u32 value, u32 offset) { - writel(value, hsotg->regs + offset); + if (hsotg->needs_byte_swap) + writel(swab32(value), hsotg->regs + offset); + else + writel(value, hsotg->regs + offset); #ifdef DWC2_LOG_WRITES pr_info("info:: wrote %08x to %p\n", value, hsotg->regs + offset); diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 4c0819554bcd..9a53a58e676e 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -353,6 +353,23 @@ static void dwc2_driver_shutdown(struct platform_device *dev) } /** + * dwc2_check_core_endianness() - Returns true if core and AHB have + * opposite endianness. + * @hsotg: Programming view of the DWC_otg controller. + */ +static bool dwc2_check_core_endianness(struct dwc2_hsotg *hsotg) +{ + u32 snpsid; + + snpsid = ioread32(hsotg->regs + GSNPSID); + if ((snpsid & GSNPSID_ID_MASK) == DWC2_OTG_ID || + (snpsid & GSNPSID_ID_MASK) == DWC2_FS_IOT_ID || + (snpsid & GSNPSID_ID_MASK) == DWC2_HS_IOT_ID) + return false; + return true; +} + +/** * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg * driver * @@ -395,6 +412,8 @@ static int dwc2_driver_probe(struct platform_device *dev) dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", (unsigned long)res->start, hsotg->regs); + hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg); + retval = dwc2_lowlevel_hw_init(hsotg); if (retval) return retval; |