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

Commit aea077cf authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3: Add support for GSI event buffer configuration"

parents 5f85cd84 3c3962f6
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ Optional properties:
 - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
			utmi_l1_suspend_n, false when asserts utmi_sleep_n
 - snps,hird-threshold: HIRD threshold
 - snps,num-normal-evt-buffs: If present, specifies number of normal event buffers. Default is 1.
 - snps,num-gsi-evt-buffs: If present, specifies number of GSI based hardware accelerated event buffers.
	1 event buffer is needed per h/w accelerated endpoint.

This is usually a subnode to DWC3 glue to which it is connected.

@@ -35,4 +38,5 @@ dwc3@4a030000 {
	usb-phy = <&usb2_phy>, <&usb3,phy>;
	tx-fifo-resize;
	snps,usb3-u1u2-disable;
	snps,num-gsi-evt-buffs = <0x2>;
};
+1 −0
Original line number Diff line number Diff line
@@ -575,6 +575,7 @@
			snps,lpm-nyet-thresh = <0x8>;
			snps,bus-suspend-enable;
			snps,usb3-u1u2-disable;
			snps,num-gsi-evt-buffs = <0x3>;
		};
	};

+54 −13
Original line number Diff line number Diff line
@@ -234,7 +234,7 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
 * otherwise ERR_PTR(errno).
 */
static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
		unsigned length)
		unsigned length, enum event_buf_type type)
{
	struct dwc3_event_buffer	*evt;

@@ -244,6 +244,7 @@ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,

	evt->dwc	= dwc;
	evt->length	= length;
	evt->type	= type;
	evt->buf	= dma_alloc_coherent(dwc->dev, length,
			&evt->dma, GFP_KERNEL);
	if (!evt->buf)
@@ -278,26 +279,40 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
 */
static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
{
	int			num;
	int	i;
	int	j = 0;

	num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
	dwc->num_event_buffers = num;
	dwc->num_event_buffers = dwc->num_normal_event_buffers +
		dwc->num_gsi_event_buffers;

	dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
	dwc->ev_buffs = devm_kzalloc(dwc->dev,
			sizeof(*dwc->ev_buffs) * dwc->num_event_buffers,
			GFP_KERNEL);
	if (!dwc->ev_buffs)
		return -ENOMEM;

	for (i = 0; i < num; i++) {
	for (i = 0; i < dwc->num_normal_event_buffers; i++) {
		struct dwc3_event_buffer	*evt;

		evt = dwc3_alloc_one_event_buffer(dwc, length);
		evt = dwc3_alloc_one_event_buffer(dwc, length,
				EVT_BUF_TYPE_NORMAL);
		if (IS_ERR(evt)) {
			dev_err(dwc->dev, "can't allocate event buffer\n");
			return PTR_ERR(evt);
		}
		dwc->ev_buffs[i] = evt;
		dwc->ev_buffs[j++] = evt;
	}

	for (i = 0; i < dwc->num_gsi_event_buffers; i++) {
		struct dwc3_event_buffer	*evt;

		evt = dwc3_alloc_one_event_buffer(dwc, length,
				EVT_BUF_TYPE_GSI);
		if (IS_ERR(evt)) {
			dev_err(dwc->dev, "can't allocate event buffer\n");
			return PTR_ERR(evt);
		}
		dwc->ev_buffs[j++] = evt;
	}

	return 0;
@@ -324,10 +339,23 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc)

		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
				lower_32_bits(evt->dma));

		if (evt->type == EVT_BUF_TYPE_NORMAL) {
			dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
					upper_32_bits(evt->dma));
			dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
					DWC3_GEVNTSIZ_SIZE(evt->length));
		} else {
			dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
				DWC3_GEVNTADRHI_EVNTADRHI_GSI_EN(
					DWC3_GEVENT_TYPE_GSI) |
				DWC3_GEVNTADRHI_EVNTADRHI_GSI_IDX(n));

			dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
				DWC3_GEVNTCOUNT_EVNTINTRPTMASK |
				((evt->length) & 0xffff));
		}

		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
	}

@@ -803,6 +831,7 @@ static int dwc3_probe(struct platform_device *pdev)
	struct dwc3		*dwc;
	u8			lpm_nyet_threshold;
	u8			hird_threshold;
	u32			num_evt_buffs;

	int			ret;

@@ -891,6 +920,18 @@ static int dwc3_probe(struct platform_device *pdev)

		dwc->disable_clk_gating = of_property_read_bool(node,
					"snps,disable-clk-gating");

		dwc->num_normal_event_buffers = 1;
		ret = of_property_read_u32(node,
			"snps,num-normal-evt-buffs", &num_evt_buffs);
		if (!ret)
			dwc->num_normal_event_buffers = num_evt_buffs;

		ret = of_property_read_u32(node,
			"snps,num-gsi-evt-buffs", &num_evt_buffs);
		if (!ret)
			dwc->num_gsi_event_buffers = num_evt_buffs;

		if (dwc->enable_bus_suspend) {
			pm_runtime_set_autosuspend_delay(dev, 500);
			pm_runtime_use_autosuspend(dev);
+13 −0
Original line number Diff line number Diff line
@@ -124,6 +124,11 @@
#define DWC3_GEVNTSIZ(n)	(0xc408 + (n * 0x10))
#define DWC3_GEVNTCOUNT(n)	(0xc40c + (n * 0x10))

#define DWC3_GEVNTCOUNT_EVNTINTRPTMASK		(1 << 31)
#define DWC3_GEVNTADRHI_EVNTADRHI_GSI_EN(n)	(n << 22)
#define DWC3_GEVNTADRHI_EVNTADRHI_GSI_IDX(n)	(n << 16)
#define DWC3_GEVENT_TYPE_GSI			0x3

#define DWC3_GHWPARAMS8		0xc600
#define DWC3_GFLADJ		0xc630

@@ -439,6 +444,11 @@

struct dwc3_trb;

enum event_buf_type {
	EVT_BUF_TYPE_NORMAL,
	EVT_BUF_TYPE_GSI
};

/**
 * struct dwc3_event_buffer - Software event buffer representation
 * @buf: _THE_ buffer
@@ -452,6 +462,7 @@ struct dwc3_trb;
struct dwc3_event_buffer {
	void			*buf;
	unsigned		length;
	enum event_buf_type	type;
	unsigned int		lpos;
	unsigned int		count;
	unsigned int		flags;
@@ -855,6 +866,8 @@ struct dwc3 {

	u32			nr_scratch;
	u32			num_event_buffers;
	u32			num_normal_event_buffers;
	u32			num_gsi_event_buffers;

	u32			u1;
	u32			u1u2;
+2 −2
Original line number Diff line number Diff line
@@ -3443,7 +3443,7 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
	spin_lock_irqsave(&dwc->lock, flags);
	dwc->bh_handled_evt_cnt[dwc->bh_dbg_index] = 0;

	for (i = 0; i < dwc->num_event_buffers; i++)
	for (i = 0; i < dwc->num_normal_event_buffers; i++)
		ret |= dwc3_process_event_buf(dwc, i);

	spin_unlock_irqrestore(&dwc->lock, flags);
@@ -3499,7 +3499,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
		return IRQ_HANDLED;
	}

	for (i = 0; i < dwc->num_event_buffers; i++) {
	for (i = 0; i < dwc->num_normal_event_buffers; i++) {
		irqreturn_t status;

		status = dwc3_check_event_buf(dwc, i);