blob: 4afb205c316be706ab43102940e309eea8356ba9 [file] [log] [blame]
Simon Glass16134fd2011-08-30 06:23:13 +00001/*
2 * Copyright (c) 2011 The Chromium OS Authors.
3 * See file CREDITS for list of people who contributed to this
4 * project.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307 USA
20 */
21
Allen Martin55d98a12012-08-31 08:30:00 +000022/* Tegra20 Clock control functions */
Simon Glass16134fd2011-08-30 06:23:13 +000023
Tom Warrenab371962012-09-19 15:50:56 -070024#include <common.h>
Simon Glass16134fd2011-08-30 06:23:13 +000025#include <asm/io.h>
Simon Glass16134fd2011-08-30 06:23:13 +000026#include <asm/arch/clock.h>
Tom Warrenab371962012-09-19 15:50:56 -070027#include <asm/arch/tegra.h>
28#include <asm/arch-tegra/clk_rst.h>
29#include <asm/arch-tegra/timer.h>
Simon Glassc2ea5e42011-09-21 12:40:04 +000030#include <div64.h>
Simon Glass2966cd22012-03-06 17:10:27 +000031#include <fdtdec.h>
Simon Glass16134fd2011-08-30 06:23:13 +000032
Simon Glass16134fd2011-08-30 06:23:13 +000033/*
Allen Martin55d98a12012-08-31 08:30:00 +000034 * Clock types that we can use as a source. The Tegra20 has muxes for the
Simon Glassc2ea5e42011-09-21 12:40:04 +000035 * peripheral clocks, and in most cases there are four options for the clock
36 * source. This gives us a clock 'type' and exploits what commonality exists
37 * in the device.
38 *
39 * Letters are obvious, except for T which means CLK_M, and S which means the
40 * clock derived from 32KHz. Beware that CLK_M (also called OSC in the
41 * datasheet) and PLL_M are different things. The former is the basic
42 * clock supplied to the SOC from an external oscillator. The latter is the
43 * memory clock PLL.
44 *
45 * See definitions in clock_id in the header file.
46 */
47enum clock_type_id {
48 CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */
49 CLOCK_TYPE_MCPA, /* and so on */
50 CLOCK_TYPE_MCPT,
51 CLOCK_TYPE_PCM,
52 CLOCK_TYPE_PCMT,
Simon Glassd2430222012-02-03 15:13:54 +000053 CLOCK_TYPE_PCMT16, /* CLOCK_TYPE_PCMT with 16-bit divider */
Simon Glassc2ea5e42011-09-21 12:40:04 +000054 CLOCK_TYPE_PCXTS,
55 CLOCK_TYPE_PDCT,
56
57 CLOCK_TYPE_COUNT,
58 CLOCK_TYPE_NONE = -1, /* invalid clock type */
59};
60
Simon Glassc2ea5e42011-09-21 12:40:04 +000061enum {
62 CLOCK_MAX_MUX = 4 /* number of source options for each clock */
63};
64
65/*
66 * Clock source mux for each clock type. This just converts our enum into
67 * a list of mux sources for use by the code. Note that CLOCK_TYPE_PCXTS
68 * is special as it has 5 sources. Since it also has a different number of
69 * bits in its register for the source, we just handle it with a special
70 * case in the code.
71 */
72#define CLK(x) CLOCK_ID_ ## x
73static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = {
74 { CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC) },
75 { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO) },
76 { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC) },
77 { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE) },
78 { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) },
Simon Glassd2430222012-02-03 15:13:54 +000079 { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) },
Simon Glassc2ea5e42011-09-21 12:40:04 +000080 { CLK(PERIPH), CLK(CGENERAL), CLK(XCPU), CLK(OSC) },
81 { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC) },
82};
83
84/*
85 * Clock peripheral IDs which sadly don't match up with PERIPH_ID. This is
86 * not in the header file since it is for purely internal use - we want
87 * callers to use the PERIPH_ID for all access to peripheral clocks to avoid
88 * confusion bewteen PERIPH_ID_... and PERIPHC_...
89 *
90 * We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be
91 * confusing.
92 *
93 * Note to SOC vendors: perhaps define a unified numbering for peripherals and
94 * use it for reset, clock enable, clock source/divider and even pinmuxing
95 * if you can.
96 */
97enum periphc_internal_id {
98 /* 0x00 */
99 PERIPHC_I2S1,
100 PERIPHC_I2S2,
101 PERIPHC_SPDIF_OUT,
102 PERIPHC_SPDIF_IN,
103 PERIPHC_PWM,
104 PERIPHC_SPI1,
105 PERIPHC_SPI2,
106 PERIPHC_SPI3,
107
108 /* 0x08 */
109 PERIPHC_XIO,
110 PERIPHC_I2C1,
111 PERIPHC_DVC_I2C,
112 PERIPHC_TWC,
113 PERIPHC_0c,
114 PERIPHC_10, /* PERIPHC_SPI1, what is this really? */
115 PERIPHC_DISP1,
116 PERIPHC_DISP2,
117
118 /* 0x10 */
119 PERIPHC_CVE,
120 PERIPHC_IDE0,
121 PERIPHC_VI,
122 PERIPHC_1c,
123 PERIPHC_SDMMC1,
124 PERIPHC_SDMMC2,
125 PERIPHC_G3D,
126 PERIPHC_G2D,
127
128 /* 0x18 */
129 PERIPHC_NDFLASH,
130 PERIPHC_SDMMC4,
131 PERIPHC_VFIR,
132 PERIPHC_EPP,
133 PERIPHC_MPE,
134 PERIPHC_MIPI,
135 PERIPHC_UART1,
136 PERIPHC_UART2,
137
138 /* 0x20 */
139 PERIPHC_HOST1X,
140 PERIPHC_21,
141 PERIPHC_TVO,
142 PERIPHC_HDMI,
143 PERIPHC_24,
144 PERIPHC_TVDAC,
145 PERIPHC_I2C2,
146 PERIPHC_EMC,
147
148 /* 0x28 */
149 PERIPHC_UART3,
150 PERIPHC_29,
151 PERIPHC_VI_SENSOR,
152 PERIPHC_2b,
153 PERIPHC_2c,
154 PERIPHC_SPI4,
155 PERIPHC_I2C3,
156 PERIPHC_SDMMC3,
157
158 /* 0x30 */
159 PERIPHC_UART4,
160 PERIPHC_UART5,
161 PERIPHC_VDE,
162 PERIPHC_OWR,
163 PERIPHC_NOR,
164 PERIPHC_CSITE,
165
166 PERIPHC_COUNT,
167
168 PERIPHC_NONE = -1,
169};
170
Simon Glassc2ea5e42011-09-21 12:40:04 +0000171/*
172 * Clock type for each peripheral clock source. We put the name in each
173 * record just so it is easy to match things up
174 */
175#define TYPE(name, type) type
176static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
177 /* 0x00 */
178 TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT),
179 TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT),
180 TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT),
181 TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM),
182 TYPE(PERIPHC_PWM, CLOCK_TYPE_PCXTS),
183 TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT),
184 TYPE(PERIPHC_SPI22, CLOCK_TYPE_PCMT),
185 TYPE(PERIPHC_SPI3, CLOCK_TYPE_PCMT),
186
187 /* 0x08 */
188 TYPE(PERIPHC_XIO, CLOCK_TYPE_PCMT),
Simon Glassd2430222012-02-03 15:13:54 +0000189 TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16),
190 TYPE(PERIPHC_DVC_I2C, CLOCK_TYPE_PCMT16),
Simon Glassc2ea5e42011-09-21 12:40:04 +0000191 TYPE(PERIPHC_TWC, CLOCK_TYPE_PCMT),
192 TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
193 TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT),
194 TYPE(PERIPHC_DISP1, CLOCK_TYPE_PDCT),
195 TYPE(PERIPHC_DISP2, CLOCK_TYPE_PDCT),
196
197 /* 0x10 */
198 TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT),
199 TYPE(PERIPHC_IDE0, CLOCK_TYPE_PCMT),
200 TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
201 TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
202 TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT),
203 TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT),
204 TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA),
205 TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA),
206
207 /* 0x18 */
208 TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT),
209 TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT),
210 TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT),
211 TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA),
212 TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA),
213 TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT),
214 TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT),
215 TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT),
216
217 /* 0x20 */
218 TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA),
219 TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
220 TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT),
221 TYPE(PERIPHC_HDMI, CLOCK_TYPE_PDCT),
222 TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
223 TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT),
Simon Glassd2430222012-02-03 15:13:54 +0000224 TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16),
Simon Glassc2ea5e42011-09-21 12:40:04 +0000225 TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT),
226
227 /* 0x28 */
228 TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT),
229 TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
230 TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
231 TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
232 TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
233 TYPE(PERIPHC_SPI4, CLOCK_TYPE_PCMT),
Simon Glassd2430222012-02-03 15:13:54 +0000234 TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16),
Simon Glassc2ea5e42011-09-21 12:40:04 +0000235 TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT),
236
237 /* 0x30 */
238 TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT),
239 TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT),
240 TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT),
241 TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT),
242 TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT),
243 TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT),
244};
245
246/*
247 * This array translates a periph_id to a periphc_internal_id
248 *
249 * Not present/matched up:
250 * uint vi_sensor; _VI_SENSOR_0, 0x1A8
251 * SPDIF - which is both 0x08 and 0x0c
252 *
253 */
254#define NONE(name) (-1)
255#define OFFSET(name, value) PERIPHC_ ## name
256static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
257 /* Low word: 31:0 */
258 NONE(CPU),
259 NONE(RESERVED1),
260 NONE(RESERVED2),
261 NONE(AC97),
262 NONE(RTC),
263 NONE(TMR),
264 PERIPHC_UART1,
265 PERIPHC_UART2, /* and vfir 0x68 */
266
267 /* 0x08 */
268 NONE(GPIO),
269 PERIPHC_SDMMC2,
270 NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */
271 PERIPHC_I2S1,
272 PERIPHC_I2C1,
273 PERIPHC_NDFLASH,
274 PERIPHC_SDMMC1,
275 PERIPHC_SDMMC4,
276
277 /* 0x10 */
278 PERIPHC_TWC,
279 PERIPHC_PWM,
280 PERIPHC_I2S2,
281 PERIPHC_EPP,
282 PERIPHC_VI,
283 PERIPHC_G2D,
284 NONE(USBD),
285 NONE(ISP),
286
287 /* 0x18 */
288 PERIPHC_G3D,
289 PERIPHC_IDE0,
290 PERIPHC_DISP2,
291 PERIPHC_DISP1,
292 PERIPHC_HOST1X,
293 NONE(VCP),
294 NONE(RESERVED30),
295 NONE(CACHE2),
296
297 /* Middle word: 63:32 */
298 NONE(MEM),
299 NONE(AHBDMA),
300 NONE(APBDMA),
301 NONE(RESERVED35),
302 NONE(KBC),
303 NONE(STAT_MON),
304 NONE(PMC),
305 NONE(FUSE),
306
307 /* 0x28 */
308 NONE(KFUSE),
309 NONE(SBC1), /* SBC1, 0x34, is this SPI1? */
310 PERIPHC_NOR,
311 PERIPHC_SPI1,
312 PERIPHC_SPI2,
313 PERIPHC_XIO,
314 PERIPHC_SPI3,
315 PERIPHC_DVC_I2C,
316
317 /* 0x30 */
318 NONE(DSI),
319 PERIPHC_TVO, /* also CVE 0x40 */
320 PERIPHC_MIPI,
321 PERIPHC_HDMI,
322 PERIPHC_CSITE,
323 PERIPHC_TVDAC,
324 PERIPHC_I2C2,
325 PERIPHC_UART3,
326
327 /* 0x38 */
328 NONE(RESERVED56),
329 PERIPHC_EMC,
330 NONE(USB2),
331 NONE(USB3),
332 PERIPHC_MPE,
333 PERIPHC_VDE,
334 NONE(BSEA),
335 NONE(BSEV),
336
337 /* Upper word 95:64 */
338 NONE(SPEEDO),
339 PERIPHC_UART4,
340 PERIPHC_UART5,
341 PERIPHC_I2C3,
342 PERIPHC_SPI4,
343 PERIPHC_SDMMC3,
344 NONE(PCIE),
345 PERIPHC_OWR,
346
347 /* 0x48 */
348 NONE(AFI),
349 NONE(CORESIGHT),
350 NONE(RESERVED74),
351 NONE(AVPUCQ),
352 NONE(RESERVED76),
353 NONE(RESERVED77),
354 NONE(RESERVED78),
355 NONE(RESERVED79),
356
357 /* 0x50 */
358 NONE(RESERVED80),
359 NONE(RESERVED81),
360 NONE(RESERVED82),
361 NONE(RESERVED83),
362 NONE(IRAMA),
363 NONE(IRAMB),
364 NONE(IRAMC),
365 NONE(IRAMD),
366
367 /* 0x58 */
368 NONE(CRAM2),
369};
370
371/*
Simon Glass16134fd2011-08-30 06:23:13 +0000372 * Get the oscillator frequency, from the corresponding hardware configuration
Tom Warren795f9d72013-01-23 14:01:01 -0700373 * field. T20 has 4 frequencies that it supports.
Simon Glass16134fd2011-08-30 06:23:13 +0000374 */
375enum clock_osc_freq clock_get_osc_freq(void)
376{
377 struct clk_rst_ctlr *clkrst =
378 (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
379 u32 reg;
380
381 reg = readl(&clkrst->crc_osc_ctrl);
382 return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
383}
384
Simon Glassc2ea5e42011-09-21 12:40:04 +0000385/* Returns a pointer to the clock source register for a peripheral */
Tom Warren795f9d72013-01-23 14:01:01 -0700386u32 *get_periph_source_reg(enum periph_id periph_id)
Simon Glassc2ea5e42011-09-21 12:40:04 +0000387{
388 struct clk_rst_ctlr *clkrst =
389 (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
390 enum periphc_internal_id internal_id;
391
392 assert(clock_periph_id_isvalid(periph_id));
393 internal_id = periph_id_to_internal_id[periph_id];
394 assert(internal_id != -1);
395 return &clkrst->crc_clk_src[internal_id];
396}
397
Simon Glassc2ea5e42011-09-21 12:40:04 +0000398/**
399 * Given a peripheral ID and the required source clock, this returns which
400 * value should be programmed into the source mux for that peripheral.
401 *
402 * There is special code here to handle the one source type with 5 sources.
403 *
404 * @param periph_id peripheral to start
405 * @param source PLL id of required parent clock
406 * @param mux_bits Set to number of bits in mux register: 2 or 4
Simon Glassd2430222012-02-03 15:13:54 +0000407 * @param divider_bits Set to number of divider bits (8 or 16)
Simon Glassc2ea5e42011-09-21 12:40:04 +0000408 * @return mux value (0-4, or -1 if not found)
409 */
Tom Warren795f9d72013-01-23 14:01:01 -0700410int get_periph_clock_source(enum periph_id periph_id,
Simon Glassd2430222012-02-03 15:13:54 +0000411 enum clock_id parent, int *mux_bits, int *divider_bits)
Simon Glassc2ea5e42011-09-21 12:40:04 +0000412{
413 enum clock_type_id type;
414 enum periphc_internal_id internal_id;
415 int mux;
416
417 assert(clock_periph_id_isvalid(periph_id));
418
419 internal_id = periph_id_to_internal_id[periph_id];
420 assert(periphc_internal_id_isvalid(internal_id));
421
422 type = clock_periph_type[internal_id];
423 assert(clock_type_id_isvalid(type));
424
Simon Glassd2430222012-02-03 15:13:54 +0000425 /*
426 * Special cases here for the clock with a 4-bit source mux and I2C
427 * with its 16-bit divisor
428 */
Simon Glassc2ea5e42011-09-21 12:40:04 +0000429 if (type == CLOCK_TYPE_PCXTS)
430 *mux_bits = 4;
431 else
432 *mux_bits = 2;
Simon Glassd2430222012-02-03 15:13:54 +0000433 if (type == CLOCK_TYPE_PCMT16)
434 *divider_bits = 16;
435 else
436 *divider_bits = 8;
Simon Glassc2ea5e42011-09-21 12:40:04 +0000437
438 for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
439 if (clock_source[type][mux] == parent)
440 return mux;
441
442 /*
443 * Not found: it might be looking for the 'S' in CLOCK_TYPE_PCXTS
444 * which is not in our table. If not, then they are asking for a
445 * source which this peripheral can't access through its mux.
446 */
447 assert(type == CLOCK_TYPE_PCXTS);
448 assert(parent == CLOCK_ID_SFROM32KHZ);
449 if (type == CLOCK_TYPE_PCXTS && parent == CLOCK_ID_SFROM32KHZ)
450 return 4; /* mux value for this clock */
451
452 /* if we get here, either us or the caller has made a mistake */
453 printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
454 parent);
455 return -1;
456}
457
Simon Glass16134fd2011-08-30 06:23:13 +0000458void clock_set_enable(enum periph_id periph_id, int enable)
459{
460 struct clk_rst_ctlr *clkrst =
461 (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
462 u32 *clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
463 u32 reg;
464
465 /* Enable/disable the clock to this peripheral */
466 assert(clock_periph_id_isvalid(periph_id));
467 reg = readl(clk);
468 if (enable)
469 reg |= PERIPH_MASK(periph_id);
470 else
471 reg &= ~PERIPH_MASK(periph_id);
472 writel(reg, clk);
473}
474
Simon Glass16134fd2011-08-30 06:23:13 +0000475void reset_set_enable(enum periph_id periph_id, int enable)
476{
477 struct clk_rst_ctlr *clkrst =
478 (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
479 u32 *reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
480 u32 reg;
481
482 /* Enable/disable reset to the peripheral */
483 assert(clock_periph_id_isvalid(periph_id));
484 reg = readl(reset);
485 if (enable)
486 reg |= PERIPH_MASK(periph_id);
487 else
488 reg &= ~PERIPH_MASK(periph_id);
489 writel(reg, reset);
490}
491
Simon Glass2966cd22012-03-06 17:10:27 +0000492#ifdef CONFIG_OF_CONTROL
493/*
494 * Convert a device tree clock ID to our peripheral ID. They are mostly
495 * the same but we are very cautious so we check that a valid clock ID is
496 * provided.
497 *
Allen Martin55d98a12012-08-31 08:30:00 +0000498 * @param clk_id Clock ID according to tegra20 device tree binding
Simon Glass2966cd22012-03-06 17:10:27 +0000499 * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
500 */
Tom Warren795f9d72013-01-23 14:01:01 -0700501enum periph_id clk_id_to_periph_id(int clk_id)
Simon Glass2966cd22012-03-06 17:10:27 +0000502{
Tom Warren795f9d72013-01-23 14:01:01 -0700503 if (clk_id > PERIPH_ID_COUNT)
Simon Glass2966cd22012-03-06 17:10:27 +0000504 return PERIPH_ID_NONE;
505
506 switch (clk_id) {
Tom Warren795f9d72013-01-23 14:01:01 -0700507 case PERIPH_ID_RESERVED1:
508 case PERIPH_ID_RESERVED2:
509 case PERIPH_ID_RESERVED30:
510 case PERIPH_ID_RESERVED35:
511 case PERIPH_ID_RESERVED56:
512 case PERIPH_ID_RESERVED74:
513 case PERIPH_ID_RESERVED76:
514 case PERIPH_ID_RESERVED77:
515 case PERIPH_ID_RESERVED78:
516 case PERIPH_ID_RESERVED79:
517 case PERIPH_ID_RESERVED80:
518 case PERIPH_ID_RESERVED81:
519 case PERIPH_ID_RESERVED82:
520 case PERIPH_ID_RESERVED83:
521 case PERIPH_ID_RESERVED91:
Simon Glass2966cd22012-03-06 17:10:27 +0000522 return PERIPH_ID_NONE;
523 default:
524 return clk_id;
525 }
526}
Simon Glass2966cd22012-03-06 17:10:27 +0000527#endif /* CONFIG_OF_CONTROL */
528
Simon Glassc2ea5e42011-09-21 12:40:04 +0000529void clock_early_init(void)
530{
531 /*
532 * PLLP output frequency set to 216MHz
533 * PLLC output frequency set to 600Mhz
534 *
535 * TODO: Can we calculate these values instead of hard-coding?
536 */
537 switch (clock_get_osc_freq()) {
538 case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
539 clock_set_rate(CLOCK_ID_PERIPH, 432, 12, 1, 8);
540 clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8);
541 break;
542
543 case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
544 clock_set_rate(CLOCK_ID_PERIPH, 432, 26, 1, 8);
545 clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
546 break;
547
Lucas Stacha5851fc2012-05-01 12:50:05 +0000548 case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
549 clock_set_rate(CLOCK_ID_PERIPH, 432, 13, 1, 8);
550 clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
551 break;
Simon Glassc2ea5e42011-09-21 12:40:04 +0000552 case CLOCK_OSC_FREQ_19_2:
553 default:
554 /*
555 * These are not supported. It is too early to print a
556 * message and the UART likely won't work anyway due to the
557 * oscillator being wrong.
558 */
559 break;
560 }
561}
Tom Warrenfbef3552013-04-01 15:48:54 -0700562
563void arch_timer_init(void)
564{
565}