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

Commit b9a4fbdd authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3: Add QTI MSM platform specific feature and other changes"

parents a9a7da0a 62523500
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@ Optional properties:
 - snps,xhci-imod-value: Interrupt moderation interval for host mode
	(in increments of 250nsec).
 - usb-core-id: Differentiates between different controllers present on a device.
 - snps,bus-suspend-enable: If present then controller supports low power mode
	during bus suspend.

 - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.

+1 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0
# define_trace.h needs to know how to find our header
CFLAGS_trace.o				:= -I$(src)
CFLAGS_dwc3-msm.o                       := -Idrivers/usb/host -Idrivers/base/power

obj-$(CONFIG_USB_DWC3)			+= dwc3.o

+185 −125
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/usb/gadget.h>
#include <linux/usb/of.h>
#include <linux/usb/otg.h>
#include <linux/irq.h>

#include "core.h"
#include "gadget.h"
@@ -38,11 +39,28 @@

#include "debug.h"

#define DWC3_DEFAULT_AUTOSUSPEND_DELAY	5000 /* ms */
#define DWC3_DEFAULT_AUTOSUSPEND_DELAY	500 /* ms */

static int count;
static struct dwc3 *dwc3_instance[DWC_CTRL_COUNT];

static void dwc3_check_params(struct dwc3 *dwc);
static void __dwc3_set_mode(struct dwc3 *dwc);

void dwc3_usb3_phy_suspend(struct dwc3 *dwc, int suspend)
{
	u32			reg;

	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));

	if (suspend)
		reg |= DWC3_GUSB3PIPECTL_SUSPHY;
	else
		reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;

	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
}

/**
 * dwc3_get_dr_mode - Validates and sets dr_mode
 * @dwc: pointer to our context structure
@@ -106,12 +124,14 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
	dwc->current_dr_role = mode;
}

static void __dwc3_set_mode(struct work_struct *work)
static void __maybe_unused __dwc3_set_mode(struct dwc3 *dwc)
{
	struct dwc3 *dwc = work_to_dwc(work);
	unsigned long flags;
	int ret;

	dev_dbg(dwc->dev, "%s(): desired_dr_role:%d curent_dr_role:%d\n",
		__func__, dwc->desired_dr_role, dwc->current_dr_role);

	if (dwc->dr_mode != USB_DR_MODE_OTG)
		return;

@@ -121,8 +141,10 @@ static void __dwc3_set_mode(struct work_struct *work)
	if (!dwc->desired_dr_role)
		return;

	if (dwc->desired_dr_role == dwc->current_dr_role)
	if (dwc->desired_dr_role == dwc->current_dr_role) {
		dwc3_set_prtcap(dwc, dwc->desired_dr_role);
		return;
	}

	if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev)
		return;
@@ -222,8 +244,36 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
	int		retries = 1000;
	int		ret;

	usb_phy_init(dwc->usb2_phy);
	usb_phy_init(dwc->usb3_phy);
	/* Reset PHYs */
	usb_phy_reset(dwc->usb2_phy);

	if (dwc->maximum_speed == USB_SPEED_SUPER)
		usb_phy_reset(dwc->usb3_phy);

	ret = usb_phy_init(dwc->usb2_phy);
	if (ret) {
		pr_err("%s: usb_phy_init(dwc->usb2_phy) returned %d\n",
				__func__, ret);
		return ret;
	}

	if (dwc->maximum_speed == USB_SPEED_HIGH)
		goto generic_phy_init;

	ret = usb_phy_init(dwc->usb3_phy);
	if (ret == -EBUSY) {
		/*
		 * Setting Max speed as high when USB3 PHY initialiation
		 * is failing and USB superspeed can't be supported.
		 */
		dwc->maximum_speed = USB_SPEED_HIGH;
	} else if (ret) {
		pr_err("%s: usb_phy_init(dwc->usb3_phy) returned %d\n",
				__func__, ret);
		return ret;
	}

generic_phy_init:
	ret = phy_init(dwc->usb2_generic_phy);
	if (ret < 0)
		return ret;
