1637cee5fSGabriel Fernandez /* SPDX-License-Identifier: GPL-2.0 */ 2637cee5fSGabriel Fernandez /* 3637cee5fSGabriel Fernandez * Copyright (C) STMicroelectronics 2022 - All Rights Reserved 4637cee5fSGabriel Fernandez * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics. 5637cee5fSGabriel Fernandez */ 6637cee5fSGabriel Fernandez 7637cee5fSGabriel Fernandez #include <linux/clk-provider.h> 8637cee5fSGabriel Fernandez 9637cee5fSGabriel Fernandez struct stm32_rcc_match_data; 10637cee5fSGabriel Fernandez 11637cee5fSGabriel Fernandez struct stm32_mux_cfg { 12637cee5fSGabriel Fernandez u16 offset; 13637cee5fSGabriel Fernandez u8 shift; 14637cee5fSGabriel Fernandez u8 width; 15637cee5fSGabriel Fernandez u8 flags; 16637cee5fSGabriel Fernandez u32 *table; 17637cee5fSGabriel Fernandez u8 ready; 18637cee5fSGabriel Fernandez }; 19637cee5fSGabriel Fernandez 20637cee5fSGabriel Fernandez struct stm32_gate_cfg { 21637cee5fSGabriel Fernandez u16 offset; 22637cee5fSGabriel Fernandez u8 bit_idx; 23637cee5fSGabriel Fernandez u8 set_clr; 24637cee5fSGabriel Fernandez }; 25637cee5fSGabriel Fernandez 26637cee5fSGabriel Fernandez struct stm32_div_cfg { 27637cee5fSGabriel Fernandez u16 offset; 28637cee5fSGabriel Fernandez u8 shift; 29637cee5fSGabriel Fernandez u8 width; 30637cee5fSGabriel Fernandez u8 flags; 31637cee5fSGabriel Fernandez u8 ready; 32637cee5fSGabriel Fernandez const struct clk_div_table *table; 33637cee5fSGabriel Fernandez }; 34637cee5fSGabriel Fernandez 35637cee5fSGabriel Fernandez struct stm32_composite_cfg { 36637cee5fSGabriel Fernandez int mux; 37637cee5fSGabriel Fernandez int gate; 38637cee5fSGabriel Fernandez int div; 39637cee5fSGabriel Fernandez }; 40637cee5fSGabriel Fernandez 41637cee5fSGabriel Fernandez #define NO_ID 0xFFFFFFFF 42637cee5fSGabriel Fernandez 43637cee5fSGabriel Fernandez #define NO_STM32_MUX 0xFFFF 44637cee5fSGabriel Fernandez #define NO_STM32_DIV 0xFFFF 45637cee5fSGabriel Fernandez #define NO_STM32_GATE 0xFFFF 46637cee5fSGabriel Fernandez 47637cee5fSGabriel Fernandez struct clock_config { 48637cee5fSGabriel Fernandez unsigned long id; 4993e336c2SGabriel Fernandez int sec_id; 50637cee5fSGabriel Fernandez void *clock_cfg; 51637cee5fSGabriel Fernandez 52637cee5fSGabriel Fernandez struct clk_hw *(*func)(struct device *dev, 53637cee5fSGabriel Fernandez const struct stm32_rcc_match_data *data, 54637cee5fSGabriel Fernandez void __iomem *base, 55637cee5fSGabriel Fernandez spinlock_t *lock, 56637cee5fSGabriel Fernandez const struct clock_config *cfg); 57637cee5fSGabriel Fernandez }; 58637cee5fSGabriel Fernandez 59637cee5fSGabriel Fernandez struct clk_stm32_clock_data { 60637cee5fSGabriel Fernandez u16 *gate_cpt; 61637cee5fSGabriel Fernandez const struct stm32_gate_cfg *gates; 62637cee5fSGabriel Fernandez const struct stm32_mux_cfg *muxes; 63637cee5fSGabriel Fernandez const struct stm32_div_cfg *dividers; 64ffa2d04dSGabriel Fernandez struct clk_hw *(*is_multi_mux)(struct clk_hw *hw); 65637cee5fSGabriel Fernandez }; 66637cee5fSGabriel Fernandez 67637cee5fSGabriel Fernandez struct stm32_rcc_match_data { 68637cee5fSGabriel Fernandez struct clk_hw_onecell_data *hw_clks; 69637cee5fSGabriel Fernandez unsigned int num_clocks; 70637cee5fSGabriel Fernandez const struct clock_config *tab_clocks; 71637cee5fSGabriel Fernandez unsigned int maxbinding; 72637cee5fSGabriel Fernandez struct clk_stm32_clock_data *clock_data; 73637cee5fSGabriel Fernandez u32 clear_offset; 7493e336c2SGabriel Fernandez int (*check_security)(void __iomem *base, 7593e336c2SGabriel Fernandez const struct clock_config *cfg); 76ffa2d04dSGabriel Fernandez int (*multi_mux)(void __iomem *base, const struct clock_config *cfg); 77637cee5fSGabriel Fernandez }; 78637cee5fSGabriel Fernandez 79637cee5fSGabriel Fernandez int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match, 80637cee5fSGabriel Fernandez void __iomem *base); 81637cee5fSGabriel Fernandez 82637cee5fSGabriel Fernandez int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, 83637cee5fSGabriel Fernandez void __iomem *base); 84637cee5fSGabriel Fernandez 85637cee5fSGabriel Fernandez /* MUX define */ 86637cee5fSGabriel Fernandez #define MUX_NO_RDY 0xFF 87*83ce0357SGabriel Fernandez #define MUX_SAFE BIT(7) 88637cee5fSGabriel Fernandez 89637cee5fSGabriel Fernandez /* DIV define */ 90637cee5fSGabriel Fernandez #define DIV_NO_RDY 0xFF 91637cee5fSGabriel Fernandez 92f95cea83SGabriel Fernandez /* Definition of clock structure */ 93f95cea83SGabriel Fernandez struct clk_stm32_mux { 94f95cea83SGabriel Fernandez u16 mux_id; 95f95cea83SGabriel Fernandez struct clk_hw hw; 96f95cea83SGabriel Fernandez void __iomem *base; 97f95cea83SGabriel Fernandez struct clk_stm32_clock_data *clock_data; 98f95cea83SGabriel Fernandez spinlock_t *lock; /* spin lock */ 99f95cea83SGabriel Fernandez }; 100f95cea83SGabriel Fernandez 101f95cea83SGabriel Fernandez #define to_clk_stm32_mux(_hw) container_of(_hw, struct clk_stm32_mux, hw) 102f95cea83SGabriel Fernandez 10395f5e0a4SGabriel Fernandez struct clk_stm32_gate { 10495f5e0a4SGabriel Fernandez u16 gate_id; 10595f5e0a4SGabriel Fernandez struct clk_hw hw; 10695f5e0a4SGabriel Fernandez void __iomem *base; 10795f5e0a4SGabriel Fernandez struct clk_stm32_clock_data *clock_data; 10895f5e0a4SGabriel Fernandez spinlock_t *lock; /* spin lock */ 10995f5e0a4SGabriel Fernandez }; 11095f5e0a4SGabriel Fernandez 11195f5e0a4SGabriel Fernandez #define to_clk_stm32_gate(_hw) container_of(_hw, struct clk_stm32_gate, hw) 11295f5e0a4SGabriel Fernandez 113720e34abSGabriel Fernandez struct clk_stm32_div { 114720e34abSGabriel Fernandez u16 div_id; 115720e34abSGabriel Fernandez struct clk_hw hw; 116720e34abSGabriel Fernandez void __iomem *base; 117720e34abSGabriel Fernandez struct clk_stm32_clock_data *clock_data; 118720e34abSGabriel Fernandez spinlock_t *lock; /* spin lock */ 119720e34abSGabriel Fernandez }; 120720e34abSGabriel Fernandez 121720e34abSGabriel Fernandez #define to_clk_stm32_divider(_hw) container_of(_hw, struct clk_stm32_div, hw) 122720e34abSGabriel Fernandez 1235f0d4721SGabriel Fernandez struct clk_stm32_composite { 1245f0d4721SGabriel Fernandez u16 gate_id; 1255f0d4721SGabriel Fernandez u16 mux_id; 1265f0d4721SGabriel Fernandez u16 div_id; 1275f0d4721SGabriel Fernandez struct clk_hw hw; 1285f0d4721SGabriel Fernandez void __iomem *base; 1295f0d4721SGabriel Fernandez struct clk_stm32_clock_data *clock_data; 1305f0d4721SGabriel Fernandez spinlock_t *lock; /* spin lock */ 1315f0d4721SGabriel Fernandez }; 1325f0d4721SGabriel Fernandez 1335f0d4721SGabriel Fernandez #define to_clk_stm32_composite(_hw) container_of(_hw, struct clk_stm32_composite, hw) 1345f0d4721SGabriel Fernandez 135f95cea83SGabriel Fernandez /* Clock operators */ 136f95cea83SGabriel Fernandez extern const struct clk_ops clk_stm32_mux_ops; 13795f5e0a4SGabriel Fernandez extern const struct clk_ops clk_stm32_gate_ops; 138720e34abSGabriel Fernandez extern const struct clk_ops clk_stm32_divider_ops; 1395f0d4721SGabriel Fernandez extern const struct clk_ops clk_stm32_composite_ops; 140f95cea83SGabriel Fernandez 141637cee5fSGabriel Fernandez /* Clock registering */ 142f95cea83SGabriel Fernandez struct clk_hw *clk_stm32_mux_register(struct device *dev, 143f95cea83SGabriel Fernandez const struct stm32_rcc_match_data *data, 144f95cea83SGabriel Fernandez void __iomem *base, 145f95cea83SGabriel Fernandez spinlock_t *lock, 146f95cea83SGabriel Fernandez const struct clock_config *cfg); 147f95cea83SGabriel Fernandez 14895f5e0a4SGabriel Fernandez struct clk_hw *clk_stm32_gate_register(struct device *dev, 14995f5e0a4SGabriel Fernandez const struct stm32_rcc_match_data *data, 15095f5e0a4SGabriel Fernandez void __iomem *base, 15195f5e0a4SGabriel Fernandez spinlock_t *lock, 15295f5e0a4SGabriel Fernandez const struct clock_config *cfg); 15395f5e0a4SGabriel Fernandez 154720e34abSGabriel Fernandez struct clk_hw *clk_stm32_div_register(struct device *dev, 155720e34abSGabriel Fernandez const struct stm32_rcc_match_data *data, 156720e34abSGabriel Fernandez void __iomem *base, 157720e34abSGabriel Fernandez spinlock_t *lock, 158720e34abSGabriel Fernandez const struct clock_config *cfg); 159720e34abSGabriel Fernandez 1605f0d4721SGabriel Fernandez struct clk_hw *clk_stm32_composite_register(struct device *dev, 1615f0d4721SGabriel Fernandez const struct stm32_rcc_match_data *data, 1625f0d4721SGabriel Fernandez void __iomem *base, 1635f0d4721SGabriel Fernandez spinlock_t *lock, 1645f0d4721SGabriel Fernandez const struct clock_config *cfg); 1655f0d4721SGabriel Fernandez 16693e336c2SGabriel Fernandez #define STM32_CLOCK_CFG(_binding, _clk, _sec_id, _struct, _register)\ 167637cee5fSGabriel Fernandez {\ 168637cee5fSGabriel Fernandez .id = (_binding),\ 16993e336c2SGabriel Fernandez .sec_id = (_sec_id),\ 170637cee5fSGabriel Fernandez .clock_cfg = (_struct) {_clk},\ 171637cee5fSGabriel Fernandez .func = (_register),\ 172637cee5fSGabriel Fernandez } 173f95cea83SGabriel Fernandez 17493e336c2SGabriel Fernandez #define STM32_MUX_CFG(_binding, _clk, _sec_id)\ 17593e336c2SGabriel Fernandez STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_mux *,\ 176f95cea83SGabriel Fernandez &clk_stm32_mux_register) 17795f5e0a4SGabriel Fernandez 17893e336c2SGabriel Fernandez #define STM32_GATE_CFG(_binding, _clk, _sec_id)\ 17993e336c2SGabriel Fernandez STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_gate *,\ 18095f5e0a4SGabriel Fernandez &clk_stm32_gate_register) 181720e34abSGabriel Fernandez 18293e336c2SGabriel Fernandez #define STM32_DIV_CFG(_binding, _clk, _sec_id)\ 18393e336c2SGabriel Fernandez STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_div *,\ 184720e34abSGabriel Fernandez &clk_stm32_div_register) 1855f0d4721SGabriel Fernandez 18693e336c2SGabriel Fernandez #define STM32_COMPOSITE_CFG(_binding, _clk, _sec_id)\ 18793e336c2SGabriel Fernandez STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_composite *,\ 1885f0d4721SGabriel Fernandez &clk_stm32_composite_register) 189