Skip to contentSkip to conversation

mv-usb fix and enhancement patches

PATCH Superseded Chao Xie 4 participants 32 messages Jan 21, 2013 – Jan 24, 2013 1 message not in the archive

Subsystems (5)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Chao Xie

author
#1 lore raw

v4 cover mv-usb fix and enhancement patches

The patches are divied into 4 parts
1. bug fixes
usb: gadget: mv_udc: use udc_start and udc_stop functions
usb: gadget: mv_udc: use devm_xxx for probe
usb: gadget: mv_udc: fix the warning of mv_udc_remove
usb: otg: mv_otg: use devm_xxx for probe
usb: host: ehci-mv: remove unused variable
usb: gadget: mv_udc: fix the value of tranceiver
usb: gadget: mv_udc: make mv_udc depends on ARCH_MMP or ARCH_PXA
Above patches are bug fixes.

2. PHY driver
To remove the callbacks in the platform data, a usb PHY driver for marvell udc/otg/ehci is written.
For device tree support, it is not good to pass the callback pointers by platform data. The PHY driver also removes the block.

usb: phy: mv_usb2: add PHY driver for marvell usb2 controller
usb: gadget: mv_udc: use PHY driver for udc
usb: ehci: ehci-mv: use PHY driver for ehci
usb: otg: mv_otg: use PHY driver for otg
Above patches are marvell usb PHY driver support.

arm: mmp2: change the defintion of usb devices
arm: pxa910: change the defintion of usb devices
arm: brownstone: add usb support for the board
arm: ttc_dkb: add usb support
arm: mmp: remove the usb phy setting
arm: mmp: remove usb devices from pxa168
Above patches are for SOC/board support for marvell usb PHY driver.

3. external chip support
The marvell usb controller can detect the vbus/idpin, but it need PHY and usb clocks to be enabled.
Based on measurement it will import 15mA current, and increase the power when the usb is not used.
Using a external chip to detect vbus/idpin changes will save the power.
In fact the marvell PMIC 88pm860x and 88pm80x can do it. The drivers are located at drivers/mfd.
So add a middle layer in the marvell usb PHY driver. PMIC call the APIs in middle driver to registers the callback for vbus/idpin detection/query
udc/otg/ehci driver will call the APIs to get vbus/idpin changes and query the states of the vbus/idpin.
usb: phy: mv_usb2_phy: add externel chip support
usb: gadget: mv_udc: add extern chip support
usb: ehci: ehci-mv: add extern chip support
usb: otg: mv_otg: add extern chip support
Above patches are the middle layer suppor for udc/otg/ehci

arm: mmp: add extern chip support for brownstone
arm: mmp: add extern chip support for ttc_dkb
Above patches are corresponding board file changes

4. device tree support
After removing the callbacks in platform data, and the not constant variables in platform data. All the information needed by udc/otg/ehci driver are constant.

usb: gadget: mv_udc: add device tree support
usb: otg: mv_otg: add device tree support
usb: ehci: ehci-mv: add device tree support
Above patches are device tree support for udc/otg/ehci driver.

V2->V1:
Change the Signed-off-by to be right email address

v3->v2
re-format the patches to new code base

v4->v3
1. make mv udc gadget driver depend on ARCH_PXA and ARCH_MMP
2. remove __devinit and __devexit
3. make the driver compiled successful if CONFIG_MV_USB2_PHY is not defined. The modified patches are
usb: gadget: mv_udc: make mv_udc depends on ARCH_MMP or ARCH_PXA
usb: phy: mv_usb2: add PHY driver for marvell usb2 controller

Chao Xie (26):
usb: gadget: mv_udc: use udc_start and udc_stop functions
usb: gadget: mv_udc: use devm_xxx for probe
usb: gadget: mv_udc: fix the warning of mv_udc_remove
usb: otg: mv_otg: use devm_xxx for probe
usb: host: ehci-mv: remove unused variable
usb: gadget: mv_udc: fix the value of tranceiver
usb: gadget: mv_udc: make mv_udc depends on ARCH_MMP or ARCH_PXA
usb: phy: mv_usb2: add PHY driver for marvell usb2 controller
usb: gadget: mv_udc: use PHY driver for udc
usb: ehci: ehci-mv: use PHY driver for ehci
usb: otg: mv_otg: use PHY driver for otg
arm: mmp2: change the defintion of usb devices
arm: pxa910: change the defintion of usb devices
arm: brownstone: add usb support for the board
arm: ttc_dkb: add usb support
arm: mmp: remove the usb phy setting
arm: mmp: remove usb devices from pxa168
usb: phy: mv_usb2_phy: add externel chip support
usb: gadget: mv_udc: add extern chip support
usb: ehci: ehci-mv: add extern chip support
usb: otg: mv_otg: add extern chip support
arm: mmp: add extern chip support for brownstone
arm: mmp: add extern chip support for ttc_dkb
usb: gadget: mv_udc: add device tree support
usb: otg: mv_otg: add device tree support
usb: ehci: ehci-mv: add device tree support

 arch/arm/mach-mmp/brownstone.c            |   45 +++
 arch/arm/mach-mmp/devices.c               |  278 ----------------
 arch/arm/mach-mmp/include/mach/mmp2.h     |    4 +
 arch/arm/mach-mmp/include/mach/pxa910.h   |    7 +-
 arch/arm/mach-mmp/include/mach/regs-usb.h |  253 --------------
 arch/arm/mach-mmp/mmp2.c                  |    4 +
 arch/arm/mach-mmp/pxa168.c                |   42 ---
 arch/arm/mach-mmp/pxa910.c                |    4 +
 arch/arm/mach-mmp/ttc_dkb.c               |   32 +-
 drivers/usb/gadget/mv_udc.h               |   10 +-
 drivers/usb/gadget/mv_udc_core.c          |  385 +++++++++++-----------
 drivers/usb/host/ehci-mv.c                |  158 ++++++----
 drivers/usb/otg/mv_otg.c                  |  283 +++++++++--------
 drivers/usb/otg/mv_otg.h                  |   11 +-
 drivers/usb/phy/Kconfig                   |    7 +
 drivers/usb/phy/Makefile                  |    1 +
 drivers/usb/phy/mv_usb2_phy.c             |  508 +++++++++++++++++++++++++++++
 include/linux/platform_data/mv_usb.h      |   22 +-
 include/linux/usb/mv_usb2.h               |   97 ++++++
 19 files changed, 1171 insertions(+), 980 deletions(-)
 delete mode 100644 arch/arm/mach-mmp/include/mach/regs-usb.h
 create mode 100644 drivers/usb/phy/mv_usb2_phy.c
 create mode 100644 include/linux/usb/mv_usb2.h
Signature · 1 line
1.7.4.1
author
#2 lore raw

PATCH v4 1/26 usb: gadget: mv_udc: use udc_start and udc_stop functions

This patches converts the driver into the new style start/stop interface. As a result the driver no longer uses the static global the_conroller variable.

---
 drivers/usb/gadget/mv_udc_core.c |   79 +++++++++++++++++---------------------
 1 files changed, 35 insertions(+), 44 deletions(-)
drivers/usb/gadget/mv_udc_core.c +35 -44
index 6e8b127..32a9972 100644
@@ -61,9 +61,6 @@ static DECLARE_COMPLETION(release_done);
 static const char driver_name[] = "mv_udc";
 static const char driver_desc[] = DRIVER_DESC;
 
-/* controller device global variable */
-static struct mv_udc	*the_controller;
-
 static void nuke(struct mv_ep *ep, int status);
 static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver);
 
@@ -1268,9 +1265,8 @@ static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
 	return retval;
 }
 
-static int mv_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int mv_udc_stop(struct usb_gadget_driver *driver);
+static int mv_udc_start(struct usb_gadget *, struct usb_gadget_driver *);
+static int mv_udc_stop(struct usb_gadget *, struct usb_gadget_driver *);
 /* device controller usb_gadget_ops structure */
 static const struct usb_gadget_ops mv_ops = {
 
@@ -1285,8 +1281,8 @@ static const struct usb_gadget_ops mv_ops = {
 
 	/* D+ pullup, software-controlled connect/disconnect to USB host */
 	.pullup		= mv_udc_pullup,
-	.start		= mv_udc_start,
-	.stop		= mv_udc_stop,
+	.udc_start	= mv_udc_start,
+	.udc_stop	= mv_udc_stop,
 };
 
 static int eps_init(struct mv_udc *udc)
@@ -1373,15 +1369,14 @@ static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
 	}
 }
 
-static int mv_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int mv_udc_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	int retval = 0;
 	unsigned long flags;
 
-	if (!udc)
-		return -ENODEV;
+	udc = container_of(gadget, struct mv_udc, gadget);
 
 	if (udc->driver)
 		return -EBUSY;
@@ -1399,26 +1394,14 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
 
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	retval = bind(&udc->gadget, driver);
-	if (retval) {
-		dev_err(&udc->dev->dev, "bind to driver %s --> %d\n",
-				driver->driver.name, retval);
-		udc->driver = NULL;
-		udc->gadget.dev.driver = NULL;
-		return retval;
-	}
-
 	if (!IS_ERR_OR_NULL(udc->transceiver)) {
 		retval = otg_set_peripheral(udc->transceiver->otg,
 					&udc->gadget);
 		if (retval) {
 			dev_err(&udc->dev->dev,
 				"unable to register peripheral to otg\n");
-			if (driver->unbind) {
-				driver->unbind(&udc->gadget);
-				udc->gadget.dev.driver = NULL;
-				udc->driver = NULL;
-			}
+			udc->driver = NULL;
+			udc->gadget.dev.driver = NULL;
 			return retval;
 		}
 	}
@@ -1433,13 +1416,13 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
 	return 0;
 }
 
-static int mv_udc_stop(struct usb_gadget_driver *driver)
+static int mv_udc_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	unsigned long flags;
 
-	if (!udc)
-		return -ENODEV;
+	udc = container_of(gadget, struct mv_udc, gadget);
 
 	spin_lock_irqsave(&udc->lock, flags);
 
@@ -1454,7 +1437,6 @@ static int mv_udc_stop(struct usb_gadget_driver *driver)
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 	/* unbind gadget driver */
-	driver->unbind(&udc->gadget);
 	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
@@ -1472,10 +1454,13 @@ static void mv_set_ptc(struct mv_udc *udc, u32 mode)
 
 static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req)
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_ep *mvep = container_of(ep, struct mv_ep, ep);
 	struct mv_req *req = container_of(_req, struct mv_req, req);
+	struct mv_udc *udc;
 	unsigned long flags;
 
+	udc = mvep->udc;
+
 	dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode);
 
 	spin_lock_irqsave(&udc->lock, flags);
@@ -2123,16 +2108,20 @@ static void mv_udc_vbus_work(struct work_struct *work)
 /* release device structure */
 static void gadget_release(struct device *_dev)
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
+
+	udc = dev_get_drvdata(_dev);
 
 	complete(udc->done);
 }
 
 static int mv_udc_remove(struct platform_device *dev)
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	int clk_i;
 
+	udc = platform_get_drvdata(dev);
+
 	usb_del_gadget_udc(&udc->gadget);
 
 	if (udc->qwork) {
@@ -2183,8 +2172,6 @@ static int mv_udc_remove(struct platform_device *dev)
 	wait_for_completion(udc->done);
 	kfree(udc);
 
-	the_controller = NULL;
-
 	return 0;
 }
 
@@ -2209,7 +2196,6 @@ static int mv_udc_probe(struct platform_device *dev)
 		return -ENOMEM;
 	}
 
-	the_controller = udc;
 	udc->done = &release_done;
 	udc->pdata = dev->dev.platform_data;
 	spin_lock_init(&udc->lock);
@@ -2400,6 +2386,7 @@ static int mv_udc_probe(struct platform_device *dev)
 	if (retval)
 		goto err_unregister;
 
+	platform_set_drvdata(dev, udc);
 	dev_info(&dev->dev, "successful probe UDC device %s clock gating.\n",
 		udc->clock_gating ? "with" : "without");
 
@@ -2431,15 +2418,16 @@ err_iounmap_capreg:
 err_put_clk:
 	for (clk_i--; clk_i >= 0; clk_i--)
 		clk_put(udc->clk[clk_i]);
-	the_controller = NULL;
 	kfree(udc);
 	return retval;
 }
 
 #ifdef CONFIG_PM
-static int mv_udc_suspend(struct device *_dev)
+static int mv_udc_suspend(struct device *dev)
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
+
+	udc = dev_get_drvdata(dev);
 
 	/* if OTG is enabled, the following will be done in OTG driver*/
 	if (!IS_ERR_OR_NULL(udc->transceiver))
@@ -2469,11 +2457,13 @@ static int mv_udc_suspend(struct device *_dev)
 	return 0;
 }
 
-static int mv_udc_resume(struct device *_dev)
+static int mv_udc_resume(struct device *dev)
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	int retval;
 
+	udc = dev_get_drvdata(dev);
+
 	/* if OTG is enabled, the following will be done in OTG driver*/
 	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return 0;
@@ -2501,9 +2491,10 @@ static const struct dev_pm_ops mv_udc_pm_ops = {
 
 static void mv_udc_shutdown(struct platform_device *dev)
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	u32 mode;
 
+	udc = platform_get_drvdata(dev);
 	/* reset controller mode to IDLE */
 	mv_udc_enable(udc);
 	mode = readl(&udc->op_regs->usbmode);
Signature · 1 line
1.7.4.1
author
#3 lore raw

PATCH v4 2/26 usb: gadget: mv_udc: use devm_xxx for probe

In reply to Chao Xie

use devm_xxx for udc driver probe. So we do need care about the resources release in driver remove or failure handling in driver probe.

---
 drivers/usb/gadget/mv_udc_core.c |  156 ++++++++++++++------------------------
 1 files changed, 56 insertions(+), 100 deletions(-)
drivers/usb/gadget/mv_udc_core.c +56 -100
index 32a9972..e2fdc8e 100644
@@ -2115,12 +2115,11 @@ static void gadget_release(struct device *_dev)
 	complete(udc->done);
 }
 
