Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95c8bc36 authored by Antti Seppälä's avatar Antti Seppälä Committed by Felipe Balbi
Browse files

usb: dwc2: Use platform endianness when accessing registers



This patch switches calls to readl/writel to their
dwc2_readl/dwc2_writel equivalents which preserve platform endianness.

This patch is necessary to access dwc2 registers correctly on big-endian
systems such as the mips based SoCs made by Lantiq. Then dwc2 can be
used to replace ifx-hcd driver for Lantiq platforms found e.g. in
OpenWrt.

The patch was autogenerated with the following commands:
$EDITOR core.h
sed -i "s/\<readl\>/dwc2_readl/g" *.c hcd.h hw.h
sed -i "s/\<writel\>/dwc2_writel/g" *.c hcd.h hw.h

Some files were then hand-edited to fix checkpatch.pl warnings about
too long lines.

Signed-off-by: default avatarAntti Seppälä <a.seppala@gmail.com>
Signed-off-by: default avatarVincent Pelletier <plr.vincent@gmail.com>
Signed-off-by: default avatarJohn Youn <johnyoun@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent bba787a8
Loading
Loading
Loading
Loading
+235 −234

File changed.

Preview size limit exceeded, changes collapsed.

+22 −6
Original line number Diff line number Diff line
@@ -44,16 +44,32 @@
#include <linux/usb/phy.h>
#include "hw.h"

#ifdef DWC2_LOG_WRITES
static inline void do_write(u32 value, void *addr)
static inline u32 dwc2_readl(const void __iomem *addr)
{
	writel(value, addr);
	pr_info("INFO:: wrote %08x to %p\n", value, addr);
	u32 value = __raw_readl(addr);

	/* In order to preserve endianness __raw_* operation is used. Therefore
	 * a barrier is needed to ensure IO access is not re-ordered across
	 * reads or writes
	 */
	mb();
	return value;
}

#undef writel
#define writel(v, a)	do_write(v, a)
static inline void dwc2_writel(u32 value, void __iomem *addr)
{
	__raw_writel(value, addr);

	/*
	 * In order to preserve endianness __raw_* operation is used. Therefore
	 * a barrier is needed to ensure IO access is not re-ordered across
	 * reads or writes
	 */
	mb();
#ifdef DWC2_LOG_WRITES
	pr_info("INFO:: wrote %08x to %p\n", value, addr);
#endif
}

/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS	16
+37 −36
Original line number Diff line number Diff line
@@ -80,15 +80,15 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
 */
static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
{
	u32 hprt0 = readl(hsotg->regs + HPRT0);
	u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);

	if (hprt0 & HPRT0_ENACHG) {
		hprt0 &= ~HPRT0_ENA;
		writel(hprt0, hsotg->regs + HPRT0);
		dwc2_writel(hprt0, hsotg->regs + HPRT0);
	}

	/* Clear interrupt */
	writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
	dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
}

/**
@@ -102,7 +102,7 @@ static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
		 dwc2_is_host_mode(hsotg) ? "Host" : "Device");

	/* Clear interrupt */
	writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
	dwc2_writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
}

/**
@@ -117,8 +117,8 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
	u32 gotgctl;
	u32 gintmsk;

	gotgint = readl(hsotg->regs + GOTGINT);
	gotgctl = readl(hsotg->regs + GOTGCTL);
	gotgint = dwc2_readl(hsotg->regs + GOTGINT);
	gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
	dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
		dwc2_op_state_str(hsotg));

@@ -126,7 +126,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
		dev_dbg(hsotg->dev,
			" ++OTG Interrupt: Session End Detected++ (%s)\n",
			dwc2_op_state_str(hsotg));
		gotgctl = readl(hsotg->regs + GOTGCTL);
		gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);

		if (dwc2_is_device_mode(hsotg))
			dwc2_hsotg_disconnect(hsotg);
@@ -152,15 +152,15 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
			hsotg->lx_state = DWC2_L0;
		}

		gotgctl = readl(hsotg->regs + GOTGCTL);
		gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
		gotgctl &= ~GOTGCTL_DEVHNPEN;
		writel(gotgctl, hsotg->regs + GOTGCTL);
		dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
	}

	if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
		dev_dbg(hsotg->dev,
			" ++OTG Interrupt: Session Request Success Status Change++\n");
		gotgctl = readl(hsotg->regs + GOTGCTL);
		gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
		if (gotgctl & GOTGCTL_SESREQSCS) {
			if (hsotg->core_params->phy_type ==
					DWC2_PHY_TYPE_PARAM_FS
@@ -168,9 +168,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
				hsotg->srp_success = 1;
			} else {
				/* Clear Session Request */
				gotgctl = readl(hsotg->regs + GOTGCTL);
				gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
				gotgctl &= ~GOTGCTL_SESREQ;
				writel(gotgctl, hsotg->regs + GOTGCTL);
				dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
			}
		}
	}
