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