]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
9e5935c0 WY |
2 | /* |
3 | * Copyright (C) 2016 Atmel Corporation | |
4 | * Wenyou.Yang <wenyou.yang@atmel.com> | |
9e5935c0 WY |
5 | */ |
6 | ||
d678a59d | 7 | #include <common.h> |
653bcce4 | 8 | #include <asm/io.h> |
7b7e2267 | 9 | #include <clk-uclass.h> |
682e73d2 | 10 | #include <linux/clk-provider.h> |
7b7e2267 CB |
11 | #include "pmc.h" |
12 | ||
13 | static int at91_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) | |
14 | { | |
15 | if (args->args_count != 2) { | |
16 | debug("AT91: clk: Invalid args_count: %d\n", args->args_count); | |
17 | return -EINVAL; | |
18 | } | |
19 | ||
20 | clk->id = AT91_TO_CLK_ID(args->args[0], args->args[1]); | |
21 | ||
22 | return 0; | |
23 | } | |
24 | ||
7b7e2267 CB |
25 | const struct clk_ops at91_clk_ops = { |
26 | .of_xlate = at91_clk_of_xlate, | |
682e73d2 SA |
27 | .set_rate = ccf_clk_set_rate, |
28 | .get_rate = ccf_clk_get_rate, | |
29 | .enable = ccf_clk_enable, | |
30 | .disable = ccf_clk_disable, | |
7b7e2267 CB |
31 | }; |
32 | ||
5d729f96 CB |
33 | /** |
34 | * pmc_read() - read content at address base + off into val | |
35 | * | |
36 | * @base: base address | |
37 | * @off: offset to read from | |
38 | * @val: where the content of base + off is stored | |
39 | * | |
40 | * @return: void | |
41 | */ | |
42 | void pmc_read(void __iomem *base, unsigned int off, unsigned int *val) | |
43 | { | |
44 | *val = readl(base + off); | |
45 | } | |
46 | ||
47 | /** | |
48 | * pmc_write() - write content of val at address base + off | |
49 | * | |
50 | * @base: base address | |
51 | * @off: offset to write to | |
52 | * @val: content to be written at base + off | |
53 | * | |
54 | * @return: void | |
55 | */ | |
56 | void pmc_write(void __iomem *base, unsigned int off, unsigned int val) | |
57 | { | |
58 | writel(val, base + off); | |
59 | } | |
60 | ||
61 | /** | |
62 | * pmc_update_bits() - update a set of bits at address base + off | |
63 | * | |
64 | * @base: base address | |
65 | * @off: offset to be updated | |
66 | * @mask: mask of bits to be updated | |
67 | * @bits: the new value to be updated | |
68 | * | |
69 | * @return: void | |
70 | */ | |
71 | void pmc_update_bits(void __iomem *base, unsigned int off, | |
72 | unsigned int mask, unsigned int bits) | |
73 | { | |
74 | unsigned int tmp; | |
75 | ||
76 | tmp = readl(base + off); | |
77 | tmp &= ~mask; | |
78 | writel(tmp | (bits & mask), base + off); | |
79 | } | |
80 | ||
81 | /** | |
82 | * at91_clk_mux_val_to_index() - get parent index in mux table | |
83 | * | |
84 | * @table: clock mux table | |
85 | * @num_parents: clock number of parents | |
86 | * @val: clock id who's mux index should be retrieved | |
87 | * | |
88 | * @return: clock index in mux table or a negative error number in case of | |
89 | * failure | |
90 | */ | |
91 | int at91_clk_mux_val_to_index(const u32 *table, u32 num_parents, u32 val) | |
92 | { | |
93 | int i; | |
94 | ||
95 | if (!table || !num_parents) | |
96 | return -EINVAL; | |
97 | ||
98 | for (i = 0; i < num_parents; i++) { | |
99 | if (table[i] == val) | |
100 | return i; | |
101 | } | |
102 | ||
103 | return -EINVAL; | |
104 | } | |
105 | ||
106 | /** | |
107 | * at91_clk_mux_index_to_val() - get parent ID corresponding to an entry in | |
108 | * clock's mux table | |
109 | * | |
110 | * @table: clock's mux table | |
111 | * @num_parents: clock's number of parents | |
112 | * @index: index in mux table which clock's ID should be retrieved | |
113 | * | |
114 | * @return: clock ID or a negative error number in case of failure | |
115 | */ | |
116 | int at91_clk_mux_index_to_val(const u32 *table, u32 num_parents, u32 index) | |
117 | { | |
118 | if (!table || !num_parents || index < 0 || index > num_parents) | |
119 | return -EINVAL; | |
120 | ||
121 | return table[index]; | |
122 | } | |
248e4100 CB |
123 | |
124 | int at91_clk_setup(const struct pmc_clk_setup *setup, int size) | |
125 | { | |
126 | struct clk *c, *parent; | |
127 | int i, ret; | |
128 | ||
129 | if (!size) | |
130 | return 0; | |
131 | ||
132 | if (!setup) | |
133 | return -EINVAL; | |
134 | ||
135 | for (i = 0; i < size; i++) { | |
136 | ret = clk_get_by_id(setup[i].cid, &c); | |
137 | if (ret) | |
138 | return ret; | |
139 | ||
140 | if (setup[i].pid) { | |
141 | ret = clk_get_by_id(setup[i].pid, &parent); | |
142 | if (ret) | |
143 | return ret; | |
144 | ||
145 | ret = clk_set_parent(c, parent); | |
146 | if (ret) | |
147 | return ret; | |
148 | ||
149 | if (setup[i].prate) { | |
150 | ret = clk_set_rate(parent, setup[i].prate); | |
151 | if (ret < 0) | |
152 | return ret; | |
153 | } | |
154 | } | |
155 | ||
156 | if (setup[i].rate) { | |
157 | ret = clk_set_rate(c, setup[i].rate); | |
158 | if (ret < 0) | |
159 | return ret; | |
160 | } | |
161 | } | |
162 | ||
163 | return 0; | |
164 | } |