]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/rockchip/clk/rk_cru.h
Finish implementation of RK3299 clocks.
[FreeBSD/FreeBSD.git] / sys / arm64 / rockchip / clk / rk_cru.h
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31 #ifndef __RK_CRU_H__
32 #define __RK_CRU_H__
33
34 #include <dev/extres/clk/clk.h>
35 #include <dev/extres/clk/clk_div.h>
36 #include <dev/extres/clk/clk_gate.h>
37 #include <dev/extres/clk/clk_fixed.h>
38 #include <dev/extres/clk/clk_link.h>
39
40 #include <arm64/rockchip/clk/rk_clk_armclk.h>
41 #include <arm64/rockchip/clk/rk_clk_composite.h>
42 #include <arm64/rockchip/clk/rk_clk_fract.h>
43 #include <arm64/rockchip/clk/rk_clk_gate.h>
44 #include <arm64/rockchip/clk/rk_clk_mux.h>
45 #include <arm64/rockchip/clk/rk_clk_pll.h>
46
47 /* Macro for defining various types of clocks. */
48 /* Pure gate */
49 #define GATE(_idx, _clkname, _pname, _o, _s)                            \
50 {                                                                       \
51         .id = _idx,                                                     \
52         .name = _clkname,                                               \
53         .parent_name = _pname,                                          \
54         .offset = CRU_CLKGATE_CON(_o),                                  \
55         .shift = _s,                                                    \
56 }
57
58 /* Fixed rate clock. */
59 #define FRATE(_id, _name, _freq)                                        \
60 {                                                                       \
61         .type = RK_CLK_FIXED,                                           \
62         .clk.fixed = &(struct clk_fixed_def) {                          \
63                 .clkdef.id = _id,                                       \
64                 .clkdef.name = _name,                                   \
65                 .clkdef.parent_names = NULL,                            \
66                 .clkdef.parent_cnt = 0,                                 \
67                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
68                 .freq = _freq,                                          \
69         },                                                              \
70 }
71
72 /* Fixed factor multipier/divider. */
73 #define FFACT(_id, _name, _pname, _mult, _div)                          \
74 {                                                                       \
75         .type = RK_CLK_FIXED,                                           \
76         .clk.fixed = &(struct clk_fixed_def) {                          \
77                 .clkdef.id = _id,                                       \
78                 .clkdef.name = _name,                                   \
79                 .clkdef.parent_names = (const char *[]){_pname},        \
80                 .clkdef.parent_cnt = 1,                                 \
81                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
82                 .mult = _mult,                                          \
83                 .div = _div,                                            \
84         },                                                              \
85 }
86
87 /* Linked clock. */
88 #define LINK(_name)                                                     \
89 {                                                                       \
90         .type = RK_CLK_LINK,                                            \
91         .clk.link = &(struct clk_link_def) {                            \
92                 .clkdef.id = 0,                                         \
93                 .clkdef.name = _name,                                   \
94                 .clkdef.parent_names = NULL,                            \
95                 .clkdef.parent_cnt = 0,                                 \
96                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
97         },                                                              \
98 }
99
100 /* Complex clock fo ARM cores. */
101 #define ARMDIV(_id, _name, _pn, _r, _o, _ds, _dw, _ms, _mw, _mp, _ap)   \
102 {                                                                       \
103         .type = RK_CLK_ARMCLK,                                          \
104         .clk.armclk = &(struct rk_clk_armclk_def) {                     \
105                 .clkdef.id = _id,                                       \
106                 .clkdef.name = _name,                                   \
107                 .clkdef.parent_names = _pn,                             \
108                 .clkdef.parent_cnt = nitems(_pn),                       \
109                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
110                 .muxdiv_offset = CRU_CLKSEL_CON(_o),                    \
111                 .mux_shift = _ms,                                       \
112                 .mux_width = _mw,                                       \
113                 .div_shift = _ds,                                       \
114                 .div_width = _dw,                                       \
115                 .main_parent = _mp,                                     \
116                 .alt_parent = _ap,                                      \
117                 .rates = _r,                                            \
118                 .nrates = nitems(_r),                                   \
119         },                                                              \
120 }
121
122 /* Fractional rate multipier/divider. */
123 #define FRACT(_id, _name, _pname, _f, _o)                               \
124 {                                                                       \
125         .type = RK_CLK_FRACT,                                           \
126         .clk.fract = &(struct rk_clk_fract_def) {                       \
127                 .clkdef.id = _id,                                       \
128                 .clkdef.name = _name,                                   \
129                 .clkdef.parent_names = (const char *[]){_pname},        \
130                 .clkdef.parent_cnt = 1,                                 \
131                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
132                 .offset = CRU_CLKSEL_CON(_o),                           \
133                 .flags = _f,                                            \
134         },                                                              \
135 }
136
137 /* Full composite clock. */
138 #define COMP(_id, _name, _pnames, _f,  _o,  _ds, _dw,  _ms, _mw)        \
139 {                                                                       \
140         .type = RK_CLK_COMPOSITE,                                       \
141         .clk.composite = &(struct rk_clk_composite_def) {               \
142                 .clkdef.id = _id,                                       \
143                 .clkdef.name = _name,                                   \
144                 .clkdef.parent_names = _pnames,                         \
145                 .clkdef.parent_cnt = nitems(_pnames),                   \
146                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
147                 .muxdiv_offset = CRU_CLKSEL_CON(_o),                    \
148                 .mux_shift = _ms,                                       \
149                 .mux_width = _mw,                                       \
150                 .div_shift = _ds,                                       \
151                 .div_width = _dw,                                       \
152                 .flags = RK_CLK_COMPOSITE_HAVE_MUX | _f,                \
153         },                                                              \
154 }
155
156 /* Composite clock without mux (divider only). */
157 #define CDIV(_id, _name, _pname, _f, _o, _ds, _dw)                      \
158 {                                                                       \
159         .type = RK_CLK_COMPOSITE,                                       \
160         .clk.composite = &(struct rk_clk_composite_def) {               \
161                 .clkdef.id = _id,                                       \
162                 .clkdef.name = _name,                                   \
163                 .clkdef.parent_names = (const char *[]){_pname},        \
164                 .clkdef.parent_cnt = 1,                                 \
165                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
166                 .muxdiv_offset = CRU_CLKSEL_CON(_o),                    \
167                 .div_shift = _ds,                                       \
168                 .div_width = _dw,                                       \
169                 .flags =  _f,                                           \
170         },                                                              \
171 }
172
173 /* Complex clock without divider (multiplexer only). */
174 #define MUX(_id, _name, _pn, _f,  _mo, _ms, _mw)                        \
175 {                                                                       \
176         .type = RK_CLK_MUX,                                             \
177         .clk.mux = &(struct rk_clk_mux_def) {                           \
178                 .clkdef.id = _id,                                       \
179                 .clkdef.name = _name,                                   \
180                 .clkdef.parent_names = _pn,                             \
181                 .clkdef.parent_cnt = nitems(_pn),                       \
182                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
183                 .offset = CRU_CLKSEL_CON(_mo),                          \
184                 .shift = _ms,                                           \
185                 .width = _mw,                                           \
186                 .mux_flags = _f,                        \
187         },                                                              \
188 }
189
190 struct rk_cru_gate {
191         const char      *name;
192         const char      *parent_name;
193         uint32_t        id;
194         uint32_t        offset;
195         uint32_t        shift;
196 };
197
198 #define CRU_GATE(idx, clkname, pname, o, s)     \
199         {                               \
200                 .id = idx,                      \
201                 .name = clkname,                \
202                 .parent_name = pname,           \
203                 .offset = o,                    \
204                 .shift = s,                     \
205         },
206
207 enum rk_clk_type {
208         RK_CLK_UNDEFINED = 0,
209         RK3328_CLK_PLL,
210         RK3399_CLK_PLL,
211         RK_CLK_COMPOSITE,
212         RK_CLK_FIXED,
213         RK_CLK_FRACT,
214         RK_CLK_MUX,
215         RK_CLK_ARMCLK,
216         RK_CLK_LINK,
217 };
218
219 struct rk_clk {
220         enum rk_clk_type        type;
221         union {
222                 struct rk_clk_pll_def           *pll;
223                 struct rk_clk_composite_def     *composite;
224                 struct rk_clk_mux_def           *mux;
225                 struct rk_clk_armclk_def        *armclk;
226                 struct clk_fixed_def            *fixed;
227                 struct rk_clk_fract_def         *fract;
228                 struct clk_link_def             *link;
229         } clk;
230 };
231
232 struct rk_cru_softc {
233         device_t                dev;
234         struct resource         *res;
235         struct clkdom           *clkdom;
236         struct mtx              mtx;
237         int                     type;
238         uint32_t                reset_offset;
239         uint32_t                reset_num;
240         struct rk_cru_gate      *gates;
241         int                     ngates;
242         struct rk_clk           *clks;
243         int                     nclks;
244         struct rk_clk_armclk_def        *armclk;
245         struct rk_clk_armclk_rates      *armclk_rates;
246         int                     narmclk_rates;
247 };
248
249 DECLARE_CLASS(rk_cru_driver);
250
251 int     rk_cru_attach(device_t dev);
252
253 #endif /* __RK_CRU_H__ */