GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / clk / tegra / clk-bpmp.c
1 /*
2  * Copyright (C) 2016 NVIDIA Corporation
3  *
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.
7  */
8
9 #include <linux/clk-provider.h>
10 #include <linux/device.h>
11 #include <linux/seq_buf.h>
12 #include <linux/slab.h>
13
14 #include <soc/tegra/bpmp.h>
15 #include <soc/tegra/bpmp-abi.h>
16
17 #define TEGRA_BPMP_DUMP_CLOCK_INFO      0
18
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)
22
23 struct tegra_bpmp_clk_info {
24         unsigned int id;
25         char name[MRQ_CLK_NAME_MAXLEN];
26         unsigned int parents[MRQ_CLK_MAX_PARENTS];
27         unsigned int num_parents;
28         unsigned long flags;
29 };
30
31 struct tegra_bpmp_clk {
32         struct clk_hw hw;
33
34         struct tegra_bpmp *bpmp;
35         unsigned int id;
36
37         unsigned int num_parents;
38         unsigned int *parents;
39 };
40
41 static inline struct tegra_bpmp_clk *to_tegra_bpmp_clk(struct clk_hw *hw)
42 {
43         return container_of(hw, struct tegra_bpmp_clk, hw);
44 }
45
46 struct tegra_bpmp_clk_message {
47         unsigned int cmd;
48         unsigned int id;
49
50         struct {
51                 const void *data;
52                 size_t size;
53         } tx;
54
55         struct {
56                 void *data;
57                 size_t size;
58                 int ret;
59         } rx;
60 };
61
62 static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp,
63                                    const struct tegra_bpmp_clk_message *clk)
64 {
65         struct mrq_clk_request request;
66         struct tegra_bpmp_message msg;
67         void *req = &request;
68         int err;
69
70         memset(&request, 0, sizeof(request));
71         request.cmd_and_id = (clk->cmd << 24) | clk->id;
72
73         /*
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
78          * maintenance burden.
79          */
80         memcpy(req + 4, clk->tx.data, clk->tx.size);
81
82         memset(&msg, 0, sizeof(msg));
83         msg.mrq = MRQ_CLK;
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;
88
89         err = tegra_bpmp_transfer(bpmp, &msg);
90         if (err < 0)
91                 return err;
92         else if (msg.rx.ret < 0)
93                 return -EINVAL;
94
95         return 0;
96 }
97
98 static int tegra_bpmp_clk_prepare(struct clk_hw *hw)
99 {
100         struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
101         struct tegra_bpmp_clk_message msg;
102
103         memset(&msg, 0, sizeof(msg));
104         msg.cmd = CMD_CLK_ENABLE;
105         msg.id = clk->id;
106
107         return tegra_bpmp_clk_transfer(clk->bpmp, &msg);
108 }
109
110 static void tegra_bpmp_clk_unprepare(struct clk_hw *hw)
111 {
112         struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
113         struct tegra_bpmp_clk_message msg;
114         int err;
115
116         memset(&msg, 0, sizeof(msg));
117         msg.cmd = CMD_CLK_DISABLE;
118         msg.id = clk->id;
119
120         err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
121         if (err < 0)
122                 dev_err(clk->bpmp->dev, "failed to disable clock %s: %d\n",
123                         clk_hw_get_name(hw), err);
124 }
125
126 static int tegra_bpmp_clk_is_prepared(struct clk_hw *hw)
127 {
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;
131         int err;
132
133         memset(&msg, 0, sizeof(msg));
134         msg.cmd = CMD_CLK_IS_ENABLED;
135         msg.id = clk->id;
136         msg.rx.data = &response;
137         msg.rx.size = sizeof(response);
138
139         err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
140         if (err < 0)
141                 return err;
142
143         return response.state;
144 }
145
146 static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw,
147                                                 unsigned long parent_rate)
148 {
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;
153         int err;
154
155         memset(&msg, 0, sizeof(msg));
156         msg.cmd = CMD_CLK_GET_RATE;
157         msg.id = clk->id;
158         msg.tx.data = &request;
159         msg.tx.size = sizeof(request);
160         msg.rx.data = &response;
161         msg.rx.size = sizeof(response);
162
163         err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
164         if (err < 0)
165                 return err;
166
167         return response.rate;
168 }
169
170 static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate,
171                                       unsigned long *parent_rate)
172 {
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;
177         int err;
178
179         memset(&request, 0, sizeof(request));
180         request.rate = rate;
181
182         memset(&msg, 0, sizeof(msg));
183         msg.cmd = CMD_CLK_ROUND_RATE;
184         msg.id = clk->id;
185         msg.tx.data = &request;
186         msg.tx.size = sizeof(request);
187         msg.rx.data = &response;
188         msg.rx.size = sizeof(response);
189
190         err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
191         if (err < 0)
192                 return err;
193
194         return response.rate;
195 }
196
197 static int tegra_bpmp_clk_set_parent(struct clk_hw *hw, u8 index)
198 {
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;
203         int err;
204
205         memset(&request, 0, sizeof(request));
206         request.parent_id = clk->parents[index];
207
208         memset(&msg, 0, sizeof(msg));
209         msg.cmd = CMD_CLK_SET_PARENT;
210         msg.id = clk->id;
211         msg.tx.data = &request;
212         msg.tx.size = sizeof(request);
213         msg.rx.data = &response;
214         msg.rx.size = sizeof(response);
215
216         err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
217         if (err < 0)
218                 return err;
219
220         /* XXX check parent ID in response */
221
222         return 0;
223 }
224
225 static u8 tegra_bpmp_clk_get_parent(struct clk_hw *hw)
226 {
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;
230         unsigned int i;
231         int err;
232
233         memset(&msg, 0, sizeof(msg));
234         msg.cmd = CMD_CLK_GET_PARENT;
235         msg.id = clk->id;
236         msg.rx.data = &response;
237         msg.rx.size = sizeof(response);
238
239         err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
240         if (err < 0) {
241                 dev_err(clk->bpmp->dev, "failed to get parent for %s: %d\n",
242                         clk_hw_get_name(hw), err);
243                 return U8_MAX;
244         }
245
246         for (i = 0; i < clk->num_parents; i++)
247                 if (clk->parents[i] == response.parent_id)
248                         return i;
249
250         return U8_MAX;
251 }
252
253 static int tegra_bpmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
254                                    unsigned long parent_rate)
255 {
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;
260
261         memset(&request, 0, sizeof(request));
262         request.rate = rate;
263
264         memset(&msg, 0, sizeof(msg));
265         msg.cmd = CMD_CLK_SET_RATE;
266         msg.id = clk->id;
267         msg.tx.data = &request;
268         msg.tx.size = sizeof(request);
269         msg.rx.data = &response;
270         msg.rx.size = sizeof(response);
271
272         return tegra_bpmp_clk_transfer(clk->bpmp, &msg);
273 }
274
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,
280 };
281
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,
289 };
290
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,
298 };
299
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,
309 };
310
311 static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp *bpmp)
312 {
313         struct cmd_clk_get_max_clk_id_response response;
314         struct tegra_bpmp_clk_message msg;
315         int err;
316
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);
321
322         err = tegra_bpmp_clk_transfer(bpmp, &msg);
323         if (err < 0)
324                 return err;
325
326         if (response.max_id > INT_MAX)
327                 return -E2BIG;
328
329         return response.max_id;
330 }
331
332 static int tegra_bpmp_clk_get_info(struct tegra_bpmp *bpmp, unsigned int id,
333                                    struct tegra_bpmp_clk_info *info)
334 {
335         struct cmd_clk_get_all_info_response response;
336         struct tegra_bpmp_clk_message msg;
337         unsigned int i;
338         int err;
339
340         memset(&msg, 0, sizeof(msg));
341         msg.cmd = CMD_CLK_GET_ALL_INFO;
342         msg.id = id;
343         msg.rx.data = &response;
344         msg.rx.size = sizeof(response);
345
346         err = tegra_bpmp_clk_transfer(bpmp, &msg);
347         if (err < 0)
348                 return err;
349
350         strlcpy(info->name, response.name, MRQ_CLK_NAME_MAXLEN);
351         info->num_parents = response.num_parents;
352
353         for (i = 0; i < info->num_parents; i++)
354                 info->parents[i] = response.parents[i];
355
356         info->flags = response.flags;
357
358         return 0;
359 }
360
361 static void tegra_bpmp_clk_info_dump(struct tegra_bpmp *bpmp,
362                                      const char *level,
363                                      const struct tegra_bpmp_clk_info *info)
364 {
365         const char *prefix = "";
366         struct seq_buf buf;
367         unsigned int i;
368         char flags[64];
369
370         seq_buf_init(&buf, flags, sizeof(flags));
371
372         if (info->flags)
373                 seq_buf_printf(&buf, "(");
374
375         if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
376                 seq_buf_printf(&buf, "%smux", prefix);
377                 prefix = ", ";
378         }
379
380         if ((info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE) == 0) {
381                 seq_buf_printf(&buf, "%sfixed", prefix);
382                 prefix = ", ";
383         }
384
385         if (info->flags & TEGRA_BPMP_CLK_IS_ROOT) {
386                 seq_buf_printf(&buf, "%sroot", prefix);
387                 prefix = ", ";
388         }
389
390         if (info->flags)
391                 seq_buf_printf(&buf, ")");
392
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);
396
397         for (i = 0; i < info->num_parents; i++)
398                 dev_printk(level, bpmp->dev, "    %03u\n", info->parents[i]);
399 }
400
401 static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp,
402                                    struct tegra_bpmp_clk_info **clocksp)
403 {
404         struct tegra_bpmp_clk_info *clocks;
405         unsigned int max_id, id, count = 0;
406         unsigned int holes = 0;
407         int err;
408
409         err = tegra_bpmp_clk_get_max_id(bpmp);
410         if (err < 0)
411                 return err;
412
413         max_id = err;
414
415         dev_dbg(bpmp->dev, "maximum clock ID: %u\n", max_id);
416
417         clocks = kcalloc(max_id + 1, sizeof(*clocks), GFP_KERNEL);
418         if (!clocks)
419                 return -ENOMEM;
420
421         for (id = 0; id <= max_id; id++) {
422                 struct tegra_bpmp_clk_info *info = &clocks[count];
423
424                 err = tegra_bpmp_clk_get_info(bpmp, id, info);
425                 if (err < 0)
426                         continue;
427
428                 if (info->num_parents >= U8_MAX) {
429                         dev_err(bpmp->dev,
430                                 "clock %u has too many parents (%u, max: %u)\n",
431                                 id, info->num_parents, U8_MAX);
432                         continue;
433                 }
434
435                 /* clock not exposed by BPMP */
436                 if (info->name[0] == '\0') {
437                         holes++;
438                         continue;
439                 }
440
441                 info->id = id;
442                 count++;
443
444                 if (TEGRA_BPMP_DUMP_CLOCK_INFO)
445                         tegra_bpmp_clk_info_dump(bpmp, KERN_DEBUG, info);
446         }
447
448         dev_dbg(bpmp->dev, "holes: %u\n", holes);
449         *clocksp = clocks;
450
451         return count;
452 }
453
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)
457 {
458         unsigned int i;
459
460         for (i = 0; i < num_clocks; i++)
461                 if (clocks[i].id == id)
462                         return &clocks[i];
463
464         return NULL;
465 }
466
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)
472 {
473         struct tegra_bpmp_clk *clk;
474         struct clk_init_data init;
475         const char **parents;
476         unsigned int i;
477         int err;
478
479         clk = devm_kzalloc(bpmp->dev, sizeof(*clk), GFP_KERNEL);
480         if (!clk)
481                 return ERR_PTR(-ENOMEM);
482
483         clk->id = info->id;
484         clk->bpmp = bpmp;
485
486         clk->parents = devm_kcalloc(bpmp->dev, info->num_parents,
487                                     sizeof(*clk->parents), GFP_KERNEL);
488         if (!clk->parents)
489                 return ERR_PTR(-ENOMEM);
490
491         clk->num_parents = info->num_parents;
492
493         /* hardware clock initialization */
494         memset(&init, 0, sizeof(init));
495         init.name = info->name;
496         clk->hw.init = &init;
497
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;
501                 else
502                         init.ops = &tegra_bpmp_clk_mux_ops;
503         } else {
504                 if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
505                         init.ops = &tegra_bpmp_clk_rate_ops;
506                 else
507                         init.ops = &tegra_bpmp_clk_gate_ops;
508         }
509
510         init.num_parents = info->num_parents;
511
512         parents = kcalloc(info->num_parents, sizeof(*parents), GFP_KERNEL);
513         if (!parents)
514                 return ERR_PTR(-ENOMEM);
515
516         for (i = 0; i < info->num_parents; i++) {
517                 const struct tegra_bpmp_clk_info *parent;
518
519                 /* keep a private copy of the ID to parent index map */
520                 clk->parents[i] = info->parents[i];
521
522                 parent = tegra_bpmp_clk_find(clocks, num_clocks,
523                                              info->parents[i]);
524                 if (!parent) {
525                         dev_err(bpmp->dev, "no parent %u found for %u\n",
526                                 info->parents[i], info->id);
527                         continue;
528                 }
529
530                 parents[i] = parent->name;
531         }
532
533         init.parent_names = parents;
534
535         err = devm_clk_hw_register(bpmp->dev, &clk->hw);
536
537         kfree(parents);
538
539         if (err < 0)
540                 return ERR_PTR(err);
541
542         return clk;
543 }
544
545 static int tegra_bpmp_register_clocks(struct tegra_bpmp *bpmp,
546                                       struct tegra_bpmp_clk_info *infos,
547                                       unsigned int count)
548 {
549         struct tegra_bpmp_clk *clk;
550         unsigned int i;
551
552         bpmp->num_clocks = count;
553
554         bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(clk), GFP_KERNEL);
555         if (!bpmp->clocks)
556                 return -ENOMEM;
557
558         for (i = 0; i < count; i++) {
559                 struct tegra_bpmp_clk_info *info = &infos[i];
560
561                 clk = tegra_bpmp_clk_register(bpmp, info, infos, count);
562                 if (IS_ERR(clk)) {
563                         dev_err(bpmp->dev,
564                                 "failed to register clock %u (%s): %ld\n",
565                                 info->id, info->name, PTR_ERR(clk));
566                         continue;
567                 }
568
569                 bpmp->clocks[i] = clk;
570         }
571
572         return 0;
573 }
574
575 static void tegra_bpmp_unregister_clocks(struct tegra_bpmp *bpmp)
576 {
577         unsigned int i;
578
579         for (i = 0; i < bpmp->num_clocks; i++)
580                 clk_hw_unregister(&bpmp->clocks[i]->hw);
581 }
582
583 static struct clk_hw *tegra_bpmp_clk_of_xlate(struct of_phandle_args *clkspec,
584                                               void *data)
585 {
586         unsigned int id = clkspec->args[0], i;
587         struct tegra_bpmp *bpmp = data;
588
589         for (i = 0; i < bpmp->num_clocks; i++) {
590                 struct tegra_bpmp_clk *clk = bpmp->clocks[i];
591
592                 if (!clk)
593                         continue;
594
595                 if (clk->id == id)
596                         return &clk->hw;
597         }
598
599         return NULL;
600 }
601
602 int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp)
603 {
604         struct tegra_bpmp_clk_info *clocks;
605         unsigned int count;
606         int err;
607
608         err = tegra_bpmp_probe_clocks(bpmp, &clocks);
609         if (err < 0)
610                 return err;
611
612         count = err;
613
614         dev_dbg(bpmp->dev, "%u clocks probed\n", count);
615
616         err = tegra_bpmp_register_clocks(bpmp, clocks, count);
617         if (err < 0)
618                 goto free;
619
620         err = of_clk_add_hw_provider(bpmp->dev->of_node,
621                                      tegra_bpmp_clk_of_xlate,
622                                      bpmp);
623         if (err < 0) {
624                 tegra_bpmp_unregister_clocks(bpmp);
625                 goto free;
626         }
627
628 free:
629         kfree(clocks);
630         return err;
631 }