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

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

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

parents 86cb2da5 f84c92f1
Loading
Loading
Loading
Loading
+169 −71
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,13 @@

#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);

/**
 * dwc3_get_dr_mode - Validates and sets dr_mode
 * @dwc: pointer to our context structure
@@ -114,6 +117,7 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)

	dwc->current_dr_role = mode;
}
EXPORT_SYMBOL(dwc3_set_prtcap);

static void __dwc3_set_mode(struct work_struct *work)
{
@@ -230,8 +234,28 @@ 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);
	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_SUPER) {
		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;
		}
	}

	ret = phy_init(dwc->usb2_generic_phy);
	if (ret < 0)
		return ret;
@@ -376,6 +400,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, 0);
}

/**
@@ -397,6 +424,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, 0);
	return 0;
}

@@ -420,6 +449,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, 0);
	return 0;
}

@@ -436,6 +467,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, 0);
}

static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
@@ -904,11 +938,24 @@ static void dwc3_set_incr_burst_type(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;

	if (!dwc3_core_is_valid(dwc)) {
		dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
		ret = -ENODEV;
		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.
@@ -957,7 +1004,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
	dwc3_set_incr_burst_type(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;
@@ -966,12 +1015,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
@@ -1059,10 +1102,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
		dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
	}

	return 0;
	dwc3_check_params(dwc);

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

err3:
	phy_power_off(dwc->usb2_generic_phy);
@@ -1070,6 +1112,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);
@@ -1083,6 +1126,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
err0:
	return ret;
}
EXPORT_SYMBOL(dwc3_core_init);

static int dwc3_core_get_phy(struct dwc3 *dwc)
{
@@ -1151,7 +1195,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
	return 0;
}

static int dwc3_core_init_mode(struct dwc3 *dwc)
static int __maybe_unused dwc3_core_init_mode(struct dwc3 *dwc)
{
	struct device *dev = dwc->dev;
	int ret;
@@ -1204,7 +1248,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
	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:
@@ -1222,6 +1266,29 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
	}
}

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

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

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

	return ret;
}
EXPORT_SYMBOL(dwc3_notify_event);

static void dwc3_get_properties(struct dwc3 *dwc)
{
	struct device		*dev = dwc->dev;
@@ -1246,6 +1313,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);

@@ -1322,6 +1390,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");
@@ -1410,6 +1480,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)
@@ -1421,19 +1499,34 @@ 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");
		return -ENODEV;
	}

	dwc->reg_phys = res->start;
	dwc->xhci_resources[0].start = res->start;
	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
					DWC3_XHCI_REGS_END;
	dwc->xhci_resources[0].flags = res->flags;
	dwc->xhci_resources[0].name = res->name;

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

	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;
	}

	if (notify_event)
		/* will be enabled in dwc3_msm_resume() */
		disable_irq(irq);

	dwc->irq = irq;
	/*
	 * Request memory region but exclude xHCI regs,
	 * since it will be requested by the xhci-plat driver.
@@ -1445,6 +1538,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);

@@ -1459,7 +1560,7 @@ static int dwc3_probe(struct platform_device *pdev)

		ret = devm_clk_bulk_get(dev, dwc->num_clks, dwc->clks);
		if (ret == -EPROBE_DEFER)
			return ret;
			goto err0;
		/*
		 * Clocks are optional, but new DT platforms should support all
		 * clocks as required by the DT-binding.
@@ -1470,60 +1571,58 @@ static int dwc3_probe(struct platform_device *pdev)

	ret = reset_control_deassert(dwc->reset);
	if (ret)
		return ret;
		goto err0;

	ret = clk_bulk_prepare_enable(dwc->num_clks, dwc->clks);
	if (ret)
		goto assert_reset;

	if (!dwc3_core_is_valid(dwc)) {
		dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
		ret = -ENODEV;
		goto disable_clks;
	}

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

	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;
		goto err2;

	if (!notify_event) {
		ret = dwc3_core_init(dwc);
		if (ret) {
			if (ret != -EPROBE_DEFER)
			dev_err(dev, "failed to initialize core: %d\n", ret);
		goto err4;
				dev_err(dev, "failed to initialize core: %d\n",
						ret);
			goto err3;
		}

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

		ret = dwc3_core_init_mode(dwc);
	if (ret)
		goto err5;
		if (ret) {
			dwc3_event_buffers_cleanup(dwc);
			goto err3;
		}
	}

	dwc3_debugfs_init(dwc);

@@ -1536,32 +1635,22 @@ 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);
	dwc3_ulpi_exit(dwc);

err4:
	dwc3_free_scratch_buffers(dwc);

err3:
	dwc3_free_event_buffers(dwc);

	dwc3_free_scratch_buffers(dwc);
err2:
	pm_runtime_allow(&pdev->dev);

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

disable_clks:
	clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks);
assert_reset:
	reset_control_assert(dwc->reset);

	destroy_workqueue(dwc->dwc_wq);
err0:
	return ret;
}

@@ -1569,15 +1658,8 @@ static int dwc3_remove(struct platform_device *pdev)
{
	struct dwc3	*dwc = platform_get_drvdata(pdev);

	pm_runtime_get_sync(&pdev->dev);

	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);

@@ -1764,6 +1846,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, 0))
		return 0;

	if (dwc3_runtime_checks(dwc))
		return -EBUSY;

@@ -1781,6 +1867,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, 0))
		return 0;

	device_init_wakeup(dev, false);

	ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME);
@@ -1830,6 +1920,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, 0))
		return 0;

	ret = dwc3_suspend_common(dwc, PMSG_SUSPEND);
	if (ret)
		return ret;
@@ -1844,6 +1938,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, 0))
		return 0;

	pinctrl_pm_select_default_state(dev);

	ret = dwc3_resume_common(dwc, PMSG_RESUME);
+93 −2
Original line number Diff line number Diff line
@@ -162,8 +162,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 SoC Bus Configuration INCRx Register 0 */
#define DWC3_GSBUSCFG0_INCR256BRSTENA	(1 << 7) /* INCR256 burst */
#define DWC3_GSBUSCFG0_INCR128BRSTENA	(1 << 6) /* INCR128 burst */
@@ -265,6 +277,9 @@
#define DWC3_GSTS_CURMOD_DEVICE	0
#define DWC3_GSTS_CURMOD_HOST	1

