aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/clk/stm32/clk-stm32-core.h
blob: f958ef610f723d1f58b58c533ffd098c91aef1f6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* 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;
	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 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 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

/* 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)

/* Clock operators */
extern const struct clk_ops clk_stm32_mux_ops;
extern const struct clk_ops clk_stm32_gate_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);

#define STM32_CLOCK_CFG(_binding, _clk, _struct, _register)\
{\
	.id		= (_binding),\
	.clock_cfg	= (_struct) {_clk},\
	.func		= (_register),\
}

#define STM32_MUX_CFG(_binding, _clk)\
	STM32_CLOCK_CFG(_binding, &(_clk), struct clk_stm32_mux *,\
			&clk_stm32_mux_register)

#define STM32_GATE_CFG(_binding, _clk)\
	STM32_CLOCK_CFG(_binding, &(_clk), struct clk_stm32_gate *,\
			&clk_stm32_gate_register)