@@ -355,6 +405,9 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
	evt = dwc->ev_buf;
	if (evt)
		dwc3_free_one_event_buffer(dwc, evt);

	/* free GSI related event buffers */
	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_FREE);
}

/**
@@ -376,6 +429,8 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
	}
	dwc->ev_buf = evt;

	/* alloc GSI related event buffers */
	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_ALLOC);
	return 0;
}

@@ -399,6 +454,8 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc)
			DWC3_GEVNTSIZ_SIZE(evt->length));
	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);

	/* setup GSI related event buffers */
	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_SETUP);
	return 0;
}

@@ -415,6 +472,9 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK
			| DWC3_GEVNTSIZ_SIZE(0));
	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);

	/* cleanup GSI related event buffers */
	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEANUP);
}

static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
@@ -787,7 +847,7 @@ static int dwc3_core_ulpi_init(struct dwc3 *dwc);
 *
 * Returns 0 on success otherwise negative errno.
 */
static int dwc3_core_init(struct dwc3 *dwc)
int dwc3_core_init(struct dwc3 *dwc)
{
	u32			reg;
	int			ret;
@@ -798,6 +858,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
		goto err0;
	}

	dwc3_cache_hwparams(dwc);
	ret = dwc3_get_dr_mode(dwc);
	if (ret) {
		ret = -EINVAL;
		goto err0;
	}

	/*
	 * Write Linux Version Code to our GUID register so it's easy to figure
	 * out which kernel version a bug was found.
@@ -844,7 +911,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
	dwc3_frame_length_adjustment(dwc);

	usb_phy_set_suspend(dwc->usb2_phy, 0);
	if (dwc->maximum_speed >= USB_SPEED_SUPER)
		usb_phy_set_suspend(dwc->usb3_phy, 0);

	ret = phy_power_on(dwc->usb2_generic_phy);
	if (ret < 0)
		goto err2;
@@ -853,12 +922,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
	if (ret < 0)
		goto err3;

	ret = dwc3_event_buffers_setup(dwc);
	if (ret) {
		dev_err(dwc->dev, "failed to setup event buffers\n");
		goto err4;
	}

	/*
	 * ENDXFER polling is available on version 3.10a and later of
	 * the DWC_usb3 controller. It is NOT available in the
@@ -923,10 +986,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
		}
	}

	return 0;
	dwc3_check_params(dwc);

err4:
	phy_power_off(dwc->usb3_generic_phy);
	return 0;

err3:
	phy_power_off(dwc->usb2_generic_phy);
@@ -934,6 +996,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
err2:
	usb_phy_set_suspend(dwc->usb2_phy, 1);
	usb_phy_set_suspend(dwc->usb3_phy, 1);
	dwc3_free_scratch_buffers(dwc);

err1:
	usb_phy_shutdown(dwc->usb2_phy);
@@ -1015,61 +1078,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
	return 0;
}

static int dwc3_core_init_mode(struct dwc3 *dwc)
{
	struct device *dev = dwc->dev;
	int ret;

	switch (dwc->dr_mode) {
	case USB_DR_MODE_PERIPHERAL:
		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);

		if (dwc->usb2_phy)
			otg_set_vbus(dwc->usb2_phy->otg, false);
		phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
		phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);

		ret = dwc3_gadget_init(dwc);
		if (ret) {
			if (ret != -EPROBE_DEFER)
				dev_err(dev, "failed to initialize gadget\n");
			return ret;
		}
		break;
	case USB_DR_MODE_HOST:
		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);

		if (dwc->usb2_phy)
			otg_set_vbus(dwc->usb2_phy->otg, true);
		phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
		phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);

		ret = dwc3_host_init(dwc);
		if (ret) {
			if (ret != -EPROBE_DEFER)
				dev_err(dev, "failed to initialize host\n");
			return ret;
		}
		phy_calibrate(dwc->usb2_generic_phy);
		break;
	case USB_DR_MODE_OTG:
		INIT_WORK(&dwc->drd_work, __dwc3_set_mode);
		ret = dwc3_drd_init(dwc);
		if (ret) {
			if (ret != -EPROBE_DEFER)
				dev_err(dev, "failed to initialize dual-role\n");
			return ret;
		}
		break;
	default:
		dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
		return -EINVAL;
	}

	return 0;
}

static void dwc3_core_exit_mode(struct dwc3 *dwc)
static void __maybe_unused dwc3_core_exit_mode(struct dwc3 *dwc)
{
	switch (dwc->dr_mode) {
	case USB_DR_MODE_PERIPHERAL:
@@ -1087,6 +1096,26 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
	}
}

static void (*notify_event)(struct dwc3 *, unsigned int);
void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned int))
{
	notify_event = notify;
}
EXPORT_SYMBOL(dwc3_set_notifier);

int dwc3_notify_event(struct dwc3 *dwc, unsigned int event)
{
	int ret = 0;

	if (notify_event)
		notify_event(dwc, event);
	else
		ret = -ENODEV;

	return ret;
}
EXPORT_SYMBOL(dwc3_notify_event);

static void dwc3_get_properties(struct dwc3 *dwc)
{
	struct device		*dev = dwc->dev;
@@ -1111,6 +1140,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
	hird_threshold = 12;

	dwc->maximum_speed = usb_get_maximum_speed(dev);
	dwc->max_hw_supp_speed = dwc->maximum_speed;
	dwc->dr_mode = usb_get_dr_mode(dev);
	dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node);

@@ -1186,6 +1216,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
				    &dwc->hsphy_interface);
	device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
				 &dwc->fladj);
	dwc->enable_bus_suspend = device_property_read_bool(dev,
					"snps,bus-suspend-enable");

	dwc->dis_metastability_quirk = device_property_read_bool(dev,
				"snps,dis_metastability_quirk");
@@ -1272,6 +1304,14 @@ static int dwc3_probe(struct platform_device *pdev)
	int			ret;

	void __iomem		*regs;
	int			irq;

	if (count >= DWC_CTRL_COUNT) {
		dev_err(dev, "Err dwc instance %d >= %d available\n",
					count, DWC_CTRL_COUNT);
		ret = -EINVAL;
		return ret;
	}

	dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
	if (!dwc)
@@ -1283,7 +1323,6 @@ static int dwc3_probe(struct platform_device *pdev)
		return -ENOMEM;

	dwc->dev = dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "missing memory resource\n");
@@ -1296,6 +1335,21 @@ static int dwc3_probe(struct platform_device *pdev)
	dwc->xhci_resources[0].flags = res->flags;
	dwc->xhci_resources[0].name = res->name;

	res->start += DWC3_GLOBALS_REGS_START;

	irq = platform_get_irq(to_platform_device(dwc->dev), 0);

	/* will be enabled in dwc3_msm_resume() */
	irq_set_status_flags(irq, IRQ_NOAUTOEN);
	ret = devm_request_irq(dev, irq, dwc3_interrupt, IRQF_SHARED, "dwc3",
			dwc);
	if (ret) {
		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
				irq, ret);
		return -ENODEV;
	}

	dwc->irq = irq;
	/*
	 * Request memory region but exclude xHCI regs,
	 * since it will be requested by the xhci-plat driver.
@@ -1307,6 +1361,14 @@ static int dwc3_probe(struct platform_device *pdev)
	if (IS_ERR(regs))
		return PTR_ERR(regs);

	dwc->dwc_wq = alloc_ordered_workqueue("dwc_wq", WQ_HIGHPRI);
	if (!dwc->dwc_wq) {
		dev_err(dev,
			"%s: Unable to create workqueue dwc_wq\n", __func__);
		goto err0;
	}

	INIT_WORK(&dwc->bh_work, dwc3_bh_work);
	dwc->regs	= regs;
	dwc->regs_size	= resource_size(&dwc_res);

@@ -1314,7 +1376,7 @@ static int dwc3_probe(struct platform_device *pdev)

	dwc->reset = devm_reset_control_get_optional_shared(dev, NULL);
	if (IS_ERR(dwc->reset))
		return PTR_ERR(dwc->reset);
		goto skip_clk_reset;

	if (dev->of_node) {
		dwc->num_clks = ARRAY_SIZE(dwc3_core_clks);
@@ -1342,47 +1404,32 @@ static int dwc3_probe(struct platform_device *pdev)
	if (ret)
		goto unprepare_clks;

skip_clk_reset:
	platform_set_drvdata(pdev, dwc);
	dwc3_cache_hwparams(dwc);

	init_waitqueue_head(&dwc->wait_linkstate);
	spin_lock_init(&dwc->lock);

	pm_runtime_no_callbacks(dev);
	pm_runtime_set_active(dev);
	if (dwc->enable_bus_suspend) {
		pm_runtime_set_autosuspend_delay(dev,
			DWC3_DEFAULT_AUTOSUSPEND_DELAY);
		pm_runtime_use_autosuspend(dev);
	pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
	}
	pm_runtime_enable(dev);
	ret = pm_runtime_get_sync(dev);
	if (ret < 0)
		goto err1;

	pm_runtime_forbid(dev);

	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
	if (ret) {
		dev_err(dwc->dev, "failed to allocate event buffers\n");
		ret = -ENOMEM;
		goto err2;
		goto err1;
	}

	ret = dwc3_get_dr_mode(dwc);
	if (ret)
		goto err3;

	ret = dwc3_alloc_scratch_buffers(dwc);
	if (ret)
		goto err3;

	ret = dwc3_core_init(dwc);
	if (ret) {
		dev_err(dev, "failed to initialize core\n");
		goto err4;
	}

	dwc3_check_params(dwc);

	ret = dwc3_core_init_mode(dwc);
	if (ret)
		goto err5;
		goto err2;

	dwc3_debugfs_init(dwc);

@@ -1395,26 +1442,13 @@ static int dwc3_probe(struct platform_device *pdev)
	dwc->index = count;
	count++;

	pm_runtime_put(dev);

	pm_runtime_allow(dev);
	return 0;

err5:
	dwc3_event_buffers_cleanup(dwc);

err4:
	dwc3_free_scratch_buffers(dwc);

err3:
	dwc3_free_event_buffers(dwc);

err2:
	pm_runtime_allow(&pdev->dev);

	dwc3_free_event_buffers(dwc);
err1:
	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

	if (dwc->num_clks) {
		clk_bulk_disable(dwc->num_clks, dwc->clks);
unprepare_clks:
		clk_bulk_unprepare(dwc->num_clks, dwc->clks);
@@ -1422,6 +1456,15 @@ static int dwc3_probe(struct platform_device *pdev)
		reset_control_assert(dwc->reset);
put_clks:
		clk_bulk_put(dwc->num_clks, dwc->clks);
	}
	destroy_workqueue(dwc->dwc_wq);
err0:
	/*
	 * restore res->start back to its original value so that, in case the
	 * probe is deferred, we don't end up getting error in request the
	 * memory region the next time probe is called.
	 */
	res->start -= DWC3_GLOBALS_REGS_START;

	return ret;
}
@@ -1429,16 +1472,17 @@ static int dwc3_probe(struct platform_device *pdev)
static int dwc3_remove(struct platform_device *pdev)
{
	struct dwc3	*dwc = platform_get_drvdata(pdev);
	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	pm_runtime_get_sync(&pdev->dev);
	/*
	 * restore res->start back to its original value so that, in case the
	 * probe is deferred, we don't end up getting error in request the
	 * memory region the next time probe is called.
	 */
	res->start -= DWC3_GLOBALS_REGS_START;

	dwc3_debugfs_exit(dwc);
	dwc3_core_exit_mode(dwc);

	dwc3_core_exit(dwc);
	dwc3_ulpi_exit(dwc);

	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_allow(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

@@ -1630,6 +1674,10 @@ static int dwc3_runtime_suspend(struct device *dev)
	struct dwc3     *dwc = dev_get_drvdata(dev);
	int		ret;

	/* Check if platform glue driver handling PM, if not then handle here */
	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_SUSPEND_EVENT))
		return 0;

	if (dwc3_runtime_checks(dwc))
		return -EBUSY;

