1/* SPDX-License-Identifier: GPL-2.0  */
2/*
3 * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
4 * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
5 */
6
7#include <linux/clk-provider.h>
8
9struct stm32_rcc_match_data;
10
11struct stm32_mux_cfg {
12	u16	offset;
13	u8	shift;
14	u8	width;
15	u8	flags;
16	u32	*table;
17	u8	ready;
18};
19
20struct stm32_gate_cfg {
21	u16	offset;
22	u8	bit_idx;
23	u8	set_clr;
24};
25
26struct stm32_div_cfg {
27	u16	offset;
28	u8	shift;
29	u8	width;
30	u8	flags;
31	u8	ready;
32	const struct clk_div_table *table;
33};
34
35struct stm32_composite_cfg {
36	int	mux;
37	int	gate;
38	int	div;
39};
40
41#define NO_ID 0xFFFFFFFF
42
43#define NO_STM32_MUX		0xFFFF
44#define NO_STM32_DIV		0xFFFF
45#define NO_STM32_GATE		0xFFFF
46
47struct clock_config {
48	unsigned long	id;
49	int		sec_id;
50	void		*clock_cfg;
51
52	struct clk_hw *(*func)(struct device *dev,
53			       const struct stm32_rcc_match_data *data,
54			       void __iomem *base,
55			       spinlock_t *lock,
56			       const struct clock_config *cfg);
57};
58
59struct clk_stm32_clock_data {
60	u16 *gate_cpt;
61	const struct stm32_gate_cfg	*gates;
62	const struct stm32_mux_cfg	*muxes;
63	const struct stm32_div_cfg	*dividers;
64	struct clk_hw *(*is_multi_mux)(struct clk_hw *hw);
65};
66
67struct stm32_rcc_match_data {
68	struct clk_hw_onecell_data	*hw_clks;
69	unsigned int			num_clocks;
70	const struct clock_config	*tab_clocks;
71	unsigned int			maxbinding;
72	struct clk_stm32_clock_data	*clock_data;
73	u32				clear_offset;
74	int (*check_security)(void __iomem *base,
75			      const struct clock_config *cfg);
76	int (*multi_mux)(void __iomem *base, const struct clock_config *cfg);
77};
78
79int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match,
80			 void __iomem *base);
81
82int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data,
83		   void __iomem *base);
84
85/* MUX define */
86#define MUX_NO_RDY		0xFF
87#define MUX_SAFE		BIT(7)
88
89/* DIV define */
90#define DIV_NO_RDY		0xFF
91
92/* Definition of clock structure */
93struct clk_stm32_mux {
94	u16 mux_id;
95	struct clk_hw hw;
96	void __iomem *base;
97	struct clk_stm32_clock_data *clock_data;
98	spinlock_t *lock; /* spin lock */
99};
100
101#define to_clk_stm32_mux(_hw) container_of(_hw, struct clk_stm32_mux, hw)
102
103struct clk_stm32_gate {
104	u16 gate_id;
105	struct clk_hw hw;
106	void __iomem *base;
107	struct clk_stm32_clock_data *clock_data;
108	spinlock_t *lock; /* spin lock */
109};
110
111#define to_clk_stm32_gate(_hw) container_of(_hw, struct clk_stm32_gate, hw)
112
113struct clk_stm32_div {
114	u16 div_id;
115	struct clk_hw hw;
116	void __iomem *base;
117	struct clk_stm32_clock_data *clock_data;
118	spinlock_t *lock; /* spin lock */
119};
120
121#define to_clk_stm32_divider(_hw) container_of(_hw, struct clk_stm32_div, hw)
122
123struct clk_stm32_composite {
124	u16 gate_id;
125	u16 mux_id;
126	u16 div_id;
127	struct clk_hw hw;
128	void __iomem *base;
129	struct clk_stm32_clock_data *clock_data;
130	spinlock_t *lock; /* spin lock */
131};
132
133#define to_clk_stm32_composite(_hw) container_of(_hw, struct clk_stm32_composite, hw)
134
135/* Clock operators */
136extern const struct clk_ops clk_stm32_mux_ops;
137extern const struct clk_ops clk_stm32_gate_ops;
138extern const struct clk_ops clk_stm32_divider_ops;
139extern const struct clk_ops clk_stm32_composite_ops;
140
141/* Clock registering */
142struct clk_hw *clk_stm32_mux_register(struct device *dev,
143				      const struct stm32_rcc_match_data *data,
144				      void __iomem *base,
145				      spinlock_t *lock,
146				      const struct clock_config *cfg);
147
148struct clk_hw *clk_stm32_gate_register(struct device *dev,
149				       const struct stm32_rcc_match_data *data,
150				       void __iomem *base,
151				       spinlock_t *lock,
152				       const struct clock_config *cfg);
153
154struct clk_hw *clk_stm32_div_register(struct device *dev,
155				      const struct stm32_rcc_match_data *data,
156				      void __iomem *base,
157				      spinlock_t *lock,
158				      const struct clock_config *cfg);
159
160struct clk_hw *clk_stm32_composite_register(struct device *dev,
161					    const struct stm32_rcc_match_data *data,
162					    void __iomem *base,
163					    spinlock_t *lock,
164					    const struct clock_config *cfg);
165
166#define STM32_CLOCK_CFG(_binding, _clk, _sec_id, _struct, _register)\
167{\
168	.id		= (_binding),\
169	.sec_id		= (_sec_id),\
170	.clock_cfg	= (_struct) {_clk},\
171	.func		= (_register),\
172}
173
174#define STM32_MUX_CFG(_binding, _clk, _sec_id)\
175	STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_mux *,\
176			&clk_stm32_mux_register)
177
178#define STM32_GATE_CFG(_binding, _clk, _sec_id)\
179	STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_gate *,\
180			&clk_stm32_gate_register)
181
182#define STM32_DIV_CFG(_binding, _clk, _sec_id)\
183	STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_div *,\
184			&clk_stm32_div_register)
185
186#define STM32_COMPOSITE_CFG(_binding, _clk, _sec_id)\
187	STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_composite *,\
188			&clk_stm32_composite_register)
189