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