1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2016 Atmel Corporation
4 * Wenyou.Yang <wenyou.yang@atmel.com>
5 */
6
7 #include <common.h>
8 #include <asm/io.h>
9 #include <clk-uclass.h>
10 #include "pmc.h"
11
at91_clk_of_xlate(struct clk * clk,struct ofnode_phandle_args * args)12 static 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
at91_clk_get_rate(struct clk * clk)24 static 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
at91_clk_set_rate(struct clk * clk,ulong rate)36 static 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
at91_clk_enable(struct clk * clk)48 static 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
at91_clk_disable(struct clk * clk)60 static 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
72 const 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
80 /**
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 */
pmc_read(void __iomem * base,unsigned int off,unsigned int * val)89 void 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 */
pmc_write(void __iomem * base,unsigned int off,unsigned int val)103 void 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 */
pmc_update_bits(void __iomem * base,unsigned int off,unsigned int mask,unsigned int bits)118 void 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 */
at91_clk_mux_val_to_index(const u32 * table,u32 num_parents,u32 val)138 int 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 */
at91_clk_mux_index_to_val(const u32 * table,u32 num_parents,u32 index)163 int 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 }
170