-static int mv_udc_remove(struct platform_device *dev)
+static int mv_udc_remove(struct platform_device *pdev)
 {
 	struct mv_udc *udc;
-	int clk_i;
 
-	udc = platform_get_drvdata(dev);
+	udc = platform_get_drvdata(pdev);
 
 	usb_del_gadget_udc(&udc->gadget);
 
@@ -2129,55 +2128,27 @@ static int mv_udc_remove(struct platform_device *dev)
 		destroy_workqueue(udc->qwork);
 	}
 
-	/*
-	 * If we have transceiver inited,
-	 * then vbus irq will not be requested in udc driver.
-	 */
-	if (udc->pdata && udc->pdata->vbus
-		&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
-		free_irq(udc->pdata->vbus->irq, &dev->dev);
-
 	/* free memory allocated in probe */
 	if (udc->dtd_pool)
 		dma_pool_destroy(udc->dtd_pool);
 
 	if (udc->ep_dqh)
-		dma_free_coherent(&dev->dev, udc->ep_dqh_size,
+		dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
 			udc->ep_dqh, udc->ep_dqh_dma);
 
-	kfree(udc->eps);
-
-	if (udc->irq)
-		free_irq(udc->irq, &dev->dev);
-
 	mv_udc_disable(udc);
 
-	if (udc->cap_regs)
-		iounmap(udc->cap_regs);
-
-	if (udc->phy_regs)
-		iounmap(udc->phy_regs);
-
-	if (udc->status_req) {
-		kfree(udc->status_req->req.buf);
-		kfree(udc->status_req);
-	}
-
-	for (clk_i = 0; clk_i <= udc->clknum; clk_i++)
-		clk_put(udc->clk[clk_i]);
-
 	device_unregister(&udc->gadget.dev);
 
 	/* free dev, wait for the release() finished */
 	wait_for_completion(udc->done);
-	kfree(udc);
 
 	return 0;
 }
 
-static int mv_udc_probe(struct platform_device *dev)
+static int mv_udc_probe(struct platform_device *pdev)
 {
-	struct mv_usb_platform_data *pdata = dev->dev.platform_data;
+	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct mv_udc *udc;
 	int retval = 0;
 	int clk_i = 0;
@@ -2185,70 +2156,68 @@ static int mv_udc_probe(struct platform_device *dev)
 	size_t size;
 
 	if (pdata == NULL) {
-		dev_err(&dev->dev, "missing platform_data\n");
+		dev_err(&pdev->dev, "missing platform_data\n");
 		return -ENODEV;
 	}
 
 	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
-	udc = kzalloc(size, GFP_KERNEL);
+	udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (udc == NULL) {
-		dev_err(&dev->dev, "failed to allocate memory for udc\n");
+		dev_err(&pdev->dev, "failed to allocate memory for udc\n");
 		return -ENOMEM;
 	}
 
 	udc->done = &release_done;
-	udc->pdata = dev->dev.platform_data;
+	udc->pdata = pdev->dev.platform_data;
 	spin_lock_init(&udc->lock);
 
-	udc->dev = dev;
+	udc->dev = pdev;
 
 #ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->mode == MV_USB_MODE_OTG)
-		udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+		udc->transceiver = devm_usb_get_phy(&pdev->dev,
+					USB_PHY_TYPE_USB2);
 #endif
 
 	udc->clknum = pdata->clknum;
 	for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
-		udc->clk[clk_i] = clk_get(&dev->dev, pdata->clkname[clk_i]);
+		udc->clk[clk_i] = devm_clk_get(&pdev->dev,
+					pdata->clkname[clk_i]);
 		if (IS_ERR(udc->clk[clk_i])) {
 			retval = PTR_ERR(udc->clk[clk_i]);
-			goto err_put_clk;
+			return retval;
 		}
 	}
 
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 	if (r == NULL) {
-		dev_err(&dev->dev, "no I/O memory resource defined\n");
-		retval = -ENODEV;
-		goto err_put_clk;
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		return -ENODEV;
 	}
 
 	udc->cap_regs = (struct mv_cap_regs __iomem *)
-		ioremap(r->start, resource_size(r));
+		devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	if (udc->cap_regs == NULL) {
-		dev_err(&dev->dev, "failed to map I/O memory\n");
-		retval = -EBUSY;
-		goto err_put_clk;
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		return -EBUSY;
 	}
 
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs");
 	if (r == NULL) {
-		dev_err(&dev->dev, "no phy I/O memory resource defined\n");
-		retval = -ENODEV;
-		goto err_iounmap_capreg;
+		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
+		return -ENODEV;
 	}
 
 	udc->phy_regs = ioremap(r->start, resource_size(r));
 	if (udc->phy_regs == NULL) {
-		dev_err(&dev->dev, "failed to map phy I/O memory\n");
-		retval = -EBUSY;
-		goto err_iounmap_capreg;
+		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
+		return -EBUSY;
 	}
 
 	/* we will acces controller register, so enable the clk */
 	retval = mv_udc_enable_internal(udc);
 	if (retval)
-		goto err_iounmap_phyreg;
+		return retval;
 
 	udc->op_regs =
 		(struct mv_op_regs __iomem *)((unsigned long)udc->cap_regs
@@ -2265,11 +2234,11 @@ static int mv_udc_probe(struct platform_device *dev)
 
 	size = udc->max_eps * sizeof(struct mv_dqh) *2;
 	size = (size + DQH_ALIGNMENT - 1) & ~(DQH_ALIGNMENT - 1);
-	udc->ep_dqh = dma_alloc_coherent(&dev->dev, size,
+	udc->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
 					&udc->ep_dqh_dma, GFP_KERNEL);
 
 	if (udc->ep_dqh == NULL) {
-		dev_err(&dev->dev, "allocate dQH memory failed\n");
+		dev_err(&pdev->dev, "allocate dQH memory failed\n");
 		retval = -ENOMEM;
 		goto err_disable_clock;
 	}
@@ -2277,7 +2246,7 @@ static int mv_udc_probe(struct platform_device *dev)
 
 	/* create dTD dma_pool resource */
 	udc->dtd_pool = dma_pool_create("mv_dtd",
-			&dev->dev,
+			&pdev->dev,
 			sizeof(struct mv_dtd),
 			DTD_ALIGNMENT,
 			DMA_BOUNDARY);
@@ -2288,19 +2257,20 @@ static int mv_udc_probe(struct platform_device *dev)
 	}
 
 	size = udc->max_eps * sizeof(struct mv_ep) *2;
-	udc->eps = kzalloc(size, GFP_KERNEL);
+	udc->eps = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (udc->eps == NULL) {
-		dev_err(&dev->dev, "allocate ep memory failed\n");
+		dev_err(&pdev->dev, "allocate ep memory failed\n");
 		retval = -ENOMEM;
 		goto err_destroy_dma;
 	}
 
 	/* initialize ep0 status request structure */
-	udc->status_req = kzalloc(sizeof(struct mv_req), GFP_KERNEL);
+	udc->status_req = devm_kzalloc(&pdev->dev, sizeof(struct mv_req),
+					GFP_KERNEL);
 	if (!udc->status_req) {
-		dev_err(&dev->dev, "allocate status_req memory failed\n");
+		dev_err(&pdev->dev, "allocate status_req memory failed\n");
 		retval = -ENOMEM;
-		goto err_free_eps;
+		goto err_destroy_dma;
 	}
 	INIT_LIST_HEAD(&udc->status_req->queue);
 
@@ -2315,17 +2285,17 @@ static int mv_udc_probe(struct platform_device *dev)
 
 	r = platform_get_resource(udc->dev, IORESOURCE_IRQ, 0);
 	if (r == NULL) {
-		dev_err(&dev->dev, "no IRQ resource defined\n");
+		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		retval = -ENODEV;
-		goto err_free_status_req;
+		goto err_destroy_dma;
 	}
 	udc->irq = r->start;
