blob: 51f124869c9c4043dfe047cf2f694bf59df7e87f [file] [log] [blame]
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2018 - Beniamino Galvani <b.galvani@gmail.com>
4 * (C) Copyright 2018 - BayLibre, SAS
5 * Author: Neil Armstrong <narmstrong@baylibre.com>
6 */
7
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Jerome Brunetf897c4b2018-10-05 17:00:37 +02009#include <asm/arch/clock-gx.h>
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +020010#include <asm/io.h>
11#include <clk-uclass.h>
12#include <div64.h>
13#include <dm.h>
Loic Devulderc0379032018-11-27 17:41:18 +010014#include <regmap.h>
15#include <syscon.h>
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +020016#include <dt-bindings/clock/gxbb-clkc.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060017#include <linux/bitops.h>
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +020018#include "clk_meson.h"
Simon Glassd66c5f72020-02-03 07:36:15 -070019#include <linux/err.h>
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +020020
Neil Armstrong07f24772018-08-06 14:49:20 +020021/* This driver support only basic clock tree operations :
22 * - Can calculate clock frequency on a limited tree
23 * - Can Read muxes and basic dividers (0-based only)
24 * - Can enable/disable gates with limited propagation
25 * - Can reparent without propagation, only on muxes
26 * - Can set rates without reparenting
27 * This driver is adapted to what is actually supported by U-Boot
28 */
29
30/* Only the clocks ids we don't want to expose, such as the internal muxes
31 * and dividers of composite clocks, will remain defined here.
32 */
33#define CLKID_MPEG_SEL 10
34#define CLKID_MPEG_DIV 11
35#define CLKID_SAR_ADC_DIV 99
36#define CLKID_MALI_0_DIV 101
37#define CLKID_MALI_1_DIV 104
38#define CLKID_CTS_AMCLK_SEL 108
39#define CLKID_CTS_AMCLK_DIV 109
40#define CLKID_CTS_MCLK_I958_SEL 111
41#define CLKID_CTS_MCLK_I958_DIV 112
42#define CLKID_32K_CLK_SEL 115
43#define CLKID_32K_CLK_DIV 116
44#define CLKID_SD_EMMC_A_CLK0_SEL 117
45#define CLKID_SD_EMMC_A_CLK0_DIV 118
46#define CLKID_SD_EMMC_B_CLK0_SEL 120
47#define CLKID_SD_EMMC_B_CLK0_DIV 121
48#define CLKID_SD_EMMC_C_CLK0_SEL 123
49#define CLKID_SD_EMMC_C_CLK0_DIV 124
50#define CLKID_VPU_0_DIV 127
51#define CLKID_VPU_1_DIV 130
52#define CLKID_VAPB_0_DIV 134
53#define CLKID_VAPB_1_DIV 137
54#define CLKID_HDMI_PLL_PRE_MULT 141
55#define CLKID_MPLL0_DIV 142
56#define CLKID_MPLL1_DIV 143
57#define CLKID_MPLL2_DIV 144
58#define CLKID_MPLL_PREDIV 145
59#define CLKID_FCLK_DIV2_DIV 146
60#define CLKID_FCLK_DIV3_DIV 147
61#define CLKID_FCLK_DIV4_DIV 148
62#define CLKID_FCLK_DIV5_DIV 149
63#define CLKID_FCLK_DIV7_DIV 150
64#define CLKID_VDEC_1_SEL 151
65#define CLKID_VDEC_1_DIV 152
66#define CLKID_VDEC_HEVC_SEL 154
67#define CLKID_VDEC_HEVC_DIV 155
68
Neil Armstrong7481d3c2024-10-09 11:15:20 +020069#define CLKID_XTAL 0x10000000
70
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +020071#define XTAL_RATE 24000000
72
73struct meson_clk {
Loic Devulderc0379032018-11-27 17:41:18 +010074 struct regmap *map;
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +020075};
76
Neil Armstrong07f24772018-08-06 14:49:20 +020077static ulong meson_div_get_rate(struct clk *clk, unsigned long id);
78static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
79 ulong current_rate);
80static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
81 unsigned long parent_id);
82static ulong meson_mux_get_rate(struct clk *clk, unsigned long id);
83static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
84 ulong rate, ulong current_rate);
85static ulong meson_mux_get_parent(struct clk *clk, unsigned long id);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +020086static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id);
87
Neil Armstrongcd977932018-11-08 17:17:41 +010088static struct meson_gate gates[] = {
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +020089 /* Everything Else (EE) domain gates */
90 MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0),
91 MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1),
92 MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5),
93 MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6),
94 MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7),
95 MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8),
96 MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9),
97 MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10),
98 MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11),
99 MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12),
100 MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13),
101 MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14),
102 MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15),
103 MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16),
104 MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17),
105 MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18),
106 MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19),
107 MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23),
108 MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24),
109 MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25),
110 MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26),
111 MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30),
112
113 MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2),
114 MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3),
115 MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4),
116 MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6),
117 MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7),
118 MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8),
119 MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9),
120 MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10),
121 MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11),
122 MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12),
123 MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13),
124 MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14),
125 MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15),
126 MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16),
127 MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20),
128 MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21),
129 MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22),
130 MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23),
131 MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24),
132 MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25),
133 MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26),
134 MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28),
135 MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29),
136 MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30),
137 MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31),
138
139 MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1),
140 MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2),
141 MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3),
142 MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4),
143 MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8),
144 MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9),
145 MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11),
146 MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12),
147 MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15),
148 MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22),
149 MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25),
150 MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26),
151 MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29),
152
153 MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1),
154 MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2),
155 MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3),
156 MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4),
157 MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8),
158 MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10),
159 MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14),
160 MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16),
161 MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20),
162 MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21),
163 MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22),
164 MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24),
165 MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25),
166 MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26),
167 MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31),
168
169 /* Always On (AO) domain gates */
170 MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0),
171 MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1),
172 MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2),
173 MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3),
174 MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4),
175
176 /* PLL Gates */
177 /* CLKID_FCLK_DIV2 is critical for the SCPI Processor */
178 MESON_GATE(CLKID_FCLK_DIV3, HHI_MPLL_CNTL6, 28),
179 MESON_GATE(CLKID_FCLK_DIV4, HHI_MPLL_CNTL6, 29),
180 MESON_GATE(CLKID_FCLK_DIV5, HHI_MPLL_CNTL6, 30),
181 MESON_GATE(CLKID_FCLK_DIV7, HHI_MPLL_CNTL6, 31),
182 MESON_GATE(CLKID_MPLL0, HHI_MPLL_CNTL7, 14),
183 MESON_GATE(CLKID_MPLL1, HHI_MPLL_CNTL8, 14),
184 MESON_GATE(CLKID_MPLL2, HHI_MPLL_CNTL9, 14),
185 /* CLKID_CLK81 is critical for the system */
186
187 /* Peripheral Gates */
188 MESON_GATE(CLKID_SAR_ADC_CLK, HHI_SAR_CLK_CNTL, 8),
189 MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7),
190 MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23),
191 MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7),
Neil Armstrong07f24772018-08-06 14:49:20 +0200192 MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8),
193 MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24),
194 MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8),
195 MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24),
196 MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30),
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200197 MESON_GATE(CLKID_HDMI, HHI_HDMI_CLK_CNTL, 8),
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200198};
199
Neil Armstrong07f24772018-08-06 14:49:20 +0200200static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on)
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200201{
202 struct meson_clk *priv = dev_get_priv(clk->dev);
203 struct meson_gate *gate;
204
Neil Armstrong07f24772018-08-06 14:49:20 +0200205 debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id);
206
207 /* Propagate through muxes */
208 switch (id) {
209 case CLKID_VPU:
210 return meson_set_gate_by_id(clk,
211 meson_mux_get_parent(clk, CLKID_VPU), on);
212 case CLKID_VAPB_SEL:
213 return meson_set_gate_by_id(clk,
214 meson_mux_get_parent(clk, CLKID_VAPB_SEL), on);
215 }
216
217 if (id >= ARRAY_SIZE(gates))
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200218 return -ENOENT;
219
Neil Armstrong07f24772018-08-06 14:49:20 +0200220 gate = &gates[id];
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200221
222 if (gate->reg == 0)
223 return 0;
224
Neil Armstrong07f24772018-08-06 14:49:20 +0200225 debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id);
226
Loic Devulderc0379032018-11-27 17:41:18 +0100227 regmap_update_bits(priv->map, gate->reg,
228 BIT(gate->bit), on ? BIT(gate->bit) : 0);
Neil Armstrong07f24772018-08-06 14:49:20 +0200229
230 /* Propagate to next gate(s) */
231 switch (id) {
232 case CLKID_VAPB:
233 return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on);
234 }
235
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200236 return 0;
237}
238
239static int meson_clk_enable(struct clk *clk)
240{
Neil Armstrong07f24772018-08-06 14:49:20 +0200241 return meson_set_gate_by_id(clk, clk->id, true);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200242}
243
244static int meson_clk_disable(struct clk *clk)
245{
Neil Armstrong07f24772018-08-06 14:49:20 +0200246 return meson_set_gate_by_id(clk, clk->id, false);
247}
248
249static struct parm meson_vpu_0_div_parm = {
250 HHI_VPU_CLK_CNTL, 0, 7,
251};
252
253int meson_vpu_0_div_parent = CLKID_VPU_0_SEL;
254
255static struct parm meson_vpu_1_div_parm = {
256 HHI_VPU_CLK_CNTL, 16, 7,
257};
258
259int meson_vpu_1_div_parent = CLKID_VPU_1_SEL;
260
261static struct parm meson_vapb_0_div_parm = {
262 HHI_VAPBCLK_CNTL, 0, 7,
263};
264
265int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL;
266
267static struct parm meson_vapb_1_div_parm = {
268 HHI_VAPBCLK_CNTL, 16, 7,
269};
270
271int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL;
272
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200273static struct parm meson_hdmi_div_parm = {
274 HHI_HDMI_CLK_CNTL, 0, 7,
275};
276
277int meson_hdmi_div_parent = CLKID_HDMI_SEL;
278
Neil Armstrong07f24772018-08-06 14:49:20 +0200279static ulong meson_div_get_rate(struct clk *clk, unsigned long id)
280{
281 struct meson_clk *priv = dev_get_priv(clk->dev);
282 unsigned int rate, parent_rate;
283 struct parm *parm;
284 int parent;
Loic Devulderc0379032018-11-27 17:41:18 +0100285 uint reg;
Neil Armstrong07f24772018-08-06 14:49:20 +0200286
287 switch (id) {
288 case CLKID_VPU_0_DIV:
289 parm = &meson_vpu_0_div_parm;
290 parent = meson_vpu_0_div_parent;
291 break;
292 case CLKID_VPU_1_DIV:
293 parm = &meson_vpu_1_div_parm;
294 parent = meson_vpu_1_div_parent;
295 break;
296 case CLKID_VAPB_0_DIV:
297 parm = &meson_vapb_0_div_parm;
298 parent = meson_vapb_0_div_parent;
299 break;
300 case CLKID_VAPB_1_DIV:
301 parm = &meson_vapb_1_div_parm;
302 parent = meson_vapb_1_div_parent;
303 break;
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200304 case CLKID_HDMI_DIV:
305 parm = &meson_hdmi_div_parm;
306 parent = meson_hdmi_div_parent;
307 break;
Neil Armstrong07f24772018-08-06 14:49:20 +0200308 default:
309 return -ENOENT;
310 }
311
Loic Devulderc0379032018-11-27 17:41:18 +0100312 regmap_read(priv->map, parm->reg_off, &reg);
Neil Armstrong07f24772018-08-06 14:49:20 +0200313 reg = PARM_GET(parm->width, parm->shift, reg);
314
315 debug("%s: div of %ld is %d\n", __func__, id, reg + 1);
316
317 parent_rate = meson_clk_get_rate_by_id(clk, parent);
318 if (IS_ERR_VALUE(parent_rate))
319 return parent_rate;
320
321 debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate);
322
323 rate = parent_rate / (reg + 1);
324
325 debug("%s: rate of %ld is %d\n", __func__, id, rate);
326
327 return rate;
328}
329
330static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
331 ulong current_rate)
332{
333 struct meson_clk *priv = dev_get_priv(clk->dev);
334 unsigned int new_div = -EINVAL;
335 unsigned long parent_rate;
336 struct parm *parm;
337 int parent;
Neil Armstrong07f24772018-08-06 14:49:20 +0200338 int ret;
339
340 if (current_rate == rate)
341 return 0;
342
343 debug("%s: setting rate of %ld from %ld to %ld\n",
344 __func__, id, current_rate, rate);
345
346 switch (id) {
347 case CLKID_VPU_0_DIV:
348 parm = &meson_vpu_0_div_parm;
349 parent = meson_vpu_0_div_parent;
350 break;
351 case CLKID_VPU_1_DIV:
352 parm = &meson_vpu_1_div_parm;
353 parent = meson_vpu_1_div_parent;
354 break;
355 case CLKID_VAPB_0_DIV:
356 parm = &meson_vapb_0_div_parm;
357 parent = meson_vapb_0_div_parent;
358 break;
359 case CLKID_VAPB_1_DIV:
360 parm = &meson_vapb_1_div_parm;
361 parent = meson_vapb_1_div_parent;
362 break;
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200363 case CLKID_HDMI_DIV:
364 parm = &meson_hdmi_div_parm;
365 parent = meson_hdmi_div_parent;
366 break;
Neil Armstrong07f24772018-08-06 14:49:20 +0200367 default:
368 return -ENOENT;
369 }
370
371 parent_rate = meson_clk_get_rate_by_id(clk, parent);
372 if (IS_ERR_VALUE(parent_rate))
373 return parent_rate;
374
375 debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate);
376
377 /* If can't divide, set parent instead */
378 if (!parent_rate || rate > parent_rate)
379 return meson_clk_set_rate_by_id(clk, parent, rate,
380 current_rate);
381
382 new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
383
384 debug("%s: new div of %ld is %d\n", __func__, id, new_div);
385
386 /* If overflow, try to set parent rate and retry */
387 if (!new_div || new_div > (1 << parm->width)) {
388 ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate);
389 if (IS_ERR_VALUE(ret))
390 return ret;
391
392 parent_rate = meson_clk_get_rate_by_id(clk, parent);
393 if (IS_ERR_VALUE(parent_rate))
394 return parent_rate;
395
396 new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
397
398 debug("%s: new new div of %ld is %d\n", __func__, id, new_div);
399
400 if (!new_div || new_div > (1 << parm->width))
401 return -EINVAL;
402 }
403
404 debug("%s: setting div of %ld to %d\n", __func__, id, new_div);
405
Loic Devulderc0379032018-11-27 17:41:18 +0100406 regmap_update_bits(priv->map, parm->reg_off, SETPMASK(parm->width, parm->shift),
407 (new_div - 1) << parm->shift);
Neil Armstrong07f24772018-08-06 14:49:20 +0200408
409 debug("%s: new rate of %ld is %ld\n",
410 __func__, id, meson_div_get_rate(clk, id));
411
412 return 0;
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200413}
414
Neil Armstrong07f24772018-08-06 14:49:20 +0200415static struct parm meson_vpu_mux_parm = {
416 HHI_VPU_CLK_CNTL, 31, 1,
417};
418
419int meson_vpu_mux_parents[] = {
420 CLKID_VPU_0,
421 CLKID_VPU_1,
422};
423
424static struct parm meson_vpu_0_mux_parm = {
425 HHI_VPU_CLK_CNTL, 9, 2,
426};
427
428static struct parm meson_vpu_1_mux_parm = {
429 HHI_VPU_CLK_CNTL, 25, 2,
430};
431
432static int meson_vpu_0_1_mux_parents[] = {
433 CLKID_FCLK_DIV4,
434 CLKID_FCLK_DIV3,
435 CLKID_FCLK_DIV5,
436 CLKID_FCLK_DIV7,
437};
438
439static struct parm meson_vapb_sel_mux_parm = {
440 HHI_VAPBCLK_CNTL, 31, 1,
441};
442
443int meson_vapb_sel_mux_parents[] = {
444 CLKID_VAPB_0,
445 CLKID_VAPB_1,
446};
447
448static struct parm meson_vapb_0_mux_parm = {
449 HHI_VAPBCLK_CNTL, 9, 2,
450};
451
452static struct parm meson_vapb_1_mux_parm = {
453 HHI_VAPBCLK_CNTL, 25, 2,
454};
455
456static int meson_vapb_0_1_mux_parents[] = {
457 CLKID_FCLK_DIV4,
458 CLKID_FCLK_DIV3,
459 CLKID_FCLK_DIV5,
460 CLKID_FCLK_DIV7,
461};
462
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200463static struct parm meson_hdmi_mux_parm = {
464 HHI_HDMI_CLK_CNTL, 9, 2,
465};
466
467static int meson_hdmi_mux_parents[] = {
468 CLKID_XTAL,
469 CLKID_FCLK_DIV4,
470 CLKID_FCLK_DIV3,
471 CLKID_FCLK_DIV5,
472};
473
Neil Armstrong07f24772018-08-06 14:49:20 +0200474static ulong meson_mux_get_parent(struct clk *clk, unsigned long id)
475{
476 struct meson_clk *priv = dev_get_priv(clk->dev);
477 struct parm *parm;
478 int *parents;
Loic Devulderc0379032018-11-27 17:41:18 +0100479 uint reg;
Neil Armstrong07f24772018-08-06 14:49:20 +0200480
481 switch (id) {
482 case CLKID_VPU:
483 parm = &meson_vpu_mux_parm;
484 parents = meson_vpu_mux_parents;
485 break;
486 case CLKID_VPU_0_SEL:
487 parm = &meson_vpu_0_mux_parm;
488 parents = meson_vpu_0_1_mux_parents;
489 break;
490 case CLKID_VPU_1_SEL:
491 parm = &meson_vpu_1_mux_parm;
492 parents = meson_vpu_0_1_mux_parents;
493 break;
494 case CLKID_VAPB_SEL:
495 parm = &meson_vapb_sel_mux_parm;
496 parents = meson_vapb_sel_mux_parents;
497 break;
498 case CLKID_VAPB_0_SEL:
499 parm = &meson_vapb_0_mux_parm;
500 parents = meson_vapb_0_1_mux_parents;
501 break;
502 case CLKID_VAPB_1_SEL:
503 parm = &meson_vapb_1_mux_parm;
504 parents = meson_vapb_0_1_mux_parents;
505 break;
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200506 case CLKID_HDMI_SEL:
507 parm = &meson_hdmi_mux_parm;
508 parents = meson_hdmi_mux_parents;
509 break;
Neil Armstrong07f24772018-08-06 14:49:20 +0200510 default:
511 return -ENOENT;
512 }
513
Loic Devulderc0379032018-11-27 17:41:18 +0100514 regmap_read(priv->map, parm->reg_off, &reg);
Neil Armstrong07f24772018-08-06 14:49:20 +0200515 reg = PARM_GET(parm->width, parm->shift, reg);
516
517 debug("%s: parent of %ld is %d (%d)\n",
518 __func__, id, parents[reg], reg);
519
520 return parents[reg];
521}
522
523static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
524 unsigned long parent_id)
525{
526 unsigned long cur_parent = meson_mux_get_parent(clk, id);
527 struct meson_clk *priv = dev_get_priv(clk->dev);
528 unsigned int new_index = -EINVAL;
529 struct parm *parm;
530 int *parents;
Neil Armstrong07f24772018-08-06 14:49:20 +0200531 int i;
532
533 if (IS_ERR_VALUE(cur_parent))
534 return cur_parent;
535
536 debug("%s: setting parent of %ld from %ld to %ld\n",
537 __func__, id, cur_parent, parent_id);
538
539 if (cur_parent == parent_id)
540 return 0;
541
542 switch (id) {
543 case CLKID_VPU:
544 parm = &meson_vpu_mux_parm;
545 parents = meson_vpu_mux_parents;
546 break;
547 case CLKID_VPU_0_SEL:
548 parm = &meson_vpu_0_mux_parm;
549 parents = meson_vpu_0_1_mux_parents;
550 break;
551 case CLKID_VPU_1_SEL:
552 parm = &meson_vpu_1_mux_parm;
553 parents = meson_vpu_0_1_mux_parents;
554 break;
555 case CLKID_VAPB_SEL:
556 parm = &meson_vapb_sel_mux_parm;
557 parents = meson_vapb_sel_mux_parents;
558 break;
559 case CLKID_VAPB_0_SEL:
560 parm = &meson_vapb_0_mux_parm;
561 parents = meson_vapb_0_1_mux_parents;
562 break;
563 case CLKID_VAPB_1_SEL:
564 parm = &meson_vapb_1_mux_parm;
565 parents = meson_vapb_0_1_mux_parents;
566 break;
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200567 case CLKID_HDMI_SEL:
568 parm = &meson_hdmi_mux_parm;
569 parents = meson_hdmi_mux_parents;
570 break;
Neil Armstrong07f24772018-08-06 14:49:20 +0200571 default:
572 /* Not a mux */
573 return -ENOENT;
574 }
575
576 for (i = 0 ; i < (1 << parm->width) ; ++i) {
577 if (parents[i] == parent_id)
578 new_index = i;
579 }
580
581 if (IS_ERR_VALUE(new_index))
582 return new_index;
583
584 debug("%s: new index of %ld is %d\n", __func__, id, new_index);
585
Loic Devulderc0379032018-11-27 17:41:18 +0100586 regmap_update_bits(priv->map, parm->reg_off, SETPMASK(parm->width, parm->shift),
587 new_index << parm->shift);
Neil Armstrong07f24772018-08-06 14:49:20 +0200588
589 debug("%s: new parent of %ld is %ld\n",
590 __func__, id, meson_mux_get_parent(clk, id));
591
592 return 0;
593}
594
595static ulong meson_mux_get_rate(struct clk *clk, unsigned long id)
596{
597 int parent = meson_mux_get_parent(clk, id);
598
599 if (IS_ERR_VALUE(parent))
600 return parent;
601
602 return meson_clk_get_rate_by_id(clk, parent);
603}
604
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200605static unsigned long meson_clk81_get_rate(struct clk *clk)
606{
607 struct meson_clk *priv = dev_get_priv(clk->dev);
608 unsigned long parent_rate;
Loic Devulderc0379032018-11-27 17:41:18 +0100609 uint reg;
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200610 int parents[] = {
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200611 CLKID_XTAL,
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200612 -1,
613 CLKID_FCLK_DIV7,
614 CLKID_MPLL1,
615 CLKID_MPLL2,
616 CLKID_FCLK_DIV4,
617 CLKID_FCLK_DIV3,
618 CLKID_FCLK_DIV5
619 };
620
621 /* mux */
Loic Devulderc0379032018-11-27 17:41:18 +0100622 regmap_read(priv->map, HHI_MPEG_CLK_CNTL, &reg);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200623 reg = (reg >> 12) & 7;
624
625 switch (reg) {
626 case 0:
627 parent_rate = XTAL_RATE;
628 break;
629 case 1:
630 return -ENOENT;
631 default:
632 parent_rate = meson_clk_get_rate_by_id(clk, parents[reg]);
633 }
634
635 /* divider */
Loic Devulderc0379032018-11-27 17:41:18 +0100636 regmap_read(priv->map, HHI_MPEG_CLK_CNTL, &reg);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200637 reg = reg & ((1 << 7) - 1);
638
Jerome Brunet0107c612018-11-13 11:38:38 +0100639 /* clk81 divider is zero based */
640 return parent_rate / (reg + 1);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200641}
642
643static long mpll_rate_from_params(unsigned long parent_rate,
644 unsigned long sdm,
645 unsigned long n2)
646{
647 unsigned long divisor = (SDM_DEN * n2) + sdm;
648
649 if (n2 < N2_MIN)
650 return -EINVAL;
651
652 return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor);
653}
654
655static struct parm meson_mpll0_parm[3] = {
656 {HHI_MPLL_CNTL7, 0, 14}, /* psdm */
657 {HHI_MPLL_CNTL7, 16, 9}, /* pn2 */
658};
659
660static struct parm meson_mpll1_parm[3] = {
661 {HHI_MPLL_CNTL8, 0, 14}, /* psdm */
662 {HHI_MPLL_CNTL8, 16, 9}, /* pn2 */
663};
664
665static struct parm meson_mpll2_parm[3] = {
666 {HHI_MPLL_CNTL9, 0, 14}, /* psdm */
667 {HHI_MPLL_CNTL9, 16, 9}, /* pn2 */
668};
669
670/*
671 * MultiPhase Locked Loops are outputs from a PLL with additional frequency
672 * scaling capabilities. MPLL rates are calculated as:
673 *
674 * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384)
675 */
676static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id)
677{
678 struct meson_clk *priv = dev_get_priv(clk->dev);
679 struct parm *psdm, *pn2;
Loic Devulderc0379032018-11-27 17:41:18 +0100680 unsigned long sdm, n2;
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200681 unsigned long parent_rate;
Loic Devulderc0379032018-11-27 17:41:18 +0100682 uint reg;
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200683
684 switch (id) {
685 case CLKID_MPLL0:
686 psdm = &meson_mpll0_parm[0];
687 pn2 = &meson_mpll0_parm[1];
688 break;
689 case CLKID_MPLL1:
690 psdm = &meson_mpll1_parm[0];
691 pn2 = &meson_mpll1_parm[1];
692 break;
693 case CLKID_MPLL2:
694 psdm = &meson_mpll2_parm[0];
695 pn2 = &meson_mpll2_parm[1];
696 break;
697 default:
698 return -ENOENT;
699 }
700
701 parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL);
702 if (IS_ERR_VALUE(parent_rate))
703 return parent_rate;
704
Loic Devulderc0379032018-11-27 17:41:18 +0100705 regmap_read(priv->map, psdm->reg_off, &reg);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200706 sdm = PARM_GET(psdm->width, psdm->shift, reg);
707
Loic Devulderc0379032018-11-27 17:41:18 +0100708 regmap_read(priv->map, pn2->reg_off, &reg);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200709 n2 = PARM_GET(pn2->width, pn2->shift, reg);
710
711 return mpll_rate_from_params(parent_rate, sdm, n2);
712}
713
714static struct parm meson_fixed_pll_parm[3] = {
715 {HHI_MPLL_CNTL, 0, 9}, /* pm */
716 {HHI_MPLL_CNTL, 9, 5}, /* pn */
717 {HHI_MPLL_CNTL, 16, 2}, /* pod */
718};
719
720static struct parm meson_sys_pll_parm[3] = {
721 {HHI_SYS_PLL_CNTL, 0, 9}, /* pm */
722 {HHI_SYS_PLL_CNTL, 9, 5}, /* pn */
723 {HHI_SYS_PLL_CNTL, 10, 2}, /* pod */
724};
725
726static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
727{
728 struct meson_clk *priv = dev_get_priv(clk->dev);
729 struct parm *pm, *pn, *pod;
730 unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
731 u16 n, m, od;
Loic Devulderc0379032018-11-27 17:41:18 +0100732 uint reg;
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200733
734 switch (id) {
735 case CLKID_FIXED_PLL:
736 pm = &meson_fixed_pll_parm[0];
737 pn = &meson_fixed_pll_parm[1];
738 pod = &meson_fixed_pll_parm[2];
739 break;
740 case CLKID_SYS_PLL:
741 pm = &meson_sys_pll_parm[0];
742 pn = &meson_sys_pll_parm[1];
743 pod = &meson_sys_pll_parm[2];
744 break;
745 default:
746 return -ENOENT;
747 }
748
Loic Devulderc0379032018-11-27 17:41:18 +0100749 regmap_read(priv->map, pn->reg_off, &reg);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200750 n = PARM_GET(pn->width, pn->shift, reg);
751
Loic Devulderc0379032018-11-27 17:41:18 +0100752 regmap_read(priv->map, pm->reg_off, &reg);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200753 m = PARM_GET(pm->width, pm->shift, reg);
754
Loic Devulderc0379032018-11-27 17:41:18 +0100755 regmap_read(priv->map, pod->reg_off, &reg);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200756 od = PARM_GET(pod->width, pod->shift, reg);
757
758 return ((parent_rate_mhz * m / n) >> od) * 1000000;
759}
760
761static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
762{
763 ulong rate;
764
765 switch (id) {
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200766 case CLKID_XTAL:
767 rate = XTAL_RATE;
768 break;
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200769 case CLKID_FIXED_PLL:
770 case CLKID_SYS_PLL:
771 rate = meson_pll_get_rate(clk, id);
772 break;
773 case CLKID_FCLK_DIV2:
774 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2;
775 break;
776 case CLKID_FCLK_DIV3:
777 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3;
778 break;
779 case CLKID_FCLK_DIV4:
780 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4;
781 break;
782 case CLKID_FCLK_DIV5:
783 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5;
784 break;
785 case CLKID_FCLK_DIV7:
786 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7;
787 break;
788 case CLKID_MPLL0:
789 case CLKID_MPLL1:
790 case CLKID_MPLL2:
791 rate = meson_mpll_get_rate(clk, id);
792 break;
793 case CLKID_CLK81:
794 rate = meson_clk81_get_rate(clk);
795 break;
Neil Armstrong07f24772018-08-06 14:49:20 +0200796 case CLKID_VPU_0:
797 rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV);
798 break;
799 case CLKID_VPU_1:
800 rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV);
801 break;
802 case CLKID_VAPB:
803 rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL);
804 break;
805 case CLKID_VAPB_0:
806 rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV);
807 break;
808 case CLKID_VAPB_1:
809 rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV);
810 break;
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200811 case CLKID_HDMI:
812 rate = meson_div_get_rate(clk, CLKID_HDMI_DIV);
813 break;
Neil Armstrong07f24772018-08-06 14:49:20 +0200814 case CLKID_VPU_0_DIV:
815 case CLKID_VPU_1_DIV:
816 case CLKID_VAPB_0_DIV:
817 case CLKID_VAPB_1_DIV:
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200818 case CLKID_HDMI_DIV:
Neil Armstrong07f24772018-08-06 14:49:20 +0200819 rate = meson_div_get_rate(clk, id);
820 break;
821 case CLKID_VPU:
822 case CLKID_VPU_0_SEL:
823 case CLKID_VPU_1_SEL:
824 case CLKID_VAPB_SEL:
825 case CLKID_VAPB_0_SEL:
826 case CLKID_VAPB_1_SEL:
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200827 case CLKID_HDMI_SEL:
Neil Armstrong07f24772018-08-06 14:49:20 +0200828 rate = meson_mux_get_rate(clk, id);
829 break;
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200830 default:
831 if (gates[id].reg != 0) {
832 /* a clock gate */
833 rate = meson_clk81_get_rate(clk);
834 break;
835 }
836 return -ENOENT;
837 }
838
Jerome Brunet0af42332018-10-26 15:42:50 +0200839 debug("clock %lu has rate %lu\n", id, rate);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200840 return rate;
841}
842
843static ulong meson_clk_get_rate(struct clk *clk)
844{
845 return meson_clk_get_rate_by_id(clk, clk->id);
846}
847
Neil Armstrong07f24772018-08-06 14:49:20 +0200848static int meson_clk_set_parent(struct clk *clk, struct clk *parent)
849{
850 return meson_mux_set_parent(clk, clk->id, parent->id);
851}
852
853static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
854 ulong rate, ulong current_rate)
855{
856 if (current_rate == rate)
857 return 0;
858
859 switch (id) {
860 /* Fixed clocks */
861 case CLKID_FIXED_PLL:
862 case CLKID_SYS_PLL:
863 case CLKID_FCLK_DIV2:
864 case CLKID_FCLK_DIV3:
865 case CLKID_FCLK_DIV4:
866 case CLKID_FCLK_DIV5:
867 case CLKID_FCLK_DIV7:
868 case CLKID_MPLL0:
869 case CLKID_MPLL1:
870 case CLKID_MPLL2:
871 case CLKID_CLK81:
Heinrich Schuchardt20072a62019-07-30 23:03:43 +0200872 return -EINVAL;
Neil Armstrong07f24772018-08-06 14:49:20 +0200873 case CLKID_VPU:
874 return meson_clk_set_rate_by_id(clk,
875 meson_mux_get_parent(clk, CLKID_VPU), rate,
876 current_rate);
877 case CLKID_VAPB:
878 case CLKID_VAPB_SEL:
879 return meson_clk_set_rate_by_id(clk,
880 meson_mux_get_parent(clk, CLKID_VAPB_SEL),
881 rate, current_rate);
882 case CLKID_VPU_0:
883 return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate,
884 current_rate);
885 case CLKID_VPU_1:
886 return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate,
887 current_rate);
888 case CLKID_VAPB_0:
889 return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate,
890 current_rate);
891 case CLKID_VAPB_1:
892 return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate,
893 current_rate);
894 case CLKID_VPU_0_DIV:
895 case CLKID_VPU_1_DIV:
896 case CLKID_VAPB_0_DIV:
897 case CLKID_VAPB_1_DIV:
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200898 case CLKID_HDMI_DIV:
Neil Armstrong07f24772018-08-06 14:49:20 +0200899 return meson_div_set_rate(clk, id, rate, current_rate);
Neil Armstrong7481d3c2024-10-09 11:15:20 +0200900 case CLKID_HDMI:
901 return meson_clk_set_rate_by_id(clk, CLKID_HDMI_DIV,
902 rate, current_rate);
Neil Armstrong07f24772018-08-06 14:49:20 +0200903 default:
904 return -ENOENT;
905 }
906
907 return -EINVAL;
908}
909
910static ulong meson_clk_set_rate(struct clk *clk, ulong rate)
911{
912 ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id);
913 int ret;
914
915 if (IS_ERR_VALUE(current_rate))
916 return current_rate;
917
918 debug("%s: setting rate of %ld from %ld to %ld\n",
919 __func__, clk->id, current_rate, rate);
920
921 ret = meson_clk_set_rate_by_id(clk, clk->id, rate, current_rate);
922 if (IS_ERR_VALUE(ret))
923 return ret;
924
Loic Devulderc0379032018-11-27 17:41:18 +0100925 debug("clock %lu has new rate %lu\n", clk->id,
926 meson_clk_get_rate_by_id(clk, clk->id));
Neil Armstrong07f24772018-08-06 14:49:20 +0200927
928 return 0;
929}
930
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200931static int meson_clk_probe(struct udevice *dev)
932{
933 struct meson_clk *priv = dev_get_priv(dev);
934
Simon Glassa7ece582020-12-19 10:40:14 -0700935 priv->map = syscon_node_to_regmap(dev_ofnode(dev_get_parent(dev)));
Loic Devulderc0379032018-11-27 17:41:18 +0100936 if (IS_ERR(priv->map))
937 return PTR_ERR(priv->map);
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200938
Jerome Brunet01c89ea2020-03-05 12:12:37 +0100939 /*
940 * Depending on the boot src, the state of the MMC clock might
941 * be different. Reset it to make sure we won't get stuck
942 */
943 regmap_write(priv->map, HHI_NAND_CLK_CNTL, 0);
944 regmap_write(priv->map, HHI_SD_EMMC_CLK_CNTL, 0);
945
Loic Devulderc0379032018-11-27 17:41:18 +0100946 debug("meson-clk: probed\n");
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200947
948 return 0;
949}
950
951static struct clk_ops meson_clk_ops = {
952 .disable = meson_clk_disable,
953 .enable = meson_clk_enable,
954 .get_rate = meson_clk_get_rate,
Neil Armstrong07f24772018-08-06 14:49:20 +0200955 .set_parent = meson_clk_set_parent,
956 .set_rate = meson_clk_set_rate,
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200957};
958
959static const struct udevice_id meson_clk_ids[] = {
960 { .compatible = "amlogic,gxbb-clkc" },
961 { .compatible = "amlogic,gxl-clkc" },
962 { }
963};
964
965U_BOOT_DRIVER(meson_clk) = {
966 .name = "meson_clk",
967 .id = UCLASS_CLK,
968 .of_match = meson_clk_ids,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700969 .priv_auto = sizeof(struct meson_clk),
Beniamino Galvanib67bfaf2018-06-14 13:43:39 +0200970 .ops = &meson_clk_ops,
971 .probe = meson_clk_probe,
972};