aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2018-09-01 12:03:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-10 14:03:50 -0400
commitffa8a31b5b3b81f12a9d77a574cc0b25bb8e856e (patch)
tree673a0a1f1465cd217b48b367bba7fd7348c6781f
parent697fa834c3103cda43107bce1e1c3cfb7a4603ac (diff)
usb: host: fotg2: add silicon clock handling
When used in a system with software-controlled silicon clocks, the FOTG210 needs to grab, prepare and enable the clock. This is needed on for example the Cortina Gemini, where the platform will by default gate off the clock unless the peripheral (in this case the USB driver) grabs and enables the clock. If there is no clock available on the platform, we live without it. Make sure to percolate probe deferrals. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/fotg210-hcd.c33
-rw-r--r--drivers/usb/host/fotg210.h3
2 files changed, 32 insertions, 4 deletions
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index e64eb47770c8..058ff82ea789 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -31,6 +31,7 @@
31#include <linux/uaccess.h> 31#include <linux/uaccess.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/io.h> 33#include <linux/io.h>
34#include <linux/clk.h>
34 35
35#include <asm/byteorder.h> 36#include <asm/byteorder.h>
36#include <asm/irq.h> 37#include <asm/irq.h>
@@ -5596,7 +5597,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
5596 hcd->regs = devm_ioremap_resource(&pdev->dev, res); 5597 hcd->regs = devm_ioremap_resource(&pdev->dev, res);
5597 if (IS_ERR(hcd->regs)) { 5598 if (IS_ERR(hcd->regs)) {
5598 retval = PTR_ERR(hcd->regs); 5599 retval = PTR_ERR(hcd->regs);
5599 goto failed; 5600 goto failed_put_hcd;
5600 } 5601 }
5601 5602
5602 hcd->rsrc_start = res->start; 5603 hcd->rsrc_start = res->start;
@@ -5606,22 +5607,42 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
5606 5607
5607 fotg210->caps = hcd->regs; 5608 fotg210->caps = hcd->regs;
5608 5609
5610 /* It's OK not to supply this clock */
5611 fotg210->pclk = clk_get(dev, "PCLK");
5612 if (!IS_ERR(fotg210->pclk)) {
5613 retval = clk_prepare_enable(fotg210->pclk);
5614 if (retval) {
5615 dev_err(dev, "failed to enable PCLK\n");
5616 goto failed_put_hcd;
5617 }
5618 } else if (PTR_ERR(fotg210->pclk) == -EPROBE_DEFER) {
5619 /*
5620 * Percolate deferrals, for anything else,
5621 * just live without the clocking.
5622 */
5623 retval = PTR_ERR(fotg210->pclk);
5624 goto failed_dis_clk;
5625 }
5626
5609 retval = fotg210_setup(hcd); 5627 retval = fotg210_setup(hcd);
5610 if (retval) 5628 if (retval)
5611 goto failed; 5629 goto failed_dis_clk;
5612 5630
5613 fotg210_init(fotg210); 5631 fotg210_init(fotg210);
5614 5632
5615 retval = usb_add_hcd(hcd, irq, IRQF_SHARED); 5633 retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
5616 if (retval) { 5634 if (retval) {
5617 dev_err(dev, "failed to add hcd with err %d\n", retval); 5635 dev_err(dev, "failed to add hcd with err %d\n", retval);
5618 goto failed; 5636 goto failed_dis_clk;
5619 } 5637 }
5620 device_wakeup_enable(hcd->self.controller); 5638 device_wakeup_enable(hcd->self.controller);
5621 5639
5622 return retval; 5640 return retval;
5623 5641
5624failed: 5642failed_dis_clk:
5643 if (!IS_ERR(fotg210->pclk))
5644 clk_disable_unprepare(fotg210->pclk);
5645failed_put_hcd:
5625 usb_put_hcd(hcd); 5646 usb_put_hcd(hcd);
5626fail_create_hcd: 5647fail_create_hcd:
5627 dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval); 5648 dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval);
@@ -5637,6 +5658,10 @@ static int fotg210_hcd_remove(struct platform_device *pdev)
5637{ 5658{
5638 struct device *dev = &pdev->dev; 5659 struct device *dev = &pdev->dev;
5639 struct usb_hcd *hcd = dev_get_drvdata(dev); 5660 struct usb_hcd *hcd = dev_get_drvdata(dev);
5661 struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
5662
5663 if (!IS_ERR(fotg210->pclk))
5664 clk_disable_unprepare(fotg210->pclk);
5640 5665
5641 if (!hcd) 5666 if (!hcd)
5642 return 0; 5667 return 0;
diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h
index 7fcd785c7bc8..28f6467c0cbf 100644
--- a/drivers/usb/host/fotg210.h
+++ b/drivers/usb/host/fotg210.h
@@ -182,6 +182,9 @@ struct fotg210_hcd { /* one per controller */
182# define COUNT(x) 182# define COUNT(x)
183#endif 183#endif
184 184
185 /* silicon clock */
186 struct clk *pclk;
187
185 /* debug files */ 188 /* debug files */
186 struct dentry *debug_dir; 189 struct dentry *debug_dir;
187}; 190};