@@ -180,7 +180,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
		 * Print statements during the HNP interrupt handling
		 * can cause it to fail
		 */
		gotgctl = readl(hsotg->regs + GOTGCTL);
		gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
		/*
		 * WA for 3.00a- HW is not setting cur_mode, even sometimes
		 * this does not help
@@ -200,9 +200,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
				 * interrupt does not get handled and Linux
				 * complains loudly.
				 */
				gintmsk = readl(hsotg->regs + GINTMSK);
				gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
				gintmsk &= ~GINTSTS_SOF;
				writel(gintmsk, hsotg->regs + GINTMSK);
				dwc2_writel(gintmsk, hsotg->regs + GINTMSK);

				/*
				 * Call callback function with spin lock
@@ -216,9 +216,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
				hsotg->op_state = OTG_STATE_B_HOST;
			}
		} else {
			gotgctl = readl(hsotg->regs + GOTGCTL);
			gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
			gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
			writel(gotgctl, hsotg->regs + GOTGCTL);
			dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
			dev_dbg(hsotg->dev, "HNP Failed\n");
			dev_err(hsotg->dev,
				"Device Not Connected/Responding\n");
@@ -244,9 +244,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
			hsotg->op_state = OTG_STATE_A_PERIPHERAL;
		} else {
			/* Need to disable SOF interrupt immediately */
			gintmsk = readl(hsotg->regs + GINTMSK);
			gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
			gintmsk &= ~GINTSTS_SOF;
			writel(gintmsk, hsotg->regs + GINTMSK);
			dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
			spin_unlock(&hsotg->lock);
			dwc2_hcd_start(hsotg);
			spin_lock(&hsotg->lock);
@@ -261,7 +261,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
		dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");

	/* Clear GOTGINT */
	writel(gotgint, hsotg->regs + GOTGINT);
	dwc2_writel(gotgint, hsotg->regs + GOTGINT);
}

/**
@@ -276,11 +276,11 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
 */
static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
{
	u32 gintmsk = readl(hsotg->regs + GINTMSK);
	u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK);

	/* Need to disable SOF interrupt immediately */
	gintmsk &= ~GINTSTS_SOF;
	writel(gintmsk, hsotg->regs + GINTMSK);
	dwc2_writel(gintmsk, hsotg->regs + GINTMSK);

	dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++  (%s)\n",
		dwc2_is_host_mode(hsotg) ? "Host" : "Device");
@@ -297,7 +297,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
	}

	/* Clear interrupt */
	writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
	dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
}

/**
@@ -316,7 +316,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
	dev_dbg(hsotg->dev, "++Session Request Interrupt++\n");

	/* Clear interrupt */
	writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
	dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);

	/*
	 * Report disconnect if there is any previous session established
@@ -339,13 +339,14 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
	dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);

	if (dwc2_is_device_mode(hsotg)) {
		dev_dbg(hsotg->dev, "DSTS=0x%0x\n", readl(hsotg->regs + DSTS));
		dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
			dwc2_readl(hsotg->regs + DSTS));
		if (hsotg->lx_state == DWC2_L2) {
			u32 dctl = readl(hsotg->regs + DCTL);
			u32 dctl = dwc2_readl(hsotg->regs + DCTL);

			/* Clear Remote Wakeup Signaling */
			dctl &= ~DCTL_RMTWKUPSIG;
			writel(dctl, hsotg->regs + DCTL);
			dwc2_writel(dctl, hsotg->regs + DCTL);
			ret = dwc2_exit_hibernation(hsotg, true);
			if (ret && (ret != -ENOTSUPP))
				dev_err(hsotg->dev, "exit hibernation failed\n");
@@ -356,11 +357,11 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
		hsotg->lx_state = DWC2_L0;
	} else {
		if (hsotg->lx_state != DWC2_L1) {
			u32 pcgcctl = readl(hsotg->regs + PCGCTL);
			u32 pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);

			/* Restart the Phy Clock */
			pcgcctl &= ~PCGCTL_STOPPCLK;
			writel(pcgcctl, hsotg->regs + PCGCTL);
			dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
			mod_timer(&hsotg->wkp_timer,
				  jiffies + msecs_to_jiffies(71));
		} else {
@@ -370,7 +371,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
	}

	/* Clear interrupt */
	writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
	dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
}

/*
@@ -389,7 +390,7 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
	/* Change to L3 (OFF) state */
	hsotg->lx_state = DWC2_L3;

	writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
	dwc2_writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
}

/*
@@ -412,7 +413,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
		 * Check the Device status register to determine if the Suspend
		 * state is active
		 */
		dsts = readl(hsotg->regs + DSTS);
		dsts = dwc2_readl(hsotg->regs + DSTS);
		dev_dbg(hsotg->dev, "DSTS=0x%0x\n", dsts);
		dev_dbg(hsotg->dev,
			"DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
@@ -465,7 +466,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)

clear_int:
	/* Clear interrupt */
	writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
	dwc2_writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
}