/* 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)
@@ -294,6 +309,7 @@
#define DWC3_GUSB3PIPECTL_DISRXDETINP3	BIT(28)
#define DWC3_GUSB3PIPECTL_UX_EXIT_PX	BIT(27)
#define DWC3_GUSB3PIPECTL_REQP1P2P3	BIT(24)
#define DWC3_GUSB3PIPECTL_DISRXDETU3	BIT(22)
#define DWC3_GUSB3PIPECTL_DEP1P2P3(n)	((n) << 19)
#define DWC3_GUSB3PIPECTL_DEP1P2P3_MASK	DWC3_GUSB3PIPECTL_DEP1P2P3(7)
#define DWC3_GUSB3PIPECTL_DEP1P2P3_EN	DWC3_GUSB3PIPECTL_DEP1P2P3(1)
@@ -303,6 +319,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 */
@@ -483,6 +500,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
@@ -683,10 +701,13 @@ struct dwc3_ep_events {
 * @pending_list: list of pending requests for this endpoint
 * @started_list: list of started requests on this endpoint
 * @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, ...)
@@ -714,8 +735,10 @@ struct dwc3_ep {

	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;
@@ -751,6 +774,7 @@ struct dwc3_ep {

	unsigned		direction:1;
	unsigned		stream_capable:1;
	unsigned		gsi:1;

	/* For isochronous START TRANSFER workaround only */
	u8			combo_num;
@@ -759,6 +783,7 @@ struct dwc3_ep {
	struct dwc3_ep_events	dbg_ep_events;
	struct dwc3_ep_events	dbg_ep_events_diff;
	ktime_t			dbg_ep_events_kt;
	int			fifo_depth;
};

enum dwc3_phy {
@@ -980,9 +1005,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
 * @version_type: VERSIONTYPE register contents, a sub release of a revision
 * @dr_mode: requested mode of operation
@@ -1071,6 +1098,14 @@ 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
 * @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
@@ -1126,6 +1161,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;
@@ -1143,6 +1179,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
@@ -1265,24 +1302,42 @@ 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;

	struct workqueue_struct *dwc_wq;
	struct work_struct      bh_work;

	unsigned long		ep_cmd_timeout_cnt;

	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 INCRX_BURST_MODE 0
@@ -1483,11 +1538,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)
@@ -1502,6 +1562,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)
@@ -1557,4 +1623,29 @@ static inline void dwc3_ulpi_exit(struct dwc3 *dwc)
{ }
#endif

enum dwc3_notify_event {
	DWC3_CONTROLLER_ERROR_EVENT,
	DWC3_CONTROLLER_RESET_EVENT,
	DWC3_CONTROLLER_POST_RESET_EVENT,
	DWC3_CORE_PM_SUSPEND_EVENT,
	DWC3_CORE_PM_RESUME_EVENT,
	DWC3_CONTROLLER_CONNDONE_EVENT,
	DWC3_CONTROLLER_NOTIFY_OTG_EVENT,
	DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT,
	DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER,

	/* USB GSI event buffer related notification */
	DWC3_GSI_EVT_BUF_ALLOC,
	DWC3_GSI_EVT_BUF_SETUP,
	DWC3_GSI_EVT_BUF_CLEANUP,
	DWC3_GSI_EVT_BUF_CLEAR,
	DWC3_GSI_EVT_BUF_FREE,
	DWC3_CONTROLLER_NOTIFY_CLEAR_DB,
};

extern void dwc3_set_notifier(void (*notify)(struct dwc3 *dwc3,
						enum dwc3_notify_event event,
						unsigned int value));
extern int dwc3_notify_event(struct dwc3 *dwc3, enum dwc3_notify_event event,
						unsigned int value);
#endif /* __DRIVERS_USB_DWC3_CORE_H */
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ void dwc3_dbg_print(struct dwc3 *dwc, u8 ep_num, const char *name,
	ipc_log_string(dwc->dwc_ipc_log_ctxt, "%02X %-25.25s %4i ?\t%s",
			ep_num, name, status, extra);
}
EXPORT_SYMBOL(dwc3_dbg_print);

/**
 * dwc3_dbg_done: prints a DONE event
+70 −0
Original line number Diff line number Diff line
@@ -331,6 +331,11 @@ static int dwc3_lsp_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_GSTS);
	current_mode = DWC3_GSTS_CURMOD(reg);
@@ -394,6 +399,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);
@@ -428,6 +438,11 @@ static ssize_t dwc3_mode_write(struct file *file,
	u32			mode = 0;
	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;

@@ -459,6 +474,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;
@@ -505,6 +525,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;

@@ -544,6 +569,11 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
	u32			reg;
	u8			speed;

	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_GSTS);
	if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) {
@@ -580,6 +610,11 @@ static ssize_t dwc3_link_state_write(struct file *file,
	u32			reg;
	u8			speed;

	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;

@@ -640,6 +675,11 @@ static int dwc3_tx_fifo_size_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_TXFIFO);

@@ -659,6 +699,11 @@ static int dwc3_rx_fifo_size_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_RXFIFO);

@@ -693,6 +738,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);
@@ -708,6 +758,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);
@@ -723,6 +778,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);
@@ -738,6 +798,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);
@@ -1052,6 +1117,11 @@ 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, "ep_cmd_timeout_cnt : %lu\n", dwc->ep_cmd_timeout_cnt);

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