diff options
Diffstat (limited to 'drivers/clk/stm32/clk-stm32-core.h')
-rw-r--r-- | drivers/clk/stm32/clk-stm32-core.h | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/drivers/clk/stm32/clk-stm32-core.h b/drivers/clk/stm32/clk-stm32-core.h new file mode 100644 index 000000000..76cffda02 --- /dev/null +++ b/drivers/clk/stm32/clk-stm32-core.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics. + */ + +#include <linux/clk-provider.h> + +struct stm32_rcc_match_data; + +struct stm32_mux_cfg { + u16 offset; + u8 shift; + u8 width; + u8 flags; + u32 *table; + u8 ready; +}; + +struct stm32_gate_cfg { + u16 offset; + u8 bit_idx; + u8 set_clr; +}; + +struct stm32_div_cfg { + u16 offset; + u8 shift; + u8 width; + u8 flags; + u8 ready; + const struct clk_div_table *table; +}; + +struct stm32_composite_cfg { + int mux; + int gate; + int div; +}; + +#define NO_ID 0xFFFFFFFF + +#define NO_STM32_MUX 0xFFFF +#define NO_STM32_DIV 0xFFFF +#define NO_STM32_GATE 0xFFFF + +struct clock_config { + unsigned long id; + int sec_id; + void *clock_cfg; + + struct clk_hw *(*func)(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); +}; + +struct clk_stm32_clock_data { + u16 *gate_cpt; + const struct stm32_gate_cfg *gates; + const struct stm32_mux_cfg *muxes; + const struct stm32_div_cfg *dividers; + struct clk_hw *(*is_multi_mux)(struct clk_hw *hw); +}; + +struct stm32_rcc_match_data { + struct clk_hw_onecell_data *hw_clks; + unsigned int num_clocks; + const struct clock_config *tab_clocks; + unsigned int maxbinding; + struct clk_stm32_clock_data *clock_data; + u32 clear_offset; + int (*check_security)(void __iomem *base, + const struct clock_config *cfg); + int (*multi_mux)(void __iomem *base, const struct clock_config *cfg); +}; + +int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match, + void __iomem *base); + +int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, + void __iomem *base); + +/* MUX define */ +#define MUX_NO_RDY 0xFF +#define MUX_SAFE BIT(7) + +/* DIV define */ +#define DIV_NO_RDY 0xFF + +/* Definition of clock structure */ +struct clk_stm32_mux { + u16 mux_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_mux(_hw) container_of(_hw, struct clk_stm32_mux, hw) + +struct clk_stm32_gate { + u16 gate_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_gate(_hw) container_of(_hw, struct clk_stm32_gate, hw) + +struct clk_stm32_div { + u16 div_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_divider(_hw) container_of(_hw, struct clk_stm32_div, hw) + +struct clk_stm32_composite { + u16 gate_id; + u16 mux_id; + u16 div_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_composite(_hw) container_of(_hw, struct clk_stm32_composite, hw) + +/* Clock operators */ +extern const struct clk_ops clk_stm32_mux_ops; +extern const struct clk_ops clk_stm32_gate_ops; +extern const struct clk_ops clk_stm32_divider_ops; +extern const struct clk_ops clk_stm32_composite_ops; + +/* Clock registering */ +struct clk_hw *clk_stm32_mux_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + +struct clk_hw *clk_stm32_gate_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + +struct clk_hw *clk_stm32_div_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + +struct clk_hw *clk_stm32_composite_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + +#define STM32_CLOCK_CFG(_binding, _clk, _sec_id, _struct, _register)\ +{\ + .id = (_binding),\ + .sec_id = (_sec_id),\ + .clock_cfg = (_struct) {_clk},\ + .func = (_register),\ +} + +#define STM32_MUX_CFG(_binding, _clk, _sec_id)\ + STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_mux *,\ + &clk_stm32_mux_register) + +#define STM32_GATE_CFG(_binding, _clk, _sec_id)\ + STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_gate *,\ + &clk_stm32_gate_register) + +#define STM32_DIV_CFG(_binding, _clk, _sec_id)\ + STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_div *,\ + &clk_stm32_div_register) + +#define STM32_COMPOSITE_CFG(_binding, _clk, _sec_id)\ + STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_composite *,\ + &clk_stm32_composite_register) |