linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support
@ 2019-04-09 12:09 Alexandre Belloni
  2019-04-09 12:09 ` [PATCH 1/5] usb: gadget: udc: lpc32xx: simplify probe Alexandre Belloni
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Alexandre Belloni @ 2019-04-09 12:09 UTC (permalink / raw)
  To: Felipe Balbi, Vladimir Zapolskiy
  Cc: Greg Kroah-Hartman, Sylvain Lemieux, linux-usb, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Hi,

This series starts to clean up the lpc32xx udc driver and also repairs
interrupt handling so hotplugging actually works. The design I tested
that on uses an stotg04 instead of the usual isp1301 so support for that
is also added.

A bit more work is needed to get the RNDIS gadget driver to work.

Alexandre Belloni (5):
  usb: gadget: udc: lpc32xx: simplify probe
  usb: gadget: udc: lpc32xx: simplify vbus handling
  usb: gadget: udc: lpc32xx: properly setup phy interrupts
  usb: gadget: udc: lpc32xx: add support for stotg04 phy
  usb: gadget: udc: lpc32xx: rework interrupt handling

 drivers/usb/gadget/udc/lpc32xx_udc.c | 167 +++++++++++----------------
 1 file changed, 66 insertions(+), 101 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] usb: gadget: udc: lpc32xx: simplify probe
  2019-04-09 12:09 [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support Alexandre Belloni
@ 2019-04-09 12:09 ` Alexandre Belloni
  2019-04-09 12:09 ` [PATCH 2/5] usb: gadget: udc: lpc32xx: simplify vbus handling Alexandre Belloni
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2019-04-09 12:09 UTC (permalink / raw)
  To: Felipe Balbi, Vladimir Zapolskiy
  Cc: Greg Kroah-Hartman, Sylvain Lemieux, linux-usb, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Simplify .probe and .remove by using devm managed allocations and requests.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/usb/gadget/udc/lpc32xx_udc.c | 93 ++++++++--------------------
 1 file changed, 25 insertions(+), 68 deletions(-)

diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index b0781771704e..5546cb509085 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -129,8 +129,6 @@ struct lpc32xx_udc {
 
 	/* Board and device specific */
 	struct lpc32xx_usbd_cfg	*board;
-	u32			io_p_start;
-	u32			io_p_size;
 	void __iomem		*udp_baseaddr;
 	int			udp_irq[4];
 	struct clk		*usb_slv_clk;
@@ -2999,7 +2997,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 	dma_addr_t dma_handle;
 	struct device_node *isp1301_node;
 
-	udc = kmemdup(&controller_template, sizeof(*udc), GFP_KERNEL);
+	udc = devm_kmemdup(dev, &controller_template, sizeof(*udc), GFP_KERNEL);
 	if (!udc)
 		return -ENOMEM;
 
@@ -3022,8 +3020,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 
 	udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
 	if (!udc->isp1301_i2c_client) {
-		retval = -EPROBE_DEFER;
-		goto phy_fail;
+		return -EPROBE_DEFER;
 	}
 
 	dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n",
@@ -3032,7 +3029,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 	pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
 	retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 	if (retval)
-		goto resource_fail;
+		return retval;
 
 	udc->board = &lpc32xx_usbddata;
 
@@ -3045,10 +3042,8 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 	 *  IORESOURCE_IRQ, USB transceiver interrupt number
 	 */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		retval = -ENXIO;
-		goto resource_fail;
-	}
+	if (!res)
+		return -ENXIO;
 
 	spin_lock_init(&udc->lock);
 
@@ -3058,39 +3053,28 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 		if (udc->udp_irq[i] < 0) {
 			dev_err(udc->dev,
 				"irq resource %d not available!\n", i);
-			retval = udc->udp_irq[i];
-			goto irq_fail;
+			return udc->udp_irq[i];
 		}
 	}
 
-	udc->io_p_start = res->start;
-	udc->io_p_size = resource_size(res);
-	if (!request_mem_region(udc->io_p_start, udc->io_p_size, driver_name)) {
-		dev_err(udc->dev, "someone's using UDC memory\n");
-		retval = -EBUSY;
-		goto request_mem_region_fail;
-	}
-
-	udc->udp_baseaddr = ioremap(udc->io_p_start, udc->io_p_size);
+	udc->udp_baseaddr = devm_ioremap_resource(dev, res);
 	if (!udc->udp_baseaddr) {
-		retval = -ENOMEM;
 		dev_err(udc->dev, "IO map failure\n");
-		goto io_map_fail;
+		return -ENOMEM;
 	}
 
 	/* Get USB device clock */
-	udc->usb_slv_clk = clk_get(&pdev->dev, NULL);
+	udc->usb_slv_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(udc->usb_slv_clk)) {
 		dev_err(udc->dev, "failed to acquire USB device clock\n");
-		retval = PTR_ERR(udc->usb_slv_clk);
-		goto usb_clk_get_fail;
+		return PTR_ERR(udc->usb_slv_clk);
 	}
 
 	/* Enable USB device clock */
 	retval = clk_prepare_enable(udc->usb_slv_clk);
 	if (retval < 0) {
 		dev_err(udc->dev, "failed to start USB device clock\n");
-		goto usb_clk_enable_fail;
+		return retval;
 	}
 
 	/* Setup deferred workqueue data */
@@ -3134,37 +3118,37 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 
 	/* Request IRQs - low and high priority USB device IRQs are routed to
 	 * the same handler, while the DMA interrupt is routed elsewhere */
-	retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
-			     0, "udc_lp", udc);
+	retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_LP],
+				  lpc32xx_usb_lp_irq, 0, "udc_lp", udc);
 	if (retval < 0) {
 		dev_err(udc->dev, "LP request irq %d failed\n",
 			udc->udp_irq[IRQ_USB_LP]);
-		goto irq_lp_fail;
+		goto irq_req_fail;
 	}
-	retval = request_irq(udc->udp_irq[IRQ_USB_HP], lpc32xx_usb_hp_irq,
-			     0, "udc_hp", udc);
+	retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_HP],
+				  lpc32xx_usb_hp_irq, 0, "udc_hp", udc);
 	if (retval < 0) {
 		dev_err(udc->dev, "HP request irq %d failed\n",
 			udc->udp_irq[IRQ_USB_HP]);
-		goto irq_hp_fail;
+		goto irq_req_fail;
 	}
 
-	retval = request_irq(udc->udp_irq[IRQ_USB_DEVDMA],
-			     lpc32xx_usb_devdma_irq, 0, "udc_dma", udc);
+	retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_DEVDMA],
+				  lpc32xx_usb_devdma_irq, 0, "udc_dma", udc);
 	if (retval < 0) {
 		dev_err(udc->dev, "DEV request irq %d failed\n",
 			udc->udp_irq[IRQ_USB_DEVDMA]);
-		goto irq_dev_fail;
+		goto irq_req_fail;
 	}
 
 	/* The transceiver interrupt is used for VBUS detection and will
 	   kick off the VBUS handler function */
-	retval = request_irq(udc->udp_irq[IRQ_USB_ATX], lpc32xx_usb_vbus_irq,
-			     0, "udc_otg", udc);
+	retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_ATX],
+				  lpc32xx_usb_vbus_irq, 0, "udc_otg", udc);
 	if (retval < 0) {
 		dev_err(udc->dev, "VBUS request irq %d failed\n",
 			udc->udp_irq[IRQ_USB_ATX]);
-		goto irq_xcvr_fail;
+		goto irq_req_fail;
 	}
 
 	/* Initialize wait queue */
@@ -3190,32 +3174,15 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 	return 0;
 
 add_gadget_fail:
-	free_irq(udc->udp_irq[IRQ_USB_ATX], udc);
-irq_xcvr_fail:
-	free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc);
-irq_dev_fail:
-	free_irq(udc->udp_irq[IRQ_USB_HP], udc);
-irq_hp_fail:
-	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
-irq_lp_fail:
+irq_req_fail:
 	dma_pool_destroy(udc->dd_cache);
 dma_alloc_fail:
 	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
 			  udc->udca_v_base, udc->udca_p_base);
 i2c_fail:
 	clk_disable_unprepare(udc->usb_slv_clk);
-usb_clk_enable_fail:
-	clk_put(udc->usb_slv_clk);
-usb_clk_get_fail:
-	iounmap(udc->udp_baseaddr);
-io_map_fail:
-	release_mem_region(udc->io_p_start, udc->io_p_size);
 	dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
-request_mem_region_fail:
-irq_fail:
-resource_fail:
-phy_fail:
-	kfree(udc);
+
 	return retval;
 }
 
@@ -3231,24 +3198,14 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)
 	udc_disable(udc);
 	pullup(udc, 0);
 
-	free_irq(udc->udp_irq[IRQ_USB_ATX], udc);
-
 	device_init_wakeup(&pdev->dev, 0);
 	remove_debug_file(udc);
 
 	dma_pool_destroy(udc->dd_cache);
 	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
 			  udc->udca_v_base, udc->udca_p_base);
-	free_irq(udc->udp_irq[IRQ_USB_DEVDMA], udc);
-	free_irq(udc->udp_irq[IRQ_USB_HP], udc);
-	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 
 	clk_disable_unprepare(udc->usb_slv_clk);
-	clk_put(udc->usb_slv_clk);
-
-	iounmap(udc->udp_baseaddr);
-	release_mem_region(udc->io_p_start, udc->io_p_size);
-	kfree(udc);
 
 	return 0;
 }
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] usb: gadget: udc: lpc32xx: simplify vbus handling
  2019-04-09 12:09 [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support Alexandre Belloni
  2019-04-09 12:09 ` [PATCH 1/5] usb: gadget: udc: lpc32xx: simplify probe Alexandre Belloni
