ARM: tegra: implement basic tegra30 clock framework
authorPeter De Schrijver <pdeschrijver@nvidia.com>
Mon, 9 Jan 2012 05:35:12 +0000 (05:35 +0000)
committerOlof Johansson <olof@lixom.net>
Mon, 6 Feb 2012 17:16:15 +0000 (09:16 -0800)
Add basic tegra30 clock framework. Not all clocks are supported yet. Mainly
clocks requiring voltage scaling are not yet implemented in this version.

Based on work by Alex Frid <afrid@nvidia.com> and
Scott Williams <scwilliams@nvidia.com>.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Tested-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Olof Johansson <olof@lixom.net>
arch/arm/mach-tegra/tegra30_clocks.c [new file with mode: 0644]

diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
new file mode 100644 (file)
index 0000000..6d08b53
--- /dev/null
@@ -0,0 +1,3099 @@
+/*
+ * arch/arm/mach-tegra/tegra30_clocks.c
+ *
+ * Copyright (c) 2010-2011 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/syscore_ops.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/iomap.h>
+
+#include "clock.h"
+#include "fuse.h"
+
+#define USE_PLL_LOCK_BITS 0
+
+#define RST_DEVICES_L                  0x004
+#define RST_DEVICES_H                  0x008
+#define RST_DEVICES_U                  0x00C
+#define RST_DEVICES_V                  0x358
+#define RST_DEVICES_W                  0x35C
+#define RST_DEVICES_SET_L              0x300
+#define RST_DEVICES_CLR_L              0x304
+#define RST_DEVICES_SET_V              0x430
+#define RST_DEVICES_CLR_V              0x434
+#define RST_DEVICES_NUM                        5
+
+#define CLK_OUT_ENB_L                  0x010
+#define CLK_OUT_ENB_H                  0x014
+#define CLK_OUT_ENB_U                  0x018
+#define CLK_OUT_ENB_V                  0x360
+#define CLK_OUT_ENB_W                  0x364
+#define CLK_OUT_ENB_SET_L              0x320
+#define CLK_OUT_ENB_CLR_L              0x324
+#define CLK_OUT_ENB_SET_V              0x440
+#define CLK_OUT_ENB_CLR_V              0x444
+#define CLK_OUT_ENB_NUM                        5
+
+#define RST_DEVICES_V_SWR_CPULP_RST_DIS        (0x1 << 1)
+#define CLK_OUT_ENB_V_CLK_ENB_CPULP_EN (0x1 << 1)
+
+#define PERIPH_CLK_TO_BIT(c)           (1 << (c->u.periph.clk_num % 32))
+#define PERIPH_CLK_TO_RST_REG(c)       \
+       periph_clk_to_reg((c), RST_DEVICES_L, RST_DEVICES_V, 4)
+#define PERIPH_CLK_TO_RST_SET_REG(c)   \
+       periph_clk_to_reg((c), RST_DEVICES_SET_L, RST_DEVICES_SET_V, 8)
+#define PERIPH_CLK_TO_RST_CLR_REG(c)   \
+       periph_clk_to_reg((c), RST_DEVICES_CLR_L, RST_DEVICES_CLR_V, 8)
+
+#define PERIPH_CLK_TO_ENB_REG(c)       \
+       periph_clk_to_reg((c), CLK_OUT_ENB_L, CLK_OUT_ENB_V, 4)
+#define PERIPH_CLK_TO_ENB_SET_REG(c)   \
+       periph_clk_to_reg((c), CLK_OUT_ENB_SET_L, CLK_OUT_ENB_SET_V, 8)
+#define PERIPH_CLK_TO_ENB_CLR_REG(c)   \
+       periph_clk_to_reg((c), CLK_OUT_ENB_CLR_L, CLK_OUT_ENB_CLR_V, 8)
+
+#define CLK_MASK_ARM                   0x44
+#define MISC_CLK_ENB                   0x48
+
+#define OSC_CTRL                       0x50
+#define OSC_CTRL_OSC_FREQ_MASK         (0xF<<28)
+#define OSC_CTRL_OSC_FREQ_13MHZ                (0x0<<28)
+#define OSC_CTRL_OSC_FREQ_19_2MHZ      (0x4<<28)
+#define OSC_CTRL_OSC_FREQ_12MHZ                (0x8<<28)
+#define OSC_CTRL_OSC_FREQ_26MHZ                (0xC<<28)
+#define OSC_CTRL_OSC_FREQ_16_8MHZ      (0x1<<28)
+#define OSC_CTRL_OSC_FREQ_38_4MHZ      (0x5<<28)
+#define OSC_CTRL_OSC_FREQ_48MHZ                (0x9<<28)
+#define OSC_CTRL_MASK                  (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
+
+#define OSC_CTRL_PLL_REF_DIV_MASK      (3<<26)
+#define OSC_CTRL_PLL_REF_DIV_1         (0<<26)
+#define OSC_CTRL_PLL_REF_DIV_2         (1<<26)
+#define OSC_CTRL_PLL_REF_DIV_4         (2<<26)
+
+#define OSC_FREQ_DET                   0x58
+#define OSC_FREQ_DET_TRIG              (1<<31)
+
+#define OSC_FREQ_DET_STATUS            0x5C
+#define OSC_FREQ_DET_BUSY              (1<<31)
+#define OSC_FREQ_DET_CNT_MASK          0xFFFF
+
+#define PERIPH_CLK_SOURCE_I2S1         0x100
+#define PERIPH_CLK_SOURCE_EMC          0x19c
+#define PERIPH_CLK_SOURCE_OSC          0x1fc
+#define PERIPH_CLK_SOURCE_NUM1 \
+       ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
+
+#define PERIPH_CLK_SOURCE_G3D2         0x3b0
+#define PERIPH_CLK_SOURCE_SE           0x42c
+#define PERIPH_CLK_SOURCE_NUM2 \
+       ((PERIPH_CLK_SOURCE_SE - PERIPH_CLK_SOURCE_G3D2) / 4 + 1)
+
+#define AUDIO_DLY_CLK                  0x49c
+#define AUDIO_SYNC_CLK_SPDIF           0x4b4
+#define PERIPH_CLK_SOURCE_NUM3 \
+       ((AUDIO_SYNC_CLK_SPDIF - AUDIO_DLY_CLK) / 4 + 1)
+
+#define PERIPH_CLK_SOURCE_NUM          (PERIPH_CLK_SOURCE_NUM1 + \
+                                        PERIPH_CLK_SOURCE_NUM2 + \
+                                        PERIPH_CLK_SOURCE_NUM3)
+
+#define CPU_SOFTRST_CTRL               0x380
+
+#define PERIPH_CLK_SOURCE_DIVU71_MASK  0xFF
+#define PERIPH_CLK_SOURCE_DIVU16_MASK  0xFFFF
+#define PERIPH_CLK_SOURCE_DIV_SHIFT    0
+#define PERIPH_CLK_SOURCE_DIVIDLE_SHIFT        8
+#define PERIPH_CLK_SOURCE_DIVIDLE_VAL  50
+#define PERIPH_CLK_UART_DIV_ENB                (1<<24)
+#define PERIPH_CLK_VI_SEL_EX_SHIFT     24
+#define PERIPH_CLK_VI_SEL_EX_MASK      (0x3<<PERIPH_CLK_VI_SEL_EX_SHIFT)
+#define PERIPH_CLK_NAND_DIV_EX_ENB     (1<<8)
+#define PERIPH_CLK_DTV_POLARITY_INV    (1<<25)
+
+#define AUDIO_SYNC_SOURCE_MASK         0x0F
+#define AUDIO_SYNC_DISABLE_BIT         0x10
+#define AUDIO_SYNC_TAP_NIBBLE_SHIFT(c) ((c->reg_shift - 24) * 4)
+
+#define PLL_BASE                       0x0
+#define PLL_BASE_BYPASS                        (1<<31)
+#define PLL_BASE_ENABLE                        (1<<30)
+#define PLL_BASE_REF_ENABLE            (1<<29)
+#define PLL_BASE_OVERRIDE              (1<<28)
+#define PLL_BASE_LOCK                  (1<<27)
+#define PLL_BASE_DIVP_MASK             (0x7<<20)
+#define PLL_BASE_DIVP_SHIFT            20
+#define PLL_BASE_DIVN_MASK             (0x3FF<<8)
+#define PLL_BASE_DIVN_SHIFT            8
+#define PLL_BASE_DIVM_MASK             (0x1F)
+#define PLL_BASE_DIVM_SHIFT            0
+
+#define PLL_OUT_RATIO_MASK             (0xFF<<8)
+#define PLL_OUT_RATIO_SHIFT            8
+#define PLL_OUT_OVERRIDE               (1<<2)
+#define PLL_OUT_CLKEN                  (1<<1)
+#define PLL_OUT_RESET_DISABLE          (1<<0)
+
+#define PLL_MISC(c)                    \
+       (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
+#define PLL_MISC_LOCK_ENABLE(c)        \
+       (((c)->flags & (PLLU | PLLD)) ? (1<<22) : (1<<18))
+
+#define PLL_MISC_DCCON_SHIFT           20
+#define PLL_MISC_CPCON_SHIFT           8
+#define PLL_MISC_CPCON_MASK            (0xF<<PLL_MISC_CPCON_SHIFT)
+#define PLL_MISC_LFCON_SHIFT           4
+#define PLL_MISC_LFCON_MASK            (0xF<<PLL_MISC_LFCON_SHIFT)
+#define PLL_MISC_VCOCON_SHIFT          0
+#define PLL_MISC_VCOCON_MASK           (0xF<<PLL_MISC_VCOCON_SHIFT)
+#define PLLD_MISC_CLKENABLE            (1<<30)
+
+#define PLLU_BASE_POST_DIV             (1<<20)
+
+#define PLLD_BASE_DSIB_MUX_SHIFT       25
+#define PLLD_BASE_DSIB_MUX_MASK                (1<<PLLD_BASE_DSIB_MUX_SHIFT)
+#define PLLD_BASE_CSI_CLKENABLE                (1<<26)
+#define PLLD_MISC_DSI_CLKENABLE                (1<<30)
+#define PLLD_MISC_DIV_RST              (1<<23)
+#define PLLD_MISC_DCCON_SHIFT          12
+
+#define PLLDU_LFCON_SET_DIVN           600
+
+/* FIXME: OUT_OF_TABLE_CPCON per pll */
+#define OUT_OF_TABLE_CPCON             0x8
+
+#define SUPER_CLK_MUX                  0x00
+#define SUPER_STATE_SHIFT              28
+#define SUPER_STATE_MASK               (0xF << SUPER_STATE_SHIFT)
+#define SUPER_STATE_STANDBY            (0x0 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_IDLE               (0x1 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_RUN                        (0x2 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_IRQ                        (0x3 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_FIQ                        (0x4 << SUPER_STATE_SHIFT)
+#define SUPER_LP_DIV2_BYPASS           (0x1 << 16)
+#define SUPER_SOURCE_MASK              0xF
+#define        SUPER_FIQ_SOURCE_SHIFT          12
+#define        SUPER_IRQ_SOURCE_SHIFT          8
+#define        SUPER_RUN_SOURCE_SHIFT          4
+#define        SUPER_IDLE_SOURCE_SHIFT         0
+
+#define SUPER_CLK_DIVIDER              0x04
+#define SUPER_CLOCK_DIV_U71_SHIFT      16
+#define SUPER_CLOCK_DIV_U71_MASK       (0xff << SUPER_CLOCK_DIV_U71_SHIFT)
+/* guarantees safe cpu backup */
+#define SUPER_CLOCK_DIV_U71_MIN                0x2
+
+#define BUS_CLK_DISABLE                        (1<<3)
+#define BUS_CLK_DIV_MASK               0x3
+
+#define PMC_CTRL                       0x0
+ #define PMC_CTRL_BLINK_ENB            (1 << 7)
+
+#define PMC_DPD_PADS_ORIDE             0x1c
+ #define PMC_DPD_PADS_ORIDE_BLINK_ENB  (1 << 20)
+
+#define PMC_BLINK_TIMER_DATA_ON_SHIFT  0
+#define PMC_BLINK_TIMER_DATA_ON_MASK   0x7fff
+#define PMC_BLINK_TIMER_ENB            (1 << 15)
+#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16
+#define PMC_BLINK_TIMER_DATA_OFF_MASK  0xffff
+
+#define PMC_PLLP_WB0_OVERRIDE                          0xf8
+#define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE              (1 << 12)
+
+#define UTMIP_PLL_CFG2                                 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x)                 (((x) & 0xfff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x)             (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN       (1 << 0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN       (1 << 2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN       (1 << 4)
+
+#define UTMIP_PLL_CFG1                                 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x)             (((x) & 0x1f) << 27)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x)              (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN      (1 << 14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN      (1 << 12)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN            (1 << 16)
+
+#define PLLE_BASE_CML_ENABLE           (1<<31)
+#define PLLE_BASE_ENABLE               (1<<30)
+#define PLLE_BASE_DIVCML_SHIFT         24
+#define PLLE_BASE_DIVCML_MASK          (0xf<<PLLE_BASE_DIVCML_SHIFT)
+#define PLLE_BASE_DIVP_SHIFT           16
+#define PLLE_BASE_DIVP_MASK            (0x3f<<PLLE_BASE_DIVP_SHIFT)
+#define PLLE_BASE_DIVN_SHIFT           8
+#define PLLE_BASE_DIVN_MASK            (0xFF<<PLLE_BASE_DIVN_SHIFT)
+#define PLLE_BASE_DIVM_SHIFT           0
+#define PLLE_BASE_DIVM_MASK            (0xFF<<PLLE_BASE_DIVM_SHIFT)
+#define PLLE_BASE_DIV_MASK             \
+       (PLLE_BASE_DIVCML_MASK | PLLE_BASE_DIVP_MASK | \
+        PLLE_BASE_DIVN_MASK | PLLE_BASE_DIVM_MASK)
+#define PLLE_BASE_DIV(m, n, p, cml)            \
+        (((cml)<<PLLE_BASE_DIVCML_SHIFT) | ((p)<<PLLE_BASE_DIVP_SHIFT) | \
+         ((n)<<PLLE_BASE_DIVN_SHIFT) | ((m)<<PLLE_BASE_DIVM_SHIFT))
+
+#define PLLE_MISC_SETUP_BASE_SHIFT     16
+#define PLLE_MISC_SETUP_BASE_MASK      (0xFFFF<<PLLE_MISC_SETUP_BASE_SHIFT)
+#define PLLE_MISC_READY                        (1<<15)
+#define PLLE_MISC_LOCK                 (1<<11)
+#define PLLE_MISC_LOCK_ENABLE          (1<<9)
+#define PLLE_MISC_SETUP_EX_SHIFT       2
+#define PLLE_MISC_SETUP_EX_MASK                (0x3<<PLLE_MISC_SETUP_EX_SHIFT)
+#define PLLE_MISC_SETUP_MASK           \
+         (PLLE_MISC_SETUP_BASE_MASK | PLLE_MISC_SETUP_EX_MASK)
+#define PLLE_MISC_SETUP_VALUE          \
+         ((0x7<<PLLE_MISC_SETUP_BASE_SHIFT) | (0x0<<PLLE_MISC_SETUP_EX_SHIFT))
+
+#define PLLE_SS_CTRL                   0x68
+#define        PLLE_SS_INCINTRV_SHIFT          24
+#define        PLLE_SS_INCINTRV_MASK           (0x3f<<PLLE_SS_INCINTRV_SHIFT)
+#define        PLLE_SS_INC_SHIFT               16
+#define        PLLE_SS_INC_MASK                (0xff<<PLLE_SS_INC_SHIFT)
+#define        PLLE_SS_MAX_SHIFT               0
+#define        PLLE_SS_MAX_MASK                (0x1ff<<PLLE_SS_MAX_SHIFT)
+#define PLLE_SS_COEFFICIENTS_MASK      \
+       (PLLE_SS_INCINTRV_MASK | PLLE_SS_INC_MASK | PLLE_SS_MAX_MASK)
+#define PLLE_SS_COEFFICIENTS_12MHZ     \
+       ((0x18<<PLLE_SS_INCINTRV_SHIFT) | (0x1<<PLLE_SS_INC_SHIFT) | \
+        (0x24<<PLLE_SS_MAX_SHIFT))
+#define PLLE_SS_DISABLE                        ((1<<12) | (1<<11) | (1<<10))
+
+#define PLLE_AUX                       0x48c
+#define PLLE_AUX_PLLP_SEL              (1<<2)
+#define PLLE_AUX_CML_SATA_ENABLE       (1<<1)
+#define PLLE_AUX_CML_PCIE_ENABLE       (1<<0)
+
+#define        PMC_SATA_PWRGT                  0x1ac
+#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE (1<<5)
+#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL (1<<4)
+
+#define ROUND_DIVIDER_UP       0
+#define ROUND_DIVIDER_DOWN     1
+
+/* FIXME: recommended safety delay after lock is detected */
+#define PLL_POST_LOCK_DELAY            100
+
+/**
+* Structure defining the fields for USB UTMI clocks Parameters.
+*/
+struct utmi_clk_param {
+       /* Oscillator Frequency in KHz */
+       u32 osc_frequency;
+       /* UTMIP PLL Enable Delay Count  */
+       u8 enable_delay_count;
+       /* UTMIP PLL Stable count */
+       u8 stable_count;
+       /*  UTMIP PLL Active delay count */
+       u8 active_delay_count;
+       /* UTMIP PLL Xtal frequency count */
+       u8 xtal_freq_count;
+};
+
+static const struct utmi_clk_param utmi_parameters[] = {
+       {
+               .osc_frequency = 13000000,
+               .enable_delay_count = 0x02,
+               .stable_count = 0x33,
+               .active_delay_count = 0x05,
+               .xtal_freq_count = 0x7F
+       },
+       {
+               .osc_frequency = 19200000,
+               .enable_delay_count = 0x03,
+               .stable_count = 0x4B,
+               .active_delay_count = 0x06,
+               .xtal_freq_count = 0xBB},
+       {
+               .osc_frequency = 12000000,
+               .enable_delay_count = 0x02,
+               .stable_count = 0x2F,
+               .active_delay_count = 0x04,
+               .xtal_freq_count = 0x76
+       },
+       {
+               .osc_frequency = 26000000,
+               .enable_delay_count = 0x04,
+               .stable_count = 0x66,
+               .active_delay_count = 0x09,
+               .xtal_freq_count = 0xFE
+       },
+       {
+               .osc_frequency = 16800000,
+               .enable_delay_count = 0x03,
+               .stable_count = 0x41,
+               .active_delay_count = 0x0A,
+               .xtal_freq_count = 0xA4
+       },
+};
+
+static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
+static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+static void __iomem *misc_gp_hidrev_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
+
+#define MISC_GP_HIDREV                  0x804
+
+/*
+ * Some peripheral clocks share an enable bit, so refcount the enable bits
+ * in registers CLK_ENABLE_L, ... CLK_ENABLE_W
+ */
+static int tegra_periph_clk_enable_refcount[CLK_OUT_ENB_NUM * 32];
+
+#define clk_writel(value, reg) \
+       __raw_writel(value, (u32)reg_clk_base + (reg))
+#define clk_readl(reg) \
+       __raw_readl((u32)reg_clk_base + (reg))
+#define pmc_writel(value, reg) \
+       __raw_writel(value, (u32)reg_pmc_base + (reg))
+#define pmc_readl(reg) \
+       __raw_readl((u32)reg_pmc_base + (reg))
+#define chipid_readl() \
+       __raw_readl((u32)misc_gp_hidrev_base + MISC_GP_HIDREV)
+
+#define clk_writel_delay(value, reg)                                   \
+       do {                                                            \
+               __raw_writel((value), (u32)reg_clk_base + (reg));       \
+               udelay(2);                                              \
+       } while (0)
+
+
+static inline int clk_set_div(struct clk *c, u32 n)
+{
+       return clk_set_rate(c, (clk_get_rate(c->parent) + n-1) / n);
+}
+
+static inline u32 periph_clk_to_reg(
+       struct clk *c, u32 reg_L, u32 reg_V, int offs)
+{
+       u32 reg = c->u.periph.clk_num / 32;
+       BUG_ON(reg >= RST_DEVICES_NUM);
+       if (reg < 3)
+               reg = reg_L + (reg * offs);
+       else
+               reg = reg_V + ((reg - 3) * offs);
+       return reg;
+}
+
+static unsigned long clk_measure_input_freq(void)
+{
+       u32 clock_autodetect;
+       clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
+       do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
+       clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
+       if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
+               return 12000000;
+       } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
+               return 13000000;
+       } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
+               return 19200000;
+       } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
+               return 26000000;
+       } else if (clock_autodetect >= 1025 - 3 && clock_autodetect <= 1025 + 3) {
+               return 16800000;
+       } else if (clock_autodetect >= 2344 - 3 && clock_autodetect <= 2344 + 3) {
+               return 38400000;
+       } else if (clock_autodetect >= 2928 - 3 && clock_autodetect <= 2928 + 3) {
+               return 48000000;
+       } else {
+               pr_err("%s: Unexpected clock autodetect value %d", __func__,
+                       clock_autodetect);
+               BUG();
+               return 0;
+       }
+}
+
+static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate,
+                                u32 flags, u32 round_mode)
+{
+       s64 divider_u71 = parent_rate;
+       if (!rate)
+               return -EINVAL;
+
+       if (!(flags & DIV_U71_INT))
+               divider_u71 *= 2;
+       if (round_mode == ROUND_DIVIDER_UP)
+               divider_u71 += rate - 1;
+       do_div(divider_u71, rate);
+       if (flags & DIV_U71_INT)
+               divider_u71 *= 2;
+
+       if (divider_u71 - 2 < 0)
+               return 0;
+
+       if (divider_u71 - 2 > 255)
+               return -EINVAL;
+
+       return divider_u71 - 2;
+}
+
+static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
+{
+       s64 divider_u16;
+
+       divider_u16 = parent_rate;
+       if (!rate)
+               return -EINVAL;
+       divider_u16 += rate - 1;
+       do_div(divider_u16, rate);
+
+       if (divider_u16 - 1 < 0)
+               return 0;
+
+       if (divider_u16 - 1 > 0xFFFF)
+               return -EINVAL;
+
+       return divider_u16 - 1;
+}
+
+/* clk_m functions */
+static unsigned long tegra30_clk_m_autodetect_rate(struct clk *c)
+{
+       u32 osc_ctrl = clk_readl(OSC_CTRL);
+       u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK;
+       u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK;
+
+       c->rate = clk_measure_input_freq();
+       switch (c->rate) {
+       case 12000000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
+               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+               break;
+       case 13000000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
+               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+               break;
+       case 19200000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
+               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+               break;
+       case 26000000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
+               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+               break;
+       case 16800000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_16_8MHZ;
+               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+               break;
+       case 38400000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_38_4MHZ;
+               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_2);
+               break;
+       case 48000000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_48MHZ;
+               BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4);
+               break;
+       default:
+               pr_err("%s: Unexpected clock rate %ld", __func__, c->rate);
+               BUG();
+       }
+       clk_writel(auto_clock_control, OSC_CTRL);
+       return c->rate;
+}
+
+static void tegra30_clk_m_init(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       tegra30_clk_m_autodetect_rate(c);
+}
+
+static int tegra30_clk_m_enable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       return 0;
+}
+
+static void tegra30_clk_m_disable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       WARN(1, "Attempting to disable main SoC clock\n");
+}
+
+static struct clk_ops tegra_clk_m_ops = {
+       .init           = tegra30_clk_m_init,
+       .enable         = tegra30_clk_m_enable,
+       .disable        = tegra30_clk_m_disable,
+};
+
+static struct clk_ops tegra_clk_m_div_ops = {
+       .enable         = tegra30_clk_m_enable,
+};
+
+/* PLL reference divider functions */
+static void tegra30_pll_ref_init(struct clk *c)
+{
+       u32 pll_ref_div = clk_readl(OSC_CTRL) & OSC_CTRL_PLL_REF_DIV_MASK;
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       switch (pll_ref_div) {
+       case OSC_CTRL_PLL_REF_DIV_1:
+               c->div = 1;
+               break;
+       case OSC_CTRL_PLL_REF_DIV_2:
+               c->div = 2;
+               break;
+       case OSC_CTRL_PLL_REF_DIV_4:
+               c->div = 4;
+               break;
+       default:
+               pr_err("%s: Invalid pll ref divider %d", __func__, pll_ref_div);
+               BUG();
+       }
+       c->mul = 1;
+       c->state = ON;
+}
+
+static struct clk_ops tegra_pll_ref_ops = {
+       .init           = tegra30_pll_ref_init,
+       .enable         = tegra30_clk_m_enable,
+       .disable        = tegra30_clk_m_disable,
+};
+
+/* super clock functions */
+/* "super clocks" on tegra30 have two-stage muxes, fractional 7.1 divider and
+ * clock skipping super divider.  We will ignore the clock skipping divider,
+ * since we can't lower the voltage when using the clock skip, but we can if
+ * we lower the PLL frequency. We will use 7.1 divider for CPU super-clock
+ * only when its parent is a fixed rate PLL, since we can't change PLL rate
+ * in this case.
+ */
+static void tegra30_super_clk_init(struct clk *c)
+{
+       u32 val;
+       int source;
+       int shift;
+       const struct clk_mux_sel *sel;
+       val = clk_readl(c->reg + SUPER_CLK_MUX);
+       c->state = ON;
+       BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+               ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+       shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+               SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+       source = (val >> shift) & SUPER_SOURCE_MASK;
+       if (c->flags & DIV_2)
+               source |= val & SUPER_LP_DIV2_BYPASS;
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->value == source)
+                       break;
+       }
+       BUG_ON(sel->input == NULL);
+       c->parent = sel->input;
+
+       if (c->flags & DIV_U71) {
+               /* Init safe 7.1 divider value (does not affect PLLX path) */
+               clk_writel(SUPER_CLOCK_DIV_U71_MIN << SUPER_CLOCK_DIV_U71_SHIFT,
+                          c->reg + SUPER_CLK_DIVIDER);
+               c->mul = 2;
+               c->div = 2;
+               if (!(c->parent->flags & PLLX))
+                       c->div += SUPER_CLOCK_DIV_U71_MIN;
+       } else
+               clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
+}
+
+static int tegra30_super_clk_enable(struct clk *c)
+{
+       return 0;
+}
+
+static void tegra30_super_clk_disable(struct clk *c)
+{
+       /* since tegra 3 has 2 CPU super clocks - low power lp-mode clock and
+          geared up g-mode super clock - mode switch may request to disable
+          either of them; accept request with no affect on h/w */
+}
+
+static int tegra30_super_clk_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       const struct clk_mux_sel *sel;
+       int shift;
+
+       val = clk_readl(c->reg + SUPER_CLK_MUX);
+       BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+               ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+       shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+               SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       /* For LP mode super-clock switch between PLLX direct
+                          and divided-by-2 outputs is allowed only when other
+                          than PLLX clock source is current parent */
+                       if ((c->flags & DIV_2) && (p->flags & PLLX) &&
+                           ((sel->value ^ val) & SUPER_LP_DIV2_BYPASS)) {
+                               if (c->parent->flags & PLLX)
+                                       return -EINVAL;
+                               val ^= SUPER_LP_DIV2_BYPASS;
+                               clk_writel_delay(val, c->reg);
+                       }
+                       val &= ~(SUPER_SOURCE_MASK << shift);
+                       val |= (sel->value & SUPER_SOURCE_MASK) << shift;
+
+                       /* 7.1 divider for CPU super-clock does not affect
+                          PLLX path */
+                       if (c->flags & DIV_U71) {
+                               u32 div = 0;
+                               if (!(p->flags & PLLX)) {
+                                       div = clk_readl(c->reg +
+                                                       SUPER_CLK_DIVIDER);
+                                       div &= SUPER_CLOCK_DIV_U71_MASK;
+                                       div >>= SUPER_CLOCK_DIV_U71_SHIFT;
+                               }
+                               c->div = div + 2;
+                               c->mul = 2;
+                       }
+
+                       if (c->refcnt)
+                               clk_enable(p);
+
+                       clk_writel_delay(val, c->reg);
+
+                       if (c->refcnt && c->parent)
+                               clk_disable(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+/*
+ * Do not use super clocks "skippers", since dividing using a clock skipper
+ * does not allow the voltage to be scaled down. Instead adjust the rate of
+ * the parent clock. This requires that the parent of a super clock have no
+ * other children, otherwise the rate will change underneath the other
+ * children. Special case: if fixed rate PLL is CPU super clock parent the
+ * rate of this PLL can't be changed, and it has many other children. In
+ * this case use 7.1 fractional divider to adjust the super clock rate.
+ */
+static int tegra30_super_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       if ((c->flags & DIV_U71) && (c->parent->flags & PLL_FIXED)) {
+               int div = clk_div71_get_divider(c->parent->u.pll.fixed_rate,
+                                       rate, c->flags, ROUND_DIVIDER_DOWN);
+               div = max(div, SUPER_CLOCK_DIV_U71_MIN);
+
+               clk_writel(div << SUPER_CLOCK_DIV_U71_SHIFT,
+                          c->reg + SUPER_CLK_DIVIDER);
+               c->div = div + 2;
+               c->mul = 2;
+               return 0;
+       }
+       return clk_set_rate(c->parent, rate);
+}
+
+static struct clk_ops tegra_super_ops = {
+       .init                   = tegra30_super_clk_init,
+       .enable                 = tegra30_super_clk_enable,
+       .disable                = tegra30_super_clk_disable,
+       .set_parent             = tegra30_super_clk_set_parent,
+       .set_rate               = tegra30_super_clk_set_rate,
+};
+
+static int tegra30_twd_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       /* The input value 'rate' is the clock rate of the CPU complex. */
+       c->rate = (rate * c->mul) / c->div;
+       return 0;
+}
+
+static struct clk_ops tegra30_twd_ops = {
+       .set_rate       = tegra30_twd_clk_set_rate,
+};
+
+/* Blink output functions */
+
+static void tegra30_blink_clk_init(struct clk *c)
+{
+       u32 val;
+
+       val = pmc_readl(PMC_CTRL);
+       c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
+       c->mul = 1;
+       val = pmc_readl(c->reg);
+
+       if (val & PMC_BLINK_TIMER_ENB) {
+               unsigned int on_off;
+
+               on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
+                       PMC_BLINK_TIMER_DATA_ON_MASK;
+               val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+               val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+               on_off += val;
+               /* each tick in the blink timer is 4 32KHz clocks */
+               c->div = on_off * 4;
+       } else {
+               c->div = 1;
+       }
+}
+
+static int tegra30_blink_clk_enable(struct clk *c)
+{
+       u32 val;
+
+       val = pmc_readl(PMC_DPD_PADS_ORIDE);
+       pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+
+       val = pmc_readl(PMC_CTRL);
+       pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
+
+       return 0;
+}
+
+static void tegra30_blink_clk_disable(struct clk *c)
+{
+       u32 val;
+
+       val = pmc_readl(PMC_CTRL);
+       pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
+
+       val = pmc_readl(PMC_DPD_PADS_ORIDE);
+       pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+}
+
+static int tegra30_blink_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(c->parent);
+       if (rate >= parent_rate) {
+               c->div = 1;
+               pmc_writel(0, c->reg);
+       } else {
+               unsigned int on_off;
+               u32 val;
+
+               on_off = DIV_ROUND_UP(parent_rate / 8, rate);
+               c->div = on_off * 8;
+
+               val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
+                       PMC_BLINK_TIMER_DATA_ON_SHIFT;
+               on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+               on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+               val |= on_off;
+               val |= PMC_BLINK_TIMER_ENB;
+               pmc_writel(val, c->reg);
+       }
+
+       return 0;
+}
+
+static struct clk_ops tegra_blink_clk_ops = {
+       .init                   = &tegra30_blink_clk_init,
+       .enable                 = &tegra30_blink_clk_enable,
+       .disable                = &tegra30_blink_clk_disable,
+       .set_rate               = &tegra30_blink_clk_set_rate,
+};
+
+/* PLL Functions */
+static int tegra30_pll_clk_wait_for_lock(struct clk *c, u32 lock_reg,
+                                        u32 lock_bit)
+{
+#if USE_PLL_LOCK_BITS
+       int i;
+       for (i = 0; i < c->u.pll.lock_delay; i++) {
+               if (clk_readl(lock_reg) & lock_bit) {
+                       udelay(PLL_POST_LOCK_DELAY);
+                       return 0;
+               }
+               udelay(2);              /* timeout = 2 * lock time */
+       }
+       pr_err("Timed out waiting for lock bit on pll %s", c->name);
+       return -1;
+#endif
+       udelay(c->u.pll.lock_delay);
+
+       return 0;
+}
+
+
+static void tegra30_utmi_param_configure(struct clk *c)
+{
+       u32 reg;
+       int i;
+       unsigned long main_rate =
+               clk_get_rate(c->parent->parent);
+
+       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+               if (main_rate == utmi_parameters[i].osc_frequency)
+                       break;
+       }
+
+       if (i >= ARRAY_SIZE(utmi_parameters)) {
+               pr_err("%s: Unexpected main rate %lu\n", __func__, main_rate);
+               return;
+       }
+
+       reg = clk_readl(UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL stable and active counts */
+       /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
+       reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+       reg |= UTMIP_PLL_CFG2_STABLE_COUNT(
+                       utmi_parameters[i].stable_count);
+
+       reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+
+       reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(
+                       utmi_parameters[i].active_delay_count);
+
+       /* Remove power downs from UTMIP PLL control bits */
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+
+       clk_writel(reg, UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL delay and oscillator frequency counts */
+       reg = clk_readl(UTMIP_PLL_CFG1);
+       reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+
+       reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(
+               utmi_parameters[i].enable_delay_count);
+
+       reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+       reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(
+               utmi_parameters[i].xtal_freq_count);
+
+       /* Remove power downs from UTMIP PLL control bits */
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+
+       clk_writel(reg, UTMIP_PLL_CFG1);
+}
+
+static void tegra30_pll_clk_init(struct clk *c)
+{
+       u32 val = clk_readl(c->reg + PLL_BASE);
+
+       c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
+
+       if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
+               const struct clk_pll_freq_table *sel;
+               unsigned long input_rate = clk_get_rate(c->parent);
+               for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
+                       if (sel->input_rate == input_rate &&
+                               sel->output_rate == c->u.pll.fixed_rate) {
+                               c->mul = sel->n;
+                               c->div = sel->m * sel->p;
+                               return;
+                       }
+               }
+               pr_err("Clock %s has unknown fixed frequency\n", c->name);
+               BUG();
+       } else if (val & PLL_BASE_BYPASS) {
+               c->mul = 1;
+               c->div = 1;
+       } else {
+               c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
+               c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
+               if (c->flags & PLLU)
+                       c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
+               else
+                       c->div *= (0x1 << ((val & PLL_BASE_DIVP_MASK) >>
+                                       PLL_BASE_DIVP_SHIFT));
+               if (c->flags & PLL_FIXED) {
+                       unsigned long rate = clk_get_rate_locked(c);
+                       BUG_ON(rate != c->u.pll.fixed_rate);
+               }
+       }
+
+       if (c->flags & PLLU)
+               tegra30_utmi_param_configure(c);
+}
+
+static int tegra30_pll_clk_enable(struct clk *c)
+{
+       u32 val;
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+#if USE_PLL_LOCK_BITS
+       val = clk_readl(c->reg + PLL_MISC(c));
+       val |= PLL_MISC_LOCK_ENABLE(c);
+       clk_writel(val, c->reg + PLL_MISC(c));
+#endif
+       val = clk_readl(c->reg + PLL_BASE);
+       val &= ~PLL_BASE_BYPASS;
+       val |= PLL_BASE_ENABLE;
+       clk_writel(val, c->reg + PLL_BASE);
+
+       if (c->flags & PLLM) {
+               val = pmc_readl(PMC_PLLP_WB0_OVERRIDE);
+               val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
+               pmc_writel(val, PMC_PLLP_WB0_OVERRIDE);
+       }
+
+       tegra30_pll_clk_wait_for_lock(c, c->reg + PLL_BASE, PLL_BASE_LOCK);
+
+       return 0;
+}
+
+static void tegra30_pll_clk_disable(struct clk *c)
+{
+       u32 val;
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       val = clk_readl(c->reg);
+       val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+       clk_writel(val, c->reg);
+
+       if (c->flags & PLLM) {
+               val = pmc_readl(PMC_PLLP_WB0_OVERRIDE);
+               val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
+               pmc_writel(val, PMC_PLLP_WB0_OVERRIDE);
+       }
+}
+
+static int tegra30_pll_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       u32 val, p_div, old_base;
+       unsigned long input_rate;
+       const struct clk_pll_freq_table *sel;
+       struct clk_pll_freq_table cfg;
+
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+       if (c->flags & PLL_FIXED) {
+               int ret = 0;
+               if (rate != c->u.pll.fixed_rate) {
+                       pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
+                              __func__, c->name, c->u.pll.fixed_rate, rate);
+                       ret = -EINVAL;
+               }
+               return ret;
+       }
+
+       if (c->flags & PLLM) {
+               if (rate != clk_get_rate_locked(c)) {
+                       pr_err("%s: Can not change memory %s rate in flight\n",
+                              __func__, c->name);
+                       return -EINVAL;
+               }
+               return 0;
+       }
+
+       p_div = 0;
+       input_rate = clk_get_rate(c->parent);
+
+       /* Check if the target rate is tabulated */
+       for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
+               if (sel->input_rate == input_rate && sel->output_rate == rate) {
+                       if (c->flags & PLLU) {
+                               BUG_ON(sel->p < 1 || sel->p > 2);
+                               if (sel->p == 1)
+                                       p_div = PLLU_BASE_POST_DIV;
+                       } else {
+                               BUG_ON(sel->p < 1);
+                               for (val = sel->p; val > 1; val >>= 1)
+                                       p_div++;
+                               p_div <<= PLL_BASE_DIVP_SHIFT;
+                       }
+                       break;
+               }
+       }
+
+       /* Configure out-of-table rate */
+       if (sel->input_rate == 0) {
+               unsigned long cfreq;
+               BUG_ON(c->flags & PLLU);
+               sel = &cfg;
+
+               switch (input_rate) {
+               case 12000000:
+               case 26000000:
+                       cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000;
+                       break;
+               case 13000000:
+                       cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000;
+                       break;
+               case 16800000:
+               case 19200000:
+                       cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000;
+                       break;
+               default:
+                       pr_err("%s: Unexpected reference rate %lu\n",
+                              __func__, input_rate);
+                       BUG();
+               }
+
+               /* Raise VCO to guarantee 0.5% accuracy */
+               for (cfg.output_rate = rate; cfg.output_rate < 200 * cfreq;
+                     cfg.output_rate <<= 1)
+                       p_div++;
+
+               cfg.p = 0x1 << p_div;
+               cfg.m = input_rate / cfreq;
+               cfg.n = cfg.output_rate / cfreq;
+               cfg.cpcon = OUT_OF_TABLE_CPCON;
+
+               if ((cfg.m > (PLL_BASE_DIVM_MASK >> PLL_BASE_DIVM_SHIFT)) ||
+                   (cfg.n > (PLL_BASE_DIVN_MASK >> PLL_BASE_DIVN_SHIFT)) ||
+                   (p_div > (PLL_BASE_DIVP_MASK >> PLL_BASE_DIVP_SHIFT)) ||
+                   (cfg.output_rate > c->u.pll.vco_max)) {
+                       pr_err("%s: Failed to set %s out-of-table rate %lu\n",
+                              __func__, c->name, rate);
+                       return -EINVAL;
+               }
+               p_div <<= PLL_BASE_DIVP_SHIFT;
+       }
+
+       c->mul = sel->n;
+       c->div = sel->m * sel->p;
+
+       old_base = val = clk_readl(c->reg + PLL_BASE);
+       val &= ~(PLL_BASE_DIVM_MASK | PLL_BASE_DIVN_MASK |
+                ((c->flags & PLLU) ? PLLU_BASE_POST_DIV : PLL_BASE_DIVP_MASK));
+       val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
+               (sel->n << PLL_BASE_DIVN_SHIFT) | p_div;
+       if (val == old_base)
+               return 0;
+
+       if (c->state == ON) {
+               tegra30_pll_clk_disable(c);
+               val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+       }
+       clk_writel(val, c->reg + PLL_BASE);
+
+       if (c->flags & PLL_HAS_CPCON) {
+               val = clk_readl(c->reg + PLL_MISC(c));
+               val &= ~PLL_MISC_CPCON_MASK;
+               val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
+               if (c->flags & (PLLU | PLLD)) {
+                       val &= ~PLL_MISC_LFCON_MASK;
+                       if (sel->n >= PLLDU_LFCON_SET_DIVN)
+                               val |= 0x1 << PLL_MISC_LFCON_SHIFT;
+               } else if (c->flags & (PLLX | PLLM)) {
+                       val &= ~(0x1 << PLL_MISC_DCCON_SHIFT);
+                       if (rate >= (c->u.pll.vco_max >> 1))
+                               val |= 0x1 << PLL_MISC_DCCON_SHIFT;
+               }
+               clk_writel(val, c->reg + PLL_MISC(c));
+       }
+
+       if (c->state == ON)
+               tegra30_pll_clk_enable(c);
+
+       return 0;
+}
+
+static struct clk_ops tegra_pll_ops = {
+       .init                   = tegra30_pll_clk_init,
+       .enable                 = tegra30_pll_clk_enable,
+       .disable                = tegra30_pll_clk_disable,
+       .set_rate               = tegra30_pll_clk_set_rate,
+};
+
+static int
+tegra30_plld_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+{
+       u32 val, mask, reg;
+
+       switch (p) {
+       case TEGRA_CLK_PLLD_CSI_OUT_ENB:
+               mask = PLLD_BASE_CSI_CLKENABLE;
+               reg = c->reg + PLL_BASE;
+               break;
+       case TEGRA_CLK_PLLD_DSI_OUT_ENB:
+               mask = PLLD_MISC_DSI_CLKENABLE;
+               reg = c->reg + PLL_MISC(c);
+               break;
+       case TEGRA_CLK_PLLD_MIPI_MUX_SEL:
+               if (!(c->flags & PLL_ALT_MISC_REG)) {
+                       mask = PLLD_BASE_DSIB_MUX_MASK;
+                       reg = c->reg + PLL_BASE;
+                       break;
+               }
+       /* fall through - error since PLLD2 does not have MUX_SEL control */
+       default:
+               return -EINVAL;
+       }
+
+       val = clk_readl(reg);
+       if (setting)
+               val |= mask;
+       else
+               val &= ~mask;
+       clk_writel(val, reg);
+       return 0;
+}
+
+static struct clk_ops tegra_plld_ops = {
+       .init                   = tegra30_pll_clk_init,
+       .enable                 = tegra30_pll_clk_enable,
+       .disable                = tegra30_pll_clk_disable,
+       .set_rate               = tegra30_pll_clk_set_rate,
+       .clk_cfg_ex             = tegra30_plld_clk_cfg_ex,
+};
+
+static void tegra30_plle_clk_init(struct clk *c)
+{
+       u32 val;
+
+       val = clk_readl(PLLE_AUX);
+       c->parent = (val & PLLE_AUX_PLLP_SEL) ?
+               tegra_get_clock_by_name("pll_p") :
+               tegra_get_clock_by_name("pll_ref");
+
+       val = clk_readl(c->reg + PLL_BASE);
+       c->state = (val & PLLE_BASE_ENABLE) ? ON : OFF;
+       c->mul = (val & PLLE_BASE_DIVN_MASK) >> PLLE_BASE_DIVN_SHIFT;
+       c->div = (val & PLLE_BASE_DIVM_MASK) >> PLLE_BASE_DIVM_SHIFT;
+       c->div *= (val & PLLE_BASE_DIVP_MASK) >> PLLE_BASE_DIVP_SHIFT;
+}
+
+static void tegra30_plle_clk_disable(struct clk *c)
+{
+       u32 val;
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       val = clk_readl(c->reg + PLL_BASE);
+       val &= ~(PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE);
+       clk_writel(val, c->reg + PLL_BASE);
+}
+
+static void tegra30_plle_training(struct clk *c)
+{
+       u32 val;
+
+       /* PLLE is already disabled, and setup cleared;
+        * create falling edge on PLLE IDDQ input */
+       val = pmc_readl(PMC_SATA_PWRGT);
+       val |= PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
+       pmc_writel(val, PMC_SATA_PWRGT);
+
+       val = pmc_readl(PMC_SATA_PWRGT);
+       val |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
+       pmc_writel(val, PMC_SATA_PWRGT);
+
+       val = pmc_readl(PMC_SATA_PWRGT);
+       val &= ~PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
+       pmc_writel(val, PMC_SATA_PWRGT);
+
+       do {
+               val = clk_readl(c->reg + PLL_MISC(c));
+       } while (!(val & PLLE_MISC_READY));
+}
+
+static int tegra30_plle_configure(struct clk *c, bool force_training)
+{
+       u32 val;
+       const struct clk_pll_freq_table *sel;
+       unsigned long rate = c->u.pll.fixed_rate;
+       unsigned long input_rate = clk_get_rate(c->parent);
+
+       for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
+               if (sel->input_rate == input_rate && sel->output_rate == rate)
+                       break;
+       }
+
+       if (sel->input_rate == 0)
+               return -ENOSYS;
+
+       /* disable PLLE, clear setup fiels */
+       tegra30_plle_clk_disable(c);
+
+       val = clk_readl(c->reg + PLL_MISC(c));
+       val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK);
+       clk_writel(val, c->reg + PLL_MISC(c));
+
+       /* training */
+       val = clk_readl(c->reg + PLL_MISC(c));
+       if (force_training || (!(val & PLLE_MISC_READY)))
+               tegra30_plle_training(c);
+
+       /* configure dividers, setup, disable SS */
+       val = clk_readl(c->reg + PLL_BASE);
+       val &= ~PLLE_BASE_DIV_MASK;
+       val |= PLLE_BASE_DIV(sel->m, sel->n, sel->p, sel->cpcon);
+       clk_writel(val, c->reg + PLL_BASE);
+       c->mul = sel->n;
+       c->div = sel->m * sel->p;
+
+       val = clk_readl(c->reg + PLL_MISC(c));
+       val |= PLLE_MISC_SETUP_VALUE;
+       val |= PLLE_MISC_LOCK_ENABLE;
+       clk_writel(val, c->reg + PLL_MISC(c));
+
+       val = clk_readl(PLLE_SS_CTRL);
+       val |= PLLE_SS_DISABLE;
+       clk_writel(val, PLLE_SS_CTRL);
+
+       /* enable and lock PLLE*/
+       val = clk_readl(c->reg + PLL_BASE);
+       val |= (PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE);
+       clk_writel(val, c->reg + PLL_BASE);
+
+       tegra30_pll_clk_wait_for_lock(c, c->reg + PLL_MISC(c), PLLE_MISC_LOCK);
+
+       return 0;
+}
+
+static int tegra30_plle_clk_enable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       return tegra30_plle_configure(c, !c->set);
+}
+
+static struct clk_ops tegra_plle_ops = {
+       .init                   = tegra30_plle_clk_init,
+       .enable                 = tegra30_plle_clk_enable,
+       .disable                = tegra30_plle_clk_disable,
+};
+
+/* Clock divider ops */
+static void tegra30_pll_div_clk_init(struct clk *c)
+{
+       if (c->flags & DIV_U71) {
+               u32 divu71;
+               u32 val = clk_readl(c->reg);
+               val >>= c->reg_shift;
+               c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
+               if (!(val & PLL_OUT_RESET_DISABLE))
+                       c->state = OFF;
+
+               divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
+               c->div = (divu71 + 2);
+               c->mul = 2;
+       } else if (c->flags & DIV_2) {
+               c->state = ON;
+               if (c->flags & (PLLD | PLLX)) {
+                       c->div = 2;
+                       c->mul = 1;
+               } else
+                       BUG();
+       } else {
+               c->state = ON;
+               c->div = 1;
+               c->mul = 1;
+       }
+}
+
+static int tegra30_pll_div_clk_enable(struct clk *c)
+{
+       u32 val;
+       u32 new_val;
+
+       pr_debug("%s: %s\n", __func__, c->name);
+       if (c->flags & DIV_U71) {
+               val = clk_readl(c->reg);
+               new_val = val >> c->reg_shift;
+               new_val &= 0xFFFF;
+
+               new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
+
+               val &= ~(0xFFFF << c->reg_shift);
+               val |= new_val << c->reg_shift;
+               clk_writel_delay(val, c->reg);
+               return 0;
+       } else if (c->flags & DIV_2) {
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static void tegra30_pll_div_clk_disable(struct clk *c)
+{
+       u32 val;
+       u32 new_val;
+
+       pr_debug("%s: %s\n", __func__, c->name);
+       if (c->flags & DIV_U71) {
+               val = clk_readl(c->reg);
+               new_val = val >> c->reg_shift;
+               new_val &= 0xFFFF;
+
+               new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
+
+               val &= ~(0xFFFF << c->reg_shift);
+               val |= new_val << c->reg_shift;
+               clk_writel_delay(val, c->reg);
+       }
+}
+
+static int tegra30_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       u32 val;
+       u32 new_val;
+       int divider_u71;
+       unsigned long parent_rate = clk_get_rate(c->parent);
+
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+       if (c->flags & DIV_U71) {
+               divider_u71 = clk_div71_get_divider(
+                       parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
+               if (divider_u71 >= 0) {
+                       val = clk_readl(c->reg);
+                       new_val = val >> c->reg_shift;
+                       new_val &= 0xFFFF;
+                       if (c->flags & DIV_U71_FIXED)
+                               new_val |= PLL_OUT_OVERRIDE;
+                       new_val &= ~PLL_OUT_RATIO_MASK;
+                       new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
+
+                       val &= ~(0xFFFF << c->reg_shift);
+                       val |= new_val << c->reg_shift;
+                       clk_writel_delay(val, c->reg);
+                       c->div = divider_u71 + 2;
+                       c->mul = 2;
+                       return 0;
+               }
+       } else if (c->flags & DIV_2)
+               return clk_set_rate(c->parent, rate * 2);
+
+       return -EINVAL;
+}
+
+static long tegra30_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
+{
+       int divider;
+       unsigned long parent_rate = clk_get_rate(c->parent);
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+       if (c->flags & DIV_U71) {
+               divider = clk_div71_get_divider(
+                       parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
+               if (divider < 0)
+                       return divider;
+               return DIV_ROUND_UP(parent_rate * 2, divider + 2);
+       } else if (c->flags & DIV_2)
+               /* no rounding - fixed DIV_2 dividers pass rate to parent PLL */
+               return rate;
+
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_pll_div_ops = {
+       .init                   = tegra30_pll_div_clk_init,
+       .enable                 = tegra30_pll_div_clk_enable,
+       .disable                = tegra30_pll_div_clk_disable,
+       .set_rate               = tegra30_pll_div_clk_set_rate,
+       .round_rate             = tegra30_pll_div_clk_round_rate,
+};
+
+/* Periph clk ops */
+static inline u32 periph_clk_source_mask(struct clk *c)
+{
+       if (c->flags & MUX8)
+               return 7 << 29;
+       else if (c->flags & MUX_PWM)
+               return 3 << 28;
+       else if (c->flags & MUX_CLK_OUT)
+               return 3 << (c->u.periph.clk_num + 4);
+       else if (c->flags & PLLD)
+               return PLLD_BASE_DSIB_MUX_MASK;
+       else
+               return 3 << 30;
+}
+
+static inline u32 periph_clk_source_shift(struct clk *c)
+{
+       if (c->flags & MUX8)
+               return 29;
+       else if (c->flags & MUX_PWM)
+               return 28;
+       else if (c->flags & MUX_CLK_OUT)
+               return c->u.periph.clk_num + 4;
+       else if (c->flags & PLLD)
+               return PLLD_BASE_DSIB_MUX_SHIFT;
+       else
+               return 30;
+}
+
+static void tegra30_periph_clk_init(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       const struct clk_mux_sel *mux = 0;
+       const struct clk_mux_sel *sel;
+       if (c->flags & MUX) {
+               for (sel = c->inputs; sel->input != NULL; sel++) {
+                       if (((val & periph_clk_source_mask(c)) >>
+                           periph_clk_source_shift(c)) == sel->value)
+                               mux = sel;
+               }
+               BUG_ON(!mux);
+
+               c->parent = mux->input;
+       } else {
+               c->parent = c->inputs[0].input;
+       }
+
+       if (c->flags & DIV_U71) {
+               u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
+               if ((c->flags & DIV_U71_UART) &&
+                   (!(val & PERIPH_CLK_UART_DIV_ENB))) {
+                       divu71 = 0;
+               }
+               if (c->flags & DIV_U71_IDLE) {
+                       val &= ~(PERIPH_CLK_SOURCE_DIVU71_MASK <<
+                               PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
+                       val |= (PERIPH_CLK_SOURCE_DIVIDLE_VAL <<
+                               PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
+                       clk_writel(val, c->reg);
+               }
+               c->div = divu71 + 2;
+               c->mul = 2;
+       } else if (c->flags & DIV_U16) {
+               u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
+               c->div = divu16 + 1;
+               c->mul = 1;
+       } else {
+               c->div = 1;
+               c->mul = 1;
+       }
+
+       c->state = ON;
+       if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
+               c->state = OFF;
+       if (!(c->flags & PERIPH_NO_RESET))
+               if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c))
+                       c->state = OFF;
+}
+
+static int tegra30_periph_clk_enable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
+       if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1)
+               return 0;
+
+       clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_SET_REG(c));
+       if (!(c->flags & PERIPH_NO_RESET) &&
+                !(c->flags & PERIPH_MANUAL_RESET)) {
+               if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) &
+                        PERIPH_CLK_TO_BIT(c)) {
+                       udelay(5);      /* reset propagation delay */
+                       clk_writel(PERIPH_CLK_TO_BIT(c),
+                                PERIPH_CLK_TO_RST_CLR_REG(c));
+               }
+       }
+       return 0;
+}
+
+static void tegra30_periph_clk_disable(struct clk *c)
+{
+       unsigned long val;
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       if (c->refcnt)
+               tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
+
+       if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0) {
+               /* If peripheral is in the APB bus then read the APB bus to
+                * flush the write operation in apb bus. This will avoid the
+                * peripheral access after disabling clock*/
+               if (c->flags & PERIPH_ON_APB)
+                       val = chipid_readl();
+
+               clk_writel_delay(
+                       PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c));
+       }
+}
+
+static void tegra30_periph_clk_reset(struct clk *c, bool assert)
+{
+       unsigned long val;
+       pr_debug("%s %s on clock %s\n", __func__,
+                assert ? "assert" : "deassert", c->name);
+
+       if (!(c->flags & PERIPH_NO_RESET)) {
+               if (assert) {
+                       /* If peripheral is in the APB bus then read the APB
+                        * bus to flush the write operation in apb bus. This
+                        * will avoid the peripheral access after disabling
+                        * clock */
+                       if (c->flags & PERIPH_ON_APB)
+                               val = chipid_readl();
+
+                       clk_writel(PERIPH_CLK_TO_BIT(c),
+                                  PERIPH_CLK_TO_RST_SET_REG(c));
+               } else
+                       clk_writel(PERIPH_CLK_TO_BIT(c),
+                                  PERIPH_CLK_TO_RST_CLR_REG(c));
+       }
+}
+
+static int tegra30_periph_clk_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       const struct clk_mux_sel *sel;
+       pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+
+       if (!(c->flags & MUX))
+               return (p == c->parent) ? 0 : (-EINVAL);
+
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       val = clk_readl(c->reg);
+                       val &= ~periph_clk_source_mask(c);
+                       val |= (sel->value << periph_clk_source_shift(c));
+
+                       if (c->refcnt)
+                               clk_enable(p);
+
+                       clk_writel_delay(val, c->reg);
+
+                       if (c->refcnt && c->parent)
+                               clk_disable(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int tegra30_periph_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       u32 val;
+       int divider;
+       unsigned long parent_rate = clk_get_rate(c->parent);
+
+       if (c->flags & DIV_U71) {
+               divider = clk_div71_get_divider(
+                       parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
+               if (divider >= 0) {
+                       val = clk_readl(c->reg);
+                       val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
+                       val |= divider;
+                       if (c->flags & DIV_U71_UART) {
+                               if (divider)
+                                       val |= PERIPH_CLK_UART_DIV_ENB;
+                               else
+                                       val &= ~PERIPH_CLK_UART_DIV_ENB;
+                       }
+                       clk_writel_delay(val, c->reg);
+                       c->div = divider + 2;
+                       c->mul = 2;
+                       return 0;
+               }
+       } else if (c->flags & DIV_U16) {
+               divider = clk_div16_get_divider(parent_rate, rate);
+               if (divider >= 0) {
+                       val = clk_readl(c->reg);
+                       val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
+                       val |= divider;
+                       clk_writel_delay(val, c->reg);
+                       c->div = divider + 1;
+                       c->mul = 1;
+                       return 0;
+               }
+       } else if (parent_rate <= rate) {
+               c->div = 1;
+               c->mul = 1;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static long tegra30_periph_clk_round_rate(struct clk *c,
+       unsigned long rate)
+{
+       int divider;
+       unsigned long parent_rate = clk_get_rate(c->parent);
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+       if (c->flags & DIV_U71) {
+               divider = clk_div71_get_divider(
+                       parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
+               if (divider < 0)
+                       return divider;
+
+               return DIV_ROUND_UP(parent_rate * 2, divider + 2);
+       } else if (c->flags & DIV_U16) {
+               divider = clk_div16_get_divider(parent_rate, rate);
+               if (divider < 0)
+                       return divider;
+               return DIV_ROUND_UP(parent_rate, divider + 1);
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_periph_clk_ops = {
+       .init                   = &tegra30_periph_clk_init,
+       .enable                 = &tegra30_periph_clk_enable,
+       .disable                = &tegra30_periph_clk_disable,
+       .set_parent             = &tegra30_periph_clk_set_parent,
+       .set_rate               = &tegra30_periph_clk_set_rate,
+       .round_rate             = &tegra30_periph_clk_round_rate,
+       .reset                  = &tegra30_periph_clk_reset,
+};
+
+
+/* Periph extended clock configuration ops */
+static int
+tegra30_vi_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+{
+       if (p == TEGRA_CLK_VI_INP_SEL) {
+               u32 val = clk_readl(c->reg);
+               val &= ~PERIPH_CLK_VI_SEL_EX_MASK;
+               val |= (setting << PERIPH_CLK_VI_SEL_EX_SHIFT) &
+                       PERIPH_CLK_VI_SEL_EX_MASK;
+               clk_writel(val, c->reg);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_vi_clk_ops = {
+       .init                   = &tegra30_periph_clk_init,
+       .enable                 = &tegra30_periph_clk_enable,
+       .disable                = &tegra30_periph_clk_disable,
+       .set_parent             = &tegra30_periph_clk_set_parent,
+       .set_rate               = &tegra30_periph_clk_set_rate,
+       .round_rate             = &tegra30_periph_clk_round_rate,
+       .clk_cfg_ex             = &tegra30_vi_clk_cfg_ex,
+       .reset                  = &tegra30_periph_clk_reset,
+};
+
+static int
+tegra30_nand_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+{
+       if (p == TEGRA_CLK_NAND_PAD_DIV2_ENB) {
+               u32 val = clk_readl(c->reg);
+               if (setting)
+                       val |= PERIPH_CLK_NAND_DIV_EX_ENB;
+               else
+                       val &= ~PERIPH_CLK_NAND_DIV_EX_ENB;
+               clk_writel(val, c->reg);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_nand_clk_ops = {
+       .init                   = &tegra30_periph_clk_init,
+       .enable                 = &tegra30_periph_clk_enable,
+       .disable                = &tegra30_periph_clk_disable,
+       .set_parent             = &tegra30_periph_clk_set_parent,
+       .set_rate               = &tegra30_periph_clk_set_rate,
+       .round_rate             = &tegra30_periph_clk_round_rate,
+       .clk_cfg_ex             = &tegra30_nand_clk_cfg_ex,
+       .reset                  = &tegra30_periph_clk_reset,
+};
+
+
+static int
+tegra30_dtv_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+{
+       if (p == TEGRA_CLK_DTV_INVERT) {
+               u32 val = clk_readl(c->reg);
+               if (setting)
+                       val |= PERIPH_CLK_DTV_POLARITY_INV;
+               else
+                       val &= ~PERIPH_CLK_DTV_POLARITY_INV;
+               clk_writel(val, c->reg);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_dtv_clk_ops = {
+       .init                   = &tegra30_periph_clk_init,
+       .enable                 = &tegra30_periph_clk_enable,
+       .disable                = &tegra30_periph_clk_disable,
+       .set_parent             = &tegra30_periph_clk_set_parent,
+       .set_rate               = &tegra30_periph_clk_set_rate,
+       .round_rate             = &tegra30_periph_clk_round_rate,
+       .clk_cfg_ex             = &tegra30_dtv_clk_cfg_ex,
+       .reset                  = &tegra30_periph_clk_reset,
+};
+
+static int tegra30_dsib_clk_set_parent(struct clk *c, struct clk *p)
+{
+       const struct clk_mux_sel *sel;
+       struct clk *d = tegra_get_clock_by_name("pll_d");
+
+       pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       if (c->refcnt)
+                               clk_enable(p);
+
+                       /* The DSIB parent selection bit is in PLLD base
+                          register - can not do direct r-m-w, must be
+                          protected by PLLD lock */
+                       tegra_clk_cfg_ex(
+                               d, TEGRA_CLK_PLLD_MIPI_MUX_SEL, sel->value);
+
+                       if (c->refcnt && c->parent)
+                               clk_disable(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_dsib_clk_ops = {
+       .init                   = &tegra30_periph_clk_init,
+       .enable                 = &tegra30_periph_clk_enable,
+       .disable                = &tegra30_periph_clk_disable,
+       .set_parent             = &tegra30_dsib_clk_set_parent,
+       .set_rate               = &tegra30_periph_clk_set_rate,
+       .round_rate             = &tegra30_periph_clk_round_rate,
+       .reset                  = &tegra30_periph_clk_reset,
+};
+
+/* pciex clock support only reset function */
+static struct clk_ops tegra_pciex_clk_ops = {
+       .reset    = tegra30_periph_clk_reset,
+};
+
+/* Output clock ops */
+
+static DEFINE_SPINLOCK(clk_out_lock);
+
+static void tegra30_clk_out_init(struct clk *c)
+{
+       const struct clk_mux_sel *mux = 0;
+       const struct clk_mux_sel *sel;
+       u32 val = pmc_readl(c->reg);
+
+       c->state = (val & (0x1 << c->u.periph.clk_num)) ? ON : OFF;
+       c->mul = 1;
+       c->div = 1;
+
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (((val & periph_clk_source_mask(c)) >>
+                    periph_clk_source_shift(c)) == sel->value)
+                       mux = sel;
+       }
+       BUG_ON(!mux);
+       c->parent = mux->input;
+}
+
+static int tegra30_clk_out_enable(struct clk *c)
+{
+       u32 val;
+       unsigned long flags;
+
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       spin_lock_irqsave(&clk_out_lock, flags);
+       val = pmc_readl(c->reg);
+       val |= (0x1 << c->u.periph.clk_num);
+       pmc_writel(val, c->reg);
+       spin_unlock_irqrestore(&clk_out_lock, flags);
+
+       return 0;
+}
+
+static void tegra30_clk_out_disable(struct clk *c)
+{
+       u32 val;
+       unsigned long flags;
+
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       spin_lock_irqsave(&clk_out_lock, flags);
+       val = pmc_readl(c->reg);
+       val &= ~(0x1 << c->u.periph.clk_num);
+       pmc_writel(val, c->reg);
+       spin_unlock_irqrestore(&clk_out_lock, flags);
+}
+
+static int tegra30_clk_out_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       unsigned long flags;
+       const struct clk_mux_sel *sel;
+
+       pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       if (c->refcnt)
+                               clk_enable(p);
+
+                       spin_lock_irqsave(&clk_out_lock, flags);
+                       val = pmc_readl(c->reg);
+                       val &= ~periph_clk_source_mask(c);
+                       val |= (sel->value << periph_clk_source_shift(c));
+                       pmc_writel(val, c->reg);
+                       spin_unlock_irqrestore(&clk_out_lock, flags);
+
+                       if (c->refcnt && c->parent)
+                               clk_disable(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_clk_out_ops = {
+       .init                   = &tegra30_clk_out_init,
+       .enable                 = &tegra30_clk_out_enable,
+       .disable                = &tegra30_clk_out_disable,
+       .set_parent             = &tegra30_clk_out_set_parent,
+};
+
+
+/* Clock doubler ops */
+static void tegra30_clk_double_init(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       c->mul = val & (0x1 << c->reg_shift) ? 1 : 2;
+       c->div = 1;
+       c->state = ON;
+       if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
+               c->state = OFF;
+};
+
+static int tegra30_clk_double_set_rate(struct clk *c, unsigned long rate)
+{
+       u32 val;
+       unsigned long parent_rate = clk_get_rate(c->parent);
+       if (rate == parent_rate) {
+               val = clk_readl(c->reg) | (0x1 << c->reg_shift);
+               clk_writel(val, c->reg);
+               c->mul = 1;
+               c->div = 1;
+               return 0;
+       } else if (rate == 2 * parent_rate) {
+               val = clk_readl(c->reg) & (~(0x1 << c->reg_shift));
+               clk_writel(val, c->reg);
+               c->mul = 2;
+               c->div = 1;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_clk_double_ops = {
+       .init                   = &tegra30_clk_double_init,
+       .enable                 = &tegra30_periph_clk_enable,
+       .disable                = &tegra30_periph_clk_disable,
+       .set_rate               = &tegra30_clk_double_set_rate,
+};
+
+/* Audio sync clock ops */
+static int tegra30_sync_source_set_rate(struct clk *c, unsigned long rate)
+{
+       c->rate = rate;
+       return 0;
+}
+
+static struct clk_ops tegra_sync_source_ops = {
+       .set_rate               = &tegra30_sync_source_set_rate,
+};
+
+static void tegra30_audio_sync_clk_init(struct clk *c)
+{
+       int source;
+       const struct clk_mux_sel *sel;
+       u32 val = clk_readl(c->reg);
+       c->state = (val & AUDIO_SYNC_DISABLE_BIT) ? OFF : ON;
+       source = val & AUDIO_SYNC_SOURCE_MASK;
+       for (sel = c->inputs; sel->input != NULL; sel++)
+               if (sel->value == source)
+                       break;
+       BUG_ON(sel->input == NULL);
+       c->parent = sel->input;
+}
+
+static int tegra30_audio_sync_clk_enable(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       clk_writel((val & (~AUDIO_SYNC_DISABLE_BIT)), c->reg);
+       return 0;
+}
+
+static void tegra30_audio_sync_clk_disable(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       clk_writel((val | AUDIO_SYNC_DISABLE_BIT), c->reg);
+}
+
+static int tegra30_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       const struct clk_mux_sel *sel;
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       val = clk_readl(c->reg);
+                       val &= ~AUDIO_SYNC_SOURCE_MASK;
+                       val |= sel->value;
+
+                       if (c->refcnt)
+                               clk_enable(p);
+
+                       clk_writel(val, c->reg);
+
+                       if (c->refcnt && c->parent)
+                               clk_disable(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_audio_sync_clk_ops = {
+       .init       = tegra30_audio_sync_clk_init,
+       .enable     = tegra30_audio_sync_clk_enable,
+       .disable    = tegra30_audio_sync_clk_disable,
+       .set_parent = tegra30_audio_sync_clk_set_parent,
+};
+
+/* cml0 (pcie), and cml1 (sata) clock ops */
+static void tegra30_cml_clk_init(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       c->state = val & (0x1 << c->u.periph.clk_num) ? ON : OFF;
+}
+
+static int tegra30_cml_clk_enable(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       val |= (0x1 << c->u.periph.clk_num);
+       clk_writel(val, c->reg);
+       return 0;
+}
+
+static void tegra30_cml_clk_disable(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       val &= ~(0x1 << c->u.periph.clk_num);
+       clk_writel(val, c->reg);
+}
+
+static struct clk_ops tegra_cml_clk_ops = {
+       .init                   = &tegra30_cml_clk_init,
+       .enable                 = &tegra30_cml_clk_enable,
+       .disable                = &tegra30_cml_clk_disable,
+};
+
+/* Clock definitions */
+static struct clk tegra_clk_32k = {
+       .name = "clk_32k",
+       .rate = 32768,
+       .ops  = NULL,
+       .max_rate = 32768,
+};
+
+static struct clk tegra_clk_m = {
+       .name      = "clk_m",
+       .flags     = ENABLE_ON_INIT,
+       .ops       = &tegra_clk_m_ops,
+       .reg       = 0x1fc,
+       .reg_shift = 28,
+       .max_rate  = 48000000,
+};
+
+static struct clk tegra_clk_m_div2 = {
+       .name      = "clk_m_div2",
+       .ops       = &tegra_clk_m_div_ops,
+       .parent    = &tegra_clk_m,
+       .mul       = 1,
+       .div       = 2,
+       .state     = ON,
+       .max_rate  = 24000000,
+};
+
+static struct clk tegra_clk_m_div4 = {
+       .name      = "clk_m_div4",
+       .ops       = &tegra_clk_m_div_ops,
+       .parent    = &tegra_clk_m,
+       .mul       = 1,
+       .div       = 4,
+       .state     = ON,
+       .max_rate  = 12000000,
+};
+
+static struct clk tegra_pll_ref = {
+       .name      = "pll_ref",
+       .flags     = ENABLE_ON_INIT,
+       .ops       = &tegra_pll_ref_ops,
+       .parent    = &tegra_clk_m,
+       .max_rate  = 26000000,
+};
+
+static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
+       { 12000000, 1040000000, 520,  6, 1, 8},
+       { 13000000, 1040000000, 480,  6, 1, 8},
+       { 16800000, 1040000000, 495,  8, 1, 8},         /* actual: 1039.5 MHz */
+       { 19200000, 1040000000, 325,  6, 1, 6},
+       { 26000000, 1040000000, 520, 13, 1, 8},
+
+       { 12000000, 832000000, 416,  6, 1, 8},
+       { 13000000, 832000000, 832, 13, 1, 8},
+       { 16800000, 832000000, 396,  8, 1, 8},          /* actual: 831.6 MHz */
+       { 19200000, 832000000, 260,  6, 1, 8},
+       { 26000000, 832000000, 416, 13, 1, 8},
+
+       { 12000000, 624000000, 624, 12, 1, 8},
+       { 13000000, 624000000, 624, 13, 1, 8},
+       { 16800000, 600000000, 520, 14, 1, 8},
+       { 19200000, 624000000, 520, 16, 1, 8},
+       { 26000000, 624000000, 624, 26, 1, 8},
+
+       { 12000000, 600000000, 600, 12, 1, 8},
+       { 13000000, 600000000, 600, 13, 1, 8},
+       { 16800000, 600000000, 500, 14, 1, 8},
+       { 19200000, 600000000, 375, 12, 1, 6},
+       { 26000000, 600000000, 600, 26, 1, 8},
+
+       { 12000000, 520000000, 520, 12, 1, 8},
+       { 13000000, 520000000, 520, 13, 1, 8},
+       { 16800000, 520000000, 495, 16, 1, 8},          /* actual: 519.75 MHz */
+       { 19200000, 520000000, 325, 12, 1, 6},
+       { 26000000, 520000000, 520, 26, 1, 8},
+
+       { 12000000, 416000000, 416, 12, 1, 8},
+       { 13000000, 416000000, 416, 13, 1, 8},
+       { 16800000, 416000000, 396, 16, 1, 8},          /* actual: 415.8 MHz */
+       { 19200000, 416000000, 260, 12, 1, 6},
+       { 26000000, 416000000, 416, 26, 1, 8},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_c = {
+       .name      = "pll_c",
+       .flags     = PLL_HAS_CPCON,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0x80,
+       .parent    = &tegra_pll_ref,
+       .max_rate  = 1400000000,
+       .u.pll = {
+               .input_min = 2000000,
+               .input_max = 31000000,
+               .cf_min    = 1000000,
+               .cf_max    = 6000000,
+               .vco_min   = 20000000,
+               .vco_max   = 1400000000,
+               .freq_table = tegra_pll_c_freq_table,
+               .lock_delay = 300,
+       },
+};
+
+static struct clk tegra_pll_c_out1 = {
+       .name      = "pll_c_out1",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_U71,
+       .parent    = &tegra_pll_c,
+       .reg       = 0x84,
+       .reg_shift = 0,
+       .max_rate  = 700000000,
+};
+
+static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
+       { 12000000, 666000000, 666, 12, 1, 8},
+       { 13000000, 666000000, 666, 13, 1, 8},
+       { 16800000, 666000000, 555, 14, 1, 8},
+       { 19200000, 666000000, 555, 16, 1, 8},
+       { 26000000, 666000000, 666, 26, 1, 8},
+       { 12000000, 600000000, 600, 12, 1, 8},
+       { 13000000, 600000000, 600, 13, 1, 8},
+       { 16800000, 600000000, 500, 14, 1, 8},
+       { 19200000, 600000000, 375, 12, 1, 6},
+       { 26000000, 600000000, 600, 26, 1, 8},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_m = {
+       .name      = "pll_m",
+       .flags     = PLL_HAS_CPCON | PLLM,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0x90,
+       .parent    = &tegra_pll_ref,
+       .max_rate  = 800000000,
+       .u.pll = {
+               .input_min = 2000000,
+               .input_max = 31000000,
+               .cf_min    = 1000000,
+               .cf_max    = 6000000,
+               .vco_min   = 20000000,
+               .vco_max   = 1200000000,
+               .freq_table = tegra_pll_m_freq_table,
+               .lock_delay = 300,
+       },
+};
+
+static struct clk tegra_pll_m_out1 = {
+       .name      = "pll_m_out1",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_U71,
+       .parent    = &tegra_pll_m,
+       .reg       = 0x94,
+       .reg_shift = 0,
+       .max_rate  = 600000000,
+};
+
+static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
+       { 12000000, 216000000, 432, 12, 2, 8},
+       { 13000000, 216000000, 432, 13, 2, 8},
+       { 16800000, 216000000, 360, 14, 2, 8},
+       { 19200000, 216000000, 360, 16, 2, 8},
+       { 26000000, 216000000, 432, 26, 2, 8},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_p = {
+       .name      = "pll_p",
+       .flags     = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xa0,
+       .parent    = &tegra_pll_ref,
+       .max_rate  = 432000000,
+       .u.pll = {
+               .input_min = 2000000,
+               .input_max = 31000000,
+               .cf_min    = 1000000,
+               .cf_max    = 6000000,
+               .vco_min   = 20000000,
+               .vco_max   = 1400000000,
+               .freq_table = tegra_pll_p_freq_table,
+               .lock_delay = 300,
+               .fixed_rate = 408000000,
+       },
+};
+
+static struct clk tegra_pll_p_out1 = {
+       .name      = "pll_p_out1",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+       .parent    = &tegra_pll_p,
+       .reg       = 0xa4,
+       .reg_shift = 0,
+       .max_rate  = 432000000,
+};
+
+static struct clk tegra_pll_p_out2 = {
+       .name      = "pll_p_out2",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+       .parent    = &tegra_pll_p,
+       .reg       = 0xa4,
+       .reg_shift = 16,
+       .max_rate  = 432000000,
+};
+
+static struct clk tegra_pll_p_out3 = {
+       .name      = "pll_p_out3",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+       .parent    = &tegra_pll_p,
+       .reg       = 0xa8,
+       .reg_shift = 0,
+       .max_rate  = 432000000,
+};
+
+static struct clk tegra_pll_p_out4 = {
+       .name      = "pll_p_out4",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+       .parent    = &tegra_pll_p,
+       .reg       = 0xa8,
+       .reg_shift = 16,
+       .max_rate  = 432000000,
+};
+
+static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
+       { 9600000, 564480000, 294, 5, 1, 4},
+       { 9600000, 552960000, 288, 5, 1, 4},
+       { 9600000, 24000000,  5,   2, 1, 1},
+
+       { 28800000, 56448000, 49, 25, 1, 1},
+       { 28800000, 73728000, 64, 25, 1, 1},
+       { 28800000, 24000000,  5,  6, 1, 1},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_a = {
+       .name      = "pll_a",
+       .flags     = PLL_HAS_CPCON,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xb0,
+       .parent    = &tegra_pll_p_out1,
+       .max_rate  = 700000000,
+       .u.pll = {
+               .input_min = 2000000,
+               .input_max = 31000000,
+               .cf_min    = 1000000,
+               .cf_max    = 6000000,
+               .vco_min   = 20000000,
+               .vco_max   = 1400000000,
+               .freq_table = tegra_pll_a_freq_table,
+               .lock_delay = 300,
+       },
+};
+
+static struct clk tegra_pll_a_out0 = {
+       .name      = "pll_a_out0",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_U71,
+       .parent    = &tegra_pll_a,
+       .reg       = 0xb4,
+       .reg_shift = 0,
+       .max_rate  = 100000000,
+};
+
+static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
+       { 12000000, 216000000, 216, 12, 1, 4},
+       { 13000000, 216000000, 216, 13, 1, 4},
+       { 16800000, 216000000, 180, 14, 1, 4},
+       { 19200000, 216000000, 180, 16, 1, 4},
+       { 26000000, 216000000, 216, 26, 1, 4},
+
+       { 12000000, 594000000, 594, 12, 1, 8},
+       { 13000000, 594000000, 594, 13, 1, 8},
+       { 16800000, 594000000, 495, 14, 1, 8},
+       { 19200000, 594000000, 495, 16, 1, 8},
+       { 26000000, 594000000, 594, 26, 1, 8},
+
+       { 12000000, 1000000000, 1000, 12, 1, 12},
+       { 13000000, 1000000000, 1000, 13, 1, 12},
+       { 19200000, 1000000000, 625,  12, 1, 8},
+       { 26000000, 1000000000, 1000, 26, 1, 12},
+
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_d = {
+       .name      = "pll_d",
+       .flags     = PLL_HAS_CPCON | PLLD,
+       .ops       = &tegra_plld_ops,
+       .reg       = 0xd0,
+       .parent    = &tegra_pll_ref,
+       .max_rate  = 1000000000,
+       .u.pll = {
+               .input_min = 2000000,
+               .input_max = 40000000,
+               .cf_min    = 1000000,
+               .cf_max    = 6000000,
+               .vco_min   = 40000000,
+               .vco_max   = 1000000000,
+               .freq_table = tegra_pll_d_freq_table,
+               .lock_delay = 1000,
+       },
+};
+
+static struct clk tegra_pll_d_out0 = {
+       .name      = "pll_d_out0",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_2 | PLLD,
+       .parent    = &tegra_pll_d,
+       .max_rate  = 500000000,
+};
+
+static struct clk tegra_pll_d2 = {
+       .name      = "pll_d2",
+       .flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLD,
+       .ops       = &tegra_plld_ops,
+       .reg       = 0x4b8,
+       .parent    = &tegra_pll_ref,
+       .max_rate  = 1000000000,
+       .u.pll = {
+               .input_min = 2000000,
+               .input_max = 40000000,
+               .cf_min    = 1000000,
+               .cf_max    = 6000000,
+               .vco_min   = 40000000,
+               .vco_max   = 1000000000,
+               .freq_table = tegra_pll_d_freq_table,
+               .lock_delay = 1000,
+       },
+};
+
+static struct clk tegra_pll_d2_out0 = {
+       .name      = "pll_d2_out0",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_2 | PLLD,
+       .parent    = &tegra_pll_d2,
+       .max_rate  = 500000000,
+};
+
+static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
+       { 12000000, 480000000, 960, 12, 2, 12},
+       { 13000000, 480000000, 960, 13, 2, 12},
+       { 16800000, 480000000, 400, 7,  2, 5},
+       { 19200000, 480000000, 200, 4,  2, 3},
+       { 26000000, 480000000, 960, 26, 2, 12},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_u = {
+       .name      = "pll_u",
+       .flags     = PLL_HAS_CPCON | PLLU,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xc0,
+       .parent    = &tegra_pll_ref,
+       .max_rate  = 480000000,
+       .u.pll = {
+               .input_min = 2000000,
+               .input_max = 40000000,
+               .cf_min    = 1000000,
+               .cf_max    = 6000000,
+               .vco_min   = 480000000,
+               .vco_max   = 960000000,
+               .freq_table = tegra_pll_u_freq_table,
+               .lock_delay = 1000,
+       },
+};
+
+static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
+       /* 1.7 GHz */
+       { 12000000, 1700000000, 850,  6,  1, 8},
+       { 13000000, 1700000000, 915,  7,  1, 8},        /* actual: 1699.2 MHz */
+       { 16800000, 1700000000, 708,  7,  1, 8},        /* actual: 1699.2 MHz */
+       { 19200000, 1700000000, 885,  10, 1, 8},        /* actual: 1699.2 MHz */
+       { 26000000, 1700000000, 850,  13, 1, 8},
+
+       /* 1.6 GHz */
+       { 12000000, 1600000000, 800,  6,  1, 8},
+       { 13000000, 1600000000, 738,  6,  1, 8},        /* actual: 1599.0 MHz */
+       { 16800000, 1600000000, 857,  9,  1, 8},        /* actual: 1599.7 MHz */
+       { 19200000, 1600000000, 500,  6,  1, 8},
+       { 26000000, 1600000000, 800,  13, 1, 8},
+
+       /* 1.5 GHz */
+       { 12000000, 1500000000, 750,  6,  1, 8},
+       { 13000000, 1500000000, 923,  8,  1, 8},        /* actual: 1499.8 MHz */
+       { 16800000, 1500000000, 625,  7,  1, 8},
+       { 19200000, 1500000000, 625,  8,  1, 8},
+       { 26000000, 1500000000, 750,  13, 1, 8},
+
+       /* 1.4 GHz */
+       { 12000000, 1400000000, 700,  6,  1, 8},
+       { 13000000, 1400000000, 969,  9,  1, 8},        /* actual: 1399.7 MHz */
+       { 16800000, 1400000000, 1000, 12, 1, 8},
+       { 19200000, 1400000000, 875,  12, 1, 8},
+       { 26000000, 1400000000, 700,  13, 1, 8},
+
+       /* 1.3 GHz */
+       { 12000000, 1300000000, 975,  9,  1, 8},
+       { 13000000, 1300000000, 1000, 10, 1, 8},
+       { 16800000, 1300000000, 928,  12, 1, 8},        /* actual: 1299.2 MHz */
+       { 19200000, 1300000000, 812,  12, 1, 8},        /* actual: 1299.2 MHz */
+       { 26000000, 1300000000, 650,  13, 1, 8},
+
+       /* 1.2 GHz */
+       { 12000000, 1200000000, 1000, 10, 1, 8},
+       { 13000000, 1200000000, 923,  10, 1, 8},        /* actual: 1199.9 MHz */
+       { 16800000, 1200000000, 1000, 14, 1, 8},
+       { 19200000, 1200000000, 1000, 16, 1, 8},
+       { 26000000, 1200000000, 600,  13, 1, 8},
+
+       /* 1.1 GHz */
+       { 12000000, 1100000000, 825,  9,  1, 8},
+       { 13000000, 1100000000, 846,  10, 1, 8},        /* actual: 1099.8 MHz */
+       { 16800000, 1100000000, 982,  15, 1, 8},        /* actual: 1099.8 MHz */
+       { 19200000, 1100000000, 859,  15, 1, 8},        /* actual: 1099.5 MHz */
+       { 26000000, 1100000000, 550,  13, 1, 8},
+
+       /* 1 GHz */
+       { 12000000, 1000000000, 1000, 12, 1, 8},
+       { 13000000, 1000000000, 1000, 13, 1, 8},
+       { 16800000, 1000000000, 833,  14, 1, 8},        /* actual: 999.6 MHz */
+       { 19200000, 1000000000, 625,  12, 1, 8},
+       { 26000000, 1000000000, 1000, 26, 1, 8},
+
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_x = {
+       .name      = "pll_x",
+       .flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLX,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xe0,
+       .parent    = &tegra_pll_ref,
+       .max_rate  = 1700000000,
+       .u.pll = {
+               .input_min = 2000000,
+               .input_max = 31000000,
+               .cf_min    = 1000000,
+               .cf_max    = 6000000,
+               .vco_min   = 20000000,
+               .vco_max   = 1700000000,
+               .freq_table = tegra_pll_x_freq_table,
+               .lock_delay = 300,
+       },
+};
+
+static struct clk tegra_pll_x_out0 = {
+       .name      = "pll_x_out0",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_2 | PLLX,
+       .parent    = &tegra_pll_x,
+       .max_rate  = 850000000,
+};
+
+
+static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
+       /* PLLE special case: use cpcon field to store cml divider value */
+       { 12000000,  100000000, 150, 1,  18, 11},
+       { 216000000, 100000000, 200, 18, 24, 13},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_e = {
+       .name      = "pll_e",
+       .flags     = PLL_ALT_MISC_REG,
+       .ops       = &tegra_plle_ops,
+       .reg       = 0xe8,
+       .max_rate  = 100000000,
+       .u.pll = {
+               .input_min = 12000000,
+               .input_max = 216000000,
+               .cf_min    = 12000000,
+               .cf_max    = 12000000,
+               .vco_min   = 1200000000,
+               .vco_max   = 2400000000U,
+               .freq_table = tegra_pll_e_freq_table,
+               .lock_delay = 300,
+               .fixed_rate = 100000000,
+       },
+};
+
+static struct clk tegra_cml0_clk = {
+       .name      = "cml0",
+       .parent    = &tegra_pll_e,
+       .ops       = &tegra_cml_clk_ops,
+       .reg       = PLLE_AUX,
+       .max_rate  = 100000000,
+       .u.periph  = {
+               .clk_num = 0,
+       },
+};
+
+static struct clk tegra_cml1_clk = {
+       .name      = "cml1",
+       .parent    = &tegra_pll_e,
+       .ops       = &tegra_cml_clk_ops,
+       .reg       = PLLE_AUX,
+       .max_rate  = 100000000,
+       .u.periph  = {
+               .clk_num   = 1,
+       },
+};
+
+static struct clk tegra_pciex_clk = {
+       .name      = "pciex",
+       .parent    = &tegra_pll_e,
+       .ops       = &tegra_pciex_clk_ops,
+       .max_rate  = 100000000,
+       .u.periph  = {
+               .clk_num   = 74,
+       },
+};
+
+/* Audio sync clocks */
+#define SYNC_SOURCE(_id)                               \
+       {                                               \
+               .name      = #_id "_sync",              \
+               .rate      = 24000000,                  \
+               .max_rate  = 24000000,                  \
+               .ops       = &tegra_sync_source_ops     \
+       }
+static struct clk tegra_sync_source_list[] = {
+       SYNC_SOURCE(spdif_in),
+       SYNC_SOURCE(i2s0),
+       SYNC_SOURCE(i2s1),
+       SYNC_SOURCE(i2s2),
+       SYNC_SOURCE(i2s3),
+       SYNC_SOURCE(i2s4),
+       SYNC_SOURCE(vimclk),
+};
+
+static struct clk_mux_sel mux_audio_sync_clk[] = {
+       { .input = &tegra_sync_source_list[0],  .value = 0},
+       { .input = &tegra_sync_source_list[1],  .value = 1},
+       { .input = &tegra_sync_source_list[2],  .value = 2},
+       { .input = &tegra_sync_source_list[3],  .value = 3},
+       { .input = &tegra_sync_source_list[4],  .value = 4},
+       { .input = &tegra_sync_source_list[5],  .value = 5},
+       { .input = &tegra_pll_a_out0,           .value = 6},
+       { .input = &tegra_sync_source_list[6],  .value = 7},
+       { 0, 0 }
+};
+
+#define AUDIO_SYNC_CLK(_id, _index)                    \
+       {                                               \
+               .name      = #_id,                      \
+               .inputs    = mux_audio_sync_clk,        \
+               .reg       = 0x4A0 + (_index) * 4,      \
+               .max_rate  = 24000000,                  \
+               .ops       = &tegra_audio_sync_clk_ops  \
+       }
+static struct clk tegra_clk_audio_list[] = {
+       AUDIO_SYNC_CLK(audio0, 0),
+       AUDIO_SYNC_CLK(audio1, 1),
+       AUDIO_SYNC_CLK(audio2, 2),
+       AUDIO_SYNC_CLK(audio3, 3),
+       AUDIO_SYNC_CLK(audio4, 4),
+       AUDIO_SYNC_CLK(audio, 5),       /* SPDIF */
+};
+
+#define AUDIO_SYNC_2X_CLK(_id, _index)                         \
+       {                                                       \
+               .name      = #_id "_2x",                        \
+               .flags     = PERIPH_NO_RESET,                   \
+               .max_rate  = 48000000,                          \
+               .ops       = &tegra_clk_double_ops,             \
+               .reg       = 0x49C,                             \
+               .reg_shift = 24 + (_index),                     \
+               .parent    = &tegra_clk_audio_list[(_index)],   \
+               .u.periph = {                                   \
+                       .clk_num = 113 + (_index),              \
+               },                                              \
+       }
+static struct clk tegra_clk_audio_2x_list[] = {
+       AUDIO_SYNC_2X_CLK(audio0, 0),
+       AUDIO_SYNC_2X_CLK(audio1, 1),
+       AUDIO_SYNC_2X_CLK(audio2, 2),
+       AUDIO_SYNC_2X_CLK(audio3, 3),
+       AUDIO_SYNC_2X_CLK(audio4, 4),
+       AUDIO_SYNC_2X_CLK(audio, 5),    /* SPDIF */
+};
+
+#define MUX_I2S_SPDIF(_id, _index)                                     \
+static struct clk_mux_sel mux_pllaout0_##_id##_2x_pllp_clkm[] = {      \
+       {.input = &tegra_pll_a_out0, .value = 0},                       \
+       {.input = &tegra_clk_audio_2x_list[(_index)], .value = 1},      \
+       {.input = &tegra_pll_p, .value = 2},                            \
+       {.input = &tegra_clk_m, .value = 3},                            \
+       { 0, 0},                                                        \
+}
+MUX_I2S_SPDIF(audio0, 0);
+MUX_I2S_SPDIF(audio1, 1);
+MUX_I2S_SPDIF(audio2, 2);
+MUX_I2S_SPDIF(audio3, 3);
+MUX_I2S_SPDIF(audio4, 4);
+MUX_I2S_SPDIF(audio, 5);               /* SPDIF */
+
+/* External clock outputs (through PMC) */
+#define MUX_EXTERN_OUT(_id)                                            \
+static struct clk_mux_sel mux_clkm_clkm2_clkm4_extern##_id[] = {       \
+       {.input = &tegra_clk_m,         .value = 0},                    \
+       {.input = &tegra_clk_m_div2,    .value = 1},                    \
+       {.input = &tegra_clk_m_div4,    .value = 2},                    \
+       {.input = NULL,                 .value = 3}, /* placeholder */  \
+       { 0, 0},                                                        \
+}
+MUX_EXTERN_OUT(1);
+MUX_EXTERN_OUT(2);
+MUX_EXTERN_OUT(3);
+
+static struct clk_mux_sel *mux_extern_out_list[] = {
+       mux_clkm_clkm2_clkm4_extern1,
+       mux_clkm_clkm2_clkm4_extern2,
+       mux_clkm_clkm2_clkm4_extern3,
+};
+
+#define CLK_OUT_CLK(_id)                                       \
+       {                                                       \
+               .name      = "clk_out_" #_id,                   \
+               .lookup    = {                                  \
+                       .dev_id    = "clk_out_" #_id,           \
+                       .con_id    = "extern" #_id,             \
+               },                                              \
+               .ops       = &tegra_clk_out_ops,                \
+               .reg       = 0x1a8,                             \
+               .inputs    = mux_clkm_clkm2_clkm4_extern##_id,  \
+               .flags     = MUX_CLK_OUT,                       \
+               .max_rate  = 216000000,                         \
+               .u.periph = {                                   \
+                       .clk_num   = (_id - 1) * 8 + 2,         \
+               },                                              \
+       }
+static struct clk tegra_clk_out_list[] = {
+       CLK_OUT_CLK(1),
+       CLK_OUT_CLK(2),
+       CLK_OUT_CLK(3),
+};
+
+/* called after peripheral external clocks are initialized */
+static void init_clk_out_mux(void)
+{
+       int i;
+       struct clk *c;
+
+       /* output clock con_id is the name of peripheral
+          external clock connected to input 3 of the output mux */
+       for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++) {
+               c = tegra_get_clock_by_name(
+                       tegra_clk_out_list[i].lookup.con_id);
+               if (!c)
+                       pr_err("%s: could not find clk %s\n", __func__,
+                              tegra_clk_out_list[i].lookup.con_id);
+               mux_extern_out_list[i][3].input = c;
+       }
+}
+
+/* Peripheral muxes */
+static struct clk_mux_sel mux_sclk[] = {
+       { .input = &tegra_clk_m,        .value = 0},
+       { .input = &tegra_pll_c_out1,   .value = 1},
+       { .input = &tegra_pll_p_out4,   .value = 2},
+       { .input = &tegra_pll_p_out3,   .value = 3},
+       { .input = &tegra_pll_p_out2,   .value = 4},
+       /* { .input = &tegra_clk_d,     .value = 5}, - no use on tegra30 */
+       { .input = &tegra_clk_32k,      .value = 6},
+       { .input = &tegra_pll_m_out1,   .value = 7},
+       { 0, 0},
+};
+
+static struct clk tegra_clk_sclk = {
+       .name   = "sclk",
+       .inputs = mux_sclk,
+       .reg    = 0x28,
+       .ops    = &tegra_super_ops,
+       .max_rate = 334000000,
+       .min_rate = 40000000,
+};
+
+static struct clk tegra_clk_blink = {
+       .name           = "blink",
+       .parent         = &tegra_clk_32k,
+       .reg            = 0x40,
+       .ops            = &tegra_blink_clk_ops,
+       .max_rate       = 32768,
+};
+
+static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
+       { .input = &tegra_pll_m, .value = 0},
+       { .input = &tegra_pll_c, .value = 1},
+       { .input = &tegra_pll_p, .value = 2},
+       { .input = &tegra_pll_a_out0, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
+       { .input = &tegra_pll_p, .value = 0},
+       { .input = &tegra_pll_c, .value = 1},
+       { .input = &tegra_pll_m, .value = 2},
+       { .input = &tegra_clk_m, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_clkm[] = {
+       { .input = &tegra_pll_p, .value = 0},
+       { .input = &tegra_clk_m, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
+       {.input = &tegra_pll_p, .value = 0},
+       {.input = &tegra_pll_d_out0, .value = 1},
+       {.input = &tegra_pll_c, .value = 2},
+       {.input = &tegra_clk_m, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
+       {.input = &tegra_pll_p, .value = 0},
+       {.input = &tegra_pll_m, .value = 1},
+       {.input = &tegra_pll_d_out0, .value = 2},
+       {.input = &tegra_pll_a_out0, .value = 3},
+       {.input = &tegra_pll_c, .value = 4},
+       {.input = &tegra_pll_d2_out0, .value = 5},
+       {.input = &tegra_clk_m, .value = 6},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_plla_pllc_pllp_clkm[] = {
+       { .input = &tegra_pll_a_out0, .value = 0},
+       /* { .input = &tegra_pll_c, .value = 1}, no use on tegra30 */
+       { .input = &tegra_pll_p, .value = 2},
+       { .input = &tegra_clk_m, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_clk32_clkm[] = {
+       {.input = &tegra_pll_p,     .value = 0},
+       {.input = &tegra_pll_c,     .value = 1},
+       {.input = &tegra_clk_32k,   .value = 2},
+       {.input = &tegra_clk_m,     .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_clkm_clk32[] = {
+       {.input = &tegra_pll_p,     .value = 0},
+       {.input = &tegra_pll_c,     .value = 1},
+       {.input = &tegra_clk_m,     .value = 2},
+       {.input = &tegra_clk_32k,   .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
+       {.input = &tegra_pll_p,     .value = 0},
+       {.input = &tegra_pll_c,     .value = 1},
+       {.input = &tegra_pll_m,     .value = 2},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_clk_m[] = {
+       { .input = &tegra_clk_m, .value = 0},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_out3[] = {
+       { .input = &tegra_pll_p_out3, .value = 0},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_plld_out0[] = {
+       { .input = &tegra_pll_d_out0, .value = 0},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_plld_out0_plld2_out0[] = {
+       { .input = &tegra_pll_d_out0,  .value = 0},
+       { .input = &tegra_pll_d2_out0, .value = 1},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_clk_32k[] = {
+       { .input = &tegra_clk_32k, .value = 0},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_plla_clk32_pllp_clkm_plle[] = {
+       { .input = &tegra_pll_a_out0, .value = 0},
+       { .input = &tegra_clk_32k,    .value = 1},
+       { .input = &tegra_pll_p,      .value = 2},
+       { .input = &tegra_clk_m,      .value = 3},
+       { .input = &tegra_pll_e,      .value = 4},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_cclk_g[] = {
+       { .input = &tegra_clk_m,        .value = 0},
+       { .input = &tegra_pll_c,        .value = 1},
+       { .input = &tegra_clk_32k,      .value = 2},
+       { .input = &tegra_pll_m,        .value = 3},
+       { .input = &tegra_pll_p,        .value = 4},
+       { .input = &tegra_pll_p_out4,   .value = 5},
+       { .input = &tegra_pll_p_out3,   .value = 6},
+       { .input = &tegra_pll_x,        .value = 8},
+       { 0, 0},
+};
+
+static struct clk tegra_clk_cclk_g = {
+       .name   = "cclk_g",
+       .flags  = DIV_U71 | DIV_U71_INT,
+       .inputs = mux_cclk_g,
+       .reg    = 0x368,
+       .ops    = &tegra_super_ops,
+       .max_rate = 1700000000,
+};
+
+static struct clk tegra30_clk_twd = {
+       .parent   = &tegra_clk_cclk_g,
+       .name     = "twd",
+       .ops      = &tegra30_twd_ops,
+       .max_rate = 1400000000, /* Same as tegra_clk_cpu_cmplx.max_rate */
+       .mul      = 1,
+       .div      = 2,
+};
+
+#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
+       {                                               \
+               .name      = _name,                     \
+               .lookup    = {                          \
+                       .dev_id    = _dev,              \
+                       .con_id    = _con,              \
+               },                                      \
+               .ops       = &tegra_periph_clk_ops,     \
+               .reg       = _reg,                      \
+               .inputs    = _inputs,                   \
+               .flags     = _flags,                    \
+               .max_rate  = _max,                      \
+               .u.periph = {                           \
+                       .clk_num   = _clk_num,          \
+               },                                      \
+       }
+
+#define PERIPH_CLK_EX(_name, _dev, _con, _clk_num, _reg, _max, _inputs,        \
+                       _flags, _ops)                                   \
+       {                                               \
+               .name      = _name,                     \
+               .lookup    = {                          \
+                       .dev_id    = _dev,              \
+                       .con_id    = _con,              \
+               },                                      \
+               .ops       = _ops,                      \
+               .reg       = _reg,                      \
+               .inputs    = _inputs,                   \
+               .flags     = _flags,                    \
+               .max_rate  = _max,                      \
+               .u.periph = {                           \
+                       .clk_num   = _clk_num,          \
+               },                                      \
+       }
+
+#define SHARED_CLK(_name, _dev, _con, _parent, _id, _div, _mode)\
+       {                                               \
+               .name      = _name,                     \
+               .lookup    = {                          \
+                       .dev_id    = _dev,              \
+                       .con_id    = _con,              \
+               },                                      \
+               .ops       = &tegra_clk_shared_bus_ops, \
+               .parent = _parent,                      \
+               .u.shared_bus_user = {                  \
+                       .client_id = _id,               \
+                       .client_div = _div,             \
+                       .mode = _mode,                  \
+               },                                      \
+       }
+struct clk tegra_list_clks[] = {
+       PERIPH_CLK("apbdma",    "tegra-dma",            NULL,   34,     0,      26000000,  mux_clk_m,                   0),
+       PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("kbc",       "tegra-kbc",            NULL,   36,     0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      26000000,  mux_clk_m,                   0),
+       PERIPH_CLK("kfuse",     "kfuse-tegra",          NULL,   40,     0,      26000000,  mux_clk_m,                   0),
+       PERIPH_CLK("fuse",      "fuse-tegra",           "fuse", 39,     0,      26000000,  mux_clk_m,                   PERIPH_ON_APB),
+       PERIPH_CLK("fuse_burn", "fuse-tegra",           "fuse_burn",    39,     0,      26000000,  mux_clk_m,           PERIPH_ON_APB),
+       PERIPH_CLK("apbif",     "tegra30-ahub",         "apbif", 107,   0,      26000000,  mux_clk_m,                   0),
+       PERIPH_CLK("i2s0",      "tegra30-i2s.0",        NULL,   30,     0x1d8,  26000000,  mux_pllaout0_audio0_2x_pllp_clkm,    MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("i2s1",      "tegra30-i2s.1",        NULL,   11,     0x100,  26000000,  mux_pllaout0_audio1_2x_pllp_clkm,    MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("i2s2",      "tegra30-i2s.2",        NULL,   18,     0x104,  26000000,  mux_pllaout0_audio2_2x_pllp_clkm,    MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("i2s3",      "tegra30-i2s.3",        NULL,   101,    0x3bc,  26000000,  mux_pllaout0_audio3_2x_pllp_clkm,    MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("i2s4",      "tegra30-i2s.4",        NULL,   102,    0x3c0,  26000000,  mux_pllaout0_audio4_2x_pllp_clkm,    MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("spdif_out", "tegra30-spdif",        "spdif_out",    10,     0x108,  100000000, mux_pllaout0_audio_2x_pllp_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("spdif_in",  "tegra30-spdif",        "spdif_in",     10,     0x10c,  100000000, mux_pllp_pllc_pllm,          MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  432000000, mux_pllp_pllc_clk32_clkm,    MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("d_audio",   "tegra30-ahub",         "d_audio", 106, 0x3d0,  48000000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("dam0",      "tegra30-dam.0",        NULL,   108,    0x3d8,  48000000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("dam1",      "tegra30-dam.1",        NULL,   109,    0x3dc,  48000000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("dam2",      "tegra30-dam.2",        NULL,   110,    0x3e0,  48000000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("hda",       "tegra30-hda",          "hda",   125,   0x428,  108000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("hda2codec_2x",      "tegra30-hda",  "hda2codec",   111,     0x3e4,  48000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("hda2hdmi",  "tegra30-hda",          "hda2hdmi",     128,    0,      48000000,  mux_clk_m,                   0),
+       PERIPH_CLK("sbc1",      "spi_tegra.0",          NULL,   41,     0x134,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sbc2",      "spi_tegra.1",          NULL,   44,     0x118,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sbc3",      "spi_tegra.2",          NULL,   46,     0x11c,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sbc4",      "spi_tegra.3",          NULL,   68,     0x1b4,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sbc5",      "spi_tegra.4",          NULL,   104,    0x3c8,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sbc6",      "spi_tegra.5",          NULL,   105,    0x3cc,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sata_oob",  "tegra_sata_oob",       NULL,   123,    0x420,  216000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sata",      "tegra_sata",           NULL,   124,    0x424,  216000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sata_cold", "tegra_sata_cold",      NULL,   129,    0,      48000000,  mux_clk_m,                   0),
+       PERIPH_CLK_EX("ndflash", "tegra_nand",          NULL,   13,     0x160,  240000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71,  &tegra_nand_clk_ops),
+       PERIPH_CLK("ndspeed",   "tegra_nand_speed",     NULL,   80,     0x3f8,  240000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("vfir",      "vfir",                 NULL,   7,      0x168,  72000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  208000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  104000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  208000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc4",    "sdhci-tegra.3",        NULL,   15,     0x164,  104000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("vcp",       "tegra-avp",            "vcp",  29,     0,      250000000, mux_clk_m,                   0),
+       PERIPH_CLK("bsea",      "tegra-avp",            "bsea", 62,     0,      250000000, mux_clk_m,                   0),
+       PERIPH_CLK("bsev",      "tegra-aes",            "bsev", 63,     0,      250000000, mux_clk_m,                   0),
+       PERIPH_CLK("vde",       "vde",                  NULL,   61,     0x1c8,  520000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_INT),
+       PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  144000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* max rate ??? */
+       PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("owr",       "tegra_w1",             NULL,   71,     0x1cc,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("nor",       "nor",                  NULL,   42,     0x1d0,  127000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("mipi",      "mipi",                 NULL,   50,     0x174,  60000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | PERIPH_ON_APB), /* scales with voltage */
+       PERIPH_CLK("i2c1",      "tegra-i2c.0",          NULL,   12,     0x124,  26000000,  mux_pllp_clkm,               MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c2",      "tegra-i2c.1",          NULL,   54,     0x198,  26000000,  mux_pllp_clkm,               MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c3",      "tegra-i2c.2",          NULL,   67,     0x1b8,  26000000,  mux_pllp_clkm,               MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c4",      "tegra-i2c.3",          NULL,   103,    0x3c4,  26000000,  mux_pllp_clkm,               MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c5",      "tegra-i2c.4",          NULL,   47,     0x128,  26000000,  mux_pllp_clkm,               MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("uarta",     "tegra_uart.0",         NULL,   6,      0x178,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartb",     "tegra_uart.1",         NULL,   7,      0x17c,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartc",     "tegra_uart.2",         NULL,   55,     0x1a0,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartd",     "tegra_uart.3",         NULL,   65,     0x1c0,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uarte",     "tegra_uart.4",         NULL,   66,     0x1c4,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uarta_dbg", "serial8250.0",         "uarta", 6,     0x178,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartb_dbg", "serial8250.0",         "uartb", 7,     0x17c,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartc_dbg", "serial8250.0",         "uartc", 55,    0x1a0,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartd_dbg", "serial8250.0",         "uartd", 65,    0x1c0,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uarte_dbg", "serial8250.0",         "uarte", 66,    0x1c4,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK_EX("vi",     "tegra_camera",         "vi",   20,     0x148,  425000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT,    &tegra_vi_clk_ops),
+       PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  520000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
+       PERIPH_CLK("3d2",       "3d2",                  NULL,   98,     0x3b0,  520000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
+       PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  520000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE),
+       PERIPH_CLK("vi_sensor", "tegra_camera",         "vi_sensor",    20,     0x1a8,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK("epp",       "epp",                  NULL,   19,     0x16c,  520000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT),
+       PERIPH_CLK("mpe",       "mpe",                  NULL,   60,     0x170,  520000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT),
+       PERIPH_CLK("host1x",    "host1x",               NULL,   28,     0x180,  260000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT),
+       PERIPH_CLK("cve",       "cve",                  NULL,   49,     0x140,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK_EX("dtv",    "dtv",                  NULL,   79,     0x1dc,  250000000, mux_clk_m,                   0,              &tegra_dtv_clk_ops),
+       PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  148500000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,     MUX | MUX8 | DIV_U71),
+       PERIPH_CLK("tvdac",     "tvdac",                NULL,   53,     0x194,  220000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("disp1",     "tegradc.0",            NULL,   27,     0x138,  600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,     MUX | MUX8),
+       PERIPH_CLK("disp2",     "tegradc.1",            NULL,   26,     0x13c,  600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,     MUX | MUX8),
+       PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("usb2",      "tegra-ehci.1",         NULL,   58,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("usb3",      "tegra-ehci.2",         NULL,   59,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("dsia",      "tegradc.0",            "dsia", 48,     0,      500000000, mux_plld_out0,               0),
+       PERIPH_CLK_EX("dsib",   "tegradc.1",            "dsib", 82,     0xd0,   500000000, mux_plld_out0_plld2_out0,    MUX | PLLD,     &tegra_dsib_clk_ops),
+       PERIPH_CLK("csi",       "tegra_camera",         "csi",  52,     0,      102000000, mux_pllp_out3,               0),
+       PERIPH_CLK("isp",       "tegra_camera",         "isp",  23,     0,      150000000, mux_clk_m,                   0), /* same frequency as VI */
+       PERIPH_CLK("csus",      "tegra_camera",         "csus", 92,     0,      150000000, mux_clk_m,                   PERIPH_NO_RESET),
+
+       PERIPH_CLK("tsensor",   "tegra-tsensor",        NULL,   100,    0x3b8,  216000000, mux_pllp_pllc_clkm_clk32,    MUX | DIV_U71),
+       PERIPH_CLK("actmon",    "actmon",               NULL,   119,    0x3e8,  216000000, mux_pllp_pllc_clk32_clkm,    MUX | DIV_U71),
+       PERIPH_CLK("extern1",   "extern1",              NULL,   120,    0x3ec,  216000000, mux_plla_clk32_pllp_clkm_plle,       MUX | MUX8 | DIV_U71),
+       PERIPH_CLK("extern2",   "extern2",              NULL,   121,    0x3f0,  216000000, mux_plla_clk32_pllp_clkm_plle,       MUX | MUX8 | DIV_U71),
+       PERIPH_CLK("extern3",   "extern3",              NULL,   122,    0x3f4,  216000000, mux_plla_clk32_pllp_clkm_plle,       MUX | MUX8 | DIV_U71),
+       PERIPH_CLK("i2cslow",   "i2cslow",              NULL,   81,     0x3fc,  26000000,  mux_pllp_pllc_clk32_clkm,    MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("pcie",      "tegra-pcie",           "pcie", 70,     0,      250000000, mux_clk_m,                   0),
+       PERIPH_CLK("afi",       "tegra-pcie",           "afi",  72,     0,      250000000, mux_clk_m,                   0),
+       PERIPH_CLK("se",        "se",                   NULL,   127,    0x42c,  520000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_INT),
+};
+
+#define CLK_DUPLICATE(_name, _dev, _con)               \
+       {                                               \
+               .name   = _name,                        \
+               .lookup = {                             \
+                       .dev_id = _dev,                 \
+                       .con_id         = _con,         \
+               },                                      \
+       }
+
+/* Some clocks may be used by different drivers depending on the board
+ * configuration.  List those here to register them twice in the clock lookup
+ * table under two names.
+ */
+struct clk_duplicate tegra_clk_duplicates[] = {
+       CLK_DUPLICATE("usbd", "utmip-pad", NULL),
+       CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
+       CLK_DUPLICATE("usbd", "tegra-otg", NULL),
+       CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
+       CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
+       CLK_DUPLICATE("dsib", "tegradc.0", "dsib"),
+       CLK_DUPLICATE("dsia", "tegradc.1", "dsia"),
+       CLK_DUPLICATE("pwm", "tegra_pwm.0", NULL),
+       CLK_DUPLICATE("pwm", "tegra_pwm.1", NULL),
+       CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL),
+       CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL),
+       CLK_DUPLICATE("bsev", "tegra-avp", "bsev"),
+       CLK_DUPLICATE("bsev", "nvavp", "bsev"),
+       CLK_DUPLICATE("vde", "tegra-aes", "vde"),
+       CLK_DUPLICATE("bsea", "tegra-aes", "bsea"),
+       CLK_DUPLICATE("bsea", "nvavp", "bsea"),
+       CLK_DUPLICATE("cml1", "tegra_sata_cml", NULL),
+       CLK_DUPLICATE("cml0", "tegra_pcie", "cml"),
+       CLK_DUPLICATE("pciex", "tegra_pcie", "pciex"),
+       CLK_DUPLICATE("i2c1", "tegra-i2c-slave.0", NULL),
+       CLK_DUPLICATE("i2c2", "tegra-i2c-slave.1", NULL),
+       CLK_DUPLICATE("i2c3", "tegra-i2c-slave.2", NULL),
+       CLK_DUPLICATE("i2c4", "tegra-i2c-slave.3", NULL),
+       CLK_DUPLICATE("i2c5", "tegra-i2c-slave.4", NULL),
+       CLK_DUPLICATE("sbc1", "spi_slave_tegra.0", NULL),
+       CLK_DUPLICATE("sbc2", "spi_slave_tegra.1", NULL),
+       CLK_DUPLICATE("sbc3", "spi_slave_tegra.2", NULL),
+       CLK_DUPLICATE("sbc4", "spi_slave_tegra.3", NULL),
+       CLK_DUPLICATE("sbc5", "spi_slave_tegra.4", NULL),
+       CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL),
+       CLK_DUPLICATE("twd", "smp_twd", NULL),
+       CLK_DUPLICATE("vcp", "nvavp", "vcp"),
+};
+
+struct clk *tegra_ptr_clks[] = {
+       &tegra_clk_32k,
+       &tegra_clk_m,
+       &tegra_clk_m_div2,
+       &tegra_clk_m_div4,
+       &tegra_pll_ref,
+       &tegra_pll_m,
+       &tegra_pll_m_out1,
+       &tegra_pll_c,
+       &tegra_pll_c_out1,
+       &tegra_pll_p,
+       &tegra_pll_p_out1,
+       &tegra_pll_p_out2,
+       &tegra_pll_p_out3,
+       &tegra_pll_p_out4,
+       &tegra_pll_a,
+       &tegra_pll_a_out0,
+       &tegra_pll_d,
+       &tegra_pll_d_out0,
+       &tegra_pll_d2,
+       &tegra_pll_d2_out0,
+       &tegra_pll_u,
+       &tegra_pll_x,
+       &tegra_pll_x_out0,
+       &tegra_pll_e,
+       &tegra_clk_cclk_g,
+       &tegra_cml0_clk,
+       &tegra_cml1_clk,
+       &tegra_pciex_clk,
+       &tegra_clk_sclk,
+       &tegra_clk_blink,
+       &tegra30_clk_twd,
+};
+
+
+static void tegra30_init_one_clock(struct clk *c)
+{
+       clk_init(c);
+       INIT_LIST_HEAD(&c->shared_bus_list);
+       if (!c->lookup.dev_id && !c->lookup.con_id)
+               c->lookup.con_id = c->name;
+       c->lookup.clk = c;
+       clkdev_add(&c->lookup);
+}
+
+void __init tegra30_init_clocks(void)
+{
+       int i;
+       struct clk *c;
+
+       for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
+               tegra30_init_one_clock(tegra_ptr_clks[i]);
+
+       for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
+               tegra30_init_one_clock(&tegra_list_clks[i]);
+
+       for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
+               c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
+               if (!c) {
+                       pr_err("%s: Unknown duplicate clock %s\n", __func__,
+                               tegra_clk_duplicates[i].name);
+                       continue;
+               }
+
+               tegra_clk_duplicates[i].lookup.clk = c;
+               clkdev_add(&tegra_clk_duplicates[i].lookup);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(tegra_sync_source_list); i++)
+               tegra30_init_one_clock(&tegra_sync_source_list[i]);
+       for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_list); i++)
+               tegra30_init_one_clock(&tegra_clk_audio_list[i]);
+       for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_2x_list); i++)
+               tegra30_init_one_clock(&tegra_clk_audio_2x_list[i]);
+
+       init_clk_out_mux();
+       for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++)
+               tegra30_init_one_clock(&tegra_clk_out_list[i]);
+
+}