Tegra2: Add more clock support
authorSimon Glass <sjg@chromium.org>
Tue, 30 Aug 2011 06:23:13 +0000 (06:23 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Sun, 4 Sep 2011 09:36:15 +0000 (11:36 +0200)
This adds functions to enable/disable clocks and reset to on-chip peripherals.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/arm/cpu/armv7/tegra2/Makefile
arch/arm/cpu/armv7/tegra2/ap20.c
arch/arm/cpu/armv7/tegra2/clock.c [new file with mode: 0644]
arch/arm/include/asm/arch-tegra2/clk_rst.h
arch/arm/include/asm/arch-tegra2/clock.h [new file with mode: 0644]
board/nvidia/common/board.c

index f1ea9158516dc6a6e08e260acc27bd227fc9c041..b35764c32176514184eee0cadb60cfe10a49d16a 100644 (file)
@@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk
 LIB    =  $(obj)lib$(SOC).o
 
 SOBJS  := lowlevel_init.o
-COBJS  := ap20.o board.o sys_info.o timer.o
+COBJS  := ap20.o board.o clock.o sys_info.o timer.o
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS) $(SOBJS))
index 60dd5dfc08489c46b1243556fa9adac662451f05..e3832e23f347ead5292947a1c9ec2c9be33cc201 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/io.h>
 #include <asm/arch/tegra2.h>
 #include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
 #include <asm/arch/pmc.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/scu.h>
@@ -35,33 +36,34 @@ u32 s_first_boot = 1;
 void init_pllx(void)
 {
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll *pll = &clkrst->crc_pll[CLOCK_PLL_ID_XCPU];
        u32 reg;
 
        /* If PLLX is already enabled, just return */
-       reg = readl(&clkrst->crc_pllx_base);
+       reg = readl(&pll->pll_base);
        if (reg & PLL_ENABLE)
                return;
 
        /* Set PLLX_MISC */
        reg = CPCON;                            /* CPCON[11:8]  = 0001 */
-       writel(reg, &clkrst->crc_pllx_misc);
+       writel(reg, &pll->pll_misc);
 
        /* Use 12MHz clock here */
-       reg = (PLL_BYPASS | PLL_DIVM);
+       reg = (PLL_BYPASS | PLL_DIVM_VALUE);
        reg |= (1000 << 8);                     /* DIVN = 0x3E8 */
-       writel(reg, &clkrst->crc_pllx_base);
+       writel(reg, &pll->pll_base);
 
        reg |= PLL_ENABLE;
-       writel(reg, &clkrst->crc_pllx_base);
+       writel(reg, &pll->pll_base);
 
        reg &= ~PLL_BYPASS;
-       writel(reg, &clkrst->crc_pllx_base);
+       writel(reg, &pll->pll_base);
 }
 
 static void enable_cpu_clock(int enable)
 {
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       u32 reg, clk;
+       u32 clk;
 
        /*
         * NOTE:
@@ -83,10 +85,6 @@ static void enable_cpu_clock(int enable)
                writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
        }
 
-       /* Fetch the register containing the main CPU complex clock enable */
-       reg = readl(&clkrst->crc_clk_out_enb_l);
-       reg |= CLK_ENB_CPU;
-
        /*
         * Read the register containing the individual CPU clock enables and
         * always stop the clock to CPU 1.
@@ -103,7 +101,8 @@ static void enable_cpu_clock(int enable)
        }
 
        writel(clk, &clkrst->crc_clk_cpu_cmplx);
-       writel(reg, &clkrst->crc_clk_out_enb_l);
+
+       clock_enable(PERIPH_ID_CPU);
 }
 
 static int is_cpu_powered(void)
@@ -179,7 +178,7 @@ static void enable_cpu_power_rail(void)
 static void reset_A9_cpu(int reset)
 {
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       u32 reg, cpu;
+       u32 cpu;
 
        /*
        * NOTE:  Regardless of whether the request is to hold the CPU in reset
@@ -193,44 +192,27 @@ static void reset_A9_cpu(int reset)
        cpu = SET_DBGRESET1 | SET_DERESET1 | SET_CPURESET1;
        writel(cpu, &clkrst->crc_cpu_cmplx_set);
 
-       reg = readl(&clkrst->crc_rst_dev_l);
        if (reset) {
                /* Now place CPU0 into reset */
                cpu |= SET_DBGRESET0 | SET_DERESET0 | SET_CPURESET0;
                writel(cpu, &clkrst->crc_cpu_cmplx_set);
-
-               /* Enable master CPU reset */
-               reg |= SWR_CPU_RST;
        } else {
                /* Take CPU0 out of reset */
                cpu = CLR_DBGRESET0 | CLR_DERESET0 | CLR_CPURESET0;
                writel(cpu, &clkrst->crc_cpu_cmplx_clr);
-
-               /* Disable master CPU reset */
-               reg &= ~SWR_CPU_RST;
        }
 