@ 2019-04-09 12:09 ` Alexandre Belloni
  2019-04-09 12:09 ` [PATCH 3/5] usb: gadget: udc: lpc32xx: properly setup phy interrupts Alexandre Belloni
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2019-04-09 12:09 UTC (permalink / raw)
  To: Felipe Balbi, Vladimir Zapolskiy
  Cc: Greg Kroah-Hartman, Sylvain Lemieux, linux-usb, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Use a threaded IRQ to handle vbus_work instead of using the global
worqueue.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/usb/gadget/udc/lpc32xx_udc.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 5546cb509085..777279fa4637 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -152,7 +152,6 @@ struct lpc32xx_udc {
 
 	/* Work queues related to I2C support */
 	struct work_struct	pullup_job;
-	struct work_struct	vbus_job;
 	struct work_struct	power_job;
 
 	/* USB device peripheral - various */
@@ -2828,11 +2827,9 @@ static irqreturn_t lpc32xx_usb_devdma_irq(int irq, void *_udc)
  * VBUS detection, pullup handler, and Gadget cable state notification
  *
  */
-static void vbus_work(struct work_struct *work)
+static void vbus_work(struct lpc32xx_udc *udc)
 {
 	u8 value;
-	struct lpc32xx_udc *udc = container_of(work, struct lpc32xx_udc,
-					       vbus_job);
 
 	if (udc->enabled != 0) {
 		/* Discharge VBUS real quick */
@@ -2877,9 +2874,7 @@ static irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc)
 {
 	struct lpc32xx_udc *udc = _udc;
 
-	/* Defer handling of VBUS IRQ to work queue */
-	disable_irq_nosync(udc->udp_irq[IRQ_USB_ATX]);
-	schedule_work(&udc->vbus_job);
+	vbus_work(udc);
 
 	return IRQ_HANDLED;
 }
@@ -2908,7 +2903,7 @@ static int lpc32xx_start(struct usb_gadget *gadget,
 
 	/* Force VBUS process once to check for cable insertion */
 	udc->last_vbus = udc->vbus = 0;
-	schedule_work(&udc->vbus_job);
+	vbus_work(udc);
 
 	/* Do not re-enable ATX IRQ (3) */
 	for (i = IRQ_USB_LP; i < IRQ_USB_ATX; i++)
@@ -3080,7 +3075,6 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 	/* Setup deferred workqueue data */
 	udc->poweron = udc->pullup = 0;
 	INIT_WORK(&udc->pullup_job, pullup_work);
-	INIT_WORK(&udc->vbus_job, vbus_work);
 #ifdef CONFIG_PM
 	INIT_WORK(&udc->power_job, power_work);
 #endif
@@ -3143,8 +3137,9 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 
 	/* The transceiver interrupt is used for VBUS detection and will
 	   kick off the VBUS handler function */
-	retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_ATX],
-				  lpc32xx_usb_vbus_irq, 0, "udc_otg", udc);
+	retval = devm_request_threaded_irq(dev, udc->udp_irq[IRQ_USB_ATX], NULL,
+					   lpc32xx_usb_vbus_irq, IRQF_ONESHOT,
+					   "udc_otg", udc);
 	if (retval < 0) {
 		dev_err(udc->dev, "VBUS request irq %d failed\n",
 			udc->udp_irq[IRQ_USB_ATX]);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] usb: gadget: udc: lpc32xx: properly setup phy interrupts
  2019-04-09 12:09 [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support Alexandre Belloni
  2019-04-09 12:09 ` [PATCH 1/5] usb: gadget: udc: lpc32xx: simplify probe Alexandre Belloni
  2019-04-09 12:09 ` [PATCH 2/5] usb: gadget: udc: lpc32xx: simplify vbus handling Alexandre Belloni
@ 2019-04-09 12:09 ` Alexandre Belloni
  2019-04-09 12:09 ` [PATCH 4/5] usb: gadget: udc: lpc32xx: add support for stotg04 phy Alexandre Belloni
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2019-04-09 12:09 UTC (permalink / raw)
  To: Felipe Balbi, Vladimir Zapolskiy
  Cc: Greg Kroah-Hartman, Sylvain Lemieux, linux-usb, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Only INT_VBUS_VLD is set to generate ATX interrupts on the phy but
INT_SESS_VLD is checked in vbus_work. This leads to cases where
hot-plugging USB doesn't work after boot.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/usb/gadget/udc/lpc32xx_udc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 777279fa4637..12f2d76e50fe 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -604,11 +604,11 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc)
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
 		ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-		ISP1301_I2C_INTERRUPT_FALLING, INT_VBUS_VLD);
+		ISP1301_I2C_INTERRUPT_FALLING, INT_SESS_VLD | INT_VBUS_VLD);
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
 		ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-		ISP1301_I2C_INTERRUPT_RISING, INT_VBUS_VLD);
