2 * Copyright (C) 2016 NVIDIA Corporation
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/clk-provider.h>
10 #include <linux/device.h>
11 #include <linux/seq_buf.h>
12 #include <linux/slab.h>
14 #include <soc/tegra/bpmp.h>
15 #include <soc/tegra/bpmp-abi.h>
17 #define TEGRA_BPMP_DUMP_CLOCK_INFO 0
19 #define TEGRA_BPMP_CLK_HAS_MUX BIT(0)
20 #define TEGRA_BPMP_CLK_HAS_SET_RATE BIT(1)
21 #define TEGRA_BPMP_CLK_IS_ROOT BIT(2)
23 struct tegra_bpmp_clk_info
{
25 char name
[MRQ_CLK_NAME_MAXLEN
];
26 unsigned int parents
[MRQ_CLK_MAX_PARENTS
];
27 unsigned int num_parents
;
31 struct tegra_bpmp_clk
{
34 struct tegra_bpmp
*bpmp
;
37 unsigned int num_parents
;
38 unsigned int *parents
;
41 static inline struct tegra_bpmp_clk
*to_tegra_bpmp_clk(struct clk_hw
*hw
)
43 return container_of(hw
, struct tegra_bpmp_clk
, hw
);
46 struct tegra_bpmp_clk_message
{
62 static int tegra_bpmp_clk_transfer(struct tegra_bpmp
*bpmp
,
63 const struct tegra_bpmp_clk_message
*clk
)
65 struct mrq_clk_request request
;
66 struct tegra_bpmp_message msg
;
70 memset(&request
, 0, sizeof(request
));
71 request
.cmd_and_id
= (clk
->cmd
<< 24) | clk
->id
;
74 * The mrq_clk_request structure has an anonymous union at offset 4
75 * that contains all possible sub-command structures. Copy the data
76 * to that union. Ideally we'd be able to refer to it by name, but
77 * doing so would require changing the ABI header and increase the
80 memcpy(req
+ 4, clk
->tx
.data
, clk
->tx
.size
);
82 memset(&msg
, 0, sizeof(msg
));
84 msg
.tx
.data
= &request
;
85 msg
.tx
.size
= sizeof(request
);
86 msg
.rx
.data
= clk
->rx
.data
;
87 msg
.rx
.size
= clk
->rx
.size
;
89 err
= tegra_bpmp_transfer(bpmp
, &msg
);
92 else if (msg
.rx
.ret
< 0)
98 static int tegra_bpmp_clk_prepare(struct clk_hw
*hw
)
100 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
101 struct tegra_bpmp_clk_message msg
;
103 memset(&msg
, 0, sizeof(msg
));
104 msg
.cmd
= CMD_CLK_ENABLE
;
107 return tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
110 static void tegra_bpmp_clk_unprepare(struct clk_hw
*hw
)
112 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
113 struct tegra_bpmp_clk_message msg
;
116 memset(&msg
, 0, sizeof(msg
));
117 msg
.cmd
= CMD_CLK_DISABLE
;
120 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
122 dev_err(clk
->bpmp
->dev
, "failed to disable clock %s: %d\n",
123 clk_hw_get_name(hw
), err
);
126 static int tegra_bpmp_clk_is_prepared(struct clk_hw
*hw
)
128 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
129 struct cmd_clk_is_enabled_response response
;
130 struct tegra_bpmp_clk_message msg
;
133 memset(&msg
, 0, sizeof(msg
));
134 msg
.cmd
= CMD_CLK_IS_ENABLED
;
136 msg
.rx
.data
= &response
;
137 msg
.rx
.size
= sizeof(response
);
139 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
143 return response
.state
;
146 static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw
*hw
,
147 unsigned long parent_rate
)
149 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
150 struct cmd_clk_get_rate_response response
;
151 struct cmd_clk_get_rate_request request
;
152 struct tegra_bpmp_clk_message msg
;
155 memset(&msg
, 0, sizeof(msg
));
156 msg
.cmd
= CMD_CLK_GET_RATE
;
158 msg
.tx
.data
= &request
;
159 msg
.tx
.size
= sizeof(request
);
160 msg
.rx
.data
= &response
;
161 msg
.rx
.size
= sizeof(response
);
163 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
167 return response
.rate
;
170 static long tegra_bpmp_clk_round_rate(struct clk_hw
*hw
, unsigned long rate
,
171 unsigned long *parent_rate
)
173 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
174 struct cmd_clk_round_rate_response response
;
175 struct cmd_clk_round_rate_request request
;
176 struct tegra_bpmp_clk_message msg
;
179 memset(&request
, 0, sizeof(request
));
182 memset(&msg
, 0, sizeof(msg
));
183 msg
.cmd
= CMD_CLK_ROUND_RATE
;
185 msg
.tx
.data
= &request
;
186 msg
.tx
.size
= sizeof(request
);
187 msg
.rx
.data
= &response
;
188 msg
.rx
.size
= sizeof(response
);
190 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
194 return response
.rate
;
197 static int tegra_bpmp_clk_set_parent(struct clk_hw
*hw
, u8 index
)
199 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
200 struct cmd_clk_set_parent_response response
;
201 struct cmd_clk_set_parent_request request
;
202 struct tegra_bpmp_clk_message msg
;
205 memset(&request
, 0, sizeof(request
));
206 request
.parent_id
= clk
->parents
[index
];
208 memset(&msg
, 0, sizeof(msg
));
209 msg
.cmd
= CMD_CLK_SET_PARENT
;
211 msg
.tx
.data
= &request
;
212 msg
.tx
.size
= sizeof(request
);
213 msg
.rx
.data
= &response
;
214 msg
.rx
.size
= sizeof(response
);
216 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
220 /* XXX check parent ID in response */
225 static u8
tegra_bpmp_clk_get_parent(struct clk_hw
*hw
)
227 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
228 struct cmd_clk_get_parent_response response
;
229 struct tegra_bpmp_clk_message msg
;
233 memset(&msg
, 0, sizeof(msg
));
234 msg
.cmd
= CMD_CLK_GET_PARENT
;
236 msg
.rx
.data
= &response
;
237 msg
.rx
.size
= sizeof(response
);
239 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
241 dev_err(clk
->bpmp
->dev
, "failed to get parent for %s: %d\n",
242 clk_hw_get_name(hw
), err
);
246 for (i
= 0; i
< clk
->num_parents
; i
++)
247 if (clk
->parents
[i
] == response
.parent_id
)
253 static int tegra_bpmp_clk_set_rate(struct clk_hw
*hw
, unsigned long rate
,
254 unsigned long parent_rate
)
256 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
257 struct cmd_clk_set_rate_response response
;
258 struct cmd_clk_set_rate_request request
;
259 struct tegra_bpmp_clk_message msg
;
261 memset(&request
, 0, sizeof(request
));
264 memset(&msg
, 0, sizeof(msg
));
265 msg
.cmd
= CMD_CLK_SET_RATE
;
267 msg
.tx
.data
= &request
;
268 msg
.tx
.size
= sizeof(request
);
269 msg
.rx
.data
= &response
;
270 msg
.rx
.size
= sizeof(response
);
272 return tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
275 static const struct clk_ops tegra_bpmp_clk_gate_ops
= {
276 .prepare
= tegra_bpmp_clk_prepare
,
277 .unprepare
= tegra_bpmp_clk_unprepare
,
278 .is_prepared
= tegra_bpmp_clk_is_prepared
,
279 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
282 static const struct clk_ops tegra_bpmp_clk_mux_ops
= {
283 .prepare
= tegra_bpmp_clk_prepare
,
284 .unprepare
= tegra_bpmp_clk_unprepare
,
285 .is_prepared
= tegra_bpmp_clk_is_prepared
,
286 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
287 .set_parent
= tegra_bpmp_clk_set_parent
,
288 .get_parent
= tegra_bpmp_clk_get_parent
,
291 static const struct clk_ops tegra_bpmp_clk_rate_ops
= {
292 .prepare
= tegra_bpmp_clk_prepare
,
293 .unprepare
= tegra_bpmp_clk_unprepare
,
294 .is_prepared
= tegra_bpmp_clk_is_prepared
,
295 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
296 .round_rate
= tegra_bpmp_clk_round_rate
,
297 .set_rate
= tegra_bpmp_clk_set_rate
,
300 static const struct clk_ops tegra_bpmp_clk_mux_rate_ops
= {
301 .prepare
= tegra_bpmp_clk_prepare
,
302 .unprepare
= tegra_bpmp_clk_unprepare
,
303 .is_prepared
= tegra_bpmp_clk_is_prepared
,
304 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
305 .round_rate
= tegra_bpmp_clk_round_rate
,
306 .set_parent
= tegra_bpmp_clk_set_parent
,
307 .get_parent
= tegra_bpmp_clk_get_parent
,
308 .set_rate
= tegra_bpmp_clk_set_rate
,
311 static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp
*bpmp
)
313 struct cmd_clk_get_max_clk_id_response response
;
314 struct tegra_bpmp_clk_message msg
;
317 memset(&msg
, 0, sizeof(msg
));
318 msg
.cmd
= CMD_CLK_GET_MAX_CLK_ID
;
319 msg
.rx
.data
= &response
;
320 msg
.rx
.size
= sizeof(response
);
322 err
= tegra_bpmp_clk_transfer(bpmp
, &msg
);
326 if (response
.max_id
> INT_MAX
)
329 return response
.max_id
;
332 static int tegra_bpmp_clk_get_info(struct tegra_bpmp
*bpmp
, unsigned int id
,
333 struct tegra_bpmp_clk_info
*info
)
335 struct cmd_clk_get_all_info_response response
;
336 struct tegra_bpmp_clk_message msg
;
340 memset(&msg
, 0, sizeof(msg
));
341 msg
.cmd
= CMD_CLK_GET_ALL_INFO
;
343 msg
.rx
.data
= &response
;
344 msg
.rx
.size
= sizeof(response
);
346 err
= tegra_bpmp_clk_transfer(bpmp
, &msg
);
350 strlcpy(info
->name
, response
.name
, MRQ_CLK_NAME_MAXLEN
);
351 info
->num_parents
= response
.num_parents
;
353 for (i
= 0; i
< info
->num_parents
; i
++)
354 info
->parents
[i
] = response
.parents
[i
];
356 info
->flags
= response
.flags
;
361 static void tegra_bpmp_clk_info_dump(struct tegra_bpmp
*bpmp
,
363 const struct tegra_bpmp_clk_info
*info
)
365 const char *prefix
= "";
370 seq_buf_init(&buf
, flags
, sizeof(flags
));
373 seq_buf_printf(&buf
, "(");
375 if (info
->flags
& TEGRA_BPMP_CLK_HAS_MUX
) {
376 seq_buf_printf(&buf
, "%smux", prefix
);
380 if ((info
->flags
& TEGRA_BPMP_CLK_HAS_SET_RATE
) == 0) {
381 seq_buf_printf(&buf
, "%sfixed", prefix
);
385 if (info
->flags
& TEGRA_BPMP_CLK_IS_ROOT
) {
386 seq_buf_printf(&buf
, "%sroot", prefix
);
391 seq_buf_printf(&buf
, ")");
393 dev_printk(level
, bpmp
->dev
, "%03u: %s\n", info
->id
, info
->name
);
394 dev_printk(level
, bpmp
->dev
, " flags: %lx %s\n", info
->flags
, flags
);
395 dev_printk(level
, bpmp
->dev
, " parents: %u\n", info
->num_parents
);
397 for (i
= 0; i
< info
->num_parents
; i
++)
398 dev_printk(level
, bpmp
->dev
, " %03u\n", info
->parents
[i
]);
401 static int tegra_bpmp_probe_clocks(struct tegra_bpmp
*bpmp
,
402 struct tegra_bpmp_clk_info
**clocksp
)
404 struct tegra_bpmp_clk_info
*clocks
;
405 unsigned int max_id
, id
, count
= 0;
406 unsigned int holes
= 0;
409 err
= tegra_bpmp_clk_get_max_id(bpmp
);
415 dev_dbg(bpmp
->dev
, "maximum clock ID: %u\n", max_id
);
417 clocks
= kcalloc(max_id
+ 1, sizeof(*clocks
), GFP_KERNEL
);
421 for (id
= 0; id
<= max_id
; id
++) {
422 struct tegra_bpmp_clk_info
*info
= &clocks
[count
];
424 err
= tegra_bpmp_clk_get_info(bpmp
, id
, info
);
428 if (info
->num_parents
>= U8_MAX
) {
430 "clock %u has too many parents (%u, max: %u)\n",
431 id
, info
->num_parents
, U8_MAX
);
435 /* clock not exposed by BPMP */
436 if (info
->name
[0] == '\0') {
444 if (TEGRA_BPMP_DUMP_CLOCK_INFO
)
445 tegra_bpmp_clk_info_dump(bpmp
, KERN_DEBUG
, info
);
448 dev_dbg(bpmp
->dev
, "holes: %u\n", holes
);
454 static const struct tegra_bpmp_clk_info
*
455 tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info
*clocks
,
456 unsigned int num_clocks
, unsigned int id
)
460 for (i
= 0; i
< num_clocks
; i
++)
461 if (clocks
[i
].id
== id
)
467 static struct tegra_bpmp_clk
*
468 tegra_bpmp_clk_register(struct tegra_bpmp
*bpmp
,
469 const struct tegra_bpmp_clk_info
*info
,
470 const struct tegra_bpmp_clk_info
*clocks
,
471 unsigned int num_clocks
)
473 struct tegra_bpmp_clk
*clk
;
474 struct clk_init_data init
;
475 const char **parents
;
479 clk
= devm_kzalloc(bpmp
->dev
, sizeof(*clk
), GFP_KERNEL
);
481 return ERR_PTR(-ENOMEM
);
486 clk
->parents
= devm_kcalloc(bpmp
->dev
, info
->num_parents
,
487 sizeof(*clk
->parents
), GFP_KERNEL
);
489 return ERR_PTR(-ENOMEM
);
491 clk
->num_parents
= info
->num_parents
;
493 /* hardware clock initialization */
494 memset(&init
, 0, sizeof(init
));
495 init
.name
= info
->name
;
496 clk
->hw
.init
= &init
;
498 if (info
->flags
& TEGRA_BPMP_CLK_HAS_MUX
) {
499 if (info
->flags
& TEGRA_BPMP_CLK_HAS_SET_RATE
)
500 init
.ops
= &tegra_bpmp_clk_mux_rate_ops
;
502 init
.ops
= &tegra_bpmp_clk_mux_ops
;
504 if (info
->flags
& TEGRA_BPMP_CLK_HAS_SET_RATE
)
505 init
.ops
= &tegra_bpmp_clk_rate_ops
;
507 init
.ops
= &tegra_bpmp_clk_gate_ops
;
510 init
.num_parents
= info
->num_parents
;
512 parents
= kcalloc(info
->num_parents
, sizeof(*parents
), GFP_KERNEL
);
514 return ERR_PTR(-ENOMEM
);
516 for (i
= 0; i
< info
->num_parents
; i
++) {
517 const struct tegra_bpmp_clk_info
*parent
;
519 /* keep a private copy of the ID to parent index map */
520 clk
->parents
[i
] = info
->parents
[i
];
522 parent
= tegra_bpmp_clk_find(clocks
, num_clocks
,
525 dev_err(bpmp
->dev
, "no parent %u found for %u\n",
526 info
->parents
[i
], info
->id
);
530 parents
[i
] = parent
->name
;
533 init
.parent_names
= parents
;
535 err
= devm_clk_hw_register(bpmp
->dev
, &clk
->hw
);
545 static int tegra_bpmp_register_clocks(struct tegra_bpmp
*bpmp
,
546 struct tegra_bpmp_clk_info
*infos
,
549 struct tegra_bpmp_clk
*clk
;
552 bpmp
->num_clocks
= count
;
554 bpmp
->clocks
= devm_kcalloc(bpmp
->dev
, count
, sizeof(clk
), GFP_KERNEL
);
558 for (i
= 0; i
< count
; i
++) {
559 struct tegra_bpmp_clk_info
*info
= &infos
[i
];
561 clk
= tegra_bpmp_clk_register(bpmp
, info
, infos
, count
);
564 "failed to register clock %u (%s): %ld\n",
565 info
->id
, info
->name
, PTR_ERR(clk
));
569 bpmp
->clocks
[i
] = clk
;
575 static void tegra_bpmp_unregister_clocks(struct tegra_bpmp
*bpmp
)
579 for (i
= 0; i
< bpmp
->num_clocks
; i
++)
580 clk_hw_unregister(&bpmp
->clocks
[i
]->hw
);
583 static struct clk_hw
*tegra_bpmp_clk_of_xlate(struct of_phandle_args
*clkspec
,
586 unsigned int id
= clkspec
->args
[0], i
;
587 struct tegra_bpmp
*bpmp
= data
;
589 for (i
= 0; i
< bpmp
->num_clocks
; i
++)
590 if (bpmp
->clocks
[i
]->id
== id
)
591 return &bpmp
->clocks
[i
]->hw
;
596 int tegra_bpmp_init_clocks(struct tegra_bpmp
*bpmp
)
598 struct tegra_bpmp_clk_info
*clocks
;
602 err
= tegra_bpmp_probe_clocks(bpmp
, &clocks
);
608 dev_dbg(bpmp
->dev
, "%u clocks probed\n", count
);
610 err
= tegra_bpmp_register_clocks(bpmp
, clocks
, count
);
614 err
= of_clk_add_hw_provider(bpmp
->dev
->of_node
,
615 tegra_bpmp_clk_of_xlate
,
618 tegra_bpmp_unregister_clocks(bpmp
);