diff options
Diffstat (limited to 'drivers/staging/fclk')
-rw-r--r-- | drivers/staging/fclk/Kconfig | 9 | ||||
-rw-r--r-- | drivers/staging/fclk/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/fclk/TODO | 2 | ||||
-rw-r--r-- | drivers/staging/fclk/dt-binding.txt | 16 | ||||
-rw-r--r-- | drivers/staging/fclk/xilinx_fclk.c | 125 |
5 files changed, 153 insertions, 0 deletions
diff --git a/drivers/staging/fclk/Kconfig b/drivers/staging/fclk/Kconfig new file mode 100644 index 000000000000..5f68261a206d --- /dev/null +++ b/drivers/staging/fclk/Kconfig @@ -0,0 +1,9 @@ +# +# Xilinx PL clk enabler +# + +config XILINX_FCLK + tristate "Xilinx PL clock enabler" + depends on COMMON_CLK && OF + ---help--- + Support for the Xilinx fclk clock enabler. diff --git a/drivers/staging/fclk/Makefile b/drivers/staging/fclk/Makefile new file mode 100644 index 000000000000..71723036c94e --- /dev/null +++ b/drivers/staging/fclk/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_XILINX_FCLK) += xilinx_fclk.o diff --git a/drivers/staging/fclk/TODO b/drivers/staging/fclk/TODO new file mode 100644 index 000000000000..912325fe5f4d --- /dev/null +++ b/drivers/staging/fclk/TODO @@ -0,0 +1,2 @@ +TODO: + - Remove this hack and clock adapt all the drivers. diff --git a/drivers/staging/fclk/dt-binding.txt b/drivers/staging/fclk/dt-binding.txt new file mode 100644 index 000000000000..23521608b4a8 --- /dev/null +++ b/drivers/staging/fclk/dt-binding.txt @@ -0,0 +1,16 @@ +Binding for Xilinx pl clocks + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: + - compatible: Must be 'xlnx,fclk' + - clocks: Handle to input clock + +Example: + fclk3: fclk3 { + status = "disabled"; + compatible = "xlnx,fclk"; + clocks = <&clkc 71>; + }; diff --git a/drivers/staging/fclk/xilinx_fclk.c b/drivers/staging/fclk/xilinx_fclk.c new file mode 100644 index 000000000000..189928b8dd79 --- /dev/null +++ b/drivers/staging/fclk/xilinx_fclk.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2017 Xilinx, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +struct fclk_state { + struct device *dev; + struct clk *pl; +}; + +/* Match table for of_platform binding */ +static const struct of_device_id fclk_of_match[] = { + { .compatible = "xlnx,fclk",}, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, fclk_of_match); + +static ssize_t set_rate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fclk_state *st = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%lu\n", clk_get_rate(st->pl)); +} + +static ssize_t set_rate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret = 0; + unsigned long rate; + struct fclk_state *st = dev_get_drvdata(dev); + + ret = kstrtoul(buf, 0, &rate); + if (ret) + return -EINVAL; + + rate = clk_round_rate(st->pl, rate); + ret = clk_set_rate(st->pl, rate); + + return ret ? ret : count; +} + +static DEVICE_ATTR_RW(set_rate); + +static const struct attribute *fclk_ctrl_attrs[] = { + &dev_attr_set_rate.attr, + NULL, +}; + +static const struct attribute_group fclk_ctrl_attr_grp = { + .attrs = (struct attribute **)fclk_ctrl_attrs, +}; + +static int fclk_probe(struct platform_device *pdev) +{ + struct fclk_state *st; + int ret; + struct device *dev = &pdev->dev; + + st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + st->dev = dev; + platform_set_drvdata(pdev, st); + + st->pl = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(st->pl)) + return PTR_ERR(st->pl); + + ret = clk_prepare_enable(st->pl); + if (ret) { + dev_err(&pdev->dev, "Unable to enable clock.\n"); + return ret; + } + + ret = sysfs_create_group(&dev->kobj, &fclk_ctrl_attr_grp); + if (ret) + return ret; + + return 0; +} + +static int fclk_remove(struct platform_device *pdev) +{ + struct fclk_state *st = platform_get_drvdata(pdev); + + clk_disable_unprepare(st->pl); + return 0; +} + +static struct platform_driver fclk_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = fclk_of_match, + }, + .probe = fclk_probe, + .remove = fclk_remove, +}; + +module_platform_driver(fclk_driver); + +MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>"); +MODULE_DESCRIPTION("fclk enable"); +MODULE_LICENSE("GPL v2"); |