-       writel(reg, &clkrst->crc_rst_dev_l);
+       /* Enable/Disable master CPU reset */
+       reset_set_enable(PERIPH_ID_CPU, reset);
 }
 
 static void clock_enable_coresight(int enable)
 {
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       u32 rst, clk, src;
-
-       rst = readl(&clkrst->crc_rst_dev_u);
-       clk = readl(&clkrst->crc_clk_out_enb_u);
-
-       if (enable) {
-               rst &= ~SWR_CSITE_RST;
-               clk |= CLK_ENB_CSITE;
-       } else {
-               rst |= SWR_CSITE_RST;
-               clk &= ~CLK_ENB_CSITE;
-       }
+       u32 rst, src;
 
-       writel(clk, &clkrst->crc_clk_out_enb_u);
-       writel(rst, &clkrst->crc_rst_dev_u);
+       clock_set_enable(PERIPH_ID_CORESIGHT, enable);
+       reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
 
        if (enable) {
                /*
diff --git a/arch/arm/cpu/armv7/tegra2/clock.c b/arch/arm/cpu/armv7/tegra2/clock.c
new file mode 100644 (file)
index 0000000..67eed14
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* Tegra2 Clock control functions */
+
+#include <asm/io.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/timer.h>
+#include <asm/arch/tegra2.h>
+#include <common.h>
+
+#ifdef DEBUG
+#define assert(x)      \
+       ({ if (!(x)) printf("Assertion failure '%s' %s line %d\n", \
+               #x, __FILE__, __LINE__); })
+#else
+#define assert(x)
+#endif
+
+/*
+ * Get the oscillator frequency, from the corresponding hardware configuration
+ * field.
+ */
+enum clock_osc_freq clock_get_osc_freq(void)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 reg;
+
+       reg = readl(&clkrst->crc_osc_ctrl);
+       return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
+}
+
+unsigned long clock_start_pll(enum clock_pll_id clkid, u32 divm, u32 divn,
+               u32 divp, u32 cpcon, u32 lfcon)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 data;
+       struct clk_pll *pll;
+
+       assert(clock_pll_id_isvalid(clkid));
+       pll = &clkrst->crc_pll[clkid];
+
+       /*
+        * We cheat by treating all PLL (except PLLU) in the same fashion.
+        * This works only because:
+        * - same fields are always mapped at same offsets, except DCCON
+        * - DCCON is always 0, doesn't conflict
+        * - M,N, P of PLLP values are ignored for PLLP
+        */
+       data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
+       writel(data, &pll->pll_misc);
+
+       data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) |
+                       (0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT);
+
+       if (clkid == CLOCK_PLL_ID_USB)
+               data |= divp << PLLU_VCO_FREQ_SHIFT;
+       else
+               data |= divp << PLL_DIVP_SHIFT;
+       writel(data, &pll->pll_base);
+
+       /* calculate the stable time */
+       return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US;
+}
+
+void clock_set_enable(enum periph_id periph_id, int enable)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 *clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
+       u32 reg;
+
+       /* Enable/disable the clock to this peripheral */
+       assert(clock_periph_id_isvalid(periph_id));
+       reg = readl(clk);
+       if (enable)
+               reg |= PERIPH_MASK(periph_id);
+       else
+               reg &= ~PERIPH_MASK(periph_id);
+       writel(reg, clk);
+}
+
+void clock_enable(enum periph_id clkid)
+{
+       clock_set_enable(clkid, 1);
+}
+
+void clock_disable(enum periph_id clkid)
+{
+       clock_set_enable(clkid, 0);
+}
+
+void reset_set_enable(enum periph_id periph_id, int enable)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 *reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
+       u32 reg;
+
+       /* Enable/disable reset to the peripheral */
+       assert(clock_periph_id_isvalid(periph_id));
+       reg = readl(reset);
+       if (enable)
+               reg |= PERIPH_MASK(periph_id);
+       else
+               reg &= ~PERIPH_MASK(periph_id);
+       writel(reg, reset);
+}
+
+void reset_periph(enum periph_id periph_id, int us_delay)
+{
+       /* Put peripheral into reset */
+       reset_set_enable(periph_id, 1);
+       udelay(us_delay);
+
+       /* Remove reset */
+       reset_set_enable(periph_id, 0);
+
+       udelay(us_delay);
+}
+
+void reset_cmplx_set_enable(int cpu, int which, int reset)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 mask;
+
+       /* Form the mask, which depends on the cpu chosen. Tegra2 has 2 */
+       assert(cpu >= 0 && cpu < 2);
+       mask = which << cpu;
+
+       /* either enable or disable those reset for that CPU */
+       if (reset)
+               writel(mask, &clkrst->crc_cpu_cmplx_set);
+       else
+               writel(mask, &clkrst->crc_cpu_cmplx_clr);
+}
index 36e27b5f3fa72cc087b2de9cf826dbe71651e33d..a574c5355d6604ddea796448becaa3d492f64993 100644 (file)
 #ifndef _CLK_RST_H_
 #define _CLK_RST_H_
 
