mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
Tegra2: Add more clock support
This adds functions to enable/disable clocks and reset to on-chip peripherals. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
39d3416f0a
commit
b4ba2be8dc
6 changed files with 524 additions and 142 deletions
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
u32 rst, 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
/*
|
||||
|
|
158
arch/arm/cpu/armv7/tegra2/clock.c
Normal file
158
arch/arm/cpu/armv7/tegra2/clock.c
Normal file
|
@ -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);
|
||||
}
|
|
@ -24,15 +24,34 @@
|
|||
#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 */
|
||||
struct clk_pll crc_pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */
|
||||
|
||||
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 */
|
||||
/* PLLs from 0xe0 to 0xf4 */
|
||||
struct clk_pll_simple crc_pll_simple[TEGRA_CLK_SIMPLE_PLLS];
|
||||
|
||||
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 */
|
||||
|
||||
uint crc_pllx_base; /* _PLLX_BASE_0, 0xE0 */
|
||||
uint crc_pllx_misc; /* _PLLX_MISC_0, 0xE4 */
|
||||
|
||||
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 */
|
||||
|
|
263
arch/arm/include/asm/arch-tegra2/clock.h
Normal file
263
arch/arm/include/asm/arch-tegra2/clock.h
Normal file
|
@ -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
|
|
@ -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);
|
||||
reset_set_enable(PERIPH_ID_SDMMC4, 1);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue