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