@@ -1647,6 +1695,10 @@ static int dwc3_runtime_resume(struct device *dev)
	struct dwc3     *dwc = dev_get_drvdata(dev);
	int		ret;

	/* Check if platform glue driver handling PM, if not then handle here */
	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT))
		return 0;

	device_init_wakeup(dev, false);

	ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME);
@@ -1696,6 +1748,10 @@ static int dwc3_suspend(struct device *dev)
	struct dwc3	*dwc = dev_get_drvdata(dev);
	int		ret;

	/* Check if platform glue driver handling PM, if not then handle here */
	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_SUSPEND_EVENT))
		return 0;

	ret = dwc3_suspend_common(dwc, PMSG_SUSPEND);
	if (ret)
		return ret;
@@ -1710,6 +1766,10 @@ static int dwc3_resume(struct device *dev)
	struct dwc3	*dwc = dev_get_drvdata(dev);
	int		ret;

	/* Check if platform glue driver handling PM, if not then handle here */
	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT))
		return 0;

	pinctrl_pm_select_default_state(dev);

	ret = dwc3_resume_common(dwc, PMSG_RESUME);
+90 −2
Original line number Diff line number Diff line
@@ -161,8 +161,20 @@
#define DWC3_OEVTEN		0xcc0C
#define DWC3_OSTS		0xcc10

