[PATCH 2/6] U6715 clocks gating management U6 clock generic driver & U6715 cgu clock specific (V2)
Philippe Langlais
philippe.langlais at stericsson.com
Thu May 27 04:27:28 EDT 2010
Signed-off-by: Philippe Langlais <philippe.langlais at stericsson.com>
---
arch/arm/mach-u67xx/Makefile | 2 +-
arch/arm/mach-u67xx/cgu.c | 760 ++++++++++++++++++++++++++
arch/arm/mach-u67xx/clock_u67xx.h | 876 ++++++++++++++++++++++++++++++
arch/arm/plat-u6xxx/Makefile | 2 +-
arch/arm/plat-u6xxx/clock.c | 650 ++++++++++++++++++++++
arch/arm/plat-u6xxx/include/mach/clock.h | 376 +++++++++++++
arch/arm/plat-u6xxx/timer.c | 1 +
7 files changed, 2665 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/mach-u67xx/cgu.c
create mode 100644 arch/arm/mach-u67xx/clock_u67xx.h
create mode 100644 arch/arm/plat-u6xxx/clock.c
create mode 100644 arch/arm/plat-u6xxx/include/mach/clock.h
diff --git a/arch/arm/mach-u67xx/Makefile b/arch/arm/mach-u67xx/Makefile
index 38cf624..0572db8 100644
--- a/arch/arm/mach-u67xx/Makefile
+++ b/arch/arm/mach-u67xx/Makefile
@@ -5,7 +5,7 @@
## Object file lists.
# Common support
-obj-y := devices.o
+obj-y := devices.o cgu.o
# Specific board support
obj-$(CONFIG_MACH_U67XX_WAVEC_2GB) += board_u67xx_wavex.o
diff --git a/arch/arm/mach-u67xx/cgu.c b/arch/arm/mach-u67xx/cgu.c
new file mode 100644
index 0000000..58a6a7a
--- /dev/null
+++ b/arch/arm/mach-u67xx/cgu.c
@@ -0,0 +1,760 @@
+/*
+ * arch/arm/mach-u67xx/cgu.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Arnaud Troel <arnaud.troel at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * U67XX Clock Gating Unit basic driver/wrapper
+ * Based on the code from Michel Jaouen
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+
+#include "clock_u67xx.h"
+
+#define MODULE_NAME "U6_CGU"
+#define PKMOD MODULE_NAME ": "
+
+#if defined(DEBUG_CGU)
+#define debug(fmt, args...) \
+ printk(PKMOD fmt, ## args)
+#else
+#define debug(fmt, args...)
+#endif
+
+/**
+ * U6 hw low level access clock functions
+ **/
+static void u6_clk_disable(struct clk *clk);
+static int u6_clk_enable(struct clk *clk);
+
+/**
+ * HW enable clock function.
+ **/
+
+static int u67xx_cgu_enable_fake_clock(struct clk *clk)
+{
+ debug("u67xx_cgu_enable_fake_clock for %s\n", clk->name);
+ return 0;
+}
+
+static int u67xx_cgu_enable_hw_clock(struct clk *clk)
+{
+ unsigned long value;
+ debug("u67xx_cgu_enable_hw_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Enable for %s without enable register\n",
+ clk->name);
+ return 0;
+ }
+
+ value = readl(clk->enable_reg);
+ value |= 1 << clk->enable_bit;
+ writel(value, clk->enable_reg);
+
+ return 0;
+}
+
+static int u67xx_cgu_enable_tvo_pll_clock(struct clk *clk)
+{
+ unsigned long value;
+
+ debug("u67xx_cgu_enable_tvo_pll_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Enable for %s without enable register\n",
+ clk->name);
+ return 0;
+ }
+
+ value = readl(clk->enable_reg);
+ value |= 1 << clk->enable_bit;
+ writel(value, clk->enable_reg);
+
+ /* wait pll lock */
+ do {
+ value = readl(clk->enable_reg);
+ } while (!(value & (0x1 << 16)));
+
+ return 0;
+}
+
+static int u67xx_cgu_enable_shared_clock(struct clk *clk)
+{
+ unsigned long value;
+
+ debug("u67xx_cgu_enable_shared_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Enable for %s without enable register\n",
+ clk->name);
+ return 0;
+ }
+
+ value = readl(clk->enable_reg);
+ value |= 1 << clk->enable_bit;
+ writel(value, clk->enable_reg);
+
+ return 0;
+}
+
+static int u67xx_cgu_enable_clock(struct clk *clk)
+{
+ printk(PKMOD "No enable clock method for %s."
+ " You should use new one !!!\n", clk->name);
+ return 0;
+}
+
+static int u67xx_cgu_enable_camout(struct clk *clk)
+{
+ unsigned long value;
+ debug("u67xx_cgu_enable_hw_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Enable for %s without enable register\n",
+ clk->name);
+ return 0;
+ }
+
+ u6_clk_enable(&fix_ck);
+ u6_clk_enable(&plltv_ck);
+
+ value = readl(clk->enable_reg);
+ value |= 1 << clk->enable_bit;
+ writel(value, clk->enable_reg);
+
+ udelay(1);
+
+ u6_clk_disable(&fix_ck);
+ u6_clk_disable(&plltv_ck);
+
+ return 0;
+}
+
+/**
+ * HW disable clock function.
+ **/
+
+static void u67xx_cgu_disable_fake_clock(struct clk *clk)
+{
+ debug("u67xx_cgu_disable_fake_clock for %s\n", clk->name);
+}
+
+static void u67xx_cgu_disable_hw_clock(struct clk *clk)
+{
+ unsigned long value;
+
+ debug("u67xx_cgu_disable_hw_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Disable for %s without enable register\n",
+ clk->name);
+ return;
+ }
+
+ value = readl(clk->enable_reg);
+ value &= ~(1 << clk->enable_bit);
+ writel(value, clk->enable_reg);
+
+ return;
+}
+
+static void u67xx_cgu_disable_shared_clock(struct clk *clk)
+{
+ unsigned long value;
+
+ debug("u67xx_cgu_disable_shared_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Disable for %s without enable register\n",
+ clk->name);
+ return;
+ }
+
+ value = readl(clk->enable_reg);
+ value &= ~(1 << clk->enable_bit);
+ writel(value, clk->enable_reg);
+}
+
+static void u67xx_cgu_disable_clock(struct clk *clk)
+{
+ printk(PKMOD
+ " No disable clock method for %s. You should use one !!!\n",
+ clk->name);
+}
+
+/**
+ * set rate clock function.
+ **/
+
+static int u6_clk_set_rate_fci(struct clk *clk, unsigned long rate)
+{
+ int ret = 0;
+ unsigned long ratio = 0;
+ unsigned long reg;
+
+ if (!rate)
+ ratio = 31;
+ else {
+ if (rate > CLK_FC_CLK_MAX_FREQ)
+ rate = CLK_FC_CLK_MAX_FREQ;
+
+ /* compute diviser ratio */
+ ratio = (clk->parent->rate / rate) - 1;
+ if (ratio < 2)
+ ratio = 2;
+ if (ratio > 31)
+ ratio = 31;
+ }
+ clk->rate = clk->parent->rate / (ratio + 1);
+
+ /* for voltage working point only */
+ /* u67xx_set_freq(FC_CLK, clk->rate/1000 , clk->rate/1000); */
+
+ reg = readl(CGU_FIXCON_REG);
+ reg &= ~(0x1F << 22);
+ reg |= (ratio << 22);
+ writel(reg, CGU_FIXCON_REG);
+
+ reg = readl(CGU_SCCON_REG);
+ writel(reg, CGU_SCCON_REG);
+
+ return ret;
+}
+
+static int u6_clk_set_rate_camout(struct clk *clk, unsigned long rate)
+{
+ int ret = 0;
+ unsigned long ratio = 0;
+ unsigned long reg;
+
+ if (!rate)
+ return -EINVAL;
+
+ if (rate > CLK_CAM_CLK_MAX_FREQ)
+ rate = CLK_CAM_CLK_MAX_FREQ;
+
+ /* compute diviser ratio */
+ ratio = (clk->parent->rate / rate) - 1;
+ if (ratio < 1)
+ ratio = 1;
+ if (ratio > 63)
+ ratio = 63;
+
+ clk->rate = clk->parent->rate / (ratio + 1);
+
+ /* for voltage working point only */
+ /* u67xx_set_freq(CAM_CLK, clk->rate/1000 , clk->rate/1000); */
+
+ reg = readl(CGU_CAMCON_REG);
+
+ reg &= ~(0x3F << 0);
+ reg |= (ratio << 0);
+
+ writel(reg, CGU_CAMCON_REG);
+
+ return ret;
+}
+
+/**
+ * set parent clock function.
+ **/
+static int u6_clk_set_parent_camout(struct clk *clk, struct clk *parent)
+{
+ int ret = 0;
+ unsigned long srce = 0;
+ unsigned long reg;
+
+ if (!strcmp(parent->name, "TVOPLL"))
+ srce = 0;
+ else if (!strcmp(parent->name, "fix_ck"))
+ srce = 1;
+ else
+ return -EINVAL;
+
+ u6_clk_enable(&fix_ck);
+ u6_clk_enable(&plltv_ck);
+
+ reg = readl(CGU_CAMCON_REG);
+
+ reg &= ~(0x1 << 6);
+ reg |= (srce << 6);
+
+ writel(reg, CGU_CAMCON_REG);
+
+ udelay(1);
+
+ u6_clk_disable(&fix_ck);
+ u6_clk_disable(&plltv_ck);
+
+ clk->parent = parent;
+
+ return ret;
+}
+
+static int u6_clk_set_parent_uart(struct clk *clk, struct clk *parent)
+{
+
+ if (!strcmp(parent->name, "pclk2_ck")) {
+ clk->parent = parent;
+ return 0;
+ } else if (!strcmp(parent->name, "clk26m_ck")) {
+ clk->parent = parent;
+ return 0;
+ } else if (!strcmp(parent->name, "clk13m_ck")) {
+ clk->parent = parent;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+/**
+ * HW init clock function.
+ **/
+
+static void u6_clk_dflt_init(struct clk *clk)
+{
+ if (clk->usecount == 0)
+ u67xx_cgu_disable_hw_clock(clk);
+ else
+ u67xx_cgu_enable_hw_clock(clk);
+ /* default rate to parent one */
+ clk->rate = clk->parent->rate;
+}
+
+static void u6_clk_init_hclk2(struct clk *clk)
+{
+ /* nothing to do */
+}
+
+static void u6_clk_init_fci(struct clk *clk)
+{
+ u6_clk_set_rate_fci(clk, clk->rate);
+}
+
+static void u6_clk_init_camout(struct clk *clk)
+{
+ u6_clk_set_parent_camout(clk, &fix_ck);
+ u6_clk_set_rate_camout(clk, clk->rate);
+}
+
+/*
+ * Update clock rate
+ */
+static void followparent_ivs_recalc(struct clk *clk)
+{
+ clk->rate = clk->parent->rate;
+ propagate_rate(clk);
+}
+
+/*
+ * U6 platform access clock functions
+ */
+
+/**
+ * @brief Disable a device clock.
+ * @param clk clock description structure
+ */
+static void u6_clk_disable(struct clk *clk)
+{
+ /* BUG_ON(!clk->ref_count); */
+ if ((clk->flags & ALWAYS_ENABLED) == ALWAYS_ENABLED)
+ return;
+
+ if (clk->usecount > 0 && !(--clk->usecount)) {
+ if (clk->disable)
+ clk->disable(clk);
+ else
+ u67xx_cgu_disable_clock(clk);
+
+ if (likely((u32) clk->parent))
+ u6_clk_disable(clk->parent);
+ }
+}
+
+/**
+ * @brief Enable a device clock.
+ * @param clk clock description structure
+ */
+static int u6_clk_enable(struct clk *clk)
+{
+ int ret = 0;
+
+ /* BUG_ON(!clk->ref_count); */
+ if ((clk->flags & ALWAYS_ENABLED) == ALWAYS_ENABLED)
+ return 0;
+
+ if (clk->usecount++ == 0) {
+ if (likely((u32) clk->parent))
+ ret = u6_clk_enable(clk->parent);
+
+ if (unlikely(ret != 0)) {
+ clk->usecount--;
+ return ret;
+ }
+
+ if (clk->enable)
+ ret = clk->enable(clk);
+ else
+ ret = u67xx_cgu_enable_clock(clk);
+
+ if (unlikely(ret != 0) && clk->parent) {
+ u6_clk_disable(clk->parent);
+ clk->usecount--;
+ }
+ }
+ return 0;
+}
+
+static long u6_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk->round_rate)
+ return clk->round_rate(clk, rate);
+ else
+ return rate;
+}
+
+static int u6_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = 0;
+
+ /* BUG_ON(!clk->ref_count); */
+ if (clk->usecount > 0) {
+ if (clk->disable)
+ clk->disable(clk);
+ else
+ u67xx_cgu_disable_clock(clk);
+ }
+
+ if (clk->set_rate)
+ ret = clk->set_rate(clk, rate);
+ else
+ ret = -EINVAL;
+
+ if (clk->usecount > 0) {
+ if (clk->enable)
+ clk->enable(clk);
+ else
+ u67xx_cgu_enable_clock(clk);
+ }
+
+ /* propagate rate */
+ propagate_rate(clk);
+
+ return ret;
+}
+
+static int u6_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret = 0;
+ int old_rate;
+
+ if (clk->usecount > 0) {
+ if (clk->disable)
+ clk->disable(clk);
+ else
+ u67xx_cgu_disable_clock(clk);
+
+ if (likely((u32) clk->parent))
+ u6_clk_disable(clk->parent);
+ }
+
+ old_rate = clk->rate;
+
+ if (clk->set_parent)
+ ret = clk->set_parent(clk, parent);
+ else
+ ret = -EINVAL;
+
+ if (clk->round_rate)
+ old_rate = clk->round_rate(clk, old_rate);
+
+ u6_clk_set_rate(clk, old_rate);
+
+ if (clk->usecount > 0) {
+ if (likely((u32) clk->parent))
+ u6_clk_enable(clk->parent);
+
+ if (clk->enable)
+ ret = clk->enable(clk);
+ else
+ ret = u67xx_cgu_enable_clock(clk);
+ }
+
+ /* propagate rate */
+ if (clk->flags & RATE_PROPAGATES)
+ propagate_rate(clk);
+
+ return ret;
+}
+
+static struct clk *u6_clk_get_parent(struct clk *clk)
+{
+ return clk->parent;
+}
+
+/*
+ * U6 platform clock constraint functions
+ */
+
+unsigned long clk_get_hw_constraint(unsigned long reg_addr)
+{
+ unsigned long reg;
+
+ reg = readl(reg_addr);
+
+ return reg;
+}
+
+ssize_t u6_clk_show_hw_rates(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+ unsigned long reg, rate, msc, psc, mclk;
+
+ size += sprintf(&buf[size], "--HW-- : \n");
+
+ mclk = clk_get_hw_constraint(CGU_FIXCON_REG);
+ mclk = osc_ck.rate / 1000000 / (((mclk & (0x3 << 17)) >> 17) + 1);
+
+ reg = clk_get_hw_constraint(CGU_SCCON_REG);
+
+ msc = (((reg & (0xF << 25)) >> 25) + 1);
+ psc = (((reg & (0x3 << 15)) >> 15) + 1);
+ size += sprintf(&buf[size], "arm_ck is ");
+ if (reg & (1 << 17)) {
+ if (reg & (1 << 18))
+ rate = 312;
+ else
+ rate = 156;
+ rate = rate / msc / psc;
+ size += sprintf(&buf[size], "%lu", rate);
+ size += sprintf(&buf[size], "Mhz fix_ck pll\n");
+ } else {
+ rate = mclk * (((reg & (0xFF << 3)) >> 3) + 1)
+ / (((reg & (0xF << 11)) >> 11) + 1);
+ rate = rate / msc / psc;
+ size += sprintf(&buf[size], "%lu", rate);
+ size += sprintf(&buf[size], "Mhz sc_ck pll\n");
+ }
+
+ rate = rate / (((reg & (0xF << 21)) >> 21) + 1);
+
+ size += sprintf(&buf[size], "hclk_ck is %luMhz\n", rate);
+
+ reg = clk_get_hw_constraint(CGU_FIXCON_REG);
+
+ rate = 13 * (((reg & (0x3 << 20)) >> 20) + 1);
+
+ size += sprintf(&buf[size], "pclk2_ck is %luMhz\n", rate);
+
+ if (reg & (1 << 31)) {
+ if (reg & (1 << 29))
+ rate = 104;
+ else
+ rate = 78;
+ } else
+ rate = 13 + (13 * ((reg & (0x7 << 29)) >> 29));
+
+ size += sprintf(&buf[size], "hclk2_ck is %luMhz\n", rate);
+
+ reg = clk_get_hw_constraint(CGU_SDMCON_REG);
+
+ msc = (((reg & (0x7 << 0)) >> 0) + 1);
+
+ size += sprintf(&buf[size], "sdm_ck is ");
+ if (reg & (1 << 17)) {
+ if (reg & (1 << 18))
+ rate = 312;
+ else
+ rate = 156;
+ size += sprintf(&buf[size], "%lu", rate / msc);
+ size += sprintf(&buf[size], "Mhz fix_ck pll\n");
+ } else {
+ rate = mclk * 2 * (((reg & (0xFF << 3)) >> 3) + 1)
+ / (((reg & (0x3F << 11)) >> 11) + 1);
+ size += sprintf(&buf[size], "%lu", rate / msc);
+ size += sprintf(&buf[size], "Mhz sdm pll\n");
+ }
+
+ if (reg & (1 << 23))
+ size += sprintf(&buf[size], "ivs-sdm concentrator is enable\n");
+ else
+ size += sprintf(&buf[size],
+ "ivs-sdm concentrator is disable\n");
+
+ return size;
+}
+
+unsigned char *cgu_name_sc1[32] = {
+ "EBI", "01", "NFI", "SDI", "04", "MSI", "UCC", "JDI",
+ "08", "09", "10", "DMAU", "RFSM1", "IIS", "USBD", "FCI",
+ "USIM", "GEAC", "PWM3", "PWM2", "PWM1", "KBS", "GPIO", "UART2",
+ "UART1", "IIC2", "IIC1", "SPI2", "SPI1", "SCTU", "EXTINT", "INTC"
+};
+
+unsigned char *cgu_name_sc2[32] = {
+ "32", "33", "34", "35", "36", "37", "38", "39",
+ "40", "41", "42", "43", "44", "45", "46", "47",
+ "48", "49", "50", "51", "52", "53", "BBIP", "55",
+ "56", "57", "58", "ETB", "60", "MMTU", "62", "CAE"
+};
+
+ssize_t u6_clk_show_sc_constraints(struct kobject *kobj, char *buf)
+{
+ int i, size = 0;
+ unsigned long reg;
+
+ size += sprintf(&buf[size], "--SC-- : \n");
+
+ reg = clk_get_hw_constraint(CGU_GATESC1_REG);
+
+ for (i = 0; i < 32; i++) {
+ if ((reg >> i) & 0x1)
+ size +=
+ sprintf(&buf[size], "%s ,", cgu_name_sc1[31 - i]);
+ }
+
+ size += sprintf(&buf[size], "\n");
+
+ reg = clk_get_hw_constraint(CGU_GATESC2_REG);
+
+ for (i = 0; i < 32; i++) {
+ if ((reg >> i) & 0x1)
+ size +=
+ sprintf(&buf[size], "%s ,", cgu_name_sc2[31 - i]);
+ }
+
+ size += sprintf(&buf[size], "\n");
+
+ return size;
+}
+
+unsigned char *cgu_name_ivs[32] = {
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "CAMJPE", "TVO", "JDU", "VDC", "VEC", "IPP", "VDE", "CAM"
+};
+
+ssize_t u6_clk_show_ivs_constraints(struct kobject *kobj, char *buf)
+{
+ int i, size = 0;
+ unsigned long reg;
+
+ size += sprintf(&buf[size], "--IVS-- : \n");
+
+ reg = clk_get_hw_constraint(CGU_GATEIVS_REG);
+
+ for (i = 0; i < 32; i++) {
+ if ((reg >> i) & 0x1)
+ size +=
+ sprintf(&buf[size], "%s ,", cgu_name_ivs[31 - i]);
+ }
+
+ size += sprintf(&buf[size], "\n");
+
+ return size;
+}
+
+ssize_t u6_clk_show_tvo_constraints(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+ unsigned long reg;
+
+ size += sprintf(&buf[size], "--TVO-- : \n");
+
+ reg = clk_get_hw_constraint(CGU_TVCON_REG);
+
+ if ((reg >> 15) & 0x1)
+ size += sprintf(&buf[size], "tvclk_ck pll enable\n");
+ else
+ size += sprintf(&buf[size], "tvclk_ck pll disable\n");
+
+ if ((reg >> 12) & 0x1)
+ size += sprintf(&buf[size], "TVOPLL enable\n");
+ else
+ size += sprintf(&buf[size], "TVOPLL disable\n");
+
+ return size;
+}
+
+ssize_t u6_clk_show_cam_constraints(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+ unsigned long reg, rate, div;
+
+ size += sprintf(&buf[size], "--CAM-- : \n");
+
+ reg = clk_get_hw_constraint(CGU_CAMCON_REG);
+
+ if ((reg >> 6) & 0x1) {
+ size += sprintf(&buf[size], "fix_clock is source\n");
+ rate = 312;
+ } else {
+ size += sprintf(&buf[size], "TVOPLL is source\n");
+ rate = 216;
+ }
+
+ div = ((reg & (0x3F << 0)) >> 0);
+
+ size += sprintf(&buf[size], "camo_ck is %luMhz\n", rate / (div + 1));
+
+ if ((reg >> 7) & 0x1)
+ size += sprintf(&buf[size], "camo_ck enable\n");
+ else
+ size += sprintf(&buf[size], "camo_ck disable\n");
+
+ return size;
+}
+
+/*
+ * U6 clock reset and init functions
+ */
+
+static struct clk_functions u6_clk_functions = {
+ .clk_enable = u6_clk_enable,
+ .clk_disable = u6_clk_disable,
+ .clk_round_rate = u6_clk_round_rate,
+ .clk_set_rate = u6_clk_set_rate,
+ .clk_set_parent = u6_clk_set_parent,
+ .clk_get_parent = u6_clk_get_parent,
+};
+
+/**
+ * @brief Attempts to connect the primary description structure for DMA case.
+ *
+ * We don't do any initialization since we expect the primary OS to have done
+ * it for us.
+ */
+static int __init u67xx_cgu_init(void)
+{
+ struct clk **clkp;
+ printk(PKMOD "clk management init\n");
+
+ if (mpurate)
+ sc_ck.rate = mpurate;
+
+ /* init clock function pointer table */
+ clk_init(&u6_clk_functions);
+
+ /* register and init clock elements */
+ for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+ clkp++) {
+ clk_register(*clkp);
+ }
+
+ return 0;
+}
+
+arch_initcall(u67xx_cgu_init);
diff --git a/arch/arm/mach-u67xx/clock_u67xx.h b/arch/arm/mach-u67xx/clock_u67xx.h
new file mode 100644
index 0000000..d92e454
--- /dev/null
+++ b/arch/arm/mach-u67xx/clock_u67xx.h
@@ -0,0 +1,876 @@
+/*
+ * linux/arch/arm/mach-u67xx/clock_u67xx.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy at stericsson.com for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ */
+
+#ifndef __ARCH_ARM_MACH_U67XX_CLOCK_H
+#define __ARCH_ARM_MACH_U67XX_CLOCK_H
+
+static int u67xx_cgu_enable_fake_clock(struct clk *clk);
+static int u67xx_cgu_enable_hw_clock(struct clk *clk);
+static int u67xx_cgu_enable_shared_clock(struct clk *clk);
+static int u67xx_cgu_enable_tvo_pll_clock(struct clk *clk);
+static int u67xx_cgu_enable_camout(struct clk *clk);
+
+static void u67xx_cgu_disable_fake_clock(struct clk *clk);
+static void u67xx_cgu_disable_hw_clock(struct clk *clk);
+static void u67xx_cgu_disable_shared_clock(struct clk *clk);
+
+static void u6_clk_dflt_init(struct clk *clk);
+static void u6_clk_init_hclk2(struct clk *clk);
+static void u6_clk_init_fci(struct clk *clk);
+static void u6_clk_init_camout(struct clk *clk);
+
+static int u6_clk_set_rate_fci(struct clk *clk, unsigned long rate);
+static int u6_clk_set_rate_camout(struct clk *clk, unsigned long rate);
+
+static int u6_clk_set_parent_camout(struct clk *clk, struct clk *parent);
+static int u6_clk_set_parent_uart(struct clk *clk, struct clk *parent);
+
+static void followparent_ivs_recalc(struct clk *clk);
+
+/* used to remove useless clock cells */
+#undef U6_OPTIMIZED_TREE
+
+/*
+ * U6 clock tree.
+ *
+ * NOTE:In many cases here we are assigning a 'default' parent. In many
+ * cases the parent is selectable. The get/set parent calls will also
+ * switch sources.
+ *
+ * Many some clocks say always_enabled, but they can be auto idled for
+ * power savings. They will always be available upon clock request.
+ *
+ * Several sources are given initial rates which may be wrong, this will
+ * be fixed up in the init func.
+ *
+ * Things are broadly separated below by clock domains. It is
+ * noteworthy that most periferals have dependencies on multiple clock
+ * domains. Many get their interface clocks from the L4 domain, but get
+ * functional clocks from fixed sources or other core domain derived
+ * clock.
+ */
+
+/*** Basic clocks ***/
+
+/* Base external input clocks */
+static struct clk func_32k_ck = {
+ .name = "func_32k_ck",
+ .rate = 32000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED,
+ .usecount = 1,
+};
+
+/* Typical 26MHz in standalone mode */
+static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */
+ .name = "osc_ck",
+ .rate = 26000000, /* fixed up in clock init */
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+ .usecount = 1,
+};
+
+/* System clock MCLK */
+/* With out modem likely 12MHz, with modem likely 13MHz */
+static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */
+ .name = "sys_ck", /* ~ ref_clk also */
+ .parent = &osc_ck,
+ .rate = 13000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+ .usecount = 1,
+};
+
+/*** System PLLs ***/
+
+static struct clk sc_ck = { /* 275-550MHz */
+ .name = "sc_ck",
+ .parent = &sys_ck,
+ .rate = 416000000,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+static struct clk fix_ck = { /* 312MHz */
+ .name = "fix_ck",
+ .parent = &sys_ck,
+ .rate = 312000000,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 0,
+};
+
+static struct clk tv_ck = { /* 216MHz */
+ .name = "tv_ck",
+ .parent = &fix_ck,
+ .rate = 216000000,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk dsp2_ck = { /* 156-320MHz */
+ .name = "dsp2_ck",
+ .parent = &sys_ck,
+ .rate = 208000000,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 8,
+};
+#endif
+
+static struct clk sdm_ck = { /* 275-550MHz */
+ .name = "sdm_ck",
+ .parent = &sys_ck,
+ .rate = 200000000,
+/* .flags = RATE_PROPAGATES,*/
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 3,
+};
+
+/*** Master clock sources ***/
+
+static struct clk arm_ck = {
+ .name = "arm_ck",
+ .rate = 416000000,
+ .parent = &sc_ck,
+/* .flags = RATE_PROPAGATES,*/
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+static struct clk hclk_ck = {
+ .name = "hclk_ck",
+ .rate = 208000000,
+ .parent = &arm_ck,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 1,
+};
+
+static struct clk hclk2_ck = {
+ .name = "hclk2_ck",
+/* .rate = 104000000,*/
+ .rate = 52000000,
+ .parent = &fix_ck,
+ .flags = RATE_PROPAGATES,
+ .init = u6_clk_init_hclk2,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 2,
+};
+
+static struct clk sdm_ivs_ck = {
+ .name = "sdm_ivs_ck",
+ .parent = &hclk2_ck,
+ .rate = 104000000,
+ .flags = RATE_PROPAGATES,
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_ivs_recalc,
+ .enable_reg = CGU_SDMCON_REG,
+ .enable_bit = 23,
+};
+
+static struct clk pclk1_ck = {
+ .name = "pclk1_ck",
+ .rate = 104000000,
+ .parent = &hclk2_ck,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+static struct clk tvclk_ck = {
+ .name = "tvclk_ck",
+ .rate = 27000000,
+ .parent = &tv_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_tvo_pll_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_TVCON_REG,
+ .enable_bit = 15,
+};
+
+static struct clk pclk2_ck = {
+ .name = "pclk2_ck",
+ .rate = 52000000,
+ .parent = &fix_ck,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 4,
+};
+
+static struct clk clk24m_ck = {
+ .name = "clk24m_ck",
+ .rate = 24000000,
+ .parent = &fix_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 5,
+};
+
+static struct clk clk26m_ck = {
+ .name = "clk26m_ck",
+ .rate = 26000000,
+ .parent = &fix_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 6,
+};
+
+static struct clk clk13m_ck = {
+ .name = "clk13m_ck",
+ .rate = 13000000,
+ .parent = &fix_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 7,
+};
+
+static struct clk clk4m_ck = {
+ .name = "clk4m_ck",
+ .rate = 4000000,
+ .parent = &fix_ck,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk sioy1clk_ck = {
+ .name = "sioy1clk_ck",
+ .rate = 208000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk sioy2clk_ck = {
+ .name = "sioy2clk_ck",
+ .rate = 208000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk rfclk_ck = {
+ .name = "rfclk_ck",
+ .rate = 208000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+#endif
+
+static struct clk fc_ck = {
+ .name = "fc_ck",
+/* .rate = 104000000,*/
+ .rate = 52000000,
+ .init = u6_clk_init_fci,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .set_rate = u6_clk_set_rate_fci,
+ .parent = &fix_ck,
+};
+
+static struct clk usb_d_ck = {
+ .name = "usb_d_ck",
+ .rate = 24000000,
+ .parent = &clk24m_ck,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+static struct clk usb_h_ck = {
+ .name = "usb_h_ck",
+ .rate = 24000000,
+ .parent = &clk24m_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk dcclk1_ck = {
+ .name = "dcclk1_ck",
+ .rate = 130000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk diclk1_ck = {
+ .name = "diclk1_ck",
+ .rate = 130000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk dcclk2_ck = {
+ .name = "dcclk2_ck",
+ .rate = 130000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk diclk2_ck = {
+ .name = "dicl2_ck",
+ .rate = 130000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+#endif
+
+static struct clk camo_ck = {
+ .name = "camo_ck",
+ .rate = 12000000,
+ .parent = &fix_ck,
+ .flags = RATE_PROPAGATES,
+ .init = u6_clk_init_camout,
+ .enable = u67xx_cgu_enable_camout,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .set_rate = u6_clk_set_rate_camout,
+ .set_parent = u6_clk_set_parent_camout,
+ .enable_reg = CGU_CAMCON_REG,
+ .enable_bit = 7,
+};
+
+/*** Peripheral clocks ***/
+
+/* CGUTVCON */
+static struct clk plltv_ck = {
+ .name = "TVOPLL",
+ .enable_reg = CGU_TVCON_REG,
+ .enable_bit = 12,
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .parent = &tvclk_ck,
+};
+
+/* CGUGATESC1 */
+#ifndef U6_OPTIMIZED_TREE
+static struct clk intc_ck = {
+ .name = "INTC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 0,
+ .parent = &hclk2_ck,
+ .usecount = 1,
+};
+
+static struct clk extint_ck = {
+ .name = "EXTINT",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 1,
+ .parent = &pclk2_ck,
+ .usecount = 1,
+};
+
+static struct clk sctu_ck = {
+ .name = "SCTU",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 2,
+ .parent = &clk13m_ck,
+};
+#endif
+
+static struct clk spi1_ck = {
+ .name = "SPI1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 3,
+ .parent = &pclk1_ck,
+};
+
+static struct clk spi2_ck = {
+ .name = "SPI2",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 4,
+ .parent = &pclk1_ck,
+};
+
+static struct clk iic1_ck = {
+ .name = "IIC1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 5,
+ .parent = &pclk2_ck,
+};
+
+static struct clk iic2_ck = {
+ .name = "IIC2",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 6,
+ .parent = &pclk2_ck,
+};
+
+static struct clk uart1_ck = {
+ .name = "UART1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .set_parent = u6_clk_set_parent_uart,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 7,
+ .parent = &clk13m_ck,
+ .usecount = 1,
+};
+
+static struct clk uart2_ck = {
+ .name = "UART2",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .set_parent = u6_clk_set_parent_uart,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 8,
+ .parent = &clk13m_ck,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk gpio_ck = {
+ .name = "GPIO",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 9,
+ .parent = &pclk2_ck,
+ .usecount = 1,
+};
+#endif
+
+static struct clk kbs_ck = {
+ .name = "KBS",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 10,
+ .parent = &func_32k_ck,
+};
+
+static struct clk pwm1_ck = {
+ .name = "PWM1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 11,
+ .parent = &clk13m_ck,
+};
+
+static struct clk pwm2_ck = {
+ .name = "PWM2",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 12,
+ .parent = &clk13m_ck,
+};
+
+static struct clk pwm3_ck = {
+ .name = "PWM3",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 13,
+ .parent = &clk13m_ck,
+};
+
+static struct clk geac_ck = {
+ .name = "GEAC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 14,
+ .parent = &pclk1_ck,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk usim_ck = {
+ .name = "USIM",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 15,
+ .parent = &pclk2_ck,
+};
+#endif
+
+static struct clk fci_ck = {
+ .name = "FCI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 16,
+ .parent = &fc_ck,
+};
+
+static struct clk usbd_ck = {
+ .name = "USBD",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 17,
+ .parent = &hclk2_ck,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk iis_ck = {
+ .name = "IIS",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 18,
+ .parent = &clk24m_ck,
+};
+
+static struct clk rfsm1_ck = {
+ .name = "RFSM1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 19,
+ .parent = &pclk1_ck,
+};
+#endif
+
+static struct clk dmau_ck = {
+ .name = "DMAU",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_shared_clock,
+ .disable = u67xx_cgu_disable_shared_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 20,
+ .parent = &hclk2_ck,
+};
+
+static struct clk jdi_ck = {
+ .name = "JDI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 24,
+ .parent = &pclk2_ck,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk ucc_ck = {
+ .name = "UCC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 25,
+ .parent = &pclk1_ck,
+};
+#endif
+
+static struct clk msi_ck = {
+ .name = "MSI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 26,
+ .parent = &fc_ck,
+};
+
+static struct clk sdi_ck = {
+ .name = "SDI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 28,
+ .parent = &hclk2_ck,
+};
+
+static struct clk nfi_ck = {
+ .name = "NFI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 29,
+ .parent = &hclk2_ck,
+
+};
+
+static struct clk ebi_ck = {
+ .name = "EBI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 31,
+ .parent = &hclk2_ck,
+
+};
+
+/* CGUGATESC2 */
+static struct clk cae_ck = {
+ .name = "CAE",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC2_REG,
+ .enable_bit = 0,
+ .parent = &pclk1_ck,
+};
+
+static struct clk mmtu_ck = {
+ .name = "MMTU",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_shared_clock,
+ .disable = u67xx_cgu_disable_shared_clock,
+ .enable_reg = CGU_GATESC2_REG,
+ .enable_bit = 2,
+ .parent = &clk13m_ck,
+ .usecount = 1,
+};
+
+/* OCL-2008-07-02: how to manage etbclk ? */
+/* static struct clk ETB_ck = */
+/* { */
+/* .name = "ETB", */
+/* .enable_reg = CGU_GATESC2_REG, */
+/* .enable_bit = 4, */
+/* .parent = &etbclk_ck, */
+/* }; */
+
+/* CGUGATEIVS */
+static struct clk cam_ck = {
+ .name = "CAM",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 0,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk vde_ck = {
+ .name = "VDE",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 1,
+ .parent = &hclk2_ck,
+};
+
+static struct clk ipp_ck = {
+ .name = "IPP",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 2,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk vec_ck = {
+ .name = "VEC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 3,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk vdc_ck = {
+ .name = "VDC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 4,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk jdu_ck = {
+ .name = "JDU",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 5,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk tvoclk_ck = {
+ .name = "TVO",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 6,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk camjpe_ck = {
+ .name = "CAMJPE",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 7,
+ .parent = &hclk_ck,
+};
+
+static struct clk *onchip_clks[] = {
+ /* external root sources */
+ &func_32k_ck,
+ &osc_ck,
+ &sys_ck,
+ &sc_ck,
+ &fix_ck,
+ &tv_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &dsp2_ck,
+#endif
+ &sdm_ck,
+ &arm_ck,
+ &hclk_ck,
+ &hclk2_ck,
+ &pclk1_ck,
+ &pclk2_ck,
+ &tvclk_ck,
+ &clk24m_ck,
+ &clk26m_ck,
+ &clk13m_ck,
+ &clk4m_ck,
+ &fc_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &sioy1clk_ck,
+ &sioy2clk_ck,
+ &rfclk_ck,
+#endif
+ &usb_h_ck,
+ &usb_d_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &dcclk1_ck,
+ &diclk1_ck,
+ &dcclk2_ck,
+ &diclk2_ck,
+#endif
+ &camo_ck,
+ &tvoclk_ck,
+ &plltv_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &intc_ck,
+ &extint_ck,
+ &sctu_ck,
+#endif
+ &spi1_ck,
+ &spi2_ck,
+ &iic1_ck,
+ &iic2_ck,
+ &uart1_ck,
+ &uart2_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &gpio_ck,
+#endif
+ &kbs_ck,
+ &pwm1_ck,
+ &pwm2_ck,
+ &pwm3_ck,
+ &geac_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &usim_ck,
+#endif
+ &fci_ck,
+ &usbd_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &iis_ck,
+ &rfsm1_ck,
+#endif
+ &dmau_ck,
+ &jdi_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &ucc_ck,
+#endif
+ &msi_ck,
+ &sdi_ck,
+ &nfi_ck,
+ &ebi_ck,
+ &cae_ck,
+ &mmtu_ck,
+ &sdm_ivs_ck,
+ &cam_ck,
+ &vde_ck,
+ &vdc_ck,
+ &vec_ck,
+ &ipp_ck,
+ &jdu_ck,
+ &camjpe_ck
+};
+
+#endif
diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
index 12c832c..afdf82b 100644
--- a/arch/arm/plat-u6xxx/Makefile
+++ b/arch/arm/plat-u6xxx/Makefile
@@ -3,6 +3,6 @@
#
# Common support
-obj-y := io.o irq.o
+obj-y := io.o irq.o clock.o
obj-$(CONFIG_U6_MTU_TIMER) += timer.o
diff --git a/arch/arm/plat-u6xxx/clock.c b/arch/arm/plat-u6xxx/clock.c
new file mode 100644
index 0000000..dd8fc02
--- /dev/null
+++ b/arch/arm/plat-u6xxx/clock.c
@@ -0,0 +1,650 @@
+/*
+ * linux/arch/arm/plat-u6xxx/clock.c
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
+ * Copyright (C) 2010 ST-Ericsson SA
+ *
+ * Modified for omap shared clock framework by Tony Lindgren <tony at atomide.com>
+ *
+ * Modified for u6 shared clock framework by Loic Pallardy @ ST-Ericsson.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.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/notifier.h>
+
+#include <linux/io.h>
+
+#include <mach/clock.h>
+
+#ifdef CONFIG_U6_POWER_SYSFS
+#include "power_sysfs.h"
+#endif
+
+LIST_HEAD(clocks);
+
+static DEFINE_MUTEX(clocks_mutex);
+DEFINE_SPINLOCK(clockfw_lock);
+
+static struct clk_functions *arch_clock;
+
+/*
+ * Additionnal specific clock functions define in include/mach/clock.h
+ */
+
+/**
+ * clk_register_notifier - register a driver with clock mngt
+ * @nb: notifier function to register
+ * @clk: clock element rate change to be notified
+ *
+ * Add a driver to one of two lists: either a list of drivers that
+ * are notified about clock rate changes (once before and once after
+ * the transition),
+ * This function may sleep, and has the same return conditions as
+ * sru_blocking_notifier_chain_register.
+ */
+int clk_register_notifier(struct notifier_block *nb, struct clk *clk)
+{
+ int ret;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ mutex_lock(&clocks_mutex);
+ if (clk->notifier)
+ ret = srcu_notifier_chain_register(clk->notifier, nb);
+ else
+ ret = -EINVAL;
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_register_notifier);
+
+/**
+ * clk_unregister_notifier - unregister a driver with clock mngt
+ * @nb: notifier function to be unregistered
+ * @clk: clock element rate change to be notified
+ *
+ * Remove a driver from the clock mngt notifier list.
+ *
+ * This function may sleep, and has the same return conditions as
+ * sru_blocking_notifier_chain_unregister.
+ */
+int clk_unregister_notifier(struct notifier_block *nb, struct clk *clk)
+{
+ int ret;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ mutex_lock(&clocks_mutex);
+ if (clk->notifier)
+ ret = srcu_notifier_chain_unregister(clk->notifier, nb);
+ else
+ ret = -EINVAL;
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_unregister_notifier);
+
+/**
+ * clk_notify_transition - call notifier chain
+ *
+ * This function calls the transition notifiers and the and set rate
+ * It is called twice on all frequency changes that have
+ * external effects.
+ */
+int clk_notify_transition(struct clk *clk, unsigned int state, void *data)
+{
+ BUG_ON(irqs_disabled());
+
+ if (clk == ERR_PTR(-ENOENT))
+ return NOTIFY_BAD;
+
+ switch (state) {
+
+ case CLK_RATE_PRECHANGE:
+ case CLK_RATE_POSTCHANGE:
+/* printk("notif %u of frequency transition of %s to %lu Hz\n",
+ state, clk->name, (unsigned long)data);
+*/
+ break;
+
+ case CLK_SRCE_PRECHANGE:
+ case CLK_SRCE_POSTCHANGE:
+/* printk("notif %u of srce transition of %s to %s\n",
+ state, clk->name, ((struct clk *)data)->name);
+*/
+ break;
+ default:
+ printk(KERN_ERR "Unknown notification srce transition\n");
+ return NOTIFY_BAD;
+ break;
+ }
+
+ return srcu_notifier_call_chain(clk->notifier, state, data);
+}
+
+/*
+ * Standard clock functions defined in include/linux/clk.h
+ */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+ mutex_lock(&clocks_mutex);
+ list_for_each_entry(p, &clocks, node) {
+ if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+ mutex_unlock(&clocks_mutex);
+
+ return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_enable)
+ ret = arch_clock->clk_enable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_disable)
+ arch_clock->clk_disable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_get_usecount(struct clk *clk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ ret = clk->usecount;
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_get_usecount);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long flags;
+ unsigned long ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ ret = clk->rate;
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+ if (clk && !IS_ERR(clk))
+ module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+/*
+ * Optional clock functions defined in include/linux/clk.h
+ */
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ long ret = rate;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_round_rate)
+ ret = arch_clock->clk_round_rate(clk, rate);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ /* notification pre change */
+ if (clk->notifier)
+ ret = clk_notify_transition(clk,
+ CLK_RATE_PRECHANGE, (void *)rate);
+
+ if (!(ret & NOTIFY_STOP_MASK)) {
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_set_rate)
+ ret = arch_clock->clk_set_rate(clk, rate);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ /* notification post change */
+ if (clk->notifier)
+ clk_notify_transition(clk,
+ CLK_RATE_POSTCHANGE,
+ (void *)clk->rate);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ /* notification pre change */
+ if (clk->notifier)
+ ret = clk_notify_transition(clk,
+ CLK_SRCE_PRECHANGE, (void *)parent);
+
+ if (!(ret & NOTIFY_STOP_MASK)) {
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_set_parent)
+ ret = arch_clock->clk_set_parent(clk, parent);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ /* notification post change */
+ if (clk->notifier)
+ clk_notify_transition(clk,
+ CLK_SRCE_POSTCHANGE,
+ (void *)clk->parent);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ unsigned long flags;
+ struct clk *ret = ERR_PTR(-ENOENT);
+
+ if (clk == ERR_PTR(-ENOENT))
+ return ret;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_get_parent)
+ ret = arch_clock->clk_get_parent(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+/*
+ * Internal clock functions
+ */
+
+unsigned int __initdata mpurate;
+/*
+ * By default we use the rate set by the bootloader.
+ * You can override this with mpurate= cmdline option.
+ */
+static int __init u6_clk_setup(char *str)
+{
+ unsigned int tmp_rate;
+
+ get_option(&str, &tmp_rate);
+
+ if (!tmp_rate)
+ return 1;
+
+ mpurate = tmp_rate;
+
+ return 1;
+}
+
+__setup("mpurate=", u6_clk_setup);
+
+/* Used for clocks that always have same value as the parent clock */
+void followparent_recalc(struct clk *clk)
+{
+ clk->rate = clk->parent->rate;
+}
+
+/* Propagate rate to children */
+void propagate_rate(struct clk *tclk)
+{
+ struct clk *clkp;
+
+ list_for_each_entry(clkp, &clocks, node) {
+ if (likely(clkp->parent != tclk))
+ continue;
+ if (likely((u32) clkp->recalc))
+ clkp->recalc(clkp);
+ }
+}
+
+int clk_register(struct clk *clk)
+{
+ mutex_lock(&clocks_mutex);
+ list_add(&clk->node, &clocks);
+ if (clk->init)
+ clk->init(clk);
+ mutex_unlock(&clocks_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+ mutex_lock(&clocks_mutex);
+ list_del(&clk->node);
+ mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+void clk_deny_idle(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_deny_idle)
+ arch_clock->clk_deny_idle(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_deny_idle);
+
+void clk_allow_idle(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_allow_idle)
+ arch_clock->clk_allow_idle(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_allow_idle);
+
+#ifdef CONFIG_U6_POWER_SYSFS
+/*
+ * SysFs interface
+ */
+
+/*** Clock mngt sysfs interface **/
+static char clk_name[64] = "MMTU";
+
+static ssize_t show_select(struct kobject *kobj, char *buf)
+{
+ return sprintf(buf, "%s \n", clk_name);
+}
+
+static ssize_t store_select(struct kobject *kobj, const char *buf, size_t size)
+{
+ strcpy(clk_name, buf);
+
+ clk_name[strlen(clk_name) - 1] = 0;
+
+ return size;
+}
+
+static ssize_t show_enable(struct kobject *kobj, char *buf)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ clk_put(clk);
+ return sprintf(buf, "%d \n", clk_get_usecount(clk));
+}
+
+static ssize_t store_enable(struct kobject *kobj, const char *buf, size_t size)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return size;
+ clk_enable(clk);
+ clk_put(clk);
+ return size;
+}
+
+static ssize_t show_disable(struct kobject *kobj, char *buf)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ clk_put(clk);
+ return sprintf(buf, "%d \n", clk_get_usecount(clk));
+}
+
+static ssize_t store_disable(struct kobject *kobj, const char *buf, size_t size)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return size;
+ clk_disable(clk);
+ clk_put(clk);
+ return size;
+}
+
+static ssize_t show_usecount(struct kobject *kobj, char *buf)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ clk_put(clk);
+ return sprintf(buf, "%d \n", clk_get_usecount(clk));
+}
+
+static ssize_t show_rate(struct kobject *kobj, char *buf)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ clk_put(clk);
+ return sprintf(buf, "%lu \n", clk_get_rate(clk));
+}
+
+static ssize_t store_rate(struct kobject *kobj, const char *buf, size_t size)
+{
+ struct clk *clk;
+ unsigned long rate;
+ if (strict_strtoul(buf, 10, &rate) == 0) {
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return size;
+ clk_set_rate(clk, rate);
+ clk_put(clk);
+ }
+ return size;
+}
+
+static ssize_t show_parent(struct kobject *kobj, char *buf)
+{
+ struct clk *clk, *pclk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ pclk = clk_get_parent(clk);
+ clk_put(clk);
+ if ((pclk) && (pclk->name))
+ return sprintf(buf, "%s\n", pclk->name);
+ else
+ return sprintf(buf, "root\n");
+}
+
+static ssize_t store_parent(struct kobject *kobj, const char *buf, size_t size)
+{
+ struct clk *clk, *pclk;
+ char parent[32];
+ strcpy(parent, buf);
+ parent[strlen(parent) - 1] = 0;
+
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return size;
+
+ pclk = clk_get(NULL, parent);
+ if (pclk == ERR_PTR(-ENOENT)) {
+ clk_put(clk);
+ return size;
+ }
+ clk_put(pclk);
+ clk_set_parent(clk, pclk);
+ clk_put(clk);
+ return size;
+}
+
+static ssize_t show_list(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+
+ struct clk *p;
+
+ list_for_each_entry(p, &clocks, node) {
+ size += sprintf(&buf[size], "%s\n", p->name);
+ }
+ return size;
+}
+
+/*** Clock mngt hw debug ***/
+static ssize_t show_hw_constraints(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+
+ size += u6_clk_show_hw_rates(kobj, &buf[size]);
+
+ size += u6_clk_show_sc_constraints(kobj, &buf[size]);
+
+ size += u6_clk_show_ivs_constraints(kobj, &buf[size]);
+
+ size += u6_clk_show_tvo_constraints(kobj, &buf[size]);
+
+ size += u6_clk_show_cam_constraints(kobj, &buf[size]);
+
+ return size;
+}
+
+static ssize_t show_hw_rates(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+
+ size += u6_clk_show_hw_rates(kobj, buf);
+
+ return size;
+}
+
+define_one_ro(hw_rates);
+define_one_ro(hw_constraints);
+define_one_rw(parent);
+define_one_rw(rate);
+define_one_ro(usecount);
+define_one_rw(disable);
+define_one_rw(enable);
+define_one_rw(select);
+define_one_ro(list);
+
+static struct attribute *dbs_attributes_clock[] = {
+
+ &hw_rates.attr,
+ &hw_constraints.attr,
+ &parent.attr,
+ &rate.attr,
+ &usecount.attr,
+ &disable.attr,
+ &enable.attr,
+ &select.attr,
+ &list.attr,
+ NULL
+};
+
+static struct attribute_group dbs_attr_clock_group = {
+ .attrs = dbs_attributes_clock,
+ .name = "clk_mngt",
+};
+
+#endif
+
+/*
+ * Init functions
+ */
+
+int __init clk_init(struct clk_functions *custom_clocks)
+{
+ if (!custom_clocks) {
+ printk(KERN_ERR "No custom clock functions registered\n");
+ BUG();
+ }
+
+ arch_clock = custom_clocks;
+
+ return 0;
+}
+
+#ifdef CONFIG_U6_POWER_SYSFS
+static int __init u6_clock_init_sysfs(void)
+{
+ if (sysfs_create_group(&u6_power_kobj, &dbs_attr_clock_group))
+ printk(KERN_ERR "Unable to register %s in sysfs\n",
+ dbs_attr_clock_group.name);
+
+ return 0;
+}
+
+module_init(u6_clock_init_sysfs);
+#endif
+
diff --git a/arch/arm/plat-u6xxx/include/mach/clock.h b/arch/arm/plat-u6xxx/include/mach/clock.h
new file mode 100644
index 0000000..bc83414
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/clock.h
@@ -0,0 +1,376 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/clock.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy at stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ */
+
+#ifndef __PLAT_CLOCK_H
+#define __PLAT_CLOCK_H
+
+struct module;
+
+struct clk {
+ struct list_head node;
+ struct module *owner;
+ const char *name;
+ struct clk *parent;
+ unsigned long rate;
+ __u32 flags;
+ u32 enable_reg;
+ __u8 enable_bit;
+ __u8 rate_offset;
+ __u8 src_offset;
+ __s8 usecount;
+ void (*recalc)(struct clk *);
+ int (*set_rate)(struct clk *, unsigned long);
+ long (*round_rate)(struct clk *, unsigned long);
+ void (*init)(struct clk *);
+ int (*enable)(struct clk *);
+ void (*disable)(struct clk *);
+ int (*set_parent)(struct clk *, struct clk *);
+ struct srcu_notifier_head *notifier;
+};
+
+struct clk_functions {
+ int (*clk_enable)(struct clk *clk);
+ void (*clk_disable)(struct clk *clk);
+ long (*clk_round_rate)(struct clk *clk, unsigned long rate);
+ int (*clk_set_rate)(struct clk *clk, unsigned long rate);
+ int (*clk_set_parent)(struct clk *clk, struct clk *parent);
+ struct clk * (*clk_get_parent)(struct clk *clk);
+ void (*clk_allow_idle)(struct clk *clk);
+ void (*clk_deny_idle)(struct clk *clk);
+};
+
+extern unsigned int mpurate;
+extern struct list_head clocks;
+extern spinlock_t clockfw_lock;
+
+extern int clk_init(struct clk_functions *custom_clocks);
+extern int clk_register(struct clk *clk);
+extern void clk_unregister(struct clk *clk);
+
+extern void propagate_rate(struct clk *clk);
+extern void followparent_recalc(struct clk *clk);
+extern void clk_allow_idle(struct clk *clk);
+extern void clk_deny_idle(struct clk *clk);
+extern int clk_get_usecount(struct clk *clk);
+
+extern ssize_t u6_clk_show_hw_rates(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_sc_constraints(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_usb_constraints(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_ivs_constraints(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_tvo_constraints(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_cam_constraints(struct kobject *kobj, char *buf);
+
+extern unsigned long clk_get_hw_constraint(unsigned long reg_addr);
+
+
+/* Clock flags */
+#define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */
+#define RATE_FIXED (1 << 1) /* Fixed clock rate */
+#define RATE_PROPAGATES (1 << 2) /* Program children too */
+#define VIRTUAL_CLOCK (1 << 3) /* Composite clock from table */
+#define ALWAYS_ENABLED (1 << 4) /* Clock cannot be disabled */
+#define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */
+#define VIRTUAL_IO_ADDRESS (1 << 6) /* Clock in virtual address */
+#define CLOCK_IDLE_CONTROL (1 << 7)
+#define CLOCK_NO_IDLE_PARENT (1 << 8)
+#define DELAYED_APP (1 << 9) /* Delay application of clock */
+#define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
+
+
+#define CLK_HCLK2_MAX_FREQ 104000000
+#define CLK_FC_CLK_MAX_FREQ 104000000
+#define CLK_CAM_CLK_MAX_FREQ 78000000
+
+/**
+ * clk_register_notifier - register a driver with clock mngt
+ * @nb: notifier function to register
+ * @clk: clock element rate change to be notified
+ */
+extern int clk_register_notifier(struct notifier_block *nb, struct clk *clk);
+
+/**
+ * clk_unregister_notifier - unregister a driver with clock mngt
+ * @nb: notifier function to register
+ * @clk: clock element rate change to be notified
+ */
+extern int clk_unregister_notifier(struct notifier_block *nb, struct clk *clk);
+
+/**
+ * clk_notify_transition - call notifier chain
+ *
+ * This function calls the transition notifiers and the and set rate
+ * It is called twice on all frequency changes that have
+ * external effects.
+ */
+extern int clk_notify_transition(struct clk *clk,
+ unsigned int state, void *data);
+
+#define CLK_RATE_PRECHANGE 0
+#define CLK_RATE_POSTCHANGE 1
+#define CLK_SRCE_PRECHANGE 2
+#define CLK_SRCE_POSTCHANGE 3
+
+/* Hardware Register Definitions CGU (Clock Gating Unit) */
+
+/* CGU DSP1CON Register (32 bits) */
+#define CGU_DSP1CON_OFFSET 0x0
+#define CGU_DSP1CON_REG IO_ADDRESS(CGU_BASE + CGU_DSP1CON_OFFSET)
+
+/* CGU SCCON Register (32 bits) */
+#define CGU_SCCON_OFFSET 0x4
+#define CGU_SCCON_REG IO_ADDRESS(CGU_BASE + CGU_SCCON_OFFSET)
+
+/* CGU GATESC1 Register (32 bits) */
+#define CGU_GATESC1_OFFSET 0x8
+#define CGU_GATESC1_REG IO_ADDRESS(CGU_BASE + CGU_GATESC1_OFFSET)
+
+/* CGU SLEEPSC Register (32 bits) */
+#define CGU_SLEEPSC_OFFSET 0xC
+#define CGU_SLEEPSC_REG IO_ADDRESS(CGU_BASE + CGU_SLEEPSC_OFFSET)
+
+/* CGU FDIV Register (32 bits) */
+#define CGU_FDIV_OFFSET 0x10
+#define CGU_FDIV_REG IO_ADDRESS(CGU_BASE + CGU_FDIV_OFFSET)
+
+/* CGU GATEIVS Register (32 bits) */
+#define CGU_GATEIVS_OFFSET 0x14
+#define CGU_GATEIVS_REG IO_ADDRESS(CGU_BASE + CGU_GATEIVS_OFFSET)
+
+/* CGU DSP2CON Register (32 bits) */
+#define CGU_DSP2CON_OFFSET 0x18
+#define CGU_DSP2CON_REG IO_ADDRESS(CGU_BASE + CGU_DSP2CON_OFFSET)
+
+/* CGU CAMCON Register (32 bits) */
+#define CGU_CAMCON_OFFSET 0x1C
+#define CGU_CAMCON_REG IO_ADDRESS(CGU_BASE + CGU_CAMCON_OFFSET)
+
+/* CGU GATESC2 Register (32 bits) */
+#define CGU_GATESC2_OFFSET 0x20
+#define CGU_GATESC2_REG IO_ADDRESS(CGU_BASE + CGU_GATESC2_OFFSET)
+
+/* CGU SDMCON Register (32 bits) */
+#define CGU_SDMCON_OFFSET 0x24
+#define CGU_SDMCON_REG IO_ADDRESS(CGU_BASE + CGU_SDMCON_OFFSET)
+
+/* CGU TVCON Register (32 bits) */
+#define CGU_TVCON_OFFSET 0x28
+#define CGU_TVCON_REG IO_ADDRESS(CGU_BASE + CGU_TVCON_OFFSET)
+
+/* CGU IDLESC Register (32 bits) */
+#define CGU_IDLESC_OFFSET 0x2C
+#define CGU_IDLESC_REG IO_ADDRESS(CGU_BASE + CGU_IDLESC_OFFSET)
+
+/* CGU FIXCON Register (32 bits) */
+#define CGU_FIXCON_OFFSET 0x30
+#define CGU_FIXCON_REG IO_ADDRESS(CGU_BASE + CGU_FIXCON_OFFSET)
+
+/* CGU CNTCON Register (32 bits) */
+#define CGU_CNTCON_OFFSET 0x38
+#define CGU_CNTCON_REG IO_ADDRESS(CGU_BASE + CGU_CNTCON_OFFSET)
+
+/* Register description for GATESC1 */
+
+/* Bits definition for register CGU_GATESC1 */
+#define CGU_EBIEN_SHIFT 31
+#define CGU_EBIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_EBIEN_SHIFT))
+#define CGU_EBIEN_0 (0x0UL<<CGU_EBIEN_SHIFT)
+#define CGU_EBIEN_1 (0x1UL<<CGU_EBIEN_SHIFT)
+#define CGU_EBIEN (0x1UL<<CGU_EBIEN_SHIFT)
+#define CGU_NFIEN_SHIFT 29
+#define CGU_NFIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_NFIEN_SHIFT))
+#define CGU_NFIEN_0 (0x0UL<<CGU_NFIEN_SHIFT)
+#define CGU_NFIEN_1 (0x1UL<<CGU_NFIEN_SHIFT)
+#define CGU_NFIEN (0x1UL<<CGU_NFIEN_SHIFT)
+#define CGU_SDIEN_SHIFT 28
+#define CGU_SDIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SDIEN_SHIFT))
+#define CGU_SDIEN_0 (0x0UL<<CGU_SDIEN_SHIFT)
+#define CGU_SDIEN_1 (0x1UL<<CGU_SDIEN_SHIFT)
+#define CGU_SDIEN (0x1UL<<CGU_SDIEN_SHIFT)
+#define CGU_MSIEN_SHIFT 26
+#define CGU_MSIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_MSIEN_SHIFT))
+#define CGU_MSIEN_0 (0x0UL<<CGU_MSIEN_SHIFT)
+#define CGU_MSIEN_1 (0x1UL<<CGU_MSIEN_SHIFT)
+#define CGU_MSIEN (0x1UL<<CGU_MSIEN_SHIFT)
+#define CGU_UCCEN_SHIFT 25
+#define CGU_UCCEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_UCCEN_SHIFT))
+#define CGU_UCCEN_0 (0x0UL<<CGU_UCCEN_SHIFT)
+#define CGU_UCCEN_1 (0x1UL<<CGU_UCCEN_SHIFT)
+#define CGU_UCCEN (0x1UL<<CGU_UCCEN_SHIFT)
+#define CGU_JDIEN_SHIFT 24
+#define CGU_JDIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_JDIEN_SHIFT))
+#define CGU_JDIEN_0 (0x0UL<<CGU_JDIEN_SHIFT)
+#define CGU_JDIEN_1 (0x1UL<<CGU_JDIEN_SHIFT)
+#define CGU_JDIEN (0x1UL<<CGU_JDIEN_SHIFT)
+#define CGU_DMAUEN_SHIFT 20
+#define CGU_DMAUEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_DMAUEN_SHIFT))
+#define CGU_DMAUEN_0 (0x0UL<<CGU_DMAUEN_SHIFT)
+#define CGU_DMAUEN_1 (0x1UL<<CGU_DMAUEN_SHIFT)
+#define CGU_DMAUEN (0x1UL<<CGU_DMAUEN_SHIFT)
+#define CGU_RFSM1EN_SHIFT 19
+#define CGU_RFSM1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_RFSM1EN_SHIFT))
+#define CGU_RFSM1EN_0 (0x0UL<<CGU_RFSM1EN_SHIFT)
+#define CGU_RFSM1EN_1 (0x1UL<<CGU_RFSM1EN_SHIFT)
+#define CGU_RFSM1EN (0x1UL<<CGU_RFSM1EN_SHIFT)
+#define CGU_SIISEN_SHIFT 18
+#define CGU_SIISEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SIISEN_SHIFT))
+#define CGU_SIISEN_0 (0x0UL<<CGU_SIISEN_SHIFT)
+#define CGU_SIISEN_1 (0x1UL<<CGU_SIISEN_SHIFT)
+#define CGU_SIISEN (0x1UL<<CGU_SIISEN_SHIFT)
+#define CGU_USBEN_SHIFT 17
+#define CGU_USBEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_USBEN_SHIFT))
+#define CGU_USBEN_0 (0x0UL<<CGU_USBEN_SHIFT)
+#define CGU_USBEN_1 (0x1UL<<CGU_USBEN_SHIFT)
+#define CGU_USBEN (0x1UL<<CGU_USBEN_SHIFT)
+#define CGU_FCIEN_SHIFT 16
+#define CGU_FCIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_FCIEN_SHIFT))
+#define CGU_FCIEN_0 (0x0UL<<CGU_FCIEN_SHIFT)
+#define CGU_FCIEN_1 (0x1UL<<CGU_FCIEN_SHIFT)
+#define CGU_FCIEN (0x1UL<<CGU_FCIEN_SHIFT)
+#define CGU_USIMEN_SHIFT 15
+#define CGU_USIMEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_USIMEN_SHIFT))
+#define CGU_USIMEN_0 (0x0UL<<CGU_USIMEN_SHIFT)
+#define CGU_USIMEN_1 (0x1UL<<CGU_USIMEN_SHIFT)
+#define CGU_USIMEN (0x1UL<<CGU_USIMEN_SHIFT)
+#define CGU_GEACEN_SHIFT 14
+#define CGU_GEACEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_GEACEN_SHIFT))
+#define CGU_GEACEN_0 (0x0UL<<CGU_GEACEN_SHIFT)
+#define CGU_GEACEN_1 (0x1UL<<CGU_GEACEN_SHIFT)
+#define CGU_GEACEN (0x1UL<<CGU_GEACEN_SHIFT)
+#define CGU_PWM3EN_SHIFT 13
+#define CGU_PWM3EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_PWM3EN_SHIFT))
+#define CGU_PWM3EN_0 (0x0UL<<CGU_PWM3EN_SHIFT)
+#define CGU_PWM3EN_1 (0x1UL<<CGU_PWM3EN_SHIFT)
+#define CGU_PWM3EN (0x1UL<<CGU_PWM3EN_SHIFT)
+#define CGU_PWM2EN_SHIFT 12
+#define CGU_PWM2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_PWM2EN_SHIFT))
+#define CGU_PWM2EN_0 (0x0UL<<CGU_PWM2EN_SHIFT)
+#define CGU_PWM2EN_1 (0x1UL<<CGU_PWM2EN_SHIFT)
+#define CGU_PWM2EN (0x1UL<<CGU_PWM2EN_SHIFT)
+#define CGU_PWM1EN_SHIFT 11
+#define CGU_PWM1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_PWM1EN_SHIFT))
+#define CGU_PWM1EN_0 (0x0UL<<CGU_PWM1EN_SHIFT)
+#define CGU_PWM1EN_1 (0x1UL<<CGU_PWM1EN_SHIFT)
+#define CGU_PWM1EN (0x1UL<<CGU_PWM1EN_SHIFT)
+#define CGU_KBSEN_SHIFT 10
+#define CGU_KBSEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_KBSEN_SHIFT))
+#define CGU_KBSEN_0 (0x0UL<<CGU_KBSEN_SHIFT)
+#define CGU_KBSEN_1 (0x1UL<<CGU_KBSEN_SHIFT)
+#define CGU_KBSEN (0x1UL<<CGU_KBSEN_SHIFT)
+#define CGU_GPIOEN_SHIFT 9
+#define CGU_GPIOEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_GPIOEN_SHIFT))
+#define CGU_GPIOEN_0 (0x0UL<<CGU_GPIOEN_SHIFT)
+#define CGU_GPIOEN_1 (0x1UL<<CGU_GPIOEN_SHIFT)
+#define CGU_GPIOEN (0x1UL<<CGU_GPIOEN_SHIFT)
+#define CGU_UART2EN_SHIFT 8
+#define CGU_UART2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_UART2EN_SHIFT))
+#define CGU_UART2EN_0 (0x0UL<<CGU_UART2EN_SHIFT)
+#define CGU_UART2EN_1 (0x1UL<<CGU_UART2EN_SHIFT)
+#define CGU_UART2EN (0x1UL<<CGU_UART2EN_SHIFT)
+#define CGU_UART1EN_SHIFT 7
+#define CGU_UART1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_UART1EN_SHIFT))
+#define CGU_UART1EN_0 (0x0UL<<CGU_UART1EN_SHIFT)
+#define CGU_UART1EN_1 (0x1UL<<CGU_UART1EN_SHIFT)
+#define CGU_UART1EN (0x1UL<<CGU_UART1EN_SHIFT)
+#define CGU_IIC2EN_SHIFT 6
+#define CGU_IIC2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_IIC2EN_SHIFT))
+#define CGU_IIC2EN_0 (0x0UL<<CGU_IIC2EN_SHIFT)
+#define CGU_IIC2EN_1 (0x1UL<<CGU_IIC2EN_SHIFT)
+#define CGU_IIC2EN (0x1UL<<CGU_IIC2EN_SHIFT)
+#define CGU_IIC1EN_SHIFT 5
+#define CGU_IIC1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_IIC1EN_SHIFT))
+#define CGU_IIC1EN_0 (0x0UL<<CGU_IIC1EN_SHIFT)
+#define CGU_IIC1EN_1 (0x1UL<<CGU_IIC1EN_SHIFT)
+#define CGU_IIC1EN (0x1UL<<CGU_IIC1EN_SHIFT)
+#define CGU_SPI2EN_SHIFT 4
+#define CGU_SPI2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SPI2EN_SHIFT))
+#define CGU_SPI2EN_0 (0x0UL<<CGU_SPI2EN_SHIFT)
+#define CGU_SPI2EN_1 (0x1UL<<CGU_SPI2EN_SHIFT)
+#define CGU_SPI2EN (0x1UL<<CGU_SPI2EN_SHIFT)
+#define CGU_SPI1EN_SHIFT 3
+#define CGU_SPI1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SPI1EN_SHIFT))
+#define CGU_SPI1EN_0 (0x0UL<<CGU_SPI1EN_SHIFT)
+#define CGU_SPI1EN_1 (0x1UL<<CGU_SPI1EN_SHIFT)
+#define CGU_SPI1EN (0x1UL<<CGU_SPI1EN_SHIFT)
+#define CGU_SCTUEN_SHIFT 2
+#define CGU_SCTUEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SCTUEN_SHIFT))
+#define CGU_SCTUEN_0 (0x0UL<<CGU_SCTUEN_SHIFT)
+#define CGU_SCTUEN_1 (0x1UL<<CGU_SCTUEN_SHIFT)
+#define CGU_SCTUEN (0x1UL<<CGU_SCTUEN_SHIFT)
+#define CGU_EXTINTEN_SHIFT 1
+#define CGU_EXTINTEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_EXTINTEN_SHIFT))
+#define CGU_EXTINTEN_0 (0x0UL<<CGU_EXTINTEN_SHIFT)
+#define CGU_EXTINTEN_1 (0x1UL<<CGU_EXTINTEN_SHIFT)
+#define CGU_EXTINTEN (0x1UL<<CGU_EXTINTEN_SHIFT)
+#define CGU_INTCEN_SHIFT 0
+#define CGU_INTCEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_INTCEN_SHIFT))
+#define CGU_INTCEN_0 (0x0UL<<CGU_INTCEN_SHIFT)
+#define CGU_INTCEN_1 (0x1UL<<CGU_INTCEN_SHIFT)
+#define CGU_INTCEN (0x1UL<<CGU_INTCEN_SHIFT)
+
+/* Register description for GATESC2 */
+
+/* Bits definition for register CGU_GATESC2 */
+#define CGU_TRAUPCLKEN_SHIFT 15
+#define CGU_TRAUPCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_TRAUPCLKEN_SHIFT))
+#define CGU_TRAUPCLKEN_0 (0x0UL<<CGU_TRAUPCLKEN_SHIFT)
+#define CGU_TRAUPCLKEN_1 (0x1UL<<CGU_TRAUPCLKEN_SHIFT)
+#define CGU_TRAUPCLKEN (0x1UL<<CGU_TRAUPCLKEN_SHIFT)
+#define CGU_AUTRXPCLKEN_SHIFT 12
+#define CGU_AUTRXPCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_AUTRXPCLKEN_SHIFT))
+#define CGU_AUTRXPCLKEN_0 (0x0UL<<CGU_AUTRXPCLKEN_SHIFT)
+#define CGU_AUTRXPCLKEN_1 (0x1UL<<CGU_AUTRXPCLKEN_SHIFT)
+#define CGU_AUTRXPCLKEN (0x1UL<<CGU_AUTRXPCLKEN_SHIFT)
+#define CGU_AUTRXMCLK2EN_SHIFT 11
+#define CGU_AUTRXMCLK2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_AUTRXMCLK2EN_SHIFT))
+#define CGU_AUTRXMCLK2EN_0 (0x0UL<<CGU_AUTRXMCLK2EN_SHIFT)
+#define CGU_AUTRXMCLK2EN_1 (0x1UL<<CGU_AUTRXMCLK2EN_SHIFT)
+#define CGU_AUTRXMCLK2EN (0x1UL<<CGU_AUTRXMCLK2EN_SHIFT)
+#define CGU_AUTRXMCLK1EN_SHIFT 10
+#define CGU_AUTRXMCLK1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_AUTRXMCLK1EN_SHIFT))
+#define CGU_AUTRXMCLK1EN_0 (0x0UL<<CGU_AUTRXMCLK1EN_SHIFT)
+#define CGU_AUTRXMCLK1EN_1 (0x1UL<<CGU_AUTRXMCLK1EN_SHIFT)
+#define CGU_AUTRXMCLK1EN (0x1UL<<CGU_AUTRXMCLK1EN_SHIFT)
+#define CGU_BBIPCLKEN_SHIFT 9
+#define CGU_BBIPCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_BBIPCLKEN_SHIFT))
+#define CGU_BBIPCLKEN_0 (0x0UL<<CGU_BBIPCLKEN_SHIFT)
+#define CGU_BBIPCLKEN_1 (0x1UL<<CGU_BBIPCLKEN_SHIFT)
+#define CGU_BBIPCLKEN (0x1UL<<CGU_BBIPCLKEN_SHIFT)
+#define CGU_HSDPAHCLKEN_SHIFT 8
+#define CGU_HSDPAHCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_HSDPAHCLKEN_SHIFT))
+#define CGU_HSDPAHCLKEN_0 (0x0UL<<CGU_HSDPAHCLKEN_SHIFT)
+#define CGU_HSDPAHCLKEN_1 (0x1UL<<CGU_HSDPAHCLKEN_SHIFT)
+#define CGU_HSDPAHCLKEN (0x1UL<<CGU_HSDPAHCLKEN_SHIFT)
+#define CGU_3GMHCLKEN_SHIFT 7
+#define CGU_3GMHCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_3GMHCLKEN_SHIFT))
+#define CGU_3GMHCLKEN_0 (0x0UL<<CGU_3GMHCLKEN_SHIFT)
+#define CGU_3GMHCLKEN_1 (0x1UL<<CGU_3GMHCLKEN_SHIFT)
+#define CGU_3GMHCLKEN (0x1UL<<CGU_3GMHCLKEN_SHIFT)
+#define CGU_3GMMCLKEN_SHIFT 6
+#define CGU_3GMMCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_3GMMCLKEN_SHIFT))
+#define CGU_3GMMCLKEN_0 (0x0UL<<CGU_3GMMCLKEN_SHIFT)
+#define CGU_3GMMCLKEN_1 (0x1UL<<CGU_3GMMCLKEN_SHIFT)
+#define CGU_3GMMCLKEN (0x1UL<<CGU_3GMMCLKEN_SHIFT)
+#define CGU_ETBEN_SHIFT 4
+#define CGU_ETBEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_ETBEN_SHIFT))
+#define CGU_ETBEN_0 (0x0UL<<CGU_ETBEN_SHIFT)
+#define CGU_ETBEN_1 (0x1UL<<CGU_ETBEN_SHIFT)
+#define CGU_ETBEN (0x1UL<<CGU_ETBEN_SHIFT)
+#define CGU_MMTUEN_SHIFT 2
+#define CGU_MMTUEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_MMTUEN_SHIFT))
+#define CGU_MMTUEN_0 (0x0UL<<CGU_MMTUEN_SHIFT)
+#define CGU_MMTUEN_1 (0x1UL<<CGU_MMTUEN_SHIFT)
+#define CGU_MMTUEN (0x1UL<<CGU_MMTUEN_SHIFT)
+#define CGU_CAEEN_SHIFT 0
+#define CGU_CAEEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_CAEEN_SHIFT))
+#define CGU_CAEEN_0 (0x0UL<<CGU_CAEEN_SHIFT)
+#define CGU_CAEEN_1 (0x1UL<<CGU_CAEEN_SHIFT)
+#define CGU_CAEEN (0x1UL<<CGU_CAEEN_SHIFT)
+
+#endif
diff --git a/arch/arm/plat-u6xxx/timer.c b/arch/arm/plat-u6xxx/timer.c
index 62f13f5..357e87c 100644
--- a/arch/arm/plat-u6xxx/timer.c
+++ b/arch/arm/plat-u6xxx/timer.c
@@ -19,6 +19,7 @@
#include <asm/mach/irq.h>
#include <linux/interrupt.h>
#include <mach/irqs.h>
+#include <mach/clock.h>
#include <linux/clk.h>
--
1.7.1
More information about the linux-arm-kernel
mailing list