summary refs log tree commit diff
path: root/drivers/usb/dwc2
diff options
context:
space:
mode:
authorGevorg Sahakyan <Gevorg.Sahakyan@synopsys.com>2018-07-27 12:26:29 +0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2018-07-30 10:39:18 +0300
commitfe369e1826b3efae11012ad07d1713223c37ec5d (patch)
tree13674f57aaeb9f3650d74b5470bd698a4df89109 /drivers/usb/dwc2
parentb138e23d3dff90c0494925b4c1874227b81bddf7 (diff)
downloadlinux-fe369e1826b3efae11012ad07d1713223c37ec5d.tar.gz
usb: dwc2: Make dwc2_readl/writel functions endianness-agnostic.
Declared dwc2_check_core_endianness() function for dynamicly check
core endianness.
Added needs_byte_swap flag to hsotg structure, and depending on
flag swap value inside dwc2_readl/writel functions.

Signed-off-by: Gevorg Sahakyan <sahakyan@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r--drivers/usb/dwc2/core.h15
-rw-r--r--drivers/usb/dwc2/platform.c19
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;