diff options
35 files changed, 646 insertions, 405 deletions
diff --git a/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt b/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt new file mode 100644 index 000000000000..2be1e038ca62 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt @@ -0,0 +1,19 @@ +Binding for simple gpio clock multiplexer. + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible : shall be "gpio-mux-clock". +- clocks: list of two references to parent clocks. +- #clock-cells : from common clock binding; shall be set to 0. +- select-gpios : GPIO reference for selecting the parent clock. + +Example: + clock { + compatible = "gpio-mux-clock"; + clocks = <&parentclk1>, <&parentclk2>; + #clock-cells = <0>; + select-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + }; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c4cf075a2320..d08b3e5985be 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-gate.o obj-$(CONFIG_COMMON_CLK) += clk-mux.o obj-$(CONFIG_COMMON_CLK) += clk-composite.o obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o -obj-$(CONFIG_COMMON_CLK) += clk-gpio-gate.o +obj-$(CONFIG_COMMON_CLK) += clk-gpio.o ifeq ($(CONFIG_OF), y) obj-$(CONFIG_COMMON_CLK) += clk-conf.o endif diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c index 152dcb3f7b5f..61566bcefa53 100644 --- a/drivers/clk/at91/clk-h32mx.c +++ b/drivers/clk/at91/clk-h32mx.c @@ -116,8 +116,10 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, h32mxclk->pmc = pmc; clk = clk_register(NULL, &h32mxclk->hw); - if (!clk) + if (!clk) { + kfree(h32mxclk); return; + } of_clk_add_provider(np, of_clk_src_simple_get, clk); } diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index c2400456a044..27dfa965cfed 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c @@ -171,8 +171,10 @@ at91_clk_register_main_osc(struct at91_pmc *pmc, irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); ret = request_irq(osc->irq, clk_main_osc_irq_handler, IRQF_TRIGGER_HIGH, name, osc); - if (ret) + if (ret) { + kfree(osc); return ERR_PTR(ret); + } if (bypass) pmc_write(pmc, AT91_CKGR_MOR, diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index f98eafe9b12d..5b3ded5205a2 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c @@ -165,12 +165,16 @@ at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, irq_set_status_flags(master->irq, IRQ_NOAUTOEN); ret = request_irq(master->irq, clk_master_irq_handler, IRQF_TRIGGER_HIGH, "clk-master", master); - if (ret) + if (ret) { + kfree(master); return ERR_PTR(ret); + } clk = clk_register(NULL, &master->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(master->irq, master); kfree(master); + } return clk; } diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index cbbe40377ad6..18b60f4895a6 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c @@ -346,12 +346,16 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, id ? "clk-pllb" : "clk-plla", pll); - if (ret) + if (ret) { + kfree(pll); return ERR_PTR(ret); + } clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(pll->irq, pll); kfree(pll); + } return clk; } diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index a76d03fd577b..58008b3e8bc1 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c @@ -130,13 +130,17 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name, irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); ret = request_irq(sys->irq, clk_system_irq_handler, IRQF_TRIGGER_HIGH, name, sys); - if (ret) + if (ret) { + kfree(sys); return ERR_PTR(ret); + } } clk = clk_register(NULL, &sys->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(sys->irq, sys); kfree(sys); + } return clk; } diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index ae3263bc1476..30dd697b1668 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -118,12 +118,16 @@ at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); ret = request_irq(utmi->irq, clk_utmi_irq_handler, IRQF_TRIGGER_HIGH, "clk-utmi", utmi); - if (ret) + if (ret) { + kfree(utmi); return ERR_PTR(ret); + } clk = clk_register(NULL, &utmi->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(utmi->irq, utmi); kfree(utmi); + } return clk; } diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index eb8e5dc9076d..8b87771c69b2 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -59,71 +59,63 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value) int of_at91_get_clk_range(struct device_node *np, const char *propname, struct clk_range *range); -extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np, - struct at91_pmc *pmc); - -extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91rm9200_clk_main_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np, - struct at91_pmc *pmc); - -extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9g45_clk_pll_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_sama5d3_clk_pll_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np, - struct at91_pmc *pmc); - -extern void __init of_at91rm9200_clk_master_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np, - struct at91_pmc *pmc); - -extern void __init of_at91rm9200_clk_sys_setup(struct device_node *np, - struct at91_pmc *pmc); - -extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, - struct at91_pmc *pmc); - -extern void __init of_at91rm9200_clk_prog_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, - struct at91_pmc *pmc); - -#if defined(CONFIG_HAVE_AT91_UTMI) -extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np, - struct at91_pmc *pmc); -#endif - -#if defined(CONFIG_HAVE_AT91_USB_CLK) -extern void __init of_at91rm9200_clk_usb_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9x5_clk_usb_setup(struct device_node *np, - struct at91_pmc *pmc); -extern void __init of_at91sam9n12_clk_usb_setup(struct device_node *np, - struct at91_pmc *pmc); -#endif - -#if defined(CONFIG_HAVE_AT91_SMD) -extern void __init of_at91sam9x5_clk_smd_setup(struct device_node *np, - struct at91_pmc *pmc); -#endif - -#if defined(CONFIG_HAVE_AT91_H32MX) -extern void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, - struct at91_pmc *pmc); -#endif +void of_at91sam9260_clk_slow_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91rm9200_clk_main_osc_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91rm9200_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9x5_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91rm9200_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9g45_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9g20_clk_pllb_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_sama5d3_clk_pll_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9x5_clk_plldiv_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91rm9200_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9x5_clk_master_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91rm9200_clk_sys_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91rm9200_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9x5_clk_periph_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91rm9200_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9g45_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9x5_clk_prog_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91sam9x5_clk_utmi_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91rm9200_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9x5_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); +void of_at91sam9n12_clk_usb_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_at91sam9x5_clk_smd_setup(struct device_node *np, + struct at91_pmc *pmc); + +void of_sama5d4_clk_h32mx_setup(struct device_node *np, + struct at91_pmc *pmc); #endif /* __PMC_H_ */ diff --git a/drivers/clk/bcm/clk-iproc-asiu.c b/drivers/clk/bcm/clk-iproc-asiu.c index e19c09cd9645..f630e1bbdcfe 100644 --- a/drivers/clk/bcm/clk-iproc-asiu.c +++ b/drivers/clk/bcm/clk-iproc-asiu.c @@ -222,10 +222,6 @@ void __init iproc_asiu_setup(struct device_node *node, struct iproc_asiu_clk *asiu_clk; const char *clk_name; - clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL); - if (WARN_ON(!clk_name)) - goto err_clk_register; - ret = of_property_read_string_index(node, "clock-output-names", i, &clk_name); if (WARN_ON(ret)) @@ -259,7 +255,7 @@ void __init iproc_asiu_setup(struct device_node *node, err_clk_register: for (i = 0; i < num_clks; i++) - kfree(asiu->clks[i].name); + clk_unregister(asiu->clk_data.clks[i]); iounmap(asiu->gate_base); err_iomap_gate: diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c index 46fb84bc2674..2dda4e8295a9 100644 --- a/drivers/clk/bcm/clk-iproc-pll.c +++ b/drivers/clk/bcm/clk-iproc-pll.c @@ -366,7 +366,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, val = readl(pll->pll_base + ctrl->ndiv_int.offset); ndiv_int = (val >> ctrl->ndiv_int.shift) & bit_mask(ctrl->ndiv_int.width); - ndiv = ndiv_int << ctrl->ndiv_int.shift; + ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift; if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { val = readl(pll->pll_base + ctrl->ndiv_frac.offset); @@ -374,7 +374,8 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, bit_mask(ctrl->ndiv_frac.width); if (ndiv_frac != 0) - ndiv = (ndiv_int << ctrl->ndiv_int.shift) | ndiv_frac; + ndiv = ((u64)ndiv_int << ctrl->ndiv_int.shift) | + ndiv_frac; } val = readl(pll->pll_base + ctrl->pdiv.offset); @@ -655,10 +656,6 @@ void __init iproc_pll_clk_setup(struct device_node *node, memset(&init, 0, sizeof(init)); parent_name = node->name; - clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL); - if (WARN_ON(!clk_name)) - goto err_clk_register; - ret = of_property_read_string_index(node, "clock-output-names", i, &clk_name); if (WARN_ON(ret)) @@ -690,10 +687,8 @@ void __init iproc_pll_clk_setup(struct device_node *node, return; err_clk_register: - for (i = 0; i < num_clks; i++) { - kfree(pll->clks[i].name); + for (i = 0; i < num_clks; i++) clk_unregister(pll->clk_data.clks[i]); - } err_pll_register: if (pll->asiu_base) diff --git a/drivers/clk/clk-gpio-gate.c b/drivers/clk/clk-gpio-gate.c deleted file mode 100644 index f564e624fb93..000000000000 --- a/drivers/clk/clk-gpio-gate.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com - * Author: Jyri Sarha <[email protected]> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Gpio gated clock implementation - */ - -#include <linux/clk-provider.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> -#include <linux/of_gpio.h> -#include <linux/err.h> -#include <linux/device.h> - -/** - * DOC: basic gpio gated clock which can be enabled and disabled - * with gpio output - * Traits of this clock: - * prepare - clk_(un)prepare only ensures parent is (un)prepared - * enable - clk_enable and clk_disable are functional & control gpio - * rate - inherits rate from parent. No clk_set_rate support - * parent - fixed parent. No clk_set_parent support - */ - -#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw) - -static int clk_gpio_gate_enable(struct clk_hw *hw) -{ - struct clk_gpio *clk = to_clk_gpio(hw); - - gpiod_set_value(clk->gpiod, 1); - - return 0; -} - -static void clk_gpio_gate_disable(struct clk_hw *hw) -{ - struct clk_gpio *clk = to_clk_gpio(hw); - - gpiod_set_value(clk->gpiod, 0); -} - -static int clk_gpio_gate_is_enabled(struct clk_hw *hw) -{ - struct clk_gpio *clk = to_clk_gpio(hw); - - return gpiod_get_value(clk->gpiod); -} - -const struct clk_ops clk_gpio_gate_ops = { - .enable = clk_gpio_gate_enable, - .disable = clk_gpio_gate_disable, - .is_enabled = clk_gpio_gate_is_enabled, -}; -EXPORT_SYMBOL_GPL(clk_gpio_gate_ops); - -/** - * clk_register_gpio - register a gpip clock with the clock framework - * @dev: device that is registering this clock - * @name: name of this clock - * @parent_name: name of this clock's parent - * @gpio: gpio number to gate this clock - * @active_low: true if gpio should be set to 0 to enable clock - * @flags: clock flags - */ -struct clk *clk_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, - unsigned long flags) -{ - struct clk_gpio *clk_gpio = NULL; - struct clk *clk = ERR_PTR(-EINVAL); - struct clk_init_data init = { NULL }; - unsigned long gpio_flags; - int err; - - if (active_low) - gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH; - else - gpio_flags = GPIOF_OUT_INIT_LOW; - - if (dev) - err = devm_gpio_request_one(dev, gpio, gpio_flags, name); - else - err = gpio_request_one(gpio, gpio_flags, name); - - if (err) { - pr_err("%s: %s: Error requesting clock control gpio %u\n", - __func__, name, gpio); - return ERR_PTR(err); - } - - if (dev) - clk_gpio = devm_kzalloc(dev, sizeof(struct clk_gpio), - GFP_KERNEL); - else - clk_gpio = kzalloc(sizeof(struct clk_gpio), GFP_KERNEL); - - if (!clk_gpio) { - clk = ERR_PTR(-ENOMEM); - goto clk_register_gpio_gate_err; - } - - init.name = name; - init.ops = &clk_gpio_gate_ops; - init.flags = flags | CLK_IS_BASIC; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); - - clk_gpio->gpiod = gpio_to_desc(gpio); - clk_gpio->hw.init = &init; - - clk = clk_register(dev, &clk_gpio->hw); - - if (!IS_ERR(clk)) - return clk; - - if (!dev) - kfree(clk_gpio); - -clk_register_gpio_gate_err: - if (!dev) - gpio_free(gpio); - - return clk; -} -EXPORT_SYMBOL_GPL(clk_register_gpio_gate); - -#ifdef CONFIG_OF -/** - * The clk_register_gpio_gate has to be delayed, because the EPROBE_DEFER - * can not be handled properly at of_clk_init() call time. - */ - -struct clk_gpio_gate_delayed_register_data { - struct device_node *node; - struct mutex lock; - struct clk *clk; -}; - -static struct clk *of_clk_gpio_gate_delayed_register_get( - struct of_phandle_args *clkspec, - void *_data) -{ - struct clk_gpio_gate_delayed_register_data *data = _data; - struct clk *clk; - const char *clk_name = data->node->name; - const char *parent_name; - int gpio; - enum of_gpio_flags of_flags; - - mutex_lock(&data->lock); - - if (data->clk) { - mutex_unlock(&data->lock); - return data->clk; - } - - gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0, - &of_flags); - if (gpio < 0) { - mutex_unlock(&data->lock); - if (gpio != -EPROBE_DEFER) - pr_err("%s: %s: Can't get 'enable-gpios' DT property\n", - __func__, clk_name); - return ERR_PTR(gpio); - } - - parent_name = of_clk_get_parent_name(data->node, 0); - - clk = clk_register_gpio_gate(NULL, clk_name, parent_name, gpio, - of_flags & OF_GPIO_ACTIVE_LOW, 0); - if (IS_ERR(clk)) { - mutex_unlock(&data->lock); - return clk; - } - - data->clk = clk; - mutex_unlock(&data->lock); - - return clk; -} - -/** - * of_gpio_gate_clk_setup() - Setup function for gpio controlled clock - */ -static void __init of_gpio_gate_clk_setup(struct device_node *node) -{ - struct clk_gpio_gate_delayed_register_data *data; - - data = kzalloc(sizeof(struct clk_gpio_gate_delayed_register_data), - GFP_KERNEL); - if (!data) - return; - - data->node = node; - mutex_init(&data->lock); - - of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data); -} -CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup); -#endif diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c new file mode 100644 index 000000000000..c0d202c24a97 --- /dev/null +++ b/drivers/clk/clk-gpio.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com + * + * Authors: + * Jyri Sarha <[email protected]> + * Sergej Sawazki <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Gpio controlled clock implementation + */ + +#include <linux/clk-provider.h> +#include <linux/export.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/of_gpio.h> +#include <linux/err.h> +#include <linux/device.h> + +/** + * DOC: basic gpio gated clock which can be enabled and disabled + * with gpio output + * Traits of this clock: + * prepare - clk_(un)prepare only ensures parent is (un)prepared + * enable - clk_enable and clk_disable are functional & control gpio + * rate - inherits rate from parent. No clk_set_rate support + * parent - fixed parent. No clk_set_parent support + */ + +#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw) + +static int clk_gpio_gate_enable(struct clk_hw *hw) +{ + struct clk_gpio *clk = to_clk_gpio(hw); + + gpiod_set_value(clk->gpiod, 1); + + return 0; +} + +static void clk_gpio_gate_disable(struct clk_hw *hw) +{ + struct clk_gpio *clk = to_clk_gpio(hw); + + gpiod_set_value(clk->gpiod, 0); +} + +static int clk_gpio_gate_is_enabled(struct clk_hw *hw) +{ + struct clk_gpio *clk = to_clk_gpio(hw); + + return gpiod_get_value(clk->gpiod); +} + +const struct clk_ops clk_gpio_gate_ops = { + .enable = clk_gpio_gate_enable, + .disable = clk_gpio_gate_disable, + .is_enabled = clk_gpio_gate_is_enabled, +}; +EXPORT_SYMBOL_GPL(clk_gpio_gate_ops); + +/** + * DOC: basic clock multiplexer which can be controlled with a gpio output + * Traits of this clock: + * prepare - clk_prepare only ensures that parents are prepared + * rate - rate is only affected by parent switching. No clk_set_rate support + * parent - parent is adjustable through clk_set_parent + */ + +static u8 clk_gpio_mux_get_parent(struct clk_hw *hw) +{ + struct clk_gpio *clk = to_clk_gpio(hw); + + return gpiod_get_value(clk->gpiod); +} + +static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_gpio *clk = to_clk_gpio(hw); + + gpiod_set_value(clk->gpiod, index); + + return 0; +} + +const struct clk_ops clk_gpio_mux_ops = { + .get_parent = clk_gpio_mux_get_parent, + .set_parent = clk_gpio_mux_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; +EXPORT_SYMBOL_GPL(clk_gpio_mux_ops); + +static struct clk *clk_register_gpio(struct device *dev, const char *name, + const char **parent_names, u8 num_parents, unsigned gpio, + bool active_low, unsigned long flags, + const struct clk_ops *clk_gpio_ops) +{ + struct clk_gpio *clk_gpio; + struct clk *clk; + struct clk_init_data init = {}; + unsigned long gpio_flags; + int err; + + if (dev) + clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL); + else + clk_gpio = kzalloc(sizeof(*clk_gpio), GFP_KERNEL); + + if (!clk_gpio) + return ERR_PTR(-ENOMEM); + + if (active_low) + gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH; + else + gpio_flags = GPIOF_OUT_INIT_LOW; + + if (dev) + err = devm_gpio_request_one(dev, gpio, gpio_flags, name); + else + err = gpio_request_one(gpio, gpio_flags, name); + if (err) { + if (err != -EPROBE_DEFER) + pr_err("%s: %s: Error requesting clock control gpio %u\n", + __func__, name, gpio); + if (!dev) + kfree(clk_gpio); + + return ERR_PTR(err); + } + + init.name = name; + init.ops = clk_gpio_ops; + init.flags = flags | CLK_IS_BASIC; + init.parent_names = parent_names; + init.num_parents = num_parents; + + clk_gpio->gpiod = gpio_to_desc(gpio); + clk_gpio->hw.init = &init; + + if (dev) + clk = devm_clk_register(dev, &clk_gpio->hw); + else + clk = clk_register(NULL, &clk_gpio->hw); + + if (!IS_ERR(clk)) + return clk; + + if (!dev) { + gpiod_put(clk_gpio->gpiod); + kfree(clk_gpio); + } + + return clk; +} + +/** + * clk_register_gpio_gate - register a gpio clock gate with the clock framework + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_name: name of this clock's parent + * @gpio: gpio number to gate this clock + * @active_low: true if gpio should be set to 0 to enable clock + * @flags: clock flags + */ +struct clk *clk_register_gpio_gate(struct device *dev, const char *name, + const char *parent_name, unsigned gpio, bool active_low, + unsigned long flags) +{ + return clk_register_gpio(dev, name, + (parent_name ? &parent_name : NULL), + (parent_name ? 1 : 0), gpio, active_low, flags, + &clk_gpio_gate_ops); +} +EXPORT_SYMBOL_GPL(clk_register_gpio_gate); + +/** + * clk_register_gpio_mux - register a gpio clock mux with the clock framework + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_names: names of this clock's parents + * @num_parents: number of parents listed in @parent_names + * @gpio: gpio number to gate this clock + * @active_low: true if gpio should be set to 0 to enable clock + * @flags: clock flags + */ +struct clk *clk_register_gpio_mux(struct device *dev, const char *name, + const char **parent_names, u8 num_parents, unsigned gpio, + bool active_low, unsigned long flags) +{ + if (num_parents != 2) { + pr_err("mux-clock %s must have 2 parents\n", name); + return ERR_PTR(-EINVAL); + } + + return clk_register_gpio(dev, name, parent_names, num_parents, + gpio, active_low, flags, &clk_gpio_mux_ops); +} +EXPORT_SYMBOL_GPL(clk_register_gpio_mux); + +#ifdef CONFIG_OF +/** + * clk_register_get() has to be delayed, because -EPROBE_DEFER + * can not be handled properly at of_clk_init() call time. + */ + +struct clk_gpio_delayed_register_data { + const char *gpio_name; + struct device_node *node; + struct mutex lock; + struct clk *clk; + struct clk *(*clk_register_get)(const char *name, + const char **parent_names, u8 num_parents, + unsigned gpio, bool active_low); +}; + +static struct clk *of_clk_gpio_delayed_register_get( + struct of_phandle_args *clkspec, void *_data) +{ + struct clk_gpio_delayed_register_data *data = _data; + struct clk *clk; + const char **parent_names; + int i, num_parents; + int gpio; + enum of_gpio_flags of_flags; + + mutex_lock(&data->lock); + + if (data->clk) { + mutex_unlock(&data->lock); + return data->clk; + } + + gpio = of_get_named_gpio_flags(data->node, data->gpio_name, 0, + &of_flags); + if (gpio < 0) { + mutex_unlock(&data->lock); + if (gpio == -EPROBE_DEFER) + pr_debug("%s: %s: GPIOs not yet available, retry later\n", + data->node->name, __func__); + else + pr_err("%s: %s: Can't get '%s' DT property\n", + data->node->name, __func__, + data->gpio_name); + return ERR_PTR(gpio); + } + + num_parents = of_clk_get_parent_count(data->node); + + parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL); + if (!parent_names) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < num_parents; i++) + parent_names[i] = of_clk_get_parent_name(data->node, i); + + clk = data->clk_register_get(data->node->name, parent_names, + num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW); + if (IS_ERR(clk)) + goto out; + + data->clk = clk; +out: + mutex_unlock(&data->lock); + kfree(parent_names); + + return clk; +} + +static struct clk *of_clk_gpio_gate_delayed_register_get(const char *name, + const char **parent_names, u8 num_parents, + unsigned gpio, bool active_low) +{ + return clk_register_gpio_gate(NULL, name, parent_names[0], + gpio, active_low, 0); +} + +static struct clk *of_clk_gpio_mux_delayed_register_get(const char *name, + const char **parent_names, u8 num_parents, unsigned gpio, + bool active_low) +{ + return clk_register_gpio_mux(NULL, name, parent_names, num_parents, + gpio, active_low, 0); +} + +static void __init of_gpio_clk_setup(struct device_node *node, + const char *gpio_name, + struct clk *(*clk_register_get)(const char *name, + const char **parent_names, u8 num_parents, + unsigned gpio, bool active_low)) +{ + struct clk_gpio_delayed_register_data *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return; + + data->node = node; + data->gpio_name = gpio_name; + data->clk_register_get = clk_register_get; + mutex_init(&data->lock); + + of_clk_add_provider(node, of_clk_gpio_delayed_register_get, data); +} + +static void __init of_gpio_gate_clk_setup(struct device_node *node) +{ + of_gpio_clk_setup(node, "enable-gpios", + of_clk_gpio_gate_delayed_register_get); +} +CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup); + +void __init of_gpio_mux_clk_setup(struct device_node *node) +{ + of_gpio_clk_setup(node, "select-gpios", + of_clk_gpio_mux_delayed_register_get); +} +CLK_OF_DECLARE(gpio_mux_clk, "gpio-mux-clock", of_gpio_mux_clk_setup); +#endif diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index b9b12a742970..3f6f7ad39490 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -268,7 +268,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) memcpy(table, stm32f42xx_gate_map, sizeof(table)); /* only bits set in table can be used as indices */ - if (WARN_ON(secondary > 8 * sizeof(table) || + if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) || 0 == (table[BIT_ULL_WORD(secondary)] & BIT_ULL_MASK(secondary)))) return -EINVAL; diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index f26b3ac36b27..4caee9356407 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c @@ -60,7 +60,6 @@ enum xgene_pll_type { struct xgene_clk_pll { struct clk_hw hw; - const char *name; void __iomem *reg; spinlock_t *lock; u32 pll_offset; @@ -75,7 +74,7 @@ static int xgene_clk_pll_is_enabled(struct clk_hw *hw) u32 data; data = xgene_clk_read(pllclk->reg + pllclk->pll_offset); - pr_debug("%s pll %s\n", pllclk->name, + pr_debug("%s pll %s\n", __clk_get_name(hw->clk), data & REGSPEC_RESET_F1_MASK ? "disabled" : "enabled"); return data & REGSPEC_RESET_F1_MASK ? 0 : 1; @@ -113,7 +112,7 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw, fref = parent_rate / nref; fvco = fref * nfb; } - pr_debug("%s pll recalc rate %ld parent %ld\n", pllclk->name, + pr_debug("%s pll recalc rate %ld parent %ld\n", __clk_get_name(hw->clk), fvco / nout, parent_rate); return fvco / nout; @@ -146,7 +145,6 @@ static struct clk *xgene_register_clk_pll(struct device *dev, init.parent_names = parent_name ? &parent_name : NULL; init.num_parents = parent_name ? 1 : 0; - apmclk->name = name; apmclk->reg = reg; apmclk->lock = lock; apmclk->pll_offset = pll_offset; @@ -210,7 +208,6 @@ struct xgene_dev_parameters { struct xgene_clk { struct clk_hw hw; - const char *name; spinlock_t *lock; struct xgene_dev_parameters param; }; @@ -228,7 +225,7 @@ static int xgene_clk_enable(struct clk_hw *hw) spin_lock_irqsave(pclk->lock, flags); if (pclk->param.csr_reg != NULL) { - pr_debug("%s clock enabled\n", pclk->name); + pr_debug("%s clock enabled\n", __clk_get_name(hw->clk)); reg = __pa(pclk->param.csr_reg); /* First enable the clock */ data = xgene_clk_read(pclk->param.csr_reg + @@ -237,7 +234,7 @@ static int xgene_clk_enable(struct clk_hw *hw) xgene_clk_write(data, pclk->param.csr_reg + pclk->param.reg_clk_offset); pr_debug("%s clock PADDR base %pa clk offset 0x%08X mask 0x%08X value 0x%08X\n", - pclk->name, ®, + __clk_get_name(hw->clk), ®, pclk->param.reg_clk_offset, pclk->param.reg_clk_mask, data); @@ -248,7 +245,7 @@ static int xgene_clk_enable(struct clk_hw *hw) xgene_clk_write(data, pclk->param.csr_reg + pclk->param.reg_csr_offset); pr_debug("%s CSR RESET PADDR base %pa csr offset 0x%08X mask 0x%08X value 0x%08X\n", - pclk->name, ®, + __clk_get_name(hw->clk), ®, pclk->param.reg_csr_offset, pclk->param.reg_csr_mask, data); } @@ -269,7 +266,7 @@ static void xgene_clk_disable(struct clk_hw *hw) spin_lock_irqsave(pclk->lock, flags); if (pclk->param.csr_reg != NULL) { - pr_debug("%s clock disabled\n", pclk->name); + pr_debug("%s clock disabled\n", __clk_get_name(hw->clk)); /* First put the CSR in reset */ data = xgene_clk_read(pclk->param.csr_reg + pclk->param.reg_csr_offset); @@ -295,10 +292,10 @@ static int xgene_clk_is_enabled(struct clk_hw *hw) u32 data = 0; if (pclk->param.csr_reg != NULL) { - pr_debug("%s clock checking\n", pclk->name); + pr_debug("%s clock checking\n", __clk_get_name(hw->clk)); data = xgene_clk_read(pclk->param.csr_reg + pclk->param.reg_clk_offset); - pr_debug("%s clock is %s\n", pclk->name, + pr_debug("%s clock is %s\n", __clk_get_name(hw->clk), data & pclk->param.reg_clk_mask ? "enabled" : "disabled"); } @@ -321,11 +318,13 @@ static unsigned long xgene_clk_recalc_rate(struct clk_hw *hw, data &= (1 << pclk->param.reg_divider_width) - 1; pr_debug("%s clock recalc rate %ld parent %ld\n", - pclk->name, parent_rate / data, parent_rate); + __clk_get_name(hw->clk), + parent_rate / data, parent_rate); + return parent_rate / data; } else { pr_debug("%s clock recalc rate %ld parent %ld\n", - pclk->name, parent_rate, parent_rate); + __clk_get_name(hw->clk), parent_rate, parent_rate); return parent_rate; } } @@ -357,7 +356,7 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate, data |= divider; xgene_clk_write(data, pclk->param.divider_reg + pclk->param.reg_divider_offset); - pr_debug("%s clock set rate %ld\n", pclk->name, + pr_debug("%s clock set rate %ld\n", __clk_get_name(hw->clk), parent_rate / divider_save); } else { divider_save = 1; @@ -419,7 +418,6 @@ static struct clk *xgene_register_clk(struct device *dev, init.parent_names = parent_name ? &parent_name : NULL; init.num_parents = parent_name ? 1 : 0; - apmclk->name = name; apmclk->lock = lock; apmclk->hw.init = &init; apmclk->param = *parameters; diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 4b9e04cdf7e8..8b6523d15fb8 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -700,6 +700,22 @@ static const struct mtk_composite peri_clks[] __initconst = { MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), }; +static struct clk_onecell_data *mt8173_top_clk_data __initdata; +static struct clk_onecell_data *mt8173_pll_clk_data __initdata; + +static void __init mtk_clk_enable_critical(void) +{ + if (!mt8173_top_clk_data || !mt8173_pll_clk_data) + return; + + clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA15PLL]); + clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA7PLL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_MEM_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_CCI400_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_RTC_SEL]); +} + static void __init mtk_topckgen_init(struct device_node *node) { struct clk_onecell_data *clk_data; @@ -712,19 +728,19 @@ static void __init mtk_topckgen_init(struct device_node *node) return; } - clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt8173_clk_lock, clk_data); - clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); + + mtk_clk_enable_critical(); } CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init); @@ -818,13 +834,13 @@ static void __init mtk_apmixedsys_init(struct device_node *node) { struct clk_onecell_data *clk_data; - clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); if (!clk_data) return; mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]); + mtk_clk_enable_critical(); } CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys", mtk_apmixedsys_init); diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c index 245d5063a385..017eede87237 100644 --- a/drivers/clk/qcom/clk-pll.c +++ b/drivers/clk/qcom/clk-pll.c @@ -292,3 +292,78 @@ void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap, clk_pll_set_fsm_mode(pll, regmap, 0); } EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp); + +static int clk_pll_sr2_enable(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + int ret; + u32 mode; + + ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &mode); + if (ret) + return ret; + + /* Disable PLL bypass mode. */ + ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL, + PLL_BYPASSNL); + if (ret) + return ret; + + /* + * H/W requires a 5us delay between disabling the bypass and + * de-asserting the reset. Delay 10us just to be safe. + */ + udelay(10); + + /* De-assert active-low PLL reset. */ + ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N, + PLL_RESET_N); + if (ret) + return ret; + + ret = wait_for_pll(pll); + if (ret) + return ret; + + /* Enable PLL output. */ + return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL, + PLL_OUTCTRL); +} + +static int +clk_pll_sr2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate) +{ + struct clk_pll *pll = to_clk_pll(hw); + const struct pll_freq_tbl *f; + bool enabled; + u32 mode; + u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N; + + f = find_freq(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + + regmap_read(pll->clkr.regmap, pll->mode_reg, &mode); + enabled = (mode & enable_mask) == enable_mask; + + if (enabled) + clk_pll_disable(hw); + + regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l); + regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m); + regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n); + + if (enabled) + clk_pll_sr2_enable(hw); + + return 0; +} + +const struct clk_ops clk_pll_sr2_ops = { + .enable = clk_pll_sr2_enable, + .disable = clk_pll_disable, + .set_rate = clk_pll_sr2_set_rate, + .recalc_rate = clk_pll_recalc_rate, + .determine_rate = clk_pll_determine_rate, +}; +EXPORT_SYMBOL_GPL(clk_pll_sr2_ops); diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h index c9c0cda306d0..ffd0c63bddbc 100644 --- a/drivers/clk/qcom/clk-pll.h +++ b/drivers/clk/qcom/clk-pll.h @@ -62,6 +62,7 @@ struct clk_pll { extern const struct clk_ops clk_pll_ops; extern const struct clk_ops clk_pll_vote_ops; +extern const struct clk_ops clk_pll_sr2_ops; #define to_clk_pll(_hw) container_of(to_clk_regmap(_hw), struct clk_pll, clkr) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index b95d17fbb8d7..92936f0912d2 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -530,19 +530,16 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate, struct clk_rcg2 *rcg = to_clk_rcg2(hw); struct freq_tbl f = *rcg->freq_tbl; const struct frac_entry *frac = frac_table_pixel; - unsigned long request, src_rate; + unsigned long request; int delta = 100000; u32 mask = BIT(rcg->hid_width) - 1; u32 hid_div; - int index = qcom_find_src_index(hw, rcg->parent_map, f.src); - struct clk *parent = clk_get_parent_by_index(hw->clk, index); for (; frac->num; frac++) { request = (rate * frac->den) / frac->num; - src_rate = __clk_round_rate(parent, request); - if ((src_rate < (request - delta)) || - (src_rate > (request + delta))) + if ((parent_rate < (request - delta)) || + (parent_rate > (request + delta))) continue; regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c index 54a756b90a37..05b7a25b80e8 100644 --- a/drivers/clk/qcom/gcc-apq8084.c +++ b/drivers/clk/qcom/gcc-apq8084.c @@ -48,7 +48,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = { { P_GPLL0, 1 } }; -static const char *gcc_xo_gpll0[] = { +static const char * const gcc_xo_gpll0[] = { "xo", "gpll0_vote", }; @@ -59,7 +59,7 @@ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = { { P_GPLL4, 5 } }; -static const char *gcc_xo_gpll0_gpll4[] = { +static const char * const gcc_xo_gpll0_gpll4[] = { "xo", "gpll0_vote", "gpll4_vote", @@ -70,7 +70,7 @@ static const struct parent_map gcc_xo_sata_asic0_map[] = { { P_SATA_ASIC0_CLK, 2 } }; -static const char *gcc_xo_sata_asic0[] = { +static const char * const gcc_xo_sata_asic0[] = { "xo", "sata_asic0_clk", }; @@ -80,7 +80,7 @@ static const struct parent_map gcc_xo_sata_rx_map[] = { { P_SATA_RX_CLK, 2} }; -static const char *gcc_xo_sata_rx[] = { +static const char * const gcc_xo_sata_rx[] = { "xo", "sata_rx_clk", }; @@ -90,7 +90,7 @@ static const struct parent_map gcc_xo_pcie_map[] = { { P_PCIE_0_1_PIPE_CLK, 2 } }; -static const char *gcc_xo_pcie[] = { +static const char * const gcc_xo_pcie[] = { "xo", "pcie_pipe", }; @@ -100,7 +100,7 @@ static const struct parent_map gcc_xo_pcie_sleep_map[] = { { P_SLEEP_CLK, 6 } }; -static const char *gcc_xo_pcie_sleep[] = { +static const char * const gcc_xo_pcie_sleep[] = { "xo", "sleep_clk_src", }; diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c index 563969942a1d..40e480220cd3 100644 --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c @@ -188,7 +188,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = { { P_PLL8, 3 } }; -static const char *gcc_pxo_pll8[] = { +static const char * const gcc_pxo_pll8[] = { "pxo", "pll8_vote", }; @@ -199,7 +199,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = { { P_CXO, 5 } }; -static const char *gcc_pxo_pll8_cxo[] = { +static const char * const gcc_pxo_pll8_cxo[] = { "pxo", "pll8_vote", "cxo", @@ -215,7 +215,7 @@ static const struct parent_map gcc_pxo_pll3_sata_map[] = { { P_PLL3, 6 } }; -static const char *gcc_pxo_pll3[] = { +static const char * const gcc_pxo_pll3[] = { "pxo", "pll3", }; @@ -226,7 +226,7 @@ static const struct parent_map gcc_pxo_pll8_pll0[] = { { P_PLL0, 2 } }; -static const char *gcc_pxo_pll8_pll0_map[] = { +static const char * const gcc_pxo_pll8_pll0_map[] = { "pxo", "pll8_vote", "pll0_vote", @@ -240,7 +240,7 @@ static const struct parent_map gcc_pxo_pll8_pll14_pll18_pll0_map[] = { { P_PLL18, 1 } }; -static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = { +static const char * const gcc_pxo_pll8_pll14_pll18_pll0[] = { "pxo", "pll8_vote", "pll0_vote", diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c index fc6b12da5b30..b02826ed770a 100644 --- a/drivers/clk/qcom/gcc-msm8660.c +++ b/drivers/clk/qcom/gcc-msm8660.c @@ -70,7 +70,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = { { P_PLL8, 3 } }; -static const char *gcc_pxo_pll8[] = { +static const char * const gcc_pxo_pll8[] = { "pxo", "pll8_vote", }; @@ -81,7 +81,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = { { P_CXO, 5 } }; -static const char *gcc_pxo_pll8_cxo[] = { +static const char * const gcc_pxo_pll8_cxo[] = { "pxo", "pll8_vote", "cxo", @@ -1917,7 +1917,7 @@ static struct clk_rcg usb_fs1_xcvr_fs_src = { } }; -static const char *usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" }; +static const char * const usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" }; static struct clk_branch usb_fs1_xcvr_fs_clk = { .halt_reg = 0x2fcc, @@ -1984,7 +1984,7 @@ static struct clk_rcg usb_fs2_xcvr_fs_src = { } }; -static const char *usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" }; +static const char * const usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" }; static struct clk_branch usb_fs2_xcvr_fs_clk = { .halt_reg = 0x2fcc, diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index c66f7bc2ae87..3bf4fb3deef6 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -51,7 +51,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = { { P_GPLL0, 1 }, }; -static const char *gcc_xo_gpll0[] = { +static const char * const gcc_xo_gpll0[] = { "xo", "gpll0_vote", }; @@ -62,7 +62,7 @@ static const struct parent_map gcc_xo_gpll0_bimc_map[] = { { P_BIMC, 2 }, }; -static const char *gcc_xo_gpll0_bimc[] = { +static const char * const gcc_xo_gpll0_bimc[] = { "xo", "gpll0_vote", "bimc_pll_vote", @@ -75,7 +75,7 @@ static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2a_map[] = { { P_GPLL2_AUX, 2 }, }; -static const char *gcc_xo_gpll0a_gpll1_gpll2a[] = { +static const char * const gcc_xo_gpll0a_gpll1_gpll2a[] = { "xo", "gpll0_vote", "gpll1_vote", @@ -88,7 +88,7 @@ static const struct parent_map gcc_xo_gpll0_gpll2_map[] = { { P_GPLL2, 2 }, }; -static const char *gcc_xo_gpll0_gpll2[] = { +static const char * const gcc_xo_gpll0_gpll2[] = { "xo", "gpll0_vote", "gpll2_vote", @@ -99,7 +99,7 @@ static const struct parent_map gcc_xo_gpll0a_map[] = { { P_GPLL0_AUX, 2 }, }; -static const char *gcc_xo_gpll0a[] = { +static const char * const gcc_xo_gpll0a[] = { "xo", "gpll0_vote", }; @@ -111,7 +111,7 @@ static const struct parent_map gcc_xo_gpll0_gpll1a_sleep_map[] = { { P_SLEEP_CLK, 6 }, }; -static const char *gcc_xo_gpll0_gpll1a_sleep[] = { +static const char * const gcc_xo_gpll0_gpll1a_sleep[] = { "xo", "gpll0_vote", "gpll1_vote", @@ -124,7 +124,7 @@ static const struct parent_map gcc_xo_gpll0_gpll1a_map[] = { { P_GPLL1_AUX, 2 }, }; -static const char *gcc_xo_gpll0_gpll1a[] = { +static const char * const gcc_xo_gpll0_gpll1a[] = { "xo", "gpll0_vote", "gpll1_vote", @@ -135,7 +135,7 @@ static const struct parent_map gcc_xo_dsibyte_map[] = { { P_DSI0_PHYPLL_BYTE, 2 }, }; -static const char *gcc_xo_dsibyte[] = { +static const char * const gcc_xo_dsibyte[] = { "xo", "dsi0pllbyte", }; @@ -146,7 +146,7 @@ static const struct parent_map gcc_xo_gpll0a_dsibyte_map[] = { { P_DSI0_PHYPLL_BYTE, 1 }, }; -static const char *gcc_xo_gpll0a_dsibyte[] = { +static const char * const gcc_xo_gpll0a_dsibyte[] = { "xo", "gpll0_vote", "dsi0pllbyte", @@ -158,7 +158,7 @@ static const struct parent_map gcc_xo_gpll0_dsiphy_map[] = { { P_DSI0_PHYPLL_DSI, 2 }, }; -static const char *gcc_xo_gpll0_dsiphy[] = { +static const char * const gcc_xo_gpll0_dsiphy[] = { "xo", "gpll0_vote", "dsi0pll", @@ -170,7 +170,7 @@ static const struct parent_map gcc_xo_gpll0a_dsiphy_map[] = { { P_DSI0_PHYPLL_DSI, 1 }, }; -static const char *gcc_xo_gpll0a_dsiphy[] = { +static const char * const gcc_xo_gpll0a_dsiphy[] = { "xo", "gpll0_vote", "dsi0pll", @@ -183,7 +183,7 @@ static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2_map[] = { { P_GPLL2, 2 }, }; -static const char *gcc_xo_gpll0a_gpll1_gpll2[] = { +static const char * const gcc_xo_gpll0a_gpll1_gpll2[] = { "xo", "gpll0_vote", "gpll1_vote", diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c index eb6a4f9fa107..aa294b1bad34 100644 --- a/drivers/clk/qcom/gcc-msm8960.c +++ b/drivers/clk/qcom/gcc-msm8960.c @@ -125,7 +125,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = { { P_PLL8, 3 } }; -static const char *gcc_pxo_pll8[] = { +static const char * const gcc_pxo_pll8[] = { "pxo", "pll8_vote", }; @@ -136,7 +136,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = { { P_CXO, 5 } }; -static const char *gcc_pxo_pll8_cxo[] = { +static const char * const gcc_pxo_pll8_cxo[] = { "pxo", "pll8_vote", "cxo", @@ -148,7 +148,7 @@ static const struct parent_map gcc_pxo_pll8_pll3_map[] = { { P_PLL3, 6 } }; -static const char *gcc_pxo_pll8_pll3[] = { +static const char * const gcc_pxo_pll8_pll3[] = { "pxo", "pll8_vote", "pll3", @@ -2085,7 +2085,7 @@ static struct clk_rcg usb_hsic_xcvr_fs_src = { } }; -static const char *usb_hsic_xcvr_fs_src_p[] = { "usb_hsic_xcvr_fs_src" }; +static const char * const usb_hsic_xcvr_fs_src_p[] = { "usb_hsic_xcvr_fs_src" }; static struct clk_branch usb_hsic_xcvr_fs_clk = { .halt_reg = 0x2fc8, @@ -2181,7 +2181,7 @@ static struct clk_rcg usb_fs1_xcvr_fs_src = { } }; -static const char *usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" }; +static const char * const usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" }; static struct clk_branch usb_fs1_xcvr_fs_clk = { .halt_reg = 0x2fcc, @@ -2248,7 +2248,7 @@ static struct clk_rcg usb_fs2_xcvr_fs_src = { } }; -static const char *usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" }; +static const char * const usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" }; static struct clk_branch usb_fs2_xcvr_fs_clk = { .halt_reg = 0x2fcc, diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index c39d09874e74..2c289702119f 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c @@ -44,7 +44,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = { { P_GPLL0, 1 } }; -static const char *gcc_xo_gpll0[] = { +static const char * const gcc_xo_gpll0[] = { "xo", "gpll0_vote", }; @@ -55,7 +55,7 @@ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = { { P_GPLL4, 5 } }; -static const char *gcc_xo_gpll0_gpll4[] = { +static const char * const gcc_xo_gpll0_gpll4[] = { "xo", "gpll0_vote", "gpll4_vote", diff --git a/drivers/clk/qcom/lcc-ipq806x.c b/drivers/clk/qcom/lcc-ipq806x.c index 47f0ac16d149..93ad42b14366 100644 --- a/drivers/clk/qcom/lcc-ipq806x.c +++ b/drivers/clk/qcom/lcc-ipq806x.c @@ -71,7 +71,7 @@ static const struct parent_map lcc_pxo_pll4_map[] = { { P_PLL4, 2 } }; -static const char *lcc_pxo_pll4[] = { +static const char * const lcc_pxo_pll4[] = { "pxo", "pll4_vote", }; @@ -146,7 +146,7 @@ static struct clk_rcg mi2s_osr_src = { }, }; -static const char *lcc_mi2s_parents[] = { +static const char * const lcc_mi2s_parents[] = { "mi2s_osr_src", }; @@ -340,7 +340,7 @@ static struct clk_rcg spdif_src = { }, }; -static const char *lcc_spdif_parents[] = { +static const char * const lcc_spdif_parents[] = { "spdif_src", }; diff --git a/drivers/clk/qcom/lcc-msm8960.c b/drivers/clk/qcom/lcc-msm8960.c index d0df9d5fc3af..ecb96c284675 100644 --- a/drivers/clk/qcom/lcc-msm8960.c +++ b/drivers/clk/qcom/lcc-msm8960.c @@ -57,7 +57,7 @@ static const struct parent_map lcc_pxo_pll4_map[] = { { P_PLL4, 2 } }; -static const char *lcc_pxo_pll4[] = { +static const char * const lcc_pxo_pll4[] = { "pxo", "pll4_vote", }; @@ -127,7 +127,7 @@ static struct clk_rcg mi2s_osr_src = { }, }; -static const char *lcc_mi2s_parents[] = { +static const char * const lcc_mi2s_parents[] = { "mi2s_osr_src", }; @@ -233,7 +233,7 @@ static struct clk_rcg prefix##_osr_src = { \ }, \ }; \ \ -static const char *lcc_##prefix##_parents[] = { \ +static const char * const lcc_##prefix##_parents[] = { \ #prefix "_osr_src", \ }; \ \ @@ -445,7 +445,7 @@ static struct clk_rcg slimbus_src = { }, }; -static const char *lcc_slimbus_parents[] = { +static const char * const lcc_slimbus_parents[] = { "slimbus_src", }; diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c index 1b17df2cb0af..f0ee6bde11af 100644 --- a/drivers/clk/qcom/mmcc-apq8084.c +++ b/drivers/clk/qcom/mmcc-apq8084.c @@ -53,7 +53,7 @@ static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = { { P_GPLL0, 5 } }; -static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = { +static const char * const mmcc_xo_mmpll0_mmpll1_gpll0[] = { "xo", "mmpll0_vote", "mmpll1_vote", @@ -69,7 +69,7 @@ static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = { { P_DSI1PLL, 3 } }; -static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = { +static const char * const mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = { "xo", "mmpll0_vote", "hdmipll", @@ -86,7 +86,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_2_gpll0_map[] = { { P_MMPLL2, 3 } }; -static const char *mmcc_xo_mmpll0_1_2_gpll0[] = { +static const char * const mmcc_xo_mmpll0_1_2_gpll0[] = { "xo", "mmpll0_vote", "mmpll1_vote", @@ -102,7 +102,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = { { P_MMPLL3, 3 } }; -static const char *mmcc_xo_mmpll0_1_3_gpll0[] = { +static const char * const mmcc_xo_mmpll0_1_3_gpll0[] = { "xo", "mmpll0_vote", "mmpll1_vote", @@ -119,7 +119,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = { { P_DSI1PLL, 2 } }; -static const char *mmcc_xo_dsi_hdmi_edp[] = { +static const char * const mmcc_xo_dsi_hdmi_edp[] = { "xo", "edp_link_clk", "hdmipll", @@ -137,7 +137,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = { { P_DSI1PLL, 2 } }; -static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = { +static const char * const mmcc_xo_dsi_hdmi_edp_gpll0[] = { "xo", "edp_link_clk", "hdmipll", @@ -155,7 +155,7 @@ static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = { { P_DSI1PLL_BYTE, 2 } }; -static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = { +static const char * const mmcc_xo_dsibyte_hdmi_edp_gpll0[] = { "xo", "edp_link_clk", "hdmipll", @@ -172,7 +172,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll0_map[] = { { P_MMPLL4, 3 } }; -static const char *mmcc_xo_mmpll0_1_4_gpll0[] = { +static const char * const mmcc_xo_mmpll0_1_4_gpll0[] = { "xo", "mmpll0", "mmpll1", @@ -189,7 +189,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll1_0_map[] = { { P_GPLL1, 4 } }; -static const char *mmcc_xo_mmpll0_1_4_gpll1_0[] = { +static const char * const mmcc_xo_mmpll0_1_4_gpll1_0[] = { "xo", "mmpll0", "mmpll1", @@ -208,7 +208,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map[] = { { P_MMSLEEP, 6 } }; -static const char *mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = { +static const char * const mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = { "xo", "mmpll0", "mmpll1", diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c index 9711bca9cc06..54aadbcda61a 100644 --- a/drivers/clk/qcom/mmcc-msm8960.c +++ b/drivers/clk/qcom/mmcc-msm8960.c @@ -50,7 +50,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_map[] = { { P_PLL2, 1 } }; -static const char *mmcc_pxo_pll8_pll2[] = { +static const char * const mmcc_pxo_pll8_pll2[] = { "pxo", "pll8_vote", "pll2", @@ -63,7 +63,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_pll3_map[] = { { P_PLL3, 3 } }; -static const char *mmcc_pxo_pll8_pll2_pll15[] = { +static const char * const mmcc_pxo_pll8_pll2_pll15[] = { "pxo", "pll8_vote", "pll2", @@ -77,7 +77,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_pll15_map[] = { { P_PLL15, 3 } }; -static const char *mmcc_pxo_pll8_pll2_pll3[] = { +static const char * const mmcc_pxo_pll8_pll2_pll3[] = { "pxo", "pll8_vote", "pll2", @@ -579,7 +579,7 @@ static const struct clk_ops clk_ops_pix_rdi = { .determine_rate = __clk_mux_determine_rate, }; -static const char *pix_rdi_parents[] = { +static const char * const pix_rdi_parents[] = { "csi0_clk", "csi1_clk", "csi2_clk", @@ -709,7 +709,7 @@ static struct clk_rcg csiphytimer_src = { }, }; -static const char *csixphy_timer_src[] = { "csiphytimer_src" }; +static const char * const csixphy_timer_src[] = { "csiphytimer_src" }; static struct clk_branch csiphy0_timer_clk = { .halt_reg = 0x01e8, @@ -1385,7 +1385,7 @@ static const struct parent_map mmcc_pxo_hdmi_map[] = { { P_HDMI_PLL, 3 } }; -static const char *mmcc_pxo_hdmi[] = { +static const char * const mmcc_pxo_hdmi[] = { "pxo", "hdmi_pll", }; @@ -1428,7 +1428,7 @@ static struct clk_rcg tv_src = { }, }; -static const char *tv_src_name[] = { "tv_src" }; +static const char * const tv_src_name[] = { "tv_src" }; static struct clk_branch tv_enc_clk = { .halt_reg = 0x01d4, diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c index 07f4cc159ad3..0987bf443e1f 100644 --- a/drivers/clk/qcom/mmcc-msm8974.c +++ b/drivers/clk/qcom/mmcc-msm8974.c @@ -56,7 +56,7 @@ static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = { { P_GPLL0, 5 } }; -static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = { +static const char * const mmcc_xo_mmpll0_mmpll1_gpll0[] = { "xo", "mmpll0_vote", "mmpll1_vote", @@ -72,7 +72,7 @@ static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = { { P_DSI1PLL, 3 } }; -static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = { +static const char * const mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = { "xo", "mmpll0_vote", "hdmipll", @@ -89,7 +89,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_2_gpll0_map[] = { { P_MMPLL2, 3 } }; -static const char *mmcc_xo_mmpll0_1_2_gpll0[] = { +static const char * const mmcc_xo_mmpll0_1_2_gpll0[] = { "xo", "mmpll0_vote", "mmpll1_vote", @@ -105,7 +105,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = { { P_MMPLL3, 3 } }; -static const char *mmcc_xo_mmpll0_1_3_gpll0[] = { +static const char * const mmcc_xo_mmpll0_1_3_gpll0[] = { "xo", "mmpll0_vote", "mmpll1_vote", @@ -121,7 +121,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_gpll1_0_map[] = { { P_GPLL1, 4 } }; -static const char *mmcc_xo_mmpll0_1_gpll1_0[] = { +static const char * const mmcc_xo_mmpll0_1_gpll1_0[] = { "xo", "mmpll0_vote", "mmpll1_vote", @@ -138,7 +138,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = { { P_DSI1PLL, 2 } }; -static const char *mmcc_xo_dsi_hdmi_edp[] = { +static const char * const mmcc_xo_dsi_hdmi_edp[] = { "xo", "edp_link_clk", "hdmipll", @@ -156,7 +156,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = { { P_DSI1PLL, 2 } }; -static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = { +static const char * const mmcc_xo_dsi_hdmi_edp_gpll0[] = { "xo", "edp_link_clk", "hdmipll", @@ -174,7 +174,7 @@ static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = { { P_DSI1PLL_BYTE, 2 } }; -static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = { +static const char * const mmcc_xo_dsibyte_hdmi_edp_gpll0[] = { "xo", "edp_link_clk", "hdmipll", diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 657ca14ba709..8dd8cce27361 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c @@ -190,7 +190,7 @@ static struct clk *clk_register_flexgen(const char *name, init.name = name; init.ops = &flexgen_ops; - init.flags = CLK_IS_BASIC | flexgen_flags; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE | flexgen_flags; init.parent_names = parent_names; init.num_parents = num_parents; @@ -303,6 +303,8 @@ static void __init st_of_flexgen_setup(struct device_node *np) if (!rlock) goto err; + spin_lock_init(rlock); + for (i = 0; i < clk_data->clk_num; i++) { struct clk *clk; const char *clk_name; diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index e94197f04b0b..99c98c15d4a4 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -489,7 +489,7 @@ static int quadfs_pll_is_enabled(struct clk_hw *hw) struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); u32 npda = CLKGEN_READ(pll, npda); - return !!npda; + return pll->data->powerup_polarity ? !npda : !!npda; } static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs, @@ -635,7 +635,7 @@ static struct clk * __init st_clk_register_quadfs_pll( init.name = name; init.ops = quadfs->pll_ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = &parent_name; init.num_parents = 1; @@ -774,7 +774,7 @@ static void quadfs_fsynth_disable(struct clk_hw *hw) if (fs->lock) spin_lock_irqsave(fs->lock, flags); - CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity); + CLKGEN_WRITE(fs, nsb[fs->chan], fs->data->standby_polarity); if (fs->lock) spin_unlock_irqrestore(fs->lock, flags); @@ -1082,10 +1082,6 @@ static const struct of_device_id quadfs_of_match[] = { .compatible = "st,stih407-quadfs660-D", .data = &st_fs660c32_D_407 }, - { - .compatible = "st,stih407-quadfs660-D", - .data = (void *)&st_fs660c32_D_407 - }, {} }; diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c index 4fbe6e099587..717c4a91a17b 100644 --- a/drivers/clk/st/clkgen-mux.c +++ b/drivers/clk/st/clkgen-mux.c @@ -237,7 +237,7 @@ static struct clk *clk_register_genamux(const char *name, init.name = name; init.ops = &clkgena_divmux_ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = parent_names; init.num_parents = num_parents; @@ -513,7 +513,8 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np) 0, &clk_name)) return; - clk = clk_register_divider_table(NULL, clk_name, parent_name, 0, + clk = clk_register_divider_table(NULL, clk_name, parent_name, + CLK_GET_RATE_NOCACHE, reg + data->offset, data->shift, 1, 0, data->table, NULL); if (IS_ERR(clk)) @@ -582,7 +583,7 @@ static struct clkgen_mux_data stih416_a9_mux_data = { }; static struct clkgen_mux_data stih407_a9_mux_data = { .offset = 0x1a4, - .shift = 1, + .shift = 0, .width = 2, }; @@ -786,7 +787,8 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np) &mux->hw, &clk_mux_ops, &div->hw, &clk_divider_ops, &gate->hw, &clk_gate_ops, - data->clk_flags); + data->clk_flags | + CLK_GET_RATE_NOCACHE); if (IS_ERR(clk)) { kfree(gate); kfree(div); diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 106532207213..72d1c27eaffa 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -406,7 +406,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name, init.name = clk_name; init.ops = pll_data->ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = &parent_name; init.num_parents = 1; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 78842f46f152..823d7f70878e 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -550,6 +550,23 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name, void of_gpio_clk_gate_setup(struct device_node *node); /** + * struct clk_gpio_mux - gpio controlled clock multiplexer + * + * @hw: see struct clk_gpio + * @gpiod: gpio descriptor to select the parent of this clock multiplexer + * + * Clock with a gpio control for selecting the parent clock. + * Implements .get_parent, .set_parent and .determine_rate + */ + +extern const struct clk_ops clk_gpio_mux_ops; +struct clk *clk_register_gpio_mux(struct device *dev, const char *name, + const char **parent_names, u8 num_parents, unsigned gpio, + bool active_low, unsigned long flags); + +void of_gpio_mux_clk_setup(struct device_node *node); + +/** * clk_register - allocate a new clock, register it and return an opaque cookie * @dev: device that is registering this clock * @hw: link to hardware-specific clock data |