1c8923236SAlexandre Belloni // SPDX-License-Identifier: GPL-2.0
2c8923236SAlexandre Belloni #include <linux/clk-provider.h>
3c8923236SAlexandre Belloni #include <linux/mfd/syscon.h>
4c8923236SAlexandre Belloni #include <linux/slab.h>
5c8923236SAlexandre Belloni
6c8923236SAlexandre Belloni #include <dt-bindings/clock/at91.h>
7c8923236SAlexandre Belloni
8c8923236SAlexandre Belloni #include "pmc.h"
9c8923236SAlexandre Belloni
10c8923236SAlexandre Belloni struct sck {
11c8923236SAlexandre Belloni char *n;
12c8923236SAlexandre Belloni char *p;
13c8923236SAlexandre Belloni u8 id;
14c8923236SAlexandre Belloni };
15c8923236SAlexandre Belloni
16c8923236SAlexandre Belloni struct pck {
17c8923236SAlexandre Belloni char *n;
18c8923236SAlexandre Belloni u8 id;
19c8923236SAlexandre Belloni };
20c8923236SAlexandre Belloni
21c8923236SAlexandre Belloni struct at91sam926x_data {
22c8923236SAlexandre Belloni const struct clk_pll_layout *plla_layout;
23c8923236SAlexandre Belloni const struct clk_pll_characteristics *plla_characteristics;
24c8923236SAlexandre Belloni const struct clk_pll_layout *pllb_layout;
25c8923236SAlexandre Belloni const struct clk_pll_characteristics *pllb_characteristics;
26c8923236SAlexandre Belloni const struct clk_master_characteristics *mck_characteristics;
27c8923236SAlexandre Belloni const struct sck *sck;
28c8923236SAlexandre Belloni const struct pck *pck;
29c8923236SAlexandre Belloni u8 num_sck;
30c8923236SAlexandre Belloni u8 num_pck;
31c8923236SAlexandre Belloni u8 num_progck;
32c8923236SAlexandre Belloni bool has_slck;
33c8923236SAlexandre Belloni };
34c8923236SAlexandre Belloni
357a110b91SClaudiu Beznea static DEFINE_SPINLOCK(at91sam9260_mck_lock);
367a110b91SClaudiu Beznea
37c8923236SAlexandre Belloni static const struct clk_master_characteristics sam9260_mck_characteristics = {
38c8923236SAlexandre Belloni .output = { .min = 0, .max = 105000000 },
39c8923236SAlexandre Belloni .divisors = { 1, 2, 4, 0 },
40c8923236SAlexandre Belloni };
41c8923236SAlexandre Belloni
42c8923236SAlexandre Belloni static u8 sam9260_plla_out[] = { 0, 2 };
43c8923236SAlexandre Belloni
44c8923236SAlexandre Belloni static u16 sam9260_plla_icpll[] = { 1, 1 };
45c8923236SAlexandre Belloni
467b4c162eSStephen Boyd static const struct clk_range sam9260_plla_outputs[] = {
47c8923236SAlexandre Belloni { .min = 80000000, .max = 160000000 },
48c8923236SAlexandre Belloni { .min = 150000000, .max = 240000000 },
49c8923236SAlexandre Belloni };
50c8923236SAlexandre Belloni
51c8923236SAlexandre Belloni static const struct clk_pll_characteristics sam9260_plla_characteristics = {
52c8923236SAlexandre Belloni .input = { .min = 1000000, .max = 32000000 },
53c8923236SAlexandre Belloni .num_output = ARRAY_SIZE(sam9260_plla_outputs),
54c8923236SAlexandre Belloni .output = sam9260_plla_outputs,
55c8923236SAlexandre Belloni .icpll = sam9260_plla_icpll,
56c8923236SAlexandre Belloni .out = sam9260_plla_out,
57c8923236SAlexandre Belloni };
58c8923236SAlexandre Belloni
59c8923236SAlexandre Belloni static u8 sam9260_pllb_out[] = { 1 };
60c8923236SAlexandre Belloni
61c8923236SAlexandre Belloni static u16 sam9260_pllb_icpll[] = { 1 };
62c8923236SAlexandre Belloni
637b4c162eSStephen Boyd static const struct clk_range sam9260_pllb_outputs[] = {
64c8923236SAlexandre Belloni { .min = 70000000, .max = 130000000 },
65c8923236SAlexandre Belloni };
66c8923236SAlexandre Belloni
67c8923236SAlexandre Belloni static const struct clk_pll_characteristics sam9260_pllb_characteristics = {
68c8923236SAlexandre Belloni .input = { .min = 1000000, .max = 5000000 },
69c8923236SAlexandre Belloni .num_output = ARRAY_SIZE(sam9260_pllb_outputs),
70c8923236SAlexandre Belloni .output = sam9260_pllb_outputs,
71c8923236SAlexandre Belloni .icpll = sam9260_pllb_icpll,
72c8923236SAlexandre Belloni .out = sam9260_pllb_out,
73c8923236SAlexandre Belloni };
74c8923236SAlexandre Belloni
75c8923236SAlexandre Belloni static const struct sck at91sam9260_systemck[] = {
76c8923236SAlexandre Belloni { .n = "uhpck", .p = "usbck", .id = 6 },
77c8923236SAlexandre Belloni { .n = "udpck", .p = "usbck", .id = 7 },
78c8923236SAlexandre Belloni { .n = "pck0", .p = "prog0", .id = 8 },
79c8923236SAlexandre Belloni { .n = "pck1", .p = "prog1", .id = 9 },
80c8923236SAlexandre Belloni };
81c8923236SAlexandre Belloni
82c8923236SAlexandre Belloni static const struct pck at91sam9260_periphck[] = {
83c8923236SAlexandre Belloni { .n = "pioA_clk", .id = 2 },
84c8923236SAlexandre Belloni { .n = "pioB_clk", .id = 3 },
85c8923236SAlexandre Belloni { .n = "pioC_clk", .id = 4 },
86c8923236SAlexandre Belloni { .n = "adc_clk", .id = 5 },
87c8923236SAlexandre Belloni { .n = "usart0_clk", .id = 6 },
88c8923236SAlexandre Belloni { .n = "usart1_clk", .id = 7 },
89c8923236SAlexandre Belloni { .n = "usart2_clk", .id = 8 },
90c8923236SAlexandre Belloni { .n = "mci0_clk", .id = 9 },
91c8923236SAlexandre Belloni { .n = "udc_clk", .id = 10 },
92c8923236SAlexandre Belloni { .n = "twi0_clk", .id = 11 },
93c8923236SAlexandre Belloni { .n = "spi0_clk", .id = 12 },
94c8923236SAlexandre Belloni { .n = "spi1_clk", .id = 13 },
95c8923236SAlexandre Belloni { .n = "ssc0_clk", .id = 14 },
96c8923236SAlexandre Belloni { .n = "tc0_clk", .id = 17 },
97c8923236SAlexandre Belloni { .n = "tc1_clk", .id = 18 },
98c8923236SAlexandre Belloni { .n = "tc2_clk", .id = 19 },
99c8923236SAlexandre Belloni { .n = "ohci_clk", .id = 20 },
100c8923236SAlexandre Belloni { .n = "macb0_clk", .id = 21 },
101c8923236SAlexandre Belloni { .n = "isi_clk", .id = 22 },
102c8923236SAlexandre Belloni { .n = "usart3_clk", .id = 23 },
103c8923236SAlexandre Belloni { .n = "uart0_clk", .id = 24 },
104c8923236SAlexandre Belloni { .n = "uart1_clk", .id = 25 },
105c8923236SAlexandre Belloni { .n = "tc3_clk", .id = 26 },
106c8923236SAlexandre Belloni { .n = "tc4_clk", .id = 27 },
107c8923236SAlexandre Belloni { .n = "tc5_clk", .id = 28 },
108c8923236SAlexandre Belloni };
109c8923236SAlexandre Belloni
110c8923236SAlexandre Belloni static struct at91sam926x_data at91sam9260_data = {
111c8923236SAlexandre Belloni .plla_layout = &at91rm9200_pll_layout,
112c8923236SAlexandre Belloni .plla_characteristics = &sam9260_plla_characteristics,
113c8923236SAlexandre Belloni .pllb_layout = &at91rm9200_pll_layout,
114c8923236SAlexandre Belloni .pllb_characteristics = &sam9260_pllb_characteristics,
115c8923236SAlexandre Belloni .mck_characteristics = &sam9260_mck_characteristics,
116c8923236SAlexandre Belloni .sck = at91sam9260_systemck,
117c8923236SAlexandre Belloni .num_sck = ARRAY_SIZE(at91sam9260_systemck),
118c8923236SAlexandre Belloni .pck = at91sam9260_periphck,
119c8923236SAlexandre Belloni .num_pck = ARRAY_SIZE(at91sam9260_periphck),
120c8923236SAlexandre Belloni .num_progck = 2,
121c8923236SAlexandre Belloni .has_slck = true,
122c8923236SAlexandre Belloni };
123c8923236SAlexandre Belloni
124c8923236SAlexandre Belloni static const struct clk_master_characteristics sam9g20_mck_characteristics = {
125c8923236SAlexandre Belloni .output = { .min = 0, .max = 133000000 },
126c8923236SAlexandre Belloni .divisors = { 1, 2, 4, 6 },
127c8923236SAlexandre Belloni };
128c8923236SAlexandre Belloni
129c8923236SAlexandre Belloni static u8 sam9g20_plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
130c8923236SAlexandre Belloni
131c8923236SAlexandre Belloni static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
132c8923236SAlexandre Belloni
1337b4c162eSStephen Boyd static const struct clk_range sam9g20_plla_outputs[] = {
134c8923236SAlexandre Belloni { .min = 745000000, .max = 800000000 },
135c8923236SAlexandre Belloni { .min = 695000000, .max = 750000000 },
136c8923236SAlexandre Belloni { .min = 645000000, .max = 700000000 },
137c8923236SAlexandre Belloni { .min = 595000000, .max = 650000000 },
138c8923236SAlexandre Belloni { .min = 545000000, .max = 600000000 },
139c8923236SAlexandre Belloni { .min = 495000000, .max = 550000000 },
140c8923236SAlexandre Belloni { .min = 445000000, .max = 500000000 },
141c8923236SAlexandre Belloni { .min = 400000000, .max = 450000000 },
142c8923236SAlexandre Belloni };
143c8923236SAlexandre Belloni
144c8923236SAlexandre Belloni static const struct clk_pll_characteristics sam9g20_plla_characteristics = {
145c8923236SAlexandre Belloni .input = { .min = 2000000, .max = 32000000 },
146c8923236SAlexandre Belloni .num_output = ARRAY_SIZE(sam9g20_plla_outputs),
147c8923236SAlexandre Belloni .output = sam9g20_plla_outputs,
148c8923236SAlexandre Belloni .icpll = sam9g20_plla_icpll,
149c8923236SAlexandre Belloni .out = sam9g20_plla_out,
150c8923236SAlexandre Belloni };
151c8923236SAlexandre Belloni
152c8923236SAlexandre Belloni static u8 sam9g20_pllb_out[] = { 0 };
153c8923236SAlexandre Belloni
154c8923236SAlexandre Belloni static u16 sam9g20_pllb_icpll[] = { 0 };
155c8923236SAlexandre Belloni
1567b4c162eSStephen Boyd static const struct clk_range sam9g20_pllb_outputs[] = {
157c8923236SAlexandre Belloni { .min = 30000000, .max = 100000000 },
158c8923236SAlexandre Belloni };
159c8923236SAlexandre Belloni
160c8923236SAlexandre Belloni static const struct clk_pll_characteristics sam9g20_pllb_characteristics = {
161c8923236SAlexandre Belloni .input = { .min = 2000000, .max = 32000000 },
162c8923236SAlexandre Belloni .num_output = ARRAY_SIZE(sam9g20_pllb_outputs),
163c8923236SAlexandre Belloni .output = sam9g20_pllb_outputs,
164c8923236SAlexandre Belloni .icpll = sam9g20_pllb_icpll,
165c8923236SAlexandre Belloni .out = sam9g20_pllb_out,
166c8923236SAlexandre Belloni };
167c8923236SAlexandre Belloni
168c8923236SAlexandre Belloni static struct at91sam926x_data at91sam9g20_data = {
169c8923236SAlexandre Belloni .plla_layout = &at91sam9g45_pll_layout,
170c8923236SAlexandre Belloni .plla_characteristics = &sam9g20_plla_characteristics,
171c8923236SAlexandre Belloni .pllb_layout = &at91sam9g20_pllb_layout,
172c8923236SAlexandre Belloni .pllb_characteristics = &sam9g20_pllb_characteristics,
173c8923236SAlexandre Belloni .mck_characteristics = &sam9g20_mck_characteristics,
174c8923236SAlexandre Belloni .sck = at91sam9260_systemck,
175c8923236SAlexandre Belloni .num_sck = ARRAY_SIZE(at91sam9260_systemck),
176c8923236SAlexandre Belloni .pck = at91sam9260_periphck,
177c8923236SAlexandre Belloni .num_pck = ARRAY_SIZE(at91sam9260_periphck),
178c8923236SAlexandre Belloni .num_progck = 2,
179c8923236SAlexandre Belloni .has_slck = true,
180c8923236SAlexandre Belloni };
181c8923236SAlexandre Belloni
182c8923236SAlexandre Belloni static const struct clk_master_characteristics sam9261_mck_characteristics = {
183c8923236SAlexandre Belloni .output = { .min = 0, .max = 94000000 },
184c8923236SAlexandre Belloni .divisors = { 1, 2, 4, 0 },
185c8923236SAlexandre Belloni };
186c8923236SAlexandre Belloni
1877b4c162eSStephen Boyd static const struct clk_range sam9261_plla_outputs[] = {
188c8923236SAlexandre Belloni { .min = 80000000, .max = 200000000 },
189c8923236SAlexandre Belloni { .min = 190000000, .max = 240000000 },
190c8923236SAlexandre Belloni };
191c8923236SAlexandre Belloni
192c8923236SAlexandre Belloni static const struct clk_pll_characteristics sam9261_plla_characteristics = {
193c8923236SAlexandre Belloni .input = { .min = 1000000, .max = 32000000 },
194c8923236SAlexandre Belloni .num_output = ARRAY_SIZE(sam9261_plla_outputs),
195c8923236SAlexandre Belloni .output = sam9261_plla_outputs,
196c8923236SAlexandre Belloni .icpll = sam9260_plla_icpll,
197c8923236SAlexandre Belloni .out = sam9260_plla_out,
198c8923236SAlexandre Belloni };
199c8923236SAlexandre Belloni
200c8923236SAlexandre Belloni static u8 sam9261_pllb_out[] = { 1 };
201c8923236SAlexandre Belloni
202c8923236SAlexandre Belloni static u16 sam9261_pllb_icpll[] = { 1 };
203c8923236SAlexandre Belloni
2047b4c162eSStephen Boyd static const struct clk_range sam9261_pllb_outputs[] = {
205c8923236SAlexandre Belloni { .min = 70000000, .max = 130000000 },
206c8923236SAlexandre Belloni };
207c8923236SAlexandre Belloni
208c8923236SAlexandre Belloni static const struct clk_pll_characteristics sam9261_pllb_characteristics = {
209c8923236SAlexandre Belloni .input = { .min = 1000000, .max = 5000000 },
210c8923236SAlexandre Belloni .num_output = ARRAY_SIZE(sam9261_pllb_outputs),
211c8923236SAlexandre Belloni .output = sam9261_pllb_outputs,
212c8923236SAlexandre Belloni .icpll = sam9261_pllb_icpll,
213c8923236SAlexandre Belloni .out = sam9261_pllb_out,
214c8923236SAlexandre Belloni };
215c8923236SAlexandre Belloni
216c8923236SAlexandre Belloni static const struct sck at91sam9261_systemck[] = {
217c8923236SAlexandre Belloni { .n = "uhpck", .p = "usbck", .id = 6 },
218c8923236SAlexandre Belloni { .n = "udpck", .p = "usbck", .id = 7 },
219c8923236SAlexandre Belloni { .n = "pck0", .p = "prog0", .id = 8 },
220c8923236SAlexandre Belloni { .n = "pck1", .p = "prog1", .id = 9 },
221c8923236SAlexandre Belloni { .n = "pck2", .p = "prog2", .id = 10 },
222c8923236SAlexandre Belloni { .n = "pck3", .p = "prog3", .id = 11 },
2237a110b91SClaudiu Beznea { .n = "hclk0", .p = "masterck_div", .id = 16 },
2247a110b91SClaudiu Beznea { .n = "hclk1", .p = "masterck_div", .id = 17 },
225c8923236SAlexandre Belloni };
226c8923236SAlexandre Belloni
227c8923236SAlexandre Belloni static const struct pck at91sam9261_periphck[] = {
228c8923236SAlexandre Belloni { .n = "pioA_clk", .id = 2, },
229c8923236SAlexandre Belloni { .n = "pioB_clk", .id = 3, },
230c8923236SAlexandre Belloni { .n = "pioC_clk", .id = 4, },
231c8923236SAlexandre Belloni { .n = "usart0_clk", .id = 6, },
232c8923236SAlexandre Belloni { .n = "usart1_clk", .id = 7, },
233c8923236SAlexandre Belloni { .n = "usart2_clk", .id = 8, },
234c8923236SAlexandre Belloni { .n = "mci0_clk", .id = 9, },
235c8923236SAlexandre Belloni { .n = "udc_clk", .id = 10, },
236c8923236SAlexandre Belloni { .n = "twi0_clk", .id = 11, },
237c8923236SAlexandre Belloni { .n = "spi0_clk", .id = 12, },
238c8923236SAlexandre Belloni { .n = "spi1_clk", .id = 13, },
239c8923236SAlexandre Belloni { .n = "ssc0_clk", .id = 14, },
240c8923236SAlexandre Belloni { .n = "ssc1_clk", .id = 15, },
241c8923236SAlexandre Belloni { .n = "ssc2_clk", .id = 16, },
242c8923236SAlexandre Belloni { .n = "tc0_clk", .id = 17, },
243c8923236SAlexandre Belloni { .n = "tc1_clk", .id = 18, },
244c8923236SAlexandre Belloni { .n = "tc2_clk", .id = 19, },
245c8923236SAlexandre Belloni { .n = "ohci_clk", .id = 20, },
246c8923236SAlexandre Belloni { .n = "lcd_clk", .id = 21, },
247c8923236SAlexandre Belloni };
248c8923236SAlexandre Belloni
249c8923236SAlexandre Belloni static struct at91sam926x_data at91sam9261_data = {
250c8923236SAlexandre Belloni .plla_layout = &at91rm9200_pll_layout,
251c8923236SAlexandre Belloni .plla_characteristics = &sam9261_plla_characteristics,
252c8923236SAlexandre Belloni .pllb_layout = &at91rm9200_pll_layout,
253c8923236SAlexandre Belloni .pllb_characteristics = &sam9261_pllb_characteristics,
254c8923236SAlexandre Belloni .mck_characteristics = &sam9261_mck_characteristics,
255c8923236SAlexandre Belloni .sck = at91sam9261_systemck,
256c8923236SAlexandre Belloni .num_sck = ARRAY_SIZE(at91sam9261_systemck),
257c8923236SAlexandre Belloni .pck = at91sam9261_periphck,
258c8923236SAlexandre Belloni .num_pck = ARRAY_SIZE(at91sam9261_periphck),
259c8923236SAlexandre Belloni .num_progck = 4,
260c8923236SAlexandre Belloni };
261c8923236SAlexandre Belloni
262c8923236SAlexandre Belloni static const struct clk_master_characteristics sam9263_mck_characteristics = {
263c8923236SAlexandre Belloni .output = { .min = 0, .max = 120000000 },
264c8923236SAlexandre Belloni .divisors = { 1, 2, 4, 0 },
265c8923236SAlexandre Belloni };
266c8923236SAlexandre Belloni
2677b4c162eSStephen Boyd static const struct clk_range sam9263_pll_outputs[] = {
268c8923236SAlexandre Belloni { .min = 80000000, .max = 200000000 },
269c8923236SAlexandre Belloni { .min = 190000000, .max = 240000000 },
270c8923236SAlexandre Belloni };
271c8923236SAlexandre Belloni
272c8923236SAlexandre Belloni static const struct clk_pll_characteristics sam9263_pll_characteristics = {
273c8923236SAlexandre Belloni .input = { .min = 1000000, .max = 32000000 },
274c8923236SAlexandre Belloni .num_output = ARRAY_SIZE(sam9263_pll_outputs),
275c8923236SAlexandre Belloni .output = sam9263_pll_outputs,
276c8923236SAlexandre Belloni .icpll = sam9260_plla_icpll,
277c8923236SAlexandre Belloni .out = sam9260_plla_out,
278c8923236SAlexandre Belloni };
279c8923236SAlexandre Belloni
280c8923236SAlexandre Belloni static const struct sck at91sam9263_systemck[] = {
281c8923236SAlexandre Belloni { .n = "uhpck", .p = "usbck", .id = 6 },
282c8923236SAlexandre Belloni { .n = "udpck", .p = "usbck", .id = 7 },
283c8923236SAlexandre Belloni { .n = "pck0", .p = "prog0", .id = 8 },
284c8923236SAlexandre Belloni { .n = "pck1", .p = "prog1", .id = 9 },
285c8923236SAlexandre Belloni { .n = "pck2", .p = "prog2", .id = 10 },
286c8923236SAlexandre Belloni { .n = "pck3", .p = "prog3", .id = 11 },
287c8923236SAlexandre Belloni };
288c8923236SAlexandre Belloni
289c8923236SAlexandre Belloni static const struct pck at91sam9263_periphck[] = {
290c8923236SAlexandre Belloni { .n = "pioA_clk", .id = 2, },
291c8923236SAlexandre Belloni { .n = "pioB_clk", .id = 3, },
292c8923236SAlexandre Belloni { .n = "pioCDE_clk", .id = 4, },
293c8923236SAlexandre Belloni { .n = "usart0_clk", .id = 7, },
294c8923236SAlexandre Belloni { .n = "usart1_clk", .id = 8, },
295c8923236SAlexandre Belloni { .n = "usart2_clk", .id = 9, },
296c8923236SAlexandre Belloni { .n = "mci0_clk", .id = 10, },
297c8923236SAlexandre Belloni { .n = "mci1_clk", .id = 11, },
298c8923236SAlexandre Belloni { .n = "can_clk", .id = 12, },
299c8923236SAlexandre Belloni { .n = "twi0_clk", .id = 13, },
300c8923236SAlexandre Belloni { .n = "spi0_clk", .id = 14, },
301c8923236SAlexandre Belloni { .n = "spi1_clk", .id = 15, },
302c8923236SAlexandre Belloni { .n = "ssc0_clk", .id = 16, },
303c8923236SAlexandre Belloni { .n = "ssc1_clk", .id = 17, },
304c8923236SAlexandre Belloni { .n = "ac97_clk", .id = 18, },
305c8923236SAlexandre Belloni { .n = "tcb_clk", .id = 19, },
306c8923236SAlexandre Belloni { .n = "pwm_clk", .id = 20, },
307c8923236SAlexandre Belloni { .n = "macb0_clk", .id = 21, },
308c8923236SAlexandre Belloni { .n = "g2de_clk", .id = 23, },
309c8923236SAlexandre Belloni { .n = "udc_clk", .id = 24, },
310c8923236SAlexandre Belloni { .n = "isi_clk", .id = 25, },
311c8923236SAlexandre Belloni { .n = "lcd_clk", .id = 26, },
312c8923236SAlexandre Belloni { .n = "dma_clk", .id = 27, },
313c8923236SAlexandre Belloni { .n = "ohci_clk", .id = 29, },
314c8923236SAlexandre Belloni };
315c8923236SAlexandre Belloni
316c8923236SAlexandre Belloni static struct at91sam926x_data at91sam9263_data = {
317c8923236SAlexandre Belloni .plla_layout = &at91rm9200_pll_layout,
318c8923236SAlexandre Belloni .plla_characteristics = &sam9263_pll_characteristics,
319c8923236SAlexandre Belloni .pllb_layout = &at91rm9200_pll_layout,
320c8923236SAlexandre Belloni .pllb_characteristics = &sam9263_pll_characteristics,
321c8923236SAlexandre Belloni .mck_characteristics = &sam9263_mck_characteristics,
322c8923236SAlexandre Belloni .sck = at91sam9263_systemck,
323c8923236SAlexandre Belloni .num_sck = ARRAY_SIZE(at91sam9263_systemck),
324c8923236SAlexandre Belloni .pck = at91sam9263_periphck,
325c8923236SAlexandre Belloni .num_pck = ARRAY_SIZE(at91sam9263_periphck),
326c8923236SAlexandre Belloni .num_progck = 4,
327c8923236SAlexandre Belloni };
328c8923236SAlexandre Belloni
at91sam926x_pmc_setup(struct device_node * np,struct at91sam926x_data * data)329c8923236SAlexandre Belloni static void __init at91sam926x_pmc_setup(struct device_node *np,
330c8923236SAlexandre Belloni struct at91sam926x_data *data)
331c8923236SAlexandre Belloni {
332c8923236SAlexandre Belloni const char *slowxtal_name, *mainxtal_name;
333c8923236SAlexandre Belloni struct pmc_data *at91sam9260_pmc;
334c8923236SAlexandre Belloni u32 usb_div[] = { 1, 2, 4, 0 };
335c8923236SAlexandre Belloni const char *parent_names[6];
336c8923236SAlexandre Belloni const char *slck_name;
337c8923236SAlexandre Belloni struct regmap *regmap;
338c8923236SAlexandre Belloni struct clk_hw *hw;
339c8923236SAlexandre Belloni int i;
340c8923236SAlexandre Belloni bool bypass;
341c8923236SAlexandre Belloni
342c8923236SAlexandre Belloni i = of_property_match_string(np, "clock-names", "slow_xtal");
343c8923236SAlexandre Belloni if (i < 0)
344c8923236SAlexandre Belloni return;
345c8923236SAlexandre Belloni
346c8923236SAlexandre Belloni slowxtal_name = of_clk_get_parent_name(np, i);
347c8923236SAlexandre Belloni
348c8923236SAlexandre Belloni i = of_property_match_string(np, "clock-names", "main_xtal");
349c8923236SAlexandre Belloni if (i < 0)
350c8923236SAlexandre Belloni return;
351c8923236SAlexandre Belloni mainxtal_name = of_clk_get_parent_name(np, i);
352c8923236SAlexandre Belloni
3536956eb33SAlexandre Belloni regmap = device_node_to_regmap(np);
354c8923236SAlexandre Belloni if (IS_ERR(regmap))
355c8923236SAlexandre Belloni return;
356c8923236SAlexandre Belloni
35703a1ee1dSMichał Mirosław at91sam9260_pmc = pmc_data_allocate(PMC_PLLBCK + 1,
358c8923236SAlexandre Belloni ndck(data->sck, data->num_sck),
35999767cd4SMichał Mirosław ndck(data->pck, data->num_pck),
36099767cd4SMichał Mirosław 0, data->num_progck);
361c8923236SAlexandre Belloni if (!at91sam9260_pmc)
362c8923236SAlexandre Belloni return;
363c8923236SAlexandre Belloni
364c8923236SAlexandre Belloni bypass = of_property_read_bool(np, "atmel,osc-bypass");
365c8923236SAlexandre Belloni
366b5105e37SClaudiu Beznea hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, NULL,
367c8923236SAlexandre Belloni bypass);
368c8923236SAlexandre Belloni if (IS_ERR(hw))
369c8923236SAlexandre Belloni goto err_free;
370c8923236SAlexandre Belloni
371b5105e37SClaudiu Beznea hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc", NULL);
372c8923236SAlexandre Belloni if (IS_ERR(hw))
373c8923236SAlexandre Belloni goto err_free;
374c8923236SAlexandre Belloni
375c8923236SAlexandre Belloni at91sam9260_pmc->chws[PMC_MAIN] = hw;
376c8923236SAlexandre Belloni
377c8923236SAlexandre Belloni if (data->has_slck) {
378c8923236SAlexandre Belloni hw = clk_hw_register_fixed_rate_with_accuracy(NULL,
379c8923236SAlexandre Belloni "slow_rc_osc",
380c8923236SAlexandre Belloni NULL, 0, 32768,
381c8923236SAlexandre Belloni 50000000);
382c8923236SAlexandre Belloni if (IS_ERR(hw))
383c8923236SAlexandre Belloni goto err_free;
384c8923236SAlexandre Belloni
385c8923236SAlexandre Belloni parent_names[0] = "slow_rc_osc";
386c8923236SAlexandre Belloni parent_names[1] = "slow_xtal";
387c8923236SAlexandre Belloni hw = at91_clk_register_sam9260_slow(regmap, "slck",
388c8923236SAlexandre Belloni parent_names, 2);
389c8923236SAlexandre Belloni if (IS_ERR(hw))
390c8923236SAlexandre Belloni goto err_free;
391c8923236SAlexandre Belloni
392c8923236SAlexandre Belloni at91sam9260_pmc->chws[PMC_SLOW] = hw;
393c8923236SAlexandre Belloni slck_name = "slck";
394c8923236SAlexandre Belloni } else {
395c8923236SAlexandre Belloni slck_name = slowxtal_name;
396c8923236SAlexandre Belloni }
397c8923236SAlexandre Belloni
398c8923236SAlexandre Belloni hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
399c8923236SAlexandre Belloni data->plla_layout,
400c8923236SAlexandre Belloni data->plla_characteristics);
401c8923236SAlexandre Belloni if (IS_ERR(hw))
402c8923236SAlexandre Belloni goto err_free;
403c8923236SAlexandre Belloni
40403a1ee1dSMichał Mirosław at91sam9260_pmc->chws[PMC_PLLACK] = hw;
40503a1ee1dSMichał Mirosław
406c8923236SAlexandre Belloni hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
407c8923236SAlexandre Belloni data->pllb_layout,
408c8923236SAlexandre Belloni data->pllb_characteristics);
409c8923236SAlexandre Belloni if (IS_ERR(hw))
410c8923236SAlexandre Belloni goto err_free;
411c8923236SAlexandre Belloni
41203a1ee1dSMichał Mirosław at91sam9260_pmc->chws[PMC_PLLBCK] = hw;
41303a1ee1dSMichał Mirosław
414c8923236SAlexandre Belloni parent_names[0] = slck_name;
415c8923236SAlexandre Belloni parent_names[1] = "mainck";
416c8923236SAlexandre Belloni parent_names[2] = "pllack";
417c8923236SAlexandre Belloni parent_names[3] = "pllbck";
4187a110b91SClaudiu Beznea hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
419171e502cSClaudiu Beznea parent_names, NULL,
420c8923236SAlexandre Belloni &at91rm9200_master_layout,
4217a110b91SClaudiu Beznea data->mck_characteristics,
4228e842f02SClaudiu Beznea &at91sam9260_mck_lock);
4237a110b91SClaudiu Beznea if (IS_ERR(hw))
4247a110b91SClaudiu Beznea goto err_free;
4257a110b91SClaudiu Beznea
4267a110b91SClaudiu Beznea hw = at91_clk_register_master_div(regmap, "masterck_div",
427171e502cSClaudiu Beznea "masterck_pres", NULL,
4287a110b91SClaudiu Beznea &at91rm9200_master_layout,
4297a110b91SClaudiu Beznea data->mck_characteristics,
4307a110b91SClaudiu Beznea &at91sam9260_mck_lock,
4317029db09SClaudiu Beznea CLK_SET_RATE_GATE, 0);
432c8923236SAlexandre Belloni if (IS_ERR(hw))
433c8923236SAlexandre Belloni goto err_free;
434c8923236SAlexandre Belloni
435c8923236SAlexandre Belloni at91sam9260_pmc->chws[PMC_MCK] = hw;
436c8923236SAlexandre Belloni
437c8923236SAlexandre Belloni hw = at91rm9200_clk_register_usb(regmap, "usbck", "pllbck", usb_div);
438c8923236SAlexandre Belloni if (IS_ERR(hw))
439c8923236SAlexandre Belloni goto err_free;
440c8923236SAlexandre Belloni
441c8923236SAlexandre Belloni parent_names[0] = slck_name;
442c8923236SAlexandre Belloni parent_names[1] = "mainck";
443c8923236SAlexandre Belloni parent_names[2] = "pllack";
444c8923236SAlexandre Belloni parent_names[3] = "pllbck";
445c8923236SAlexandre Belloni for (i = 0; i < data->num_progck; i++) {
446c8923236SAlexandre Belloni char name[6];
447c8923236SAlexandre Belloni
448c8923236SAlexandre Belloni snprintf(name, sizeof(name), "prog%d", i);
449c8923236SAlexandre Belloni
450c8923236SAlexandre Belloni hw = at91_clk_register_programmable(regmap, name,
4511a2669dfSClaudiu Beznea parent_names, NULL, 4, i,
452c57aaaa2SClaudiu Beznea &at91rm9200_programmable_layout,
453c57aaaa2SClaudiu Beznea NULL);
454c8923236SAlexandre Belloni if (IS_ERR(hw))
455c8923236SAlexandre Belloni goto err_free;
45699767cd4SMichał Mirosław
45799767cd4SMichał Mirosław at91sam9260_pmc->pchws[i] = hw;
458c8923236SAlexandre Belloni }
459c8923236SAlexandre Belloni
460c8923236SAlexandre Belloni for (i = 0; i < data->num_sck; i++) {
461c8923236SAlexandre Belloni hw = at91_clk_register_system(regmap, data->sck[i].n,
462*1a537f62SClaudiu Beznea data->sck[i].p, NULL,
46368b3b6f1SClaudiu Beznea data->sck[i].id, 0);
464c8923236SAlexandre Belloni if (IS_ERR(hw))
465c8923236SAlexandre Belloni goto err_free;
466c8923236SAlexandre Belloni
467c8923236SAlexandre Belloni at91sam9260_pmc->shws[data->sck[i].id] = hw;
468c8923236SAlexandre Belloni }
469c8923236SAlexandre Belloni
470c8923236SAlexandre Belloni for (i = 0; i < data->num_pck; i++) {
471c8923236SAlexandre Belloni hw = at91_clk_register_peripheral(regmap,
472c8923236SAlexandre Belloni data->pck[i].n,
473c2f2ca0bSClaudiu Beznea "masterck_div", NULL,
474c8923236SAlexandre Belloni data->pck[i].id);
475c8923236SAlexandre Belloni if (IS_ERR(hw))
476c8923236SAlexandre Belloni goto err_free;
477c8923236SAlexandre Belloni
478c8923236SAlexandre Belloni at91sam9260_pmc->phws[data->pck[i].id] = hw;
479c8923236SAlexandre Belloni }
480c8923236SAlexandre Belloni
481c8923236SAlexandre Belloni of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9260_pmc);
482c8923236SAlexandre Belloni
483c8923236SAlexandre Belloni return;
484c8923236SAlexandre Belloni
485c8923236SAlexandre Belloni err_free:
4867425f246SMichał Mirosław kfree(at91sam9260_pmc);
487c8923236SAlexandre Belloni }
488c8923236SAlexandre Belloni
at91sam9260_pmc_setup(struct device_node * np)489c8923236SAlexandre Belloni static void __init at91sam9260_pmc_setup(struct device_node *np)
490c8923236SAlexandre Belloni {
491c8923236SAlexandre Belloni at91sam926x_pmc_setup(np, &at91sam9260_data);
492c8923236SAlexandre Belloni }
493428d97e1STudor Ambarus
494428d97e1STudor Ambarus CLK_OF_DECLARE(at91sam9260_pmc, "atmel,at91sam9260-pmc", at91sam9260_pmc_setup);
495c8923236SAlexandre Belloni
at91sam9261_pmc_setup(struct device_node * np)496c8923236SAlexandre Belloni static void __init at91sam9261_pmc_setup(struct device_node *np)
497c8923236SAlexandre Belloni {
498c8923236SAlexandre Belloni at91sam926x_pmc_setup(np, &at91sam9261_data);
499c8923236SAlexandre Belloni }
500428d97e1STudor Ambarus
501428d97e1STudor Ambarus CLK_OF_DECLARE(at91sam9261_pmc, "atmel,at91sam9261-pmc", at91sam9261_pmc_setup);
502c8923236SAlexandre Belloni
at91sam9263_pmc_setup(struct device_node * np)503c8923236SAlexandre Belloni static void __init at91sam9263_pmc_setup(struct device_node *np)
504c8923236SAlexandre Belloni {
505c8923236SAlexandre Belloni at91sam926x_pmc_setup(np, &at91sam9263_data);
506c8923236SAlexandre Belloni }
507428d97e1STudor Ambarus
508428d97e1STudor Ambarus CLK_OF_DECLARE(at91sam9263_pmc, "atmel,at91sam9263-pmc", at91sam9263_pmc_setup);
509c8923236SAlexandre Belloni
at91sam9g20_pmc_setup(struct device_node * np)510c8923236SAlexandre Belloni static void __init at91sam9g20_pmc_setup(struct device_node *np)
511c8923236SAlexandre Belloni {
512c8923236SAlexandre Belloni at91sam926x_pmc_setup(np, &at91sam9g20_data);
513c8923236SAlexandre Belloni }
514428d97e1STudor Ambarus
515428d97e1STudor Ambarus CLK_OF_DECLARE(at91sam9g20_pmc, "atmel,at91sam9g20-pmc", at91sam9g20_pmc_setup);
516