#define GINTMSK_COMMON	(GINTSTS_WKUPINT | GINTSTS_SESSREQINT |		\
@@ -483,9 +484,9 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
	u32 gahbcfg;
	u32 gintmsk_common = GINTMSK_COMMON;

	gintsts = readl(hsotg->regs + GINTSTS);
	gintmsk = readl(hsotg->regs + GINTMSK);
	gahbcfg = readl(hsotg->regs + GAHBCFG);
	gintsts = dwc2_readl(hsotg->regs + GINTSTS);
	gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
	gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);

	/* If any common interrupts set */
	if (gintsts & gintmsk_common)
+26 −26
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ static int testmode_show(struct seq_file *s, void *unused)
	int dctl;

	spin_lock_irqsave(&hsotg->lock, flags);
	dctl = readl(hsotg->regs + DCTL);
	dctl = dwc2_readl(hsotg->regs + DCTL);
	dctl &= DCTL_TSTCTL_MASK;
	dctl >>= DCTL_TSTCTL_SHIFT;
	spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -137,38 +137,38 @@ static int state_show(struct seq_file *seq, void *v)
	int idx;

	seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n",
		 readl(regs + DCFG),
		 readl(regs + DCTL),
		 readl(regs + DSTS));
		 dwc2_readl(regs + DCFG),
		 dwc2_readl(regs + DCTL),
		 dwc2_readl(regs + DSTS));

	seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n",
		   readl(regs + DIEPMSK), readl(regs + DOEPMSK));
		   dwc2_readl(regs + DIEPMSK), dwc2_readl(regs + DOEPMSK));

	seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n",
		   readl(regs + GINTMSK),
		   readl(regs + GINTSTS));
		   dwc2_readl(regs + GINTMSK),
		   dwc2_readl(regs + GINTSTS));

	seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n",
		   readl(regs + DAINTMSK),
		   readl(regs + DAINT));
		   dwc2_readl(regs + DAINTMSK),
		   dwc2_readl(regs + DAINT));

	seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n",
		   readl(regs + GNPTXSTS),
		   readl(regs + GRXSTSR));
		   dwc2_readl(regs + GNPTXSTS),
		   dwc2_readl(regs + GRXSTSR));

	seq_puts(seq, "\nEndpoint status:\n");

	for (idx = 0; idx < hsotg->num_of_eps; idx++) {
		u32 in, out;

		in = readl(regs + DIEPCTL(idx));
		out = readl(regs + DOEPCTL(idx));
		in = dwc2_readl(regs + DIEPCTL(idx));
		out = dwc2_readl(regs + DOEPCTL(idx));

		seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x",
			   idx, in, out);

		in = readl(regs + DIEPTSIZ(idx));
		out = readl(regs + DOEPTSIZ(idx));
		in = dwc2_readl(regs + DIEPTSIZ(idx));
		out = dwc2_readl(regs + DOEPTSIZ(idx));

		seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x",
			   in, out);
@@ -208,9 +208,9 @@ static int fifo_show(struct seq_file *seq, void *v)
	int idx;

	seq_puts(seq, "Non-periodic FIFOs:\n");
	seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ));
	seq_printf(seq, "RXFIFO: Size %d\n", dwc2_readl(regs + GRXFSIZ));

	val = readl(regs + GNPTXFSIZ);
	val = dwc2_readl(regs + GNPTXFSIZ);
	seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
		   val >> FIFOSIZE_DEPTH_SHIFT,
		   val & FIFOSIZE_DEPTH_MASK);
@@ -218,7 +218,7 @@ static int fifo_show(struct seq_file *seq, void *v)
	seq_puts(seq, "\nPeriodic TXFIFOs:\n");

	for (idx = 1; idx < hsotg->num_of_eps; idx++) {
		val = readl(regs + DPTXFSIZN(idx));
		val = dwc2_readl(regs + DPTXFSIZN(idx));

		seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx,
			   val >> FIFOSIZE_DEPTH_SHIFT,
@@ -270,20 +270,20 @@ static int ep_show(struct seq_file *seq, void *v)
	/* first show the register state */

	seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n",
		   readl(regs + DIEPCTL(index)),
		   readl(regs + DOEPCTL(index)));
		   dwc2_readl(regs + DIEPCTL(index)),
		   dwc2_readl(regs + DOEPCTL(index)));

	seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n",
		   readl(regs + DIEPDMA(index)),
		   readl(regs + DOEPDMA(index)));
		   dwc2_readl(regs + DIEPDMA(index)),
		   dwc2_readl(regs + DOEPDMA(index)));

	seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n",
		   readl(regs + DIEPINT(index)),
		   readl(regs + DOEPINT(index)));
		   dwc2_readl(regs + DIEPINT(index)),
		   dwc2_readl(regs + DOEPINT(index)));

	seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n",
		   readl(regs + DIEPTSIZ(index)),
		   readl(regs + DOEPTSIZ(index)));
		   dwc2_readl(regs + DIEPTSIZ(index)),
		   dwc2_readl(regs + DOEPTSIZ(index)));

	seq_puts(seq, "\n");
	seq_printf(seq, "mps %d\n", ep->ep.maxpacket);
+142 −142

File changed.

Preview size limit exceeded, changes collapsed.

Loading