/* DWC 3.1 Link Registers */
#define DWC31_LINK_LU3LFPSRXTIM(n)	(0xd010 + ((n) * 0x80))
#define GEN2_U3_EXIT_RSP_RX_CLK(n)	((n) << 16)
#define GEN2_U3_EXIT_RSP_RX_CLK_MASK	GEN2_U3_EXIT_RSP_RX_CLK(0xff)
#define GEN1_U3_EXIT_RSP_RX_CLK(n)	(n)
#define GEN1_U3_EXIT_RSP_RX_CLK_MASK	GEN1_U3_EXIT_RSP_RX_CLK(0xff)
#define DWC31_LINK_GDBGLTSSM	0xd050

/* Bit fields */

/* Global SoC Bus Configuration Register 1 */
#define DWC3_GSBUSCFG1_PIPETRANSLIMIT_MASK	(0x0f << 8)
#define DWC3_GSBUSCFG1_PIPETRANSLIMIT(n)	((n) << 8)

/* Global Debug Queue/FIFO Space Available Register */
#define DWC3_GDBGFIFOSPACE_NUM(n)	((n) & 0x1f)
#define DWC3_GDBGFIFOSPACE_TYPE(n)	(((n) << 5) & 0x1e0)
@@ -240,6 +252,9 @@
#define DWC3_GSTS_CSR_TIMEOUT	BIT(5)
#define DWC3_GSTS_BUS_ERR_ADDR_VLD	BIT(4)

