usb: gadget: udc-xilinx: Add clock support

Currently the driver depends on the  bootloader to enable the clocks.
Add support for clocking. The patch enables the clock at  probe and
disables them at remove.

Signed-off-by: Shubhrajyoti Datta <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Link: https://lore.kernel.org/r/054de6deeab81020eaf0399add2839c36b64275f.1632805672.git.shubhrajyoti.datta@xilinx.com
Signed-off-by: Greg Kroah-Hartman <[email protected]>
This commit is contained in:
Shubhrajyoti Datta authored and Greg Kroah-Hartman committed 2021-10-05 12:55:16 +02:00
1 parent 01b5415044
commit 2474922921
1 file changed
+25
+25
View File
@@ -11,6 +11,7 @@
* USB peripheral controller (at91_udc.c).
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
@@ -171,6 +172,7 @@ struct xusb_ep {
* @addr: the usb device base address
* @lock: instance of spinlock
* @dma_enabled: flag indicating whether the dma is included in the system
* @clk: pointer to struct clk
* @read_fn: function pointer to read device registers
* @write_fn: function pointer to write to device registers
*/
@@ -188,6 +190,7 @@ struct xusb_udc {
void __iomem *addr;
spinlock_t lock;
bool dma_enabled;
struct clk *clk;
unsigned int (*read_fn)(void __iomem *);
void (*write_fn)(void __iomem *, u32, u32);
@@ -2092,6 +2095,27 @@ static int xudc_probe(struct platform_device *pdev)
udc->gadget.ep0 = &udc->ep[XUSB_EP_NUMBER_ZERO].ep_usb;
udc->gadget.name = driver_name;
udc->clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
if (IS_ERR(udc->clk)) {
if (PTR_ERR(udc->clk) != -ENOENT) {
ret = PTR_ERR(udc->clk);
goto fail;
}
/*
* Clock framework support is optional, continue on,
* anyways if we don't find a matching clock
*/
dev_warn(&pdev->dev, "s_axi_aclk clock property is not found\n");
udc->clk = NULL;
}
ret = clk_prepare_enable(udc->clk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable clock.\n");
return ret;
}
spin_lock_init(&udc->lock);
/* Check for IP endianness */
@@ -2147,6 +2171,7 @@ static int xudc_remove(struct platform_device *pdev)
struct xusb_udc *udc = platform_get_drvdata(pdev);
usb_del_gadget_udc(&udc->gadget);
clk_disable_unprepare(udc->clk);
return 0;
}