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

Commit 25534828 authored by Alexandre Bailon's avatar Alexandre Bailon Committed by Greg Kroah-Hartman
Browse files

usb: musb: dsps: Manage CPPI 4.1 DMA interrupt in DSPS



Despite the CPPI 4.1 is a generic DMA, it is tied to USB.
On the DSPS, CPPI 4.1 interrupt's registers are in USBSS (the MUSB glue).
Currently, to enable / disable and clear interrupts, the CPPI 4.1 driver
maps and accesses to USBSS's register, which making CPPI 4.1 driver not
really generic.
Move the interrupt management to DSPS driver.

Signed-off-by: default avatarAlexandre Bailon <abailon@baylibre.com>
Acked-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarBin Liu <b-liu@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a96ca0d2
Loading
Loading
Loading
Loading
+7 −21
Original line number Diff line number Diff line
@@ -79,14 +79,6 @@
#define QMGR_QUEUE_C(n)	(0x2008 + (n) * 0x10)
#define QMGR_QUEUE_D(n)	(0x200c + (n) * 0x10)

/* Glue layer specific */
/* USBSS  / USB AM335x */
#define USBSS_IRQ_STATUS	0x28
#define USBSS_IRQ_ENABLER	0x2c
#define USBSS_IRQ_CLEARR	0x30

#define USBSS_IRQ_PD_COMP	(1 <<  2)

/* Packet Descriptor */
#define PD2_ZERO_LENGTH		(1 << 19)

@@ -294,14 +286,8 @@ static irqreturn_t cppi41_irq(int irq, void *data)
{
	struct cppi41_dd *cdd = data;
	struct cppi41_channel *c;
	u32 status;
	int i;

	status = cppi_readl(cdd->usbss_mem + USBSS_IRQ_STATUS);
	if (!(status & USBSS_IRQ_PD_COMP))
		return IRQ_NONE;
	cppi_writel(status, cdd->usbss_mem + USBSS_IRQ_STATUS);

	for (i = QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE); i < QMGR_NUM_PEND;
			i++) {
		u32 val;
@@ -618,6 +604,7 @@ static void cppi41_compute_td_desc(struct cppi41_desc *d)

static int cppi41_tear_down_chan(struct cppi41_channel *c)
{
	struct dmaengine_result abort_result;
	struct cppi41_dd *cdd = c->cdd;
	struct cppi41_desc *td;
	u32 reg;
@@ -701,6 +688,12 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
	c->td_seen = 0;
	c->td_desc_seen = 0;
	cppi_writel(0, c->gcr_reg);

	/* Invoke the callback to do the necessary clean-up */
	abort_result.result = DMA_TRANS_ABORTED;
	dma_cookie_complete(&c->txd);
	dmaengine_desc_get_callback_invoke(&c->txd, &abort_result);

	return 0;
}

@@ -1066,8 +1059,6 @@ static int cppi41_dma_probe(struct platform_device *pdev)
		goto err_irq;
	}

	cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER);

	ret = devm_request_irq(&pdev->dev, irq, glue_info->isr, IRQF_SHARED,
			dev_name(dev), cdd);
	if (ret)
@@ -1091,7 +1082,6 @@ static int cppi41_dma_probe(struct platform_device *pdev)
	dma_async_device_unregister(&cdd->ddev);
err_dma_reg:
err_irq:
	cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
	cleanup_chans(cdd);
err_chans:
	deinit_cppi41(dev, cdd);
@@ -1119,7 +1109,6 @@ static int cppi41_dma_remove(struct platform_device *pdev)
	of_dma_controller_free(pdev->dev.of_node);
	dma_async_device_unregister(&cdd->ddev);

	cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
	devm_free_irq(&pdev->dev, cdd->irq, cdd);
	cleanup_chans(cdd);
	deinit_cppi41(&pdev->dev, cdd);
@@ -1138,7 +1127,6 @@ static int __maybe_unused cppi41_suspend(struct device *dev)
	struct cppi41_dd *cdd = dev_get_drvdata(dev);

	cdd->dma_tdfdq = cppi_readl(cdd->ctrl_mem + DMA_TDFDQ);
	cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
	disable_sched(cdd);

	return 0;
@@ -1164,8 +1152,6 @@ static int __maybe_unused cppi41_resume(struct device *dev)
	cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE);
	cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE);

	cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER);

	return 0;
}

