|  | /* | 
|  | * | 
|  | * arch/arm/mach-u300/clock.c | 
|  | * | 
|  | * | 
|  | * Copyright (C) 2007-2009 ST-Ericsson AB | 
|  | * License terms: GNU General Public License (GPL) version 2 | 
|  | * Define clocks in the app platform. | 
|  | * Author: Linus Walleij <linus.walleij@stericsson.com> | 
|  | * Author: Jonas Aaberg <jonas.aberg@stericsson.com> | 
|  | * | 
|  | */ | 
|  | #include <linux/module.h> | 
|  | #include <linux/kernel.h> | 
|  | #include <linux/list.h> | 
|  | #include <linux/errno.h> | 
|  | #include <linux/err.h> | 
|  | #include <linux/string.h> | 
|  | #include <linux/clk.h> | 
|  | #include <linux/mutex.h> | 
|  | #include <linux/spinlock.h> | 
|  | #include <linux/debugfs.h> | 
|  | #include <linux/device.h> | 
|  | #include <linux/init.h> | 
|  | #include <linux/timer.h> | 
|  | #include <linux/io.h> | 
|  | #include <linux/seq_file.h> | 
|  | #include <linux/clkdev.h> | 
|  |  | 
|  | #include <mach/hardware.h> | 
|  | #include <mach/syscon.h> | 
|  |  | 
|  | #include "clock.h" | 
|  |  | 
|  | /* | 
|  | * TODO: | 
|  | * - move all handling of the CCR register into this file and create | 
|  | *   a spinlock for the CCR register | 
|  | * - switch to the clkdevice lookup mechanism that maps clocks to | 
|  | *   device ID:s instead when it becomes available in kernel 2.6.29. | 
|  | * - implement rate get/set for all clocks that need it. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Syscon clock I/O registers lock so clock requests don't collide | 
|  | * NOTE: this is a local lock only used to lock access to clock and | 
|  | * reset registers in syscon. | 
|  | */ | 
|  | static DEFINE_SPINLOCK(syscon_clkreg_lock); | 
|  | static DEFINE_SPINLOCK(syscon_resetreg_lock); | 
|  |  | 
|  | /* | 
|  | * The clocking hierarchy currently looks like this. | 
|  | * NOTE: the idea is NOT to show how the clocks are routed on the chip! | 
|  | * The ideas is to show dependencies, so a clock higher up in the | 
|  | * hierarchy has to be on in order for another clock to be on. Now, | 
|  | * both CPU and DMA can actually be on top of the hierarchy, and that | 
|  | * is not modeled currently. Instead we have the backbone AMBA bus on | 
|  | * top. This bus cannot be programmed in any way but conceptually it | 
|  | * needs to be active for the bridges and devices to transport data. | 
|  | * | 
|  | * Please be aware that a few clocks are hw controlled, which mean that | 
|  | * the hw itself can turn on/off or change the rate of the clock when | 
|  | * needed! | 
|  | * | 
|  | *  AMBA bus | 
|  | *  | | 
|  | *  +- CPU | 
|  | *  +- FSMC NANDIF NAND Flash interface | 
|  | *  +- SEMI Shared Memory interface | 
|  | *  +- ISP Image Signal Processor (U335 only) | 
|  | *  +- CDS (U335 only) | 
|  | *  +- DMA Direct Memory Access Controller | 
|  | *  +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL) | 
|  | *  +- APEX | 
|  | *  +- VIDEO_ENC AVE2/3 Video Encoder | 
|  | *  +- XGAM Graphics Accelerator Controller | 
|  | *  +- AHB | 
|  | *  | | 
|  | *  +- ahb:0 AHB Bridge | 
|  | *  |  | | 
|  | *  |  +- ahb:1 INTCON Interrupt controller | 
|  | *  |  +- ahb:3 MSPRO  Memory Stick Pro controller | 
|  | *  |  +- ahb:4 EMIF   External Memory interface | 
|  | *  | | 
|  | *  +- fast:0 FAST bridge | 
|  | *  |  | | 
|  | *  |  +- fast:1 MMCSD MMC/SD card reader controller | 
|  | *  |  +- fast:2 I2S0  PCM I2S channel 0 controller | 
|  | *  |  +- fast:3 I2S1  PCM I2S channel 1 controller | 
|  | *  |  +- fast:4 I2C0  I2C channel 0 controller | 
|  | *  |  +- fast:5 I2C1  I2C channel 1 controller | 
|  | *  |  +- fast:6 SPI   SPI controller | 
|  | *  |  +- fast:7 UART1 Secondary UART (U335 only) | 
|  | *  | | 
|  | *  +- slow:0 SLOW bridge | 
|  | *     | | 
|  | *     +- slow:1 SYSCON (not possible to control) | 
|  | *     +- slow:2 WDOG Watchdog | 
|  | *     +- slow:3 UART0 primary UART | 
|  | *     +- slow:4 TIMER_APP Application timer - used in Linux | 
|  | *     +- slow:5 KEYPAD controller | 
|  | *     +- slow:6 GPIO controller | 
|  | *     +- slow:7 RTC controller | 
|  | *     +- slow:8 BT Bus Tracer (not used currently) | 
|  | *     +- slow:9 EH Event Handler (not used currently) | 
|  | *     +- slow:a TIMER_ACC Access style timer (not used currently) | 
|  | *     +- slow:b PPM (U335 only, what is that?) | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Reset control functions. We remember if a block has been | 
|  | * taken out of reset and don't remove the reset assertion again | 
|  | * and vice versa. Currently we only remove resets so the | 
|  | * enablement function is defined out. | 
|  | */ | 
|  | static void syscon_block_reset_enable(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  | unsigned long iflags; | 
|  |  | 
|  | /* Not all blocks support resetting */ | 
|  | if (!clk->res_reg || !clk->res_mask) | 
|  | return; | 
|  | spin_lock_irqsave(&syscon_resetreg_lock, iflags); | 
|  | val = readw(clk->res_reg); | 
|  | val |= clk->res_mask; | 
|  | writew(val, clk->res_reg); | 
|  | spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); | 
|  | clk->reset = true; | 
|  | } | 
|  |  | 
|  | static void syscon_block_reset_disable(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  | unsigned long iflags; | 
|  |  | 
|  | /* Not all blocks support resetting */ | 
|  | if (!clk->res_reg || !clk->res_mask) | 
|  | return; | 
|  | spin_lock_irqsave(&syscon_resetreg_lock, iflags); | 
|  | val = readw(clk->res_reg); | 
|  | val &= ~clk->res_mask; | 
|  | writew(val, clk->res_reg); | 
|  | spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); | 
|  | clk->reset = false; | 
|  | } | 
|  |  | 
|  | int __clk_get(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  |  | 
|  | /* The MMC and MSPRO clocks need some special set-up */ | 
|  | if (!strcmp(clk->name, "MCLK")) { | 
|  | /* Set default MMC clock divisor to 18.9 MHz */ | 
|  | writew(0x0054U, U300_SYSCON_VBASE + U300_SYSCON_MMF0R); | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR); | 
|  | /* Disable the MMC feedback clock */ | 
|  | val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; | 
|  | /* Disable MSPRO frequency */ | 
|  | val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR); | 
|  | } | 
|  | if (!strcmp(clk->name, "MSPRO")) { | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR); | 
|  | /* Disable the MMC feedback clock */ | 
|  | val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; | 
|  | /* Enable MSPRO frequency */ | 
|  | val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR); | 
|  | } | 
|  | return 1; | 
|  | } | 
|  | EXPORT_SYMBOL(__clk_get); | 
|  |  | 
|  | void __clk_put(struct clk *clk) | 
|  | { | 
|  | } | 
|  | EXPORT_SYMBOL(__clk_put); | 
|  |  | 
|  | static void syscon_clk_disable(struct clk *clk) | 
|  | { | 
|  | unsigned long iflags; | 
|  |  | 
|  | /* Don't touch the hardware controlled clocks */ | 
|  | if (clk->hw_ctrld) | 
|  | return; | 
|  |  | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCDR); | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | } | 
|  |  | 
|  | static void syscon_clk_enable(struct clk *clk) | 
|  | { | 
|  | unsigned long iflags; | 
|  |  | 
|  | /* Don't touch the hardware controlled clocks */ | 
|  | if (clk->hw_ctrld) | 
|  | return; | 
|  |  | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCER); | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | } | 
|  |  | 
|  | static u16 syscon_clk_get_rate(void) | 
|  | { | 
|  | u16 val; | 
|  | unsigned long iflags; | 
|  |  | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | return val; | 
|  | } | 
|  |  | 
|  | #ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER | 
|  | static void enable_i2s0_vcxo(void) | 
|  | { | 
|  | u16 val; | 
|  | unsigned long iflags; | 
|  |  | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | /* Set I2S0 to use the VCXO 26 MHz clock */ | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val |= U300_SYSCON_CCR_TURN_VCXO_ON; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val |= U300_SYSCON_CCR_I2S0_USE_VCXO; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); | 
|  | val |= U300_SYSCON_CEFR_I2S0_CLK_EN; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | } | 
|  |  | 
|  | static void enable_i2s1_vcxo(void) | 
|  | { | 
|  | u16 val; | 
|  | unsigned long iflags; | 
|  |  | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | /* Set I2S1 to use the VCXO 26 MHz clock */ | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val |= U300_SYSCON_CCR_TURN_VCXO_ON; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val |= U300_SYSCON_CCR_I2S1_USE_VCXO; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); | 
|  | val |= U300_SYSCON_CEFR_I2S1_CLK_EN; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | } | 
|  |  | 
|  | static void disable_i2s0_vcxo(void) | 
|  | { | 
|  | u16 val; | 
|  | unsigned long iflags; | 
|  |  | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | /* Disable I2S0 use of the VCXO 26 MHz clock */ | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val &= ~U300_SYSCON_CCR_I2S0_USE_VCXO; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | /* Deactivate VCXO if no one else is using VCXO */ | 
|  | if (!(val & U300_SYSCON_CCR_I2S1_USE_VCXO)) | 
|  | val &= ~U300_SYSCON_CCR_TURN_VCXO_ON; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); | 
|  | val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | } | 
|  |  | 
|  | static void disable_i2s1_vcxo(void) | 
|  | { | 
|  | u16 val; | 
|  | unsigned long iflags; | 
|  |  | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | /* Disable I2S1 use of the VCXO 26 MHz clock */ | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val &= ~U300_SYSCON_CCR_I2S1_USE_VCXO; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | /* Deactivate VCXO if no one else is using VCXO */ | 
|  | if (!(val & U300_SYSCON_CCR_I2S0_USE_VCXO)) | 
|  | val &= ~U300_SYSCON_CCR_TURN_VCXO_ON; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); | 
|  | val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | } | 
|  | #endif /* CONFIG_MACH_U300_USE_I2S_AS_MASTER */ | 
|  |  | 
|  |  | 
|  | static void syscon_clk_rate_set_mclk(unsigned long rate) | 
|  | { | 
|  | u16 val; | 
|  | u32 reg; | 
|  | unsigned long iflags; | 
|  |  | 
|  | switch (rate) { | 
|  | case 18900000: | 
|  | val = 0x0054; | 
|  | break; | 
|  | case 20800000: | 
|  | val = 0x0044; | 
|  | break; | 
|  | case 23100000: | 
|  | val = 0x0043; | 
|  | break; | 
|  | case 26000000: | 
|  | val = 0x0033; | 
|  | break; | 
|  | case 29700000: | 
|  | val = 0x0032; | 
|  | break; | 
|  | case 34700000: | 
|  | val = 0x0022; | 
|  | break; | 
|  | case 41600000: | 
|  | val = 0x0021; | 
|  | break; | 
|  | case 52000000: | 
|  | val = 0x0011; | 
|  | break; | 
|  | case 104000000: | 
|  | val = 0x0000; | 
|  | break; | 
|  | default: | 
|  | printk(KERN_ERR "Trying to set MCLK to unknown speed! %ld\n", | 
|  | rate); | 
|  | return; | 
|  | } | 
|  |  | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | reg = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) & | 
|  | ~U300_SYSCON_MMF0R_MASK; | 
|  | writew(reg | val, U300_SYSCON_VBASE + U300_SYSCON_MMF0R); | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | } | 
|  |  | 
|  | void syscon_clk_rate_set_cpuclk(unsigned long rate) | 
|  | { | 
|  | u16 val; | 
|  | unsigned long iflags; | 
|  |  | 
|  | switch (rate) { | 
|  | case 13000000: | 
|  | val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER; | 
|  | break; | 
|  | case 52000000: | 
|  | val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE; | 
|  | break; | 
|  | case 104000000: | 
|  | val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH; | 
|  | break; | 
|  | case 208000000: | 
|  | val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST; | 
|  | break; | 
|  | default: | 
|  | return; | 
|  | } | 
|  | spin_lock_irqsave(&syscon_clkreg_lock, iflags); | 
|  | val |= readw(U300_SYSCON_VBASE + U300_SYSCON_CCR) & | 
|  | ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); | 
|  | } | 
|  | EXPORT_SYMBOL(syscon_clk_rate_set_cpuclk); | 
|  |  | 
|  | void clk_disable(struct clk *clk) | 
|  | { | 
|  | unsigned long iflags; | 
|  |  | 
|  | spin_lock_irqsave(&clk->lock, iflags); | 
|  | if (clk->usecount > 0 && !(--clk->usecount)) { | 
|  | /* some blocks lack clocking registers and cannot be disabled */ | 
|  | if (clk->disable) | 
|  | clk->disable(clk); | 
|  | if (likely((u32)clk->parent)) | 
|  | clk_disable(clk->parent); | 
|  | } | 
|  | #ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER | 
|  | if (unlikely(!strcmp(clk->name, "I2S0"))) | 
|  | disable_i2s0_vcxo(); | 
|  | if (unlikely(!strcmp(clk->name, "I2S1"))) | 
|  | disable_i2s1_vcxo(); | 
|  | #endif | 
|  | spin_unlock_irqrestore(&clk->lock, iflags); | 
|  | } | 
|  | EXPORT_SYMBOL(clk_disable); | 
|  |  | 
|  | int clk_enable(struct clk *clk) | 
|  | { | 
|  | int ret = 0; | 
|  | unsigned long iflags; | 
|  |  | 
|  | spin_lock_irqsave(&clk->lock, iflags); | 
|  | if (clk->usecount++ == 0) { | 
|  | if (likely((u32)clk->parent)) | 
|  | ret = clk_enable(clk->parent); | 
|  |  | 
|  | if (unlikely(ret != 0)) | 
|  | clk->usecount--; | 
|  | else { | 
|  | /* remove reset line (we never enable reset again) */ | 
|  | syscon_block_reset_disable(clk); | 
|  | /* clocks without enable function are always on */ | 
|  | if (clk->enable) | 
|  | clk->enable(clk); | 
|  | #ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER | 
|  | if (unlikely(!strcmp(clk->name, "I2S0"))) | 
|  | enable_i2s0_vcxo(); | 
|  | if (unlikely(!strcmp(clk->name, "I2S1"))) | 
|  | enable_i2s1_vcxo(); | 
|  | #endif | 
|  | } | 
|  | } | 
|  | spin_unlock_irqrestore(&clk->lock, iflags); | 
|  | return ret; | 
|  |  | 
|  | } | 
|  | EXPORT_SYMBOL(clk_enable); | 
|  |  | 
|  | /* Returns the clock rate in Hz */ | 
|  | static unsigned long clk_get_rate_cpuclk(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  |  | 
|  | val = syscon_clk_get_rate(); | 
|  |  | 
|  | switch (val) { | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: | 
|  | return 13000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: | 
|  | return 52000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: | 
|  | return 104000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: | 
|  | return 208000000; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | return clk->rate; | 
|  | } | 
|  |  | 
|  | static unsigned long clk_get_rate_ahb_clk(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  |  | 
|  | val = syscon_clk_get_rate(); | 
|  |  | 
|  | switch (val) { | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: | 
|  | return 6500000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: | 
|  | return 26000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: | 
|  | return 52000000; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | return clk->rate; | 
|  |  | 
|  | } | 
|  |  | 
|  | static unsigned long clk_get_rate_emif_clk(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  |  | 
|  | val = syscon_clk_get_rate(); | 
|  |  | 
|  | switch (val) { | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: | 
|  | return 13000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: | 
|  | return 52000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: | 
|  | return 104000000; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | return clk->rate; | 
|  |  | 
|  | } | 
|  |  | 
|  | static unsigned long clk_get_rate_xgamclk(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  |  | 
|  | val = syscon_clk_get_rate(); | 
|  |  | 
|  | switch (val) { | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: | 
|  | return 6500000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: | 
|  | return 26000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: | 
|  | return 52000000; | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | return clk->rate; | 
|  | } | 
|  |  | 
|  | static unsigned long clk_get_rate_mclk(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  |  | 
|  | val = syscon_clk_get_rate(); | 
|  |  | 
|  | switch (val) { | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: | 
|  | /* | 
|  | * Here, the 208 MHz PLL gets shut down and the always | 
|  | * on 13 MHz PLL used for RTC etc kicks into use | 
|  | * instead. | 
|  | */ | 
|  | return 13000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: | 
|  | { | 
|  | /* | 
|  | * This clock is under program control. The register is | 
|  | * divided in two nybbles, bit 7-4 gives cycles-1 to count | 
|  | * high, bit 3-0 gives cycles-1 to count low. Distribute | 
|  | * these with no more than 1 cycle difference between | 
|  | * low and high and add low and high to get the actual | 
|  | * divisor. The base PLL is 208 MHz. Writing 0x00 will | 
|  | * divide by 1 and 1 so the highest frequency possible | 
|  | * is 104 MHz. | 
|  | * | 
|  | * e.g. 0x54 => | 
|  | * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz | 
|  | */ | 
|  | u16 val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) & | 
|  | U300_SYSCON_MMF0R_MASK; | 
|  | switch (val) { | 
|  | case 0x0054: | 
|  | return 18900000; | 
|  | case 0x0044: | 
|  | return 20800000; | 
|  | case 0x0043: | 
|  | return 23100000; | 
|  | case 0x0033: | 
|  | return 26000000; | 
|  | case 0x0032: | 
|  | return 29700000; | 
|  | case 0x0022: | 
|  | return 34700000; | 
|  | case 0x0021: | 
|  | return 41600000; | 
|  | case 0x0011: | 
|  | return 52000000; | 
|  | case 0x0000: | 
|  | return 104000000; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | return clk->rate; | 
|  | } | 
|  |  | 
|  | static unsigned long clk_get_rate_i2s_i2c_spi(struct clk *clk) | 
|  | { | 
|  | u16 val; | 
|  |  | 
|  | val = syscon_clk_get_rate(); | 
|  |  | 
|  | switch (val) { | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: | 
|  | return 13000000; | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: | 
|  | case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: | 
|  | return 26000000; | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | return clk->rate; | 
|  | } | 
|  |  | 
|  | unsigned long clk_get_rate(struct clk *clk) | 
|  | { | 
|  | if (clk->get_rate) | 
|  | return clk->get_rate(clk); | 
|  | else | 
|  | return clk->rate; | 
|  | } | 
|  | EXPORT_SYMBOL(clk_get_rate); | 
|  |  | 
|  | static unsigned long clk_round_rate_mclk(struct clk *clk, unsigned long rate) | 
|  | { | 
|  | if (rate <= 18900000) | 
|  | return 18900000; | 
|  | if (rate <= 20800000) | 
|  | return 20800000; | 
|  | if (rate <= 23100000) | 
|  | return 23100000; | 
|  | if (rate <= 26000000) | 
|  | return 26000000; | 
|  | if (rate <= 29700000) | 
|  | return 29700000; | 
|  | if (rate <= 34700000) | 
|  | return 34700000; | 
|  | if (rate <= 41600000) | 
|  | return 41600000; | 
|  | if (rate <= 52000000) | 
|  | return 52000000; | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate) | 
|  | { | 
|  | if (rate <= 13000000) | 
|  | return 13000000; | 
|  | if (rate <= 52000000) | 
|  | return 52000000; | 
|  | if (rate <= 104000000) | 
|  | return 104000000; | 
|  | if (rate <= 208000000) | 
|  | return 208000000; | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * This adjusts a requested rate to the closest exact rate | 
|  | * a certain clock can provide. For a fixed clock it's | 
|  | * mostly clk->rate. | 
|  | */ | 
|  | long clk_round_rate(struct clk *clk, unsigned long rate) | 
|  | { | 
|  | /* TODO: get appropriate switches for EMIFCLK, AHBCLK and MCLK */ | 
|  | /* Else default to fixed value */ | 
|  |  | 
|  | if (clk->round_rate) { | 
|  | return (long) clk->round_rate(clk, rate); | 
|  | } else { | 
|  | printk(KERN_ERR "clock: Failed to round rate of %s\n", | 
|  | clk->name); | 
|  | } | 
|  | return (long) clk->rate; | 
|  | } | 
|  | EXPORT_SYMBOL(clk_round_rate); | 
|  |  | 
|  | static int clk_set_rate_mclk(struct clk *clk, unsigned long rate) | 
|  | { | 
|  | syscon_clk_rate_set_mclk(clk_round_rate(clk, rate)); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int clk_set_rate_cpuclk(struct clk *clk, unsigned long rate) | 
|  | { | 
|  | syscon_clk_rate_set_cpuclk(clk_round_rate(clk, rate)); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int clk_set_rate(struct clk *clk, unsigned long rate) | 
|  | { | 
|  | /* TODO: set for EMIFCLK and AHBCLK */ | 
|  | /* Else assume the clock is fixed and fail */ | 
|  | if (clk->set_rate) { | 
|  | return clk->set_rate(clk, rate); | 
|  | } else { | 
|  | printk(KERN_ERR "clock: Failed to set %s to %ld hz\n", | 
|  | clk->name, rate); | 
|  | return -EINVAL; | 
|  | } | 
|  | } | 
|  | EXPORT_SYMBOL(clk_set_rate); | 
|  |  | 
|  | /* | 
|  | * Clock definitions. The clock parents are set to respective | 
|  | * bridge and the clock framework makes sure that the clocks have | 
|  | * parents activated and are brought out of reset when in use. | 
|  | * | 
|  | * Clocks that have hw_ctrld = true are hw controlled, and the hw | 
|  | * can by itself turn these clocks on and off. | 
|  | * So in other words, we don't really have to care about them. | 
|  | */ | 
|  |  | 
|  | static struct clk amba_clk = { | 
|  | .name	    = "AMBA", | 
|  | .rate	    = 52000000, /* this varies! */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = false, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(amba_clk.lock), | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * These blocks are connected directly to the AMBA bus | 
|  | * with no bridge. | 
|  | */ | 
|  |  | 
|  | static struct clk cpu_clk = { | 
|  | .name	    = "CPU", | 
|  | .parent	    = &amba_clk, | 
|  | .rate	    = 208000000, /* this varies! */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_CPU_RESET_EN, | 
|  | .set_rate   = clk_set_rate_cpuclk, | 
|  | .get_rate   = clk_get_rate_cpuclk, | 
|  | .round_rate = clk_round_rate_cpuclk, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(cpu_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk nandif_clk = { | 
|  | .name       = "FSMC", | 
|  | .parent	    = &amba_clk, | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_NANDIF_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_NANDIF_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(nandif_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk semi_clk = { | 
|  | .name       = "SEMI", | 
|  | .parent	    = &amba_clk, | 
|  | .rate       = 0, /* FIXME */ | 
|  | /* It is not possible to reset SEMI */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = false, | 
|  | .clk_val    = U300_SYSCON_SBCER_SEMI_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(semi_clk.lock), | 
|  | }; | 
|  |  | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | static struct clk isp_clk = { | 
|  | .name	    = "ISP", | 
|  | .parent	    = &amba_clk, | 
|  | .rate	    = 0, /* FIXME */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_ISP_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_ISP_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(isp_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk cds_clk = { | 
|  | .name	    = "CDS", | 
|  | .parent	    = &amba_clk, | 
|  | .rate	    = 0, /* FIXME */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_CDS_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_CDS_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(cds_clk.lock), | 
|  | }; | 
|  | #endif | 
|  |  | 
|  | static struct clk dma_clk = { | 
|  | .name       = "DMA", | 
|  | .parent	    = &amba_clk, | 
|  | .rate       = 52000000, /* this varies! */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_DMAC_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_DMAC_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(dma_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk aaif_clk = { | 
|  | .name       = "AAIF", | 
|  | .parent	    = &amba_clk, | 
|  | .rate       = 52000000, /* this varies! */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_AAIF_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_AAIF_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(aaif_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk apex_clk = { | 
|  | .name       = "APEX", | 
|  | .parent	    = &amba_clk, | 
|  | .rate       = 0, /* FIXME */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_APEX_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_APEX_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(apex_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk video_enc_clk = { | 
|  | .name       = "VIDEO_ENC", | 
|  | .parent	    = &amba_clk, | 
|  | .rate       = 208000000, /* this varies! */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = false, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | /* This has XGAM in the name but refers to the video encoder */ | 
|  | .res_mask   = U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(video_enc_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk xgam_clk = { | 
|  | .name       = "XGAMCLK", | 
|  | .parent	    = &amba_clk, | 
|  | .rate       = 52000000, /* this varies! */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_XGAM_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_XGAM_CLK_EN, | 
|  | .get_rate   = clk_get_rate_xgamclk, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(xgam_clk.lock), | 
|  | }; | 
|  |  | 
|  | /* This clock is used to activate the video encoder */ | 
|  | static struct clk ahb_clk = { | 
|  | .name	    = "AHB", | 
|  | .parent	    = &amba_clk, | 
|  | .rate	    = 52000000, /* this varies! */ | 
|  | .hw_ctrld   = false, /* This one is set to false due to HW bug */ | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_AHB_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_AHB_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .get_rate   = clk_get_rate_ahb_clk, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(ahb_clk.lock), | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Clocks on the AHB bridge | 
|  | */ | 
|  |  | 
|  | static struct clk ahb_subsys_clk = { | 
|  | .name	    = "AHB_SUBSYS", | 
|  | .parent	    = &amba_clk, | 
|  | .rate	    = 52000000, /* this varies! */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = false, | 
|  | .clk_val    = U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .get_rate   = clk_get_rate_ahb_clk, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(ahb_subsys_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk intcon_clk = { | 
|  | .name	    = "INTCON", | 
|  | .parent	    = &ahb_subsys_clk, | 
|  | .rate	    = 52000000, /* this varies! */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_INTCON_RESET_EN, | 
|  | /* INTCON can be reset but not clock-gated */ | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(intcon_clk.lock), | 
|  |  | 
|  | }; | 
|  |  | 
|  | static struct clk mspro_clk = { | 
|  | .name       = "MSPRO", | 
|  | .parent	    = &ahb_subsys_clk, | 
|  | .rate       = 0, /* FIXME */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_MSPRO_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_MSPRO_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(mspro_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk emif_clk = { | 
|  | .name	    = "EMIF", | 
|  | .parent	    = &ahb_subsys_clk, | 
|  | .rate	    = 104000000, /* this varies! */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR, | 
|  | .res_mask   = U300_SYSCON_RRR_EMIF_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_EMIF_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .get_rate   = clk_get_rate_emif_clk, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(emif_clk.lock), | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Clocks on the FAST bridge | 
|  | */ | 
|  | static struct clk fast_clk = { | 
|  | .name	    = "FAST_BRIDGE", | 
|  | .parent	    = &amba_clk, | 
|  | .rate	    = 13000000, /* this varies! */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR, | 
|  | .res_mask   = U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE, | 
|  | .clk_val    = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(fast_clk.lock), | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * The MMCI apb_pclk is hardwired to the same terminal as the | 
|  | * external MCI clock. Thus this will be referenced twice. | 
|  | */ | 
|  | static struct clk mmcsd_clk = { | 
|  | .name       = "MCLK", | 
|  | .parent	    = &fast_clk, | 
|  | .rate       = 18900000, /* this varies! */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR, | 
|  | .res_mask   = U300_SYSCON_RFR_MMC_RESET_ENABLE, | 
|  | .clk_val    = U300_SYSCON_SBCER_MMC_CLK_EN, | 
|  | .get_rate   = clk_get_rate_mclk, | 
|  | .set_rate   = clk_set_rate_mclk, | 
|  | .round_rate = clk_round_rate_mclk, | 
|  | .disable    = syscon_clk_disable, | 
|  | .enable     = syscon_clk_enable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(mmcsd_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk i2s0_clk = { | 
|  | .name       = "i2s0", | 
|  | .parent	    = &fast_clk, | 
|  | .rate       = 26000000, /* this varies! */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR, | 
|  | .res_mask   = U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE, | 
|  | .clk_val    = U300_SYSCON_SBCER_I2S0_CORE_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .get_rate   = clk_get_rate_i2s_i2c_spi, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(i2s0_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk i2s1_clk = { | 
|  | .name       = "i2s1", | 
|  | .parent	    = &fast_clk, | 
|  | .rate       = 26000000, /* this varies! */ | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR, | 
|  | .res_mask   = U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE, | 
|  | .clk_val    = U300_SYSCON_SBCER_I2S1_CORE_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .get_rate   = clk_get_rate_i2s_i2c_spi, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(i2s1_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk i2c0_clk = { | 
|  | .name       = "I2C0", | 
|  | .parent	    = &fast_clk, | 
|  | .rate       = 26000000, /* this varies! */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR, | 
|  | .res_mask   = U300_SYSCON_RFR_I2C0_RESET_ENABLE, | 
|  | .clk_val    = U300_SYSCON_SBCER_I2C0_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .get_rate   = clk_get_rate_i2s_i2c_spi, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(i2c0_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk i2c1_clk = { | 
|  | .name       = "I2C1", | 
|  | .parent	    = &fast_clk, | 
|  | .rate       = 26000000, /* this varies! */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR, | 
|  | .res_mask   = U300_SYSCON_RFR_I2C1_RESET_ENABLE, | 
|  | .clk_val    = U300_SYSCON_SBCER_I2C1_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .get_rate   = clk_get_rate_i2s_i2c_spi, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(i2c1_clk.lock), | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * The SPI apb_pclk is hardwired to the same terminal as the | 
|  | * external SPI clock. Thus this will be referenced twice. | 
|  | */ | 
|  | static struct clk spi_clk = { | 
|  | .name       = "SPI", | 
|  | .parent	    = &fast_clk, | 
|  | .rate       = 26000000, /* this varies! */ | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR, | 
|  | .res_mask   = U300_SYSCON_RFR_SPI_RESET_ENABLE, | 
|  | .clk_val    = U300_SYSCON_SBCER_SPI_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .get_rate   = clk_get_rate_i2s_i2c_spi, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(spi_clk.lock), | 
|  | }; | 
|  |  | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | static struct clk uart1_pclk = { | 
|  | .name	    = "UART1_PCLK", | 
|  | .parent	    = &fast_clk, | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR, | 
|  | .res_mask   = U300_SYSCON_RFR_UART1_RESET_ENABLE, | 
|  | .clk_val    = U300_SYSCON_SBCER_UART1_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(uart1_pclk.lock), | 
|  | }; | 
|  |  | 
|  | /* This one is hardwired to PLL13 */ | 
|  | static struct clk uart1_clk = { | 
|  | .name	    = "UART1_CLK", | 
|  | .rate	    = 13000000, | 
|  | .hw_ctrld   = true, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(uart1_clk.lock), | 
|  | }; | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Clocks on the SLOW bridge | 
|  | */ | 
|  | static struct clk slow_clk = { | 
|  | .name	    = "SLOW_BRIDGE", | 
|  | .parent	    = &amba_clk, | 
|  | .rate	    = 13000000, | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(slow_clk.lock), | 
|  | }; | 
|  |  | 
|  | /* TODO: implement SYSCON clock? */ | 
|  |  | 
|  | static struct clk wdog_clk = { | 
|  | .name	    = "WDOG", | 
|  | .parent	    = &slow_clk, | 
|  | .hw_ctrld   = false, | 
|  | .rate	    = 32768, | 
|  | .reset	    = false, | 
|  | /* This is always on, cannot be enabled/disabled or reset */ | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(wdog_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk uart0_pclk = { | 
|  | .name	    = "UART0_PCLK", | 
|  | .parent	    = &slow_clk, | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_UART_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_UART_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(uart0_pclk.lock), | 
|  | }; | 
|  |  | 
|  | /* This one is hardwired to PLL13 */ | 
|  | static struct clk uart0_clk = { | 
|  | .name	    = "UART0_CLK", | 
|  | .parent	    = &slow_clk, | 
|  | .rate	    = 13000000, | 
|  | .hw_ctrld   = true, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(uart0_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk keypad_clk = { | 
|  | .name       = "KEYPAD", | 
|  | .parent	    = &slow_clk, | 
|  | .rate       = 32768, | 
|  | .hw_ctrld   = false, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_KEYPAD_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_KEYPAD_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(keypad_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk gpio_clk = { | 
|  | .name       = "GPIO", | 
|  | .parent	    = &slow_clk, | 
|  | .rate       = 13000000, | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_GPIO_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_GPIO_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(gpio_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk rtc_clk = { | 
|  | .name	    = "RTC", | 
|  | .parent	    = &slow_clk, | 
|  | .rate	    = 32768, | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_RTC_RESET_EN, | 
|  | /* This clock is always on, cannot be enabled/disabled */ | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(rtc_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk bustr_clk = { | 
|  | .name       = "BUSTR", | 
|  | .parent	    = &slow_clk, | 
|  | .rate       = 13000000, | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_BTR_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_BTR_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(bustr_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk evhist_clk = { | 
|  | .name       = "EVHIST", | 
|  | .parent	    = &slow_clk, | 
|  | .rate       = 13000000, | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_EH_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_EH_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(evhist_clk.lock), | 
|  | }; | 
|  |  | 
|  | static struct clk timer_clk = { | 
|  | .name       = "TIMER", | 
|  | .parent	    = &slow_clk, | 
|  | .rate       = 13000000, | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_ACC_TMR_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_ACC_TMR_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(timer_clk.lock), | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * There is a binary divider in the hardware that divides | 
|  | * the 13MHz PLL by 13 down to 1 MHz. | 
|  | */ | 
|  | static struct clk app_timer_clk = { | 
|  | .name       = "TIMER_APP", | 
|  | .parent	    = &slow_clk, | 
|  | .rate       = 1000000, | 
|  | .hw_ctrld   = true, | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_APP_TMR_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_APP_TMR_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(app_timer_clk.lock), | 
|  | }; | 
|  |  | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | static struct clk ppm_clk = { | 
|  | .name	    = "PPM", | 
|  | .parent	    = &slow_clk, | 
|  | .rate	    = 0, /* FIXME */ | 
|  | .hw_ctrld   = true, /* TODO: Look up if it is hw ctrld or not */ | 
|  | .reset	    = true, | 
|  | .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR, | 
|  | .res_mask   = U300_SYSCON_RSR_PPM_RESET_EN, | 
|  | .clk_val    = U300_SYSCON_SBCER_PPM_CLK_EN, | 
|  | .enable     = syscon_clk_enable, | 
|  | .disable    = syscon_clk_disable, | 
|  | .lock       = __SPIN_LOCK_UNLOCKED(ppm_clk.lock), | 
|  | }; | 
|  | #endif | 
|  |  | 
|  | #define DEF_LOOKUP(devid, clkref)		\ | 
|  | {					\ | 
|  | .dev_id = devid,			\ | 
|  | .clk = clkref,				\ | 
|  | } | 
|  |  | 
|  | #define DEF_LOOKUP_CON(devid, conid, clkref)	\ | 
|  | {					\ | 
|  | .dev_id = devid,			\ | 
|  | .con_id = conid,			\ | 
|  | .clk = clkref,				\ | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Here we only define clocks that are meaningful to | 
|  | * look up through clockdevice. | 
|  | */ | 
|  | static struct clk_lookup lookups[] = { | 
|  | /* Connected directly to the AMBA bus */ | 
|  | DEF_LOOKUP("amba",      &amba_clk), | 
|  | DEF_LOOKUP("cpu",       &cpu_clk), | 
|  | DEF_LOOKUP("fsmc-nand", &nandif_clk), | 
|  | DEF_LOOKUP("semi",      &semi_clk), | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | DEF_LOOKUP("isp",       &isp_clk), | 
|  | DEF_LOOKUP("cds",       &cds_clk), | 
|  | #endif | 
|  | DEF_LOOKUP("dma",       &dma_clk), | 
|  | DEF_LOOKUP("msl",       &aaif_clk), | 
|  | DEF_LOOKUP("apex",      &apex_clk), | 
|  | DEF_LOOKUP("video_enc", &video_enc_clk), | 
|  | DEF_LOOKUP("xgam",      &xgam_clk), | 
|  | DEF_LOOKUP("ahb",       &ahb_clk), | 
|  | /* AHB bridge clocks */ | 
|  | DEF_LOOKUP("ahb_subsys", &ahb_subsys_clk), | 
|  | DEF_LOOKUP("intcon",    &intcon_clk), | 
|  | DEF_LOOKUP_CON("intcon", "apb_pclk", &intcon_clk), | 
|  | DEF_LOOKUP("mspro",     &mspro_clk), | 
|  | DEF_LOOKUP("pl172",     &emif_clk), | 
|  | DEF_LOOKUP_CON("pl172", "apb_pclk", &emif_clk), | 
|  | /* FAST bridge clocks */ | 
|  | DEF_LOOKUP("fast",      &fast_clk), | 
|  | DEF_LOOKUP("mmci",      &mmcsd_clk), | 
|  | DEF_LOOKUP_CON("mmci", "apb_pclk", &mmcsd_clk), | 
|  | /* | 
|  | * The .0 and .1 identifiers on these comes from the platform device | 
|  | * .id field and are assigned when the platform devices are registered. | 
|  | */ | 
|  | DEF_LOOKUP("i2s.0",     &i2s0_clk), | 
|  | DEF_LOOKUP("i2s.1",     &i2s1_clk), | 
|  | DEF_LOOKUP("stu300.0",  &i2c0_clk), | 
|  | DEF_LOOKUP("stu300.1",  &i2c1_clk), | 
|  | DEF_LOOKUP("pl022",     &spi_clk), | 
|  | DEF_LOOKUP_CON("pl022", "apb_pclk", &spi_clk), | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | DEF_LOOKUP("uart1",     &uart1_clk), | 
|  | DEF_LOOKUP_CON("uart1", "apb_pclk", &uart1_pclk), | 
|  | #endif | 
|  | /* SLOW bridge clocks */ | 
|  | DEF_LOOKUP("slow",      &slow_clk), | 
|  | DEF_LOOKUP("coh901327_wdog",      &wdog_clk), | 
|  | DEF_LOOKUP("uart0",     &uart0_clk), | 
|  | DEF_LOOKUP_CON("uart0", "apb_pclk", &uart0_pclk), | 
|  | DEF_LOOKUP("apptimer",  &app_timer_clk), | 
|  | DEF_LOOKUP("coh901461-keypad",    &keypad_clk), | 
|  | DEF_LOOKUP("u300-gpio", &gpio_clk), | 
|  | DEF_LOOKUP("rtc-coh901331",      &rtc_clk), | 
|  | DEF_LOOKUP("bustr",     &bustr_clk), | 
|  | DEF_LOOKUP("evhist",    &evhist_clk), | 
|  | DEF_LOOKUP("timer",     &timer_clk), | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | DEF_LOOKUP("ppm",       &ppm_clk), | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | static void __init clk_register(void) | 
|  | { | 
|  | /* Register the lookups */ | 
|  | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | 
|  | } | 
|  |  | 
|  | #if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG)) | 
|  | /* | 
|  | * The following makes it possible to view the status (especially | 
|  | * reference count and reset status) for the clocks in the platform | 
|  | * by looking into the special file <debugfs>/u300_clocks | 
|  | */ | 
|  |  | 
|  | /* A list of all clocks in the platform */ | 
|  | static struct clk *clks[] = { | 
|  | /* Top node clock for the AMBA bus */ | 
|  | &amba_clk, | 
|  | /* Connected directly to the AMBA bus */ | 
|  | &cpu_clk, | 
|  | &nandif_clk, | 
|  | &semi_clk, | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | &isp_clk, | 
|  | &cds_clk, | 
|  | #endif | 
|  | &dma_clk, | 
|  | &aaif_clk, | 
|  | &apex_clk, | 
|  | &video_enc_clk, | 
|  | &xgam_clk, | 
|  | &ahb_clk, | 
|  |  | 
|  | /* AHB bridge clocks */ | 
|  | &ahb_subsys_clk, | 
|  | &intcon_clk, | 
|  | &mspro_clk, | 
|  | &emif_clk, | 
|  | /* FAST bridge clocks */ | 
|  | &fast_clk, | 
|  | &mmcsd_clk, | 
|  | &i2s0_clk, | 
|  | &i2s1_clk, | 
|  | &i2c0_clk, | 
|  | &i2c1_clk, | 
|  | &spi_clk, | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | &uart1_clk, | 
|  | &uart1_pclk, | 
|  | #endif | 
|  | /* SLOW bridge clocks */ | 
|  | &slow_clk, | 
|  | &wdog_clk, | 
|  | &uart0_clk, | 
|  | &uart0_pclk, | 
|  | &app_timer_clk, | 
|  | &keypad_clk, | 
|  | &gpio_clk, | 
|  | &rtc_clk, | 
|  | &bustr_clk, | 
|  | &evhist_clk, | 
|  | &timer_clk, | 
|  | #ifdef CONFIG_MACH_U300_BS335 | 
|  | &ppm_clk, | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | static int u300_clocks_show(struct seq_file *s, void *data) | 
|  | { | 
|  | struct clk *clk; | 
|  | int i; | 
|  |  | 
|  | seq_printf(s, "CLOCK           DEVICE          RESET STATE\t" \ | 
|  | "ACTIVE\tUSERS\tHW CTRL FREQ\n"); | 
|  | seq_printf(s, "---------------------------------------------" \ | 
|  | "-----------------------------------------\n"); | 
|  | for (i = 0; i < ARRAY_SIZE(clks); i++) { | 
|  | clk = clks[i]; | 
|  | if (clk != ERR_PTR(-ENOENT)) { | 
|  | /* Format clock and device name nicely */ | 
|  | char cdp[33]; | 
|  | int chars; | 
|  |  | 
|  | chars = snprintf(&cdp[0], 17, "%s", clk->name); | 
|  | while (chars < 16) { | 
|  | cdp[chars] = ' '; | 
|  | chars++; | 
|  | } | 
|  | chars = snprintf(&cdp[16], 17, "%s", clk->dev ? | 
|  | dev_name(clk->dev) : "N/A"); | 
|  | while (chars < 16) { | 
|  | cdp[chars+16] = ' '; | 
|  | chars++; | 
|  | } | 
|  | cdp[32] = '\0'; | 
|  | if (clk->get_rate || clk->rate != 0) | 
|  | seq_printf(s, | 
|  | "%s%s\t%s\t%d\t%s\t%lu Hz\n", | 
|  | &cdp[0], | 
|  | clk->reset ? | 
|  | "ASSERTED" : "RELEASED", | 
|  | clk->usecount ? "ON" : "OFF", | 
|  | clk->usecount, | 
|  | clk->hw_ctrld  ? "YES" : "NO ", | 
|  | clk_get_rate(clk)); | 
|  | else | 
|  | seq_printf(s, | 
|  | "%s%s\t%s\t%d\t%s\t" \ | 
|  | "(unknown rate)\n", | 
|  | &cdp[0], | 
|  | clk->reset ? | 
|  | "ASSERTED" : "RELEASED", | 
|  | clk->usecount ? "ON" : "OFF", | 
|  | clk->usecount, | 
|  | clk->hw_ctrld  ? "YES" : "NO "); | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int u300_clocks_open(struct inode *inode, struct file *file) | 
|  | { | 
|  | return single_open(file, u300_clocks_show, NULL); | 
|  | } | 
|  |  | 
|  | static const struct file_operations u300_clocks_operations = { | 
|  | .open		= u300_clocks_open, | 
|  | .read		= seq_read, | 
|  | .llseek		= seq_lseek, | 
|  | .release	= single_release, | 
|  | }; | 
|  |  | 
|  | static int __init init_clk_read_debugfs(void) | 
|  | { | 
|  | /* Expose a simple debugfs interface to view all clocks */ | 
|  | (void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO, | 
|  | NULL, NULL, | 
|  | &u300_clocks_operations); | 
|  | return 0; | 
|  | } | 
|  | /* | 
|  | * This needs to come in after the core_initcall() for the | 
|  | * overall clocks, because debugfs is not available until | 
|  | * the subsystems come up. | 
|  | */ | 
|  | module_init(init_clk_read_debugfs); | 
|  | #endif | 
|  |  | 
|  | int __init u300_clock_init(void) | 
|  | { | 
|  | u16 val; | 
|  |  | 
|  | /* | 
|  | * FIXME: shall all this powermanagement stuff really live here??? | 
|  | */ | 
|  |  | 
|  | /* Set system to run at PLL208, max performance, a known state. */ | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); | 
|  | /* Wait for the PLL208 to lock if not locked in yet */ | 
|  | while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) & | 
|  | U300_SYSCON_CSR_PLL208_LOCK_IND)); | 
|  |  | 
|  | /* Power management enable */ | 
|  | val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMCR); | 
|  | val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE; | 
|  | writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMCR); | 
|  |  | 
|  | clk_register(); | 
|  |  | 
|  | /* | 
|  | * Some of these may be on when we boot the system so make sure they | 
|  | * are turned OFF. | 
|  | */ | 
|  | syscon_block_reset_enable(&timer_clk); | 
|  | timer_clk.disable(&timer_clk); | 
|  |  | 
|  | /* | 
|  | * These shall be turned on by default when we boot the system | 
|  | * so make sure they are ON. (Adding CPU here is a bit too much.) | 
|  | * These clocks will be claimed by drivers later. | 
|  | */ | 
|  | syscon_block_reset_disable(&semi_clk); | 
|  | syscon_block_reset_disable(&emif_clk); | 
|  | clk_enable(&semi_clk); | 
|  | clk_enable(&emif_clk); | 
|  |  | 
|  | return 0; | 
|  | } |