/* Global Debug LTSSM Register */
#define DWC3_GDBGLTSSM_LINKSTATE_MASK	(0xF << 22)

/* Global USB2 PHY Configuration Register */
#define DWC3_GUSB2PHYCFG_PHYSOFTRST	BIT(31)
#define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS	BIT(30)
@@ -278,6 +293,7 @@
#define DWC3_GUSB3PIPECTL_RX_DETOPOLL	BIT(8)
#define DWC3_GUSB3PIPECTL_TX_DEEPH_MASK	DWC3_GUSB3PIPECTL_TX_DEEPH(3)
#define DWC3_GUSB3PIPECTL_TX_DEEPH(n)	((n) << 1)
#define DWC3_GUSB3PIPECTL_DELAYP1TRANS  BIT(18)

/* Global TX Fifo Size Register */
#define DWC31_GTXFIFOSIZ_TXFRAMNUM	BIT(15)		/* DWC_usb31 only */
@@ -458,6 +474,7 @@
#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO	0x04
#define DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI	0x05

#define DWC3_DGCMD_XMIT_DEV		0x07
#define DWC3_DGCMD_SELECTED_FIFO_FLUSH	0x09
#define DWC3_DGCMD_ALL_FIFO_FLUSH	0x0a
#define DWC3_DGCMD_SET_ENDPOINT_NRDY	0x0c
@@ -659,10 +676,13 @@ struct dwc3_ep_events {
 * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
 * @lock: spinlock for endpoint request queue traversal
 * @regs: pointer to first endpoint register
 * @trb_dma_pool: dma pool used to get aligned trb memory pool
 * @trb_pool: array of transaction buffers
 * @trb_pool_dma: dma address of @trb_pool
 * @num_trbs: num of trbs in the trb dma pool
 * @trb_enqueue: enqueue 'pointer' into TRB array
 * @trb_dequeue: dequeue 'pointer' into TRB array
 * @desc: usb_endpoint_descriptor pointer
 * @dwc: pointer to DWC controller
 * @saved_state: ep state saved during hibernation
 * @flags: endpoint flags (wedged, stalled, ...)
@@ -688,8 +708,10 @@ struct dwc3_ep {
	spinlock_t		lock;
	void __iomem		*regs;

	struct dma_pool		*trb_dma_pool;
	struct dwc3_trb		*trb_pool;
	dma_addr_t		trb_pool_dma;
	u32			num_trbs;
	struct dwc3		*dwc;

	u32			saved_state;
@@ -906,6 +928,22 @@ struct dwc3_scratchpad_array {
	__le64	dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
};

#define DWC3_CONTROLLER_ERROR_EVENT		0
#define DWC3_CONTROLLER_RESET_EVENT		1
#define DWC3_CONTROLLER_POST_RESET_EVENT	2
#define DWC3_CORE_PM_SUSPEND_EVENT		3
#define DWC3_CORE_PM_RESUME_EVENT		4
#define DWC3_CONTROLLER_CONNDONE_EVENT		5
#define DWC3_CONTROLLER_NOTIFY_OTG_EVENT	6
#define DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT	7
#define DWC3_CONTROLLER_RESTART_USB_SESSION	8

/* USB GSI event buffer related notification */
#define DWC3_GSI_EVT_BUF_ALLOC			9
#define DWC3_GSI_EVT_BUF_SETUP			10
#define DWC3_GSI_EVT_BUF_CLEANUP		11
#define DWC3_GSI_EVT_BUF_FREE			12

#define MAX_INTR_STATS				10

/**
@@ -940,9 +978,11 @@ struct dwc3_scratchpad_array {
 * @current_otg_role: current role of operation while using the OTG block
 * @desired_otg_role: desired role of operation while using the OTG block
 * @otg_restart_host: flag that OTG controller needs to restart host
 * @reg_phys: physical base address of dwc3 core register address space
 * @nr_scratch: number of scratch buffers
 * @u1u2: only used on revisions <1.83a for workaround
 * @maximum_speed: maximum speed requested (mainly for testing purposes)
 * @maximum_speed: maximum speed to operate as requested by sw
 * @max_hw_supp_speed: maximum speed supported by hw design
 * @revision: revision register contents
 * @dr_mode: requested mode of operation
 * @current_dr_role: current role of operation when in dual-role mode
@@ -1024,6 +1064,15 @@ struct dwc3_scratchpad_array {
 * 	2	- No de-emphasis
 * 	3	- Reserved
 * @dis_metastability_quirk: set to disable metastability quirk.
 * @err_evt_seen: previous event in queue was erratic error
 * @in_lpm: indicates if controller is in low power mode (no clocks)
 * @irq: irq number
 * @irq_cnt: total irq count
 * @bh_completion_time: time taken for IRQ bottom-half completion
 * @bh_handled_evt_cnt: no. of events handled per IRQ bottom-half
 * @irq_dbg_index: index for capturing IRQ stats
 * @wait_linkstate: waitqueue for waiting LINK to move into required state
 * @vbus_draw: current to be drawn from USB
 * @imod_interval: set the interrupt moderation interval in 250ns
 *                 increments or 0 to disable.
 * @xhci_imod_value: imod value to use with xhci
@@ -1080,6 +1129,7 @@ struct dwc3 {

	void __iomem		*regs;
	size_t			regs_size;
	phys_addr_t		reg_phys;

	enum usb_dr_mode	dr_mode;
	u32			current_dr_role;
@@ -1097,6 +1147,7 @@ struct dwc3 {
	u32			nr_scratch;
	u32			u1u2;
	u32			maximum_speed;
	u32			max_hw_supp_speed;

	/*
	 * All 3.1 IP version constants are greater than the 3.0 IP
@@ -1166,6 +1217,8 @@ struct dwc3 {

	const char		*hsphy_interface;

	struct work_struct	wakeup_work;

	unsigned		connected:1;
	unsigned		delayed_status:1;
	unsigned		ep0_bounced:1;
@@ -1199,25 +1252,45 @@ struct dwc3 {

	unsigned		tx_de_emphasis_quirk:1;
	unsigned		tx_de_emphasis:2;
	unsigned		err_evt_seen:1;
	unsigned		enable_bus_suspend:1;

	atomic_t		in_lpm;
	bool			b_suspend;
	unsigned int		vbus_draw;

	unsigned		dis_metastability_quirk:1;

	u16			imod_interval;
	u32			xhci_imod_value;
	int			core_id;
	struct workqueue_struct *dwc_wq;
	struct work_struct      bh_work;

	unsigned long		ep_cmd_timeout_cnt;
	unsigned long		l1_remote_wakeup_cnt;

	wait_queue_head_t	wait_linkstate;

	unsigned int		index;
	void			*dwc_ipc_log_ctxt;
	struct dwc3_gadget_events	dbg_gadget_events;

	/* IRQ timing statistics */
	int			irq;
	unsigned long		irq_cnt;
	unsigned int		bh_completion_time[MAX_INTR_STATS];
	unsigned int		bh_handled_evt_cnt[MAX_INTR_STATS];
	ktime_t			irq_start_time[MAX_INTR_STATS];
	ktime_t			t_pwr_evt_irq;
	unsigned int		irq_completion_time[MAX_INTR_STATS];
	unsigned int		irq_event_count[MAX_INTR_STATS];
	unsigned int		irq_dbg_index;

	/* Indicate if the gadget was powered by the otg driver */
	unsigned int		vbus_active:1;
	/* Indicate if software connect was issued by the usb_gadget_driver */
	unsigned int		softconnect:1;
};

#define work_to_dwc(w)		(container_of((w), struct dwc3, drd_work))
@@ -1415,11 +1488,16 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state);
int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
		struct dwc3_gadget_ep_cmd_params *params);
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param);
void dwc3_gadget_disable_irq(struct dwc3 *dwc);
int dwc3_core_init(struct dwc3 *dwc);
int dwc3_event_buffers_setup(struct dwc3 *dwc);
#else
static inline int dwc3_gadget_init(struct dwc3 *dwc)
{ return 0; }
static inline void dwc3_gadget_exit(struct dwc3 *dwc)
{ }
static inline void dwc3_gadget_restart(struct dwc3 *dwc)
{ }
static inline int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
{ return 0; }
static inline int dwc3_gadget_get_link_state(struct dwc3 *dwc)
@@ -1434,6 +1512,12 @@ static inline int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
		int cmd, u32 param)
{ return 0; }
static inline void dwc3_gadget_disable_irq(struct dwc3 *dwc)
{ }
static int dwc3_core_init(struct dwc3 *dwc)
{ return 0; }
static int dwc3_event_buffers_setup(struct dwc3 *dwc)
{ return 0; }
#endif