+/* PLL registers - there are several PLLs in the clock controller */
+struct clk_pll {
+       uint pll_base;          /* the control register */
+       uint pll_out;           /* output control */
+       uint reserved;
+       uint pll_misc;          /* other misc things */
+};
+
+/* PLL registers - there are several PLLs in the clock controller */
+struct clk_pll_simple {
+       uint pll_base;          /* the control register */
+       uint pll_misc;          /* other misc things */
+};
+
+/*
+ * Most PLLs use the clk_pll structure, but some have a simpler two-member
+ * structure for which we use clk_pll_simple. The reason for this non-
+ * othogonal setup is not stated.
+ */
+#define TEGRA_CLK_PLLS         6
+#define TEGRA_CLK_SIMPLE_PLLS  3       /* Number of simple PLLs */
+#define TEGRA_CLK_REGS         3       /* Number of clock enable registers */
+
 /* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
 struct clk_rst_ctlr {
-       uint crc_rst_src;               /* _RST_SOURCE_0,       0x00 */
-       uint crc_rst_dev_l;             /* _RST_DEVICES_L_0,    0x04 */
-       uint crc_rst_dev_h;             /* _RST_DEVICES_H_0,    0x08 */
-       uint crc_rst_dev_u;             /* _RST_DEVICES_U_0,    0x0C */
-       uint crc_clk_out_enb_l;         /* _CLK_OUT_ENB_L_0,    0x10 */
-       uint crc_clk_out_enb_h;         /* _CLK_OUT_ENB_H_0,    0x14 */
-       uint crc_clk_out_enb_u;         /* _CLK_OUT_ENB_U_0,    0x18 */
+       uint crc_rst_src;                       /* _RST_SOURCE_0,0x00 */
+       uint crc_rst_dev[TEGRA_CLK_REGS];       /* _RST_DEVICES_L/H/U_0 */
+       uint crc_clk_out_enb[TEGRA_CLK_REGS];   /* _CLK_OUT_ENB_L/H/U_0 */
        uint crc_reserved0;             /* reserved_0,          0x1C */
        uint crc_cclk_brst_pol;         /* _CCLK_BURST_POLICY_0,0x20 */
        uint crc_super_cclk_div;        /* _SUPER_CCLK_DIVIDER_0,0x24 */
