1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (c) 2018 BayLibre, SAS.
4  * Author: Jerome Brunet <jbrunet@baylibre.com>
5  */
6 
7 #ifndef __CLK_REGMAP_H
8 #define __CLK_REGMAP_H
9 
10 #include <linux/clk-provider.h>
11 #include <linux/regmap.h>
12 
13 /**
14  * struct clk_regmap - regmap backed clock
15  *
16  * @hw:		handle between common and hardware-specific interfaces
17  * @map:	pointer to the regmap structure controlling the clock
18  * @data:	data specific to the clock type
19  *
20  * Clock which is controlled by regmap backed registers. The actual type of
21  * of the clock is controlled by the clock_ops and data.
22  */
23 struct clk_regmap {
24 	struct clk_hw	hw;
25 	struct regmap	*map;
26 	void		*data;
27 };
28 
to_clk_regmap(struct clk_hw * hw)29 static inline struct clk_regmap *to_clk_regmap(struct clk_hw *hw)
30 {
31 	return container_of(hw, struct clk_regmap, hw);
32 }
33 
34 /**
35  * struct clk_regmap_gate_data - regmap backed gate specific data
36  *
37  * @offset:	offset of the register controlling gate
38  * @bit_idx:	single bit controlling gate
39  * @flags:	hardware-specific flags
40  *
41  * Flags:
42  * Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored
43  */
44 struct clk_regmap_gate_data {
45 	unsigned int	offset;
46 	u8		bit_idx;
47 	u8		flags;
48 };
49 
50 static inline struct clk_regmap_gate_data *
clk_get_regmap_gate_data(struct clk_regmap * clk)51 clk_get_regmap_gate_data(struct clk_regmap *clk)
52 {
53 	return (struct clk_regmap_gate_data *)clk->data;
54 }
55 
56 extern const struct clk_ops clk_regmap_gate_ops;
57 extern const struct clk_ops clk_regmap_gate_ro_ops;
58 
59 /**
60  * struct clk_regmap_div_data - regmap backed adjustable divider specific data
61  *
62  * @offset:	offset of the register controlling the divider
63  * @shift:	shift to the divider bit field
64  * @width:	width of the divider bit field
65  * @table:	array of value/divider pairs, last entry should have div = 0
66  *
67  * Flags:
68  * Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored
69  */
70 struct clk_regmap_div_data {
71 	unsigned int	offset;
72 	u8		shift;
73 	u8		width;
74 	u8		flags;
75 	const struct clk_div_table	*table;
76 };
77 
78 static inline struct clk_regmap_div_data *
clk_get_regmap_div_data(struct clk_regmap * clk)79 clk_get_regmap_div_data(struct clk_regmap *clk)
80 {
81 	return (struct clk_regmap_div_data *)clk->data;
82 }
83 
84 extern const struct clk_ops clk_regmap_divider_ops;
85 extern const struct clk_ops clk_regmap_divider_ro_ops;
86 
87 /**
88  * struct clk_regmap_mux_data - regmap backed multiplexer clock specific data
89  *
90  * @hw:		handle between common and hardware-specific interfaces
91  * @offset:	offset of theregister controlling multiplexer
92  * @table:	array of parent indexed register values
93  * @shift:	shift to multiplexer bit field
94  * @mask:	mask of mutliplexer bit field
95  * @flags:	hardware-specific flags
96  *
97  * Flags:
98  * Same as clk_divider except CLK_MUX_HIWORD_MASK which is ignored
99  */
100 struct clk_regmap_mux_data {
101 	unsigned int	offset;
102 	u32		*table;
103 	u32		mask;
104 	u8		shift;
105 	u8		flags;
106 };
107 
108 static inline struct clk_regmap_mux_data *
clk_get_regmap_mux_data(struct clk_regmap * clk)109 clk_get_regmap_mux_data(struct clk_regmap *clk)
110 {
111 	return (struct clk_regmap_mux_data *)clk->data;
112 }
113 
114 extern const struct clk_ops clk_regmap_mux_ops;
115 extern const struct clk_ops clk_regmap_mux_ro_ops;
116 
117 #define __MESON_PCLK(_name, _reg, _bit, _ops, _pname)			\
118 struct clk_regmap _name = {						\
119 	.data = &(struct clk_regmap_gate_data){				\
120 		.offset = (_reg),					\
121 		.bit_idx = (_bit),					\
122 	},								\
123 	.hw.init = &(struct clk_init_data) {				\
124 		.name = #_name,						\
125 		.ops = _ops,						\
126 		.parent_hws = (const struct clk_hw *[]) { _pname },	\
127 		.num_parents = 1,					\
128 		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),	\
129 	},								\
130 }
131 
132 #define MESON_PCLK(_name, _reg, _bit, _pname)	\
133 	__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pname)
134 
135 #define MESON_PCLK_RO(_name, _reg, _bit, _pname)	\
136 	__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pname)
137 #endif /* __CLK_REGMAP_H */
138