#if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
@@ -1489,4 +1573,8 @@ static inline void dwc3_ulpi_exit(struct dwc3 *dwc)
{ }
#endif

extern void dwc3_set_notifier(
		void (*notify)(struct dwc3 *dwc3, unsigned int event));
extern int dwc3_notify_event(struct dwc3 *dwc3, unsigned int event);
void dwc3_usb3_phy_suspend(struct dwc3 *dwc, int suspend);
#endif /* __DRIVERS_USB_DWC3_CORE_H */
+67 −1
Original line number Diff line number Diff line
@@ -288,6 +288,11 @@ static int dwc3_mode_show(struct seq_file *s, void *unused)
	unsigned long		flags;
	u32			reg;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
	spin_unlock_irqrestore(&dwc->lock, flags);
@@ -320,7 +325,12 @@ static ssize_t dwc3_mode_write(struct file *file,
	struct seq_file		*s = file->private_data;
	struct dwc3		*dwc = s->private;
	u32			mode = 0;
	char			buf[32];
	char			buf[32] = {};

	if (atomic_read(&dwc->in_lpm)) {
		dev_err(dwc->dev, "USB device is powered off\n");
		return count;
	}

	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
		return -EFAULT;
@@ -353,6 +363,11 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused)
	unsigned long		flags;
	u32			reg;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
	reg &= DWC3_DCTL_TSTCTRL_MASK;
