|
@@ -1,1504 +0,0 @@
|
|
|
-/*
|
|
|
- *
|
|
|
- * 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;
|
|
|
-}
|