+		ISP1301_I2C_INTERRUPT_RISING, INT_SESS_VLD | INT_VBUS_VLD);
 
 	dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n",
 		 i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00));
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] usb: gadget: udc: lpc32xx: add support for stotg04 phy
  2019-04-09 12:09 [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support Alexandre Belloni
                   ` (2 preceding siblings ...)
  2019-04-09 12:09 ` [PATCH 3/5] usb: gadget: udc: lpc32xx: properly setup phy interrupts Alexandre Belloni
@ 2019-04-09 12:09 ` Alexandre Belloni
  2019-04-09 12:09 ` [PATCH 5/5] usb: gadget: udc: lpc32xx: rework interrupt handling Alexandre Belloni
  2019-05-13 11:32 ` [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support James Grant
  5 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2019-04-09 12:09 UTC (permalink / raw)
  To: Felipe Balbi, Vladimir Zapolskiy
  Cc: Greg Kroah-Hartman, Sylvain Lemieux, linux-usb, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

The STOTG04 phy is used as a drop-in replacement of the ISP1301 but some
bits doesn't have exactly the same meaning and this can lead to issues.
Detect the phy dynamically and avoid writing to reserved bits.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/usb/gadget/udc/lpc32xx_udc.c | 32 +++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 12f2d76e50fe..5d6246d23b99 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -115,6 +115,11 @@ struct lpc32xx_ep {
 	bool			wedge;
 };
 
+enum atx_type {
+	ISP1301,
+	STOTG04,
+};
+
 /*
  * Common UDC structure
  */
@@ -149,6 +154,7 @@ struct lpc32xx_udc {
 	u8			last_vbus;
 	int			pullup;
 	int			poweron;
+	enum atx_type		atx;
 
 	/* Work queues related to I2C support */
 	struct work_struct	pullup_job;
@@ -550,6 +556,15 @@ static inline void remove_debug_file(struct lpc32xx_udc *udc) {}
 /* Primary initialization sequence for the ISP1301 transceiver */
 static void isp1301_udc_configure(struct lpc32xx_udc *udc)
 {
+	u8 value;
+	s32 vendor, product;
+
+	vendor = i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00);
+	product = i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02);
+
+	if (vendor == 0x0483 && product == 0xa0c4)
+		udc->atx = STOTG04;
+
 	/* LPC32XX only supports DAT_SE0 USB mode */
 	/* This sequence is important */
 
@@ -569,8 +584,12 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc)
 	 */
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
 		(ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR), ~0);
+
+	value = MC2_BI_DI;
+	if (udc->atx != STOTG04)
+		value |= MC2_SPD_SUSP_CTRL;
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-		ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_SPD_SUSP_CTRL));
+		ISP1301_I2C_MODE_CONTROL_2, value);
 
 	/* Driver VBUS_DRV high or low depending on board setup */
 	if (udc->board->vbus_drv_pol != 0)
@@ -610,12 +629,11 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc)
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
 		ISP1301_I2C_INTERRUPT_RISING, INT_SESS_VLD | INT_VBUS_VLD);
 
-	dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n",
-		 i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x00));
-	dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n",
-		 i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x02));
+	dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n", vendor);
+	dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n", product);
 	dev_info(udc->dev, "ISP1301 Version ID : 0x%04x\n",
 		 i2c_smbus_read_word_data(udc->isp1301_i2c_client, 0x14));
+
 }
 
 /* Enables or disables the USB device pullup via the ISP1301 transceiver */
@@ -658,6 +676,10 @@ static void isp1301_pullup_enable(struct lpc32xx_udc *udc, int en_pullup,
 /* Powers up or down the ISP1301 transceiver */
 static void isp1301_set_powerstate(struct lpc32xx_udc *udc, int enable)
 {
+	/* There is no "global power down" register for stotg04 */
+	if (udc->atx == STOTG04)
+		return;
+
 	if (enable != 0)
 		/* Power up ISP1301 - this ISP1301 will automatically wakeup
 		   when VBUS is detected */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] usb: gadget: udc: lpc32xx: rework interrupt handling
  2019-04-09 12:09 [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support Alexandre Belloni
                   ` (3 preceding siblings ...)
  2019-04-09 12:09 ` [PATCH 4/5] usb: gadget: udc: lpc32xx: add support for stotg04 phy Alexandre Belloni
@ 2019-04-09 12:09 ` Alexandre Belloni
  2019-05-13 11:32 ` [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support James Grant
  5 siblings, 0 replies; 8+ messages in thread
From: Alexandre Belloni @ 2019-04-09 12:09 UTC (permalink / raw)
  To: Felipe Balbi, Vladimir Zapolskiy
  Cc: Greg Kroah-Hartman, Sylvain Lemieux, linux-usb, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

There is no actual need to do the enable/disable_irq dance. Instead enable
the interrupts on the phy only when necessary.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 drivers/usb/gadget/udc/lpc32xx_udc.c | 29 ++++++++++------------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 5d6246d23b99..d8f1c60793ed 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -617,17 +617,13 @@ static void isp1301_udc_configure(struct lpc32xx_udc *udc)
 		(ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR),
 		OTG1_VBUS_DISCHRG);
 
-	/* Clear and enable VBUS high edge interrupt */
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
 		ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
 		ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
-	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-		ISP1301_I2C_INTERRUPT_FALLING, INT_SESS_VLD | INT_VBUS_VLD);
 	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
 		ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
-	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
-		ISP1301_I2C_INTERRUPT_RISING, INT_SESS_VLD | INT_VBUS_VLD);
 
 	dev_info(udc->dev, "ISP1301 Vendor ID  : 0x%04x\n", vendor);
 	dev_info(udc->dev, "ISP1301 Product ID : 0x%04x\n", product);
@@ -2887,9 +2883,6 @@ static void vbus_work(struct lpc32xx_udc *udc)
 			lpc32xx_vbus_session(&udc->gadget, udc->vbus);
 		}
 	}
-
-	/* Re-enable after completion */
-	enable_irq(udc->udp_irq[IRQ_USB_ATX]);
 }
 
 static irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc)
@@ -2905,7 +2898,6 @@ static int lpc32xx_start(struct usb_gadget *gadget,
 			 struct usb_gadget_driver *driver)
 {
 	struct lpc32xx_udc *udc = to_udc(gadget);
-	int i;
 
 	if (!driver || driver->max_speed < USB_SPEED_FULL || !driver->setup) {
 		dev_err(udc->dev, "bad parameter.\n");
@@ -2927,20 +2919,23 @@ static int lpc32xx_start(struct usb_gadget *gadget,
 	udc->last_vbus = udc->vbus = 0;
 	vbus_work(udc);
 
-	/* Do not re-enable ATX IRQ (3) */
-	for (i = IRQ_USB_LP; i < IRQ_USB_ATX; i++)
-		enable_irq(udc->udp_irq[i]);
+	/* enable interrupts */
+	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_FALLING, INT_SESS_VLD | INT_VBUS_VLD);
+	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_RISING, INT_SESS_VLD | INT_VBUS_VLD);
 
 	return 0;
 }
 
 static int lpc32xx_stop(struct usb_gadget *gadget)
 {
-	int i;
 	struct lpc32xx_udc *udc = to_udc(gadget);
 
-	for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
-		disable_irq(udc->udp_irq[i]);
+	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
+	i2c_smbus_write_byte_data(udc->isp1301_i2c_client,
+		ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, ~0);
 
 	if (udc->clocked) {
 		spin_lock(&udc->lock);
@@ -3172,10 +3167,6 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
 	init_waitqueue_head(&udc->ep_disable_wait_queue);
 	atomic_set(&udc->enabled_ep_cnt, 0);
 
-	/* Keep all IRQs disabled until GadgetFS starts up */
-	for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
-		disable_irq(udc->udp_irq[i]);
-
 	retval = usb_add_gadget_udc(dev, &udc->gadget);
 	if (retval < 0)
 		goto add_gadget_fail;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support
  2019-04-09 12:09 [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support Alexandre Belloni
                   ` (4 preceding siblings ...)
  2019-04-09 12:09 ` [PATCH 5/5] usb: gadget: udc: lpc32xx: rework interrupt handling Alexandre Belloni
@ 2019-05-13 11:32 ` James Grant
  2019-05-22 15:00   ` Sylvain Lemieux
  5 siblings, 1 reply; 8+ messages in thread
From: James Grant @ 2019-05-13 11:32 UTC (permalink / raw)
  To: Alexandre Belloni, Felipe Balbi, Vladimir Zapolskiy
  Cc: Greg Kroah-Hartman, Sylvain Lemieux, linux-usb, linux-arm-kernel,
	linux-kernel, Alexandre Belloni

Tested with a board containing LPC3250 SOC and STOTG04 PHY by using 
serial gadget.

Needed patch "[PATCH] usb: gadget: udc: lpc32xx: allocate descriptor 
with GFP_ATOMIC" also.

Tested-by: James Grant <jamesg@zaltys.org>

Regards,
James Grant.

On 09/04/2019 14:09, Alexandre Belloni Wrote:
> Hi,
>
> This series starts to clean up the lpc32xx udc driver and also repairs
> interrupt handling so hotplugging actually works. The design I tested
> that on uses an stotg04 instead of the usual isp1301 so support for that
> is also added.
>
> A bit more work is needed to get the RNDIS gadget driver to work.
>
> Alexandre Belloni (5):
>    usb: gadget: udc: lpc32xx: simplify probe
>    usb: gadget: udc: lpc32xx: simplify vbus handling
>    usb: gadget: udc: lpc32xx: properly setup phy interrupts
>    usb: gadget: udc: lpc32xx: add support for stotg04 phy
>    usb: gadget: udc: lpc32xx: rework interrupt handling
>
>   drivers/usb/gadget/udc/lpc32xx_udc.c | 167 +++++++++++----------------
>   1 file changed, 66 insertions(+), 101 deletions(-)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support
  2019-05-13 11:32 ` [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support James Grant
@ 2019-05-22 15:00   ` Sylvain Lemieux
  0 siblings, 0 replies; 8+ messages in thread
From: Sylvain Lemieux @ 2019-05-22 15:00 UTC (permalink / raw)
  To: James Grant
  Cc: Alexandre Belloni, Felipe Balbi, Vladimir Zapolskiy,
	Greg Kroah-Hartman, linux-usb, moderated list:ARM PORT,
	linux-kernel

You can add my "Acked-by" on the 5 patches.
Acked-by: Sylvain Lemieux <slemieux.tyco@gmail.com>

On Mon, May 13, 2019 at 7:32 AM James Grant <jamesg@zaltys.org> wrote:
>
> Tested with a board containing LPC3250 SOC and STOTG04 PHY by using
> serial gadget.
>
> Needed patch "[PATCH] usb: gadget: udc: lpc32xx: allocate descriptor
> with GFP_ATOMIC" also.
>
> Tested-by: James Grant <jamesg@zaltys.org>
>
> Regards,
> James Grant.
>
> On 09/04/2019 14:09, Alexandre Belloni Wrote:
> > Hi,
> >
> > This series starts to clean up the lpc32xx udc driver and also repairs
> > interrupt handling so hotplugging actually works. The design I tested
> > that on uses an stotg04 instead of the usual isp1301 so support for that
> > is also added.
> >
> > A bit more work is needed to get the RNDIS gadget driver to work.
> >
> > Alexandre Belloni (5):
> >    usb: gadget: udc: lpc32xx: simplify probe
> >    usb: gadget: udc: lpc32xx: simplify vbus handling
> >    usb: gadget: udc: lpc32xx: properly setup phy interrupts
> >    usb: gadget: udc: lpc32xx: add support for stotg04 phy
> >    usb: gadget: udc: lpc32xx: rework interrupt handling
> >
> >   drivers/usb/gadget/udc/lpc32xx_udc.c | 167 +++++++++++----------------
> >   1 file changed, 66 insertions(+), 101 deletions(-)

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-05-22 15:01 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-09 12:09 [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support Alexandre Belloni
2019-04-09 12:09 ` [PATCH 1/5] usb: gadget: udc: lpc32xx: simplify probe Alexandre Belloni
2019-04-09 12:09 ` [PATCH 2/5] usb: gadget: udc: lpc32xx: simplify vbus handling Alexandre Belloni
2019-04-09 12:09 ` [PATCH 3/5] usb: gadget: udc: lpc32xx: properly setup phy interrupts Alexandre Belloni
2019-04-09 12:09 ` [PATCH 4/5] usb: gadget: udc: lpc32xx: add support for stotg04 phy Alexandre Belloni
2019-04-09 12:09 ` [PATCH 5/5] usb: gadget: udc: lpc32xx: rework interrupt handling Alexandre Belloni
2019-05-13 11:32 ` [PATCH 0/5] usb: gadget: udc: lpc32xx: add stotg04 phy support James Grant
2019-05-22 15:00   ` Sylvain Lemieux

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).