@@ -399,6 +414,11 @@ static ssize_t dwc3_testmode_write(struct file *file,
	u32			testmode = 0;
	char			buf[32];

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
		return -EFAULT;

@@ -437,6 +457,11 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
	enum dwc3_link_state	state;
	u32			reg;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	reg = dwc3_readl(dwc->regs, DWC3_DSTS);
	state = DWC3_DSTS_USBLNKST(reg);
@@ -461,6 +486,11 @@ static ssize_t dwc3_link_state_write(struct file *file,
	enum dwc3_link_state	state = 0;
	char			buf[32];

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
		return -EFAULT;

@@ -506,6 +536,11 @@ static int dwc3_tx_fifo_queue_show(struct seq_file *s, void *unused)
	unsigned long		flags;
	u32			val;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	val = dwc3_core_fifo_space(dep, DWC3_TXFIFOQ);
	seq_printf(s, "%u\n", val);
@@ -521,6 +556,11 @@ static int dwc3_rx_fifo_queue_show(struct seq_file *s, void *unused)
	unsigned long		flags;
	u32			val;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	val = dwc3_core_fifo_space(dep, DWC3_RXFIFOQ);
	seq_printf(s, "%u\n", val);
@@ -551,6 +591,11 @@ static int dwc3_rx_request_queue_show(struct seq_file *s, void *unused)
	unsigned long		flags;
	u32			val;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	val = dwc3_core_fifo_space(dep, DWC3_RXREQQ);
	seq_printf(s, "%u\n", val);
@@ -566,6 +611,11 @@ static int dwc3_rx_info_queue_show(struct seq_file *s, void *unused)
	unsigned long		flags;
	u32			val;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	val = dwc3_core_fifo_space(dep, DWC3_RXINFOQ);
	seq_printf(s, "%u\n", val);
@@ -581,6 +631,11 @@ static int dwc3_descriptor_fetch_queue_show(struct seq_file *s, void *unused)
	unsigned long		flags;
	u32			val;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	val = dwc3_core_fifo_space(dep, DWC3_DESCFETCHQ);
	seq_printf(s, "%u\n", val);
@@ -596,6 +651,11 @@ static int dwc3_event_queue_show(struct seq_file *s, void *unused)
	unsigned long		flags;
	u32			val;

	if (atomic_read(&dwc->in_lpm)) {
		seq_puts(s, "USB device is powered off\n");
		return 0;
	}

	spin_lock_irqsave(&dwc->lock, flags);
	val = dwc3_core_fifo_space(dep, DWC3_EVENTQ);
	seq_printf(s, "%u\n", val);
@@ -887,6 +947,12 @@ static int dwc3_gadget_int_events_show(struct seq_file *s, void *unused)
		seq_printf(s, "%d\t", dwc->bh_completion_time[i]);
	seq_putc(s, '\n');

	seq_printf(s, "t_pwr evt irq : %lld\n",
			ktime_to_us(dwc->t_pwr_evt_irq));

	seq_printf(s, "l1_remote_wakeup_cnt : %lu\n",
		dwc->l1_remote_wakeup_cnt);

	spin_unlock_irqrestore(&dwc->lock, flags);
	return 0;
}
Loading