+79 −2
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ struct dsps_glue {
	struct timer_list timer;	/* otg_workaround timer */
	unsigned long last_timer;    /* last timer data for each instance */
	bool sw_babble_enabled;
	void __iomem *usbss_base;

	struct dsps_context context;
	struct debugfs_regset32 regset;
@@ -169,6 +170,13 @@ static void dsps_mod_timer_optional(struct dsps_glue *glue)
	dsps_mod_timer(glue, -1);
}

/* USBSS  / USB AM335x */
#define USBSS_IRQ_STATUS	0x28
#define USBSS_IRQ_ENABLER	0x2c
#define USBSS_IRQ_CLEARR	0x30

#define USBSS_IRQ_PD_COMP	(1 << 2)

/**
 * dsps_musb_enable - enable interrupts
 */
@@ -641,14 +649,76 @@ static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
	}
}

#ifdef CONFIG_USB_TI_CPPI41_DMA
static void dsps_dma_controller_callback(struct dma_controller *c)
{
	struct musb *musb = c->musb;
	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
	void __iomem *usbss_base = glue->usbss_base;
	u32 status;

	status = musb_readl(usbss_base, USBSS_IRQ_STATUS);
	if (status & USBSS_IRQ_PD_COMP)
		musb_writel(usbss_base, USBSS_IRQ_STATUS, USBSS_IRQ_PD_COMP);
}

static struct dma_controller *
dsps_dma_controller_create(struct musb *musb, void __iomem *base)
{
	struct dma_controller *controller;
	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
	void __iomem *usbss_base = glue->usbss_base;

	controller = cppi41_dma_controller_create(musb, base);
	if (IS_ERR_OR_NULL(controller))
		return controller;

	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
	controller->dma_callback = dsps_dma_controller_callback;

	return controller;
}

static void dsps_dma_controller_destroy(struct dma_controller *c)
{
	struct musb *musb = c->musb;
	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
	void __iomem *usbss_base = glue->usbss_base;

	musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP);
	cppi41_dma_controller_destroy(c);
}

#ifdef CONFIG_PM_SLEEP
static void dsps_dma_controller_suspend(struct dsps_glue *glue)
{
	void __iomem *usbss_base = glue->usbss_base;

	musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP);
}

static void dsps_dma_controller_resume(struct dsps_glue *glue)
{
	void __iomem *usbss_base = glue->usbss_base;

	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
}
#endif
#else /* CONFIG_USB_TI_CPPI41_DMA */
#ifdef CONFIG_PM_SLEEP
static void dsps_dma_controller_suspend(struct dsps_glue *glue) {}
static void dsps_dma_controller_resume(struct dsps_glue *glue) {}
#endif
#endif /* CONFIG_USB_TI_CPPI41_DMA */

static struct musb_platform_ops dsps_ops = {
	.quirks		= MUSB_DMA_CPPI41 | MUSB_INDEXED_EP,
	.init		= dsps_musb_init,
	.exit		= dsps_musb_exit,

#ifdef CONFIG_USB_TI_CPPI41_DMA
	.dma_init	= cppi41_dma_controller_create,
	.dma_exit	= cppi41_dma_controller_destroy,
	.dma_init	= dsps_dma_controller_create,
	.dma_exit	= dsps_dma_controller_destroy,
#endif
	.enable		= dsps_musb_enable,
	.disable	= dsps_musb_disable,
@@ -856,6 +926,9 @@ static int dsps_probe(struct platform_device *pdev)

	glue->dev = &pdev->dev;
	glue->wrp = wrp;
	glue->usbss_base = of_iomap(pdev->dev.parent->of_node, 0);
	if (!glue->usbss_base)
		return -ENXIO;

	if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
		ret = dsps_setup_optional_vbus_irq(pdev, glue);
@@ -950,6 +1023,8 @@ static int dsps_suspend(struct device *dev)
	glue->context.tx_mode = musb_readl(mbase, wrp->tx_mode);
	glue->context.rx_mode = musb_readl(mbase, wrp->rx_mode);

	dsps_dma_controller_suspend(glue);

	return 0;
}

@@ -963,6 +1038,8 @@ static int dsps_resume(struct device *dev)
	if (!musb)
		return 0;

	dsps_dma_controller_resume(glue);

	mbase = musb->ctrl_base;
	musb_writel(mbase, wrp->control, glue->context.control);
	musb_writel(mbase, wrp->epintr_set, glue->context.epintr);