From a9d3e8832dfd73afa9d7cb492abb188f83740061 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Mon, 3 Dec 2018 11:15:28 +0100 Subject: clk: regmap: support the clk-regmap wrapper for all devices The meson clk-regmap wrapper api has no dependencies to any architecture code, so we can make it public. This allows regmap devices to use the common clk framework as well. Signed-off-by: Marco Felsch --- drivers/clk/Kconfig | 9 ++ drivers/clk/Makefile | 1 + drivers/clk/clk-regmap.c | 177 ++++++++++++++++++++++++++++++++++++++++ drivers/clk/meson/Kconfig | 8 +- drivers/clk/meson/Makefile | 1 - drivers/clk/meson/axg-aoclk.c | 2 +- drivers/clk/meson/clk-regmap.c | 177 ---------------------------------------- drivers/clk/meson/clk-regmap.h | 113 ------------------------- drivers/clk/meson/clkc.h | 2 +- drivers/clk/meson/gxbb-aoclk.c | 2 +- drivers/clk/meson/gxbb.c | 2 +- drivers/clk/meson/meson-aoclk.c | 2 +- drivers/clk/meson/meson-aoclk.h | 2 +- drivers/clk/meson/meson8b.c | 2 +- include/linux/clk-regmap.h | 113 +++++++++++++++++++++++++ 15 files changed, 309 insertions(+), 304 deletions(-) create mode 100644 drivers/clk/clk-regmap.c delete mode 100644 drivers/clk/meson/clk-regmap.c delete mode 100644 drivers/clk/meson/clk-regmap.h create mode 100644 include/linux/clk-regmap.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 81cdb4eaca07f..be2f4cfc05bb5 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -22,6 +22,15 @@ config COMMON_CLK menu "Common Clock Framework" depends on COMMON_CLK +config COMMON_CLK_REGMAP + bool + select REGMAP + help + This is a wrapper API around the common clock framework, so + you can use the common clock framework on devices supporting + only the regmap interface. This is useful for external devices + such as several I2C devices which has complex clock structures too. + config COMMON_CLK_WM831X tristate "Clock driver for WM831x/2x PMICs" depends on MFD_WM831X diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 72be7a38cff1e..0bcfc94ed4875 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -12,6 +12,7 @@ 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.o +obj-$(CONFIG_COMMON_CLK_REGMAP) += clk-regmap.o ifeq ($(CONFIG_OF), y) obj-$(CONFIG_COMMON_CLK) += clk-conf.o endif diff --git a/drivers/clk/clk-regmap.c b/drivers/clk/clk-regmap.c new file mode 100644 index 0000000000000..aabdf81c3eeb2 --- /dev/null +++ b/drivers/clk/clk-regmap.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 BayLibre, SAS. + * Author: Jerome Brunet + */ + +#include + +static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk); + int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; + + set ^= enable; + + return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx), + set ? BIT(gate->bit_idx) : 0); +} + +static int clk_regmap_gate_enable(struct clk_hw *hw) +{ + return clk_regmap_gate_endisable(hw, 1); +} + +static void clk_regmap_gate_disable(struct clk_hw *hw) +{ + clk_regmap_gate_endisable(hw, 0); +} + +static int clk_regmap_gate_is_enabled(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk); + unsigned int val; + + regmap_read(clk->map, gate->offset, &val); + if (gate->flags & CLK_GATE_SET_TO_DISABLE) + val ^= BIT(gate->bit_idx); + + val &= BIT(gate->bit_idx); + + return val ? 1 : 0; +} + +const struct clk_ops clk_regmap_gate_ops = { + .enable = clk_regmap_gate_enable, + .disable = clk_regmap_gate_disable, + .is_enabled = clk_regmap_gate_is_enabled, +}; +EXPORT_SYMBOL_GPL(clk_regmap_gate_ops); + +static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); + unsigned int val; + int ret; + + ret = regmap_read(clk->map, div->offset, &val); + if (ret) + /* Gives a hint that something is wrong */ + return 0; + + val >>= div->shift; + val &= clk_div_mask(div->width); + return divider_recalc_rate(hw, prate, val, div->table, div->flags, + div->width); +} + +static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); + unsigned int val; + int ret; + + /* if read only, just return current value */ + if (div->flags & CLK_DIVIDER_READ_ONLY) { + ret = regmap_read(clk->map, div->offset, &val); + if (ret) + /* Gives a hint that something is wrong */ + return 0; + + val >>= div->shift; + val &= clk_div_mask(div->width); + + return divider_ro_round_rate(hw, rate, prate, div->table, + div->width, div->flags, val); + } + + return divider_round_rate(hw, rate, prate, div->table, div->width, + div->flags); +} + +static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); + unsigned int val; + int ret; + + ret = divider_get_val(rate, parent_rate, div->table, div->width, + div->flags); + if (ret < 0) + return ret; + + val = (unsigned int)ret << div->shift; + return regmap_update_bits(clk->map, div->offset, + clk_div_mask(div->width) << div->shift, val); +}; + +/* Would prefer clk_regmap_div_ro_ops but clashes with qcom */ + +const struct clk_ops clk_regmap_divider_ops = { + .recalc_rate = clk_regmap_div_recalc_rate, + .round_rate = clk_regmap_div_round_rate, + .set_rate = clk_regmap_div_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_regmap_divider_ops); + +const struct clk_ops clk_regmap_divider_ro_ops = { + .recalc_rate = clk_regmap_div_recalc_rate, + .round_rate = clk_regmap_div_round_rate, +}; +EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops); + +static u8 clk_regmap_mux_get_parent(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk); + unsigned int val; + int ret; + + ret = regmap_read(clk->map, mux->offset, &val); + if (ret) + return ret; + + val >>= mux->shift; + val &= mux->mask; + return clk_mux_val_to_index(hw, mux->table, mux->flags, val); +} + +static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk); + unsigned int val = clk_mux_index_to_val(mux->table, mux->flags, index); + + return regmap_update_bits(clk->map, mux->offset, + mux->mask << mux->shift, + val << mux->shift); +} + +static int clk_regmap_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk); + + return clk_mux_determine_rate_flags(hw, req, mux->flags); +} + +const struct clk_ops clk_regmap_mux_ops = { + .get_parent = clk_regmap_mux_get_parent, + .set_parent = clk_regmap_mux_set_parent, + .determine_rate = clk_regmap_mux_determine_rate, +}; +EXPORT_SYMBOL_GPL(clk_regmap_mux_ops); + +const struct clk_ops clk_regmap_mux_ro_ops = { + .get_parent = clk_regmap_mux_get_parent, +}; +EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops); diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index efaa70f682b45..9c7f3042c933c 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -1,7 +1,7 @@ config COMMON_CLK_AMLOGIC bool depends on ARCH_MESON || COMPILE_TEST - select COMMON_CLK_REGMAP_MESON + select COMMON_CLK_REGMAP config COMMON_CLK_AMLOGIC_AUDIO bool @@ -12,13 +12,9 @@ config COMMON_CLK_MESON_AO bool depends on OF depends on ARCH_MESON || COMPILE_TEST - select COMMON_CLK_REGMAP_MESON + select COMMON_CLK_REGMAP select RESET_CONTROLLER -config COMMON_CLK_REGMAP_MESON - bool - select REGMAP - config COMMON_CLK_MESON8B bool select COMMON_CLK_AMLOGIC diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 72ec8c40d848d..5e18738d0accb 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -9,4 +9,3 @@ obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o -obj-$(CONFIG_COMMON_CLK_REGMAP_MESON) += clk-regmap.o diff --git a/drivers/clk/meson/axg-aoclk.c b/drivers/clk/meson/axg-aoclk.c index 29e0885423871..f91898e9472f0 100644 --- a/drivers/clk/meson/axg-aoclk.c +++ b/drivers/clk/meson/axg-aoclk.c @@ -9,10 +9,10 @@ * Author: Qiufang Dai */ #include +#include #include #include #include -#include "clk-regmap.h" #include "meson-aoclk.h" #include "axg-aoclk.h" diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c deleted file mode 100644 index 305ee307c003b..0000000000000 --- a/drivers/clk/meson/clk-regmap.c +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2018 BayLibre, SAS. - * Author: Jerome Brunet - */ - -#include "clk-regmap.h" - -static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk); - int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; - - set ^= enable; - - return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx), - set ? BIT(gate->bit_idx) : 0); -} - -static int clk_regmap_gate_enable(struct clk_hw *hw) -{ - return clk_regmap_gate_endisable(hw, 1); -} - -static void clk_regmap_gate_disable(struct clk_hw *hw) -{ - clk_regmap_gate_endisable(hw, 0); -} - -static int clk_regmap_gate_is_enabled(struct clk_hw *hw) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk); - unsigned int val; - - regmap_read(clk->map, gate->offset, &val); - if (gate->flags & CLK_GATE_SET_TO_DISABLE) - val ^= BIT(gate->bit_idx); - - val &= BIT(gate->bit_idx); - - return val ? 1 : 0; -} - -const struct clk_ops clk_regmap_gate_ops = { - .enable = clk_regmap_gate_enable, - .disable = clk_regmap_gate_disable, - .is_enabled = clk_regmap_gate_is_enabled, -}; -EXPORT_SYMBOL_GPL(clk_regmap_gate_ops); - -static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); - unsigned int val; - int ret; - - ret = regmap_read(clk->map, div->offset, &val); - if (ret) - /* Gives a hint that something is wrong */ - return 0; - - val >>= div->shift; - val &= clk_div_mask(div->width); - return divider_recalc_rate(hw, prate, val, div->table, div->flags, - div->width); -} - -static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); - unsigned int val; - int ret; - - /* if read only, just return current value */ - if (div->flags & CLK_DIVIDER_READ_ONLY) { - ret = regmap_read(clk->map, div->offset, &val); - if (ret) - /* Gives a hint that something is wrong */ - return 0; - - val >>= div->shift; - val &= clk_div_mask(div->width); - - return divider_ro_round_rate(hw, rate, prate, div->table, - div->width, div->flags, val); - } - - return divider_round_rate(hw, rate, prate, div->table, div->width, - div->flags); -} - -static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); - unsigned int val; - int ret; - - ret = divider_get_val(rate, parent_rate, div->table, div->width, - div->flags); - if (ret < 0) - return ret; - - val = (unsigned int)ret << div->shift; - return regmap_update_bits(clk->map, div->offset, - clk_div_mask(div->width) << div->shift, val); -}; - -/* Would prefer clk_regmap_div_ro_ops but clashes with qcom */ - -const struct clk_ops clk_regmap_divider_ops = { - .recalc_rate = clk_regmap_div_recalc_rate, - .round_rate = clk_regmap_div_round_rate, - .set_rate = clk_regmap_div_set_rate, -}; -EXPORT_SYMBOL_GPL(clk_regmap_divider_ops); - -const struct clk_ops clk_regmap_divider_ro_ops = { - .recalc_rate = clk_regmap_div_recalc_rate, - .round_rate = clk_regmap_div_round_rate, -}; -EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops); - -static u8 clk_regmap_mux_get_parent(struct clk_hw *hw) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk); - unsigned int val; - int ret; - - ret = regmap_read(clk->map, mux->offset, &val); - if (ret) - return ret; - - val >>= mux->shift; - val &= mux->mask; - return clk_mux_val_to_index(hw, mux->table, mux->flags, val); -} - -static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk); - unsigned int val = clk_mux_index_to_val(mux->table, mux->flags, index); - - return regmap_update_bits(clk->map, mux->offset, - mux->mask << mux->shift, - val << mux->shift); -} - -static int clk_regmap_mux_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - struct clk_regmap *clk = to_clk_regmap(hw); - struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk); - - return clk_mux_determine_rate_flags(hw, req, mux->flags); -} - -const struct clk_ops clk_regmap_mux_ops = { - .get_parent = clk_regmap_mux_get_parent, - .set_parent = clk_regmap_mux_set_parent, - .determine_rate = clk_regmap_mux_determine_rate, -}; -EXPORT_SYMBOL_GPL(clk_regmap_mux_ops); - -const struct clk_ops clk_regmap_mux_ro_ops = { - .get_parent = clk_regmap_mux_get_parent, -}; -EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops); diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h deleted file mode 100644 index ed2d4348dbe28..0000000000000 --- a/drivers/clk/meson/clk-regmap.h +++ /dev/null @@ -1,113 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2018 BayLibre, SAS. - * Author: Jerome Brunet - */ - -#ifndef __CLK_REGMAP_H -#define __CLK_REGMAP_H - -#include -#include - -/** - * struct clk_regmap - regmap backed clock - * - * @hw: handle between common and hardware-specific interfaces - * @map: pointer to the regmap structure controlling the clock - * @data: data specific to the clock type - * - * Clock which is controlled by regmap backed registers. The actual type of - * of the clock is controlled by the clock_ops and data. - */ -struct clk_regmap { - struct clk_hw hw; - struct regmap *map; - void *data; -}; - -#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw) - -/** - * struct clk_regmap_gate_data - regmap backed gate specific data - * - * @offset: offset of the register controlling gate - * @bit_idx: single bit controlling gate - * @flags: hardware-specific flags - * - * Flags: - * Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored - */ -struct clk_regmap_gate_data { - unsigned int offset; - u8 bit_idx; - u8 flags; -}; - -static inline struct clk_regmap_gate_data * -clk_get_regmap_gate_data(struct clk_regmap *clk) -{ - return (struct clk_regmap_gate_data *)clk->data; -} - -extern const struct clk_ops clk_regmap_gate_ops; - -/** - * struct clk_regmap_div_data - regmap backed adjustable divider specific data - * - * @offset: offset of the register controlling the divider - * @shift: shift to the divider bit field - * @width: width of the divider bit field - * @table: array of value/divider pairs, last entry should have div = 0 - * - * Flags: - * Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored - */ -struct clk_regmap_div_data { - unsigned int offset; - u8 shift; - u8 width; - u8 flags; - const struct clk_div_table *table; -}; - -static inline struct clk_regmap_div_data * -clk_get_regmap_div_data(struct clk_regmap *clk) -{ - return (struct clk_regmap_div_data *)clk->data; -} - -extern const struct clk_ops clk_regmap_divider_ops; -extern const struct clk_ops clk_regmap_divider_ro_ops; - -/** - * struct clk_regmap_mux_data - regmap backed multiplexer clock specific data - * - * @hw: handle between common and hardware-specific interfaces - * @offset: offset of theregister controlling multiplexer - * @table: array of parent indexed register values - * @shift: shift to multiplexer bit field - * @mask: mask of mutliplexer bit field - * @flags: hardware-specific flags - * - * Flags: - * Same as clk_divider except CLK_MUX_HIWORD_MASK which is ignored - */ -struct clk_regmap_mux_data { - unsigned int offset; - u32 *table; - u32 mask; - u8 shift; - u8 flags; -}; - -static inline struct clk_regmap_mux_data * -clk_get_regmap_mux_data(struct clk_regmap *clk) -{ - return (struct clk_regmap_mux_data *)clk->data; -} - -extern const struct clk_ops clk_regmap_mux_ops; -extern const struct clk_ops clk_regmap_mux_ro_ops; - -#endif /* __CLK_REGMAP_H */ diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 6b96d55c047d6..92fb237dccce9 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -8,7 +8,7 @@ #define __CLKC_H #include -#include "clk-regmap.h" +#include #define PMASK(width) GENMASK(width - 1, 0) #define SETPMASK(width, shift) GENMASK(shift + width - 1, shift) diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c index 42ed61d3c3fba..5283d0491acbb 100644 --- a/drivers/clk/meson/gxbb-aoclk.c +++ b/drivers/clk/meson/gxbb-aoclk.c @@ -3,9 +3,9 @@ * Copyright (c) 2016 BayLibre, SAS. * Author: Neil Armstrong */ +#include #include #include -#include "clk-regmap.h" #include "meson-aoclk.h" #include "gxbb-aoclk.h" diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 9309cfaaa464e..8db60e0570945 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -14,7 +15,6 @@ #include "clkc.h" #include "gxbb.h" -#include "clk-regmap.h" static DEFINE_SPINLOCK(meson_clk_lock); diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c index f965845917e34..ccf0390912e4e 100644 --- a/drivers/clk/meson/meson-aoclk.c +++ b/drivers/clk/meson/meson-aoclk.c @@ -10,11 +10,11 @@ * Author: Yixun Lan */ +#include #include #include #include #include -#include "clk-regmap.h" #include "meson-aoclk.h" static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev, diff --git a/drivers/clk/meson/meson-aoclk.h b/drivers/clk/meson/meson-aoclk.h index ab2819e889228..3051da204eb13 100644 --- a/drivers/clk/meson/meson-aoclk.h +++ b/drivers/clk/meson/meson-aoclk.h @@ -11,9 +11,9 @@ #ifndef __MESON_AOCLK_H__ #define __MESON_AOCLK_H__ +#include #include #include -#include "clk-regmap.h" struct meson_aoclk_data { const unsigned int reset_reg; diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 346b9e165b7a9..3a5c66eeff23b 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -17,7 +18,6 @@ #include "clkc.h" #include "meson8b.h" -#include "clk-regmap.h" static DEFINE_SPINLOCK(meson_clk_lock); diff --git a/include/linux/clk-regmap.h b/include/linux/clk-regmap.h new file mode 100644 index 0000000000000..ed2d4348dbe28 --- /dev/null +++ b/include/linux/clk-regmap.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 BayLibre, SAS. + * Author: Jerome Brunet + */ + +#ifndef __CLK_REGMAP_H +#define __CLK_REGMAP_H + +#include +#include + +/** + * struct clk_regmap - regmap backed clock + * + * @hw: handle between common and hardware-specific interfaces + * @map: pointer to the regmap structure controlling the clock + * @data: data specific to the clock type + * + * Clock which is controlled by regmap backed registers. The actual type of + * of the clock is controlled by the clock_ops and data. + */ +struct clk_regmap { + struct clk_hw hw; + struct regmap *map; + void *data; +}; + +#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw) + +/** + * struct clk_regmap_gate_data - regmap backed gate specific data + * + * @offset: offset of the register controlling gate + * @bit_idx: single bit controlling gate + * @flags: hardware-specific flags + * + * Flags: + * Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored + */ +struct clk_regmap_gate_data { + unsigned int offset; + u8 bit_idx; + u8 flags; +}; + +static inline struct clk_regmap_gate_data * +clk_get_regmap_gate_data(struct clk_regmap *clk) +{ + return (struct clk_regmap_gate_data *)clk->data; +} + +extern const struct clk_ops clk_regmap_gate_ops; + +/** + * struct clk_regmap_div_data - regmap backed adjustable divider specific data + * + * @offset: offset of the register controlling the divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @table: array of value/divider pairs, last entry should have div = 0 + * + * Flags: + * Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored + */ +struct clk_regmap_div_data { + unsigned int offset; + u8 shift; + u8 width; + u8 flags; + const struct clk_div_table *table; +}; + +static inline struct clk_regmap_div_data * +clk_get_regmap_div_data(struct clk_regmap *clk) +{ + return (struct clk_regmap_div_data *)clk->data; +} + +extern const struct clk_ops clk_regmap_divider_ops; +extern const struct clk_ops clk_regmap_divider_ro_ops; + +/** + * struct clk_regmap_mux_data - regmap backed multiplexer clock specific data + * + * @hw: handle between common and hardware-specific interfaces + * @offset: offset of theregister controlling multiplexer + * @table: array of parent indexed register values + * @shift: shift to multiplexer bit field + * @mask: mask of mutliplexer bit field + * @flags: hardware-specific flags + * + * Flags: + * Same as clk_divider except CLK_MUX_HIWORD_MASK which is ignored + */ +struct clk_regmap_mux_data { + unsigned int offset; + u32 *table; + u32 mask; + u8 shift; + u8 flags; +}; + +static inline struct clk_regmap_mux_data * +clk_get_regmap_mux_data(struct clk_regmap *clk) +{ + return (struct clk_regmap_mux_data *)clk->data; +} + +extern const struct clk_ops clk_regmap_mux_ops; +extern const struct clk_ops clk_regmap_mux_ro_ops; + +#endif /* __CLK_REGMAP_H */ -- cgit v1.2.3