-	if (request_irq(udc->irq, mv_udc_irq,
+	if (devm_request_irq(&pdev->dev, udc->irq, mv_udc_irq,
 		IRQF_SHARED, driver_name, udc)) {
-		dev_err(&dev->dev, "Request irq %d for UDC failed\n",
+		dev_err(&pdev->dev, "Request irq %d for UDC failed\n",
 			udc->irq);
 		retval = -ENODEV;
-		goto err_free_status_req;
+		goto err_destroy_dma;
 	}
 
 	/* initialize gadget structure */
@@ -2337,14 +2307,14 @@ static int mv_udc_probe(struct platform_device *dev)
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	dev_set_name(&udc->gadget.dev, "gadget");
-	udc->gadget.dev.parent = &dev->dev;
-	udc->gadget.dev.dma_mask = dev->dev.dma_mask;
+	udc->gadget.dev.parent = &pdev->dev;
+	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
 	udc->gadget.dev.release = gadget_release;
 	udc->gadget.name = driver_name;		/* gadget name */
 
 	retval = device_register(&udc->gadget.dev);
 	if (retval)
-		goto err_free_irq;
+		goto err_destroy_dma;
 
 	eps_init(udc);
 
@@ -2353,10 +2323,11 @@ static int mv_udc_probe(struct platform_device *dev)
 		udc->clock_gating = 1;
 	else if (pdata->vbus) {
 		udc->clock_gating = 1;
-		retval = request_threaded_irq(pdata->vbus->irq, NULL,
+		retval = devm_request_threaded_irq(&pdev->dev,
+				pdata->vbus->irq, NULL,
 				mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc);
 		if (retval) {
-			dev_info(&dev->dev,
+			dev_info(&pdev->dev,
 				"Can not request irq for VBUS, "
 				"disable clock gating\n");
 			udc->clock_gating = 0;
@@ -2364,7 +2335,7 @@ static int mv_udc_probe(struct platform_device *dev)
 
 		udc->qwork = create_singlethread_workqueue("mv_udc_queue");
 		if (!udc->qwork) {
-			dev_err(&dev->dev, "cannot create workqueue\n");
+			dev_err(&pdev->dev, "cannot create workqueue\n");
 			retval = -ENOMEM;
 			goto err_unregister;
 		}
@@ -2382,43 +2353,28 @@ static int mv_udc_probe(struct platform_device *dev)
 	else
 		udc->vbus_active = 1;
 
-	retval = usb_add_gadget_udc(&dev->dev, &udc->gadget);
+	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	if (retval)
-		goto err_unregister;
+		goto err_create_workqueue;
 
-	platform_set_drvdata(dev, udc);
-	dev_info(&dev->dev, "successful probe UDC device %s clock gating.\n",
+	platform_set_drvdata(pdev, udc);
+	dev_info(&pdev->dev, "successful probe UDC device %s clock gating.\n",
 		udc->clock_gating ? "with" : "without");
 
 	return 0;
 
+err_create_workqueue:
+	destroy_workqueue(udc->qwork);
 err_unregister:
-	if (udc->pdata && udc->pdata->vbus
-		&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
-		free_irq(pdata->vbus->irq, &dev->dev);
 	device_unregister(&udc->gadget.dev);
-err_free_irq:
-	free_irq(udc->irq, &dev->dev);
-err_free_status_req:
-	kfree(udc->status_req->req.buf);
-	kfree(udc->status_req);
-err_free_eps:
-	kfree(udc->eps);
 err_destroy_dma:
 	dma_pool_destroy(udc->dtd_pool);
 err_free_dma:
-	dma_free_coherent(&dev->dev, udc->ep_dqh_size,
+	dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
 			udc->ep_dqh, udc->ep_dqh_dma);
 err_disable_clock:
 	mv_udc_disable_internal(udc);
-err_iounmap_phyreg:
-	iounmap(udc->phy_regs);
-err_iounmap_capreg:
-	iounmap(udc->cap_regs);
-err_put_clk:
-	for (clk_i--; clk_i >= 0; clk_i--)
-		clk_put(udc->clk[clk_i]);
-	kfree(udc);
+
 	return retval;
 }
 
@@ -2489,12 +2445,12 @@ static const struct dev_pm_ops mv_udc_pm_ops = {
 };
 #endif
 
-static void mv_udc_shutdown(struct platform_device *dev)
+static void mv_udc_shutdown(struct platform_device *pdev)
 {
 	struct mv_udc *udc;
 	u32 mode;
 
-	udc = platform_get_drvdata(dev);
+	udc = platform_get_drvdata(pdev);
 	/* reset controller mode to IDLE */
 	mv_udc_enable(udc);
 	mode = readl(&udc->op_regs->usbmode);
Signature · 1 line
1.7.4.1
author
#4 lore raw

PATCH v4 3/26 usb: gadget: mv_udc: fix the warning of mv_udc_remove

In reply to Chao Xie

The __exit_p() will be NULL if MODULE is no defined. It will cause the warning. Removing __exit_p to remove the warning.

---
 drivers/usb/gadget/mv_udc_core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/usb/gadget/mv_udc_core.c +1 -1
index e2fdc8e..910c4b5 100644
@@ -2461,7 +2461,7 @@ static void mv_udc_shutdown(struct platform_device *pdev)
 
 static struct platform_driver udc_driver = {
 	.probe		= mv_udc_probe,
-	.remove		= __exit_p(mv_udc_remove),
+	.remove		= mv_udc_remove,
 	.shutdown	= mv_udc_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
Signature · 1 line
1.7.4.1
author
#5 lore raw

PATCH v4 4/26 usb: otg: mv_otg: use devm_xxx for probe

In reply to Chao Xie

use devm_xxx for otg driver probe. So we do need care about the resources release in driver remove or failure handling in driver probe.

---
 drivers/usb/otg/mv_otg.c |   82 ++++++++++++---------------------------------
 1 files changed, 22 insertions(+), 60 deletions(-)
drivers/usb/otg/mv_otg.c +22 -60
index eace975..da2d60c 100644
@@ -662,18 +662,9 @@ static struct attribute_group inputs_attr_group = {
 int mv_otg_remove(struct platform_device *pdev)
 {
 	struct mv_otg *mvotg = platform_get_drvdata(pdev);
-	int clk_i;
 
 	sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
 
-	if (mvotg->irq)
-		free_irq(mvotg->irq, mvotg);
-
-	if (mvotg->pdata->vbus)
-		free_irq(mvotg->pdata->vbus->irq, mvotg);
-	if (mvotg->pdata->id)
-		free_irq(mvotg->pdata->id->irq, mvotg);
-
 	if (mvotg->qwork) {
 		flush_workqueue(mvotg->qwork);
 		destroy_workqueue(mvotg->qwork);
@@ -681,21 +672,9 @@ int mv_otg_remove(struct platform_device *pdev)
 
 	mv_otg_disable(mvotg);
 
-	if (mvotg->cap_regs)
-		iounmap(mvotg->cap_regs);
-
-	if (mvotg->phy_regs)
-		iounmap(mvotg->phy_regs);
-
-	for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
-		clk_put(mvotg->clk[clk_i]);
-
 	usb_remove_phy(&mvotg->phy);
 	platform_set_drvdata(pdev, NULL);
 
-	kfree(mvotg->phy.otg);
-	kfree(mvotg);
-
 	return 0;
 }
 
@@ -714,17 +693,15 @@ static int mv_otg_probe(struct platform_device *pdev)
 	}
 
 	size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
-	mvotg = kzalloc(size, GFP_KERNEL);
+	mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (!mvotg) {
 		dev_err(&pdev->dev, "failed to allocate memory!\n");
 		return -ENOMEM;
 	}
 
-	otg = kzalloc(sizeof *otg, GFP_KERNEL);
-	if (!otg) {
-		kfree(mvotg);
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg)
 		return -ENOMEM;
-	}
 
 	platform_set_drvdata(pdev, mvotg);
 
@@ -733,18 +710,18 @@ static int mv_otg_probe(struct platform_device *pdev)
 
 	mvotg->clknum = pdata->clknum;
 	for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
-		mvotg->clk[clk_i] = clk_get(&pdev->dev, pdata->clkname[clk_i]);
+		mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
+						pdata->clkname[clk_i]);
 		if (IS_ERR(mvotg->clk[clk_i])) {
 			retval = PTR_ERR(mvotg->clk[clk_i]);
-			goto err_put_clk;
+			return retval;
 		}
 	}
 
 	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
 	if (!mvotg->qwork) {
 		dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
-		retval = -ENOMEM;
-		goto err_put_clk;
+		return -ENOMEM;
 	}
 
 	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
@@ -772,7 +749,7 @@ static int mv_otg_probe(struct platform_device *pdev)
 		goto err_destroy_workqueue;
 	}
 
-	mvotg->phy_regs = ioremap(r->start, resource_size(r));
+	mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	if (mvotg->phy_regs == NULL) {
 		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
 		retval = -EFAULT;
@@ -784,21 +761,21 @@ static int mv_otg_probe(struct platform_device *pdev)
 	if (r == NULL) {
 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
 		retval = -ENODEV;
-		goto err_unmap_phyreg;
+		goto err_destroy_workqueue;
 	}
 
-	mvotg->cap_regs = ioremap(r->start, resource_size(r));
+	mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	if (mvotg->cap_regs == NULL) {
 		dev_err(&pdev->dev, "failed to map I/O memory\n");
 		retval = -EFAULT;
-		goto err_unmap_phyreg;
+		goto err_destroy_workqueue;
 	}
 
 	/* we will acces controller register, so enable the udc controller */
 	retval = mv_otg_enable_internal(mvotg);
 	if (retval) {
 		dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
-		goto err_unmap_capreg;
+		goto err_destroy_workqueue;
 	}
 
 	mvotg->op_regs =
@@ -806,9 +783,9 @@ static int mv_otg_probe(struct platform_device *pdev)
 			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
 
 	if (pdata->id) {
-		retval = request_threaded_irq(pdata->id->irq, NULL,
-					      mv_otg_inputs_irq,
-					      IRQF_ONESHOT, "id", mvotg);
+		retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
+						NULL, mv_otg_inputs_irq,
+						IRQF_ONESHOT, "id", mvotg);
 		if (retval) {
 			dev_info(&pdev->dev,
 				 "Failed to request irq for ID\n");
@@ -818,9 +795,9 @@ static int mv_otg_probe(struct platform_device *pdev)
 
 	if (pdata->vbus) {
 		mvotg->clock_gating = 1;
-		retval = request_threaded_irq(pdata->vbus->irq, NULL,
-					      mv_otg_inputs_irq,
-					      IRQF_ONESHOT, "vbus", mvotg);
+		retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
+						NULL, mv_otg_inputs_irq,
+						IRQF_ONESHOT, "vbus", mvotg);
 		if (retval) {
 			dev_info(&pdev->dev,
 				 "Failed to request irq for VBUS, "
@@ -844,7 +821,7 @@ static int mv_otg_probe(struct platform_device *pdev)
 	}
 
 	mvotg->irq = r->start;
-	if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED,
+	if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
 			driver_name, mvotg)) {
 		dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
 			mvotg->irq);
@@ -857,14 +834,14 @@ static int mv_otg_probe(struct platform_device *pdev)
 	if (retval < 0) {
 		dev_err(&pdev->dev, "can't register transceiver, %d\n",
 			retval);
-		goto err_free_irq;
+		goto err_disable_clk;
 	}
 
 	retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
 	if (retval < 0) {
 		dev_dbg(&pdev->dev,
 			"Can't register sysfs attr group: %d\n", retval);
-		goto err_set_transceiver;
+		goto err_remove_phy;
 	}
 
 	spin_lock_init(&mvotg->wq_lock);
@@ -879,30 +856,15 @@ static int mv_otg_probe(struct platform_device *pdev)
 
 	return 0;
 
-err_set_transceiver:
+err_remove_phy:
 	usb_remove_phy(&mvotg->phy);
-err_free_irq:
-	free_irq(mvotg->irq, mvotg);
 err_disable_clk:
-	if (pdata->vbus)
-		free_irq(pdata->vbus->irq, mvotg);
-	if (pdata->id)
-		free_irq(pdata->id->irq, mvotg);
 	mv_otg_disable_internal(mvotg);
-err_unmap_capreg:
-	iounmap(mvotg->cap_regs);
-err_unmap_phyreg:
-	iounmap(mvotg->phy_regs);
 err_destroy_workqueue:
 	flush_workqueue(mvotg->qwork);
 	destroy_workqueue(mvotg->qwork);
-err_put_clk:
-	for (clk_i--; clk_i >= 0; clk_i--)
-		clk_put(mvotg->clk[clk_i]);
 
 	platform_set_drvdata(pdev, NULL);
-	kfree(otg);
-	kfree(mvotg);
 
 	return retval;
 }
Signature · 1 line
1.7.4.1
author
#6 lore raw

PATCH v4 5/26 usb: host: ehci-mv: remove unused variable

In reply to Chao Xie
---
 drivers/usb/host/ehci-mv.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/usb/host/ehci-mv.c +0 -1
index 6c56297..3065809 100644
@@ -302,7 +302,6 @@ static int mv_ehci_remove(struct platform_device *pdev)
 {
 	struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
 	struct usb_hcd *hcd = ehci_mv->hcd;
-	int clk_i;
 
 	if (hcd->rh_registered)
 		usb_remove_hcd(hcd);
Signature · 1 line
1.7.4.1
author
#7 lore raw

PATCH v4 6/26 usb: gadget: mv_udc: fix the value of tranceiver

In reply to Chao Xie

usally we will use udc->tranceiver == NULL or udc->tranceiver != NULL.
So when failed to get the udc->tranceiver by usb_get_phy(), we directly set udc->tranceiver to be NULL.
Then the source code will not need macro IS_ERR_OR_NULL() for udc->tranceiver judgement. It can reduce the line size and make the judgement simple.

---
 drivers/usb/gadget/mv_udc_core.c |   15 ++++++++++-----
 1 files changed, 10 insertions(+), 5 deletions(-)
drivers/usb/gadget/mv_udc_core.c +10 -5
index 910c4b5..c8cf959 100644
@@ -1394,7 +1394,7 @@ static int mv_udc_start(struct usb_gadget *gadget,
 
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	if (!IS_ERR_OR_NULL(udc->transceiver)) {
+	if (udc->transceiver) {
 		retval = otg_set_peripheral(udc->transceiver->otg,
 					&udc->gadget);
 		if (retval) {
@@ -2174,9 +2174,14 @@ static int mv_udc_probe(struct platform_device *pdev)
 	udc->dev = pdev;
 
 #ifdef CONFIG_USB_OTG_UTILS
-	if (pdata->mode == MV_USB_MODE_OTG)
+	if (pdata->mode == MV_USB_MODE_OTG) {
 		udc->transceiver = devm_usb_get_phy(&pdev->dev,
 					USB_PHY_TYPE_USB2);
+		if (IS_ERR_OR_NULL(udc->transceiver)) {
+			udc->transceiver = NULL;
+			return -ENODEV;
+		}
+	}
 #endif
 
 	udc->clknum = pdata->clknum;
@@ -2319,7 +2324,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 	eps_init(udc);
 
 	/* VBUS detect: we can disable/enable clock on demand.*/
-	if (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		udc->clock_gating = 1;
 	else if (pdata->vbus) {
 		udc->clock_gating = 1;
@@ -2386,7 +2391,7 @@ static int mv_udc_suspend(struct device *dev)
 	udc = dev_get_drvdata(dev);
 
 	/* if OTG is enabled, the following will be done in OTG driver*/
-	if (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		return 0;
 
 	if (udc->pdata->vbus && udc->pdata->vbus->poll)
@@ -2421,7 +2426,7 @@ static int mv_udc_resume(struct device *dev)
 	udc = dev_get_drvdata(dev);
 
 	/* if OTG is enabled, the following will be done in OTG driver*/
-	if (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		return 0;
 
 	if (!udc->clock_gating) {
Signature · 1 line
1.7.4.1
author
#8 lore raw

PATCH v4 7/26 usb: gadget: mv_udc: make mv_udc depends on ARCH_MMP or ARCH_PXA

In reply to Chao Xie

Only ARCH_PXA and ARCH_MMP will use mv_udc.

---
 drivers/usb/gadget/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/usb/gadget/Kconfig +1 -0
index 14625fd..53943f7 100644
@@ -319,6 +319,7 @@ config USB_S3C_HSUDC
 
 config USB_MV_UDC
 	tristate "Marvell USB2.0 Device Controller"
+	depends on ARCH_PXA || ARCH_MMP
 	help
 	  Marvell Socs (including PXA and MMP series) include a high speed
 	  USB2.0 OTG controller, which can be configured as high speed or
Signature · 1 line
1.7.4.1
author
#9 lore raw

PATCH v4 8/26 usb: phy: mv_usb2: add PHY driver for marvell usb2 controller

In reply to Chao Xie

The PHY is seperated from usb controller.
The usb controller used in marvell pxa168/pxa910/mmp2 are same, but PHY initialization may be different.
the usb controller can support udc/otg/ehci, and for each of the mode, it need PHY to initialized before use the controller. Direclty writing the phy driver will make the usb controller driver to be simple and portable.
The PHY driver will be used by marvell udc/otg/ehci.

---
 drivers/usb/phy/Kconfig              |    7 +
 drivers/usb/phy/Makefile             |    1 +
 drivers/usb/phy/mv_usb2_phy.c        |  454 ++++++++++++++++++++++++++++++++++
 include/linux/platform_data/mv_usb.h |    9 +-
 include/linux/usb/mv_usb2.h          |   43 ++++
 5 files changed, 511 insertions(+), 3 deletions(-)
 create mode 100644 drivers/usb/phy/mv_usb2_phy.c
 create mode 100644 include/linux/usb/mv_usb2.h
drivers/usb/phy/Kconfig +7 -0
index 5de6e7f..7bfce04 100644
@@ -45,3 +45,10 @@ config USB_RCAR_PHY
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called rcar-phy.
+
+config MV_USB2_PHY
+	tristate "Marvell USB 2.0 PHY Driver"
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  Enable this to support Marvell USB 2.0 phy driver for Marvell
+	  SoC.
drivers/usb/phy/Makefile +1 -0
index 1a579a8..e33e09c 100644
@@ -9,3 +9,4 @@ obj-$(CONFIG_USB_ISP1301)		+= isp1301.o
 obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o
 obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
 obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o
+obj-$(CONFIG_MV_USB2_PHY)		+= mv_usb2_phy.o
drivers/usb/phy/mv_usb2_phy.c new file +454 -0

454 lines not on this page · raw message

include/linux/platform_data/mv_usb.h +6 -3
index 944b01d..fd3d1b4 100644
@@ -47,9 +47,12 @@ struct mv_usb_platform_data {
 	/* Force a_bus_req to be asserted */
 	 unsigned int    otg_force_a_bus_req:1;
 
-	int	(*phy_init)(void __iomem *regbase);
-	void	(*phy_deinit)(void __iomem *regbase);
 	int	(*set_vbus)(unsigned int vbus);
-	int     (*private_init)(void __iomem *opregs, void __iomem *phyregs);
 };
+
+struct mv_usb_phy_platform_data {
+	unsigned int	clknum;
+	char		**clkname;
+};
+
 #endif
include/linux/usb/mv_usb2.h new file +43 -0

43 lines not on this page · raw message

Signature · 1 line
1.7.4.1
author
#10 lore raw

PATCH v4 9/26 usb: gadget: mv_udc: use PHY driver for udc

In reply to Chao Xie

Originaly, udc driver will call the callbacks in platform data for PHY initialization and shut down.
With PHY driver, it will call the APIs provided by PHY driver for PHY initialization and shut down. It removes the callbacks in platform data, and at same time it removes one block in the way of enabling device tree for udc driver.

---
 drivers/usb/gadget/mv_udc.h      |    2 +-
 drivers/usb/gadget/mv_udc_core.c |   23 ++++++++---------------
 2 files changed, 9 insertions(+), 16 deletions(-)
drivers/usb/gadget/mv_udc.h +1 -1
index 9073436..4851b2b 100644
@@ -180,7 +180,6 @@ struct mv_udc {
 
 	struct mv_cap_regs __iomem	*cap_regs;
 	struct mv_op_regs __iomem	*op_regs;
-	void __iomem                    *phy_regs;
 	unsigned int			max_eps;
 	struct mv_dqh			*ep_dqh;
 	size_t				ep_dqh_size;
@@ -217,6 +216,7 @@ struct mv_udc {
 	struct work_struct	vbus_work;
 	struct workqueue_struct *qwork;
 
+	struct mv_usb2_phy	*phy;
 	struct usb_phy		*transceiver;
 
 	struct mv_usb_platform_data     *pdata;
drivers/usb/gadget/mv_udc_core.c +8 -15
index c8cf959..76fcfc7 100644
@@ -35,6 +35,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/platform_data/mv_usb.h>
+#include <linux/usb/mv_usb2.h>
 #include <asm/unaligned.h>
 
 #include "mv_udc.h"
@@ -1121,8 +1122,8 @@ static int mv_udc_enable_internal(struct mv_udc *udc)
 
 	dev_dbg(&udc->dev->dev, "enable udc\n");
 	udc_clock_enable(udc);
-	if (udc->pdata->phy_init) {
-		retval = udc->pdata->phy_init(udc->phy_regs);
+	if (udc->phy->init) {
+		retval = udc->phy->init(udc->phy);
 		if (retval) {
 			dev_err(&udc->dev->dev,
 				"init phy error %d\n", retval);
@@ -1147,8 +1148,8 @@ static void mv_udc_disable_internal(struct mv_udc *udc)
 {
 	if (udc->active) {
 		dev_dbg(&udc->dev->dev, "disable udc\n");
-		if (udc->pdata->phy_deinit)
-			udc->pdata->phy_deinit(udc->phy_regs);
+		if (udc->phy->shutdown)
+			udc->phy->shutdown(udc->phy);
 		udc_clock_disable(udc);
 		udc->active = 0;
 	}
@@ -2194,7 +2195,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 		}
 	}
 
-	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
+	r = platform_get_resource(udc->dev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
 		return -ENODEV;
@@ -2207,17 +2208,9 @@ static int mv_udc_probe(struct platform_device *pdev)
 		return -EBUSY;
 	}
 
-	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs");
-	if (r == NULL) {
-		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
+	udc->phy = mv_usb2_get_phy();
+	if (udc->phy == NULL)
 		return -ENODEV;
-	}
-
-	udc->phy_regs = ioremap(r->start, resource_size(r));
-	if (udc->phy_regs == NULL) {
-		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
-		return -EBUSY;
-	}
 
 	/* we will acces controller register, so enable the clk */
 	retval = mv_udc_enable_internal(udc);
Signature · 1 line
1.7.4.1
author
#11 lore raw

PATCH v4 10/26 usb: ehci: ehci-mv: use PHY driver for ehci

In reply to Chao Xie

Originaly, ehci driver will call the callbacks in platform data for PHY initialization and shut down.
With PHY driver, it will call the APIs provided by PHY driver for PHY initialization and shut down. It removes the callbacks in platform data, and at same time it removes one block in the way of enabling device tree for ehci driver.

---
 drivers/usb/host/ehci-mv.c |   37 +++++++++++++------------------------
 1 files changed, 13 insertions(+), 24 deletions(-)
drivers/usb/host/ehci-mv.c +13 -24
index 3065809..be504fd 100644
@@ -15,17 +15,18 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/mv_usb2.h>
 #include <linux/platform_data/mv_usb.h>
 
 #define CAPLENGTH_MASK         (0xff)
 
 struct ehci_hcd_mv {
 	struct usb_hcd *hcd;
+	struct mv_usb2_phy *mvphy;
 
 	/* Which mode does this ehci running OTG/Host ? */
 	int mode;
 
-	void __iomem *phy_regs;
 	void __iomem *cap_regs;
 	void __iomem *op_regs;
 
@@ -59,8 +60,8 @@ static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
 	int retval;
 
 	ehci_clock_enable(ehci_mv);
-	if (ehci_mv->pdata->phy_init) {
-		retval = ehci_mv->pdata->phy_init(ehci_mv->phy_regs);
+	if (ehci_mv->mvphy->init) {
+		retval = ehci_mv->mvphy->init(ehci_mv->mvphy);
 		if (retval)
 			return retval;
 	}
@@ -70,8 +71,8 @@ static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
 
 static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv)
 {
-	if (ehci_mv->pdata->phy_deinit)
-		ehci_mv->pdata->phy_deinit(ehci_mv->phy_regs);
+	if (ehci_mv->mvphy->shutdown)
+		ehci_mv->mvphy->shutdown(ehci_mv->mvphy);
 	ehci_clock_disable(ehci_mv);
 }
 
@@ -184,22 +185,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
 		}
 	}
 
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
-	if (r == NULL) {
-		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
-		retval = -ENODEV;
-		goto err_clear_drvdata;
-	}
-
-	ehci_mv->phy_regs = devm_ioremap(&pdev->dev, r->start,
-					 resource_size(r));
-	if (ehci_mv->phy_regs == 0) {
-		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
-		retval = -EFAULT;
-		goto err_clear_drvdata;
-	}
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs");
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
 		retval = -ENODEV;
@@ -214,6 +200,12 @@ static int mv_ehci_probe(struct platform_device *pdev)
 		goto err_clear_drvdata;
 	}
 
+	ehci_mv->mvphy = mv_usb2_get_phy();
+	if (ehci_mv->mvphy == NULL) {
+		retval = -ENODEV;
+		goto err_clear_drvdata;
+	}
+
 	retval = mv_ehci_enable(ehci_mv);
 	if (retval) {
 		dev_err(&pdev->dev, "init phy error %d\n", retval);
@@ -275,9 +267,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (pdata->private_init)
-		pdata->private_init(ehci_mv->op_regs, ehci_mv->phy_regs);
-
 	dev_info(&pdev->dev,
 		 "successful find EHCI device with regs 0x%p irq %d"
 		 " working in %s mode\n", hcd->regs, hcd->irq,
Signature · 1 line
1.7.4.1
author
#12 lore raw

PATCH v4 11/26 usb: otg: mv_otg: use PHY driver for otg

In reply to Chao Xie

Originaly, otg driver will call the callbacks in platform data for PHY initialization and shut down.
With PHY driver, it will call the APIs provided by PHY driver for PHY initialization and shut down. It removes the callbacks in platform data, and at same time it removes one block in the way of enabling device tree for otg driver.

---
 drivers/usb/otg/mv_otg.c |   33 ++++++++++++---------------------
 drivers/usb/otg/mv_otg.h |    2 +-
 2 files changed, 13 insertions(+), 22 deletions(-)
drivers/usb/otg/mv_otg.c +12 -21
index da2d60c..cc45ef2 100644
@@ -25,6 +25,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/hcd.h>
+#include <linux/usb/mv_usb2.h>
 #include <linux/platform_data/mv_usb.h>
 
 #include "mv_otg.h"
@@ -261,8 +262,8 @@ static int mv_otg_enable_internal(struct mv_otg *mvotg)
 	dev_dbg(&mvotg->pdev->dev, "otg enabled\n");
 
 	otg_clock_enable(mvotg);
-	if (mvotg->pdata->phy_init) {
-		retval = mvotg->pdata->phy_init(mvotg->phy_regs);
+	if (mvotg->mvphy->init) {
+		retval = mvotg->mvphy->init(mvotg->mvphy);
 		if (retval) {
 			dev_err(&mvotg->pdev->dev,
 				"init phy error %d\n", retval);
@@ -288,8 +289,8 @@ static void mv_otg_disable_internal(struct mv_otg *mvotg)
 {
 	if (mvotg->active) {
 		dev_dbg(&mvotg->pdev->dev, "otg disabled\n");
-		if (mvotg->pdata->phy_deinit)
-			mvotg->pdata->phy_deinit(mvotg->phy_regs);
+		if (mvotg->mvphy->shutdown)
+			mvotg->mvphy->shutdown(mvotg->mvphy);
 		otg_clock_disable(mvotg);
 		mvotg->active = 0;
 	}
@@ -741,23 +742,8 @@ static int mv_otg_probe(struct platform_device *pdev)
 	for (i = 0; i < OTG_TIMER_NUM; i++)
 		init_timer(&mvotg->otg_ctrl.timer[i]);
 
-	r = platform_get_resource_byname(mvotg->pdev,
-					 IORESOURCE_MEM, "phyregs");
-	if (r == NULL) {
-		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
-		retval = -ENODEV;
-		goto err_destroy_workqueue;
-	}
-
-	mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
-	if (mvotg->phy_regs == NULL) {
-		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
-		retval = -EFAULT;
-		goto err_destroy_workqueue;
-	}
-
-	r = platform_get_resource_byname(mvotg->pdev,
-					 IORESOURCE_MEM, "capregs");
+	r = platform_get_resource(mvotg->pdev,
+					 IORESOURCE_MEM, 0);
 	if (r == NULL) {
 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
 		retval = -ENODEV;
@@ -770,6 +756,11 @@ static int mv_otg_probe(struct platform_device *pdev)
 		retval = -EFAULT;
 		goto err_destroy_workqueue;
 	}
+	mvotg->mvphy = mv_usb2_get_phy();
+	if (mvotg->mvphy == NULL) {
+		retval = -ENODEV;
+		goto err_destroy_workqueue;
+	}
 
 	/* we will acces controller register, so enable the udc controller */
 	retval = mv_otg_enable_internal(mvotg);
drivers/usb/otg/mv_otg.h +1 -1
index 8a9e351..7b9629a 100644
@@ -137,10 +137,10 @@ struct mv_otg_regs {
 
 struct mv_otg {
 	struct usb_phy phy;
+	struct mv_usb2_phy *mvphy;
 	struct mv_otg_ctrl otg_ctrl;
 
 	/* base address */
-	void __iomem *phy_regs;
 	void __iomem *cap_regs;
 	struct mv_otg_regs __iomem *op_regs;
 
Signature · 1 line
1.7.4.1
author
#13 lore raw

PATCH v4 12/26 arm: mmp2: change the defintion of usb devices

In reply to Chao Xie

add the udc/otg/ehci devices for mmp2

---
 arch/arm/mach-mmp/include/mach/mmp2.h |    4 ++++
 arch/arm/mach-mmp/mmp2.c              |    4 ++++
 2 files changed, 8 insertions(+), 0 deletions(-)
arch/arm/mach-mmp/include/mach/mmp2.h +4 -0
index c4ca4d1..58e96b0 100644
@@ -31,6 +31,10 @@ extern struct pxa_device_desc mmp2_device_sdh2;
 extern struct pxa_device_desc mmp2_device_sdh3;
 extern struct pxa_device_desc mmp2_device_asram;
 extern struct pxa_device_desc mmp2_device_isram;
+extern struct pxa_device_desc mmp2_device_u2o;
+extern struct pxa_device_desc mmp2_device_u2ootg;
+extern struct pxa_device_desc mmp2_device_u2oehci;
+extern struct pxa_device_desc mmp2_device_u2ophy;
 
 extern struct platform_device mmp2_device_gpio;
 
arch/arm/mach-mmp/mmp2.c +4 -0
index 3a3768c..73edbfc 100644
@@ -153,6 +153,10 @@ MMP2_DEVICE(sdh3, "sdhci-pxav3", 3, MMC4, 0xd4281800, 0x120);
 MMP2_DEVICE(asram, "asram", -1, NONE, 0xe0000000, 0x4000);
 /* 0xd1000000 ~ 0xd101ffff is reserved for secure processor */
 MMP2_DEVICE(isram, "isram", -1, NONE, 0xd1020000, 0x18000);
+MMP2_DEVICE(u2ophy, "mmp2-usb-phy", -1, NONE, 0xd4207000, 0x1ff);
+MMP2_DEVICE(u2o, "mv-udc", -1, USB_OTG, 0xd4208100, 0x1ff);
+MMP2_DEVICE(u2ootg, "mv-otg", -1, USB_OTG, 0xd4208100, 0x1ff);
+MMP2_DEVICE(u2oehci, "mv-ehci", -1, USB_OTG, 0xd4208100, 0x1ff);
 
 struct resource mmp2_resource_gpio[] = {
 	{
Signature · 1 line
1.7.4.1
author
#14 lore raw

PATCH v4 13/26 arm: pxa910: change the defintion of usb devices

In reply to Chao Xie

because phy is seperated from the usb controller driver, we can use the common pxa_device_desc for device register.

---
 arch/arm/mach-mmp/include/mach/pxa910.h |    7 ++++---
 arch/arm/mach-mmp/pxa910.c              |    4 ++++
 2 files changed, 8 insertions(+), 3 deletions(-)
arch/arm/mach-mmp/include/mach/pxa910.h +4 -3
index 3b58a3b..26ea4fe 100644
@@ -20,9 +20,10 @@ extern struct pxa_device_desc pxa910_device_pwm2;
 extern struct pxa_device_desc pxa910_device_pwm3;
 extern struct pxa_device_desc pxa910_device_pwm4;
 extern struct pxa_device_desc pxa910_device_nand;
-extern struct platform_device pxa168_device_u2o;
-extern struct platform_device pxa168_device_u2ootg;
-extern struct platform_device pxa168_device_u2oehci;
+extern struct pxa_device_desc pxa910_device_u2o;
+extern struct pxa_device_desc pxa910_device_u2ootg;
+extern struct pxa_device_desc pxa910_device_u2oehci;
+extern struct pxa_device_desc pxa910_device_u2ophy;
 
 extern struct platform_device pxa910_device_gpio;
 extern struct platform_device pxa910_device_rtc;
arch/arm/mach-mmp/pxa910.c +4 -0
index 8b1e16f..65174f7 100644
@@ -138,6 +138,10 @@ PXA910_DEVICE(pwm2, "pxa910-pwm", 1, NONE, 0xd401a400, 0x10);
 PXA910_DEVICE(pwm3, "pxa910-pwm", 2, NONE, 0xd401a800, 0x10);
 PXA910_DEVICE(pwm4, "pxa910-pwm", 3, NONE, 0xd401ac00, 0x10);
 PXA910_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x80, 97, 99);
+PXA910_DEVICE(u2ophy, "pxa910-usb-phy", -1, NONE, 0xd4207000, 0x1ff);
+PXA910_DEVICE(u2o, "mv-udc", -1, USB1, 0xd4208100, 0x1ff);
+PXA910_DEVICE(u2ootg, "mv-otg", -1, USB1, 0xd4208100, 0x1ff);
+PXA910_DEVICE(u2oehci, "mv-ehci", -1, USB1, 0xd4208100, 0x1ff);
 
 struct resource pxa910_resource_gpio[] = {
 	{
Signature · 1 line
1.7.4.1
author
#15 lore raw

PATCH v4 14/26 arm: brownstone: add usb support for the board

In reply to Chao Xie

for brownstone board, add the udc/otg/ehci support

---
 arch/arm/mach-mmp/brownstone.c |   47 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 47 insertions(+), 0 deletions(-)
arch/arm/mach-mmp/brownstone.c +47 -0
index 5cb769c..90c0340 100644
@@ -18,6 +18,7 @@
 #include <linux/regulator/max8649.h>
 #include <linux/regulator/fixed.h>
 #include <linux/mfd/max8925.h>
+#include <linux/platform_data/mv_usb.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -195,6 +196,31 @@ static struct sram_platdata mmp2_isram_platdata = {
 	.granularity	= SRAM_GRANULARITY,
 };
 
+#ifdef CONFIG_USB_SUPPORT
+
+static char *mmp2_usb_clock_name[] = {
+	[0] = "usb_clk",
+};
+
+static struct mv_usb_phy_platform_data brownstone_usb_phy_pdata = {
+	.clknum		= 1,
+	.clkname	= mmp2_usb_clock_name,
+};
+
+#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
+
+static struct mv_usb_platform_data brownstone_usb_pdata = {
+	.clknum		= 1,
+	.clkname	= mmp2_usb_clock_name,
+	.vbus		= NULL,
+	.mode		= MV_USB_MODE_OTG,
+	.otg_force_a_bus_req = 1,
+	.set_vbus	= NULL,
+};
+#endif
+#endif
+
+
 static void __init brownstone_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(brownstone_pin_config));
@@ -211,6 +237,27 @@ static void __init brownstone_init(void)
 
 	/* enable 5v regulator */
 	platform_device_register(&brownstone_v_5vp_device);
+
+#ifdef CONFIG_USB_SUPPORT
+	pxa_register_device(&mmp2_device_u2ophy, &brownstone_usb_phy_pdata,
+				sizeof(brownstone_usb_phy_pdata));
+#endif
+
+#ifdef CONFIG_USB_MV_UDC
+	pxa_register_device(&mmp2_device_u2o, &brownstone_usb_pdata,
+				sizeof(brownstone_usb_pdata));
+#endif
+
+#ifdef CONFIG_USB_EHCI_MV_U2O
+	pxa_register_device(&mmp2_device_u2oehci, &brownstone_usb_pdata,
+				sizeof(brownstone_usb_pdata));
+#endif
+
+#ifdef CONFIG_USB_MV_OTG
+	pxa_register_device(&mmp2_device_u2ootg, &brownstone_usb_pdata,
+				sizeof(brownstone_usb_pdata));
+#endif
+
 }
 
 MACHINE_START(BROWNSTONE, "Brownstone Development Platform")
Signature · 1 line
1.7.4.1
author
#16 lore raw

PATCH v4 15/26 arm: ttc_dkb: add usb support

In reply to Chao Xie

for ttc_dkb board, add udc/otg/ehci support

---
 arch/arm/mach-mmp/ttc_dkb.c |   30 +++++++++++++++++++-----------
 1 files changed, 19 insertions(+), 11 deletions(-)
arch/arm/mach-mmp/ttc_dkb.c +19 -11
index ce55fd8..0962791 100644
@@ -27,7 +27,6 @@
 #include <mach/mfp-pxa910.h>
 #include <mach/pxa910.h>
 #include <mach/irqs.h>
-#include <mach/regs-usb.h>
 
 #include "common.h"
 
@@ -158,20 +157,24 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
 };
 
 #ifdef CONFIG_USB_SUPPORT
-#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
 
 static char *pxa910_usb_clock_name[] = {
-	[0] = "U2OCLK",
+	[0] = "usb_clk",
+};
+
+static struct mv_usb_phy_platform_data ttc_usb_phy_pdata = {
+	.clknum		= 1,
+	.clkname	= pxa910_usb_clock_name,
 };
 
+#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
+
 static struct mv_usb_platform_data ttc_usb_pdata = {
 	.clknum		= 1,
 	.clkname	= pxa910_usb_clock_name,
 	.vbus		= NULL,
 	.mode		= MV_USB_MODE_OTG,
 	.otg_force_a_bus_req = 1,
-	.phy_init	= pxa_usb_phy_init,
-	.phy_deinit	= pxa_usb_phy_deinit,
 	.set_vbus	= NULL,
 };
 #endif
@@ -198,19 +201,24 @@ static void __init ttc_dkb_init(void)
 	pxa910_add_twsi(0, NULL, ARRAY_AND_SIZE(ttc_dkb_i2c_info));
 	platform_add_devices(ARRAY_AND_SIZE(ttc_dkb_devices));
 
+#ifdef CONFIG_USB_SUPPORT
+	pxa_register_device(&pxa910_device_u2ophy, &ttc_usb_phy_pdata,
+				sizeof(ttc_usb_phy_pdata));
+#endif
+
 #ifdef CONFIG_USB_MV_UDC
-	pxa168_device_u2o.dev.platform_data = &ttc_usb_pdata;
-	platform_device_register(&pxa168_device_u2o);
+	pxa_register_device(&pxa910_device_u2o, &ttc_usb_pdata,
+				sizeof(ttc_usb_pdata));
 #endif
 
 #ifdef CONFIG_USB_EHCI_MV_U2O
-	pxa168_device_u2oehci.dev.platform_data = &ttc_usb_pdata;
-	platform_device_register(&pxa168_device_u2oehci);
+	pxa_register_device(&pxa910_device_u2oehci, &ttc_usb_pdata,
+				sizeof(ttc_usb_pdata));
 #endif
 
 #ifdef CONFIG_USB_MV_OTG
-	pxa168_device_u2ootg.dev.platform_data = &ttc_usb_pdata;
-	platform_device_register(&pxa168_device_u2ootg);
+	pxa_register_device(&pxa910_device_u2ootg, &ttc_usb_pdata,
+				sizeof(ttc_usb_pdata));
 #endif
 }
 
Signature · 1 line
1.7.4.1
author
#17 lore raw

PATCH v4 16/26 arm: mmp: remove the usb phy setting

In reply to Chao Xie

phy setting are formatted into a phy driver at drivers/usb/phy, we do not need do the setting in SOC files.

---
 arch/arm/mach-mmp/devices.c               |  278 -----------------------------
 arch/arm/mach-mmp/include/mach/regs-usb.h |  253 --------------------------
 2 files changed, 0 insertions(+), 531 deletions(-)
 delete mode 100644 arch/arm/mach-mmp/include/mach/regs-usb.h
arch/arm/mach-mmp/devices.c +0 -278
index dd2d8b1..af341e5 100644
@@ -15,7 +15,6 @@
 #include <mach/irqs.h>
 #include <mach/devices.h>
 #include <mach/cputype.h>
-#include <mach/regs-usb.h>
 
 int __init pxa_register_device(struct pxa_device_desc *desc,
 				void *data, size_t size)
@@ -72,280 +71,3 @@ int __init pxa_register_device(struct pxa_device_desc *desc,
 	return platform_device_add(pdev);
 }
 
-#if defined(CONFIG_USB) || defined(CONFIG_USB_GADGET)
-
-/*****************************************************************************
- * The registers read/write routines
- *****************************************************************************/
-
-static unsigned int u2o_get(void __iomem *base, unsigned int offset)
-{
-	return readl_relaxed(base + offset);
-}
-
-static void u2o_set(void __iomem *base, unsigned int offset,
-		unsigned int value)
-{
-	u32 reg;
-
-	reg = readl_relaxed(base + offset);
-	reg |= value;
-	writel_relaxed(reg, base + offset);
-	readl_relaxed(base + offset);
-}
-
-static void u2o_clear(void __iomem *base, unsigned int offset,
-		unsigned int value)
-{
-	u32 reg;
-
-	reg = readl_relaxed(base + offset);
-	reg &= ~value;
-	writel_relaxed(reg, base + offset);
-	readl_relaxed(base + offset);
-}
-
-static void u2o_write(void __iomem *base, unsigned int offset,
-		unsigned int value)
-{
-	writel_relaxed(value, base + offset);
-	readl_relaxed(base + offset);
-}
-
-#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV)
-
-#if defined(CONFIG_CPU_PXA910) || defined(CONFIG_CPU_PXA168)
-
-static DEFINE_MUTEX(phy_lock);
-static int phy_init_cnt;
-
-static int usb_phy_init_internal(void __iomem *base)
-{
-	int loops;
-
-	pr_info("Init usb phy!!!\n");
-
-	/* Initialize the USB PHY power */
-	if (cpu_is_pxa910()) {
-		u2o_set(base, UTMI_CTRL, (1<<UTMI_CTRL_INPKT_DELAY_SOF_SHIFT)
-			| (1<<UTMI_CTRL_PU_REF_SHIFT));
-	}
-
-	u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
-	u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
-
-	/* UTMI_PLL settings */
-	u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK
-		| UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK
-		| UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK
-		| UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK);
-
-	u2o_set(base, UTMI_PLL, 0xee<<UTMI_PLL_FBDIV_SHIFT
-		| 0xb<<UTMI_PLL_REFDIV_SHIFT | 3<<UTMI_PLL_PLLVDD18_SHIFT
-		| 3<<UTMI_PLL_PLLVDD12_SHIFT | 3<<UTMI_PLL_PLLCALI12_SHIFT
-		| 1<<UTMI_PLL_ICP_SHIFT | 3<<UTMI_PLL_KVCO_SHIFT);
-
-	/* UTMI_TX */
-	u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK
-		| UTMI_TX_TXVDD12_MASK | UTMI_TX_CK60_PHSEL_MASK
-		| UTMI_TX_IMPCAL_VTH_MASK | UTMI_TX_REG_EXT_FS_RCAL_MASK
-		| UTMI_TX_AMP_MASK);
-	u2o_set(base, UTMI_TX, 3<<UTMI_TX_TXVDD12_SHIFT
-		| 4<<UTMI_TX_CK60_PHSEL_SHIFT | 4<<UTMI_TX_IMPCAL_VTH_SHIFT
-		| 8<<UTMI_TX_REG_EXT_FS_RCAL_SHIFT | 3<<UTMI_TX_AMP_SHIFT);
-
-	/* UTMI_RX */
-	u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK
-		| UTMI_REG_SQ_LENGTH_MASK);
-	u2o_set(base, UTMI_RX, 7<<UTMI_RX_SQ_THRESH_SHIFT
-		| 2<<UTMI_REG_SQ_LENGTH_SHIFT);
-
-	/* UTMI_IVREF */
-	if (cpu_is_pxa168())
-		/* fixing Microsoft Altair board interface with NEC hub issue -
-		 * Set UTMI_IVREF from 0x4a3 to 0x4bf */
-		u2o_write(base, UTMI_IVREF, 0x4bf);
-
-	/* toggle VCOCAL_START bit of UTMI_PLL */
-	udelay(200);
-	u2o_set(base, UTMI_PLL, VCOCAL_START);
-	udelay(40);
-	u2o_clear(base, UTMI_PLL, VCOCAL_START);
-
-	/* toggle REG_RCAL_START bit of UTMI_TX */
-	udelay(400);
-	u2o_set(base, UTMI_TX, REG_RCAL_START);
-	udelay(40);
-	u2o_clear(base, UTMI_TX, REG_RCAL_START);
-	udelay(400);
-
-	/* Make sure PHY PLL is ready */
-	loops = 0;
-	while ((u2o_get(base, UTMI_PLL) & PLL_READY) == 0) {
-		mdelay(1);
-		loops++;
-		if (loops > 100) {
-			printk(KERN_WARNING "calibrate timeout, UTMI_PLL %x\n",
-				u2o_get(base, UTMI_PLL));
-			break;
-		}
-	}
-
-	if (cpu_is_pxa168()) {
-		u2o_set(base, UTMI_RESERVE, 1 << 5);
-		/* Turn on UTMI PHY OTG extension */
-		u2o_write(base, UTMI_OTG_ADDON, 1);
-	}
-
-	return 0;
-}
-
-static int usb_phy_deinit_internal(void __iomem *base)
-{
-	pr_info("Deinit usb phy!!!\n");
-
-	if (cpu_is_pxa168())
-		u2o_clear(base, UTMI_OTG_ADDON, UTMI_OTG_ADDON_OTG_ON);
-
-	u2o_clear(base, UTMI_CTRL, UTMI_CTRL_RXBUF_PDWN);
-	u2o_clear(base, UTMI_CTRL, UTMI_CTRL_TXBUF_PDWN);
-	u2o_clear(base, UTMI_CTRL, UTMI_CTRL_USB_CLK_EN);
-	u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
-	u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
-
-	return 0;
-}
-
-int pxa_usb_phy_init(void __iomem *phy_reg)
-{
-	mutex_lock(&phy_lock);
-	if (phy_init_cnt++ == 0)
-		usb_phy_init_internal(phy_reg);
-	mutex_unlock(&phy_lock);
-	return 0;
-}
-
-void pxa_usb_phy_deinit(void __iomem *phy_reg)
-{
-	WARN_ON(phy_init_cnt == 0);
-
-	mutex_lock(&phy_lock);
-	if (--phy_init_cnt == 0)
-		usb_phy_deinit_internal(phy_reg);
-	mutex_unlock(&phy_lock);
-}
-#endif
-#endif
-#endif
-
-#ifdef CONFIG_USB_SUPPORT
-static u64 usb_dma_mask = ~(u32)0;
-
-#ifdef CONFIG_USB_MV_UDC
-struct resource pxa168_u2o_resources[] = {
-	/* regbase */
-	[0] = {
-		.start	= PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
-		.end	= PXA168_U2O_REGBASE + USB_REG_RANGE,
-		.flags	= IORESOURCE_MEM,
-		.name	= "capregs",
-	},
-	/* phybase */
-	[1] = {
-		.start	= PXA168_U2O_PHYBASE,
-		.end	= PXA168_U2O_PHYBASE + USB_PHY_RANGE,
-		.flags	= IORESOURCE_MEM,
-		.name	= "phyregs",
-	},
-	[2] = {
-		.start	= IRQ_PXA168_USB1,
-		.end	= IRQ_PXA168_USB1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device pxa168_device_u2o = {
-	.name		= "mv-udc",
-	.id		= -1,
-	.resource	= pxa168_u2o_resources,
-	.num_resources	= ARRAY_SIZE(pxa168_u2o_resources),
-	.dev		=  {
-		.dma_mask	= &usb_dma_mask,
-		.coherent_dma_mask = 0xffffffff,
-	}
-};
-#endif /* CONFIG_USB_MV_UDC */
-
-#ifdef CONFIG_USB_EHCI_MV_U2O
-struct resource pxa168_u2oehci_resources[] = {
-	/* regbase */
-	[0] = {
-		.start	= PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
-		.end	= PXA168_U2O_REGBASE + USB_REG_RANGE,
-		.flags	= IORESOURCE_MEM,
-		.name	= "capregs",
-	},
-	/* phybase */
-	[1] = {
-		.start	= PXA168_U2O_PHYBASE,
-		.end	= PXA168_U2O_PHYBASE + USB_PHY_RANGE,
-		.flags	= IORESOURCE_MEM,
-		.name	= "phyregs",
-	},
-	[2] = {
-		.start	= IRQ_PXA168_USB1,
-		.end	= IRQ_PXA168_USB1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device pxa168_device_u2oehci = {
-	.name		= "pxa-u2oehci",
-	.id		= -1,
-	.dev		= {
-		.dma_mask		= &usb_dma_mask,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-
-	.num_resources	= ARRAY_SIZE(pxa168_u2oehci_resources),
-	.resource	= pxa168_u2oehci_resources,
-};
-#endif
-
-#if defined(CONFIG_USB_MV_OTG)
-struct resource pxa168_u2ootg_resources[] = {
-	/* regbase */
-	[0] = {
-		.start	= PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
-		.end	= PXA168_U2O_REGBASE + USB_REG_RANGE,
-		.flags	= IORESOURCE_MEM,
-		.name	= "capregs",
-	},
-	/* phybase */
-	[1] = {
-		.start	= PXA168_U2O_PHYBASE,
-		.end	= PXA168_U2O_PHYBASE + USB_PHY_RANGE,
-		.flags	= IORESOURCE_MEM,
-		.name	= "phyregs",
-	},
-	[2] = {
-		.start	= IRQ_PXA168_USB1,
-		.end	= IRQ_PXA168_USB1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device pxa168_device_u2ootg = {
-	.name		= "mv-otg",
-	.id		= -1,
-	.dev  = {
-		.dma_mask          = &usb_dma_mask,
-		.coherent_dma_mask = 0xffffffff,
-	},
-
-	.num_resources	= ARRAY_SIZE(pxa168_u2ootg_resources),
-	.resource      = pxa168_u2ootg_resources,
-};
-#endif /* CONFIG_USB_MV_OTG */
-
-#endif
arch/arm/mach-mmp/include/mach/regs-usb.h deleted +0 -253

253 lines not on this page · raw message

Signature · 1 line
1.7.4.1
author
#18 lore raw

PATCH v4 17/26 arm: mmp: remove usb devices from pxa168

In reply to Chao Xie
---
 arch/arm/mach-mmp/pxa168.c |   42 ------------------------------------------
 1 files changed, 0 insertions(+), 42 deletions(-)
arch/arm/mach-mmp/pxa168.c +0 -42
index b7f074f..dd3a68b 100644
@@ -28,7 +28,6 @@
 #include <mach/mfp.h>
 #include <linux/dma-mapping.h>
 #include <mach/pxa168.h>
-#include <mach/regs-usb.h>
 
 #include "common.h"
 #include "clock.h"
@@ -135,47 +134,6 @@ struct platform_device pxa168_device_gpio = {
 	.resource	= pxa168_resource_gpio,
 };
 
-struct resource pxa168_usb_host_resources[] = {
-	/* USB Host conroller register base */
-	[0] = {
-		.start	= PXA168_U2H_REGBASE + U2x_CAPREGS_OFFSET,
-		.end	= PXA168_U2H_REGBASE + USB_REG_RANGE,
-		.flags	= IORESOURCE_MEM,
-		.name	= "capregs",
-	},
-	/* USB PHY register base */
-	[1] = {
-		.start	= PXA168_U2H_PHYBASE,
-		.end	= PXA168_U2H_PHYBASE + USB_PHY_RANGE,
-		.flags	= IORESOURCE_MEM,
-		.name	= "phyregs",
-	},
-	[2] = {
-		.start	= IRQ_PXA168_USB2,
-		.end	= IRQ_PXA168_USB2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 pxa168_usb_host_dmamask = DMA_BIT_MASK(32);
-struct platform_device pxa168_device_usb_host = {
-	.name = "pxa-sph",
-	.id   = -1,
-	.dev  = {
-		.dma_mask = &pxa168_usb_host_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-
-	.num_resources = ARRAY_SIZE(pxa168_usb_host_resources),
-	.resource      = pxa168_usb_host_resources,
-};
-
-int __init pxa168_add_usb_host(struct mv_usb_platform_data *pdata)
-{
-	pxa168_device_usb_host.dev.platform_data = pdata;
-	return platform_device_register(&pxa168_device_usb_host);
-}
-
 void pxa168_restart(char mode, const char *cmd)
 {
 	soft_restart(0xffff0000);
Signature · 1 line
1.7.4.1
author
#19 lore raw

PATCH v4 18/26 usb: phy: mv_usb2_phy: add externel chip support

In reply to Chao Xie

For the vbus and idpin detection. It may be completed by some external chip, for example the pmic chip 88pm860x in driver/mfd can do it.
Although the usb controller can detect the vbus and id pin, but it need clock on and PHY enabled to detect the vbus/idpin. It will increase the power.
Using the external chip to detect vbus/idpin can save the power.

---
 drivers/usb/phy/mv_usb2_phy.c        |   54 +++++++++++++++++++++
 include/linux/platform_data/mv_usb.h |   15 ++----
 include/linux/usb/mv_usb2.h          |   85 ++++++++++++++++++++++++++++++++++
 3 files changed, 144 insertions(+), 10 deletions(-)
drivers/usb/phy/mv_usb2_phy.c +54 -0
index c2bccae..0bea901 100644
@@ -136,6 +136,53 @@ struct mv_usb2_phy *mv_usb2_get_phy(void)
 }
 EXPORT_SYMBOL(mv_usb2_get_phy);
 
+int mv_usb2_register_notifier(struct mv_usb2_phy *phy,
+		struct notifier_block *nb)
+{
+	int ret;
+
+	if (!phy)
+		return -ENODEV;
+
+	ret = atomic_notifier_chain_register(phy->extern_chip.head, nb);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(mv_usb2_register_notifier);
+
+int mv_usb2_unregister_notifier(struct mv_usb2_phy *phy,
+		struct notifier_block *nb)
+{
+	int ret;
+
+	if (!phy)
+		return -ENODEV;
+
+	ret = atomic_notifier_chain_unregister(phy->extern_chip.head, nb);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(mv_usb2_unregister_notifier);
+
+int mv_usb2_notify(struct mv_usb2_phy *phy, unsigned long val, void *v)
+{
+	int ret;
+
+	if (!phy)
+		return -ENODEV;
+
+	ret = atomic_notifier_call_chain(phy->extern_chip.head, val, v);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(mv_usb2_notify);
+
 static unsigned int u2o_get(void __iomem *base, unsigned int offset)
 {
 	return readl(base + offset);
@@ -414,6 +461,13 @@ static int usb_phy_probe(struct platform_device *pdev)
 	mv_phy->init = usb_phy_init;
 	mv_phy->shutdown = usb_phy_shutdown;
 
+	mv_phy->extern_chip.head = devm_kzalloc(&pdev->dev,
+					sizeof(*mv_phy->extern_chip.head),
+					GFP_KERNEL);
+	if (mv_phy->extern_chip.head == NULL)
+		return -ENOMEM;
+	ATOMIC_INIT_NOTIFIER_HEAD(mv_phy->extern_chip.head);
+
 	platform_set_drvdata(pdev, mv_phy);
 
 	the_phy = mv_phy;
include/linux/platform_data/mv_usb.h +5 -10
index fd3d1b4..dc25d60 100644
@@ -28,16 +28,13 @@ enum {
 	VBUS_HIGH	= 1 << 0,
 };
 
-struct mv_usb_addon_irq {
-	unsigned int	irq;
-	int		(*poll)(void);
-};
-
+#define MV_USB_HAS_VBUS_DETECTION	(1 << 0)
+#define MV_USB_HAS_IDPIN_DETECTION	(1 << 1)
 struct mv_usb_platform_data {
 	unsigned int		clknum;
 	char			**clkname;
-	struct mv_usb_addon_irq	*id;	/* Only valid for OTG. ID pin change*/
-	struct mv_usb_addon_irq	*vbus;	/* valid for OTG/UDC. VBUS change*/
+
+	unsigned int		extern_attr;
 
 	/* only valid for HCD. OTG or Host only*/
 	unsigned int		mode;
@@ -45,9 +42,7 @@ struct mv_usb_platform_data {
 	/* This flag is used for that needs id pin checked by otg */
 	unsigned int    disable_otg_clock_gating:1;
 	/* Force a_bus_req to be asserted */
-	 unsigned int    otg_force_a_bus_req:1;
-
-	int	(*set_vbus)(unsigned int vbus);
+	unsigned int    otg_force_a_bus_req:1;
 };
 
 struct mv_usb_phy_platform_data {
include/linux/usb/mv_usb2.h +85 -0

107 lines not on this page · raw message

Signature · 1 line
1.7.4.1
#20 lore raw

PATCH v4 18/26 usb: phy: mv_usb2_phy: add externel chip support

drivers/usb/phy/mv_usb2_phy.c static int usb_phy_probe(struct platform_device *pdev) · line 469

Quoted 6 lines · Chao Xie
drivers/usb/phy/mv_usb2_phy.c +6 -0
+	mv_phy->extern_chip.head = devm_kzalloc(&pdev->dev,
+					sizeof(*mv_phy->extern_chip.head),
+					GFP_KERNEL);
+	if (mv_phy->extern_chip.head == NULL)
+		return -ENOMEM;
+	ATOMIC_INIT_NOTIFIER_HEAD(mv_phy->extern_chip.head);

Why do you need to allocate an atomic notifier list head as an entirely separate data structure?

#21 lore raw

PATCH v4 18/26 usb: phy: mv_usb2_phy: add externel chip support

Quoted 8 lines · Russell King - ARM Linux

drivers/usb/phy/mv_usb2_phy.c static int usb_phy_probe(struct platform_device *pdev) · line 469

Quoted 6 lines · Chao Xie
drivers/usb/phy/mv_usb2_phy.c +6 -0
+     mv_phy->extern_chip.head = devm_kzalloc(&pdev->dev,
+                                     sizeof(*mv_phy->extern_chip.head),
+                                     GFP_KERNEL);
+     if (mv_phy->extern_chip.head == NULL)
+             return -ENOMEM;
+     ATOMIC_INIT_NOTIFIER_HEAD(mv_phy->extern_chip.head);
Quoted 6 lines

Why do you need to allocate an atomic notifier list head as an entirely separate data structure?
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

Th reason is that the original code seperate the extern_chip and phy support. So it depends
on the ->head to detect whether extern_chip is initialized or not. Now it is combined with phy, the ->phy pointer can do the job.

#22 lore raw

PATCH v4 18/26 usb: phy: mv_usb2_phy: add externel chip support

Hi,

Quoted 17 lines · Chao Xie
Quoted 8 lines · Russell King - ARM Linux

drivers/usb/phy/mv_usb2_phy.c static int usb_phy_probe(struct platform_device *pdev) · line 469

Quoted 6 lines · Chao Xie
drivers/usb/phy/mv_usb2_phy.c +6 -0
+     mv_phy->extern_chip.head = devm_kzalloc(&pdev->dev,
+                                     sizeof(*mv_phy->extern_chip.head),
+                                     GFP_KERNEL);
+     if (mv_phy->extern_chip.head == NULL)
+             return -ENOMEM;
+     ATOMIC_INIT_NOTIFIER_HEAD(mv_phy->extern_chip.head);
Quoted 6 lines

Why do you need to allocate an atomic notifier list head as an entirely separate data structure?
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

Quoted 4 lines

Th reason is that the original code seperate the extern_chip and phy support. So it depends
on the ->head to detect whether extern_chip is initialized or not. Now it is combined with phy, the ->phy pointer can do the job.

does that need to be dynamically allocated ?

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130123/36addcdc/attachment.sig>
#23 lore raw

PATCH v4 18/26 usb: phy: mv_usb2_phy: add externel chip support

Quoted 25 lines · Felipe Balbi

Hi,

Quoted 17 lines · Chao Xie
Quoted 8 lines · Russell King - ARM Linux

drivers/usb/phy/mv_usb2_phy.c static int usb_phy_probe(struct platform_device *pdev) · line 469

Quoted 6 lines · Chao Xie
drivers/usb/phy/mv_usb2_phy.c +6 -0
+     mv_phy->extern_chip.head = devm_kzalloc(&pdev->dev,
+                                     sizeof(*mv_phy->extern_chip.head),
+                                     GFP_KERNEL);
+     if (mv_phy->extern_chip.head == NULL)
+             return -ENOMEM;
+     ATOMIC_INIT_NOTIFIER_HEAD(mv_phy->extern_chip.head);
Quoted 6 lines

Why do you need to allocate an atomic notifier list head as an entirely separate data structure?
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

Quoted 4 lines

Th reason is that the original code seperate the extern_chip and phy support. So it depends
on the ->head to detect whether extern_chip is initialized or not. Now it is combined with phy, the ->phy pointer can do the job.

Quoted 4 lines

does that need to be dynamically allocated ?

--
balbi

hi
It does not need to be dynamically allocated. I will modify it, and send out V5 today. Thanks for Russell's review.

author
#24 lore raw

PATCH v4 19/26 usb: gadget: mv_udc: add extern chip support

In reply to Chao Xie

Because arch-mmp will make use of irq domain for irq allocation, the irqs allocated for PMIC is dynamical. The vbus/idpin irqs from PMIC can not be passed by platform data. Using the extern chip APIs provides by PHY driver can solve this problem.
Marvell usb PHY driver provides a middle layer.
The PMIC usb drivers will help to register the callbacks in the marvell usb PHY driver.
udc/otg/ehci driver will call the callbacks.
Then we do not need pass the information in platform data. It will remove another block in the way of enabling device tree for usb.

---
 drivers/usb/gadget/mv_udc.h      |    3 ++
 drivers/usb/gadget/mv_udc_core.c |   45 ++++++++++++++++++++++---------------
 2 files changed, 30 insertions(+), 18 deletions(-)
drivers/usb/gadget/mv_udc.h +3 -0
index 4851b2b..50ae7c7 100644
@@ -178,6 +178,9 @@ struct mv_udc {
 	struct platform_device		*dev;
 	int				irq;
 
+	unsigned int			extern_attr;
+	struct notifier_block		notifier;
+
 	struct mv_cap_regs __iomem	*cap_regs;
 	struct mv_op_regs __iomem	*op_regs;
 	unsigned int			max_eps;
drivers/usb/gadget/mv_udc_core.c +27 -18

110 lines not on this page · raw message

Signature · 1 line
1.7.4.1
author
#25 lore raw

PATCH v4 20/26 usb: ehci: ehci-mv: add extern chip support

In reply to Chao Xie

It does the similar things as what we do for udc driver.

---
 drivers/usb/host/ehci-mv.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)
drivers/usb/host/ehci-mv.c +6 -6
index be504fd..171e145 100644
@@ -256,8 +256,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
 		goto err_disable_clk;
 #endif
 	} else {
-		if (pdata->set_vbus)
-			pdata->set_vbus(1);
+		if (mv_usb2_has_extern_call(ehci_mv->mvphy, vbus, set_vbus))
+			mv_usb2_extern_call(ehci_mv->mvphy, vbus, set_vbus, 1);
 
 		retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
 		if (retval) {
@@ -275,8 +275,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	return 0;
 
 err_set_vbus:
-	if (pdata->set_vbus)
-		pdata->set_vbus(0);
+	if (mv_usb2_has_extern_call(ehci_mv->mvphy, vbus, set_vbus))
+		mv_usb2_extern_call(ehci_mv->mvphy, vbus, set_vbus, 0);
 err_disable_clk:
 	mv_ehci_disable(ehci_mv);
 err_clear_drvdata:
@@ -299,8 +299,8 @@ static int mv_ehci_remove(struct platform_device *pdev)
 		otg_set_host(ehci_mv->otg->otg, NULL);
 
 	if (ehci_mv->mode == MV_USB_MODE_HOST) {
-		if (ehci_mv->pdata->set_vbus)
-			ehci_mv->pdata->set_vbus(0);
+		if (mv_usb2_has_extern_call(ehci_mv->mvphy, vbus, set_vbus))
+			mv_usb2_extern_call(ehci_mv->mvphy, vbus, set_vbus, 1);
 
 		mv_ehci_disable(ehci_mv);
 	}
Signature · 1 line
1.7.4.1
author
#26 lore raw

PATCH v4 21/26 usb: otg: mv_otg: add extern chip support

In reply to Chao Xie

It does the similar things as what we do for udc driver.

---
 drivers/usb/otg/mv_otg.c |   63 ++++++++++++++++++++-------------------------
 drivers/usb/otg/mv_otg.h |    3 ++
 2 files changed, 31 insertions(+), 35 deletions(-)
drivers/usb/otg/mv_otg.c +28 -35
index cc45ef2..379df92 100644
@@ -59,10 +59,10 @@ static char *state_string[] = {
 static int mv_otg_set_vbus(struct usb_otg *otg, bool on)
 {
 	struct mv_otg *mvotg = container_of(otg->phy, struct mv_otg, phy);
-	if (mvotg->pdata->set_vbus == NULL)
+	if (!mv_usb2_has_extern_call(mvotg->mvphy, vbus, set_vbus))
 		return -ENODEV;
 
-	return mvotg->pdata->set_vbus(on);
+	return mv_usb2_extern_call(mvotg->mvphy, vbus, set_vbus, on);
 }
 
 static int mv_otg_set_host(struct usb_otg *otg,
@@ -184,14 +184,14 @@ static void mv_otg_init_irq(struct mv_otg *mvotg)
 	mvotg->irq_status = OTGSC_INTSTS_A_SESSION_VALID
 	    | OTGSC_INTSTS_A_VBUS_VALID;
 
-	if (mvotg->pdata->vbus == NULL) {
+	if (!(mvotg->extern_attr & MV_USB_HAS_VBUS_DETECTION)) {
 		mvotg->irq_en |= OTGSC_INTR_B_SESSION_VALID
 		    | OTGSC_INTR_B_SESSION_END;
 		mvotg->irq_status |= OTGSC_INTSTS_B_SESSION_VALID
 		    | OTGSC_INTSTS_B_SESSION_END;
 	}
 
-	if (mvotg->pdata->id == NULL) {
+	if (!(mvotg->extern_attr & MV_USB_HAS_IDPIN_DETECTION)) {
 		mvotg->irq_en |= OTGSC_INTR_USB_ID;
 		mvotg->irq_status |= OTGSC_INTSTS_USB_ID;
 	}
@@ -306,11 +306,14 @@ static void mv_otg_update_inputs(struct mv_otg *mvotg)
 {
 	struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
 	u32 otgsc;
+	unsigned int vbus, idpin;
 
 	otgsc = readl(&mvotg->op_regs->otgsc);
 
-	if (mvotg->pdata->vbus) {
-		if (mvotg->pdata->vbus->poll() == VBUS_HIGH) {
+	if (mvotg->extern_attr & MV_USB_HAS_VBUS_DETECTION) {
+		if (mv_usb2_extern_call(mvotg->mvphy, vbus, get_vbus, &vbus))
+			return;
+		if (vbus == VBUS_HIGH) {
 			otg_ctrl->b_sess_vld = 1;
 			otg_ctrl->b_sess_end = 0;
 		} else {
@@ -322,8 +325,11 @@ static void mv_otg_update_inputs(struct mv_otg *mvotg)
 		otg_ctrl->b_sess_end = !!(otgsc & OTGSC_STS_B_SESSION_END);
 	}
 
-	if (mvotg->pdata->id)
-		otg_ctrl->id = !!mvotg->pdata->id->poll();
+	if (mvotg->extern_attr & MV_USB_HAS_IDPIN_DETECTION) {
+		if (mv_usb2_extern_call(mvotg->mvphy, idpin, get_idpin, &idpin))
+			return;
+		otg_ctrl->id = !!idpin;
+	}
 	else
 		otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID);
 
@@ -505,7 +511,7 @@ static irqreturn_t mv_otg_irq(int irq, void *dev)
 	 * if we have vbus, then the vbus detection for B-device
 	 * will be done by mv_otg_inputs_irq().
 	 */
-	if (mvotg->pdata->vbus)
+	if (mvotg->extern_attr & MV_USB_HAS_VBUS_DETECTION)
 		if ((otgsc & OTGSC_STS_USB_ID) &&
 		    !(otgsc & OTGSC_INTSTS_USB_ID))
 			return IRQ_NONE;
@@ -518,9 +524,10 @@ static irqreturn_t mv_otg_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t mv_otg_inputs_irq(int irq, void *dev)
+static int mv_otg_notifier_call(struct notifier_block *nb,
+				unsigned long val, void *v)
 {
-	struct mv_otg *mvotg = dev;
+	struct mv_otg *mvotg = container_of(nb, struct mv_otg, notifier);
 
 	/* The clock may disabled at this time */
 	if (!mvotg->active) {
@@ -530,7 +537,7 @@ static irqreturn_t mv_otg_inputs_irq(int irq, void *dev)
 
 	mv_otg_run_state_machine(mvotg, 0);
 
-	return IRQ_HANDLED;
+	return 0;
 }
 
 static ssize_t
@@ -666,6 +673,10 @@ int mv_otg_remove(struct platform_device *pdev)
 
 	sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
 
+	if ((mvotg->extern_attr & MV_USB_HAS_VBUS_DETECTION) ||
+		(mvotg->extern_attr & MV_USB_HAS_IDPIN_DETECTION))
+		mv_usb2_unregister_notifier(mvotg->mvphy, &mvotg->notifier);
+
 	if (mvotg->qwork) {
 		flush_workqueue(mvotg->qwork);
 		destroy_workqueue(mvotg->qwork);
@@ -707,6 +718,7 @@ static int mv_otg_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, mvotg);
 
 	mvotg->pdev = pdev;
+	mvotg->extern_attr = pdata->extern_attr;
 	mvotg->pdata = pdata;
 
 	mvotg->clknum = pdata->clknum;
@@ -773,29 +785,10 @@ static int mv_otg_probe(struct platform_device *pdev)
 		(struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs
 			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
 
-	if (pdata->id) {
-		retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
-						NULL, mv_otg_inputs_irq,
-						IRQF_ONESHOT, "id", mvotg);
-		if (retval) {
-			dev_info(&pdev->dev,
-				 "Failed to request irq for ID\n");
-			pdata->id = NULL;
-		}
-	}
-
-	if (pdata->vbus) {
-		mvotg->clock_gating = 1;
-		retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
-						NULL, mv_otg_inputs_irq,
-						IRQF_ONESHOT, "vbus", mvotg);
-		if (retval) {
-			dev_info(&pdev->dev,
-				 "Failed to request irq for VBUS, "
-				 "disable clock gating\n");
-			mvotg->clock_gating = 0;
-			pdata->vbus = NULL;
-		}
+	if ((mvotg->extern_attr & MV_USB_HAS_VBUS_DETECTION) ||
+		(mvotg->extern_attr & MV_USB_HAS_IDPIN_DETECTION)) {
+		mvotg->notifier.notifier_call = mv_otg_notifier_call;
+		mv_usb2_register_notifier(mvotg->mvphy, &mvotg->notifier);
 	}
 
 	if (pdata->disable_otg_clock_gating)
drivers/usb/otg/mv_otg.h +3 -0
index 7b9629a..f5bc7dd 100644
@@ -149,6 +149,9 @@ struct mv_otg {
 	u32 irq_status;
 	u32 irq_en;
 
+	unsigned int extern_attr;
+	struct notifier_block notifier;
+
 	struct delayed_work work;
 	struct workqueue_struct *qwork;
 
Signature · 1 line
1.7.4.1
author
#27 lore raw

PATCH v4 22/26 arm: mmp: add extern chip support for brownstone

In reply to Chao Xie

Change the board support for usb as extern chip is supported in marvell usb PHY driver

---
 arch/arm/mach-mmp/brownstone.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
arch/arm/mach-mmp/brownstone.c +0 -2
index 90c0340..3dcf38f 100644
@@ -212,10 +212,8 @@ static struct mv_usb_phy_platform_data brownstone_usb_phy_pdata = {
 static struct mv_usb_platform_data brownstone_usb_pdata = {
 	.clknum		= 1,
 	.clkname	= mmp2_usb_clock_name,
-	.vbus		= NULL,
 	.mode		= MV_USB_MODE_OTG,
 	.otg_force_a_bus_req = 1,
-	.set_vbus	= NULL,
 };
 #endif
 #endif
Signature · 1 line
1.7.4.1
author
#28 lore raw

PATCH v4 23/26 arm: mmp: add extern chip support for ttc_dkb

In reply to Chao Xie

Change the board support for usb as extern chip is supported in marvell usb PHY driver.

---
 arch/arm/mach-mmp/ttc_dkb.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
arch/arm/mach-mmp/ttc_dkb.c +0 -2
index 0962791..eb34608 100644
@@ -172,10 +172,8 @@ static struct mv_usb_phy_platform_data ttc_usb_phy_pdata = {
 static struct mv_usb_platform_data ttc_usb_pdata = {
 	.clknum		= 1,
 	.clkname	= pxa910_usb_clock_name,
-	.vbus		= NULL,
 	.mode		= MV_USB_MODE_OTG,
 	.otg_force_a_bus_req = 1,
-	.set_vbus	= NULL,
 };
 #endif
 #endif
Signature · 1 line
1.7.4.1
author
#29 lore raw

PATCH v4 24/26 usb: gadget: mv_udc: add device tree support

In reply to Chao Xie

In original driver, we have callbacks in platform data, and some dynamically allocations variables in platform data. Now, these blocks are removed, the device tree support is easier now.

---
 drivers/usb/gadget/mv_udc.h      |    5 +-
 drivers/usb/gadget/mv_udc_core.c |  106 ++++++++++++++++++++++++++++++--------
 2 files changed, 86 insertions(+), 25 deletions(-)
drivers/usb/gadget/mv_udc.h +2 -3
index 50ae7c7..de84722 100644
@@ -179,6 +179,7 @@ struct mv_udc {
 	int				irq;
 
 	unsigned int			extern_attr;
+	unsigned int			mode;
 	struct notifier_block		notifier;
 
 	struct mv_cap_regs __iomem	*cap_regs;
@@ -222,11 +223,9 @@ struct mv_udc {
 	struct mv_usb2_phy	*phy;
 	struct usb_phy		*transceiver;
 
-	struct mv_usb_platform_data     *pdata;
-
 	/* some SOC has mutiple clock sources for USB*/
 	unsigned int    clknum;
-	struct clk      *clk[0];
+	struct clk      **clk;
 };
 
 /* endpoint data structure */
drivers/usb/gadget/mv_udc_core.c +84 -22

154 lines not on this page · raw message

Signature · 1 line
1.7.4.1
author
#30 lore raw

PATCH v4 25/26 usb: otg: mv_otg: add device tree support

In reply to Chao Xie

All blocks are removed. Add the device tree support for otg.

---
 drivers/usb/otg/mv_otg.c |  128 +++++++++++++++++++++++++++++++++++++--------
 drivers/usb/otg/mv_otg.h |    6 +-
 2 files changed, 108 insertions(+), 26 deletions(-)
drivers/usb/otg/mv_otg.c +105 -23
index 379df92..3aa7fdc 100644
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/proc_fs.h>
 #include <linux/clk.h>
+#include <linux/of.h>
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
 
@@ -333,7 +334,7 @@ static void mv_otg_update_inputs(struct mv_otg *mvotg)
 	else
 		otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID);
 
-	if (mvotg->pdata->otg_force_a_bus_req && !otg_ctrl->id)
+	if (mvotg->otg_force_a_bus_req && !otg_ctrl->id)
 		otg_ctrl->a_bus_req = 1;
 
 	otg_ctrl->a_sess_vld = !!(otgsc & OTGSC_STS_A_SESSION_VALID);
@@ -690,21 +691,69 @@ int mv_otg_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int mv_otg_parse_dt(struct platform_device *pdev,
+				struct mv_otg *mvotg)
+{
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int clks_num;
+	unsigned int val;
+	int i, ret;
+	const char *clk_name;
+
+	if (!np)
+		return 1;
+
+	clks_num = of_property_count_strings(np, "clocks");
+	if (clks_num < 0)
+		return clks_num;
+
+	mvotg->clk = devm_kzalloc(&pdev->dev,
+		sizeof(struct clk *) * clks_num, GFP_KERNEL);
+	if (mvotg->clk == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < clks_num; i++) {
+		ret = of_property_read_string_index(np, "clocks", i,
+			&clk_name);
+		if (ret)
+			return ret;
+		mvotg->clk[i] = devm_clk_get(&pdev->dev, clk_name);
+		if (IS_ERR(mvotg->clk[i]))
+			return PTR_ERR(mvotg->clk[i]);
+	}
+
+	mvotg->clknum = clks_num;
+
+	ret = of_property_read_u32(np, "extern_attr", &mvotg->extern_attr);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32(np, "mode", &mvotg->mode);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32(np, "force_a_bus_req", &val);
+	if (ret)
+		return ret;
+	mvotg->otg_force_a_bus_req = !!val;
+
+	ret = of_property_read_u32(np, "disable_clock_gating", &val);
+	if (ret)
+		return ret;
+	mvotg->clock_gating = !val;
+
+	return 0;
+}
+
 static int mv_otg_probe(struct platform_device *pdev)
 {
-	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct mv_otg *mvotg;
 	struct usb_otg *otg;
 	struct resource *r;
-	int retval = 0, clk_i, i;
+	int retval = 0, i;
 	size_t size;
 
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "failed to get platform data\n");
-		return -ENODEV;
-	}
-
-	size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
+	size = sizeof(*mvotg);
 	mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (!mvotg) {
 		dev_err(&pdev->dev, "failed to allocate memory!\n");
@@ -718,17 +767,45 @@ static int mv_otg_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, mvotg);
 
 	mvotg->pdev = pdev;
-	mvotg->extern_attr = pdata->extern_attr;
-	mvotg->pdata = pdata;
 
-	mvotg->clknum = pdata->clknum;
-	for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
-		mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
+	retval = mv_otg_parse_dt(pdev, mvotg);
+	if (retval > 0) {
+		struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+		/* no CONFIG_OF */
+		int clk_i = 0;
+
+		if (pdata == NULL) {
+			dev_err(&pdev->dev, "missing platform_data\n");
+			return -ENODEV;
+		}
+		mvotg->extern_attr = pdata->extern_attr;
+		mvotg->mode = pdata->mode;
+		mvotg->clknum = pdata->clknum;
+		mvotg->otg_force_a_bus_req = pdata->otg_force_a_bus_req;
+		if (pdata->disable_otg_clock_gating)
+			mvotg->clock_gating = 0;
+
+		size = sizeof(struct clk *) * mvotg->clknum;
+		mvotg->clk = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+		if (mvotg->clk == NULL) {
+			dev_err(&pdev->dev,
+				"failed to allocate memory for clk\n");
+			return -ENOMEM;
+		}
+
+		for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
+			mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
 						pdata->clkname[clk_i]);
-		if (IS_ERR(mvotg->clk[clk_i])) {
-			retval = PTR_ERR(mvotg->clk[clk_i]);
-			return retval;
+			if (IS_ERR(mvotg->clk[clk_i])) {
+				dev_err(&pdev->dev, "failed to get clk %s\n",
+					pdata->clkname[clk_i]);
+				retval = PTR_ERR(mvotg->clk[clk_i]);
+				return retval;
+			}
 		}
+	} else if (retval < 0) {
+		dev_err(&pdev->dev, "error parse dt\n");
+		return retval;
 	}
 
 	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
@@ -770,6 +847,7 @@ static int mv_otg_probe(struct platform_device *pdev)
 	}
 	mvotg->mvphy = mv_usb2_get_phy();
 	if (mvotg->mvphy == NULL) {
+		dev_err(&pdev->dev, "failed to get usb phy\n");
 		retval = -ENODEV;
 		goto err_destroy_workqueue;
 	}
@@ -791,9 +869,6 @@ static int mv_otg_probe(struct platform_device *pdev)
 		mv_usb2_register_notifier(mvotg->mvphy, &mvotg->notifier);
 	}
 
-	if (pdata->disable_otg_clock_gating)
-		mvotg->clock_gating = 0;
-
 	mv_otg_reset(mvotg);
 	mv_otg_init_irq(mvotg);
 
@@ -892,13 +967,20 @@ static int mv_otg_resume(struct platform_device *pdev)
 }
 #endif
 
+static struct of_device_id mv_otg_dt_ids[] = {
+	{ .compatible = "mrvl,mv-otg" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mv_otg_dt_ids);
+
 static struct platform_driver mv_otg_driver = {
 	.probe = mv_otg_probe,
 	.remove = __exit_p(mv_otg_remove),
 	.driver = {
-		   .owner = THIS_MODULE,
-		   .name = driver_name,
-		   },
+		.owner = THIS_MODULE,
+		.name = driver_name,
+		.of_match_table = mv_otg_dt_ids,
+	},
 #ifdef CONFIG_PM
 	.suspend = mv_otg_suspend,
 	.resume = mv_otg_resume,
drivers/usb/otg/mv_otg.h +3 -3
index f5bc7dd..3b9356d 100644
@@ -157,12 +157,12 @@ struct mv_otg {
 
 	spinlock_t wq_lock;
 
-	struct mv_usb_platform_data *pdata;
-
 	unsigned int active;
 	unsigned int clock_gating;
+	unsigned int mode;
+	unsigned int otg_force_a_bus_req;
 	unsigned int clknum;
-	struct clk *clk[0];
+	struct clk **clk;
 };
 
 #endif
Signature · 1 line
1.7.4.1
author
#31 lore raw

PATCH v4 26/26 usb: ehci: ehci-mv: add device tree support

In reply to Chao Xie

All blocks are removed. Add the device tree support for ehci.

---
 drivers/usb/host/ehci-mv.c |  105 +++++++++++++++++++++++++++++++++----------
 1 files changed, 80 insertions(+), 25 deletions(-)
drivers/usb/host/ehci-mv.c +80 -25
index 171e145..79eca0c 100644
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/of.h>
 #include <linux/err.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/mv_usb2.h>
@@ -32,11 +33,9 @@ struct ehci_hcd_mv {
 
 	struct usb_phy *otg;
 
-	struct mv_usb_platform_data *pdata;
-
 	/* clock source and total clock number */
 	unsigned int clknum;
-	struct clk *clk[0];
+	struct clk **clk;
 };
 
 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
@@ -138,22 +137,55 @@ static const struct hc_driver mv_ehci_hc_driver = {
 	.bus_resume = ehci_bus_resume,
 };
 
+static int mv_ehci_parse_dt(struct platform_device *pdev,
+				struct ehci_hcd_mv *ehci_mv)
+{
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int clks_num;
+	int i, ret;
+	const char *clk_name;
+
+	if (!np)
+		return 1;
+
+	clks_num = of_property_count_strings(np, "clocks");
+	if (clks_num < 0)
+		return clks_num;
+
+	ehci_mv->clk = devm_kzalloc(&pdev->dev,
+		sizeof(struct clk *) * clks_num, GFP_KERNEL);
+	if (ehci_mv->clk == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < clks_num; i++) {
+		ret = of_property_read_string_index(np, "clocks", i,
+			&clk_name);
+		if (ret)
+			return ret;
+		ehci_mv->clk[i] = clk_get(NULL, clk_name);
+		if (IS_ERR(ehci_mv->clk[i]))
+			return PTR_ERR(ehci_mv->clk[i]);
+	}
+
+	ehci_mv->clknum = clks_num;
+
+	ret = of_property_read_u32(np, "mode", &ehci_mv->mode);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int mv_ehci_probe(struct platform_device *pdev)
 {
-	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct usb_hcd *hcd;
 	struct ehci_hcd *ehci;
 	struct ehci_hcd_mv *ehci_mv;
 	struct resource *r;
-	int clk_i, retval = -ENODEV;
+	int retval = -ENODEV;
 	u32 offset;
 	size_t size;
 
-	if (!pdata) {
-		dev_err(&pdev->dev, "missing platform_data\n");
-		return -ENODEV;
-	}
-
 	if (usb_disabled())
 		return -ENODEV;
 
@@ -161,7 +193,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	if (!hcd)
 		return -ENOMEM;
 
-	size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
+	size = sizeof(*ehci_mv);
 	ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (ehci_mv == NULL) {
 		dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
@@ -170,19 +202,36 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, ehci_mv);
-	ehci_mv->pdata = pdata;
 	ehci_mv->hcd = hcd;
 
-	ehci_mv->clknum = pdata->clknum;
-	for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
-		ehci_mv->clk[clk_i] =
-		    devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
-		if (IS_ERR(ehci_mv->clk[clk_i])) {
-			dev_err(&pdev->dev, "error get clck \"%s\"\n",
-				pdata->clkname[clk_i]);
-			retval = PTR_ERR(ehci_mv->clk[clk_i]);
-			goto err_clear_drvdata;
+	retval = mv_ehci_parse_dt(pdev, ehci_mv);
+	if (retval > 0) {
+		struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+		int clk_i = 0;
+
+		/* no CONFIG_OF */
+		if (pdata == NULL) {
+			dev_err(&pdev->dev, "missing platform_data\n");
+			return -ENODEV;
+		}
+		ehci_mv->mode = pdata->mode;
+		ehci_mv->clknum = pdata->clknum;
+
+		size = sizeof(struct clk *) * ehci_mv->clknum;
+		ehci_mv->clk = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+		if (ehci_mv->clk == NULL)
+			return -ENOMEM;
+		for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
+			ehci_mv->clk[clk_i] = devm_clk_get(&pdev->dev,
+						pdata->clkname[clk_i]);
+			if (IS_ERR(ehci_mv->clk[clk_i])) {
+				retval = PTR_ERR(ehci_mv->clk[clk_i]);
+				return retval;
+			}
 		}
+	} else if (retval < 0) {
+		dev_err(&pdev->dev, "error parse dt\n");
+		return retval;
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -230,7 +279,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs;
 
-	ehci_mv->mode = pdata->mode;
 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
 #ifdef CONFIG_USB_OTG_UTILS
 		ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
@@ -334,13 +382,20 @@ static void mv_ehci_shutdown(struct platform_device *pdev)
 		hcd->driver->shutdown(hcd);
 }
 
+static struct of_device_id mv_ehci_dt_ids[] = {
+	{ .compatible = "mrvl,mv-ehci" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mv_ehci_dt_ids);
+
 static struct platform_driver ehci_mv_driver = {
 	.probe = mv_ehci_probe,
 	.remove = mv_ehci_remove,
 	.shutdown = mv_ehci_shutdown,
 	.driver = {
-		   .name = "mv-ehci",
-		   .bus = &platform_bus_type,
-		   },
+		.name = "mv-ehci",
+		.bus = &platform_bus_type,
+		.of_match_table = mv_ehci_dt_ids,
+	},
 	.id_table = ehci_id_table,
 };
Signature · 1 line
1.7.4.1
#32 lore raw

v4 cover mv-usb fix and enhancement patches

In reply to Chao Xie

Hi,

Quoted 62 lines · Chao Xie

The patches are divied into 4 parts
1. bug fixes
usb: gadget: mv_udc: use udc_start and udc_stop functions
usb: gadget: mv_udc: use devm_xxx for probe
usb: gadget: mv_udc: fix the warning of mv_udc_remove
usb: otg: mv_otg: use devm_xxx for probe
usb: host: ehci-mv: remove unused variable
usb: gadget: mv_udc: fix the value of tranceiver
usb: gadget: mv_udc: make mv_udc depends on ARCH_MMP or ARCH_PXA
Above patches are bug fixes.

2. PHY driver
To remove the callbacks in the platform data, a usb PHY driver for marvell udc/otg/ehci is written.
For device tree support, it is not good to pass the callback pointers by platform data. The PHY driver also removes the block.

usb: phy: mv_usb2: add PHY driver for marvell usb2 controller
usb: gadget: mv_udc: use PHY driver for udc
usb: ehci: ehci-mv: use PHY driver for ehci
usb: otg: mv_otg: use PHY driver for otg
Above patches are marvell usb PHY driver support.

arm: mmp2: change the defintion of usb devices
arm: pxa910: change the defintion of usb devices
arm: brownstone: add usb support for the board
arm: ttc_dkb: add usb support
arm: mmp: remove the usb phy setting
arm: mmp: remove usb devices from pxa168
Above patches are for SOC/board support for marvell usb PHY driver.

3. external chip support
The marvell usb controller can detect the vbus/idpin, but it need PHY and usb clocks to be enabled.
Based on measurement it will import 15mA current, and increase the power when the usb is not used.
Using a external chip to detect vbus/idpin changes will save the power.
In fact the marvell PMIC 88pm860x and 88pm80x can do it. The drivers are located at drivers/mfd.
So add a middle layer in the marvell usb PHY driver. PMIC call the APIs in middle driver to registers the callback for vbus/idpin detection/query
udc/otg/ehci driver will call the APIs to get vbus/idpin changes and query the states of the vbus/idpin.
usb: phy: mv_usb2_phy: add externel chip support
usb: gadget: mv_udc: add extern chip support
usb: ehci: ehci-mv: add extern chip support
usb: otg: mv_otg: add extern chip support
Above patches are the middle layer suppor for udc/otg/ehci

arm: mmp: add extern chip support for brownstone
arm: mmp: add extern chip support for ttc_dkb
Above patches are corresponding board file changes

4. device tree support
After removing the callbacks in platform data, and the not constant variables in platform data. All the information needed by udc/otg/ehci driver are constant.

Quoted 4 lines

usb: gadget: mv_udc: add device tree support
usb: otg: mv_otg: add device tree support
usb: ehci: ehci-mv: add device tree support
Above patches are device tree support for udc/otg/ehci driver.

this series will be delayed for v3.10. Sorry

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130123/85fa8727/attachment.sig>