1b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
2b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * arch/arm/mach-lpc32xx/clock.c
3b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
4b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Author: Kevin Wells <kevin.wells@nxp.com>
5b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
6b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Copyright (C) 2010 NXP Semiconductors
7b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
8b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * This program is free software; you can redistribute it and/or modify
9b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * it under the terms of the GNU General Public License as published by
10b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * the Free Software Foundation; either version 2 of the License, or
11b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * (at your option) any later version.
12b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
13b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * This program is distributed in the hope that it will be useful,
14b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * but WITHOUT ANY WARRANTY; without even the implied warranty of
15b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * GNU General Public License for more details.
17b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
18b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
19b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
20b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * LPC32xx clock management driver overview
21b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
22b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * The LPC32XX contains a number of high level system clocks that can be
23b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * generated from different sources. These system clocks are used to
24b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * generate the CPU and bus rates and the individual peripheral clocks in
25b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * the system. When Linux is started by the boot loader, the system
26b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * clocks are already running. Stopping a system clock during normal
27b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Linux operation should never be attempted, as peripherals that require
28b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * those clocks will quit working (ie, DRAM).
29b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
30b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * The LPC32xx high level clock tree looks as follows. Clocks marked with
31b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * an asterisk are always on and cannot be disabled. Clocks marked with
32b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * an ampersand can only be disabled in CPU suspend mode. Clocks marked
33b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * with a caret are always on if it is the selected clock for the SYSCLK
34b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * source. The clock that isn't used for SYSCLK can be enabled and
35b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * disabled normally.
36b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                               32KHz oscillator*
37b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                               /      |      \
38b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                             RTC*   PLL397^ TOUCH
39b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                                     /
40b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *               Main oscillator^     /
41b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                   |        \      /
42b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                   |         SYSCLK&
43b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                   |            \
44b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                   |             \
45b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                USB_PLL       HCLK_PLL&
46b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                   |           |    |
47b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *            USB host/device  PCLK&  |
48b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                               |    |
49b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *                             Peripherals
50b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
51b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * The CPU and chip bus rates are derived from the HCLK PLL, which can
52b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * generate various clock rates up to 266MHz and beyond. The internal bus
53b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * rates (PCLK and HCLK) are generated from dividers based on the HCLK
54b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * PLL rate. HCLK can be a ratio of 1:1, 1:2, or 1:4 or HCLK PLL rate,
55b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * while PCLK can be 1:1 to 1:32 of HCLK PLL rate. Most peripherals high
56b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * level clocks are based on either HCLK or PCLK, but have their own
57b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * dividers as part of the IP itself. Because of this, the system clock
58b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * rates should not be changed.
59b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
60b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * The HCLK PLL is clocked from SYSCLK, which can be derived from the
61b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * main oscillator or PLL397. PLL397 generates a rate that is 397 times
62b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * the 32KHz oscillator rate. The main oscillator runs at the selected
63b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * oscillator/crystal rate on the mosc_in pin of the LPC32xx. This rate
64b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * is normally 13MHz, but depends on the selection of external crystals
65b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * or oscillators. If USB operation is required, the main oscillator must
66b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * be used in the system.
67b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *
68b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Switching SYSCLK between sources during normal Linux operation is not
69b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * supported. SYSCLK is preset in the bootloader. Because of the
70b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * complexities of clock management during clock frequency changes,
71b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * there are some limitations to the clock driver explained below:
72b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * - The PLL397 and main oscillator can be enabled and disabled by the
73b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *   clk_enable() and clk_disable() functions unless SYSCLK is based
74b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *   on that clock. This allows the other oscillator that isn't driving
75b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *   the HCLK PLL to be used as another system clock that can be routed
76b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *   to an external pin.
77b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * - The muxed SYSCLK input and HCLK_PLL rate cannot be changed with
78b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *   this driver.
79b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * - HCLK and PCLK rates cannot be changed as part of this driver.
80b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * - Most peripherals have their own dividers are part of the peripheral
81b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *   block. Changing SYSCLK, HCLK PLL, HCLK, or PCLK sources or rates
82b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells *   will also impact the individual peripheral rates.
83b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
84b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
858998316c425ed2b36ca3b01a658f08a7d006a4f9Roland Stigge#include <linux/export.h>
86b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <linux/kernel.h>
87b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <linux/list.h>
88b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <linux/errno.h>
89b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <linux/device.h>
9048a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge#include <linux/delay.h>
91b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <linux/err.h>
92b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <linux/clk.h>
93b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <linux/amba/bus.h>
94b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <linux/amba/clcd.h>
956d803ba736abb5e122dede70a4720e4843dd6df4Jean-Christop PLAGNIOL-VILLARD#include <linux/clkdev.h>
96b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
97b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <mach/hardware.h>
98b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include <mach/platform.h>
99b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include "clock.h"
100b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells#include "common.h"
101b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
102b84518625183e87c6930b11db0592be786181128Roland Stiggestatic DEFINE_SPINLOCK(global_clkregs_lock);
103b84518625183e87c6930b11db0592be786181128Roland Stigge
10448a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stiggestatic int usb_pll_enable, usb_pll_valid;
10548a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge
106b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_armpll;
107b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_usbpll;
108b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
109b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
110b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Post divider values for PLLs based on selected register value
111b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
112b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic const u32 pll_postdivs[4] = {1, 2, 4, 8};
113b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
114b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic unsigned long local_return_parent_rate(struct clk *clk)
115b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
116b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/*
117b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * If a clock has a rate of 0, then it inherits it's parent
118b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * clock rate
119b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 */
120b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	while (clk->rate == 0)
121b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		clk = clk->parent;
122b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
123b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return clk->rate;
124b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
125b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
126b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/* 32KHz clock has a fixed rate and is not stoppable */
127b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk osc_32KHz = {
128b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.rate		= LPC32XX_CLOCK_OSC_FREQ,
129b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
130b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
131b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
132b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int local_pll397_enable(struct clk *clk, int enable)
133b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
134b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 reg;
135f40a6818857e00c1d0ecec9af832f46a83f12f53Roland Stigge	unsigned long timeout = jiffies + msecs_to_jiffies(10);
136b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
137b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	reg = __raw_readl(LPC32XX_CLKPWR_PLL397_CTRL);
138b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
139b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (enable == 0) {
140b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		reg |= LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS;
141b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		__raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL);
142b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	} else {
143b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		/* Enable PLL397 */
144b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		reg &= ~LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS;
145b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		__raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL);
146b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
147b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		/* Wait for PLL397 lock */
148b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		while (((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) &
149b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) &&
150f40a6818857e00c1d0ecec9af832f46a83f12f53Roland Stigge			time_before(jiffies, timeout))
151b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			cpu_relax();
152b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
153b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if ((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) &
154b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0)
155b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			return -ENODEV;
156b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
157b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
158b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
159b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
160b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
161b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int local_oscmain_enable(struct clk *clk, int enable)
162b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
163b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 reg;
164f40a6818857e00c1d0ecec9af832f46a83f12f53Roland Stigge	unsigned long timeout = jiffies + msecs_to_jiffies(10);
165b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
166b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	reg = __raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL);
167b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
168b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (enable == 0) {
169b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		reg |= LPC32XX_CLKPWR_MOSC_DISABLE;
170b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		__raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL);
171b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	} else {
172b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		/* Enable main oscillator */
173b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		reg &= ~LPC32XX_CLKPWR_MOSC_DISABLE;
174b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		__raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL);
175b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
176b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		/* Wait for main oscillator to start */
177b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		while (((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) &
178b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			LPC32XX_CLKPWR_MOSC_DISABLE) != 0) &&
179f40a6818857e00c1d0ecec9af832f46a83f12f53Roland Stigge			time_before(jiffies, timeout))
180b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			cpu_relax();
181b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
182b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if ((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) &
183b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			LPC32XX_CLKPWR_MOSC_DISABLE) != 0)
184b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			return -ENODEV;
185b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
186b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
187b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
188b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
189b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
190b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk osc_pll397 = {
191b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &osc_32KHz,
192b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_pll397_enable,
193b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.rate		= LPC32XX_CLOCK_OSC_FREQ * 397,
194b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
195b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
196b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
197b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk osc_main = {
198b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_oscmain_enable,
199b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.rate		= LPC32XX_MAIN_OSC_FREQ,
200b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
201b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
202b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
203b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_sys;
204b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
205b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
206b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Convert a PLL register value to a PLL output frequency
207b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
208b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsu32 clk_get_pllrate_from_reg(u32 inputclk, u32 regval)
209b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
210b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	struct clk_pll_setup pllcfg;
211b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
212b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllcfg.cco_bypass_b15 = 0;
213b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllcfg.direct_output_b14 = 0;
214b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllcfg.fdbk_div_ctrl_b13 = 0;
215b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if ((regval & LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS) != 0)
216b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllcfg.cco_bypass_b15 = 1;
217b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if ((regval & LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS) != 0)
218b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllcfg.direct_output_b14 = 1;
219b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if ((regval & LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK) != 0)
220b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllcfg.fdbk_div_ctrl_b13 = 1;
221b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllcfg.pll_m = 1 + ((regval >> 1) & 0xFF);
222b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllcfg.pll_n = 1 + ((regval >> 9) & 0x3);
223b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllcfg.pll_p = pll_postdivs[((regval >> 11) & 0x3)];
224b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
225b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return clk_check_pll_setup(inputclk, &pllcfg);
226b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
227b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
228b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
229b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Setup the HCLK PLL with a PLL structure
230b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
231b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic u32 local_clk_pll_setup(struct clk_pll_setup *PllSetup)
232b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
233b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 tv, tmp = 0;
234b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
235b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (PllSetup->analog_on != 0)
236b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp |= LPC32XX_CLKPWR_HCLKPLL_POWER_UP;
237b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (PllSetup->cco_bypass_b15 != 0)
238b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp |= LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS;
239b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (PllSetup->direct_output_b14 != 0)
240b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS;
241b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (PllSetup->fdbk_div_ctrl_b13 != 0)
242b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp |= LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK;
243b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
244b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tv = ffs(PllSetup->pll_p) - 1;
245b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if ((!is_power_of_2(PllSetup->pll_p)) || (tv > 3))
246b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		return 0;
247b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
248b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_2POW(tv);
249b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp |= LPC32XX_CLKPWR_HCLKPLL_PREDIV_PLUS1(PllSetup->pll_n - 1);
250b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp |= LPC32XX_CLKPWR_HCLKPLL_PLLM(PllSetup->pll_m - 1);
251b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
252b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return tmp;
253b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
254b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
255b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
256b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Update the ARM core PLL frequency rate variable from the actual PLL setting
257b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
258b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic void local_update_armpll_rate(void)
259b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
260b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 clkin, pllreg;
261b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
262b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	clkin = clk_armpll.parent->rate;
263b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
264b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
265b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	clk_armpll.rate = clk_get_pllrate_from_reg(clkin, pllreg);
266b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
267b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
268b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
269b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Find a PLL configuration for the selected input frequency
270b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
271b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic u32 local_clk_find_pll_cfg(u32 pllin_freq, u32 target_freq,
272b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	struct clk_pll_setup *pllsetup)
273b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
274b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 ifreq, freqtol, m, n, p, fclkout;
275b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
276b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Determine frequency tolerance limits */
277b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	freqtol = target_freq / 250;
278b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	ifreq = pllin_freq;
279b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
280b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Is direct bypass mode possible? */
281b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (abs(pllin_freq - target_freq) <= freqtol) {
282b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->analog_on = 0;
283b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->cco_bypass_b15 = 1;
284b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->direct_output_b14 = 1;
285b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->fdbk_div_ctrl_b13 = 1;
286b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->pll_p = pll_postdivs[0];
287b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->pll_n = 1;
288b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->pll_m = 1;
289b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		return clk_check_pll_setup(ifreq, pllsetup);
290b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	} else if (target_freq <= ifreq) {
291b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->analog_on = 0;
292b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->cco_bypass_b15 = 1;
293b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->direct_output_b14 = 0;
294b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->fdbk_div_ctrl_b13 = 1;
295b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->pll_n = 1;
296b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pllsetup->pll_m = 1;
297b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		for (p = 0; p <= 3; p++) {
298b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			pllsetup->pll_p = pll_postdivs[p];
299b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			fclkout = clk_check_pll_setup(ifreq, pllsetup);
300b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			if (abs(target_freq - fclkout) <= freqtol)
301b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				return fclkout;
302b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		}
303b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
304b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
305b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Is direct mode possible? */
306b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->analog_on = 1;
307b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->cco_bypass_b15 = 0;
308b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->direct_output_b14 = 1;
309b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->fdbk_div_ctrl_b13 = 0;
310b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->pll_p = pll_postdivs[0];
311b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	for (m = 1; m <= 256; m++) {
312b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		for (n = 1; n <= 4; n++) {
313b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			/* Compute output frequency for this value */
314b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			pllsetup->pll_n = n;
315b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			pllsetup->pll_m = m;
316b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			fclkout = clk_check_pll_setup(ifreq,
317b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				pllsetup);
318b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			if (abs(target_freq - fclkout) <=
319b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				freqtol)
320b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				return fclkout;
321b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		}
322b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
323b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
324b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Is integer mode possible? */
325b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->analog_on = 1;
326b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->cco_bypass_b15 = 0;
327b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->direct_output_b14 = 0;
328b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->fdbk_div_ctrl_b13 = 1;
329b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	for (m = 1; m <= 256; m++) {
330b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		for (n = 1; n <= 4; n++) {
331b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			for (p = 0; p < 4; p++) {
332b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				/* Compute output frequency */
333b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				pllsetup->pll_p = pll_postdivs[p];
334b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				pllsetup->pll_n = n;
335b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				pllsetup->pll_m = m;
336b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				fclkout = clk_check_pll_setup(
337b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells					ifreq, pllsetup);
338b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				if (abs(target_freq - fclkout) <= freqtol)
339b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells					return fclkout;
340b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			}
341b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		}
342b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
343b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
344b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Try non-integer mode */
345b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->analog_on = 1;
346b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->cco_bypass_b15 = 0;
347b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->direct_output_b14 = 0;
348b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	pllsetup->fdbk_div_ctrl_b13 = 0;
349b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	for (m = 1; m <= 256; m++) {
350b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		for (n = 1; n <= 4; n++) {
351b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			for (p = 0; p < 4; p++) {
352b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				/* Compute output frequency */
353b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				pllsetup->pll_p = pll_postdivs[p];
354b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				pllsetup->pll_n = n;
355b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				pllsetup->pll_m = m;
356b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				fclkout = clk_check_pll_setup(
357b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells					ifreq, pllsetup);
358b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				if (abs(target_freq - fclkout) <= freqtol)
359b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells					return fclkout;
360b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			}
361b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		}
362b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
363b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
364b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
365b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
366b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
367b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_armpll = {
368b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_sys,
369b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
370b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
371b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
372b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
373b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * Setup the USB PLL with a PLL structure
374b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
375b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic u32 local_clk_usbpll_setup(struct clk_pll_setup *pHCLKPllSetup)
376b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
377b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 reg, tmp = local_clk_pll_setup(pHCLKPllSetup);
378b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
379b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL) & ~0x1FFFF;
380b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	reg |= tmp;
381b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
382b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
383b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return clk_check_pll_setup(clk_usbpll.parent->rate,
384b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		pHCLKPllSetup);
385b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
386b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
387b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int local_usbpll_enable(struct clk *clk, int enable)
388b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
389b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 reg;
39048a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	int ret = 0;
39148a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	unsigned long timeout = jiffies + msecs_to_jiffies(20);
392b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
393b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
394b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
39548a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	__raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN2 |
39648a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP),
39748a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		LPC32XX_CLKPWR_USB_CTRL);
39848a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	__raw_writel(reg & ~LPC32XX_CLKPWR_USBCTRL_CLK_EN1,
39948a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		LPC32XX_CLKPWR_USB_CTRL);
40048a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge
40148a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	if (enable && usb_pll_valid && usb_pll_enable) {
40248a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		ret = -ENODEV;
40348a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		/*
40448a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 * If the PLL rate has been previously set, then the rate
40548a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 * in the PLL register is valid and can be enabled here.
40648a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 * Otherwise, it needs to be enabled as part of setrate.
40748a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 */
40848a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge
40948a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		/*
41048a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 * Gate clock into PLL
41148a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 */
412b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
413b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
414b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
41548a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		/*
41648a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 * Enable PLL
41748a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 */
41848a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		reg |= LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP;
41948a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
42048a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge
42148a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		/*
42248a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 * Wait for PLL to lock
42348a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 */
424f40a6818857e00c1d0ecec9af832f46a83f12f53Roland Stigge		while (time_before(jiffies, timeout) && (ret == -ENODEV)) {
425b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
426b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS)
427b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells				ret = 0;
42848a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge			else
42948a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge				udelay(10);
430b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		}
431b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
43248a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		/*
43348a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 * Gate clock from PLL if PLL is locked
43448a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		 */
435b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if (ret == 0) {
43648a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge			__raw_writel(reg | LPC32XX_CLKPWR_USBCTRL_CLK_EN2,
43748a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge				LPC32XX_CLKPWR_USB_CTRL);
43848a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		} else {
43948a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge			__raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 |
44048a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge				LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP),
44148a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge				LPC32XX_CLKPWR_USB_CTRL);
442b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		}
44348a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	} else if ((enable == 0) && usb_pll_valid  && usb_pll_enable) {
44448a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		usb_pll_valid = 0;
44548a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		usb_pll_enable = 0;
446b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
447b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
448b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return ret;
449b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
450b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
451b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic unsigned long local_usbpll_round_rate(struct clk *clk,
452b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	unsigned long rate)
453b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
454b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 clkin, usbdiv;
455b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	struct clk_pll_setup pllsetup;
456b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
457b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/*
458b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * Unlike other clocks, this clock has a KHz input rate, so bump
459b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * it up to work with the PLL function
460b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 */
461b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	rate = rate * 1000;
462b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
46348a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	clkin = clk->get_rate(clk);
464b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) &
465b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1;
466b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	clkin = clkin / usbdiv;
467b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
468b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Try to find a good rate setup */
469b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0)
470b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		return 0;
471b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
472b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return clk_check_pll_setup(clkin, &pllsetup);
473b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
474b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
475b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int local_usbpll_set_rate(struct clk *clk, unsigned long rate)
476b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
47748a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	int ret = -ENODEV;
47848a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	u32 clkin, usbdiv;
479b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	struct clk_pll_setup pllsetup;
480b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
481b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/*
482b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * Unlike other clocks, this clock has a KHz input rate, so bump
483b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * it up to work with the PLL function
484b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 */
485b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	rate = rate * 1000;
486b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
48748a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	clkin = clk->get_rate(clk->parent);
488b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) &
489b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1;
490b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	clkin = clkin / usbdiv;
491b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
492b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Try to find a good rate setup */
493b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0)
494b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		return -EINVAL;
495b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
49648a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	/*
49748a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	 * Disable PLL clocks during PLL change
49848a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	 */
499b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	local_usbpll_enable(clk, 0);
50048a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	pllsetup.analog_on = 0;
501b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	local_clk_usbpll_setup(&pllsetup);
502b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
50348a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	/*
50448a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	 * Start USB PLL and check PLL status
50548a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	 */
50648a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge
50748a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	usb_pll_valid = 1;
50848a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	usb_pll_enable = 1;
509b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
51048a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	ret = local_usbpll_enable(clk, 1);
51148a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	if (ret >= 0)
51248a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge		clk->rate = clk_check_pll_setup(clkin, &pllsetup);
513b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
51448a5dedfa78899dad50b3b4ae30f07e27e6591abRoland Stigge	return ret;
515b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
516b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
517b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_usbpll = {
518b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &osc_main,
519b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.set_rate	= local_usbpll_set_rate,
520b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_usbpll_enable,
521b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.rate		= 48000, /* In KHz */
522b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
523b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.round_rate	= local_usbpll_round_rate,
524b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
525b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
526b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic u32 clk_get_hclk_div(void)
527b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
528b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	static const u32 hclkdivs[4] = {1, 2, 4, 4};
529b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return hclkdivs[LPC32XX_CLKPWR_HCLKDIV_DIV_2POW(
530b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		__raw_readl(LPC32XX_CLKPWR_HCLK_DIV))];
531b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
532b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
533b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_hclk = {
534b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_armpll,
535b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
536b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
537b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
538b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_pclk = {
539b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_armpll,
540b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
541b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
542b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
543b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int local_onoff_enable(struct clk *clk, int enable)
544b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
545b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 tmp;
546b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
547b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp = __raw_readl(clk->enable_reg);
548b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
549b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (enable == 0)
550b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp &= ~clk->enable_mask;
551b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	else
552b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp |= clk->enable_mask;
553b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
554b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(tmp, clk->enable_reg);
555b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
556b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
557b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
558b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
559b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/* Peripheral clock sources */
560b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_timer0 = {
561b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
562b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
563b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
564b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN,
565b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
566b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
567b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_timer1 = {
568b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
569b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
570b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
571b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
572b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
573b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
574b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_timer2 = {
575b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
576b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
577b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
578b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN,
579b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
580b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
581b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_timer3 = {
582b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
583b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
584b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
585b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN,
586b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
587b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
58884cee34db4d34b9059f4ef66f7d1805e438cc7f3Alban Bedelstatic struct clk clk_mpwm = {
58984cee34db4d34b9059f4ef66f7d1805e438cc7f3Alban Bedel	.parent		= &clk_pclk,
59084cee34db4d34b9059f4ef66f7d1805e438cc7f3Alban Bedel	.enable		= local_onoff_enable,
59184cee34db4d34b9059f4ef66f7d1805e438cc7f3Alban Bedel	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
59284cee34db4d34b9059f4ef66f7d1805e438cc7f3Alban Bedel	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_MPWM_EN,
59384cee34db4d34b9059f4ef66f7d1805e438cc7f3Alban Bedel	.get_rate	= local_return_parent_rate,
59484cee34db4d34b9059f4ef66f7d1805e438cc7f3Alban Bedel};
595b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_wdt = {
596b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
597b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
598b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_TIMER_CLK_CTRL,
599b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_PWMCLK_WDOG_EN,
600b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
601b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
602b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_vfp9 = {
603b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
604b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
605b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_DEBUG_CTRL,
606b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_VFP_CLOCK_ENABLE_BIT,
607b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
608b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
609b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_dma = {
610b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
611b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
612b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_DMA_CLK_CTRL,
613b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN,
614b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
615b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
616b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
6171f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silvastatic struct clk clk_pwm = {
6181f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva	.parent		= &clk_pclk,
6191f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva	.enable		= local_onoff_enable,
6201f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva	.enable_reg	= LPC32XX_CLKPWR_PWM_CLK_CTRL,
6211f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva	.enable_mask	= LPC32XX_CLKPWR_PWMCLK_PWM1CLK_EN |
6221f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva			  LPC32XX_CLKPWR_PWMCLK_PWM1SEL_PCLK |
6231f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva			  LPC32XX_CLKPWR_PWMCLK_PWM1_DIV(1) |
6241f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva			  LPC32XX_CLKPWR_PWMCLK_PWM2CLK_EN |
6251f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva			  LPC32XX_CLKPWR_PWMCLK_PWM2SEL_PCLK |
6261f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva			  LPC32XX_CLKPWR_PWMCLK_PWM2_DIV(1),
6271f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva	.get_rate	= local_return_parent_rate,
6281f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva};
6291f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva
630b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_uart3 = {
631b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
632b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
633b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
634b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART3_EN,
635b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
636b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
637b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
638b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_uart4 = {
639b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
640b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
641b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
642b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART4_EN,
643b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
644b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
645b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
646b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_uart5 = {
647b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
648b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
649b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
650b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART5_EN,
651b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
652b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
653b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
654b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_uart6 = {
655b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
656b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
657b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
658b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART6_EN,
659b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
660b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
661b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
662b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_i2c0 = {
663b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
664b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
665b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_I2C_CLK_CTRL,
666b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_I2CCLK_I2C1CLK_EN,
667b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
668b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
669b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
670b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_i2c1 = {
671b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
672b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
673b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_I2C_CLK_CTRL,
674b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_I2CCLK_I2C2CLK_EN,
675b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
676b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
677b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
678b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_i2c2 = {
679b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_pclk,
680b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
681b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= io_p2v(LPC32XX_USB_BASE + 0xFF4),
682b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= 0x4,
683b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
684b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
685b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
686b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_ssp0 = {
687b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
688b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
689b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_SSP_CLK_CTRL,
690b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN,
691b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
692b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
693b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
694b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_ssp1 = {
695b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
696b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
697b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_SSP_CLK_CTRL,
698b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_SSPCTRL_SSPCLK1_EN,
699b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
700b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
701b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
702b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_kscan = {
703b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &osc_32KHz,
704b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
705b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_KEY_CLK_CTRL,
706b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_KEYCLKCTRL_CLK_EN,
707b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
708b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
709b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
710b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_nand = {
711b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
712b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
713b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_NAND_CLK_CTRL,
714b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge	.enable_mask	= LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN |
715b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge			  LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
716b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
717b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
718b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
719b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stiggestatic struct clk clk_nand_mlc = {
720b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge	.parent         = &clk_hclk,
721b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge	.enable         = local_onoff_enable,
722b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge	.enable_reg     = LPC32XX_CLKPWR_NAND_CLK_CTRL,
723b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge	.enable_mask    = LPC32XX_CLKPWR_NANDCLK_MLCCLK_EN |
724b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge			  LPC32XX_CLKPWR_NANDCLK_DMA_INT |
725b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge			  LPC32XX_CLKPWR_NANDCLK_INTSEL_MLC,
726b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge	.get_rate       = local_return_parent_rate,
727b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge};
728b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge
729b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_i2s0 = {
730b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
731b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
732b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_I2S_CLK_CTRL,
733b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_I2SCTRL_I2SCLK0_EN,
734b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
735b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
736b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
737b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_i2s1 = {
738b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
739b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
740b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_I2S_CLK_CTRL,
741df072717eb0050326f0f63eed98200412c395831Alexandre Pereira da Silva	.enable_mask	= LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN |
742df072717eb0050326f0f63eed98200412c395831Alexandre Pereira da Silva			  LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA,
743b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
744b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
745b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
746b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_net = {
747b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
748b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
749b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_MACCLK_CTRL,
750b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= (LPC32XX_CLKPWR_MACCTRL_DMACLK_EN |
751b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		LPC32XX_CLKPWR_MACCTRL_MMIOCLK_EN |
752b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		LPC32XX_CLKPWR_MACCTRL_HRCCLK_EN),
753b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
754b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
755b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
756b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_rtc = {
757b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &osc_32KHz,
758b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.rate		= 1, /* 1 Hz */
759b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
760b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
761b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
762a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silvastatic int local_usb_enable(struct clk *clk, int enable)
763a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva{
764a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	u32 tmp;
765a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
766a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	if (enable) {
767a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		/* Set up I2C pull levels */
768a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
769a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE;
770a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		__raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
771a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	}
772a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
773a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	return local_onoff_enable(clk, enable);
774a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva}
775a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
776b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_usbd = {
777b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_usbpll,
778a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.enable		= local_usb_enable,
779b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_USB_CTRL,
780b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_USBCTRL_HCLK_EN,
781b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
782b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
783b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
784a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva#define OTG_ALWAYS_MASK		(LPC32XX_USB_OTG_OTG_CLOCK_ON | \
785a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva				 LPC32XX_USB_OTG_I2C_CLOCK_ON)
786a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
787a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silvastatic int local_usb_otg_enable(struct clk *clk, int enable)
788a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva{
789a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	int to = 1000;
790a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
791a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	if (enable) {
792a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		__raw_writel(clk->enable_mask, clk->enable_reg);
793a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
794a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		while (((__raw_readl(LPC32XX_USB_OTG_CLK_STAT) &
795a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			clk->enable_mask) != clk->enable_mask) && (to > 0))
796a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			to--;
797a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	} else {
798a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		__raw_writel(OTG_ALWAYS_MASK, clk->enable_reg);
799a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
800a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		while (((__raw_readl(LPC32XX_USB_OTG_CLK_STAT) &
801a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			OTG_ALWAYS_MASK) != OTG_ALWAYS_MASK) && (to > 0))
802a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			to--;
803a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	}
804a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
805a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	if (to)
806a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		return 0;
807a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	else
808a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva		return -1;
809a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva}
810a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
811a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silvastatic struct clk clk_usb_otg_dev = {
812a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.parent		= &clk_usbpll,
813a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.enable		= local_usb_otg_enable,
814a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.enable_reg	= LPC32XX_USB_OTG_CLK_CTRL,
815a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.enable_mask	= LPC32XX_USB_OTG_AHB_M_CLOCK_ON |
816a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			  LPC32XX_USB_OTG_OTG_CLOCK_ON |
817a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			  LPC32XX_USB_OTG_DEV_CLOCK_ON |
818a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			  LPC32XX_USB_OTG_I2C_CLOCK_ON,
819a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.get_rate	= local_return_parent_rate,
820a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva};
821a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
822a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silvastatic struct clk clk_usb_otg_host = {
823a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.parent		= &clk_usbpll,
824a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.enable		= local_usb_otg_enable,
825a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.enable_reg	= LPC32XX_USB_OTG_CLK_CTRL,
826a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.enable_mask	= LPC32XX_USB_OTG_AHB_M_CLOCK_ON |
827a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			  LPC32XX_USB_OTG_OTG_CLOCK_ON |
828a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			  LPC32XX_USB_OTG_HOST_CLOCK_ON |
829a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva			  LPC32XX_USB_OTG_I2C_CLOCK_ON,
830a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	.get_rate	= local_return_parent_rate,
831a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva};
832a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva
833b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int tsc_onoff_enable(struct clk *clk, int enable)
834b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
835b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 tmp;
836b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
837b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Make sure 32KHz clock is the selected clock */
838b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp = __raw_readl(LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
839b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp &= ~LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL;
840b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(tmp, LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
841b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
842b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (enable == 0)
843b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		__raw_writel(0, clk->enable_reg);
844b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	else
845b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		__raw_writel(clk->enable_mask, clk->enable_reg);
846b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
847b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
848b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
849b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
850b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_tsc = {
851b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &osc_32KHz,
852b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= tsc_onoff_enable,
853b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_ADC_CLK_CTRL,
854b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN,
855b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= local_return_parent_rate,
856b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
857b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
858678a0222edc9da43a22145d68647500ee85e6c04Roland Stiggestatic int adc_onoff_enable(struct clk *clk, int enable)
859678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge{
860678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	u32 tmp;
861678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	u32 divider;
862678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge
863678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	/* Use PERIPH_CLOCK */
864678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	tmp = __raw_readl(LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
865678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	tmp |= LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL;
866678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	/*
867678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	 * Set clock divider so that we have equal to or less than
868678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	 * 4.5MHz clock at ADC
869678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	 */
870678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	divider = clk->get_rate(clk) / 4500000 + 1;
871678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	tmp |= divider;
872678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	__raw_writel(tmp, LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
873678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge
874678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	/* synchronize rate of this clock w/ actual HW setting */
875678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	clk->rate = clk->get_rate(clk->parent) / divider;
876678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge
877678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	if (enable == 0)
878678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge		__raw_writel(0, clk->enable_reg);
879678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	else
880678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge		__raw_writel(clk->enable_mask, clk->enable_reg);
881678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge
882678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	return 0;
883678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge}
884678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge
885678a0222edc9da43a22145d68647500ee85e6c04Roland Stiggestatic struct clk clk_adc = {
886678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	.parent		= &clk_pclk,
887678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	.enable		= adc_onoff_enable,
888678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	.enable_reg	= LPC32XX_CLKPWR_ADC_CLK_CTRL,
889678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	.enable_mask	= LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN,
890678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge	.get_rate	= local_return_parent_rate,
891678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge};
892678a0222edc9da43a22145d68647500ee85e6c04Roland Stigge
893b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int mmc_onoff_enable(struct clk *clk, int enable)
894b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
895b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 tmp;
896b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
897b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
8985df5d01dd04ce0dde58e305dd258c7e54f079e65Roland Stigge		~(LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
899b0d9ef0e2df67685ffc74b1bafa648261ede30c0Roland Stigge		  LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN |
900b0d9ef0e2df67685ffc74b1bafa648261ede30c0Roland Stigge		  LPC32XX_CLKPWR_MSCARD_MSDIO_PIN_DIS |
901b0d9ef0e2df67685ffc74b1bafa648261ede30c0Roland Stigge		  LPC32XX_CLKPWR_MSCARD_MSDIO0_DIS |
902b0d9ef0e2df67685ffc74b1bafa648261ede30c0Roland Stigge		  LPC32XX_CLKPWR_MSCARD_MSDIO1_DIS |
903b0d9ef0e2df67685ffc74b1bafa648261ede30c0Roland Stigge		  LPC32XX_CLKPWR_MSCARD_MSDIO23_DIS);
904b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
905b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* If rate is 0, disable clock */
906b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (enable != 0)
9075df5d01dd04ce0dde58e305dd258c7e54f079e65Roland Stigge		tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
9085df5d01dd04ce0dde58e305dd258c7e54f079e65Roland Stigge			LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN;
909b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
910b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
911b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
912b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
913b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
914b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
915b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic unsigned long mmc_get_rate(struct clk *clk)
916b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
917b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 div, rate, oldclk;
918b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
919b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* The MMC clock must be on when accessing an MMC register */
920b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	oldclk = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
921b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(oldclk | LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
922b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		LPC32XX_CLKPWR_MS_CTRL);
923b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	div = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
924b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(oldclk, LPC32XX_CLKPWR_MS_CTRL);
925b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
926b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Get the parent clock rate */
927b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	rate = clk->parent->get_rate(clk->parent);
928b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
929b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Get the MMC controller clock divider value */
930b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	div = div & LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(0xf);
931b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
932b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (!div)
933b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		div = 1;
934b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
935b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return rate / div;
936b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
937b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
938b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic unsigned long mmc_round_rate(struct clk *clk, unsigned long rate)
939b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
940b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	unsigned long div, prate;
941b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
942b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Get the parent clock rate */
943b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	prate = clk->parent->get_rate(clk->parent);
944b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
945b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (rate >= prate)
946b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		return prate;
947b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
948b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	div = prate / rate;
949b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (div > 0xf)
950b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		div = 0xf;
951b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
952b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return prate / div;
953b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
954b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
955b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int mmc_set_rate(struct clk *clk, unsigned long rate)
956b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
957a0a30b6a69275c54542130a8391e0fda30a4553bRoland Stigge	u32 tmp;
958b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	unsigned long prate, div, crate = mmc_round_rate(clk, rate);
959b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
960b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	prate = clk->parent->get_rate(clk->parent);
961b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
962b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	div = prate / crate;
963b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
964b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* The MMC clock must be on when accessing an MMC register */
965b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
966b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		~LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(0xf);
967a0a30b6a69275c54542130a8391e0fda30a4553bRoland Stigge	tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(div) |
968a0a30b6a69275c54542130a8391e0fda30a4553bRoland Stigge		LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
969b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
970b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
971b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
972b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
973b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
974b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_mmc = {
975b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_armpll,
976b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.set_rate	= mmc_set_rate,
977b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= mmc_get_rate,
978b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.round_rate	= mmc_round_rate,
979b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= mmc_onoff_enable,
980b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_MS_CTRL,
981b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
982b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
983b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
984b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic unsigned long clcd_get_rate(struct clk *clk)
985b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
986b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 tmp, div, rate, oldclk;
987b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
988b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* The LCD clock must be on when accessing an LCD register */
989b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	oldclk = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
990b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(oldclk | LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
991b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		LPC32XX_CLKPWR_LCDCLK_CTRL);
992b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
993b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(oldclk, LPC32XX_CLKPWR_LCDCLK_CTRL);
994b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
995b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	rate = clk->parent->get_rate(clk->parent);
996b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
997b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Only supports internal clocking */
998b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (tmp & TIM2_BCD)
999b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		return rate;
1000b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1001b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	div = (tmp & 0x1F) | ((tmp & 0xF8) >> 22);
1002b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp = rate / (2 + div);
1003b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1004b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return tmp;
1005b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1006b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1007b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int clcd_set_rate(struct clk *clk, unsigned long rate)
1008b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1009b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 tmp, prate, div, oldclk;
1010b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1011b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* The LCD clock must be on when accessing an LCD register */
1012b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	oldclk = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
1013b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(oldclk | LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
1014b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		LPC32XX_CLKPWR_LCDCLK_CTRL);
1015b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1016b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2)) | TIM2_BCD;
1017b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	prate = clk->parent->get_rate(clk->parent);
1018b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1019b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (rate < prate) {
1020b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		/* Find closest divider */
1021b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		div = prate / rate;
1022b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if (div >= 2) {
1023b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			div -= 2;
1024b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			tmp &= ~TIM2_BCD;
1025b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		}
1026b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1027b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp &= ~(0xF800001F);
1028b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp |= (div & 0x1F);
1029b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		tmp |= (((div >> 5) & 0x1F) << 27);
1030b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
1031b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1032b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(tmp, io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
1033b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	__raw_writel(oldclk, LPC32XX_CLKPWR_LCDCLK_CTRL);
1034b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1035b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
1036b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1037b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1038b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic unsigned long clcd_round_rate(struct clk *clk, unsigned long rate)
1039b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1040b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	u32 prate, div;
1041b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1042b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	prate = clk->parent->get_rate(clk->parent);
1043b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1044b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (rate >= prate)
1045b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		rate = prate;
1046b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	else {
1047b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		div = prate / rate;
1048b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if (div > 0x3ff)
1049b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			div = 0x3ff;
1050b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1051b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		rate = prate / div;
1052b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
1053b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1054b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return rate;
1055b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1056b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1057b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk clk_lcd = {
1058b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.parent		= &clk_hclk,
1059b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.set_rate	= clcd_set_rate,
1060b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.get_rate	= clcd_get_rate,
1061b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.round_rate	= clcd_round_rate,
1062b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable		= local_onoff_enable,
1063b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_reg	= LPC32XX_CLKPWR_LCDCLK_CTRL,
1064b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	.enable_mask	= LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
1065b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
1066b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1067b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic void local_clk_disable(struct clk *clk)
1068b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1069b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Don't attempt to disable clock if it has no users */
1070b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (clk->usecount > 0) {
1071b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		clk->usecount--;
1072b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1073b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		/* Only disable clock when it has no more users */
1074b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if ((clk->usecount == 0) && (clk->enable))
1075b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			clk->enable(clk, 0);
1076b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1077b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		/* Check parent clocks, they may need to be disabled too */
1078b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if (clk->parent)
1079b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			local_clk_disable(clk->parent);
1080b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
1081b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1082b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1083b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int local_clk_enable(struct clk *clk)
1084b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1085b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	int ret = 0;
1086b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1087b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Enable parent clocks first and update use counts */
1088b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (clk->parent)
1089b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		ret = local_clk_enable(clk->parent);
1090b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1091b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (!ret) {
1092b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		/* Only enable clock if it's currently disabled */
1093b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if ((clk->usecount == 0) && (clk->enable))
1094b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			ret = clk->enable(clk, 1);
1095b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1096b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		if (!ret)
1097b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			clk->usecount++;
1098b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		else if (clk->parent)
1099b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells			local_clk_disable(clk->parent);
1100b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	}
1101b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1102b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return ret;
1103b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1104b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1105b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
1106b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * clk_enable - inform the system when the clock source should be running.
1107b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
1108b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsint clk_enable(struct clk *clk)
1109b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1110b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	int ret;
1111b84518625183e87c6930b11db0592be786181128Roland Stigge	unsigned long flags;
1112b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1113b84518625183e87c6930b11db0592be786181128Roland Stigge	spin_lock_irqsave(&global_clkregs_lock, flags);
1114b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	ret = local_clk_enable(clk);
1115b84518625183e87c6930b11db0592be786181128Roland Stigge	spin_unlock_irqrestore(&global_clkregs_lock, flags);
1116b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1117b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return ret;
1118b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1119b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin WellsEXPORT_SYMBOL(clk_enable);
1120b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1121b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
1122b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * clk_disable - inform the system when the clock source is no longer required
1123b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
1124b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsvoid clk_disable(struct clk *clk)
1125b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1126b84518625183e87c6930b11db0592be786181128Roland Stigge	unsigned long flags;
1127b84518625183e87c6930b11db0592be786181128Roland Stigge
1128b84518625183e87c6930b11db0592be786181128Roland Stigge	spin_lock_irqsave(&global_clkregs_lock, flags);
1129b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	local_clk_disable(clk);
1130b84518625183e87c6930b11db0592be786181128Roland Stigge	spin_unlock_irqrestore(&global_clkregs_lock, flags);
1131b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1132b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin WellsEXPORT_SYMBOL(clk_disable);
1133b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1134b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
1135b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * clk_get_rate - obtain the current clock rate (in Hz) for a clock source
1136b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
1137b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsunsigned long clk_get_rate(struct clk *clk)
1138b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1139b84518625183e87c6930b11db0592be786181128Roland Stigge	return clk->get_rate(clk);
1140b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1141b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin WellsEXPORT_SYMBOL(clk_get_rate);
1142b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1143b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
1144b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * clk_set_rate - set the clock rate for a clock source
1145b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
1146b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsint clk_set_rate(struct clk *clk, unsigned long rate)
1147b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1148b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	int ret = -EINVAL;
1149b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1150b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/*
1151b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * Most system clocks can only be enabled or disabled, with
1152b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * the actual rate set as part of the peripheral dividers
1153b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * instead of high level clock control
1154b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 */
1155b84518625183e87c6930b11db0592be786181128Roland Stigge	if (clk->set_rate)
1156b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		ret = clk->set_rate(clk, rate);
1157b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1158b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return ret;
1159b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1160b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin WellsEXPORT_SYMBOL(clk_set_rate);
1161b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1162b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
1163b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * clk_round_rate - adjust a rate to the exact rate a clock can provide
1164b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
1165b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellslong clk_round_rate(struct clk *clk, unsigned long rate)
1166b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1167b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (clk->round_rate)
1168b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		rate = clk->round_rate(clk, rate);
1169b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	else
1170b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		rate = clk->get_rate(clk);
1171b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1172b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return rate;
1173b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1174b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin WellsEXPORT_SYMBOL(clk_round_rate);
1175b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1176b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
1177b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * clk_set_parent - set the parent clock source for this clock
1178b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
1179b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsint clk_set_parent(struct clk *clk, struct clk *parent)
1180b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1181b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Clock re-parenting is not supported */
1182b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return -EINVAL;
1183b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1184b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin WellsEXPORT_SYMBOL(clk_set_parent);
1185b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1186b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells/*
1187b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells * clk_get_parent - get the parent clock source for this clock
1188b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells */
1189b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstruct clk *clk_get_parent(struct clk *clk)
1190b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1191b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return clk->parent;
1192b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1193b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin WellsEXPORT_SYMBOL(clk_get_parent);
1194b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1195b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic struct clk_lookup lookups[] = {
11965dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "osc_32KHz", &osc_32KHz),
11975dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "osc_pll397", &osc_pll397),
11985dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "osc_main", &osc_main),
11995dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "sys_ck", &clk_sys),
12005dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "arm_pll_ck", &clk_armpll),
12015dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "ck_pll5", &clk_usbpll),
12025dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "hclk_ck", &clk_hclk),
12035dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "pclk_ck", &clk_pclk),
12045dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "timer0_ck", &clk_timer0),
12055dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "timer1_ck", &clk_timer1),
12065dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "timer2_ck", &clk_timer2),
12075dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "timer3_ck", &clk_timer3),
12085dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "vfp9_ck", &clk_vfp9),
1209171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("pl08xdmac", NULL, &clk_dma),
1210171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("4003c000.watchdog", NULL, &clk_wdt),
12111f37a3a32b86c443396293b1f9d3e23b0a0344e5Alexandre Pereira da Silva	CLKDEV_INIT("4005c000.pwm", NULL, &clk_pwm),
121284cee34db4d34b9059f4ef66f7d1805e438cc7f3Alban Bedel	CLKDEV_INIT("400e8000.mpwm", NULL, &clk_mpwm),
12135dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "uart3_ck", &clk_uart3),
12145dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "uart4_ck", &clk_uart4),
12155dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "uart5_ck", &clk_uart5),
12165dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "uart6_ck", &clk_uart6),
1217171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("400a0000.i2c", NULL, &clk_i2c0),
1218171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("400a8000.i2c", NULL, &clk_i2c1),
1219171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("31020300.i2c", NULL, &clk_i2c2),
12205dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT("dev:ssp0", NULL, &clk_ssp0),
12215dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT("dev:ssp1", NULL, &clk_ssp1),
1222821e7edd5130a1efd8754bcd7e4c30ccb1fc9c71Roland Stigge	CLKDEV_INIT("40050000.key", NULL, &clk_kscan),
1223b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge	CLKDEV_INIT("20020000.flash", NULL, &clk_nand),
1224b27f48227c59754e1c881bd8e2b327ac02fe17b6Roland Stigge	CLKDEV_INIT("200a8000.flash", NULL, &clk_nand_mlc),
1225171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("40048000.adc", NULL, &clk_adc),
12265dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "i2s0_ck", &clk_i2s0),
12275dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT(NULL, "i2s1_ck", &clk_i2s1),
1228171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("40048000.tsc", NULL, &clk_tsc),
1229171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("20098000.sd", NULL, &clk_mmc),
1230171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("31060000.ethernet", NULL, &clk_net),
12315dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT("dev:clcd", NULL, &clk_lcd),
1232171b0a4f951926bf2e2bd58df53d5bd6549fb94aRoland Stigge	CLKDEV_INIT("31020000.usbd", "ck_usbd", &clk_usbd),
1233a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	CLKDEV_INIT("31020000.ohci", "ck_usbd", &clk_usbd),
1234a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	CLKDEV_INIT("31020000.usbd", "ck_usb_otg", &clk_usb_otg_dev),
1235a408e8f423e91a50727e7e85461cf7677d25ebf6Alexandre Pereira da Silva	CLKDEV_INIT("31020000.ohci", "ck_usb_otg", &clk_usb_otg_host),
12365dfdb0a0639751781c440a00ea97630d3eafe7caRoland Stigge	CLKDEV_INIT("lpc32xx_rtc", NULL, &clk_rtc),
1237b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells};
1238b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1239b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellsstatic int __init clk_init(void)
1240b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells{
1241b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	int i;
1242b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1243b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	for (i = 0; i < ARRAY_SIZE(lookups); i++)
1244b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		clkdev_add(&lookups[i]);
1245b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1246b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/*
1247b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * Setup muxed SYSCLK for HCLK PLL base -this selects the
1248b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * parent clock used for the ARM PLL and is used to derive
1249b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * the many system clock rates in the device.
1250b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 */
1251b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (clk_is_sysclk_mainosc() != 0)
1252b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		clk_sys.parent = &osc_main;
1253b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	else
1254b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		clk_sys.parent = &osc_pll397;
1255b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1256b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	clk_sys.rate = clk_sys.parent->rate;
1257b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1258b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Compute the current ARM PLL and USB PLL frequencies */
1259b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	local_update_armpll_rate();
1260b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1261b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/* Compute HCLK and PCLK bus rates */
1262b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	clk_hclk.rate = clk_hclk.parent->rate / clk_get_hclk_div();
1263b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	clk_pclk.rate = clk_pclk.parent->rate / clk_get_pclk_div();
1264b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1265b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/*
1266b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * Enable system clocks - this step is somewhat formal, as the
1267b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * clocks are already running, but it does get the clock data
1268b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * inline with the actual system state. Never disable these
1269b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * clocks as they will only stop if the system is going to sleep.
1270b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * In that case, the chip/system power management functions will
1271b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * handle clock gating.
1272b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 */
1273b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (clk_enable(&clk_hclk) || clk_enable(&clk_pclk))
1274b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		printk(KERN_ERR "Error enabling system HCLK and PCLK\n");
1275b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1276b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	/*
1277b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * Timers 0 and 1 were enabled and are being used by the high
1278b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * resolution tick function prior to this driver being initialized.
1279b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 * Tag them now as used.
1280b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	 */
1281b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	if (clk_enable(&clk_timer0) || clk_enable(&clk_timer1))
1282b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells		printk(KERN_ERR "Error enabling timer tick clocks\n");
1283b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1284b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells	return 0;
1285b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells}
1286b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wellscore_initcall(clk_init);
1287b9cc4bf6656d5f349c283e6ac267b852b7a2e42eKevin Wells
1288