[PATCH 4/4] usb: dwc2: Make dwc2_readl/writel functions endianness-agnostic.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Gevorg Sahakyan <sahakyan@xxxxxxxxxxxx>

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@xxxxxxxxxxxx>
Signed-off-by: Gevorg Sahakya <sahakyan@xxxxxxxxxxxx>
---
 drivers/usb/dwc2/core.h     | 22 ++++++++++++++++++++--
 drivers/usb/dwc2/platform.c | 18 ++++++++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a32ff26386c2..7e5690e27cdd 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -96,6 +96,13 @@ static const char * const dwc2_hsotg_supply_names[] = {
  */
 #define EP0_MPS_LIMIT   64
 
+#define swap32(x) (\
+	{typeof(x) x_ = (x); \
+	(((u32)(x_) << 24) & (u32)0xFF000000) | \
+	(((u32)(x_) <<  8) & (u32)0x00FF0000) | \
+	(((u32)(x_) >>  8) & (u32)0x0000FF00) | \
+	(((u32)(x_) >> 24) & (u32)0x000000FF); })
+
 struct dwc2_hsotg;
 struct dwc2_hsotg_req;
 
@@ -781,6 +788,7 @@ struct dwc2_hregs_backup {
  * @gregs_backup: Backup of global registers during suspend
  * @dregs_backup: Backup of device registers during suspend
  * @hregs_backup: Backup of host registers during suspend
+ * @needs_byte_swap:		Specifies whether the opposite endianness.
  *
  * These are for host mode:
  *
@@ -928,6 +936,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
@@ -1043,12 +1052,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 swap32(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(swap32(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..5252e8286a37 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -352,6 +352,22 @@ static void dwc2_driver_shutdown(struct platform_device *dev)
 	disable_irq(hsotg->irq);
 }
 
+/**
+ * dwc2_check_core_endianness() - Returns true if the big endian
+ * @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
@@ -376,6 +392,8 @@ static int dwc2_driver_probe(struct platform_device *dev)
 
 	hsotg->dev = &dev->dev;
 
+	hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg);
+
 	/*
 	 * Use reasonable defaults so platforms don't have to provide these.
 	 */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux