blob: 943e8bd0189236f4e6035aaf2ac612075a7ee126 [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
Sam Protsenko62112352024-03-07 20:18:57 -060013static void samsung_clk_register_mux(void __iomem *base, unsigned int cmu_id,
14 const struct samsung_mux_clock *clk_list,
15 unsigned int nr_clk)
Sam Protsenko8a0f6342024-01-10 21:09:03 -060016{
17 unsigned int cnt;
18
19 for (cnt = 0; cnt < nr_clk; cnt++) {
20 struct clk *clk;
21 const struct samsung_mux_clock *m;
Sam Protsenko62112352024-03-07 20:18:57 -060022 unsigned long clk_id;
Sam Protsenko8a0f6342024-01-10 21:09:03 -060023
24 m = &clk_list[cnt];
25 clk = clk_register_mux(NULL, m->name, m->parent_names,
26 m->num_parents, m->flags, base + m->offset, m->shift,
27 m->width, m->mux_flags);
Sam Protsenko62112352024-03-07 20:18:57 -060028 clk_id = SAMSUNG_TO_CLK_ID(cmu_id, m->id);
29 clk_dm(clk_id, clk);
Sam Protsenko8a0f6342024-01-10 21:09:03 -060030 }
31}
32
Sam Protsenko62112352024-03-07 20:18:57 -060033static void samsung_clk_register_div(void __iomem *base, unsigned int cmu_id,
34 const struct samsung_div_clock *clk_list,
35 unsigned int nr_clk)
Sam Protsenko8a0f6342024-01-10 21:09:03 -060036{
37 unsigned int cnt;
38
39 for (cnt = 0; cnt < nr_clk; cnt++) {
40 struct clk *clk;
41 const struct samsung_div_clock *d;
Sam Protsenko62112352024-03-07 20:18:57 -060042 unsigned long clk_id;
Sam Protsenko8a0f6342024-01-10 21:09:03 -060043
44 d = &clk_list[cnt];
45 clk = clk_register_divider(NULL, d->name, d->parent_name,
46 d->flags, base + d->offset, d->shift,
47 d->width, d->div_flags);
Sam Protsenko62112352024-03-07 20:18:57 -060048 clk_id = SAMSUNG_TO_CLK_ID(cmu_id, d->id);
49 clk_dm(clk_id, clk);
Sam Protsenko8a0f6342024-01-10 21:09:03 -060050 }
51}
52
Sam Protsenko62112352024-03-07 20:18:57 -060053static void samsung_clk_register_gate(void __iomem *base, unsigned int cmu_id,
54 const struct samsung_gate_clock *clk_list,
55 unsigned int nr_clk)
Sam Protsenko8a0f6342024-01-10 21:09:03 -060056{
57 unsigned int cnt;
58
59 for (cnt = 0; cnt < nr_clk; cnt++) {
60 struct clk *clk;
61 const struct samsung_gate_clock *g;
Sam Protsenko62112352024-03-07 20:18:57 -060062 unsigned long clk_id;
Sam Protsenko8a0f6342024-01-10 21:09:03 -060063
64 g = &clk_list[cnt];
65 clk = clk_register_gate(NULL, g->name, g->parent_name,
66 g->flags, base + g->offset, g->bit_idx,
67 g->gate_flags, NULL);
Sam Protsenko62112352024-03-07 20:18:57 -060068 clk_id = SAMSUNG_TO_CLK_ID(cmu_id, g->id);
69 clk_dm(clk_id, clk);
Sam Protsenko8a0f6342024-01-10 21:09:03 -060070 }
71}
72
Sam Protsenko62112352024-03-07 20:18:57 -060073typedef void (*samsung_clk_register_fn)(void __iomem *base, unsigned int cmu_id,
Sam Protsenko8a0f6342024-01-10 21:09:03 -060074 const void *clk_list,
75 unsigned int nr_clk);
76
77static const samsung_clk_register_fn samsung_clk_register_fns[] = {
78 [S_CLK_MUX] = (samsung_clk_register_fn)samsung_clk_register_mux,
79 [S_CLK_DIV] = (samsung_clk_register_fn)samsung_clk_register_div,
80 [S_CLK_GATE] = (samsung_clk_register_fn)samsung_clk_register_gate,
81 [S_CLK_PLL] = (samsung_clk_register_fn)samsung_clk_register_pll,
82};
83
84/**
85 * samsung_cmu_register_clocks() - Register provided clock groups
86 * @base: Base address of CMU registers
Sam Protsenko62112352024-03-07 20:18:57 -060087 * @cmu_id: CMU index number
Sam Protsenko8a0f6342024-01-10 21:09:03 -060088 * @clk_groups: list of clock groups
89 * @nr_groups: count of clock groups in @clk_groups
90 *
91 * Having the array of clock groups @clk_groups makes it possible to keep a
92 * correct clocks registration order.
93 */
Sam Protsenko62112352024-03-07 20:18:57 -060094static void samsung_cmu_register_clocks(void __iomem *base, unsigned int cmu_id,
Sam Protsenko49ba25a2024-03-07 20:18:56 -060095 const struct samsung_clk_group *clk_groups,
96 unsigned int nr_groups)
Sam Protsenko8a0f6342024-01-10 21:09:03 -060097{
98 unsigned int i;
99
100 for (i = 0; i < nr_groups; i++) {
101 const struct samsung_clk_group *g = &clk_groups[i];
102
Sam Protsenko62112352024-03-07 20:18:57 -0600103 samsung_clk_register_fns[g->type](base, cmu_id,
104 g->clk_list, g->nr_clk);
Sam Protsenko8a0f6342024-01-10 21:09:03 -0600105 }
106}
107
108/**
109 * samsung_cmu_register_one - Register all CMU clocks
110 * @dev: CMU device
Sam Protsenko62112352024-03-07 20:18:57 -0600111 * @cmu_id: CMU index number
Sam Protsenko8a0f6342024-01-10 21:09:03 -0600112 * @clk_groups: list of CMU clock groups
113 * @nr_groups: count of CMU clock groups in @clk_groups
114 *
115 * Return: 0 on success or negative value on error.
116 */
Sam Protsenko62112352024-03-07 20:18:57 -0600117int samsung_cmu_register_one(struct udevice *dev, unsigned int cmu_id,
Sam Protsenko8a0f6342024-01-10 21:09:03 -0600118 const struct samsung_clk_group *clk_groups,
119 unsigned int nr_groups)
120{
121 void __iomem *base;
122
123 base = dev_read_addr_ptr(dev);
124 if (!base)
125 return -EINVAL;
126
Sam Protsenko62112352024-03-07 20:18:57 -0600127 samsung_cmu_register_clocks(base, cmu_id, clk_groups, nr_groups);
Sam Protsenko8a0f6342024-01-10 21:09:03 -0600128
129 return 0;
130}