blob: 430767f072d896cde1e40db29082da88c7f21832 [file] [log] [blame]
Sam Protsenko8a0f6342024-01-10 21:09:03 -06001// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2023 Linaro Ltd.
4 * Sam Protsenko <semen.protsenko@linaro.org>
5 *
6 * This file includes utility functions to register clocks to common
7 * clock framework for Samsung platforms.
8 */
9
10#include <dm.h>
11#include "clk.h"
12
13void samsung_clk_register_mux(void __iomem *base,
14 const struct samsung_mux_clock *clk_list,
15 unsigned int nr_clk)
16{
17 unsigned int cnt;
18
19 for (cnt = 0; cnt < nr_clk; cnt++) {
20 struct clk *clk;
21 const struct samsung_mux_clock *m;
22
23 m = &clk_list[cnt];
24 clk = clk_register_mux(NULL, m->name, m->parent_names,
25 m->num_parents, m->flags, base + m->offset, m->shift,
26 m->width, m->mux_flags);
27 clk_dm(m->id, clk);
28 }
29}
30
31void samsung_clk_register_div(void __iomem *base,
32 const struct samsung_div_clock *clk_list,
33 unsigned int nr_clk)
34{
35 unsigned int cnt;
36
37 for (cnt = 0; cnt < nr_clk; cnt++) {
38 struct clk *clk;
39 const struct samsung_div_clock *d;
40
41 d = &clk_list[cnt];
42 clk = clk_register_divider(NULL, d->name, d->parent_name,
43 d->flags, base + d->offset, d->shift,
44 d->width, d->div_flags);
45 clk_dm(d->id, clk);
46 }
47}
48
49void samsung_clk_register_gate(void __iomem *base,
50 const struct samsung_gate_clock *clk_list,
51 unsigned int nr_clk)
52{
53 unsigned int cnt;
54
55 for (cnt = 0; cnt < nr_clk; cnt++) {
56 struct clk *clk;
57 const struct samsung_gate_clock *g;
58
59 g = &clk_list[cnt];
60 clk = clk_register_gate(NULL, g->name, g->parent_name,
61 g->flags, base + g->offset, g->bit_idx,
62 g->gate_flags, NULL);
63 clk_dm(g->id, clk);
64 }
65}
66
67typedef void (*samsung_clk_register_fn)(void __iomem *base,
68 const void *clk_list,
69 unsigned int nr_clk);
70
71static const samsung_clk_register_fn samsung_clk_register_fns[] = {
72 [S_CLK_MUX] = (samsung_clk_register_fn)samsung_clk_register_mux,
73 [S_CLK_DIV] = (samsung_clk_register_fn)samsung_clk_register_div,
74 [S_CLK_GATE] = (samsung_clk_register_fn)samsung_clk_register_gate,
75 [S_CLK_PLL] = (samsung_clk_register_fn)samsung_clk_register_pll,
76};
77
78/**
79 * samsung_cmu_register_clocks() - Register provided clock groups
80 * @base: Base address of CMU registers
81 * @clk_groups: list of clock groups
82 * @nr_groups: count of clock groups in @clk_groups
83 *
84 * Having the array of clock groups @clk_groups makes it possible to keep a
85 * correct clocks registration order.
86 */
87void samsung_cmu_register_clocks(void __iomem *base,
88 const struct samsung_clk_group *clk_groups,
89 unsigned int nr_groups)
90{
91 unsigned int i;
92
93 for (i = 0; i < nr_groups; i++) {
94 const struct samsung_clk_group *g = &clk_groups[i];
95
96 samsung_clk_register_fns[g->type](base, g->clk_list, g->nr_clk);
97 }
98}
99
100/**
101 * samsung_cmu_register_one - Register all CMU clocks
102 * @dev: CMU device
103 * @clk_groups: list of CMU clock groups
104 * @nr_groups: count of CMU clock groups in @clk_groups
105 *
106 * Return: 0 on success or negative value on error.
107 */
108int samsung_cmu_register_one(struct udevice *dev,
109 const struct samsung_clk_group *clk_groups,
110 unsigned int nr_groups)
111{
112 void __iomem *base;
113
114 base = dev_read_addr_ptr(dev);
115 if (!base)
116 return -EINVAL;
117
118 samsung_cmu_register_clocks(base, clk_groups, nr_groups);
119
120 return 0;
121}