Commit ffa8a31b authored by Linus Walleij's avatar Linus Walleij Committed by Greg Kroah-Hartman

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: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 697fa834
......@@ -31,6 +31,7 @@
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
......@@ -5596,7 +5597,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
hcd->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hcd->regs)) {
retval = PTR_ERR(hcd->regs);
goto failed;
goto failed_put_hcd;
}
hcd->rsrc_start = res->start;
......@@ -5606,22 +5607,42 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
fotg210->caps = hcd->regs;
/* It's OK not to supply this clock */
fotg210->pclk = clk_get(dev, "PCLK");
if (!IS_ERR(fotg210->pclk)) {
retval = clk_prepare_enable(fotg210->pclk);
if (retval) {
dev_err(dev, "failed to enable PCLK\n");
goto failed_put_hcd;
}
} else if (PTR_ERR(fotg210->pclk) == -EPROBE_DEFER) {
/*
* Percolate deferrals, for anything else,
* just live without the clocking.
*/
retval = PTR_ERR(fotg210->pclk);
goto failed_dis_clk;
}
retval = fotg210_setup(hcd);
if (retval)
goto failed;
goto failed_dis_clk;
fotg210_init(fotg210);
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval) {
dev_err(dev, "failed to add hcd with err %d\n", retval);
goto failed;
goto failed_dis_clk;
}
device_wakeup_enable(hcd->self.controller);
return retval;
failed:
failed_dis_clk:
if (!IS_ERR(fotg210->pclk))
clk_disable_unprepare(fotg210->pclk);
failed_put_hcd:
usb_put_hcd(hcd);
fail_create_hcd:
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)
{
struct device *dev = &pdev->dev;
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
if (!IS_ERR(fotg210->pclk))
clk_disable_unprepare(fotg210->pclk);
if (!hcd)
return 0;
......
......@@ -182,6 +182,9 @@ struct fotg210_hcd { /* one per controller */
# define COUNT(x)
#endif
/* silicon clock */
struct clk *pclk;
/* debug files */
struct dentry *debug_dir;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment