diff options
| -rw-r--r-- | arch/arm/cpu/armv7/tegra2/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/tegra2/ap20.c | 52 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/tegra2/clock.c | 158 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-tegra2/clk_rst.h | 112 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-tegra2/clock.h | 263 | ||||
| -rw-r--r-- | board/nvidia/common/board.c | 79 | 
6 files changed, 524 insertions, 142 deletions
| diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile index f1ea91585..b35764c32 100644 --- a/arch/arm/cpu/armv7/tegra2/Makefile +++ b/arch/arm/cpu/armv7/tegra2/Makefile @@ -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)) diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c index 60dd5dfc0..e3832e23f 100644 --- a/arch/arm/cpu/armv7/tegra2/ap20.c +++ b/arch/arm/cpu/armv7/tegra2/ap20.c @@ -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 index 000000000..67eed1404 --- /dev/null +++ b/arch/arm/cpu/armv7/tegra2/clock.c @@ -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); +} diff --git a/arch/arm/include/asm/arch-tegra2/clk_rst.h b/arch/arm/include/asm/arch-tegra2/clk_rst.h index 36e27b5f3..a574c5355 100644 --- a/arch/arm/include/asm/arch-tegra2/clk_rst.h +++ b/arch/arm/include/asm/arch-tegra2/clk_rst.h @@ -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 */ - -	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 index 000000000..d01aec825 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra2/clock.h @@ -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 diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index 5eca5eb34..945141e7d 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -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);  }  /* |