@@ -52,44 +71,11 @@ struct clk_rst_ctlr {
        uint crc_osc_freq_det_stat;     /* _OSC_FREQ_DET_STATUS_0,0x5C */
        uint crc_reserved2[8];          /* reserved_2[8],       0x60-7C */
 
-       uint crc_pllc_base;             /* _PLLC_BASE_0,        0x80 */
-       uint crc_pllc_out;              /* _PLLC_OUT_0,         0x84 */
-       uint crc_reserved3;             /* reserved_3,          0x88 */
-       uint crc_pllc_misc;             /* _PLLC_MISC_0,        0x8C */
-
-       uint crc_pllm_base;             /* _PLLM_BASE_0,        0x90 */
-       uint crc_pllm_out;              /* _PLLM_OUT_0,         0x94 */
-       uint crc_reserved4;             /* reserved_4,          0x98 */
-       uint crc_pllm_misc;             /* _PLLM_MISC_0,        0x9C */
-
-       uint crc_pllp_base;             /* _PLLP_BASE_0,        0xA0 */
-       uint crc_pllp_outa;             /* _PLLP_OUTA_0,        0xA4 */
-       uint crc_pllp_outb;             /* _PLLP_OUTB_0,        0xA8 */
-       uint crc_pllp_misc;             /* _PLLP_MISC_0,        0xAC */
-
-       uint crc_plla_base;             /* _PLLA_BASE_0,        0xB0 */
-       uint crc_plla_out;              /* _PLLA_OUT_0,         0xB4 */
-       uint crc_reserved5;             /* reserved_5,          0xB8 */
-       uint crc_plla_misc;             /* _PLLA_MISC_0,        0xBC */
-
-       uint crc_pllu_base;             /* _PLLU_BASE_0,        0xC0 */
-       uint crc_reserved6;             /* _reserved_6,         0xC4 */
-       uint crc_reserved7;             /* _reserved_7,         0xC8 */
-       uint crc_pllu_misc;             /* _PLLU_MISC_0,        0xCC */
-
-       uint crc_plld_base;             /* _PLLD_BASE_0,        0xD0 */
-       uint crc_reserved8;             /* _reserved_8,         0xD4 */
-       uint crc_reserved9;             /* _reserved_9,         0xD8 */
-       uint crc_plld_misc;             /* _PLLD_MISC_0,        0xDC */
+       struct clk_pll crc_pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */
 
-       uint crc_pllx_base;             /* _PLLX_BASE_0,        0xE0 */
-       uint crc_pllx_misc;             /* _PLLX_MISC_0,        0xE4 */
+       /* PLLs from 0xe0 to 0xf4    */
+       struct clk_pll_simple crc_pll_simple[TEGRA_CLK_SIMPLE_PLLS];
 
-       uint crc_plle_base;             /* _PLLE_BASE_0,        0xE8 */
-       uint crc_plle_misc;             /* _PLLE_MISC_0,        0xEC */
-
-       uint crc_plls_base;             /* _PLLS_BASE_0,        0xF0 */
-       uint crc_plls_misc;             /* _PLLS_MISC_0,        0xF4 */
        uint crc_reserved10;            /* _reserved_10,        0xF8 */
        uint crc_reserved11;            /* _reserved_11,        0xFC */
 
@@ -157,8 +143,8 @@ struct clk_rst_ctlr {
 #define PLL_BYPASS             (1 << 31)
 #define PLL_ENABLE             (1 << 30)
 #define PLL_BASE_OVRRIDE       (1 << 28)
-#define PLL_DIVP               (1 << 20)       /* post divider, b22:20 */
-#define PLL_DIVM               0x0C            /* input divider, b4:0 */
+#define PLL_DIVP_VALUE         (1 << 20)       /* post divider, b22:20 */
+#define PLL_DIVM_VALUE         0x0C            /* input divider, b4:0 */
 
 #define SWR_UARTD_RST          (1 << 1)
 #define CLK_ENB_UARTD          (1 << 1)
@@ -191,9 +177,37 @@ struct clk_rst_ctlr {
 
 #define CPCON                  (1 << 8)
 
-#define SWR_SDMMC4_RST         (1 << 15)
-#define CLK_ENB_SDMMC4         (1 << 15)
-#define SWR_SDMMC3_RST         (1 << 5)
-#define CLK_ENB_SDMMC3         (1 << 5)
+/* CLK_RST_CONTROLLER_CLK_CPU_CMPLX_0 */
+#define CPU1_CLK_STP_SHIFT     9
+
+#define CPU0_CLK_STP_SHIFT     8
+#define CPU0_CLK_STP_MASK      (1U << CPU0_CLK_STP_SHIFT)
+
+/* CLK_RST_CONTROLLER_PLLx_BASE_0 */
+#define PLL_BYPASS_SHIFT       31
+#define PLL_BYPASS_MASK                (1U << PLL_BYPASS_SHIFT)
+
+#define PLL_ENABLE_SHIFT       30
+#define PLL_ENABLE_MASK                (1U << PLL_ENABLE_SHIFT)
+
+#define PLL_BASE_OVRRIDE_MASK  (1U << 28)
+
+#define PLL_DIVP_SHIFT         20
+
+#define PLL_DIVN_SHIFT         8
+
+#define PLL_DIVM_SHIFT         0
+
+/* CLK_RST_CONTROLLER_PLLx_MISC_0 */
+#define PLL_CPCON_SHIFT                8
+#define PLL_CPCON_MASK         (15U << PLL_CPCON_SHIFT)
+
+#define PLL_LFCON_SHIFT                4
+
+#define PLLU_VCO_FREQ_SHIFT    20
+
+/* CLK_RST_CONTROLLER_OSC_CTRL_0 */
+#define OSC_FREQ_SHIFT         30
+#define OSC_FREQ_MASK          (3U << OSC_FREQ_SHIFT)
 
 #endif /* CLK_RST_H */
diff --git a/arch/arm/include/asm/arch-tegra2/clock.h b/arch/arm/include/asm/arch-tegra2/clock.h
new file mode 100644 (file)
index 0000000..d01aec8
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* Tegra2 clock control functions */
+
+#ifndef _CLOCK_H
+
+
+/* Set of oscillator frequencies supported in the internal API. */
+enum clock_osc_freq {
+       /* All in MHz, so 13_0 is 13.0MHz */
+       CLOCK_OSC_FREQ_13_0,
+       CLOCK_OSC_FREQ_19_2,
+       CLOCK_OSC_FREQ_12_0,
+       CLOCK_OSC_FREQ_26_0,
+
+       CLOCK_OSC_FREQ_COUNT,
+};
+
+/* The PLLs supported by the hardware */
+enum clock_pll_id {
+       CLOCK_PLL_ID_FIRST,
+       CLOCK_PLL_ID_CGENERAL = CLOCK_PLL_ID_FIRST,
+       CLOCK_PLL_ID_MEMORY,
+       CLOCK_PLL_ID_PERIPH,
+       CLOCK_PLL_ID_AUDIO,
+       CLOCK_PLL_ID_USB,
+       CLOCK_PLL_ID_DISPLAY,
+
+       /* now the simple ones */
+       CLOCK_PLL_ID_FIRST_SIMPLE,
+       CLOCK_PLL_ID_XCPU = CLOCK_PLL_ID_FIRST_SIMPLE,
+       CLOCK_PLL_ID_EPCI,
+       CLOCK_PLL_ID_SFROM32KHZ,
+
+       CLOCK_PLL_ID_COUNT,
+};
+
+/* The clocks supported by the hardware */
+enum periph_id {
+       PERIPH_ID_FIRST,
+
+       /* Low word: 31:0 */
+       PERIPH_ID_CPU = PERIPH_ID_FIRST,
+       PERIPH_ID_RESERVED1,
+       PERIPH_ID_RESERVED2,
+       PERIPH_ID_AC97,
+       PERIPH_ID_RTC,
+       PERIPH_ID_TMR,
+       PERIPH_ID_UART1,
+       PERIPH_ID_UART2,
+
+       /* 8 */
+       PERIPH_ID_GPIO,
+       PERIPH_ID_SDMMC2,
+       PERIPH_ID_SPDIF,
+       PERIPH_ID_I2S1,
+       PERIPH_ID_I2C1,
+       PERIPH_ID_NDFLASH,
+       PERIPH_ID_SDMMC1,
+       PERIPH_ID_SDMMC4,
+
+       /* 16 */
+       PERIPH_ID_TWC,
+       PERIPH_ID_PWC,
+       PERIPH_ID_I2S2,
+       PERIPH_ID_EPP,
+       PERIPH_ID_VI,
+       PERIPH_ID_2D,
+       PERIPH_ID_USBD,
+       PERIPH_ID_ISP,
+
+       /* 24 */
+       PERIPH_ID_3D,
+       PERIPH_ID_IDE,
+       PERIPH_ID_DISP2,
+       PERIPH_ID_DISP1,
+       PERIPH_ID_HOST1X,
+       PERIPH_ID_VCP,
+       PERIPH_ID_RESERVED30,
+       PERIPH_ID_CACHE2,
+
+       /* Middle word: 63:32 */
+       PERIPH_ID_MEM,
+       PERIPH_ID_AHBDMA,
+       PERIPH_ID_APBDMA,
+       PERIPH_ID_RESERVED35,
+       PERIPH_ID_KBC,
+       PERIPH_ID_STAT_MON,
+       PERIPH_ID_PMC,
+       PERIPH_ID_FUSE,
+
+       /* 40 */
+       PERIPH_ID_KFUSE,
+       PERIPH_ID_SBC1,
+       PERIPH_ID_SNOR,
+       PERIPH_ID_SPI1,
+       PERIPH_ID_SBC2,
+       PERIPH_ID_XIO,
+       PERIPH_ID_SBC3,
+       PERIPH_ID_DVC_I2C,
+
+       /* 48 */
+       PERIPH_ID_DSI,
+       PERIPH_ID_TVO,
+       PERIPH_ID_MIPI,
+       PERIPH_ID_HDMI,
+       PERIPH_ID_CSI,
+       PERIPH_ID_TVDAC,
+       PERIPH_ID_I2C2,
+       PERIPH_ID_UART3,
+
+       /* 56 */
+       PERIPH_ID_RESERVED56,
+       PERIPH_ID_EMC,
+       PERIPH_ID_USB2,
+       PERIPH_ID_USB3,
+       PERIPH_ID_MPE,
+       PERIPH_ID_VDE,
+       PERIPH_ID_BSEA,
+       PERIPH_ID_BSEV,
+
+       /* Upper word 95:64 */
+       PERIPH_ID_SPEEDO,
+       PERIPH_ID_UART4,
+       PERIPH_ID_UART5,
+       PERIPH_ID_I2C3,
+       PERIPH_ID_SBC4,
+       PERIPH_ID_SDMMC3,
+       PERIPH_ID_PCIE,
+       PERIPH_ID_OWR,
+
+       /* 72 */
+       PERIPH_ID_AFI,
+       PERIPH_ID_CORESIGHT,
+       PERIPH_ID_RESERVED74,
+       PERIPH_ID_AVPUCQ,
+       PERIPH_ID_RESERVED76,
+       PERIPH_ID_RESERVED77,
+       PERIPH_ID_RESERVED78,
+       PERIPH_ID_RESERVED79,
+
+       /* 80 */
+       PERIPH_ID_RESERVED80,
+       PERIPH_ID_RESERVED81,
+       PERIPH_ID_RESERVED82,
+       PERIPH_ID_RESERVED83,
+       PERIPH_ID_IRAMA,
+       PERIPH_ID_IRAMB,
+       PERIPH_ID_IRAMC,
+       PERIPH_ID_IRAMD,
+
+       /* 88 */
+       PERIPH_ID_CRAM2,
+
+       PERIPH_ID_COUNT,
+};
+
+/* Converts a clock number to a clock register: 0=L, 1=H, 2=U */
+#define PERIPH_REG(id) ((id) >> 5)
+
+/* Mask value for a clock (within PERIPH_REG(id)) */
+#define PERIPH_MASK(id) (1 << ((id) & 0x1f))
+
+/* return 1 if a PLL ID is in range */
+#define clock_pll_id_isvalid(id) ((id) >= CLOCK_PLL_ID_FIRST && \
+               (id) < CLOCK_PLL_ID_COUNT)
+
+/* return 1 if a peripheral ID is in range */
+#define clock_periph_id_isvalid(id) ((id) >= PERIPH_ID_FIRST && \
+               (id) < PERIPH_ID_COUNT)
+
+/* PLL stabilization delay in usec */
+#define CLOCK_PLL_STABLE_DELAY_US 300
+
+/* return the current oscillator clock frequency */
+enum clock_osc_freq clock_get_osc_freq(void);
+
+/*
+ * Start PLL using the provided configuration parameters.
+ *
+ * @param id   clock id
+ * @param divm input divider
+ * @param divn feedback divider
+ * @param divp post divider 2^n
+ * @param cpcon        charge pump setup control
+ * @param lfcon        loop filter setup control
+ *
+ * @returns monotonic time in us that the PLL will be stable
+ */
+unsigned long clock_start_pll(enum clock_pll_id id, u32 divm, u32 divn,
+               u32 divp, u32 cpcon, u32 lfcon);
+
+/*
+ * Enable a clock
+ *
+ * @param id   clock id
+ */
+void clock_enable(enum periph_id clkid);
+
+/*
+ * Set whether a clock is enabled or disabled.
+ *
+ * @param id           clock id
+ * @param enable       1 to enable, 0 to disable
+ */
+void clock_set_enable(enum periph_id clkid, int enable);
+
+/*
+ * Reset a peripheral. This puts it in reset, waits for a delay, then takes
+ * it out of reset and waits for th delay again.
+ *
+ * @param periph_id    peripheral to reset
+ * @param us_delay     time to delay in microseconds
+ */
+void reset_periph(enum periph_id periph_id, int us_delay);
+
+/*
+ * Put a peripheral into or out of reset.
+ *
+ * @param periph_id    peripheral to reset
+ * @param enable       1 to put into reset, 0 to take out of reset
+ */
+void reset_set_enable(enum periph_id periph_id, int enable);
+
+
+/* CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET/CLR_0 */
+enum crc_reset_id {
+       /* Things we can hold in reset for each CPU */
+       crc_rst_cpu = 1,
+       crc_rst_de = 1 << 2,    /* What is de? */
+       crc_rst_watchdog = 1 << 3,
+       crc_rst_debug = 1 << 4,
+};
+
+/*
+ * Put parts of the CPU complex into or out of reset.\
+ *
+ * @param cpu          cpu number (0 or 1 on Tegra2)
+ * @param which                which parts of the complex to affect (OR of crc_reset_id)
+ * @param reset                1 to assert reset, 0 to de-assert
+ */
+void reset_cmplx_set_enable(int cpu, int which, int reset);
+
+#endif
index 5eca5eb344b6307518ccef12650e87aa6cc2acf7..945141e7d3c498cf2f30f6f61984f75162b39080 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/arch/sys_proto.h>
 
 #include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/uart.h>
 #include "board.h"
@@ -76,33 +77,28 @@ int timer_init(void)
 static void clock_init_uart(void)
 {
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll *pll = &clkrst->crc_pll[CLOCK_PLL_ID_PERIPH];
        u32 reg;
 
-       reg = readl(&clkrst->crc_pllp_base);
+       reg = readl(&pll->pll_base);
        if (!(reg & PLL_BASE_OVRRIDE)) {
                /* Override pllp setup for 216MHz operation. */
-               reg = (PLL_BYPASS | PLL_BASE_OVRRIDE | PLL_DIVP);
-               reg |= (((NVRM_PLLP_FIXED_FREQ_KHZ/500) << 8) | PLL_DIVM);
-               writel(reg, &clkrst->crc_pllp_base);
+               reg = (PLL_BYPASS | PLL_BASE_OVRRIDE | PLL_DIVP_VALUE);
+               reg |= (((NVRM_PLLP_FIXED_FREQ_KHZ/500) << 8) | PLL_DIVM_VALUE);
+               writel(reg, &pll->pll_base);
 
                reg |= PLL_ENABLE;
-               writel(reg, &clkrst->crc_pllp_base);
+               writel(reg, &pll->pll_base);
 
                reg &= ~PLL_BYPASS;
-               writel(reg, &clkrst->crc_pllp_base);
+               writel(reg, &pll->pll_base);
        }
 
        /* Now do the UART reset/clock enable */
 #if defined(CONFIG_TEGRA2_ENABLE_UARTA)
-       /* Assert Reset to UART */
-       reg = readl(&clkrst->crc_rst_dev_l);
-       reg |= SWR_UARTA_RST;           /* SWR_UARTA_RST = 1 */
-       writel(reg, &clkrst->crc_rst_dev_l);
-
-       /* Enable clk to UART */
-       reg = readl(&clkrst->crc_clk_out_enb_l);
-       reg |= CLK_ENB_UARTA;           /* CLK_ENB_UARTA = 1 */
-       writel(reg, &clkrst->crc_clk_out_enb_l);
+       /* Assert UART reset and enable clock */
+       reset_set_enable(PERIPH_ID_UART1, 1);
+       clock_enable(PERIPH_ID_UART1);
 
        /* Enable pllp_out0 to UART */
        reg = readl(&clkrst->crc_clk_src_uarta);
@@ -113,20 +109,12 @@ static void clock_init_uart(void)
        udelay(2);
 
        /* De-assert reset to UART */
-       reg = readl(&clkrst->crc_rst_dev_l);
-       reg &= ~SWR_UARTA_RST;          /* SWR_UARTA_RST = 0 */
-       writel(reg, &clkrst->crc_rst_dev_l);
+       reset_set_enable(PERIPH_ID_UART1, 0);
 #endif /* CONFIG_TEGRA2_ENABLE_UARTA */
 #if defined(CONFIG_TEGRA2_ENABLE_UARTD)
-       /* Assert Reset to UART */
-       reg = readl(&clkrst->crc_rst_dev_u);
-       reg |= SWR_UARTD_RST;           /* SWR_UARTD_RST = 1 */
-       writel(reg, &clkrst->crc_rst_dev_u);
-
-       /* Enable clk to UART */
-       reg = readl(&clkrst->crc_clk_out_enb_u);
-       reg |= CLK_ENB_UARTD;           /* CLK_ENB_UARTD = 1 */
-       writel(reg, &clkrst->crc_clk_out_enb_u);
+       /* Assert UART reset and enable clock */
+       reset_set_enable(PERIPH_ID_UART4, 1);
+       clock_enable(PERIPH_ID_UART4);
 
        /* Enable pllp_out0 to UART */
        reg = readl(&clkrst->crc_clk_src_uartd);
@@ -137,9 +125,7 @@ static void clock_init_uart(void)
        udelay(2);
 
        /* De-assert reset to UART */
-       reg = readl(&clkrst->crc_rst_dev_u);
-       reg &= ~SWR_UARTD_RST;          /* SWR_UARTD_RST = 0 */
-       writel(reg, &clkrst->crc_rst_dev_u);
+       reset_set_enable(PERIPH_ID_UART4, 0);
 #endif /* CONFIG_TEGRA2_ENABLE_UARTD */
 }
 
@@ -183,16 +169,8 @@ static void clock_init_mmc(void)
        u32 reg;
 
        /* Do the SDMMC resets/clock enables */
-
-       /* Assert Reset to SDMMC4 */
-       reg = readl(&clkrst->crc_rst_dev_l);
-       reg |= SWR_SDMMC4_RST;          /* SWR_SDMMC4_RST = 1 */
-       writel(reg, &clkrst->crc_rst_dev_l);
-
-       /* Enable clk to SDMMC4 */
-       reg = readl(&clkrst->crc_clk_out_enb_l);
-       reg |= CLK_ENB_SDMMC4;          /* CLK_ENB_SDMMC4 = 1 */
-       writel(reg, &clkrst->crc_clk_out_enb_l);
+       reset_set_enable(PERIPH_ID_SDMMC4, 1);
+       clock_enable(PERIPH_ID_SDMMC4);
 
        /* Enable pllp_out0 to SDMMC4 */
        reg = readl(&clkrst->crc_clk_src_sdmmc4);
@@ -206,20 +184,10 @@ static void clock_init_mmc(void)
         */
        udelay(2);
 
-       /* De-assert reset to SDMMC4 */
-       reg = readl(&clkrst->crc_rst_dev_l);
-       reg &= ~SWR_SDMMC4_RST;         /* SWR_SDMMC4_RST = 0 */
-       writel(reg, &clkrst->crc_rst_dev_l);
-
-       /* Assert Reset to SDMMC3 */
-       reg = readl(&clkrst->crc_rst_dev_u);
-       reg |= SWR_SDMMC3_RST;          /* SWR_SDMMC3_RST = 1 */
-       writel(reg, &clkrst->crc_rst_dev_u);
+       reset_set_enable(PERIPH_ID_SDMMC4, 1);
 
-       /* Enable clk to SDMMC3 */
-       reg = readl(&clkrst->crc_clk_out_enb_u);
-       reg |= CLK_ENB_SDMMC3;          /* CLK_ENB_SDMMC3 = 1 */
-       writel(reg, &clkrst->crc_clk_out_enb_u);
+       reset_set_enable(PERIPH_ID_SDMMC3, 1);
+       clock_enable(PERIPH_ID_SDMMC3);
 
        /* Enable pllp_out0 to SDMMC4, set divisor to 11 for 20MHz */
        reg = readl(&clkrst->crc_clk_src_sdmmc3);
@@ -230,10 +198,7 @@ static void clock_init_mmc(void)
        /* wait for 2us */
        udelay(2);
 
-       /* De-assert reset to SDMMC3 */
-       reg = readl(&clkrst->crc_rst_dev_u);
-       reg &= ~SWR_SDMMC3_RST;         /* SWR_SDMMC3_RST = 0 */
-       writel(reg, &clkrst->crc_rst_dev_u);
+       reset_set_enable(PERIPH_ID_SDMMC3, 0);
 }
 
 /*