From: Dario Binacchi Date: Tue, 29 Dec 2020 23:16:20 +0000 (+0100) Subject: clk: move clk-ti-sci driver to 'ti' directory X-Git-Tag: baikal/mips/sdk5.9~34^2^2~249^2~16 X-Git-Url: https://git.baikalelectronics.ru/sdk/?a=commitdiff_plain;h=627a572fb9d690237a50a9b142252fe7cc1ed2e7;p=uboot.git clk: move clk-ti-sci driver to 'ti' directory The patch moves the clk-ti-sci.c file to the 'ti' directory along with all the other TI's drivers, and renames it clk-sci.c. Signed-off-by: Dario Binacchi --- diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 9e54929039..db06f276ec 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -98,14 +98,6 @@ config CLK_STM32F This clock driver adds support for RCC clock management for STM32F4 and STM32F7 SoCs. -config CLK_TI_SCI - bool "TI System Control Interface (TI SCI) clock driver" - depends on CLK && TI_SCI_PROTOCOL && OF_CONTROL - help - This enables the clock driver support over TI System Control Interface - available on some new TI's SoCs. If you wish to use clock resources - managed by the TI System Controller, say Y here. Otherwise, say N. - config CLK_HSDK bool "Enable cgu clock driver for HSDK boards" depends on CLK && TARGET_HSDK diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 2581fe0a19..f8383e523d 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -48,6 +48,5 @@ obj-$(CONFIG_SANDBOX) += clk_sandbox.o obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o obj-$(CONFIG_SANDBOX_CLK_CCF) += clk_sandbox_ccf.o obj-$(CONFIG_STM32H7) += clk_stm32h7.o -obj-$(CONFIG_CLK_TI_SCI) += clk-ti-sci.o obj-$(CONFIG_CLK_VERSAL) += clk_versal.o obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o diff --git a/drivers/clk/clk-ti-sci.c b/drivers/clk/clk-ti-sci.c deleted file mode 100644 index 6f0fdaa111..0000000000 --- a/drivers/clk/clk-ti-sci.c +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Texas Instruments System Control Interface (TI SCI) clock driver - * - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ - * Andreas Dannenberg - * - * Loosely based on Linux kernel sci-clk.c... - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * struct ti_sci_clk_data - clock controller information structure - * @sci: TI SCI handle used for communication with system controller - */ -struct ti_sci_clk_data { - const struct ti_sci_handle *sci; -}; - -static int ti_sci_clk_probe(struct udevice *dev) -{ - struct ti_sci_clk_data *data = dev_get_priv(dev); - - debug("%s(dev=%p)\n", __func__, dev); - - if (!data) - return -ENOMEM; - - /* Store handle for communication with the system controller */ - data->sci = ti_sci_get_handle(dev); - if (IS_ERR(data->sci)) - return PTR_ERR(data->sci); - - return 0; -} - -static int ti_sci_clk_of_xlate(struct clk *clk, - struct ofnode_phandle_args *args) -{ - debug("%s(clk=%p, args_count=%d)\n", __func__, clk, args->args_count); - - if (args->args_count != 2) { - debug("Invalid args_count: %d\n", args->args_count); - return -EINVAL; - } - - /* - * On TI SCI-based devices, the clock provider id field is used as a - * device ID, and the data field is used as the associated sub-ID. - */ - clk->id = args->args[0]; - clk->data = args->args[1]; - - return 0; -} - -static int ti_sci_clk_request(struct clk *clk) -{ - debug("%s(clk=%p)\n", __func__, clk); - return 0; -} - -static int ti_sci_clk_free(struct clk *clk) -{ - debug("%s(clk=%p)\n", __func__, clk); - return 0; -} - -static ulong ti_sci_clk_get_rate(struct clk *clk) -{ - struct ti_sci_clk_data *data = dev_get_priv(clk->dev); - const struct ti_sci_handle *sci = data->sci; - const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; - u64 current_freq; - int ret; - - debug("%s(clk=%p)\n", __func__, clk); - - ret = cops->get_freq(sci, clk->id, clk->data, ¤t_freq); - if (ret) { - dev_err(clk->dev, "%s: get_freq failed (%d)\n", __func__, ret); - return ret; - } - - debug("%s(current_freq=%llu)\n", __func__, current_freq); - - return current_freq; -} - -static ulong ti_sci_clk_set_rate(struct clk *clk, ulong rate) -{ - struct ti_sci_clk_data *data = dev_get_priv(clk->dev); - const struct ti_sci_handle *sci = data->sci; - const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; - int ret; - - debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate); - -#ifdef CONFIG_K3_AVS0 - k3_avs_notify_freq(clk->id, clk->data, rate); -#endif - - ret = cops->set_freq(sci, clk->id, clk->data, 0, rate, ULONG_MAX); - if (ret) - dev_err(clk->dev, "%s: set_freq failed (%d)\n", __func__, ret); - - return ret; -} - -static int ti_sci_clk_set_parent(struct clk *clk, struct clk *parent) -{ - struct ti_sci_clk_data *data = dev_get_priv(clk->dev); - const struct ti_sci_handle *sci = data->sci; - const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; - u8 num_parents; - u8 parent_cid; - int ret; - - debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent); - - /* Make sure the clock parent is valid for a given device ID */ - if (clk->id != parent->id) - return -EINVAL; - - /* Make sure clock has parents that can be set */ - ret = cops->get_num_parents(sci, clk->id, clk->data, &num_parents); - if (ret) { - dev_err(clk->dev, "%s: get_num_parents failed (%d)\n", - __func__, ret); - return ret; - } - if (num_parents < 2) { - dev_err(clk->dev, "%s: clock has no settable parents!\n", - __func__); - return -EINVAL; - } - - /* Make sure parent clock ID is valid */ - parent_cid = parent->data - clk->data - 1; - if (parent_cid >= num_parents) { - dev_err(clk->dev, "%s: invalid parent clock!\n", __func__); - return -EINVAL; - } - - /* Ready to proceed to configure the new clock parent */ - ret = cops->set_parent(sci, clk->id, clk->data, parent->data); - if (ret) - dev_err(clk->dev, "%s: set_parent failed (%d)\n", __func__, - ret); - - return ret; -} - -static int ti_sci_clk_enable(struct clk *clk) -{ - struct ti_sci_clk_data *data = dev_get_priv(clk->dev); - const struct ti_sci_handle *sci = data->sci; - const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; - int ret; - - debug("%s(clk=%p)\n", __func__, clk); - - /* - * Allow the System Controller to automatically manage the state of - * this clock. If the device is enabled, then the clock is enabled. - */ - ret = cops->put_clock(sci, clk->id, clk->data); - if (ret) - dev_err(clk->dev, "%s: put_clock failed (%d)\n", __func__, ret); - - return ret; -} - -static int ti_sci_clk_disable(struct clk *clk) -{ - struct ti_sci_clk_data *data = dev_get_priv(clk->dev); - const struct ti_sci_handle *sci = data->sci; - const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; - int ret; - - debug("%s(clk=%p)\n", __func__, clk); - - /* Unconditionally disable clock, regardless of state of the device */ - ret = cops->idle_clock(sci, clk->id, clk->data); - if (ret) - dev_err(clk->dev, "%s: idle_clock failed (%d)\n", __func__, - ret); - - return ret; -} - -static const struct udevice_id ti_sci_clk_of_match[] = { - { .compatible = "ti,k2g-sci-clk" }, - { /* sentinel */ }, -}; - -static struct clk_ops ti_sci_clk_ops = { - .of_xlate = ti_sci_clk_of_xlate, - .request = ti_sci_clk_request, - .rfree = ti_sci_clk_free, - .get_rate = ti_sci_clk_get_rate, - .set_rate = ti_sci_clk_set_rate, - .set_parent = ti_sci_clk_set_parent, - .enable = ti_sci_clk_enable, - .disable = ti_sci_clk_disable, -}; - -U_BOOT_DRIVER(ti_sci_clk) = { - .name = "ti-sci-clk", - .id = UCLASS_CLK, - .of_match = ti_sci_clk_of_match, - .probe = ti_sci_clk_probe, - .priv_auto = sizeof(struct ti_sci_clk_data), - .ops = &ti_sci_clk_ops, -}; diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig index 9e257a2eb7..2dc86d44a9 100644 --- a/drivers/clk/ti/Kconfig +++ b/drivers/clk/ti/Kconfig @@ -33,3 +33,11 @@ config CLK_TI_MUX depends on CLK && OF_CONTROL && CLK_CCF help This enables the mux clock driver support on TI's SoCs. + +config CLK_TI_SCI + bool "TI System Control Interface (TI SCI) clock driver" + depends on CLK && TI_SCI_PROTOCOL && OF_CONTROL + help + This enables the clock driver support over TI System Control Interface + available on some new TI's SoCs. If you wish to use clock resources + managed by the TI System Controller, say Y here. Otherwise, say N. diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile index dbd343069c..9f56b47736 100644 --- a/drivers/clk/ti/Makefile +++ b/drivers/clk/ti/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_CLK_TI_CTRL) += clk-ctrl.o obj-$(CONFIG_CLK_TI_DIVIDER) += clk-divider.o obj-$(CONFIG_CLK_TI_GATE) += clk-gate.o obj-$(CONFIG_CLK_TI_MUX) += clk-mux.o +obj-$(CONFIG_CLK_TI_SCI) += clk-sci.o diff --git a/drivers/clk/ti/clk-sci.c b/drivers/clk/ti/clk-sci.c new file mode 100644 index 0000000000..6f0fdaa111 --- /dev/null +++ b/drivers/clk/ti/clk-sci.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments System Control Interface (TI SCI) clock driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Andreas Dannenberg + * + * Loosely based on Linux kernel sci-clk.c... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct ti_sci_clk_data - clock controller information structure + * @sci: TI SCI handle used for communication with system controller + */ +struct ti_sci_clk_data { + const struct ti_sci_handle *sci; +}; + +static int ti_sci_clk_probe(struct udevice *dev) +{ + struct ti_sci_clk_data *data = dev_get_priv(dev); + + debug("%s(dev=%p)\n", __func__, dev); + + if (!data) + return -ENOMEM; + + /* Store handle for communication with the system controller */ + data->sci = ti_sci_get_handle(dev); + if (IS_ERR(data->sci)) + return PTR_ERR(data->sci); + + return 0; +} + +static int ti_sci_clk_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + debug("%s(clk=%p, args_count=%d)\n", __func__, clk, args->args_count); + + if (args->args_count != 2) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + /* + * On TI SCI-based devices, the clock provider id field is used as a + * device ID, and the data field is used as the associated sub-ID. + */ + clk->id = args->args[0]; + clk->data = args->args[1]; + + return 0; +} + +static int ti_sci_clk_request(struct clk *clk) +{ + debug("%s(clk=%p)\n", __func__, clk); + return 0; +} + +static int ti_sci_clk_free(struct clk *clk) +{ + debug("%s(clk=%p)\n", __func__, clk); + return 0; +} + +static ulong ti_sci_clk_get_rate(struct clk *clk) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + u64 current_freq; + int ret; + + debug("%s(clk=%p)\n", __func__, clk); + + ret = cops->get_freq(sci, clk->id, clk->data, ¤t_freq); + if (ret) { + dev_err(clk->dev, "%s: get_freq failed (%d)\n", __func__, ret); + return ret; + } + + debug("%s(current_freq=%llu)\n", __func__, current_freq); + + return current_freq; +} + +static ulong ti_sci_clk_set_rate(struct clk *clk, ulong rate) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + int ret; + + debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate); + +#ifdef CONFIG_K3_AVS0 + k3_avs_notify_freq(clk->id, clk->data, rate); +#endif + + ret = cops->set_freq(sci, clk->id, clk->data, 0, rate, ULONG_MAX); + if (ret) + dev_err(clk->dev, "%s: set_freq failed (%d)\n", __func__, ret); + + return ret; +} + +static int ti_sci_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + u8 num_parents; + u8 parent_cid; + int ret; + + debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent); + + /* Make sure the clock parent is valid for a given device ID */ + if (clk->id != parent->id) + return -EINVAL; + + /* Make sure clock has parents that can be set */ + ret = cops->get_num_parents(sci, clk->id, clk->data, &num_parents); + if (ret) { + dev_err(clk->dev, "%s: get_num_parents failed (%d)\n", + __func__, ret); + return ret; + } + if (num_parents < 2) { + dev_err(clk->dev, "%s: clock has no settable parents!\n", + __func__); + return -EINVAL; + } + + /* Make sure parent clock ID is valid */ + parent_cid = parent->data - clk->data - 1; + if (parent_cid >= num_parents) { + dev_err(clk->dev, "%s: invalid parent clock!\n", __func__); + return -EINVAL; + } + + /* Ready to proceed to configure the new clock parent */ + ret = cops->set_parent(sci, clk->id, clk->data, parent->data); + if (ret) + dev_err(clk->dev, "%s: set_parent failed (%d)\n", __func__, + ret); + + return ret; +} + +static int ti_sci_clk_enable(struct clk *clk) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + int ret; + + debug("%s(clk=%p)\n", __func__, clk); + + /* + * Allow the System Controller to automatically manage the state of + * this clock. If the device is enabled, then the clock is enabled. + */ + ret = cops->put_clock(sci, clk->id, clk->data); + if (ret) + dev_err(clk->dev, "%s: put_clock failed (%d)\n", __func__, ret); + + return ret; +} + +static int ti_sci_clk_disable(struct clk *clk) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + int ret; + + debug("%s(clk=%p)\n", __func__, clk); + + /* Unconditionally disable clock, regardless of state of the device */ + ret = cops->idle_clock(sci, clk->id, clk->data); + if (ret) + dev_err(clk->dev, "%s: idle_clock failed (%d)\n", __func__, + ret); + + return ret; +} + +static const struct udevice_id ti_sci_clk_of_match[] = { + { .compatible = "ti,k2g-sci-clk" }, + { /* sentinel */ }, +}; + +static struct clk_ops ti_sci_clk_ops = { + .of_xlate = ti_sci_clk_of_xlate, + .request = ti_sci_clk_request, + .rfree = ti_sci_clk_free, + .get_rate = ti_sci_clk_get_rate, + .set_rate = ti_sci_clk_set_rate, + .set_parent = ti_sci_clk_set_parent, + .enable = ti_sci_clk_enable, + .disable = ti_sci_clk_disable, +}; + +U_BOOT_DRIVER(ti_sci_clk) = { + .name = "ti-sci-clk", + .id = UCLASS_CLK, + .of_match = ti_sci_clk_of_match, + .probe = ti_sci_clk_probe, + .priv_auto = sizeof(struct ti_sci_clk_data), + .ops = &ti_sci_clk_ops, +};