Merge branch 'master' of git://git.denx.de/u-boot-arm

This commit is contained in:
Stefano Babic 2013-02-23 10:13:40 +01:00
commit 9cd9b34dc7
488 changed files with 18843 additions and 15350 deletions

View file

@ -27,6 +27,10 @@ Poonam Aggrwal <poonam.aggrwal@freescale.com>
BSC9131RDB BSC9131
Naveen Burmi <NaveenBurmi@freescale.com>
BSC9132QDS BSC9132
Greg Allen <gallen@arlut.utexas.edu>
UTX8245 MPC8245
@ -603,6 +607,7 @@ Enric Balletbo i Serra <eballetbo@iseebcn.com>
igep0020 ARM ARMV7 (OMAP3xx SoC)
igep0030 ARM ARMV7 (OMAP3xx SoC)
igep0032 ARM ARMV7 (OMAP3xx SoC)
Eric Benard <eric@eukrea.com>
@ -815,6 +820,9 @@ Dave Peverley <dpeverley@mpc-data.co.uk>
omap730p2 ARM926EJS
Lars Poeschel <poeschel@lemonage.de>
pcm051 ARM ARMV7 (AM33xx Soc)
Mathieu Poirier <mathieu.poirier@linaro.org>
snowball ARM ARMV7 (u8500 SoC)

View file

@ -230,10 +230,6 @@ endif
# U-Boot objects....order is important (i.e. start must be first)
OBJS = $(CPUDIR)/start.o
ifeq ($(CPU),x86)
RESET_OBJS-$(CONFIG_X86_NO_RESET_VECTOR) += $(CPUDIR)/start16.o
RESET_OBJS-$(CONFIG_X86_NO_RESET_VECTOR) += $(CPUDIR)/resetvec.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += $(CPUDIR)/resetvec.o
endif
@ -241,7 +237,7 @@ ifeq ($(CPU),mpc85xx)
OBJS += $(CPUDIR)/resetvec.o
endif
OBJS := $(addprefix $(obj),$(OBJS) $(RESET_OBJS-))
OBJS := $(addprefix $(obj),$(OBJS))
HAVE_VENDOR_COMMON_LIB = $(if $(wildcard board/$(VENDOR)/common/Makefile),y,n)
@ -348,7 +344,7 @@ endif
ifeq ($(SOC),exynos)
LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o
endif
ifeq ($(SOC),tegra20)
ifneq ($(CONFIG_TEGRA),)
LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
LIBS-y += arch/$(ARCH)/cpu/tegra-common/libcputegra-common.o
LIBS-y += $(CPUDIR)/tegra-common/libtegra-common.o
@ -413,7 +409,7 @@ ALL-$(CONFIG_SPL) += $(obj)$(subst ",,$(CONFIG_SPL_TARGET))
ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin
# enable combined SPL/u-boot/dtb rules for tegra
ifeq ($(SOC),tegra20)
ifneq ($(CONFIG_TEGRA),)
ifeq ($(CONFIG_OF_SEPARATE),y)
ALL-y += $(obj)u-boot-dtb-tegra.bin
else
@ -485,8 +481,12 @@ $(obj)u-boot.sha1: $(obj)u-boot.bin
$(obj)u-boot.dis: $(obj)u-boot
$(OBJDUMP) -d $< > $@
$(obj)u-boot-with-spl.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $(obj)spl/u-boot-spl $(obj)spl/u-boot-spl-pad.bin
$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(or $(CONFIG_SPL_PAD_TO),0) \
-O binary $(obj)spl/u-boot-spl \
$(obj)spl/u-boot-spl-pad.bin
cat $(obj)spl/u-boot-spl-pad.bin $(obj)u-boot.bin > $@
rm $(obj)spl/u-boot-spl-pad.bin
@ -530,7 +530,7 @@ $(obj)u-boot.spr: $(obj)u-boot.img $(obj)spl/u-boot-spl.bin
conv=notrunc 2>/dev/null
cat $(obj)spl/u-boot-spl-pad.img $(obj)u-boot.img > $@
ifeq ($(SOC),tegra20)
ifneq ($(CONFIG_TEGRA),)
ifeq ($(CONFIG_OF_SEPARATE),y)
nodtb=dtb
dtbfile=$(obj)u-boot.dtb

21
README
View file

@ -2819,6 +2819,12 @@ FIT uImage format:
CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME
Filename to read to load U-Boot when reading from FAT
CONFIG_SPL_MPC83XX_WAIT_FOR_NAND
Set this for NAND SPL on PPC mpc83xx targets, so that
start.S waits for the rest of the SPL to load before
continuing (the hardware starts execution after just
loading the first page rather than the full 4K).
CONFIG_SPL_NAND_BASE
Include nand_base.c in the SPL. Requires
CONFIG_SPL_NAND_DRIVERS.
@ -2876,6 +2882,10 @@ FIT uImage format:
CONFIG_SPL_LIBGENERIC_SUPPORT
Support for lib/libgeneric.o in SPL binary
CONFIG_SPL_PAD_TO
Linker address to which the SPL should be padded before
appending the SPL payload.
CONFIG_SPL_TARGET
Final target image containing SPL and payload. Some SPLs
use an arch-specific makefile fragment instead, for
@ -3806,14 +3816,9 @@ Low Level (hardware related) configuration options:
be used if available. These functions may be faster under some
conditions but may increase the binary size.
- CONFIG_X86_NO_RESET_VECTOR
If defined, the x86 reset vector code is excluded. You will need
to do this when U-Boot is running from Coreboot.
- CONFIG_X86_NO_REAL_MODE
If defined, x86 real mode code is omitted. This assumes a
32-bit environment where such code is not needed. You will
need to do this when U-Boot is running from Coreboot.
- CONFIG_X86_RESET_VECTOR
If defined, the x86 reset vector code is included. This is not
needed when U-Boot is running from Coreboot.
Freescale QE/FMAN Firmware Support:

View file

@ -115,13 +115,13 @@ unsigned long long get_ticks(void)
{
ulong now = GPTCNT; /* current tick value */
if (now >= gd->lastinc) /* normal mode (non roll) */
if (now >= gd->arch.lastinc) /* normal mode (non roll) */
/* move stamp forward with absolut diff ticks */
gd->tbl += (now - gd->lastinc);
gd->arch.tbl += (now - gd->arch.lastinc);
else /* we have rollover of incrementer */
gd->tbl += (0xFFFFFFFF - gd->lastinc) + now;
gd->lastinc = now;
return gd->tbl;
gd->arch.tbl += (0xFFFFFFFF - gd->arch.lastinc) + now;
gd->arch.lastinc = now;
return gd->arch.tbl;
}
ulong get_timer_masked(void)

View file

@ -478,11 +478,11 @@ int get_clocks(void)
{
#ifdef CONFIG_FSL_ESDHC
#if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
#else
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK);
#endif
#endif
return 0;

View file

@ -32,8 +32,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define timestamp (gd->tbl)
#define lastinc (gd->lastinc)
#define timestamp (gd->arch.tbl)
#define lastinc (gd->arch.lastinc)
/* General purpose timers bitfields */
#define GPTCR_SWR (1<<15) /* Software reset */

View file

@ -51,8 +51,8 @@ int timer_init (void)
*((int32_t *) (CONFIG_SYS_TIMERBASE + TCLR)) = val; /* start timer */
/* reset time */
gd->lastinc = READ_TIMER; /* capture current incrementer value */
gd->tbl = 0; /* start "advancing" time stamp */
gd->arch.lastinc = READ_TIMER; /* capture current incrementer value */
gd->arch.tbl = 0; /* start "advancing" time stamp */
return(0);
}
@ -81,8 +81,8 @@ void __udelay (unsigned long usec)
tmp = get_timer (0); /* get current timestamp */
if ((tmo + tmp + 1) < tmp) { /* if setting this forward will roll */
/* time stamp, then reset time */
gd->lastinc = READ_TIMER; /* capture incrementer value */
gd->tbl = 0; /* start time stamp */
gd->arch.lastinc = READ_TIMER; /* capture incrementer value */
gd->arch.tbl = 0; /* start time stamp */
} else {
tmo += tmp; /* else, set advancing stamp wake up time */
}
@ -94,12 +94,15 @@ ulong get_timer_masked (void)
{
ulong now = READ_TIMER; /* current tick value */
if (now >= gd->lastinc) /* normal mode (non roll) */
gd->tbl += (now - gd->lastinc); /* move stamp fordward with absoulte diff ticks */
else /* we have rollover of incrementer */
gd->tbl += (0xFFFFFFFF - gd->lastinc) + now;
gd->lastinc = now;
return gd->tbl;
if (now >= gd->arch.lastinc) { /* normal mode (non roll) */
/* move stamp fordward with absoulte diff ticks */
gd->arch.tbl += (now - gd->arch.lastinc);
} else {
/* we have rollover of incrementer */
gd->arch.tbl += (0xFFFFFFFF - gd->arch.lastinc) + now;
}
gd->arch.lastinc = now;
return gd->arch.tbl;
}
/* waits specified delay value and resets timestamp */

View file

@ -28,6 +28,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)libtegra-common.o
COBJS-$(CONFIG_SPL_BUILD) += spl.o
COBJS-y += cpu.o
SRCS := $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))

View file

@ -0,0 +1,333 @@
/*
* Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/gp_padctrl.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/scu.h>
#include "cpu.h"
int get_num_cpus(void)
{
struct apb_misc_gp_ctlr *gp;
uint rev;
gp = (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
switch (rev) {
case CHIPID_TEGRA20:
return 2;
break;
case CHIPID_TEGRA30:
case CHIPID_TEGRA114:
default:
return 4;
break;
}
}
/*
* Timing tables for each SOC for all four oscillator options.
*/
struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = {
/* T20: 1 GHz */
/* n, m, p, cpcon */
{{ 1000, 13, 0, 12}, /* OSC 13M */
{ 625, 12, 0, 8}, /* OSC 19.2M */
{ 1000, 12, 0, 12}, /* OSC 12M */
{ 1000, 26, 0, 12}, /* OSC 26M */
},
/* T25: 1.2 GHz */
{{ 923, 10, 0, 12},
{ 750, 12, 0, 8},
{ 600, 6, 0, 12},
{ 600, 13, 0, 12},
},
/* T30: 1.4 GHz */
{{ 862, 8, 0, 8},
{ 583, 8, 0, 4},
{ 700, 6, 0, 8},
{ 700, 13, 0, 8},
},
/* T114: 1.4 GHz */
{{ 862, 8, 0, 8},
{ 583, 8, 0, 4},
{ 696, 12, 0, 8},
{ 700, 13, 0, 8},
},
};
void adjust_pllp_out_freqs(void)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_PERIPH];
u32 reg;
/* Set T30 PLLP_OUT1, 2, 3 & 4 freqs to 9.6, 48, 102 & 204MHz */
reg = readl(&pll->pll_out[0]); /* OUTA, contains OUT2 / OUT1 */
reg |= (IN_408_OUT_48_DIVISOR << PLLP_OUT2_RATIO) | PLLP_OUT2_OVR
| (IN_408_OUT_9_6_DIVISOR << PLLP_OUT1_RATIO) | PLLP_OUT1_OVR;
writel(reg, &pll->pll_out[0]);
reg = readl(&pll->pll_out[1]); /* OUTB, contains OUT4 / OUT3 */
reg |= (IN_408_OUT_204_DIVISOR << PLLP_OUT4_RATIO) | PLLP_OUT4_OVR
| (IN_408_OUT_102_DIVISOR << PLLP_OUT3_RATIO) | PLLP_OUT3_OVR;
writel(reg, &pll->pll_out[1]);
}
int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm,
u32 divp, u32 cpcon)
{
u32 reg;
/* If PLLX is already enabled, just return */
if (readl(&pll->pll_base) & PLL_ENABLE_MASK) {
debug("pllx_set_rate: PLLX already enabled, returning\n");
return 0;
}
debug(" pllx_set_rate entry\n");
/* Set BYPASS, m, n and p to PLLX_BASE */
reg = PLL_BYPASS_MASK | (divm << PLL_DIVM_SHIFT);
reg |= ((divn << PLL_DIVN_SHIFT) | (divp << PLL_DIVP_SHIFT));
writel(reg, &pll->pll_base);
/* Set cpcon to PLLX_MISC */
reg = (cpcon << PLL_CPCON_SHIFT);
/* Set dccon to PLLX_MISC if freq > 600MHz */
if (divn > 600)
reg |= (1 << PLL_DCCON_SHIFT);
writel(reg, &pll->pll_misc);
/* Enable PLLX */
reg = readl(&pll->pll_base);
reg |= PLL_ENABLE_MASK;
/* Disable BYPASS */
reg &= ~PLL_BYPASS_MASK;
writel(reg, &pll->pll_base);
/* Set lock_enable to PLLX_MISC */
reg = readl(&pll->pll_misc);
reg |= PLL_LOCK_ENABLE_MASK;
writel(reg, &pll->pll_misc);
return 0;
}
void init_pllx(void)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
struct clk_pll_simple *pll = &clkrst->crc_pll_simple[SIMPLE_PLLX];
int chip_type;
enum clock_osc_freq osc;
struct clk_pll_table *sel;
debug("init_pllx entry\n");
/* get chip type */
chip_type = tegra_get_chip_type();
debug(" init_pllx: chip_type = %d\n", chip_type);
/* get osc freq */
osc = clock_get_osc_freq();
debug(" init_pllx: osc = %d\n", osc);
/* set pllx */
sel = &tegra_pll_x_table[chip_type][osc];
pllx_set_rate(pll, sel->n, sel->m, sel->p, sel->cpcon);
/* adjust PLLP_out1-4 on T30/T114 */
if (chip_type == TEGRA_SOC_T30 || chip_type == TEGRA_SOC_T114) {
debug(" init_pllx: adjusting PLLP out freqs\n");
adjust_pllp_out_freqs();
}
}
void enable_cpu_clock(int enable)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
u32 clk;
/*
* NOTE:
* Regardless of whether the request is to enable or disable the CPU
* clock, every processor in the CPU complex except the master (CPU 0)
* will have it's clock stopped because the AVP only talks to the
* master.
*/
if (enable) {
/* Initialize PLLX */
init_pllx();
/* Wait until all clocks are stable */
udelay(PLL_STABILIZATION_DELAY);
writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
}
/*
* Read the register containing the individual CPU clock enables and
* always stop the clocks to CPUs > 0.
*/
clk = readl(&clkrst->crc_clk_cpu_cmplx);
clk |= 1 << CPU1_CLK_STP_SHIFT;
if (get_num_cpus() == 4)
clk |= (1 << CPU2_CLK_STP_SHIFT) + (1 << CPU3_CLK_STP_SHIFT);
/* Stop/Unstop the CPU clock */
clk &= ~CPU0_CLK_STP_MASK;
clk |= !enable << CPU0_CLK_STP_SHIFT;
writel(clk, &clkrst->crc_clk_cpu_cmplx);
clock_enable(PERIPH_ID_CPU);
}
static int is_cpu_powered(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
}
static void remove_cpu_io_clamps(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
/* Remove the clamps on the CPU I/O signals */
reg = readl(&pmc->pmc_remove_clamping);
reg |= CPU_CLMP;
writel(reg, &pmc->pmc_remove_clamping);
/* Give I/O signals time to stabilize */
udelay(IO_STABILIZATION_DELAY);
}
void powerup_cpu(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
int timeout = IO_STABILIZATION_DELAY;
if (!is_cpu_powered()) {
/* Toggle the CPU power state (OFF -> ON) */
reg = readl(&pmc->pmc_pwrgate_toggle);
reg &= PARTID_CP;
reg |= START_CP;
writel(reg, &pmc->pmc_pwrgate_toggle);
/* Wait for the power to come up */
while (!is_cpu_powered()) {
if (timeout-- == 0)
printf("CPU failed to power up!\n");
else
udelay(10);
}
/*
* Remove the I/O clamps from CPU power partition.
* Recommended only on a Warm boot, if the CPU partition gets
* power gated. Shouldn't cause any harm when called after a
* cold boot according to HW, probably just redundant.
*/
remove_cpu_io_clamps();
}
}
void reset_A9_cpu(int reset)
{
/*
* NOTE: Regardless of whether the request is to hold the CPU in reset
* or take it out of reset, every processor in the CPU complex
* except the master (CPU 0) will be held in reset because the
* AVP only talks to the master. The AVP does not know that there
* are multiple processors in the CPU complex.
*/
int mask = crc_rst_cpu | crc_rst_de | crc_rst_debug;
int num_cpus = get_num_cpus();
int cpu;
debug("reset_a9_cpu entry\n");
/* Hold CPUs 1 onwards in reset, and CPU 0 if asked */
for (cpu = 1; cpu < num_cpus; cpu++)
reset_cmplx_set_enable(cpu, mask, 1);
reset_cmplx_set_enable(0, mask, reset);
/* Enable/Disable master CPU reset */
reset_set_enable(PERIPH_ID_CPU, reset);
}
void clock_enable_coresight(int enable)
{
u32 rst, src = 2;
int chip;
debug("clock_enable_coresight entry\n");
clock_set_enable(PERIPH_ID_CORESIGHT, enable);
reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
if (enable) {
/*
* Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
* 1.5, giving an effective frequency of 144MHz.
* Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
* (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
*
* Clock divider request for 204MHz would setup CSITE clock as
* 144MHz for PLLP base 216MHz and 204MHz for PLLP base 408MHz
*/
chip = tegra_get_chip_type();
if (chip == TEGRA_SOC_T30 || chip == TEGRA_SOC_T114)
src = CLK_DIVIDER(NVBL_PLLP_KHZ, 204000);
else if (chip == TEGRA_SOC_T20 || chip == TEGRA_SOC_T25)
src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
else
printf("%s: Unknown chip type %X!\n", __func__, chip);
clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
/* Unlock the CPU CoreSight interfaces */
rst = CORESIGHT_UNLOCK;
writel(rst, CSITE_CPU_DBG0_LAR);
writel(rst, CSITE_CPU_DBG1_LAR);
if (get_num_cpus() == 4) {
writel(rst, CSITE_CPU_DBG2_LAR);
writel(rst, CSITE_CPU_DBG3_LAR);
}
}
}
void halt_avp(void)
{
for (;;) {
writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
| HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
FLOW_CTLR_HALT_COP_EVENTS);
}
}

View file

@ -26,7 +26,13 @@
#define PLL_STABILIZATION_DELAY (300)
#define IO_STABILIZATION_DELAY (1000)
#if defined(CONFIG_TEGRA20)
#define NVBL_PLLP_KHZ (216000)
#elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114)
#define NVBL_PLLP_KHZ (408000)
#else
#error "Unknown Tegra chip!"
#endif
#define PLLX_ENABLED (1 << 30)
#define CCLK_BURST_POLICY 0x20008888
@ -44,50 +50,11 @@
#define CORESIGHT_UNLOCK 0xC5ACCE55;
/* AP20-Specific Base Addresses */
/* AP20 Base physical address of SDRAM. */
#define AP20_BASE_PA_SDRAM 0x00000000
/* AP20 Base physical address of internal SRAM. */
#define AP20_BASE_PA_SRAM 0x40000000
/* AP20 Size of internal SRAM (256KB). */
#define AP20_BASE_PA_SRAM_SIZE 0x00040000
/* AP20 Base physical address of flash. */
#define AP20_BASE_PA_NOR_FLASH 0xD0000000
/* AP20 Base physical address of boot information table. */
#define AP20_BASE_PA_BOOT_INFO AP20_BASE_PA_SRAM
/*
* Super-temporary stacks for EXTREMELY early startup. The values chosen for
* these addresses must be valid on ALL SOCs because this value is used before
* we are able to differentiate between the SOC types.
*
* NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
* stack is placed below the AVP stack. Once the CPU stack has been moved,
* the AVP is free to use the IRAM the CPU stack previously occupied if
* it should need to do so.
*
* NOTE: In multi-processor CPU complex configurations, each processor will have
* its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
* limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
* stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
* CPU.
*/
/* Common AVP early boot stack limit */
#define AVP_EARLY_BOOT_STACK_LIMIT \
(AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
/* Common AVP early boot stack size */
#define AVP_EARLY_BOOT_STACK_SIZE 0x1000
/* Common CPU early boot stack limit */
#define CPU_EARLY_BOOT_STACK_LIMIT \
(AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
/* Common CPU early boot stack size */
#define CPU_EARLY_BOOT_STACK_SIZE 0x1000
#define EXCEP_VECTOR_CPU_RESET_VECTOR (NV_PA_EVP_BASE + 0x100)
#define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0)
#define CSITE_CPU_DBG1_LAR (NV_PA_CSITE_BASE + 0x12FB0)
#define CSITE_CPU_DBG2_LAR (NV_PA_CSITE_BASE + 0x14FB0)
#define CSITE_CPU_DBG3_LAR (NV_PA_CSITE_BASE + 0x16FB0)
#define FLOW_CTLR_HALT_COP_EVENTS (NV_PA_FLOW_BASE + 4)
#define FLOW_MODE_STOP 2
@ -95,6 +62,23 @@
#define HALT_COP_EVENT_IRQ_1 (1 << 11)
#define HALT_COP_EVENT_FIQ_1 (1 << 9)
void start_cpu(u32 reset_vector);
int ap20_cpu_is_cortexa9(void);
#define FLOW_MODE_NONE 0
#define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE)
struct clk_pll_table {
u16 n;
u16 m;
u8 p;
u8 cpcon;
};
void clock_enable_coresight(int enable);
void enable_cpu_clock(int enable);
void halt_avp(void) __attribute__ ((noreturn));
void init_pllx(void);
void powerup_cpu(void);
void reset_A9_cpu(int reset);
void start_cpu(u32 reset_vector);
int tegra_get_chip_type(void);
void adjust_pllp_out_freqs(void);

View file

@ -23,7 +23,6 @@
* MA 02111-1307 USA
*/
#include <common.h>
#include "cpu.h"
#include <spl.h>
#include <asm/io.h>
@ -32,7 +31,7 @@
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/board.h>
#include <asm/arch/spl.h>
#include "cpu.h"
void spl_board_init(void)
{

View file

@ -0,0 +1,42 @@
#
# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2000-2008
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
#COBJS-y += cpu.o t11x.o
COBJS-y += cpu.o
SRCS := $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,19 @@
#
# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2002
# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
USE_PRIVATE_LIBGCC = yes

View file

@ -0,0 +1,297 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/flow.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/pmc.h>
#include "../tegra-common/cpu.h"
/* Tegra114-specific CPU init code */
static void enable_cpu_power_rail(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
u32 reg;
debug("enable_cpu_power_rail entry\n");
/* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */
pinmux_tristate_disable(PINGRP_PWR_I2C_SCL);
pinmux_tristate_disable(PINGRP_PWR_I2C_SDA);
/*
* Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz),
* set it for 25ms (102MHz * .025)
*/
reg = 0x26E8F0;
writel(reg, &pmc->pmc_cpupwrgood_timer);
/* Set polarity to 0 (normal) and enable CPUPWRREQ_OE */
clrbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_POL);
setbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_OE);
/*
* Set CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0_CAR2PMC_CPU_ACK_WIDTH
* to 408 to satisfy the requirement of having at least 16 CPU clock
* cycles before clamp removal.
*/
clrbits_le32(&clkrst->crc_cpu_softrst_ctrl2, 0xFFF);
setbits_le32(&clkrst->crc_cpu_softrst_ctrl2, 408);
}
static void enable_cpu_clocks(void)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
u32 reg;
debug("enable_cpu_clocks entry\n");
/* Wait for PLL-X to lock */
do {
reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
} while ((reg & (1 << 27)) == 0);
/* Wait until all clocks are stable */
udelay(PLL_STABILIZATION_DELAY);
writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
/* Always enable the main CPU complex clocks */
clock_enable(PERIPH_ID_CPU);
clock_enable(PERIPH_ID_CPULP);
clock_enable(PERIPH_ID_CPUG);
}
static void remove_cpu_resets(void)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
u32 reg;
debug("remove_cpu_resets entry\n");
/* Take the slow non-CPU partition out of reset */
reg = readl(&clkrst->crc_rst_cpulp_cmplx_clr);
writel((reg | CLR_NONCPURESET), &clkrst->crc_rst_cpulp_cmplx_clr);
/* Take the fast non-CPU partition out of reset */
reg = readl(&clkrst->crc_rst_cpug_cmplx_clr);
writel((reg | CLR_NONCPURESET), &clkrst->crc_rst_cpug_cmplx_clr);
/* Clear the SW-controlled reset of the slow cluster */
reg = readl(&clkrst->crc_rst_cpulp_cmplx_clr);
reg |= (CLR_CPURESET0+CLR_DBGRESET0+CLR_CORERESET0+CLR_CXRESET0);
writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr);
/* Clear the SW-controlled reset of the fast cluster */
reg = readl(&clkrst->crc_rst_cpug_cmplx_clr);
reg |= (CLR_CPURESET0+CLR_DBGRESET0+CLR_CORERESET0+CLR_CXRESET0);
reg |= (CLR_CPURESET1+CLR_DBGRESET1+CLR_CORERESET1+CLR_CXRESET1);
reg |= (CLR_CPURESET2+CLR_DBGRESET2+CLR_CORERESET2+CLR_CXRESET2);
reg |= (CLR_CPURESET3+CLR_DBGRESET3+CLR_CORERESET3+CLR_CXRESET3);
writel(reg, &clkrst->crc_rst_cpug_cmplx_clr);
}
/**
* The T114 requires some special clock initialization, including setting up
* the DVC I2C, turning on MSELECT and selecting the G CPU cluster
*/
void t114_init_clocks(void)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
u32 val;
debug("t114_init_clocks entry\n");
/* Set active CPU cluster to G */
clrbits_le32(&flow->cluster_control, 1);
/*
* Switch system clock to PLLP_OUT4 (108 MHz), AVP will now run
* at 108 MHz. This is glitch free as only the source is changed, no
* special precaution needed.
*/
val = (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) |
(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) |
(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) |
(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) |
(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT);
writel(val, &clkrst->crc_sclk_brst_pol);
writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div);
debug("Setting up PLLX\n");
init_pllx();
val = (1 << CLK_SYS_RATE_AHB_RATE_SHIFT);
writel(val, &clkrst->crc_clk_sys_rate);
/* Enable clocks to required peripherals. TBD - minimize this list */
debug("Enabling clocks\n");
clock_set_enable(PERIPH_ID_CACHE2, 1);
clock_set_enable(PERIPH_ID_GPIO, 1);
clock_set_enable(PERIPH_ID_TMR, 1);
clock_set_enable(PERIPH_ID_RTC, 1);
clock_set_enable(PERIPH_ID_CPU, 1);
clock_set_enable(PERIPH_ID_EMC, 1);
clock_set_enable(PERIPH_ID_I2C5, 1);
clock_set_enable(PERIPH_ID_FUSE, 1);
clock_set_enable(PERIPH_ID_PMC, 1);
clock_set_enable(PERIPH_ID_APBDMA, 1);
clock_set_enable(PERIPH_ID_MEM, 1);
clock_set_enable(PERIPH_ID_IRAMA, 1);
clock_set_enable(PERIPH_ID_IRAMB, 1);
clock_set_enable(PERIPH_ID_IRAMC, 1);
clock_set_enable(PERIPH_ID_IRAMD, 1);
clock_set_enable(PERIPH_ID_CORESIGHT, 1);
clock_set_enable(PERIPH_ID_MSELECT, 1);
clock_set_enable(PERIPH_ID_EMC1, 1);
clock_set_enable(PERIPH_ID_MC1, 1);
clock_set_enable(PERIPH_ID_DVFS, 1);
/* Switch MSELECT clock to PLLP (00) */
clock_ll_set_source(PERIPH_ID_MSELECT, 0);
/*
* Clock divider request for 102MHz would setup MSELECT clock as
* 102MHz for PLLP base 408MHz
*/
clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0,
(NVBL_PLLP_KHZ/102000));
/* I2C5 (DVC) gets CLK_M and a divisor of 17 */
clock_ll_set_source_divisor(PERIPH_ID_I2C5, 3, 16);
/* Give clocks time to stabilize */
udelay(1000);
/* Take required peripherals out of reset */
debug("Taking periphs out of reset\n");
reset_set_enable(PERIPH_ID_CACHE2, 0);
reset_set_enable(PERIPH_ID_GPIO, 0);
reset_set_enable(PERIPH_ID_TMR, 0);
reset_set_enable(PERIPH_ID_COP, 0);
reset_set_enable(PERIPH_ID_EMC, 0);
reset_set_enable(PERIPH_ID_I2C5, 0);
reset_set_enable(PERIPH_ID_FUSE, 0);
reset_set_enable(PERIPH_ID_APBDMA, 0);
reset_set_enable(PERIPH_ID_MEM, 0);
reset_set_enable(PERIPH_ID_CORESIGHT, 0);
reset_set_enable(PERIPH_ID_MSELECT, 0);
reset_set_enable(PERIPH_ID_EMC1, 0);
reset_set_enable(PERIPH_ID_MC1, 0);
debug("t114_init_clocks exit\n");
}
static int is_partition_powered(u32 mask)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
/* Get power gate status */
reg = readl(&pmc->pmc_pwrgate_status);
return (reg & mask) == mask;
}
static int is_clamp_enabled(u32 mask)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
/* Get clamp status. TODO: Add pmc_clamp_status alias to pmc.h */
reg = readl(&pmc->pmc_pwrgate_timer_on);
return (reg & mask) == mask;
}
static void power_partition(u32 status, u32 partid)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
debug("%s: status = %08X, part ID = %08X\n", __func__, status, partid);
/* Is the partition already on? */
if (!is_partition_powered(status)) {
/* No, toggle the partition power state (OFF -> ON) */
debug("power_partition, toggling state\n");
clrbits_le32(&pmc->pmc_pwrgate_toggle, 0x1F);
setbits_le32(&pmc->pmc_pwrgate_toggle, partid);
setbits_le32(&pmc->pmc_pwrgate_toggle, START_CP);
/* Wait for the power to come up */
while (!is_partition_powered(status))
;
/* Wait for the clamp status to be cleared */
while (is_clamp_enabled(status))
;
/* Give I/O signals time to stabilize */
udelay(IO_STABILIZATION_DELAY);
}
}
void powerup_cpus(void)
{
debug("powerup_cpus entry\n");
/* We boot to the fast cluster */
debug("powerup_cpus entry: G cluster\n");
/* Power up the fast cluster rail partition */
power_partition(CRAIL, CRAILID);
/* Power up the fast cluster non-CPU partition */
power_partition(C0NC, C0NCID);
/* Power up the fast cluster CPU0 partition */
power_partition(CE0, CE0ID);
}
void start_cpu(u32 reset_vector)
{
debug("start_cpu entry, reset_vector = %x\n", reset_vector);
t114_init_clocks();
/* Enable VDD_CPU */
enable_cpu_power_rail();
/* Get the CPU(s) running */
enable_cpu_clocks();
/* Enable CoreSight */
clock_enable_coresight(1);
/* Take CPU(s) out of reset */
remove_cpu_resets();
/*
* Set the entry point for CPU execution from reset,
* if it's a non-zero value.
*/
if (reset_vector)
writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
/* If the CPU(s) don't already have power, power 'em up */
powerup_cpus();
}

View file

@ -1,160 +1,25 @@
/*
* (C) Copyright 2010-2011
* NVIDIA Corporation <www.nvidia.com>
*
* 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
*/
* Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/scu.h>
#include "../tegra-common/cpu.h"
/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
int ap20_cpu_is_cortexa9(void)
{
u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
return id == (PG_UP_TAG_0_PID_CPU & 0xff);
}
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_ID_XCPU];
u32 reg;
/* If PLLX is already enabled, just return */
if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
return;
/* Set PLLX_MISC */
writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
/* Use 12MHz clock here */
reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
reg |= 1000 << PLL_DIVN_SHIFT;
writel(reg, &pll->pll_base);
reg |= PLL_ENABLE_MASK;
writel(reg, &pll->pll_base);
reg &= ~PLL_BYPASS_MASK;
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 clk;
/*
* NOTE:
* Regardless of whether the request is to enable or disable the CPU
* clock, every processor in the CPU complex except the master (CPU 0)
* will have it's clock stopped because the AVP only talks to the
* master. The AVP does not know (nor does it need to know) that there
* are multiple processors in the CPU complex.
*/
if (enable) {
/* Initialize PLLX */
init_pllx();
/* Wait until all clocks are stable */
udelay(PLL_STABILIZATION_DELAY);
writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
}
/*
* Read the register containing the individual CPU clock enables and
* always stop the clock to CPU 1.
*/
clk = readl(&clkrst->crc_clk_cpu_cmplx);
clk |= 1 << CPU1_CLK_STP_SHIFT;
/* Stop/Unstop the CPU clock */
clk &= ~CPU0_CLK_STP_MASK;
clk |= !enable << CPU0_CLK_STP_SHIFT;
writel(clk, &clkrst->crc_clk_cpu_cmplx);
clock_enable(PERIPH_ID_CPU);
}
static int is_cpu_powered(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
}
static void remove_cpu_io_clamps(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
/* Remove the clamps on the CPU I/O signals */
reg = readl(&pmc->pmc_remove_clamping);
reg |= CPU_CLMP;
writel(reg, &pmc->pmc_remove_clamping);
/* Give I/O signals time to stabilize */
udelay(IO_STABILIZATION_DELAY);
}
static void powerup_cpu(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
int timeout = IO_STABILIZATION_DELAY;
if (!is_cpu_powered()) {
/* Toggle the CPU power state (OFF -> ON) */
reg = readl(&pmc->pmc_pwrgate_toggle);
reg &= PARTID_CP;
reg |= START_CP;
writel(reg, &pmc->pmc_pwrgate_toggle);
/* Wait for the power to come up */
while (!is_cpu_powered()) {
if (timeout-- == 0)
printf("CPU failed to power up!\n");
else
udelay(10);
}
/*
* Remove the I/O clamps from CPU power partition.
* Recommended only on a Warm boot, if the CPU partition gets
* power gated. Shouldn't cause any harm when called after a
* cold boot according to HW, probably just redundant.
*/
remove_cpu_io_clamps();
}
}
static void enable_cpu_power_rail(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
@ -173,49 +38,6 @@ static void enable_cpu_power_rail(void)
udelay(3750);
}
static void reset_A9_cpu(int reset)
{
/*
* NOTE: Regardless of whether the request is to hold the CPU in reset
* or take it out of reset, every processor in the CPU complex
* except the master (CPU 0) will be held in reset because the
* AVP only talks to the master. The AVP does not know that there
* are multiple processors in the CPU complex.
*/
/* Hold CPU 1 in reset, and CPU 0 if asked */
reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1);
reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
reset);
/* Enable/Disable master CPU reset */
reset_set_enable(PERIPH_ID_CPU, reset);
}
static void clock_enable_coresight(int enable)
{
u32 rst, src;
clock_set_enable(PERIPH_ID_CORESIGHT, enable);
reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
if (enable) {
/*
* Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
* 1.5, giving an effective frequency of 144MHz.
* Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
* (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
*/
src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
/* Unlock the CPU CoreSight interfaces */
rst = 0xC5ACCE55;
writel(rst, CSITE_CPU_DBG0_LAR);
writel(rst, CSITE_CPU_DBG1_LAR);
}
}
void start_cpu(u32 reset_vector)
{
/* Enable VDD_CPU */
@ -246,13 +68,3 @@ void start_cpu(u32 reset_vector)
/* Take the CPU out of reset */
reset_A9_cpu(0);
}
void halt_avp(void)
{
for (;;) {
writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
| HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
FLOW_CTLR_HALT_COP_EVENTS);
}
}

View file

@ -0,0 +1,41 @@
#
# Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2000-2008
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
COBJS-y += cpu.o
SRCS := $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,19 @@
#
# Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2002
# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
USE_PRIVATE_LIBGCC = yes

View file

@ -0,0 +1,176 @@
/*
* Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/flow.h>
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/tegra_i2c.h>
#include "../tegra-common/cpu.h"
/* Tegra30-specific CPU init code */
void tegra_i2c_ll_write_addr(uint addr, uint config)
{
struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE;
writel(addr, &reg->cmd_addr0);
writel(config, &reg->cnfg);
}
void tegra_i2c_ll_write_data(uint data, uint config)
{
struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE;
writel(data, &reg->cmd_data1);
writel(config, &reg->cnfg);
}
#define TPS65911_I2C_ADDR 0x5A
#define TPS65911_VDDCTRL_OP_REG 0x28
#define TPS65911_VDDCTRL_SR_REG 0x27
#define TPS65911_VDDCTRL_OP_DATA (0x2300 | TPS65911_VDDCTRL_OP_REG)
#define TPS65911_VDDCTRL_SR_DATA (0x0100 | TPS65911_VDDCTRL_SR_REG)
#define I2C_SEND_2_BYTES 0x0A02
static void enable_cpu_power_rail(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
debug("enable_cpu_power_rail entry\n");
reg = readl(&pmc->pmc_cntrl);
reg |= CPUPWRREQ_OE;
writel(reg, &pmc->pmc_cntrl);
/*
* Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus.
* First set VDD to 1.4V, then enable the VDD regulator.
*/
tegra_i2c_ll_write_addr(TPS65911_I2C_ADDR, 2);
tegra_i2c_ll_write_data(TPS65911_VDDCTRL_OP_DATA, I2C_SEND_2_BYTES);
udelay(1000);
tegra_i2c_ll_write_data(TPS65911_VDDCTRL_SR_DATA, I2C_SEND_2_BYTES);
udelay(10 * 1000);
}
/**
* The T30 requires some special clock initialization, including setting up
* the dvc i2c, turning on mselect and selecting the G CPU cluster
*/
void t30_init_clocks(void)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
u32 val;
debug("t30_init_clocks entry\n");
/* Set active CPU cluster to G */
clrbits_le32(flow->cluster_control, 1 << 0);
/*
* Switch system clock to PLLP_OUT4 (108 MHz), AVP will now run
* at 108 MHz. This is glitch free as only the source is changed, no
* special precaution needed.
*/
val = (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) |
(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) |
(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) |
(SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) |
(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT);
writel(val, &clkrst->crc_sclk_brst_pol);
writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div);
val = (0 << CLK_SYS_RATE_HCLK_DISABLE_SHIFT) |
(1 << CLK_SYS_RATE_AHB_RATE_SHIFT) |
(0 << CLK_SYS_RATE_PCLK_DISABLE_SHIFT) |
(0 << CLK_SYS_RATE_APB_RATE_SHIFT);
writel(val, &clkrst->crc_clk_sys_rate);
/* Put i2c, mselect in reset and enable clocks */
reset_set_enable(PERIPH_ID_DVC_I2C, 1);
clock_set_enable(PERIPH_ID_DVC_I2C, 1);
reset_set_enable(PERIPH_ID_MSELECT, 1);
clock_set_enable(PERIPH_ID_MSELECT, 1);
/* Switch MSELECT clock to PLLP (00) */
clock_ll_set_source(PERIPH_ID_MSELECT, 0);
/*
* Our high-level clock routines are not available prior to
* relocation. We use the low-level functions which require a
* hard-coded divisor. Use CLK_M with divide by (n + 1 = 17)
*/
clock_ll_set_source_divisor(PERIPH_ID_DVC_I2C, 3, 16);
/*
* Give clocks time to stabilize, then take i2c and mselect out of
* reset
*/
udelay(1000);
reset_set_enable(PERIPH_ID_DVC_I2C, 0);
reset_set_enable(PERIPH_ID_MSELECT, 0);
}
static void set_cpu_running(int run)
{
struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
debug("set_cpu_running entry, run = %d\n", run);
writel(run ? FLOW_MODE_NONE : FLOW_MODE_STOP, &flow->halt_cpu_events);
}
void start_cpu(u32 reset_vector)
{
debug("start_cpu entry, reset_vector = %x\n", reset_vector);
t30_init_clocks();
/* Enable VDD_CPU */
enable_cpu_power_rail();
set_cpu_running(0);
/* Hold the CPUs in reset */
reset_A9_cpu(1);
/* Disable the CPU clock */
enable_cpu_clock(0);
/* Enable CoreSight */
clock_enable_coresight(1);
/*
* Set the entry point for CPU execution from reset,
* if it's a non-zero value.
*/
if (reset_vector)
writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
/* Enable the CPU clock */
enable_cpu_clock(1);
/* If the CPU doesn't already have power, power it up */
powerup_cpu();
/* Take the CPU out of reset */
reset_A9_cpu(0);
set_cpu_running(1);
}

View file

@ -31,14 +31,14 @@ DECLARE_GLOBAL_DATA_PTR;
static inline unsigned long long tick_to_time(unsigned long long tick)
{
tick *= CONFIG_SYS_HZ;
do_div(tick, gd->timer_rate_hz);
do_div(tick, gd->arch.timer_rate_hz);
return tick;
}
static inline unsigned long long usec_to_tick(unsigned long long usec)
{
usec *= gd->timer_rate_hz;
usec *= gd->arch.timer_rate_hz;
do_div(usec, 1000000);
return usec;
@ -74,8 +74,8 @@ int timer_init(void)
cr |= FTTMR010_TM3_ENABLE;
writel(cr, &tmr->cr);
gd->timer_rate_hz = TIMER_CLOCK;
gd->tbu = gd->tbl = 0;
gd->arch.timer_rate_hz = TIMER_CLOCK;
gd->arch.tbu = gd->arch.tbl = 0;
return 0;
}
@ -89,10 +89,10 @@ unsigned long long get_ticks(void)
ulong now = TIMER_LOAD_VAL - readl(&tmr->timer3_counter);
/* increment tbu if tbl has rolled over */
if (now < gd->tbl)
gd->tbu++;
gd->tbl = now;
return (((unsigned long long)gd->tbu) << 32) | gd->tbl;
if (now < gd->arch.tbl)
gd->arch.tbu++;
gd->arch.tbl = now;
return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
}
void __udelay(unsigned long usec)
@ -126,5 +126,5 @@ ulong get_timer(ulong base)
*/
ulong get_tbclk(void)
{
return gd->timer_rate_hz;
return gd->arch.timer_rate_hz;
}

View file

@ -29,11 +29,11 @@ static unsigned long at91_css_to_rate(unsigned long css)
case AT91_PMC_MCKR_CSS_SLOW:
return CONFIG_SYS_AT91_SLOW_CLOCK;
case AT91_PMC_MCKR_CSS_MAIN:
return gd->main_clk_rate_hz;
return gd->arch.main_clk_rate_hz;
case AT91_PMC_MCKR_CSS_PLLA:
return gd->plla_rate_hz;
return gd->arch.plla_rate_hz;
case AT91_PMC_MCKR_CSS_PLLB:
return gd->pllb_rate_hz;
return gd->arch.pllb_rate_hz;
}
return 0;
@ -124,10 +124,10 @@ int at91_clock_init(unsigned long main_clock)
main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
}
#endif
gd->main_clk_rate_hz = main_clock;
gd->arch.main_clk_rate_hz = main_clock;
/* report if PLLA is more than mildly overclocked */
gd->plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
#ifdef CONFIG_USB_ATMEL
/*
@ -136,9 +136,10 @@ int at91_clock_init(unsigned long main_clock)
*
* REVISIT: assumes MCK doesn't derive from PLLB!
*/
gd->at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
AT91_PMC_PLLBR_USBDIV_2;
gd->pllb_rate_hz = at91_pll_rate(main_clock, gd->at91_pllb_usb_init);
gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
gd->arch.at91_pllb_usb_init);
#endif
/*
@ -146,13 +147,14 @@ int at91_clock_init(unsigned long main_clock)
* For now, assume this parentage won't change.
*/
mckr = readl(&pmc->mckr);
gd->mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
freq = gd->mck_rate_hz;
gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
freq = gd->arch.mck_rate_hz;
freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */
/* mdiv */
gd->mck_rate_hz = freq / (1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
gd->cpu_clk_rate_hz = freq;
gd->arch.mck_rate_hz = freq /
(1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
gd->arch.cpu_clk_rate_hz = freq;
return 0;
}

View file

@ -63,8 +63,8 @@ int timer_init(void)
writel(TIMER_LOAD_VAL, &tc->tc[0].rc);
writel(AT91_TC_CCR_SWTRG | AT91_TC_CCR_CLKEN, &tc->tc[0].ccr);
gd->lastinc = 0;
gd->tbl = 0;
gd->arch.lastinc = 0;
gd->arch.tbl = 0;
return 0;
}
@ -89,16 +89,16 @@ ulong get_timer_raw(void)
now = readl(&tc->tc[0].cv) & 0x0000ffff;
if (now >= gd->lastinc) {
if (now >= gd->arch.lastinc) {
/* normal mode */
gd->tbl += now - gd->lastinc;
gd->arch.tbl += now - gd->arch.lastinc;
} else {
/* we have an overflow ... */
gd->tbl += now + TIMER_LOAD_VAL - gd->lastinc;
gd->arch.tbl += now + TIMER_LOAD_VAL - gd->arch.lastinc;
}
gd->lastinc = now;
gd->arch.lastinc = now;
return gd->tbl;
return gd->arch.tbl;
}
ulong get_timer_masked(void)

View file

@ -45,25 +45,25 @@ int timer_init(void)
/* use PWM Timer 4 because it has no output */
/* prescaler for Timer 4 is 16 */
writel(0x0f00, &timers->tcfg0);
if (gd->tbu == 0) {
if (gd->arch.tbu == 0) {
/*
* for 10 ms clock period @ PCLK with 4 bit divider = 1/2
* (default) and prescaler = 16. Should be 10390
* @33.25MHz and 15625 @ 50 MHz
*/
gd->tbu = get_PCLK() / (2 * 16 * 100);
gd->timer_rate_hz = get_PCLK() / (2 * 16);
gd->arch.tbu = get_PCLK() / (2 * 16 * 100);
gd->arch.timer_rate_hz = get_PCLK() / (2 * 16);
}
/* load value for 10 ms timeout */
writel(gd->tbu, &timers->tcntb4);
writel(gd->arch.tbu, &timers->tcntb4);
/* auto load, manual update of timer 4 */
tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000;
writel(tmr, &timers->tcon);
/* auto load, start timer 4 */
tmr = (tmr & ~0x0700000) | 0x0500000;
writel(tmr, &timers->tcon);
gd->lastinc = 0;
gd->tbl = 0;
gd->arch.lastinc = 0;
gd->arch.tbl = 0;
return 0;
}
@ -82,7 +82,7 @@ void __udelay (unsigned long usec)
ulong start = get_ticks();
tmo = usec / 1000;
tmo *= (gd->tbu * 100);
tmo *= (gd->arch.tbu * 100);
tmo /= 1000;
while ((ulong) (get_ticks() - start) < tmo)
@ -93,7 +93,7 @@ ulong get_timer_masked(void)
{
ulong tmr = get_ticks();
return tmr / (gd->timer_rate_hz / CONFIG_SYS_HZ);
return tmr / (gd->arch.timer_rate_hz / CONFIG_SYS_HZ);
}
void udelay_masked(unsigned long usec)
@ -104,10 +104,10 @@ void udelay_masked(unsigned long usec)
if (usec >= 1000) {
tmo = usec / 1000;
tmo *= (gd->tbu * 100);
tmo *= (gd->arch.tbu * 100);
tmo /= 1000;
} else {
tmo = usec * (gd->tbu * 100);
tmo = usec * (gd->arch.tbu * 100);
tmo /= (1000 * 1000);
}
@ -128,16 +128,16 @@ unsigned long long get_ticks(void)
struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
ulong now = readl(&timers->tcnto4) & 0xffff;
if (gd->lastinc >= now) {
if (gd->arch.lastinc >= now) {
/* normal mode */
gd->tbl += gd->lastinc - now;
gd->arch.tbl += gd->arch.lastinc - now;
} else {
/* we have an overflow ... */
gd->tbl += gd->lastinc + gd->tbu - now;
gd->arch.tbl += gd->arch.lastinc + gd->arch.tbu - now;
}
gd->lastinc = now;
gd->arch.lastinc = now;
return gd->tbl;
return gd->arch.tbl;
}
/*

View file

@ -61,7 +61,7 @@ struct armd1tmr_registers {
#define COUNT_RD_REQ 0x1
DECLARE_GLOBAL_DATA_PTR;
/* Using gd->tbu from timestamp and gd->tbl for lastdec */
/* Using gd->arch.tbu from timestamp and gd->arch.tbl for lastdec */
/* For preventing risk of instability in reading counter value,
* first set read request to register cvwr and then read same
@ -82,16 +82,16 @@ ulong get_timer_masked(void)
{
ulong now = read_timer();
if (now >= gd->tbl) {
if (now >= gd->arch.tbl) {
/* normal mode */
gd->tbu += now - gd->tbl;
gd->arch.tbu += now - gd->arch.tbl;
} else {
/* we have an overflow ... */
gd->tbu += now + TIMER_LOAD_VAL - gd->tbl;
gd->arch.tbu += now + TIMER_LOAD_VAL - gd->arch.tbl;
}
gd->tbl = now;
gd->arch.tbl = now;
return gd->tbu;
return gd->arch.tbu;
}
ulong get_timer(ulong base)
@ -135,9 +135,9 @@ int timer_init(void)
/* Enable timer 0 */
writel(0x1, &armd1timers->cer);
/* init the gd->tbu and gd->tbl value */
gd->tbl = read_timer();
gd->tbu = 0;
/* init the gd->arch.tbu and gd->arch.tbl value */
gd->arch.tbl = read_timer();
gd->arch.tbu = 0;
return 0;
}

View file

@ -29,11 +29,11 @@ static unsigned long at91_css_to_rate(unsigned long css)
case AT91_PMC_MCKR_CSS_SLOW:
return CONFIG_SYS_AT91_SLOW_CLOCK;
case AT91_PMC_MCKR_CSS_MAIN:
return gd->main_clk_rate_hz;
return gd->arch.main_clk_rate_hz;
case AT91_PMC_MCKR_CSS_PLLA:
return gd->plla_rate_hz;
return gd->arch.plla_rate_hz;
case AT91_PMC_MCKR_CSS_PLLB:
return gd->pllb_rate_hz;
return gd->arch.pllb_rate_hz;
}
return 0;
@ -132,10 +132,10 @@ int at91_clock_init(unsigned long main_clock)
main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
}
#endif
gd->main_clk_rate_hz = main_clock;
gd->arch.main_clk_rate_hz = main_clock;
/* report if PLLA is more than mildly overclocked */
gd->plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
#ifdef CONFIG_USB_ATMEL
/*
@ -144,9 +144,10 @@ int at91_clock_init(unsigned long main_clock)
*
* REVISIT: assumes MCK doesn't derive from PLLB!
*/
gd->at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
AT91_PMC_PLLBR_USBDIV_2;
gd->pllb_rate_hz = at91_pll_rate(main_clock, gd->at91_pllb_usb_init);
gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
gd->arch.at91_pllb_usb_init);
#endif
/*
@ -157,15 +158,15 @@ int at91_clock_init(unsigned long main_clock)
#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
|| defined(CONFIG_AT91SAM9X5)
/* plla divisor by 2 */
gd->plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
gd->arch.plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
#endif
gd->mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
freq = gd->mck_rate_hz;
gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
freq = gd->arch.mck_rate_hz;
freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */
#if defined(CONFIG_AT91SAM9G20)
/* mdiv ; (x >> 7) = ((x >> 8) * 2) */
gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq;
if (mckr & AT91_PMC_MCKR_MDIV_MASK)
freq /= 2; /* processor clock division */
@ -177,14 +178,15 @@ int at91_clock_init(unsigned long main_clock)
* 2 <==> 4
* 3 <==> 3
*/
gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
(AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4)
? freq / 3
: freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
#else
gd->mck_rate_hz = freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
gd->arch.mck_rate_hz = freq /
(1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
#endif
gd->cpu_clk_rate_hz = freq;
gd->arch.cpu_clk_rate_hz = freq;
return 0;
}

View file

@ -52,14 +52,14 @@ DECLARE_GLOBAL_DATA_PTR;
static inline unsigned long long tick_to_time(unsigned long long tick)
{
tick *= CONFIG_SYS_HZ;
do_div(tick, gd->timer_rate_hz);
do_div(tick, gd->arch.timer_rate_hz);
return tick;
}
static inline unsigned long long usec_to_tick(unsigned long long usec)
{
usec *= gd->timer_rate_hz;
usec *= gd->arch.timer_rate_hz;
do_div(usec, 1000000);
return usec;
@ -79,8 +79,8 @@ int timer_init(void)
/* Enable PITC */
writel(TIMER_LOAD_VAL | AT91_PIT_MR_EN , &pit->mr);
gd->timer_rate_hz = gd->mck_rate_hz / 16;
gd->tbu = gd->tbl = 0;
gd->arch.timer_rate_hz = gd->arch.mck_rate_hz / 16;
gd->arch.tbu = gd->arch.tbl = 0;
return 0;
}
@ -95,10 +95,10 @@ unsigned long long get_ticks(void)
ulong now = readl(&pit->piir);
/* increment tbu if tbl has rolled over */
if (now < gd->tbl)
gd->tbu++;
gd->tbl = now;
return (((unsigned long long)gd->tbu) << 32) | gd->tbl;
if (now < gd->arch.tbl)
gd->arch.tbu++;
gd->arch.tbl = now;
return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
}
void __udelay(unsigned long usec)
@ -132,5 +132,5 @@ ulong get_timer(ulong base)
*/
ulong get_tbclk(void)
{
return gd->timer_rate_hz;
return gd->arch.timer_rate_hz;
}

View file

@ -60,8 +60,8 @@ int timer_init(void)
writel(0x0, &timer->tim34);
writel(TIMER_LOAD_VAL, &timer->prd34);
writel(2 << 22, &timer->tcr);
gd->timer_rate_hz = CONFIG_SYS_HZ_CLOCK / TIM_CLK_DIV;
gd->timer_reset_value = 0;
gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK / TIM_CLK_DIV;
gd->arch.timer_reset_value = 0;
return(0);
}
@ -74,27 +74,28 @@ unsigned long long get_ticks(void)
unsigned long now = readl(&timer->tim34);
/* increment tbu if tbl has rolled over */
if (now < gd->tbl)
gd->tbu++;
gd->tbl = now;
if (now < gd->arch.tbl)
gd->arch.tbu++;
gd->arch.tbl = now;
return (((unsigned long long)gd->tbu) << 32) | gd->tbl;
return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
}
ulong get_timer(ulong base)
{
unsigned long long timer_diff;
timer_diff = get_ticks() - gd->timer_reset_value;
timer_diff = get_ticks() - gd->arch.timer_reset_value;
return lldiv(timer_diff, (gd->timer_rate_hz / CONFIG_SYS_HZ)) - base;
return lldiv(timer_diff,
(gd->arch.timer_rate_hz / CONFIG_SYS_HZ)) - base;
}
void __udelay(unsigned long usec)
{
unsigned long long endtime;
endtime = lldiv((unsigned long long)usec * gd->timer_rate_hz,
endtime = lldiv((unsigned long long)usec * gd->arch.timer_rate_hz,
1000000UL);
endtime += get_ticks();
@ -108,7 +109,7 @@ void __udelay(unsigned long usec)
*/
ulong get_tbclk(void)
{
return gd->timer_rate_hz;
return gd->arch.timer_rate_hz;
}
#ifdef CONFIG_HW_WATCHDOG

View file

@ -86,8 +86,8 @@ struct kwtmr_registers *kwtmr_regs = (struct kwtmr_registers *)KW_TIMER_BASE;
DECLARE_GLOBAL_DATA_PTR;
#define timestamp gd->tbl
#define lastdec gd->lastinc
#define timestamp gd->arch.tbl
#define lastdec gd->arch.lastinc
ulong get_timer_masked(void)
{

View file

@ -35,8 +35,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define timestamp gd->tbl
#define lastdec gd->lastinc
#define timestamp gd->arch.tbl
#define lastdec gd->arch.lastinc
static inline unsigned long long tick_to_time(unsigned long long tick)
{

View file

@ -229,9 +229,9 @@ int get_clocks(void)
{
#ifdef CONFIG_FSL_ESDHC
#if CONFIG_SYS_FSL_ESDHC_ADDR == IMX_MMC_SDHC2_BASE
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
#else
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK);
#endif
#endif
return 0;

View file

@ -44,8 +44,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define timestamp (gd->tbl)
#define lastinc (gd->lastinc)
#define timestamp (gd->arch.tbl)
#define lastinc (gd->arch.lastinc)
/*
* "time" is measured in 1 / CONFIG_SYS_HZ seconds,

View file

@ -45,8 +45,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define timestamp (gd->tbl)
#define lastinc (gd->lastinc)
#define timestamp (gd->arch.tbl)
#define lastinc (gd->arch.lastinc)
/*
* "time" is measured in 1 / CONFIG_SYS_HZ seconds,

View file

@ -36,8 +36,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define timestamp (gd->tbl)
#define lastdec (gd->lastinc)
#define timestamp (gd->arch.tbl)
#define lastdec (gd->arch.lastinc)
/*
* This driver uses 1kHz clock source.

View file

@ -44,8 +44,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define timestamp gd->tbl
#define lastdec gd->lastinc
#define timestamp gd->arch.tbl
#define lastdec gd->arch.lastinc
int timer_init (void)
{

View file

@ -92,8 +92,8 @@ static inline ulong read_timer(void)
DECLARE_GLOBAL_DATA_PTR;
#define timestamp gd->tbl
#define lastdec gd->lastinc
#define timestamp gd->arch.tbl
#define lastdec gd->arch.lastinc
ulong get_timer_masked(void)
{

View file

@ -60,7 +60,7 @@ struct panthtmr_registers {
#define COUNT_RD_REQ 0x1
DECLARE_GLOBAL_DATA_PTR;
/* Using gd->tbu from timestamp and gd->tbl for lastdec */
/* Using gd->arch.tbu from timestamp and gd->arch.tbl for lastdec */
/*
* For preventing risk of instability in reading counter value,
@ -90,16 +90,16 @@ ulong get_timer_masked(void)
{
ulong now = read_timer();
if (now >= gd->tbl) {
if (now >= gd->arch.tbl) {
/* normal mode */
gd->tbu += now - gd->tbl;
gd->arch.tbu += now - gd->arch.tbl;
} else {
/* we have an overflow ... */
gd->tbu += now + TIMER_LOAD_VAL - gd->tbl;
gd->arch.tbu += now + TIMER_LOAD_VAL - gd->arch.tbl;
}
gd->tbl = now;
gd->arch.tbl = now;
return gd->tbu;
return gd->arch.tbu;
}
ulong get_timer(ulong base)
@ -144,9 +144,9 @@ int timer_init(void)
/* Enable timer 0 */
writel(0x1, &panthtimers->cer);
/* init the gd->tbu and gd->tbl value */
gd->tbl = read_timer();
gd->tbu = 0;
/* init the gd->arch.tbu and gd->arch.tbl value */
gd->arch.tbl = read_timer();
gd->arch.tbu = 0;
return 0;
}

View file

@ -38,8 +38,8 @@ static struct misc_regs *const misc_regs_p =
DECLARE_GLOBAL_DATA_PTR;
#define timestamp gd->tbl
#define lastdec gd->lastinc
#define timestamp gd->arch.tbl
#define lastdec gd->arch.lastinc
int timer_init(void)
{

View file

@ -44,8 +44,8 @@
DECLARE_GLOBAL_DATA_PTR;
#define timestamp gd->tbl
#define lastdec gd->lastinc
#define timestamp gd->arch.tbl
#define lastdec gd->arch.lastinc
#define TIMER_ENABLE (1 << 7)
#define TIMER_MODE_MSK (1 << 6)

View file

@ -32,7 +32,7 @@ COBJS += cache_v7.o
COBJS += cpu.o
COBJS += syslib.o
ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA),)
SOBJS += lowlevel_init.o
endif

View file

@ -55,6 +55,9 @@ void spl_board_init(void)
#ifdef CONFIG_SPL_NAND_SUPPORT
gpmc_init();
#endif
#if defined(CONFIG_AM33XX) && defined(CONFIG_SPL_MUSB_NEW_SUPPORT)
arch_misc_init();
#endif
}
int board_mmc_init(bd_t *bis)

View file

@ -56,8 +56,9 @@ int timer_init(void)
&timer_base->tclr);
/* reset time, capture current incrementer value time */
gd->lastinc = readl(&timer_base->tcrr) / (TIMER_CLOCK / CONFIG_SYS_HZ);
gd->tbl = 0; /* start "advancing" time stamp from 0 */
gd->arch.lastinc = readl(&timer_base->tcrr) /
(TIMER_CLOCK / CONFIG_SYS_HZ);
gd->arch.tbl = 0; /* start "advancing" time stamp from 0 */
return 0;
}
@ -91,14 +92,15 @@ ulong get_timer_masked(void)
/* current tick value */
ulong now = readl(&timer_base->tcrr) / (TIMER_CLOCK / CONFIG_SYS_HZ);
if (now >= gd->lastinc) /* normal mode (non roll) */
if (now >= gd->arch.lastinc) { /* normal mode (non roll) */
/* move stamp fordward with absoulte diff ticks */
gd->tbl += (now - gd->lastinc);
else /* we have rollover of incrementer */
gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLOCK / CONFIG_SYS_HZ))
- gd->lastinc) + now;
gd->lastinc = now;
return gd->tbl;
gd->arch.tbl += (now - gd->arch.lastinc);
} else { /* we have rollover of incrementer */
gd->arch.tbl += ((TIMER_LOAD_VAL / (TIMER_CLOCK /
CONFIG_SYS_HZ)) - gd->arch.lastinc) + now;
}
gd->arch.lastinc = now;
return gd->arch.tbl;
}
/*

View file

@ -105,8 +105,8 @@ void reset_timer_masked(void)
struct s5p_timer *const timer = s5p_get_base_timer();
/* reset time */
gd->lastinc = readl(&timer->tcnto4);
gd->tbl = 0;
gd->arch.lastinc = readl(&timer->tcnto4);
gd->arch.tbl = 0;
}
unsigned long get_timer_masked(void)
@ -123,14 +123,14 @@ unsigned long get_current_tick(void)
unsigned long now = readl(&timer->tcnto4);
unsigned long count_value = readl(&timer->tcntb4);
if (gd->lastinc >= now)
gd->tbl += gd->lastinc - now;
if (gd->arch.lastinc >= now)
gd->arch.tbl += gd->arch.lastinc - now;
else
gd->tbl += gd->lastinc + count_value - now;
gd->arch.tbl += gd->arch.lastinc + count_value - now;
gd->lastinc = now;
gd->arch.lastinc = now;
return gd->tbl;
return gd->arch.tbl;
}
/*

View file

@ -80,16 +80,16 @@ ulong get_timer_masked(void)
{
/* current tick value */
ulong now = read_timer() / (CONFIG_TIMER_CLOCK_KHZ/CONFIG_SYS_HZ);
if (gd->lastinc >= now) {
if (gd->arch.lastinc >= now) {
/* normal mode (non roll) */
/* move stamp forward with absolute diff ticks */
gd->tbl += gd->lastinc - now;
gd->arch.tbl += gd->arch.lastinc - now;
} else {
/* we have overflow of the count down timer */
gd->tbl += TIMER_LOAD_VAL - gd->lastinc + now;
gd->arch.tbl += TIMER_LOAD_VAL - gd->arch.lastinc + now;
}
gd->lastinc = now;
return gd->tbl;
gd->arch.lastinc = now;
return gd->arch.tbl;
}
/*
@ -98,7 +98,8 @@ ulong get_timer_masked(void)
void reset_timer(void)
{
/* capture current decrementer value time */
gd->lastinc = read_timer() / (CONFIG_TIMER_CLOCK_KHZ/CONFIG_SYS_HZ);
gd->arch.lastinc = read_timer() /
(CONFIG_TIMER_CLOCK_KHZ / CONFIG_SYS_HZ);
/* start "advancing" time stamp from 0 */
gd->tbl = 0;
gd->arch.tbl = 0;
}

View file

@ -251,12 +251,12 @@ ENTRY(c_runtime_cpu_setup)
/*
* Move vector table
*/
#if !defined(CONFIG_TEGRA20)
#if !defined(CONFIG_TEGRA)
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
add r0, r0, r9
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif /* !Tegra20 */
#endif /* !Tegra */
bx lr

View file

@ -0,0 +1,40 @@
#
# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2000-2003
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,19 @@
#
# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2002
# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
CONFIG_ARCH_DEVICE_TREE := tegra114

View file

@ -0,0 +1,40 @@
#
# Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2000-2003
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,19 @@
#
# Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2002
# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
CONFIG_ARCH_DEVICE_TREE := tegra30

View file

@ -100,12 +100,14 @@ ulong get_timer_masked(void)
/* current tick value */
ulong now = TICKS_TO_HZ(READ_TIMER());
if (now >= gd->lastinc) /* normal (non rollover) */
gd->tbl += (now - gd->lastinc);
else /* rollover */
gd->tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL) - gd->lastinc) + now;
gd->lastinc = now;
return gd->tbl;
if (now >= gd->arch.lastinc) { /* normal (non rollover) */
gd->arch.tbl += (now - gd->arch.lastinc);
} else { /* rollover */
gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL) -
gd->arch.lastinc) + now;
}
gd->arch.lastinc = now;
return gd->arch.tbl;
}
/* Delay x useconds */
@ -132,7 +134,7 @@ ulong get_timer(ulong base)
/*
* Emulation of Power architecture long long timebase.
*
* TODO: Support gd->tbu for real long long timebase.
* TODO: Support gd->arch.tbu for real long long timebase.
*/
unsigned long long get_ticks(void)
{

View file

@ -30,6 +30,7 @@ LIB = $(obj)lib$(SOC).o
COBJS-y := timer.o
COBJS-y += cpu.o
COBJS-y += slcr.o
COBJS := $(COBJS-y)

View file

@ -21,11 +21,37 @@
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/hardware.h>
inline void lowlevel_init(void) {}
void lowlevel_init(void)
{
zynq_slcr_unlock();
/* remap DDR to zero, FILTERSTART */
writel(0, &scu_base->filter_start);
/* Device config APB, unlock the PCAP */
writel(0x757BDF0D, &devcfg_base->unlock);
writel(0xFFFFFFFF, &devcfg_base->rom_shadow);
/* OCM_CFG, Mask out the ROM, map ram into upper addresses */
writel(0x1F, &slcr_base->ocm_cfg);
/* FPGA_RST_CTRL, clear resets on AXI fabric ports */
writel(0x0, &slcr_base->fpga_rst_ctrl);
/* TZ_DDR_RAM, Set DDR trust zone non-secure */
writel(0xFFFFFFFF, &slcr_base->trust_zone);
/* Set urgent bits with register */
writel(0x0, &slcr_base->ddr_urgent_sel);
/* Urgent write, ports S2/S3 */
writel(0xC, &slcr_base->ddr_urgent);
zynq_slcr_lock();
}
void reset_cpu(ulong addr)
{
zynq_slcr_cpu_reset();
while (1)
;
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2013 Xilinx Inc.
*
* 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
*/
#include <common.h>
#include <asm/io.h>
#include <malloc.h>
#include <asm/arch/hardware.h>
#define SLCR_LOCK_MAGIC 0x767B
#define SLCR_UNLOCK_MAGIC 0xDF0D
static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */
void zynq_slcr_lock(void)
{
if (!slcr_lock)
writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock);
}
void zynq_slcr_unlock(void)
{
if (slcr_lock)
writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock);
}
/* Reset the entire system */
void zynq_slcr_cpu_reset(void)
{
/*
* Unlock the SLCR then reset the system.
* Note that this seems to require raw i/o
* functions or there's a lockup?
*/
zynq_slcr_unlock();
/*
* Clear 0x0F000000 bits of reboot status register to workaround
* the FSBL not loading the bitstream after soft-reboot
* This is a temporary solution until we know more.
*/
clrbits_le32(&slcr_base->reboot_status, 0xF000000);
writel(1, &slcr_base->pss_rst_ctrl);
}

View file

@ -83,9 +83,9 @@ int timer_init(void)
emask);
/* Reset time */
gd->lastinc = readl(&timer_base->counter) /
gd->arch.lastinc = readl(&timer_base->counter) /
(TIMER_TICK_HZ / CONFIG_SYS_HZ);
gd->tbl = 0;
gd->arch.tbl = 0;
return 0;
}
@ -100,16 +100,16 @@ ulong get_timer_masked(void)
now = readl(&timer_base->counter) / (TIMER_TICK_HZ / CONFIG_SYS_HZ);
if (gd->lastinc >= now) {
if (gd->arch.lastinc >= now) {
/* Normal mode */
gd->tbl += gd->lastinc - now;
gd->arch.tbl += gd->arch.lastinc - now;
} else {
/* We have an overflow ... */
gd->tbl += gd->lastinc + TIMER_LOAD_VAL - now;
gd->arch.tbl += gd->arch.lastinc + TIMER_LOAD_VAL - now;
}
gd->lastinc = now;
gd->arch.lastinc = now;
return gd->tbl;
return gd->arch.tbl;
}
void __udelay(unsigned long usec)

View file

@ -70,23 +70,23 @@ unsigned long long get_ticks(void)
if (readl(IXP425_OSST) & IXP425_OSST_TIMER_TS_PEND) {
/* rollover of timestamp timer register */
gd->timestamp += (0xFFFFFFFF - gd->lastinc) + now + 1;
gd->arch.timestamp += (0xFFFFFFFF - gd->arch.lastinc) + now + 1;
writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST);
} else {
/* move stamp forward with absolut diff ticks */
gd->timestamp += (now - gd->lastinc);
gd->arch.timestamp += (now - gd->arch.lastinc);
}
gd->lastinc = now;
return gd->timestamp;
gd->arch.lastinc = now;
return gd->arch.timestamp;
}
void reset_timer_masked(void)
{
/* capture current timestamp counter */
gd->lastinc = readl(IXP425_OSTS_B);
gd->arch.lastinc = readl(IXP425_OSTS_B);
/* start "advancing" time stamp from 0 */
gd->timestamp = 0;
gd->arch.timestamp = 0;
}
ulong get_timer_masked(void)

View file

@ -31,8 +31,8 @@ DECLARE_GLOBAL_DATA_PTR;
#define TIMER_LOAD_VAL 0xffffffff
#define timestamp (gd->tbl)
#define lastinc (gd->lastinc)
#define timestamp (gd->arch.tbl)
#define lastinc (gd->arch.lastinc)
#if defined(CONFIG_CPU_PXA27X) || defined(CONFIG_CPU_MONAHANS)
#define TIMER_FREQ_HZ 3250000

View file

@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)libcputegra-common.o
SOBJS += lowlevel_init.o
COBJS-y += ap.o board.o sys_info.o timer.o
COBJS-y += ap.o board.o sys_info.o timer.o clock.o
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))

View file

@ -20,13 +20,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* Tegra AP (Application Processor) code */
#include <common.h>
#include <asm/io.h>
#include <asm/arch/gp_padctrl.h>
#include <asm/arch-tegra/ap.h>
#include <asm/arch-tegra/clock.h>
#include <asm/arch-tegra/fuse.h>
#include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/scu.h>
#include <asm/arch-tegra/tegra.h>
#include <asm/arch-tegra/warmboot.h>
int tegra_get_chip_type(void)
@ -38,7 +43,7 @@ int tegra_get_chip_type(void)
/*
* This is undocumented, Chip ID is bits 15:8 of the register
* APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for
* Tegra30
* Tegra30, and 0x35 for T114.
*/
gp = (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
@ -58,6 +63,18 @@ int tegra_get_chip_type(void)
return TEGRA_SOC_T25;
}
break;
case CHIPID_TEGRA30:
switch (tegra_sku_id) {
case SKU_ID_T30:
return TEGRA_SOC_T30;
}
break;
case CHIPID_TEGRA114:
switch (tegra_sku_id) {
case SKU_ID_T114_ENG:
return TEGRA_SOC_T114;
}
break;
}
/* unknown sku id */
return TEGRA_SOC_UNKNOWN;
@ -93,7 +110,7 @@ static u32 get_odmdata(void)
u32 bct_start, odmdata;
bct_start = readl(AP20_BASE_PA_SRAM + NVBOOTINFOTABLE_BCTPTR);
bct_start = readl(NV_PA_BASE_SRAM + NVBOOTINFOTABLE_BCTPTR);
odmdata = readl(bct_start + BCT_ODMDATA_OFFSET);
return odmdata;
@ -127,5 +144,5 @@ void s_init(void)
"orr r0, r0, #0x41\n"
"mcr p15, 0, r0, c1, c0, 1\n");
/* FIXME: should have ap20's L2 disabled too? */
/* FIXME: should have SoC's L2 disabled too? */
}

View file

@ -37,8 +37,10 @@ enum {
/* UARTs which we can enable */
UARTA = 1 << 0,
UARTB = 1 << 1,
UARTC = 1 << 2,
UARTD = 1 << 3,
UART_COUNT = 4,
UARTE = 1 << 4,
UART_COUNT = 5,
};
/*
@ -54,16 +56,37 @@ unsigned int query_sdram_size(void)
reg = readl(&pmc->pmc_scratch20);
debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg);
/* bits 31:28 in OdmData are used for RAM size */
#if defined(CONFIG_TEGRA20)
/* bits 30:28 in OdmData are used for RAM size on T20 */
reg &= 0x70000000;
switch ((reg) >> 28) {
case 1:
return 0x10000000; /* 256 MB */
case 0:
case 2:
default:
return 0x20000000; /* 512 MB */
case 3:
return 0x40000000; /* 1GB */
}
#else /* Tegra30/Tegra114 */
/* bits 31:28 in OdmData are used for RAM size on T30 */
switch ((reg) >> 28) {
case 0:
case 1:
default:
return 0x10000000; /* 256 MB */
case 2:
return 0x20000000; /* 512 MB */
case 3:
return 0x30000000; /* 768 MB */
case 4:
return 0x40000000; /* 1GB */
case 8:
return 0x7ff00000; /* 2GB - 1MB */
}
#endif
}
int dram_init(void)
@ -82,19 +105,33 @@ int checkboard(void)
#endif /* CONFIG_DISPLAY_BOARDINFO */
static int uart_configs[] = {
#if defined(CONFIG_TEGRA_UARTA_UAA_UAB)
#if defined(CONFIG_TEGRA20)
#if defined(CONFIG_TEGRA_UARTA_UAA_UAB)
FUNCMUX_UART1_UAA_UAB,
#elif defined(CONFIG_TEGRA_UARTA_GPU)
#elif defined(CONFIG_TEGRA_UARTA_GPU)
FUNCMUX_UART1_GPU,
#elif defined(CONFIG_TEGRA_UARTA_SDIO1)
#elif defined(CONFIG_TEGRA_UARTA_SDIO1)
FUNCMUX_UART1_SDIO1,
#else
#else
FUNCMUX_UART1_IRRX_IRTX,
#endif
FUNCMUX_UART2_IRDA,
FUNCMUX_UART2_UAD,
-1,
FUNCMUX_UART4_GMC,
-1,
#elif defined(CONFIG_TEGRA30)
FUNCMUX_UART1_ULPI, /* UARTA */
-1,
-1,
-1,
-1,
#else /* Tegra114 */
-1,
-1,
-1,
FUNCMUX_UART4_GMI, /* UARTD */
-1,
#endif
};
/**
@ -109,6 +146,7 @@ static void setup_uarts(int uart_ids)
PERIPH_ID_UART2,
PERIPH_ID_UART3,
PERIPH_ID_UART4,
PERIPH_ID_UART5,
};
size_t i;
@ -132,8 +170,14 @@ void board_init_uart_f(void)
#ifdef CONFIG_TEGRA_ENABLE_UARTB
uart_ids |= UARTB;
#endif
#ifdef CONFIG_TEGRA_ENABLE_UARTC
uart_ids |= UARTC;
#endif
#ifdef CONFIG_TEGRA_ENABLE_UARTD
uart_ids |= UARTD;
#endif
#ifdef CONFIG_TEGRA_ENABLE_UARTE
uart_ids |= UARTE;
#endif
setup_uarts(uart_ids);
}

View file

@ -0,0 +1,560 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra SoC common clock control functions */
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/timer.h>
#include <div64.h>
#include <fdtdec.h>
/*
* This is our record of the current clock rate of each clock. We don't
* fill all of these in since we are only really interested in clocks which
* we use as parents.
*/
static unsigned pll_rate[CLOCK_ID_COUNT];
/*
* The oscillator frequency is fixed to one of four set values. Based on this
* the other clocks are set up appropriately.
*/
static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {
13000000,
19200000,
12000000,
26000000,
};
/* return 1 if a peripheral ID is in range */
#define clock_type_id_isvalid(id) ((id) >= 0 && \
(id) < CLOCK_TYPE_COUNT)
char pllp_valid = 1; /* PLLP is set up correctly */
/* return 1 if a periphc_internal_id is in range */
#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
(id) < PERIPHC_COUNT)
/* number of clock outputs of a PLL */
static const u8 pll_num_clkouts[] = {
1, /* PLLC */
1, /* PLLM */
4, /* PLLP */
1, /* PLLA */
0, /* PLLU */
0, /* PLLD */
};
int clock_get_osc_bypass(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_XOBP_MASK) >> OSC_XOBP_SHIFT;
}
/* Returns a pointer to the registers of the given pll */
static struct clk_pll *get_pll(enum clock_id clkid)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
assert(clock_id_is_pll(clkid));
return &clkrst->crc_pll[clkid];
}
int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
u32 *divp, u32 *cpcon, u32 *lfcon)
{
struct clk_pll *pll = get_pll(clkid);
u32 data;
assert(clkid != CLOCK_ID_USB);
/* Safety check, adds to code size but is small */
if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB)
return -1;
data = readl(&pll->pll_base);
*divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
*divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
*divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
data = readl(&pll->pll_misc);
*cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
*lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
return 0;
}
unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
u32 divp, u32 cpcon, u32 lfcon)
{
struct clk_pll *pll = get_pll(clkid);
u32 data;
/*
* 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_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_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
unsigned divisor)
{
u32 *reg = get_periph_source_reg(periph_id);
u32 value;
value = readl(reg);
value &= ~OUT_CLK_SOURCE_MASK;
value |= source << OUT_CLK_SOURCE_SHIFT;
value &= ~OUT_CLK_DIVISOR_MASK;
value |= divisor << OUT_CLK_DIVISOR_SHIFT;
writel(value, reg);
}
void clock_ll_set_source(enum periph_id periph_id, unsigned source)
{
u32 *reg = get_periph_source_reg(periph_id);
clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
source << OUT_CLK_SOURCE_SHIFT);
}
/**
* Given the parent's rate and the required rate for the children, this works
* out the peripheral clock divider to use, in 7.1 binary format.
*
* @param divider_bits number of divider bits (8 or 16)
* @param parent_rate clock rate of parent clock in Hz
* @param rate required clock rate for this clock
* @return divider which should be used
*/
static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
unsigned long rate)
{
u64 divider = parent_rate * 2;
unsigned max_divider = 1 << divider_bits;
divider += rate - 1;
do_div(divider, rate);
if ((s64)divider - 2 < 0)
return 0;
if ((s64)divider - 2 >= max_divider)
return -1;
return divider - 2;
}
int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout, unsigned rate)
{
struct clk_pll *pll = get_pll(clkid);
int data = 0, div = 0, offset = 0;
if (!clock_id_is_pll(clkid))
return -1;
if (pllout + 1 > pll_num_clkouts[clkid])
return -1;
div = clk_get_divider(8, pll_rate[clkid], rate);
if (div < 0)
return -1;
/* out2 and out4 are in the high part of the register */
if (pllout == PLL_OUT2 || pllout == PLL_OUT4)
offset = 16;
data = (div << PLL_OUT_RATIO_SHIFT) |
PLL_OUT_OVRRIDE | PLL_OUT_CLKEN | PLL_OUT_RSTN;
clrsetbits_le32(&pll->pll_out[pllout >> 1],
PLL_OUT_RATIO_MASK << offset, data << offset);
return 0;
}
/**
* Given the parent's rate and the divider in 7.1 format, this works out the
* resulting peripheral clock rate.
*
* @param parent_rate clock rate of parent clock in Hz
* @param divider which should be used in 7.1 format
* @return effective clock rate of peripheral
*/
static unsigned long get_rate_from_divider(unsigned long parent_rate,
int divider)
{
u64 rate;
rate = (u64)parent_rate * 2;
do_div(rate, divider + 2);
return rate;
}
unsigned long clock_get_periph_rate(enum periph_id periph_id,
enum clock_id parent)
{
u32 *reg = get_periph_source_reg(periph_id);
return get_rate_from_divider(pll_rate[parent],
(readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
}
/**
* Find the best available 7.1 format divisor given a parent clock rate and
* required child clock rate. This function assumes that a second-stage
* divisor is available which can divide by powers of 2 from 1 to 256.
*
* @param divider_bits number of divider bits (8 or 16)
* @param parent_rate clock rate of parent clock in Hz
* @param rate required clock rate for this clock
* @param extra_div value for the second-stage divisor (not set if this
* function returns -1.
* @return divider which should be used, or -1 if nothing is valid
*
*/
static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
unsigned long rate, int *extra_div)
{
int shift;
int best_divider = -1;
int best_error = rate;
/* try dividers from 1 to 256 and find closest match */
for (shift = 0; shift <= 8 && best_error > 0; shift++) {
unsigned divided_parent = parent_rate >> shift;
int divider = clk_get_divider(divider_bits, divided_parent,
rate);
unsigned effective_rate = get_rate_from_divider(divided_parent,
divider);
int error = rate - effective_rate;
/* Given a valid divider, look for the lowest error */
if (divider != -1 && error < best_error) {
best_error = error;
*extra_div = 1 << shift;
best_divider = divider;
}
}
/* return what we found - *extra_div will already be set */
return best_divider;
}
/**
* Adjust peripheral PLL to use the given divider and source.
*
* @param periph_id peripheral to adjust
* @param source Source number (0-3 or 0-7)
* @param mux_bits Number of mux bits (2 or 4)
* @param divider Required divider in 7.1 or 15.1 format
* @return 0 if ok, -1 on error (requesting a parent clock which is not valid
* for this peripheral)
*/
static int adjust_periph_pll(enum periph_id periph_id, int source,
int mux_bits, unsigned divider)
{
u32 *reg = get_periph_source_reg(periph_id);
clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK,
divider << OUT_CLK_DIVISOR_SHIFT);
udelay(1);
/* work out the source clock and set it */
if (source < 0)
return -1;
if (mux_bits == 4) {
clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
source << OUT_CLK_SOURCE4_SHIFT);
} else {
clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
source << OUT_CLK_SOURCE_SHIFT);
}
udelay(2);
return 0;
}
unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
enum clock_id parent, unsigned rate, int *extra_div)
{
unsigned effective_rate;
int mux_bits, divider_bits, source;
int divider;
/* work out the source clock and set it */
source = get_periph_clock_source(periph_id, parent, &mux_bits,
&divider_bits);
if (extra_div)
divider = find_best_divider(divider_bits, pll_rate[parent],
rate, extra_div);
else
divider = clk_get_divider(divider_bits, pll_rate[parent],
rate);
assert(divider >= 0);
if (adjust_periph_pll(periph_id, source, mux_bits, divider))
return -1U;
debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
get_periph_source_reg(periph_id),
readl(get_periph_source_reg(periph_id)));
/* Check what we ended up with. This shouldn't matter though */
effective_rate = clock_get_periph_rate(periph_id, parent);
if (extra_div)
effective_rate /= *extra_div;
if (rate != effective_rate)
debug("Requested clock rate %u not honored (got %u)\n",
rate, effective_rate);
return effective_rate;
}
unsigned clock_start_periph_pll(enum periph_id periph_id,
enum clock_id parent, unsigned rate)
{
unsigned effective_rate;
reset_set_enable(periph_id, 1);
clock_enable(periph_id);
effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate,
NULL);
reset_set_enable(periph_id, 0);
return effective_rate;
}
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_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 (2 or 4) */
assert(cpu >= 0 && cpu < MAX_NUM_CPU);
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);
}
unsigned clock_get_rate(enum clock_id clkid)
{
struct clk_pll *pll;
u32 base;
u32 divm;
u64 parent_rate;
u64 rate;
parent_rate = osc_freq[clock_get_osc_freq()];
if (clkid == CLOCK_ID_OSC)
return parent_rate;
pll = get_pll(clkid);
base = readl(&pll->pll_base);
/* Oh for bf_unpack()... */
rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
if (clkid == CLOCK_ID_USB)
divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
else
divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
do_div(rate, divm);
return rate;
}
/**
* Set the output frequency you want for each PLL clock.
* PLL output frequencies are programmed by setting their N, M and P values.
* The governing equations are:
* VCO = (Fi / m) * n, Fo = VCO / (2^p)
* where Fo is the output frequency from the PLL.
* Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
* 216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
* Please see Tegra TRM section 5.3 to get the detail for PLL Programming
*
* @param n PLL feedback divider(DIVN)
* @param m PLL input divider(DIVN)
* @param p post divider(DIVP)
* @param cpcon base PLL charge pump(CPCON)
* @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
* be overriden), 1 if PLL is already correct
*/
int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
{
u32 base_reg;
u32 misc_reg;
struct clk_pll *pll;
pll = get_pll(clkid);
base_reg = readl(&pll->pll_base);
/* Set BYPASS, m, n and p to PLL_BASE */
base_reg &= ~PLL_DIVM_MASK;
base_reg |= m << PLL_DIVM_SHIFT;
base_reg &= ~PLL_DIVN_MASK;
base_reg |= n << PLL_DIVN_SHIFT;
base_reg &= ~PLL_DIVP_MASK;
base_reg |= p << PLL_DIVP_SHIFT;
if (clkid == CLOCK_ID_PERIPH) {
/*
* If the PLL is already set up, check that it is correct
* and record this info for clock_verify() to check.
*/
if (base_reg & PLL_BASE_OVRRIDE_MASK) {
base_reg |= PLL_ENABLE_MASK;
if (base_reg != readl(&pll->pll_base))
pllp_valid = 0;
return pllp_valid ? 1 : -1;
}
base_reg |= PLL_BASE_OVRRIDE_MASK;
}
base_reg |= PLL_BYPASS_MASK;
writel(base_reg, &pll->pll_base);
/* Set cpcon to PLL_MISC */
misc_reg = readl(&pll->pll_misc);
misc_reg &= ~PLL_CPCON_MASK;
misc_reg |= cpcon << PLL_CPCON_SHIFT;
writel(misc_reg, &pll->pll_misc);
/* Enable PLL */
base_reg |= PLL_ENABLE_MASK;
writel(base_reg, &pll->pll_base);
/* Disable BYPASS */
base_reg &= ~PLL_BYPASS_MASK;
writel(base_reg, &pll->pll_base);
return 0;
}
void clock_ll_start_uart(enum periph_id periph_id)
{
/* Assert UART reset and enable clock */
reset_set_enable(periph_id, 1);
clock_enable(periph_id);
clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
/* wait for 2us */
udelay(2);
/* De-assert reset to UART */
reset_set_enable(periph_id, 0);
}
#ifdef CONFIG_OF_CONTROL
int clock_decode_periph_id(const void *blob, int node)
{
enum periph_id id;
u32 cell[2];
int err;
err = fdtdec_get_int_array(blob, node, "clocks", cell,
ARRAY_SIZE(cell));
if (err)
return -1;
id = clk_id_to_periph_id(cell[1]);
assert(clock_periph_id_isvalid(id));
return id;
}
#endif /* CONFIG_OF_CONTROL */
int clock_verify(void)
{
struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH);
u32 reg = readl(&pll->pll_base);
if (!pllp_valid) {
printf("Warning: PLLP %x is not correct\n", reg);
return -1;
}
debug("PLLP %x is correct\n", reg);
return 0;
}
void clock_init(void)
{
pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY);
pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH);
pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL);
pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
pll_rate[CLOCK_ID_XCPU] = clock_get_rate(CLOCK_ID_XCPU);
debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
debug("PLLC = %d\n", pll_rate[CLOCK_ID_CGENERAL]);
debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]);
}

View file

@ -22,12 +22,26 @@
*/
#include <common.h>
#include <linux/ctype.h>
#ifdef CONFIG_DISPLAY_CPUINFO
void upstring(char *s)
{
while (*s) {
*s = toupper(*s);
s++;
}
}
/* Print CPU information */
int print_cpuinfo(void)
{
puts("TEGRA20\n");
char soc_name[10];
strncpy(soc_name, CONFIG_SYS_SOC, 10);
upstring(soc_name);
puts(soc_name);
puts("\n");
/* TBD: Add printf of major/minor rev info, stepping, etc. */
return 0;

View file

@ -75,14 +75,14 @@ ulong get_timer_masked(void)
/* current tick value */
now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);
if (now >= gd->lastinc) /* normal mode (non roll) */
if (now >= gd->arch.lastinc) /* normal mode (non roll) */
/* move stamp forward with absolute diff ticks */
gd->tbl += (now - gd->lastinc);
gd->arch.tbl += (now - gd->arch.lastinc);
else /* we have rollover of incrementer */
gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLK / CONFIG_SYS_HZ))
- gd->lastinc) + now;
gd->lastinc = now;
return gd->tbl;
gd->arch.tbl += ((TIMER_LOAD_VAL / (TIMER_CLK / CONFIG_SYS_HZ))
- gd->arch.lastinc) + now;
gd->arch.lastinc = now;
return gd->arch.tbl;
}
/*

View file

@ -0,0 +1,41 @@
#
# Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2000-2008
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC)-common.o
COBJS-y += clock.o funcmux.o pinmux.o
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,655 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra114 Clock control functions */
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/timer.h>
#include <div64.h>
#include <fdtdec.h>
/*
* Clock types that we can use as a source. The Tegra114 has muxes for the
* peripheral clocks, and in most cases there are four options for the clock
* source. This gives us a clock 'type' and exploits what commonality exists
* in the device.
*
* Letters are obvious, except for T which means CLK_M, and S which means the
* clock derived from 32KHz. Beware that CLK_M (also called OSC in the
* datasheet) and PLL_M are different things. The former is the basic
* clock supplied to the SOC from an external oscillator. The latter is the
* memory clock PLL.
*
* See definitions in clock_id in the header file.
*/
enum clock_type_id {
CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */
CLOCK_TYPE_MCPA, /* and so on */
CLOCK_TYPE_MCPT,
CLOCK_TYPE_PCM,
CLOCK_TYPE_PCMT,
CLOCK_TYPE_PCMT16,
CLOCK_TYPE_PDCT,
CLOCK_TYPE_ACPT,
CLOCK_TYPE_ASPTE,
CLOCK_TYPE_PMDACD2T,
CLOCK_TYPE_PCST,
CLOCK_TYPE_COUNT,
CLOCK_TYPE_NONE = -1, /* invalid clock type */
};
enum {
CLOCK_MAX_MUX = 8 /* number of source options for each clock */
};
enum {
MASK_BITS_31_30 = 2, /* num of bits used to specify clock source */
MASK_BITS_31_29,
MASK_BITS_29_28,
};
/*
* Clock source mux for each clock type. This just converts our enum into
* a list of mux sources for use by the code.
*
* Note:
* The extra column in each clock source array is used to store the mask
* bits in its register for the source.
*/
#define CLK(x) CLOCK_ID_ ## x
static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = {
{ CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(AUDIO), CLK(CGENERAL), CLK(PERIPH), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(AUDIO), CLK(SFROM32KHZ), CLK(PERIPH), CLK(OSC),
CLK(EPCI), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_29},
{ CLK(PERIPH), CLK(MEMORY), CLK(DISPLAY), CLK(AUDIO),
CLK(CGENERAL), CLK(DISPLAY2), CLK(OSC), CLK(NONE),
MASK_BITS_31_29},
{ CLK(PERIPH), CLK(CGENERAL), CLK(SFROM32KHZ), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_29_28}
};
/*
* Clock type for each peripheral clock source. We put the name in each
* record just so it is easy to match things up
*/
#define TYPE(name, type) type
static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
/* 0x00 */
TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM),
TYPE(PERIPHC_PWM, CLOCK_TYPE_PCST), /* only PWM uses b29:28 */
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SBC2, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_SBC3, CLOCK_TYPE_PCMT),
/* 0x08 */
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_I2C5, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SBC1, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_DISP1, CLOCK_TYPE_PMDACD2T),
TYPE(PERIPHC_DISP2, CLOCK_TYPE_PMDACD2T),
/* 0x10 */
TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA),
/* 0x18 */
TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT), /* MIPI base-band HSI */
TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT),
/* 0x20 */
TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT),
TYPE(PERIPHC_HDMI, CLOCK_TYPE_PMDACD2T),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT),
TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT),
/* 0x28 */
TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SBC4, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT),
/* 0x30 */
TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_I2S0, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
/* 0x38h */ /* Jumps to reg offset 0x3B0h */
TYPE(PERIPHC_G3D2, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_MSELECT, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCST), /* s/b PCTS */
TYPE(PERIPHC_I2S3, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_I2S4, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_I2C4, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_SBC5, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_SBC6, CLOCK_TYPE_PCMT),
/* 0x40 */
TYPE(PERIPHC_AUDIO, CLOCK_TYPE_ACPT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_DAM0, CLOCK_TYPE_ACPT),
TYPE(PERIPHC_DAM1, CLOCK_TYPE_ACPT),
TYPE(PERIPHC_DAM2, CLOCK_TYPE_ACPT),
TYPE(PERIPHC_HDA2CODEC2X, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_ACTMON, CLOCK_TYPE_PCST), /* MASK 31:30 */
TYPE(PERIPHC_EXTPERIPH1, CLOCK_TYPE_ASPTE),
/* 0x48 */
TYPE(PERIPHC_EXTPERIPH2, CLOCK_TYPE_ASPTE),
TYPE(PERIPHC_EXTPERIPH3, CLOCK_TYPE_ASPTE),
TYPE(PERIPHC_NANDSPEED, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_I2CSLOW, CLOCK_TYPE_PCST), /* MASK 31:30 */
TYPE(PERIPHC_SYS, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SPEEDO, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
/* 0x50 */
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SATAOOB, CLOCK_TYPE_PCMT), /* offset 0x420h */
TYPE(PERIPHC_SATA, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_HDA, CLOCK_TYPE_PCMT),
};
/*
* This array translates a periph_id to a periphc_internal_id
*
* Not present/matched up:
* uint vi_sensor; _VI_SENSOR_0, 0x1A8
* SPDIF - which is both 0x08 and 0x0c
*
*/
#define NONE(name) (-1)
#define OFFSET(name, value) PERIPHC_ ## name
static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
/* Low word: 31:0 */
NONE(CPU),
NONE(COP),
NONE(TRIGSYS),
NONE(RESERVED3),
NONE(RTC),
NONE(TMR),
PERIPHC_UART1,
PERIPHC_UART2, /* and vfir 0x68 */
/* 8 */
NONE(GPIO),
PERIPHC_SDMMC2,
NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */
PERIPHC_I2S1,
PERIPHC_I2C1,
PERIPHC_NDFLASH,
PERIPHC_SDMMC1,
PERIPHC_SDMMC4,
/* 16 */
NONE(RESERVED16),
PERIPHC_PWM,
PERIPHC_I2S2,
PERIPHC_EPP,
PERIPHC_VI,
PERIPHC_G2D,
NONE(USBD),
NONE(ISP),
/* 24 */
PERIPHC_G3D,
NONE(RESERVED25),
PERIPHC_DISP2,
PERIPHC_DISP1,
PERIPHC_HOST1X,
NONE(VCP),
PERIPHC_I2S0,
NONE(CACHE2),
/* Middle word: 63:32 */
NONE(MEM),
NONE(AHBDMA),
NONE(APBDMA),
NONE(RESERVED35),
NONE(RESERVED36),
NONE(STAT_MON),
NONE(RESERVED38),
NONE(RESERVED39),
/* 40 */
NONE(KFUSE),
NONE(SBC1), /* SBC1, 0x34, is this SPI1? */
PERIPHC_NOR,
NONE(RESERVED43),
PERIPHC_SBC2,
NONE(RESERVED45),
PERIPHC_SBC3,
PERIPHC_I2C5,
/* 48 */
NONE(DSI),
PERIPHC_TVO, /* also CVE 0x40 */
PERIPHC_MIPI,
PERIPHC_HDMI,
NONE(CSI),
PERIPHC_TVDAC,
PERIPHC_I2C2,
PERIPHC_UART3,
/* 56 */
NONE(RESERVED56),
PERIPHC_EMC,
NONE(USB2),
NONE(USB3),
PERIPHC_MPE,
PERIPHC_VDE,
NONE(BSEA),
NONE(BSEV),
/* Upper word 95:64 */
PERIPHC_SPEEDO,
PERIPHC_UART4,
PERIPHC_UART5,
PERIPHC_I2C3,
PERIPHC_SBC4,
PERIPHC_SDMMC3,
NONE(PCIE),
PERIPHC_OWR,
/* 72 */
NONE(AFI),
PERIPHC_CSITE,
NONE(PCIEXCLK),
NONE(AVPUCQ),
NONE(RESERVED76),
NONE(RESERVED77),
NONE(RESERVED78),
NONE(DTV),
/* 80 */
PERIPHC_NANDSPEED,
PERIPHC_I2CSLOW,
NONE(DSIB),
NONE(RESERVED83),
NONE(IRAMA),
NONE(IRAMB),
NONE(IRAMC),
NONE(IRAMD),
/* 88 */
NONE(CRAM2),
NONE(RESERVED89),
NONE(MDOUBLER),
NONE(RESERVED91),
NONE(SUSOUT),
NONE(RESERVED93),
NONE(RESERVED94),
NONE(RESERVED95),
/* V word: 31:0 */
NONE(CPUG),
NONE(CPULP),
PERIPHC_G3D2,
PERIPHC_MSELECT,
PERIPHC_TSENSOR,
PERIPHC_I2S3,
PERIPHC_I2S4,
PERIPHC_I2C4,
/* 08 */
PERIPHC_SBC5,
PERIPHC_SBC6,
PERIPHC_AUDIO,
NONE(APBIF),
PERIPHC_DAM0,
PERIPHC_DAM1,
PERIPHC_DAM2,
PERIPHC_HDA2CODEC2X,
/* 16 */
NONE(ATOMICS),
NONE(RESERVED17),
NONE(RESERVED18),
NONE(RESERVED19),
NONE(RESERVED20),
NONE(RESERVED21),
NONE(RESERVED22),
PERIPHC_ACTMON,
/* 24 */
NONE(RESERVED24),
NONE(RESERVED25),
NONE(RESERVED26),
NONE(RESERVED27),
PERIPHC_SATA,
PERIPHC_HDA,
NONE(RESERVED30),
NONE(RESERVED31),
/* W word: 31:0 */
NONE(HDA2HDMICODEC),
NONE(RESERVED1_SATACOLD),
NONE(RESERVED2_PCIERX0),
NONE(RESERVED3_PCIERX1),
NONE(RESERVED4_PCIERX2),
NONE(RESERVED5_PCIERX3),
NONE(RESERVED6_PCIERX4),
NONE(RESERVED7_PCIERX5),
/* 40 */
NONE(CEC),
NONE(PCIE2_IOBIST),
NONE(EMC_IOBIST),
NONE(HDMI_IOBIST),
NONE(SATA_IOBIST),
NONE(MIPI_IOBIST),
NONE(EMC1_IOBIST),
NONE(XUSB),
/* 48 */
NONE(CILAB),
NONE(CILCD),
NONE(CILE),
NONE(DSIA_LP),
NONE(DSIB_LP),
NONE(RESERVED21_ENTROPY),
NONE(RESERVED22_W),
NONE(RESERVED23_W),
/* 56 */
NONE(RESERVED24_W),
NONE(AMX0),
NONE(ADX0),
NONE(DVFS),
NONE(XUSB_SS),
NONE(EMC_DLL),
NONE(MC1),
NONE(EMC1),
};
/*
* Get the oscillator frequency, from the corresponding hardware configuration
* field. Note that T30/T114 support 3 new higher freqs, but we map back
* to the old T20 freqs. Support for the higher oscillators is TBD.
*/
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);
reg = (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
if (reg & 1) /* one of the newer freqs */
printf("Warning: OSC_FREQ is unsupported! (%d)\n", reg);
return reg >> 2; /* Map to most common (T20) freqs */
}
/* Returns a pointer to the clock source register for a peripheral */
u32 *get_periph_source_reg(enum periph_id periph_id)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
enum periphc_internal_id internal_id;
/* Coresight is a special case */
if (periph_id == PERIPH_ID_CSI)
return &clkrst->crc_clk_src[PERIPH_ID_CSI+1];
assert(periph_id >= PERIPH_ID_FIRST && periph_id < PERIPH_ID_COUNT);
internal_id = periph_id_to_internal_id[periph_id];
assert(internal_id != -1);
if (internal_id >= PERIPHC_VW_FIRST) {
internal_id -= PERIPHC_VW_FIRST;
return &clkrst->crc_clk_src_vw[internal_id];
} else
return &clkrst->crc_clk_src[internal_id];
}
/**
* Given a peripheral ID and the required source clock, this returns which
* value should be programmed into the source mux for that peripheral.
*
* There is special code here to handle the one source type with 5 sources.
*
* @param periph_id peripheral to start
* @param source PLL id of required parent clock
* @param mux_bits Set to number of bits in mux register: 2 or 4
* @param divider_bits Set to number of divider bits (8 or 16)
* @return mux value (0-4, or -1 if not found)
*/
int get_periph_clock_source(enum periph_id periph_id,
enum clock_id parent, int *mux_bits, int *divider_bits)
{
enum clock_type_id type;
enum periphc_internal_id internal_id;
int mux;
assert(clock_periph_id_isvalid(periph_id));
internal_id = periph_id_to_internal_id[periph_id];
assert(periphc_internal_id_isvalid(internal_id));
type = clock_periph_type[internal_id];
assert(clock_type_id_isvalid(type));
*mux_bits = clock_source[type][CLOCK_MAX_MUX];
if (type == CLOCK_TYPE_PCMT16)
*divider_bits = 16;
else
*divider_bits = 8;
for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
if (clock_source[type][mux] == parent)
return mux;
/* if we get here, either us or the caller has made a mistake */
printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
parent);
return -1;
}
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;
u32 reg;
/* Enable/disable the clock to this peripheral */
assert(clock_periph_id_isvalid(periph_id));
if ((int)periph_id < (int)PERIPH_ID_VW_FIRST)
clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
else
clk = &clkrst->crc_clk_out_enb_vw[PERIPH_REG(periph_id)];
reg = readl(clk);
if (enable)
reg |= PERIPH_MASK(periph_id);
else
reg &= ~PERIPH_MASK(periph_id);
writel(reg, clk);
}
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;
u32 reg;
/* Enable/disable reset to the peripheral */
assert(clock_periph_id_isvalid(periph_id));
if (periph_id < PERIPH_ID_VW_FIRST)
reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
else
reset = &clkrst->crc_rst_dev_vw[PERIPH_REG(periph_id)];
reg = readl(reset);
if (enable)
reg |= PERIPH_MASK(periph_id);
else
reg &= ~PERIPH_MASK(periph_id);
writel(reg, reset);
}
#ifdef CONFIG_OF_CONTROL
/*
* Convert a device tree clock ID to our peripheral ID. They are mostly
* the same but we are very cautious so we check that a valid clock ID is
* provided.
*
* @param clk_id Clock ID according to tegra114 device tree binding
* @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
*/
enum periph_id clk_id_to_periph_id(int clk_id)
{
if (clk_id > PERIPH_ID_COUNT)
return PERIPH_ID_NONE;
switch (clk_id) {
case PERIPH_ID_RESERVED3:
case PERIPH_ID_RESERVED16:
case PERIPH_ID_RESERVED24:
case PERIPH_ID_RESERVED35:
case PERIPH_ID_RESERVED43:
case PERIPH_ID_RESERVED45:
case PERIPH_ID_RESERVED56:
case PERIPH_ID_RESERVED76:
case PERIPH_ID_RESERVED77:
case PERIPH_ID_RESERVED78:
case PERIPH_ID_RESERVED83:
case PERIPH_ID_RESERVED89:
case PERIPH_ID_RESERVED91:
case PERIPH_ID_RESERVED93:
case PERIPH_ID_RESERVED94:
case PERIPH_ID_RESERVED95:
return PERIPH_ID_NONE;
default:
return clk_id;
}
}
#endif /* CONFIG_OF_CONTROL */
void clock_early_init(void)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
/*
* PLLP output frequency set to 408Mhz
* PLLC output frequency set to 600Mhz
* PLLD output frequency set to 925Mhz
*/
switch (clock_get_osc_freq()) {
case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
clock_set_rate(CLOCK_ID_PERIPH, 408, 12, 0, 8);
clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8);
clock_set_rate(CLOCK_ID_DISPLAY, 925, 12, 0, 12);
break;
case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
clock_set_rate(CLOCK_ID_PERIPH, 408, 26, 0, 8);
clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
clock_set_rate(CLOCK_ID_DISPLAY, 925, 26, 0, 12);
break;
case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
clock_set_rate(CLOCK_ID_PERIPH, 408, 13, 0, 8);
clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
clock_set_rate(CLOCK_ID_DISPLAY, 925, 13, 0, 12);
break;
case CLOCK_OSC_FREQ_19_2:
default:
/*
* These are not supported. It is too early to print a
* message and the UART likely won't work anyway due to the
* oscillator being wrong.
*/
break;
}
/* PLLC_MISC2: Set dynramp_stepA/B. MISC2 maps to pll_out[1] */
writel(0x00561600, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_out[1]);
/* PLLC_MISC: Set LOCK_ENABLE */
writel(0x01000000, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc);
udelay(2);
/* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1 */
writel(0x40000C10, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc);
udelay(2);
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra114 high-level function multiplexing */
#include <common.h>
#include <asm/arch/clock.h>
#include <asm/arch/funcmux.h>
#include <asm/arch/pinmux.h>
int funcmux_select(enum periph_id id, int config)
{
int bad_config = config != FUNCMUX_DEFAULT;
switch (id) {
case PERIPH_ID_UART4:
switch (config) {
case FUNCMUX_UART4_GMI:
pinmux_set_func(PINGRP_GMI_A16, PMUX_FUNC_UARTD);
pinmux_set_func(PINGRP_GMI_A17, PMUX_FUNC_UARTD);
pinmux_set_func(PINGRP_GMI_A18, PMUX_FUNC_UARTD);
pinmux_set_func(PINGRP_GMI_A19, PMUX_FUNC_UARTD);
pinmux_set_io(PINGRP_GMI_A16, PMUX_PIN_OUTPUT);
pinmux_set_io(PINGRP_GMI_A17, PMUX_PIN_INPUT);
pinmux_set_io(PINGRP_GMI_A18, PMUX_PIN_INPUT);
pinmux_set_io(PINGRP_GMI_A19, PMUX_PIN_OUTPUT);
pinmux_tristate_disable(PINGRP_GMI_A16);
pinmux_tristate_disable(PINGRP_GMI_A17);
pinmux_tristate_disable(PINGRP_GMI_A18);
pinmux_tristate_disable(PINGRP_GMI_A19);
break;
}
break;
/* Add other periph IDs here as needed */
default:
debug("%s: invalid periph_id %d", __func__, id);
return -1;
}
if (bad_config) {
debug("%s: invalid config %d for periph_id %d", __func__,
config, id);
return -1;
}
return 0;
}

View file

@ -0,0 +1,506 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra114 pin multiplexing functions */
#include <common.h>
#include <asm/io.h>
#include <asm/arch/tegra.h>
#include <asm/arch/pinmux.h>
struct tegra_pingroup_desc {
const char *name;
enum pmux_func funcs[4];
enum pmux_func func_safe;
enum pmux_vddio vddio;
enum pmux_pin_io io;
};
#define PMUX_MUXCTL_SHIFT 0
#define PMUX_PULL_SHIFT 2
#define PMUX_TRISTATE_SHIFT 4
#define PMUX_TRISTATE_MASK (1 << PMUX_TRISTATE_SHIFT)
#define PMUX_IO_SHIFT 5
#define PMUX_OD_SHIFT 6
#define PMUX_LOCK_SHIFT 7
#define PMUX_IO_RESET_SHIFT 8
/* Convenient macro for defining pin group properties */
#define PIN(pg_name, vdd, f0, f1, f2, f3, iod) \
{ \
.vddio = PMUX_VDDIO_ ## vdd, \
.funcs = { \
PMUX_FUNC_ ## f0, \
PMUX_FUNC_ ## f1, \
PMUX_FUNC_ ## f2, \
PMUX_FUNC_ ## f3, \
}, \
.func_safe = PMUX_FUNC_RSVD1, \
.io = PMUX_PIN_ ## iod, \
}
/* Input and output pins */
#define PINI(pg_name, vdd, f0, f1, f2, f3) \
PIN(pg_name, vdd, f0, f1, f2, f3, INPUT)
#define PINO(pg_name, vdd, f0, f1, f2, f3) \
PIN(pg_name, vdd, f0, f1, f2, f3, OUTPUT)
const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
/* NAME VDD f0 f1 f2 f3 */
PINI(ULPI_DATA0, BB, SPI3, HSI, UARTA, ULPI),
PINI(ULPI_DATA1, BB, SPI3, HSI, UARTA, ULPI),
PINI(ULPI_DATA2, BB, SPI3, HSI, UARTA, ULPI),
PINI(ULPI_DATA3, BB, SPI3, HSI, UARTA, ULPI),
PINI(ULPI_DATA4, BB, SPI2, HSI, UARTA, ULPI),
PINI(ULPI_DATA5, BB, SPI2, HSI, UARTA, ULPI),
PINI(ULPI_DATA6, BB, SPI2, HSI, UARTA, ULPI),
PINI(ULPI_DATA7, BB, SPI2, HSI, UARTA, ULPI),
PINI(ULPI_CLK, BB, SPI1, SPI5, UARTD, ULPI),
PINI(ULPI_DIR, BB, SPI1, SPI5, UARTD, ULPI),
PINI(ULPI_NXT, BB, SPI1, SPI5, UARTD, ULPI),
PINI(ULPI_STP, BB, SPI1, SPI5, UARTD, ULPI),
PINI(DAP3_FS, BB, I2S2, SPI5, DISPA, DISPB),
PINI(DAP3_DIN, BB, I2S2, SPI5, DISPA, DISPB),
PINI(DAP3_DOUT, BB, I2S2, SPI5, DISPA, DISPB),
PINI(DAP3_SCLK, BB, I2S2, SPI5, DISPA, DISPB),
PINI(GPIO_PV0, BB, USB, RSVD2, RSVD3, RSVD4),
PINI(GPIO_PV1, BB, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(SDMMC1_CLK, SDMMC1, SDMMC1, CLK12, RSVD3, RSVD4),
PINI(SDMMC1_CMD, SDMMC1, SDMMC1, SPDIF, SPI4, UARTA),
PINI(SDMMC1_DAT3, SDMMC1, SDMMC1, SPDIF, SPI4, UARTA),
PINI(SDMMC1_DAT2, SDMMC1, SDMMC1, PWM0, SPI4, UARTA),
PINI(SDMMC1_DAT1, SDMMC1, SDMMC1, PWM1, SPI4, UARTA),
PINI(SDMMC1_DAT0, SDMMC1, SDMMC1, RSVD2, SPI4, UARTA),
PINI(GPIO_PV2, BB, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(GPIO_PV3, BB, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(CLK2_OUT, SDMMC1, EXTPERIPH2, RSVD2, RSVD3, RSVD4),
PINI(CLK2_REQ, SDMMC1, DAP, RSVD2, RSVD3, RSVD4),
PINO(LCD_PWR1, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_PWR2, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_SDIN, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_SDOUT, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_WR_N, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_CS0_N, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_DC0, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_SCK, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_PWR0, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_PCLK, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_DE, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_HSYNC, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_VSYNC, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D0, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D1, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D2, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D3, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D4, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D5, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D6, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D7, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D8, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D9, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D10, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D11, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D12, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D13, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D14, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D15, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D16, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D17, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D18, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D19, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D20, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D21, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D22, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_D23, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_CS1_N, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_M1, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINO(LCD_DC1, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(HDMI_INT, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(DDC_SCL, LCD, I2C4, RSVD2, RSVD3, RSVD4),
PINI(DDC_SDA, LCD, I2C4, RSVD2, RSVD3, RSVD4),
PINI(CRT_HSYNC, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(CRT_VSYNC, LCD, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D0, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D1, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D2, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D3, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D4, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D5, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D6, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D7, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D8, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D9, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D10, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_D11, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_PCLK, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_MCLK, VI, RSVD1, RSVD3, RSVD3, RSVD4),
PINI(VI_VSYNC, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(VI_HSYNC, VI, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(UART2_RXD, UART, UARTB, SPDIF, UARTA, SPI4),
PINI(UART2_TXD, UART, UARTB, SPDIF, UARTA, SPI4),
PINI(UART2_RTS_N, UART, UARTA, UARTB, RSVD3, SPI4),
PINI(UART2_CTS_N, UART, UARTA, UARTB, RSVD3, SPI4),
PINI(UART3_TXD, UART, UARTC, RSVD2, RSVD3, SPI4),
PINI(UART3_RXD, UART, UARTC, RSVD2, RSVD3, SPI4),
PINI(UART3_CTS_N, UART, UARTC, SDMMC1, DTV, SPI4),
PINI(UART3_RTS_N, UART, UARTC, PWM0, DTV, DISPA),
PINI(GPIO_PU0, UART, OWR, UARTA, RSVD3, RSVD4),
PINI(GPIO_PU1, UART, RSVD1, UARTA, RSVD3, RSVD4),
PINI(GPIO_PU2, UART, RSVD1, UARTA, RSVD3, RSVD4),
PINI(GPIO_PU3, UART, PWM0, UARTA, DISPA, DISPB),
PINI(GPIO_PU4, UART, PWM1, UARTA, DISPA, DISPB),
PINI(GPIO_PU5, UART, PWM2, UARTA, DISPA, DISPB),
PINI(GPIO_PU6, UART, PWM3, UARTA, USB, DISPB),
PINI(GEN1_I2C_SDA, UART, I2C1, RSVD2, RSVD3, RSVD4),
PINI(GEN1_I2C_SCL, UART, I2C1, RSVD2, RSVD3, RSVD4),
PINI(DAP4_FS, UART, I2S3, RSVD2, DTV, RSVD4),
PINI(DAP4_DIN, UART, I2S3, RSVD2, RSVD3, RSVD4),
PINI(DAP4_DOUT, UART, I2S3, RSVD2, DTV, RSVD4),
PINI(DAP4_SCLK, UART, I2S3, RSVD2, RSVD3, RSVD4),
PINI(CLK3_OUT, UART, EXTPERIPH3, RSVD2, RSVD3, RSVD4),
PINI(CLK3_REQ, UART, DEV3, RSVD2, RSVD3, RSVD4),
PINI(GMI_WP_N, GMI, RSVD1, NAND, GMI, GMI_ALT),
PINI(GMI_IORDY, GMI, SDMMC2, RSVD2, GMI, TRACE),
PINI(GMI_WAIT, GMI, SPI4, NAND, GMI, DTV),
PINI(GMI_ADV_N, GMI, RSVD1, NAND, GMI, TRACE),
PINI(GMI_CLK, GMI, SDMMC2, NAND, GMI, TRACE),
PINI(GMI_CS0_N, GMI, RSVD1, NAND, GMI, USB),
PINI(GMI_CS1_N, GMI, RSVD1, NAND, GMI, SOC),
PINI(GMI_CS2_N, GMI, SDMMC2, NAND, GMI, TRACE),
PINI(GMI_CS3_N, GMI, SDMMC2, NAND, GMI, GMI_ALT),
PINI(GMI_CS4_N, GMI, USB, NAND, GMI, TRACE),
PINI(GMI_CS6_N, GMI, NAND, NAND_ALT, GMI, SPI4),
PINI(GMI_CS7_N, GMI, NAND, NAND_ALT, GMI, SDMMC2),
PINI(GMI_AD0, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD1, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD2, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD3, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD4, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD5, GMI, RSVD1, NAND, GMI, SPI4),
PINI(GMI_AD6, GMI, RSVD1, NAND, GMI, SPI4),
PINI(GMI_AD7, GMI, RSVD1, NAND, GMI, SPI4),
PINI(GMI_AD8, GMI, PWM0, NAND, GMI, DTV),
PINI(GMI_AD9, GMI, PWM1, NAND, GMI, CLDVFS),
PINI(GMI_AD10, GMI, PWM2, NAND, GMI, CLDVFS),
PINI(GMI_AD11, GMI, PWM3, NAND, GMI, USB),
PINI(GMI_AD12, GMI, SDMMC2, NAND, GMI, RSVD4),
PINI(GMI_AD13, GMI, SDMMC2, NAND, GMI, RSVD4),
PINI(GMI_AD14, GMI, SDMMC2, NAND, GMI, DTV),
PINI(GMI_AD15, GMI, SDMMC2, NAND, GMI, DTV),
PINI(GMI_A16, GMI, UARTD, TRACE, GMI, GMI_ALT),
PINI(GMI_A17, GMI, UARTD, RSVD2, GMI, TRACE),
PINI(GMI_A18, GMI, UARTD, RSVD2, GMI, TRACE),
PINI(GMI_A19, GMI, UARTD, SPI4, GMI, TRACE),
PINI(GMI_WR_N, GMI, RSVD1, NAND, GMI, SPI4),
PINI(GMI_OE_N, GMI, RSVD1, NAND, GMI, SOC),
PINI(GMI_DQS, GMI, SDMMC2, NAND, GMI, TRACE),
PINI(GMI_RST_N, GMI, NAND, NAND_ALT, GMI, RSVD4),
PINI(GEN2_I2C_SCL, GMI, I2C2, RSVD2, GMI, RSVD4),
PINI(GEN2_I2C_SDA, GMI, I2C2, RSVD2, GMI, RSVD4),
PINI(SDMMC4_CLK, SDMMC4, SDMMC4, RSVD2, GMI, RSVD4),
PINI(SDMMC4_CMD, SDMMC4, SDMMC4, RSVD2, GMI, RSVD4),
PINI(SDMMC4_DAT0, SDMMC4, SDMMC4, SPI3, GMI, RSVD4),
PINI(SDMMC4_DAT1, SDMMC4, SDMMC4, SPI3, GMI, RSVD4),
PINI(SDMMC4_DAT2, SDMMC4, SDMMC4, SPI3, GMI, RSVD4),
PINI(SDMMC4_DAT3, SDMMC4, SDMMC4, SPI3, GMI, RSVD4),
PINI(SDMMC4_DAT4, SDMMC4, SDMMC4, SPI3, GMI, RSVD4),
PINI(SDMMC4_DAT5, SDMMC4, SDMMC4, SPI3, GMI, RSVD4),
PINI(SDMMC4_DAT6, SDMMC4, SDMMC4, SPI3, GMI, RSVD4),
PINI(SDMMC4_DAT7, SDMMC4, SDMMC4, RSVD2, GMI, RSVD4),
PINI(SDMMC4_RST_N, SDMMC4, RSVD1, RSVD2, RSVD3, SDMMC4),
PINI(CAM_MCLK, CAM, VI, VI_ALT1, VI_ALT2, RSVD4),
PINI(GPIO_PCC1, CAM, I2S4, RSVD2, RSVD3, RSVD4),
PINI(GPIO_PBB0, CAM, I2S4, VI, VI_ALT1, VI_ALT3),
PINI(CAM_I2C_SCL, CAM, VGP1, I2C3, RSVD3, RSVD4),
PINI(CAM_I2C_SDA, CAM, VGP2, I2C3, RSVD3, RSVD4),
PINI(GPIO_PBB3, CAM, VGP3, DISPA, DISPB, RSVD4),
PINI(GPIO_PBB4, CAM, VGP4, DISPA, DISPB, RSVD4),
PINI(GPIO_PBB5, CAM, VGP5, DISPA, DISPB, RSVD4),
PINI(GPIO_PBB6, CAM, VGP6, DISPA, DISPB, RSVD4),
PINI(GPIO_PBB7, CAM, I2S4, RSVD2, RSVD3, RSVD4),
PINI(GPIO_PCC2, CAM, I2S4, RSVD2, RSVD3, RSVD4),
PINI(JTAG_RTCK, SYS, RTCK, RSVD2, RSVD3, RSVD4),
PINI(PWR_I2C_SCL, SYS, I2CPWR, RSVD2, RSVD3, RSVD4),
PINI(PWR_I2C_SDA, SYS, I2CPWR, RSVD2, RSVD3, RSVD4),
PINI(KB_ROW0, SYS, KBC, RSVD2, DTV, RSVD4),
PINI(KB_ROW1, SYS, KBC, RSVD2, DTV, RSVD4),
PINI(KB_ROW2, SYS, KBC, RSVD2, DTV, SOC),
PINI(KB_ROW3, SYS, KBC, DISPA, RSVD3, DISPB),
PINI(KB_ROW4, SYS, KBC, DISPA, SPI2, DISPB),
PINI(KB_ROW5, SYS, KBC, DISPA, SPI2, DISPB),
PINI(KB_ROW6, SYS, KBC, DISPA, RSVD3, DISPB),
PINI(KB_ROW7, SYS, KBC, RSVD2, CLDVFS, UARTA),
PINI(KB_ROW8, SYS, KBC, RSVD2, RSVD3, UARTA),
PINI(KB_ROW9, SYS, KBC, RSVD2, RSVD3, UARTA),
PINI(KB_ROW10, SYS, KBC, RSVD2, RSVD3, UARTA),
PINI(KB_ROW11, SYS, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(KB_ROW12, SYS, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(KB_ROW13, SYS, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(KB_ROW14, SYS, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(KB_ROW15, SYS, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(KB_COL0, SYS, KBC, USB, SPI2, EMC_DLL),
PINI(KB_COL1, SYS, KBC, RSVD2, SPI2, EMC_DLL),
PINI(KB_COL2, SYS, KBC, RSVD2, SPI2, RSVD4),
PINI(KB_COL3, SYS, KBC, DISPA, PWM2, UARTA),
PINI(KB_COL4, SYS, KBC, OWR, SDMMC3, UARTA),
PINI(KB_COL5, SYS, KBC, RSVD2, SDMMC1, RSVD4),
PINI(KB_COL6, SYS, KBC, RSVD2, SPI2, RSVD4),
PINI(KB_COL7, SYS, KBC, RSVD2, SPI2, RSVD4),
PINI(CLK_32K_OUT, SYS, BLINK, SOC, RSVD3, RSVD4),
PINI(SYS_CLK_REQ, SYS, SYSCLK, RSVD2, RSVD3, RSVD4),
PINI(CORE_PWR_REQ, SYS, PWRON, RSVD2, RSVD3, RSVD4),
PINI(CPU_PWR_REQ, SYS, CPU, RSVD2, RSVD3, RSVD4),
PINI(PWR_INT_N, SYS, PMI, RSVD2, RSVD3, RSVD4),
PINI(CLK_32K_IN, SYS, CLK, RSVD2, RSVD3, RSVD4),
PINI(OWR, SYS, OWR, RSVD2, RSVD3, RSVD4),
PINI(DAP1_FS, AUDIO, I2S0, HDA, GMI, RSVD4),
PINI(DAP1_DIN, AUDIO, I2S0, HDA, GMI, RSVD4),
PINI(DAP1_DOUT, AUDIO, I2S0, HDA, GMI, RSVD4),
PINI(DAP1_SCLK, AUDIO, I2S0, HDA, GMI, RSVD4),
PINI(CLK1_REQ, AUDIO, DAP, DAP1, RSVD3, RSVD4),
PINI(CLK1_OUT, AUDIO, EXTPERIPH1, DAP2, RSVD3, RSVD4),
PINI(SPDIF_IN, AUDIO, SPDIF, USB, RSVD3, RSVD4),
PINI(SPDIF_OUT, AUDIO, SPDIF, RSVD2, RSVD3, RSVD4),
PINI(DAP2_FS, AUDIO, I2S1, HDA, RSVD3, RSVD4),
PINI(DAP2_DIN, AUDIO, I2S1, HDA, RSVD3, RSVD4),
PINI(DAP2_DOUT, AUDIO, I2S1, HDA, RSVD3, RSVD4),
PINI(DAP2_SCLK, AUDIO, I2S1, HDA, RSVD3, RSVD4),
PINI(SPI2_MOSI, AUDIO, SPI6, CLDVFS, RSVD3, RSVD4),
PINI(SPI2_MISO, AUDIO, SPI6, RSVD2, RSVD3, RSVD4),
PINI(SPI2_CS0_N, AUDIO, SPI6, SPI1, RSVD3, RSVD4),
PINI(SPI2_SCK, AUDIO, SPI6, CLDVFS, RSVD3, RSVD4),
PINI(SPI1_MOSI, AUDIO, RSVD1, SPI1, SPI2, DAP2),
PINI(SPI1_SCK, AUDIO, RSVD1, SPI1, SPI2, RSVD4),
PINI(SPI1_CS0_N, AUDIO, SPI6, SPI1, SPI2, RSVD4),
PINI(SPI1_MISO, AUDIO, RSVD1, SPI1, SPI2, RSVD4),
PINI(SPI2_CS1_N, AUDIO, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(SPI2_CS2_N, AUDIO, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(SDMMC3_CLK, SDMMC3, SDMMC3, RSVD2, RSVD3, SPI3),
PINI(SDMMC3_CMD, SDMMC3, SDMMC3, PWM3, UARTA, SPI3),
PINI(SDMMC3_DAT0, SDMMC3, SDMMC3, RSVD2, RSVD3, SPI3),
PINI(SDMMC3_DAT1, SDMMC3, SDMMC3, PWM2, UARTA, SPI3),
PINI(SDMMC3_DAT2, SDMMC3, SDMMC3, PWM1, DISPA, SPI3),
PINI(SDMMC3_DAT3, SDMMC3, SDMMC3, PWM0, DISPB, SPI3),
PINI(SDMMC3_DAT4, SDMMC3, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(SDMMC3_DAT5, SDMMC3, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(SDMMC3_DAT6, SDMMC3, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(SDMMC3_DAT7, SDMMC3, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(HDMI_CEC, SYS, CEC, SDMMC3, RSVD3, SOC),
PINI(SDMMC1_WP_N, SDMMC1, SDMMC1, CLK12, SPI4, UARTA),
PINI(SDMMC3_CD_N, SDMMC3, SDMMC3, OWR, RSVD3, RSVD4),
PINI(SPI1_CS1_N, AUDIO, SPI6, RSVD2, SPI2, I2C1),
PINI(SPI1_CS2_N, AUDIO, SPI6, SPI1, SPI2, I2C1),
PINI(USB_VBUS_EN0, SYS, USB, RSVD2, RSVD3, RSVD4),
PINI(USB_VBUS_EN1, SYS, USB, RSVD2, RSVD3, RSVD4),
PINI(SDMMC3_CLK_LB_IN, SDMMC3, SDMMC3, RSVD2, RSVD3, RSVD4),
PINO(SDMMC3_CLK_LB_OUT, SDMMC3, SDMMC3, RSVD2, RSVD3, RSVD4),
PINO(NAND_GMI_CLK_LB, GMI, SDMMC2, NAND, GMI, RSVD4),
PINO(RESET_OUT_N, SYS, RSVD1, RSVD2, RSVD3, RESET_OUT_N),
};
void pinmux_set_tristate(enum pmux_pingrp pin, int enable)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *tri = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin */
assert(pmux_pingrp_isvalid(pin));
reg = readl(tri);
if (enable)
reg |= PMUX_TRISTATE_MASK;
else
reg &= ~PMUX_TRISTATE_MASK;
writel(reg, tri);
}
void pinmux_tristate_enable(enum pmux_pingrp pin)
{
pinmux_set_tristate(pin, 1);
}
void pinmux_tristate_disable(enum pmux_pingrp pin)
{
pinmux_set_tristate(pin, 0);
}
void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pull = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and pupd */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_pupd_isvalid(pupd));
reg = readl(pull);
reg &= ~(0x3 << PMUX_PULL_SHIFT);
reg |= (pupd << PMUX_PULL_SHIFT);
writel(reg, pull);
}
void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *muxctl = &pmt->pmt_ctl[pin];
int i, mux = -1;
u32 reg;
/* Error check on pin and func */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_func_isvalid(func));
/* Handle special values */
if (func == PMUX_FUNC_SAFE)
func = tegra_soc_pingroups[pin].func_safe;
if (func & PMUX_FUNC_RSVD1) {
mux = func & 0x3;
} else {
/* Search for the appropriate function */
for (i = 0; i < 4; i++) {
if (tegra_soc_pingroups[pin].funcs[i] == func) {
mux = i;
break;
}
}
}
assert(mux != -1);
reg = readl(muxctl);
reg &= ~(0x3 << PMUX_MUXCTL_SHIFT);
reg |= (mux << PMUX_MUXCTL_SHIFT);
writel(reg, muxctl);
}
void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pin_io = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and io */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_io_isvalid(io));
reg = readl(pin_io);
reg &= ~(0x1 << PMUX_IO_SHIFT);
reg |= (io & 0x1) << PMUX_IO_SHIFT;
writel(reg, pin_io);
}
static int pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pin_lock = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and lock */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_lock_isvalid(lock));
if (lock == PMUX_PIN_LOCK_DEFAULT)
return 0;
reg = readl(pin_lock);
reg &= ~(0x1 << PMUX_LOCK_SHIFT);
if (lock == PMUX_PIN_LOCK_ENABLE)
reg |= (0x1 << PMUX_LOCK_SHIFT);
else {
/* lock == DISABLE, which isn't possible */
printf("%s: Warning: lock == %d, DISABLE is not allowed!\n",
__func__, lock);
}
writel(reg, pin_lock);
return 0;
}
static int pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pin_od = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and od */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_od_isvalid(od));
if (od == PMUX_PIN_OD_DEFAULT)
return 0;
reg = readl(pin_od);
reg &= ~(0x1 << PMUX_OD_SHIFT);
if (od == PMUX_PIN_OD_ENABLE)
reg |= (0x1 << PMUX_OD_SHIFT);
writel(reg, pin_od);
return 0;
}
static int pinmux_set_ioreset(enum pmux_pingrp pin,
enum pmux_pin_ioreset ioreset)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pin_ioreset = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and ioreset */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_ioreset_isvalid(ioreset));
if (ioreset == PMUX_PIN_IO_RESET_DEFAULT)
return 0;
reg = readl(pin_ioreset);
reg &= ~(0x1 << PMUX_IO_RESET_SHIFT);
if (ioreset == PMUX_PIN_IO_RESET_ENABLE)
reg |= (0x1 << PMUX_IO_RESET_SHIFT);
writel(reg, pin_ioreset);
return 0;
}
void pinmux_config_pingroup(struct pingroup_config *config)
{
enum pmux_pingrp pin = config->pingroup;
pinmux_set_func(pin, config->func);
pinmux_set_pullupdown(pin, config->pull);
pinmux_set_tristate(pin, config->tristate);
pinmux_set_io(pin, config->io);
pinmux_set_lock(pin, config->lock);
pinmux_set_od(pin, config->od);
pinmux_set_ioreset(pin, config->ioreset);
}
void pinmux_config_table(struct pingroup_config *config, int len)
{
int i;
for (i = 0; i < len; i++)
pinmux_config_pingroup(&config[i]);
}

View file

@ -30,24 +30,6 @@
#include <div64.h>
#include <fdtdec.h>
/*
* This is our record of the current clock rate of each clock. We don't
* fill all of these in since we are only really interested in clocks which
* we use as parents.
*/
static unsigned pll_rate[CLOCK_ID_COUNT];
/*
* The oscillator frequency is fixed to one of four set values. Based on this
* the other clocks are set up appropriately.
*/
static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {
13000000,
19200000,
12000000,
26000000,
};
/*
* Clock types that we can use as a source. The Tegra20 has muxes for the
* peripheral clocks, and in most cases there are four options for the clock
@ -76,12 +58,6 @@ enum clock_type_id {
CLOCK_TYPE_NONE = -1, /* invalid clock type */
};
/* return 1 if a peripheral ID is in range */
#define clock_type_id_isvalid(id) ((id) >= 0 && \
(id) < CLOCK_TYPE_COUNT)
char pllp_valid = 1; /* PLLP is set up correctly */
enum {
CLOCK_MAX_MUX = 4 /* number of source options for each clock */
};
@ -192,10 +168,6 @@ enum periphc_internal_id {
PERIPHC_NONE = -1,
};
/* return 1 if a periphc_internal_id is in range */
#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
(id) < PERIPHC_COUNT)
/*
* Clock type for each peripheral clock source. We put the name in each
* record just so it is easy to match things up
@ -396,19 +368,9 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
NONE(CRAM2),
};
/* number of clock outputs of a PLL */
static const u8 pll_num_clkouts[] = {
1, /* PLLC */
1, /* PLLM */
4, /* PLLP */
1, /* PLLA */
0, /* PLLU */
0, /* PLLD */
};
/*
* Get the oscillator frequency, from the corresponding hardware configuration
* field.
* field. T20 has 4 frequencies that it supports.
*/
enum clock_osc_freq clock_get_osc_freq(void)
{
@ -420,110 +382,8 @@ enum clock_osc_freq clock_get_osc_freq(void)
return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
}
int clock_get_osc_bypass(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_XOBP_MASK) >> OSC_XOBP_SHIFT;
}
/* Returns a pointer to the registers of the given pll */
static struct clk_pll *get_pll(enum clock_id clkid)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
assert(clock_id_is_pll(clkid));
return &clkrst->crc_pll[clkid];
}
int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
u32 *divp, u32 *cpcon, u32 *lfcon)
{
struct clk_pll *pll = get_pll(clkid);
u32 data;
assert(clkid != CLOCK_ID_USB);
/* Safety check, adds to code size but is small */
if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB)
return -1;
data = readl(&pll->pll_base);
*divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
*divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
*divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
data = readl(&pll->pll_misc);
*cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
*lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
return 0;
}
unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
u32 divp, u32 cpcon, u32 lfcon)
{
struct clk_pll *pll = get_pll(clkid);
u32 data;
/*
* 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_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;
}
/* return 1 if a peripheral ID is in range and valid */
static int clock_periph_id_isvalid(enum periph_id id)
{
if (id < PERIPH_ID_FIRST || id >= PERIPH_ID_COUNT)
printf("Peripheral id %d out of range\n", id);
else {
switch (id) {
case PERIPH_ID_RESERVED1:
case PERIPH_ID_RESERVED2:
case PERIPH_ID_RESERVED30:
case PERIPH_ID_RESERVED35:
case PERIPH_ID_RESERVED56:
case PERIPH_ID_RESERVED74:
case PERIPH_ID_RESERVED76:
case PERIPH_ID_RESERVED77:
case PERIPH_ID_RESERVED78:
case PERIPH_ID_RESERVED79:
case PERIPH_ID_RESERVED80:
case PERIPH_ID_RESERVED81:
case PERIPH_ID_RESERVED82:
case PERIPH_ID_RESERVED83:
case PERIPH_ID_RESERVED91:
printf("Peripheral id %d is reserved\n", id);
break;
default:
return 1;
}
}
return 0;
}
/* Returns a pointer to the clock source register for a peripheral */
static u32 *get_periph_source_reg(enum periph_id periph_id)
u32 *get_periph_source_reg(enum periph_id periph_id)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
@ -535,154 +395,6 @@ static u32 *get_periph_source_reg(enum periph_id periph_id)
return &clkrst->crc_clk_src[internal_id];
}
void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
unsigned divisor)
{
u32 *reg = get_periph_source_reg(periph_id);
u32 value;
value = readl(reg);
value &= ~OUT_CLK_SOURCE_MASK;
value |= source << OUT_CLK_SOURCE_SHIFT;
value &= ~OUT_CLK_DIVISOR_MASK;
value |= divisor << OUT_CLK_DIVISOR_SHIFT;
writel(value, reg);
}
void clock_ll_set_source(enum periph_id periph_id, unsigned source)
{
u32 *reg = get_periph_source_reg(periph_id);
clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
source << OUT_CLK_SOURCE_SHIFT);
}
/**
* Given the parent's rate and the required rate for the children, this works
* out the peripheral clock divider to use, in 7.1 binary format.
*
* @param divider_bits number of divider bits (8 or 16)
* @param parent_rate clock rate of parent clock in Hz
* @param rate required clock rate for this clock
* @return divider which should be used
*/
static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
unsigned long rate)
{
u64 divider = parent_rate * 2;
unsigned max_divider = 1 << divider_bits;
divider += rate - 1;
do_div(divider, rate);
if ((s64)divider - 2 < 0)
return 0;
if ((s64)divider - 2 >= max_divider)
return -1;
return divider - 2;
}
/**
* Given the parent's rate and the divider in 7.1 format, this works out the
* resulting peripheral clock rate.
*
* @param parent_rate clock rate of parent clock in Hz
* @param divider which should be used in 7.1 format
* @return effective clock rate of peripheral
*/
static unsigned long get_rate_from_divider(unsigned long parent_rate,
int divider)
{
u64 rate;
rate = (u64)parent_rate * 2;
do_div(rate, divider + 2);
return rate;
}
unsigned long clock_get_periph_rate(enum periph_id periph_id,
enum clock_id parent)
{
u32 *reg = get_periph_source_reg(periph_id);
return get_rate_from_divider(pll_rate[parent],
(readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
}
int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout, unsigned rate)
{
struct clk_pll *pll = get_pll(clkid);
int data = 0, div = 0, offset = 0;
if (!clock_id_is_pll(clkid))
return -1;
if (pllout + 1 > pll_num_clkouts[clkid])
return -1;
div = clk_get_divider(8, pll_rate[clkid], rate);
if (div < 0)
return -1;
/* out2 and out4 are in the high part of the register */
if (pllout == PLL_OUT2 || pllout == PLL_OUT4)
offset = 16;
data = (div << PLL_OUT_RATIO_SHIFT) |
PLL_OUT_OVRRIDE | PLL_OUT_CLKEN | PLL_OUT_RSTN;
clrsetbits_le32(&pll->pll_out[pllout >> 1],
PLL_OUT_RATIO_MASK << offset, data << offset);
return 0;
}
/**
* Find the best available 7.1 format divisor given a parent clock rate and
* required child clock rate. This function assumes that a second-stage
* divisor is available which can divide by powers of 2 from 1 to 256.
*
* @param divider_bits number of divider bits (8 or 16)
* @param parent_rate clock rate of parent clock in Hz
* @param rate required clock rate for this clock
* @param extra_div value for the second-stage divisor (not set if this
* function returns -1.
* @return divider which should be used, or -1 if nothing is valid
*
*/
static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
unsigned long rate, int *extra_div)
{
int shift;
int best_divider = -1;
int best_error = rate;
/* try dividers from 1 to 256 and find closest match */
for (shift = 0; shift <= 8 && best_error > 0; shift++) {
unsigned divided_parent = parent_rate >> shift;
int divider = clk_get_divider(divider_bits, divided_parent,
rate);
unsigned effective_rate = get_rate_from_divider(divided_parent,
divider);
int error = rate - effective_rate;
/* Given a valid divider, look for the lowest error */
if (divider != -1 && error < best_error) {
best_error = error;
*extra_div = 1 << shift;
best_divider = divider;
}
}
/* return what we found - *extra_div will already be set */
return best_divider;
}
/**
* Given a peripheral ID and the required source clock, this returns which
* value should be programmed into the source mux for that peripheral.
@ -695,7 +407,7 @@ static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
* @param divider_bits Set to number of divider bits (8 or 16)
* @return mux value (0-4, or -1 if not found)
*/
static int get_periph_clock_source(enum periph_id periph_id,
int get_periph_clock_source(enum periph_id periph_id,
enum clock_id parent, int *mux_bits, int *divider_bits)
{
enum clock_type_id type;
@ -743,88 +455,6 @@ static int get_periph_clock_source(enum periph_id periph_id,
return -1;
}
/**
* Adjust peripheral PLL to use the given divider and source.
*
* @param periph_id peripheral to adjust
* @param source Source number (0-3 or 0-7)
* @param mux_bits Number of mux bits (2 or 4)
* @param divider Required divider in 7.1 or 15.1 format
* @return 0 if ok, -1 on error (requesting a parent clock which is not valid
* for this peripheral)
*/
static int adjust_periph_pll(enum periph_id periph_id, int source,
int mux_bits, unsigned divider)
{
u32 *reg = get_periph_source_reg(periph_id);
clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK,
divider << OUT_CLK_DIVISOR_SHIFT);
udelay(1);
/* work out the source clock and set it */
if (source < 0)
return -1;
if (mux_bits == 4) {
clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
source << OUT_CLK_SOURCE4_SHIFT);
} else {
clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
source << OUT_CLK_SOURCE_SHIFT);
}
udelay(2);
return 0;
}
unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
enum clock_id parent, unsigned rate, int *extra_div)
{
unsigned effective_rate;
int mux_bits, divider_bits, source;
int divider;
/* work out the source clock and set it */
source = get_periph_clock_source(periph_id, parent, &mux_bits,
&divider_bits);
if (extra_div)
divider = find_best_divider(divider_bits, pll_rate[parent],
rate, extra_div);
else
divider = clk_get_divider(divider_bits, pll_rate[parent],
rate);
assert(divider >= 0);
if (adjust_periph_pll(periph_id, source, mux_bits, divider))
return -1U;
debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
get_periph_source_reg(periph_id),
readl(get_periph_source_reg(periph_id)));
/* Check what we ended up with. This shouldn't matter though */
effective_rate = clock_get_periph_rate(periph_id, parent);
if (extra_div)
effective_rate /= *extra_div;
if (rate != effective_rate)
debug("Requested clock rate %u not honored (got %u)\n",
rate, effective_rate);
return effective_rate;
}
unsigned clock_start_periph_pll(enum periph_id periph_id,
enum clock_id parent, unsigned rate)
{
unsigned effective_rate;
reset_set_enable(periph_id, 1);
clock_enable(periph_id);
effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate,
NULL);
reset_set_enable(periph_id, 0);
return effective_rate;
}
void clock_set_enable(enum periph_id periph_id, int enable)
{
struct clk_rst_ctlr *clkrst =
@ -842,16 +472,6 @@ void clock_set_enable(enum periph_id periph_id, int enable)
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 =
@ -869,146 +489,6 @@ void reset_set_enable(enum periph_id periph_id, int enable)
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. Tegra20 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);
}
unsigned clock_get_rate(enum clock_id clkid)
{
struct clk_pll *pll;
u32 base;
u32 divm;
u64 parent_rate;
u64 rate;
parent_rate = osc_freq[clock_get_osc_freq()];
if (clkid == CLOCK_ID_OSC)
return parent_rate;
pll = get_pll(clkid);
base = readl(&pll->pll_base);
/* Oh for bf_unpack()... */
rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
if (clkid == CLOCK_ID_USB)
divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
else
divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
do_div(rate, divm);
return rate;
}
/**
* Set the output frequency you want for each PLL clock.
* PLL output frequencies are programmed by setting their N, M and P values.
* The governing equations are:
* VCO = (Fi / m) * n, Fo = VCO / (2^p)
* where Fo is the output frequency from the PLL.
* Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
* 216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
* Please see Tegra TRM section 5.3 to get the detail for PLL Programming
*
* @param n PLL feedback divider(DIVN)
* @param m PLL input divider(DIVN)
* @param p post divider(DIVP)
* @param cpcon base PLL charge pump(CPCON)
* @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
* be overriden), 1 if PLL is already correct
*/
static int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
{
u32 base_reg;
u32 misc_reg;
struct clk_pll *pll;
pll = get_pll(clkid);
base_reg = readl(&pll->pll_base);
/* Set BYPASS, m, n and p to PLL_BASE */
base_reg &= ~PLL_DIVM_MASK;
base_reg |= m << PLL_DIVM_SHIFT;
base_reg &= ~PLL_DIVN_MASK;
base_reg |= n << PLL_DIVN_SHIFT;
base_reg &= ~PLL_DIVP_MASK;
base_reg |= p << PLL_DIVP_SHIFT;
if (clkid == CLOCK_ID_PERIPH) {
/*
* If the PLL is already set up, check that it is correct
* and record this info for clock_verify() to check.
*/
if (base_reg & PLL_BASE_OVRRIDE_MASK) {
base_reg |= PLL_ENABLE_MASK;
if (base_reg != readl(&pll->pll_base))
pllp_valid = 0;
return pllp_valid ? 1 : -1;
}
base_reg |= PLL_BASE_OVRRIDE_MASK;
}
base_reg |= PLL_BYPASS_MASK;
writel(base_reg, &pll->pll_base);
/* Set cpcon to PLL_MISC */
misc_reg = readl(&pll->pll_misc);
misc_reg &= ~PLL_CPCON_MASK;
misc_reg |= cpcon << PLL_CPCON_SHIFT;
writel(misc_reg, &pll->pll_misc);
/* Enable PLL */
base_reg |= PLL_ENABLE_MASK;
writel(base_reg, &pll->pll_base);
/* Disable BYPASS */
base_reg &= ~PLL_BYPASS_MASK;
writel(base_reg, &pll->pll_base);
return 0;
}
void clock_ll_start_uart(enum periph_id periph_id)
{
/* Assert UART reset and enable clock */
reset_set_enable(periph_id, 1);
clock_enable(periph_id);
clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
/* wait for 2us */
udelay(2);
/* De-assert reset to UART */
reset_set_enable(periph_id, 0);
}
#ifdef CONFIG_OF_CONTROL
/*
* Convert a device tree clock ID to our peripheral ID. They are mostly
@ -1018,67 +498,34 @@ void clock_ll_start_uart(enum periph_id periph_id)
* @param clk_id Clock ID according to tegra20 device tree binding
* @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
*/
static enum periph_id clk_id_to_periph_id(int clk_id)
enum periph_id clk_id_to_periph_id(int clk_id)
{
if (clk_id > 95)
if (clk_id > PERIPH_ID_COUNT)
return PERIPH_ID_NONE;
switch (clk_id) {
case 1:
case 2:
case 7:
case 10:
case 20:
case 30:
case 35:
case 49:
case 56:
case 74:
case 76:
case 77:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 91:
case 95:
case PERIPH_ID_RESERVED1:
case PERIPH_ID_RESERVED2:
case PERIPH_ID_RESERVED30:
case PERIPH_ID_RESERVED35:
case PERIPH_ID_RESERVED56:
case PERIPH_ID_RESERVED74:
case PERIPH_ID_RESERVED76:
case PERIPH_ID_RESERVED77:
case PERIPH_ID_RESERVED78:
case PERIPH_ID_RESERVED79:
case PERIPH_ID_RESERVED80:
case PERIPH_ID_RESERVED81:
case PERIPH_ID_RESERVED82:
case PERIPH_ID_RESERVED83:
case PERIPH_ID_RESERVED91:
return PERIPH_ID_NONE;
default:
return clk_id;
}
}
int clock_decode_periph_id(const void *blob, int node)
{
enum periph_id id;
u32 cell[2];
int err;
err = fdtdec_get_int_array(blob, node, "clocks", cell,
ARRAY_SIZE(cell));
if (err)
return -1;
id = clk_id_to_periph_id(cell[1]);
assert(clock_periph_id_isvalid(id));
return id;
}
#endif /* CONFIG_OF_CONTROL */
int clock_verify(void)
{
struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH);
u32 reg = readl(&pll->pll_base);
if (!pllp_valid) {
printf("Warning: PLLP %x is not correct\n", reg);
return -1;
}
debug("PLLX %x is correct\n", reg);
return 0;
}
void clock_early_init(void)
{
/*
@ -1112,15 +559,3 @@ void clock_early_init(void)
break;
}
}
void clock_init(void)
{
pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY);
pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH);
pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL);
pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
}

View file

@ -98,8 +98,8 @@ int funcmux_select(enum periph_id id, int config)
break;
case PERIPH_ID_UART2:
if (config == FUNCMUX_UART2_IRDA) {
pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
if (config == FUNCMUX_UART2_UAD) {
pinmux_set_func(PINGRP_UAD, PMUX_FUNC_UARTB);
pinmux_tristate_disable(PINGRP_UAD);
}
break;

View file

@ -390,7 +390,7 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
PIN(UAA, BB, SPI3, MIPI_HS, UARTA, ULPI, MIPI_HS),
PIN(UAB, BB, SPI2, MIPI_HS, UARTA, ULPI, MIPI_HS),
PIN(UAC, BB, OWR, RSVD, RSVD, RSVD, RSVD4),
PIN(UAD, UART, IRDA, SPDIF, UARTA, SPI4, SPDIF),
PIN(UAD, UART, UARTB, SPDIF, UARTA, SPI4, SPDIF),
PIN(UCA, UART, UARTC, RSVD, GMI, RSVD, RSVD4),
PIN(UCB, UART, UARTC, PWM, GMI, RSVD, RSVD4),

View file

@ -46,7 +46,7 @@ DECLARE_GLOBAL_DATA_PTR;
* This is the place in SRAM where the SDRAM parameters are stored. There
* are 4 blocks, one for each RAM code
*/
#define SDRAM_PARAMS_BASE (AP20_BASE_PA_SRAM + 0x188)
#define SDRAM_PARAMS_BASE (NV_PA_BASE_SRAM + 0x188)
/* TODO: If we later add support for the Misc GP controller, refactor this */
union xm2cfga_reg {

View file

@ -0,0 +1,44 @@
#
# Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
#
# (C) Copyright 2000-2008
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
#
include $(TOPDIR)/config.mk
# The AVP is ARMv4T architecture so we must use special compiler
# flags for any startup files it might use.
LIB = $(obj)lib$(SOC)-common.o
COBJS-y += clock.o funcmux.o pinmux.o
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,618 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra30 Clock control functions */
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/timer.h>
#include <div64.h>
#include <fdtdec.h>
/*
* Clock types that we can use as a source. The Tegra30 has muxes for the
* peripheral clocks, and in most cases there are four options for the clock
* source. This gives us a clock 'type' and exploits what commonality exists
* in the device.
*
* Letters are obvious, except for T which means CLK_M, and S which means the
* clock derived from 32KHz. Beware that CLK_M (also called OSC in the
* datasheet) and PLL_M are different things. The former is the basic
* clock supplied to the SOC from an external oscillator. The latter is the
* memory clock PLL.
*
* See definitions in clock_id in the header file.
*/
enum clock_type_id {
CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */
CLOCK_TYPE_MCPA, /* and so on */
CLOCK_TYPE_MCPT,
CLOCK_TYPE_PCM,
CLOCK_TYPE_PCMT,
CLOCK_TYPE_PCMT16,
CLOCK_TYPE_PDCT,
CLOCK_TYPE_ACPT,
CLOCK_TYPE_ASPTE,
CLOCK_TYPE_PMDACD2T,
CLOCK_TYPE_PCST,
CLOCK_TYPE_COUNT,
CLOCK_TYPE_NONE = -1, /* invalid clock type */
};
enum {
CLOCK_MAX_MUX = 8 /* number of source options for each clock */
};
enum {
MASK_BITS_31_30 = 2, /* num of bits used to specify clock source */
MASK_BITS_31_29,
MASK_BITS_29_28,
};
/*
* Clock source mux for each clock type. This just converts our enum into
* a list of mux sources for use by the code.
*
* Note:
* The extra column in each clock source array is used to store the mask
* bits in its register for the source.
*/
#define CLK(x) CLOCK_ID_ ## x
static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = {
{ CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(AUDIO), CLK(CGENERAL), CLK(PERIPH), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_30},
{ CLK(AUDIO), CLK(SFROM32KHZ), CLK(PERIPH), CLK(OSC),
CLK(EPCI), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_31_29},
{ CLK(PERIPH), CLK(MEMORY), CLK(DISPLAY), CLK(AUDIO),
CLK(CGENERAL), CLK(DISPLAY2), CLK(OSC), CLK(NONE),
MASK_BITS_31_29},
{ CLK(PERIPH), CLK(CGENERAL), CLK(SFROM32KHZ), CLK(OSC),
CLK(NONE), CLK(NONE), CLK(NONE), CLK(NONE),
MASK_BITS_29_28}
};
/*
* Clock type for each peripheral clock source. We put the name in each
* record just so it is easy to match things up
*/
#define TYPE(name, type) type
static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
/* 0x00 */
TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM),
TYPE(PERIPHC_PWM, CLOCK_TYPE_PCST), /* only PWM uses b29:28 */
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SBC2, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_SBC3, CLOCK_TYPE_PCMT),
/* 0x08 */
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_DVC_I2C, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SBC1, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_DISP1, CLOCK_TYPE_PMDACD2T),
TYPE(PERIPHC_DISP2, CLOCK_TYPE_PMDACD2T),
/* 0x10 */
TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA),
/* 0x18 */
TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT), /* MIPI base-band HSI */
TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT),
/* 0x20 */
TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT),
TYPE(PERIPHC_HDMI, CLOCK_TYPE_PMDACD2T),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT),
TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT),
/* 0x28 */
TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SBC4, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT),
/* 0x30 */
TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_I2S0, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
/* 0x38h */ /* Jumps to reg offset 0x3B0h - new for T30 */
TYPE(PERIPHC_G3D2, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_MSELECT, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCST), /* s/b PCTS */
TYPE(PERIPHC_I2S3, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_I2S4, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_I2C4, CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_SBC5, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_SBC6, CLOCK_TYPE_PCMT),
/* 0x40 */
TYPE(PERIPHC_AUDIO, CLOCK_TYPE_ACPT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_DAM0, CLOCK_TYPE_ACPT),
TYPE(PERIPHC_DAM1, CLOCK_TYPE_ACPT),
TYPE(PERIPHC_DAM2, CLOCK_TYPE_ACPT),
TYPE(PERIPHC_HDA2CODEC2X, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_ACTMON, CLOCK_TYPE_PCST), /* MASK 31:30 */
TYPE(PERIPHC_EXTPERIPH1, CLOCK_TYPE_ASPTE),
/* 0x48 */
TYPE(PERIPHC_EXTPERIPH2, CLOCK_TYPE_ASPTE),
TYPE(PERIPHC_EXTPERIPH3, CLOCK_TYPE_ASPTE),
TYPE(PERIPHC_NANDSPEED, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_I2CSLOW, CLOCK_TYPE_PCST), /* MASK 31:30 */
TYPE(PERIPHC_SYS, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SPEEDO, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
/* 0x50 */
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE),
TYPE(PERIPHC_SATAOOB, CLOCK_TYPE_PCMT), /* offset 0x420h */
TYPE(PERIPHC_SATA, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_HDA, CLOCK_TYPE_PCMT),
};
/*
* This array translates a periph_id to a periphc_internal_id
*
* Not present/matched up:
* uint vi_sensor; _VI_SENSOR_0, 0x1A8
* SPDIF - which is both 0x08 and 0x0c
*
*/
#define NONE(name) (-1)
#define OFFSET(name, value) PERIPHC_ ## name
static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
/* Low word: 31:0 */
NONE(CPU),
NONE(COP),
NONE(TRIGSYS),
NONE(RESERVED3),
NONE(RESERVED4),
NONE(TMR),
PERIPHC_UART1,
PERIPHC_UART2, /* and vfir 0x68 */
/* 8 */
NONE(GPIO),
PERIPHC_SDMMC2,
NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */
PERIPHC_I2S1,
PERIPHC_I2C1,
PERIPHC_NDFLASH,
PERIPHC_SDMMC1,
PERIPHC_SDMMC4,
/* 16 */
NONE(RESERVED16),
PERIPHC_PWM,
PERIPHC_I2S2,
PERIPHC_EPP,
PERIPHC_VI,
PERIPHC_G2D,
NONE(USBD),
NONE(ISP),
/* 24 */
PERIPHC_G3D,
NONE(RESERVED25),
PERIPHC_DISP2,
PERIPHC_DISP1,
PERIPHC_HOST1X,
NONE(VCP),
PERIPHC_I2S0,
NONE(CACHE2),
/* Middle word: 63:32 */
NONE(MEM),
NONE(AHBDMA),
NONE(APBDMA),
NONE(RESERVED35),
NONE(RESERVED36),
NONE(STAT_MON),
NONE(RESERVED38),
NONE(RESERVED39),
/* 40 */
NONE(KFUSE),
PERIPHC_SBC1,
PERIPHC_NOR,
NONE(RESERVED43),
PERIPHC_SBC2,
NONE(RESERVED45),
PERIPHC_SBC3,
PERIPHC_DVC_I2C,
/* 48 */
NONE(DSI),
PERIPHC_TVO, /* also CVE 0x40 */
PERIPHC_MIPI,
PERIPHC_HDMI,
NONE(CSI),
PERIPHC_TVDAC,
PERIPHC_I2C2,
PERIPHC_UART3,
/* 56 */
NONE(RESERVED56),
PERIPHC_EMC,
NONE(USB2),
NONE(USB3),
PERIPHC_MPE,
PERIPHC_VDE,
NONE(BSEA),
NONE(BSEV),
/* Upper word 95:64 */
PERIPHC_SPEEDO,
PERIPHC_UART4,
PERIPHC_UART5,
PERIPHC_I2C3,
PERIPHC_SBC4,
PERIPHC_SDMMC3,
NONE(PCIE),
PERIPHC_OWR,
/* 72 */
NONE(AFI),
PERIPHC_CSITE,
NONE(PCIEXCLK),
NONE(AVPUCQ),
NONE(RESERVED76),
NONE(RESERVED77),
NONE(RESERVED78),
NONE(DTV),
/* 80 */
PERIPHC_NANDSPEED,
PERIPHC_I2CSLOW,
NONE(DSIB),
NONE(RESERVED83),
NONE(IRAMA),
NONE(IRAMB),
NONE(IRAMC),
NONE(IRAMD),
/* 88 */
NONE(CRAM2),
NONE(RESERVED89),
NONE(MDOUBLER),
NONE(RESERVED91),
NONE(SUSOUT),
NONE(RESERVED93),
NONE(RESERVED94),
NONE(RESERVED95),
/* V word: 31:0 */
NONE(CPUG),
NONE(CPULP),
PERIPHC_G3D2,
PERIPHC_MSELECT,
PERIPHC_TSENSOR,
PERIPHC_I2S3,
PERIPHC_I2S4,
PERIPHC_I2C4,
/* 08 */
PERIPHC_SBC5,
PERIPHC_SBC6,
PERIPHC_AUDIO,
NONE(APBIF),
PERIPHC_DAM0,
PERIPHC_DAM1,
PERIPHC_DAM2,
PERIPHC_HDA2CODEC2X,
/* 16 */
NONE(ATOMICS),
NONE(RESERVED17),
NONE(RESERVED18),
NONE(RESERVED19),
NONE(RESERVED20),
NONE(RESERVED21),
NONE(RESERVED22),
PERIPHC_ACTMON,
/* 24 */
NONE(RESERVED24),
NONE(RESERVED25),
NONE(RESERVED26),
NONE(RESERVED27),
PERIPHC_SATA,
PERIPHC_HDA,
NONE(RESERVED30),
NONE(RESERVED31),
/* W word: 31:0 */
NONE(HDA2HDMICODEC),
NONE(SATACOLD),
NONE(RESERVED0_PCIERX0),
NONE(RESERVED1_PCIERX1),
NONE(RESERVED2_PCIERX2),
NONE(RESERVED3_PCIERX3),
NONE(RESERVED4_PCIERX4),
NONE(RESERVED5_PCIERX5),
/* 40 */
NONE(CEC),
NONE(RESERVED6_PCIE2),
NONE(RESERVED7_EMC),
NONE(RESERVED8_HDMI),
NONE(RESERVED9_SATA),
NONE(RESERVED10_MIPI),
NONE(EX_RESERVED46),
NONE(EX_RESERVED47),
};
/*
* Get the oscillator frequency, from the corresponding hardware configuration
* field. Note that T30 supports 3 new higher freqs, but we map back
* to the old T20 freqs. Support for the higher oscillators is TBD.
*/
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);
reg = (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
if (reg & 1) /* one of the newer freqs */
printf("Warning: OSC_FREQ is unsupported! (%d)\n", reg);
return reg >> 2; /* Map to most common (T20) freqs */
}
/* Returns a pointer to the clock source register for a peripheral */
u32 *get_periph_source_reg(enum periph_id periph_id)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
enum periphc_internal_id internal_id;
/* Coresight is a special case */
if (periph_id == PERIPH_ID_CSI)
return &clkrst->crc_clk_src[PERIPH_ID_CSI+1];
assert(periph_id >= PERIPH_ID_FIRST && periph_id < PERIPH_ID_COUNT);
internal_id = periph_id_to_internal_id[periph_id];
assert(internal_id != -1);
if (internal_id >= PERIPHC_VW_FIRST) {
internal_id -= PERIPHC_VW_FIRST;
return &clkrst->crc_clk_src_vw[internal_id];
} else
return &clkrst->crc_clk_src[internal_id];
}
/**
* Given a peripheral ID and the required source clock, this returns which
* value should be programmed into the source mux for that peripheral.
*
* There is special code here to handle the one source type with 5 sources.
*
* @param periph_id peripheral to start
* @param source PLL id of required parent clock
* @param mux_bits Set to number of bits in mux register: 2 or 4
* @param divider_bits Set to number of divider bits (8 or 16)
* @return mux value (0-4, or -1 if not found)
*/
int get_periph_clock_source(enum periph_id periph_id,
enum clock_id parent, int *mux_bits, int *divider_bits)
{
enum clock_type_id type;
enum periphc_internal_id internal_id;
int mux;
assert(clock_periph_id_isvalid(periph_id));
internal_id = periph_id_to_internal_id[periph_id];
assert(periphc_internal_id_isvalid(internal_id));
type = clock_periph_type[internal_id];
assert(clock_type_id_isvalid(type));
*mux_bits = clock_source[type][CLOCK_MAX_MUX];
if (type == CLOCK_TYPE_PCMT16)
*divider_bits = 16;
else
*divider_bits = 8;
for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
if (clock_source[type][mux] == parent)
return mux;
/* if we get here, either us or the caller has made a mistake */
printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
parent);
return -1;
}
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;
u32 reg;
/* Enable/disable the clock to this peripheral */
assert(clock_periph_id_isvalid(periph_id));
if ((int)periph_id < (int)PERIPH_ID_VW_FIRST)
clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
else
clk = &clkrst->crc_clk_out_enb_vw[PERIPH_REG(periph_id)];
reg = readl(clk);
if (enable)
reg |= PERIPH_MASK(periph_id);
else
reg &= ~PERIPH_MASK(periph_id);
writel(reg, clk);
}
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;
u32 reg;
/* Enable/disable reset to the peripheral */
assert(clock_periph_id_isvalid(periph_id));
if (periph_id < PERIPH_ID_VW_FIRST)
reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
else
reset = &clkrst->crc_rst_dev_vw[PERIPH_REG(periph_id)];
reg = readl(reset);
if (enable)
reg |= PERIPH_MASK(periph_id);
else
reg &= ~PERIPH_MASK(periph_id);
writel(reg, reset);
}
#ifdef CONFIG_OF_CONTROL
/*
* Convert a device tree clock ID to our peripheral ID. They are mostly
* the same but we are very cautious so we check that a valid clock ID is
* provided.
*
* @param clk_id Clock ID according to tegra30 device tree binding
* @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
*/
enum periph_id clk_id_to_periph_id(int clk_id)
{
if (clk_id > PERIPH_ID_COUNT)
return PERIPH_ID_NONE;
switch (clk_id) {
case PERIPH_ID_RESERVED3:
case PERIPH_ID_RESERVED4:
case PERIPH_ID_RESERVED16:
case PERIPH_ID_RESERVED24:
case PERIPH_ID_RESERVED35:
case PERIPH_ID_RESERVED43:
case PERIPH_ID_RESERVED45:
case PERIPH_ID_RESERVED56:
case PERIPH_ID_RESERVED76:
case PERIPH_ID_RESERVED77:
case PERIPH_ID_RESERVED78:
case PERIPH_ID_RESERVED83:
case PERIPH_ID_RESERVED89:
case PERIPH_ID_RESERVED91:
case PERIPH_ID_RESERVED93:
case PERIPH_ID_RESERVED94:
case PERIPH_ID_RESERVED95:
return PERIPH_ID_NONE;
default:
return clk_id;
}
}
#endif /* CONFIG_OF_CONTROL */
void clock_early_init(void)
{
/*
* PLLP output frequency set to 408Mhz
* PLLC output frequency set to 228Mhz
*/
switch (clock_get_osc_freq()) {
case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
clock_set_rate(CLOCK_ID_PERIPH, 408, 12, 0, 8);
clock_set_rate(CLOCK_ID_CGENERAL, 456, 12, 1, 8);
break;
case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
clock_set_rate(CLOCK_ID_PERIPH, 408, 26, 0, 8);
clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
break;
case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
clock_set_rate(CLOCK_ID_PERIPH, 408, 13, 0, 8);
clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
break;
case CLOCK_OSC_FREQ_19_2:
default:
/*
* These are not supported. It is too early to print a
* message and the UART likely won't work anyway due to the
* oscillator being wrong.
*/
break;
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra30 high-level function multiplexing */
#include <common.h>
#include <asm/arch/clock.h>
#include <asm/arch/funcmux.h>
#include <asm/arch/pinmux.h>
int funcmux_select(enum periph_id id, int config)
{
int bad_config = config != FUNCMUX_DEFAULT;
switch (id) {
case PERIPH_ID_UART1:
switch (config) {
case FUNCMUX_UART1_ULPI:
pinmux_set_func(PINGRP_ULPI_DATA0, PMUX_FUNC_UARTA);
pinmux_set_func(PINGRP_ULPI_DATA1, PMUX_FUNC_UARTA);
pinmux_set_func(PINGRP_ULPI_DATA2, PMUX_FUNC_UARTA);
pinmux_set_func(PINGRP_ULPI_DATA3, PMUX_FUNC_UARTA);
pinmux_tristate_disable(PINGRP_ULPI_DATA0);
pinmux_tristate_disable(PINGRP_ULPI_DATA1);
pinmux_tristate_disable(PINGRP_ULPI_DATA2);
pinmux_tristate_disable(PINGRP_ULPI_DATA3);
break;
}
break;
/* Add other periph IDs here as needed */
default:
debug("%s: invalid periph_id %d", __func__, id);
return -1;
}
if (bad_config) {
debug("%s: invalid config %d for periph_id %d", __func__,
config, id);
return -1;
}
return 0;
}

View file

@ -0,0 +1,506 @@
/*
* Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra30 pin multiplexing functions */
#include <common.h>
#include <asm/io.h>
#include <asm/arch/tegra.h>
#include <asm/arch/pinmux.h>
struct tegra_pingroup_desc {
const char *name;
enum pmux_func funcs[4];
enum pmux_func func_safe;
enum pmux_vddio vddio;
enum pmux_pin_io io;
};
#define PMUX_MUXCTL_SHIFT 0
#define PMUX_PULL_SHIFT 2
#define PMUX_TRISTATE_SHIFT 4
#define PMUX_TRISTATE_MASK (1 << PMUX_TRISTATE_SHIFT)
#define PMUX_IO_SHIFT 5
#define PMUX_OD_SHIFT 6
#define PMUX_LOCK_SHIFT 7
#define PMUX_IO_RESET_SHIFT 8
/* Convenient macro for defining pin group properties */
#define PIN(pg_name, vdd, f0, f1, f2, f3, iod) \
{ \
.vddio = PMUX_VDDIO_ ## vdd, \
.funcs = { \
PMUX_FUNC_ ## f0, \
PMUX_FUNC_ ## f1, \
PMUX_FUNC_ ## f2, \
PMUX_FUNC_ ## f3, \
}, \
.func_safe = PMUX_FUNC_RSVD1, \
.io = PMUX_PIN_ ## iod, \
}
/* Input and output pins */
#define PINI(pg_name, vdd, f0, f1, f2, f3) \
PIN(pg_name, vdd, f0, f1, f2, f3, INPUT)
#define PINO(pg_name, vdd, f0, f1, f2, f3) \
PIN(pg_name, vdd, f0, f1, f2, f3, OUTPUT)
const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
/* NAME VDD f0 f1 f2 f3 */
PINI(ULPI_DATA0, BB, SPI3, HSI, UARTA, ULPI),
PINI(ULPI_DATA1, BB, SPI3, HSI, UARTA, ULPI),
PINI(ULPI_DATA2, BB, SPI3, HSI, UARTA, ULPI),
PINI(ULPI_DATA3, BB, SPI3, HSI, UARTA, ULPI),
PINI(ULPI_DATA4, BB, SPI2, HSI, UARTA, ULPI),
PINI(ULPI_DATA5, BB, SPI2, HSI, UARTA, ULPI),
PINI(ULPI_DATA6, BB, SPI2, HSI, UARTA, ULPI),
PINI(ULPI_DATA7, BB, SPI2, HSI, UARTA, ULPI),
PINI(ULPI_CLK, BB, SPI1, RSVD2, UARTD, ULPI),
PINI(ULPI_DIR, BB, SPI1, RSVD2, UARTD, ULPI),
PINI(ULPI_NXT, BB, SPI1, RSVD2, UARTD, ULPI),
PINI(ULPI_STP, BB, SPI1, RSVD2, UARTD, ULPI),
PINI(DAP3_FS, BB, I2S2, RSVD2, DISPA, DISPB),
PINI(DAP3_DIN, BB, I2S2, RSVD2, DISPA, DISPB),
PINI(DAP3_DOUT, BB, I2S2, RSVD2, DISPA, DISPB),
PINI(DAP3_SCLK, BB, I2S2, RSVD2, DISPA, DISPB),
PINI(GPIO_PV0, BB, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(GPIO_PV1, BB, RSVD1, RSVD2, RSVD3, RSVD4),
PINI(SDMMC1_CLK, SDMMC1, SDMMC1, RSVD2, RSVD3, UARTA),
PINI(SDMMC1_CMD, SDMMC1, SDMMC1, RSVD2, RSVD3, UARTA),
PINI(SDMMC1_DAT3, SDMMC1, SDMMC1, RSVD2, UARTE, UARTA),
PINI(SDMMC1_DAT2, SDMMC1, SDMMC1, RSVD2, UARTE, UARTA),
PINI(SDMMC1_DAT1, SDMMC1, SDMMC1, RSVD2, UARTE, UARTA),
PINI(SDMMC1_DAT0, SDMMC1, SDMMC1, RSVD2, UARTE, UARTA),
PINI(GPIO_PV2, SDMMC1, OWR, RSVD2, RSVD3, RSVD4),
PINI(GPIO_PV3, SDMMC1, CLK_12M_OUT, RSVD2, RSVD3, RSVD4),
PINI(CLK2_OUT, SDMMC1, EXTPERIPH2, RSVD2, RSVD3, RSVD4),
PINI(CLK2_REQ, SDMMC1, DAP, RSVD2, RSVD3, RSVD4),
PINO(LCD_PWR1, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_PWR2, LCD, DISPA, DISPB, SPI5, HDCP),
PINO(LCD_SDIN, LCD, DISPA, DISPB, SPI5, RSVD4),
PINO(LCD_SDOUT, LCD, DISPA, DISPB, SPI5, HDCP),
PINO(LCD_WR_N, LCD, DISPA, DISPB, SPI5, HDCP),
PINO(LCD_CS0_N, LCD, DISPA, DISPB, SPI5, RSVD4),
PINO(LCD_DC0, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_SCK, LCD, DISPA, DISPB, SPI5, HDCP),
PINO(LCD_PWR0, LCD, DISPA, DISPB, SPI5, HDCP),
PINO(LCD_PCLK, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_DE, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_HSYNC, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_VSYNC, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D0, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D1, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D2, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D3, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D4, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D5, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D6, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D7, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D8, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D9, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D10, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D11, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D12, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D13, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D14, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D15, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D16, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D17, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D18, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D19, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D20, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D21, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D22, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_D23, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_CS1_N, LCD, DISPA, DISPB, SPI5, RSVD4),
PINO(LCD_M1, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINO(LCD_DC1, LCD, DISPA, DISPB, RSVD3, RSVD4),
PINI(HDMI_INT, LCD, HDMI, RSVD2, RSVD3, RSVD4),
PINI(DDC_SCL, LCD, I2C4, RSVD2, RSVD3, RSVD4),
PINI(DDC_SDA, LCD, I2C4, RSVD2, RSVD3, RSVD4),
PINI(CRT_HSYNC, LCD, CRT, RSVD2, RSVD3, RSVD4),
PINI(CRT_VSYNC, LCD, CRT, RSVD2, RSVD3, RSVD4),
PINI(VI_D0, VI, DDR, RSVD2, VI, RSVD4),
PINI(VI_D1, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D2, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D3, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D4, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D5, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D6, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D7, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D8, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D9, VI, DDR, SDMMC2, VI, RSVD4),
PINI(VI_D10, VI, DDR, RSVD2, VI, RSVD4),
PINI(VI_D11, VI, DDR, RSVD2, VI, RSVD4),
PINI(VI_PCLK, VI, RSVD1, SDMMC2, VI, RSVD4),
PINI(VI_MCLK, VI, VI, VI, VI, VI),
PINI(VI_VSYNC, VI, DDR, RSVD2, VI, RSVD4),
PINI(VI_HSYNC, VI, DDR, RSVD2, VI, RSVD4),
PINI(UART2_RXD, UART, UARTB, SPDIF, UARTA, SPI4),
PINI(UART2_TXD, UART, UARTB, SPDIF, UARTA, SPI4),
PINI(UART2_RTS_N, UART, UARTA, UARTB, GMI, SPI4),
PINI(UART2_CTS_N, UART, UARTA, UARTB, GMI, SPI4),
PINI(UART3_TXD, UART, UARTC, RSVD2, GMI, RSVD4),
PINI(UART3_RXD, UART, UARTC, RSVD2, GMI, RSVD4),
PINI(UART3_CTS_N, UART, UARTC, RSVD2, GMI, RSVD4),
PINI(UART3_RTS_N, UART, UARTC, PWM0, GMI, RSVD4),
PINI(GPIO_PU0, UART, OWR, UARTA, GMI, RSVD4),
PINI(GPIO_PU1, UART, RSVD1, UARTA, GMI, RSVD4),
PINI(GPIO_PU2, UART, RSVD1, UARTA, GMI, RSVD4),
PINI(GPIO_PU3, UART, PWM0, UARTA, GMI, RSVD4),
PINI(GPIO_PU4, UART, PWM1, UARTA, GMI, RSVD4),
PINI(GPIO_PU5, UART, PWM2, UARTA, GMI, RSVD4),
PINI(GPIO_PU6, UART, PWM3, UARTA, GMI, RSVD4),
PINI(GEN1_I2C_SDA, UART, I2C1, RSVD2, RSVD3, RSVD4),
PINI(GEN1_I2C_SCL, UART, I2C1, RSVD2, RSVD3, RSVD4),
PINI(DAP4_FS, UART, I2S3, RSVD2, GMI, RSVD4),
PINI(DAP4_DIN, UART, I2S3, RSVD2, GMI, RSVD4),
PINI(DAP4_DOUT, UART, I2S3, RSVD2, GMI, RSVD4),
PINI(DAP4_SCLK, UART, I2S3, RSVD2, GMI, RSVD4),
PINI(CLK3_OUT, UART, EXTPERIPH3, RSVD2, RSVD3, RSVD4),
PINI(CLK3_REQ, UART, DEV3, RSVD2, RSVD3, RSVD4),
PINI(GMI_WP_N, GMI, RSVD1, NAND, GMI, GMI_ALT),
PINI(GMI_IORDY, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_WAIT, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_ADV_N, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_CLK, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_CS0_N, GMI, RSVD1, NAND, GMI, DTV),
PINI(GMI_CS1_N, GMI, RSVD1, NAND, GMI, DTV),
PINI(GMI_CS2_N, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_CS3_N, GMI, RSVD1, NAND, GMI, GMI_ALT),
PINI(GMI_CS4_N, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_CS6_N, GMI, NAND, NAND_ALT, GMI, SATA),
PINI(GMI_CS7_N, GMI, NAND, NAND_ALT, GMI, GMI_ALT),
PINI(GMI_AD0, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD1, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD2, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD3, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD4, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD5, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD6, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD7, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD8, GMI, PWM0, NAND, GMI, RSVD4),
PINI(GMI_AD9, GMI, PWM1, NAND, GMI, RSVD4),
PINI(GMI_AD10, GMI, PWM2, NAND, GMI, RSVD4),
PINI(GMI_AD11, GMI, PWM3, NAND, GMI, RSVD4),
PINI(GMI_AD12, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD13, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD14, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_AD15, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_A16, GMI, UARTD, SPI4, GMI, GMI_ALT),
PINI(GMI_A17, GMI, UARTD, SPI4, GMI, DTV),
PINI(GMI_A18, GMI, UARTD, SPI4, GMI, DTV),
PINI(GMI_A19, GMI, UARTD, SPI4, GMI, RSVD4),
PINI(GMI_WR_N, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_OE_N, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_DQS, GMI, RSVD1, NAND, GMI, RSVD4),
PINI(GMI_RST_N, GMI, NAND, NAND_ALT, GMI, RSVD4),
PINI(GEN2_I2C_SCL, GMI, I2C2, HDCP, GMI, RSVD4),
PINI(GEN2_I2C_SDA, GMI, I2C2, HDCP, GMI, RSVD4),
PINI(SDMMC4_CLK, SDMMC4, RSVD1, NAND, GMI, SDMMC4),
PINI(SDMMC4_CMD, SDMMC4, I2C3, NAND, GMI, SDMMC4),
PINI(SDMMC4_DAT0, SDMMC4, UARTE, SPI3, GMI, SDMMC4),
PINI(SDMMC4_DAT1, SDMMC4, UARTE, SPI3, GMI, SDMMC4),
PINI(SDMMC4_DAT2, SDMMC4, UARTE, SPI3, GMI, SDMMC4),
PINI(SDMMC4_DAT3, SDMMC4, UARTE, SPI3, GMI, SDMMC4),
PINI(SDMMC4_DAT4, SDMMC4, I2C3, I2S4, GMI, SDMMC4),
PINI(SDMMC4_DAT5, SDMMC4, VGP3, I2S4, GMI, SDMMC4),
PINI(SDMMC4_DAT6, SDMMC4, VGP4, I2S4, GMI, SDMMC4),
PINI(SDMMC4_DAT7, SDMMC4, VGP5, I2S4, GMI, SDMMC4),
PINI(SDMMC4_RST_N, SDMMC4, VGP6, RSVD2, RSVD3, SDMMC4),
PINI(CAM_MCLK, CAM, VI, RSVD2, VI_ALT2, SDMMC4),
PINI(GPIO_PCC1, CAM, I2S4, RSVD2, RSVD3, SDMMC4),
PINI(GPIO_PBB0, CAM, I2S4, RSVD2, RSVD3, SDMMC4),
PINI(CAM_I2C_SCL, CAM, VGP1, I2C3, RSVD3, SDMMC4),
PINI(CAM_I2C_SDA, CAM, VGP2, I2C3, RSVD3, SDMMC4),
PINI(GPIO_PBB3, CAM, VGP3, DISPA, DISPB, SDMMC4),
PINI(GPIO_PBB4, CAM, VGP4, DISPA, DISPB, SDMMC4),
PINI(GPIO_PBB5, CAM, VGP5, DISPA, DISPB, SDMMC4),
PINI(GPIO_PBB6, CAM, VGP6, DISPA, DISPB, SDMMC4),
PINI(GPIO_PBB7, CAM, I2S4, RSVD2, RSVD3, SDMMC4),
PINI(GPIO_PCC2, CAM, I2S4, RSVD2, RSVD3, RSVD4),
PINI(JTAG_RTCK, SYS, RTCK, RSVD2, RSVD3, RSVD4),
PINI(PWR_I2C_SCL, SYS, I2CPWR, RSVD2, RSVD3, RSVD4),
PINI(PWR_I2C_SDA, SYS, I2CPWR, RSVD2, RSVD3, RSVD4),
PINI(KB_ROW0, SYS, KBC, NAND, RSVD3, RSVD4),
PINI(KB_ROW1, SYS, KBC, NAND, RSVD3, RSVD4),
PINI(KB_ROW2, SYS, KBC, NAND, RSVD3, RSVD4),
PINI(KB_ROW3, SYS, KBC, NAND, RSVD3, RSVD4),
PINI(KB_ROW4, SYS, KBC, NAND, TRACE, RSVD4),
PINI(KB_ROW5, SYS, KBC, NAND, TRACE, OWR),
PINI(KB_ROW6, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW7, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW8, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW9, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW10, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW11, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW12, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW13, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW14, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_ROW15, SYS, KBC, NAND, SDMMC2, MIO),
PINI(KB_COL0, SYS, KBC, NAND, TRACE, TEST),
PINI(KB_COL1, SYS, KBC, NAND, TRACE, TEST),
PINI(KB_COL2, SYS, KBC, NAND, TRACE, RSVD4),
PINI(KB_COL3, SYS, KBC, NAND, TRACE, RSVD4),
PINI(KB_COL4, SYS, KBC, NAND, TRACE, RSVD4),
PINI(KB_COL5, SYS, KBC, NAND, TRACE, RSVD4),
PINI(KB_COL6, SYS, KBC, NAND, TRACE, MIO),
PINI(KB_COL7, SYS, KBC, NAND, TRACE, MIO),
PINI(CLK_32K_OUT, SYS, BLINK, RSVD2, RSVD3, RSVD4),
PINI(SYS_CLK_REQ, SYS, SYSCLK, RSVD2, RSVD3, RSVD4),
PINI(CORE_PWR_REQ, SYS, CORE_PWR_REQ, RSVD2, RSVD3, RSVD4),
PINI(CPU_PWR_REQ, SYS, CPU_PWR_REQ, RSVD2, RSVD3, RSVD4),
PINI(PWR_INT_N, SYS, PWR_INT_N, RSVD2, RSVD3, RSVD4),
PINI(CLK_32K_IN, SYS, CLK_32K_IN, RSVD2, RSVD3, RSVD4),
PINI(OWR, SYS, OWR, CEC, RSVD3, RSVD4),
PINI(DAP1_FS, AUDIO, I2S0, HDA, GMI, SDMMC2),
PINI(DAP1_DIN, AUDIO, I2S0, HDA, GMI, SDMMC2),
PINI(DAP1_DOUT, AUDIO, I2S0, HDA, GMI, SDMMC2),
PINI(DAP1_SCLK, AUDIO, I2S0, HDA, GMI, SDMMC2),
PINI(CLK1_REQ, AUDIO, DAP, HDA, RSVD3, RSVD4),
PINI(CLK1_OUT, AUDIO, EXTPERIPH1, RSVD2, RSVD3, RSVD4),
PINI(SPDIF_IN, AUDIO, SPDIF, HDA, I2C1, SDMMC2),
PINI(SPDIF_OUT, AUDIO, SPDIF, RSVD2, I2C1, SDMMC2),
PINI(DAP2_FS, AUDIO, I2S1, HDA, RSVD3, GMI),
PINI(DAP2_DIN, AUDIO, I2S1, HDA, RSVD3, GMI),
PINI(DAP2_DOUT, AUDIO, I2S1, HDA, RSVD3, GMI),
PINI(DAP2_SCLK, AUDIO, I2S1, HDA, RSVD3, GMI),
PINI(SPI2_MOSI, AUDIO, SPI6, SPI2, GMI, GMI),
PINI(SPI2_MISO, AUDIO, SPI6, SPI2, GMI, GMI),
PINI(SPI2_CS0_N, AUDIO, SPI6, SPI2, GMI, GMI),
PINI(SPI2_SCK, AUDIO, SPI6, SPI2, GMI, GMI),
PINI(SPI1_MOSI, AUDIO, SPI2, SPI1, SPI2_ALT, GMI),
PINI(SPI1_SCK, AUDIO, SPI2, SPI1, SPI2_ALT, GMI),
PINI(SPI1_CS0_N, AUDIO, SPI2, SPI1, SPI2_ALT, GMI),
PINI(SPI1_MISO, AUDIO, SPI3, SPI1, SPI2_ALT, RSVD4),
PINI(SPI2_CS1_N, AUDIO, SPI3, SPI2, SPI2_ALT, I2C1),
PINI(SPI2_CS2_N, AUDIO, SPI3, SPI2, SPI2_ALT, I2C1),
PINI(SDMMC3_CLK, SDMMC3, UARTA, PWM2, SDMMC3, SPI3),
PINI(SDMMC3_CMD, SDMMC3, UARTA, PWM3, SDMMC3, SPI2),
PINI(SDMMC3_DAT0, SDMMC3, RSVD1, RSVD2, SDMMC3, SPI3),
PINI(SDMMC3_DAT1, SDMMC3, RSVD1, RSVD2, SDMMC3, SPI3),
PINI(SDMMC3_DAT2, SDMMC3, RSVD1, PWM1, SDMMC3, SPI3),
PINI(SDMMC3_DAT3, SDMMC3, RSVD1, PWM0, SDMMC3, SPI3),
PINI(SDMMC3_DAT4, SDMMC3, PWM1, SPI4, SDMMC3, SPI2),
PINI(SDMMC3_DAT5, SDMMC3, PWM0, SPI4, SDMMC3, SPI2),
PINI(SDMMC3_DAT6, SDMMC3, SPDIF, SPI4, SDMMC3, SPI2),
PINI(SDMMC3_DAT7, SDMMC3, SPDIF, SPI4, SDMMC3, SPI2),
PINI(PEX_L0_PRSNT_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_L0_RST_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_L0_CLKREQ_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_WAKE_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_L1_PRSNT_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_L1_RST_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_L1_CLKREQ_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_L2_PRSNT_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_L2_RST_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(PEX_L2_CLKREQ_N, PEXCTL, PCIE, HDA, RSVD3, RSVD4),
PINI(HDMI_CEC, SYS, CEC, RSVD2, RSVD3, RSVD4),
};
void pinmux_set_tristate(enum pmux_pingrp pin, int enable)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *tri = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin */
assert(pmux_pingrp_isvalid(pin));
reg = readl(tri);
if (enable)
reg |= PMUX_TRISTATE_MASK;
else
reg &= ~PMUX_TRISTATE_MASK;
writel(reg, tri);
}
void pinmux_tristate_enable(enum pmux_pingrp pin)
{
pinmux_set_tristate(pin, 1);
}
void pinmux_tristate_disable(enum pmux_pingrp pin)
{
pinmux_set_tristate(pin, 0);
}
void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pull = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and pupd */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_pupd_isvalid(pupd));
reg = readl(pull);
reg &= ~(0x3 << PMUX_PULL_SHIFT);
reg |= (pupd << PMUX_PULL_SHIFT);
writel(reg, pull);
}
void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *muxctl = &pmt->pmt_ctl[pin];
int i, mux = -1;
u32 reg;
/* Error check on pin and func */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_func_isvalid(func));
/* Handle special values */
if (func == PMUX_FUNC_SAFE)
func = tegra_soc_pingroups[pin].func_safe;
if (func & PMUX_FUNC_RSVD1) {
mux = func & 0x3;
} else {
/* Search for the appropriate function */
for (i = 0; i < 4; i++) {
if (tegra_soc_pingroups[pin].funcs[i] == func) {
mux = i;
break;
}
}
}
assert(mux != -1);
reg = readl(muxctl);
reg &= ~(0x3 << PMUX_MUXCTL_SHIFT);
reg |= (mux << PMUX_MUXCTL_SHIFT);
writel(reg, muxctl);
}
void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pin_io = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and io */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_io_isvalid(io));
reg = readl(pin_io);
reg &= ~(0x1 << PMUX_IO_SHIFT);
reg |= (io & 0x1) << PMUX_IO_SHIFT;
writel(reg, pin_io);
}
static int pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pin_lock = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and lock */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_lock_isvalid(lock));
if (lock == PMUX_PIN_LOCK_DEFAULT)
return 0;
reg = readl(pin_lock);
reg &= ~(0x1 << PMUX_LOCK_SHIFT);
if (lock == PMUX_PIN_LOCK_ENABLE)
reg |= (0x1 << PMUX_LOCK_SHIFT);
else {
/* lock == DISABLE, which isn't possible */
printf("%s: Warning: lock == %d, DISABLE is not allowed!\n",
__func__, lock);
}
writel(reg, pin_lock);
return 0;
}
static int pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pin_od = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and od */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_od_isvalid(od));
if (od == PMUX_PIN_OD_DEFAULT)
return 0;
reg = readl(pin_od);
reg &= ~(0x1 << PMUX_OD_SHIFT);
if (od == PMUX_PIN_OD_ENABLE)
reg |= (0x1 << PMUX_OD_SHIFT);
writel(reg, pin_od);
return 0;
}
static int pinmux_set_ioreset(enum pmux_pingrp pin,
enum pmux_pin_ioreset ioreset)
{
struct pmux_tri_ctlr *pmt =
(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
u32 *pin_ioreset = &pmt->pmt_ctl[pin];
u32 reg;
/* Error check on pin and ioreset */
assert(pmux_pingrp_isvalid(pin));
assert(pmux_pin_ioreset_isvalid(ioreset));
if (ioreset == PMUX_PIN_IO_RESET_DEFAULT)
return 0;
reg = readl(pin_ioreset);
reg &= ~(0x1 << PMUX_IO_RESET_SHIFT);
if (ioreset == PMUX_PIN_IO_RESET_ENABLE)
reg |= (0x1 << PMUX_IO_RESET_SHIFT);
writel(reg, pin_ioreset);
return 0;
}
void pinmux_config_pingroup(struct pingroup_config *config)
{
enum pmux_pingrp pin = config->pingroup;
pinmux_set_func(pin, config->func);
pinmux_set_pullupdown(pin, config->pull);
pinmux_set_tristate(pin, config->tristate);
pinmux_set_io(pin, config->io);
pinmux_set_lock(pin, config->lock);
pinmux_set_od(pin, config->od);
pinmux_set_ioreset(pin, config->ioreset);
}
void pinmux_config_table(struct pingroup_config *config, int len)
{
int i;
for (i = 0; i < len; i++)
pinmux_config_pingroup(&config[i]);
}

View file

@ -0,0 +1,5 @@
/include/ "skeleton.dtsi"
/ {
compatible = "nvidia,tegra114";
};

View file

@ -4,220 +4,6 @@
compatible = "nvidia,tegra20";
interrupt-parent = <&intc>;
tegra_car: clock@60006000 {
compatible = "nvidia,tegra20-car";
reg = <0x60006000 0x1000>;
#clock-cells = <1>;
};
clocks {
#address-cells = <1>;
#size-cells = <0>;
osc: clock {
compatible = "fixed-clock";
#clock-cells = <0>;
};
};
intc: interrupt-controller@50041000 {
compatible = "nvidia,tegra20-gic";
interrupt-controller;
#interrupt-cells = <1>;
reg = < 0x50041000 0x1000 >,
< 0x50040100 0x0100 >;
};
i2c@7000c000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2c";
reg = <0x7000C000 0x100>;
interrupts = < 70 >;
/* PERIPH_ID_I2C1, PLL_P_OUT3 */
clocks = <&tegra_car 12>, <&tegra_car 124>;
};
i2c@7000c400 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2c";
reg = <0x7000C400 0x100>;
interrupts = < 116 >;
/* PERIPH_ID_I2C2, PLL_P_OUT3 */
clocks = <&tegra_car 54>, <&tegra_car 124>;
};
i2c@7000c500 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2c";
reg = <0x7000C500 0x100>;
interrupts = < 124 >;
/* PERIPH_ID_I2C3, PLL_P_OUT3 */
clocks = <&tegra_car 67>, <&tegra_car 124>;
};
i2c@7000d000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2c-dvc";
reg = <0x7000D000 0x200>;
interrupts = < 85 >;
/* PERIPH_ID_DVC_I2C, PLL_P_OUT3 */
clocks = <&tegra_car 47>, <&tegra_car 124>;
};
i2s@70002800 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2s";
reg = <0x70002800 0x200>;
interrupts = < 45 >;
dma-channel = < 2 >;
};
i2s@70002a00 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2s";
reg = <0x70002a00 0x200>;
interrupts = < 35 >;
dma-channel = < 1 >;
};
das@70000c00 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-das";
reg = <0x70000c00 0x80>;
};
gpio: gpio@6000d000 {
compatible = "nvidia,tegra20-gpio";
reg = < 0x6000d000 0x1000 >;
interrupts = < 64 65 66 67 87 119 121 >;
#gpio-cells = <2>;
gpio-controller;
};
pinmux: pinmux@70000000 {
compatible = "nvidia,tegra20-pinmux";
reg = < 0x70000014 0x10 /* Tri-state registers */
0x70000080 0x20 /* Mux registers */
0x700000a0 0x14 /* Pull-up/down registers */
0x70000868 0xa8 >; /* Pad control registers */
};
serial@70006000 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006000 0x40>;
reg-shift = <2>;
interrupts = < 68 >;
};
serial@70006040 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006040 0x40>;
reg-shift = <2>;
interrupts = < 69 >;
};
serial@70006200 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006200 0x100>;
reg-shift = <2>;
interrupts = < 78 >;
};
serial@70006300 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006300 0x100>;
reg-shift = <2>;
interrupts = < 122 >;
};
serial@70006400 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006400 0x100>;
reg-shift = <2>;
interrupts = < 123 >;
};
sdhci@c8000000 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000000 0x200>;
interrupts = < 46 >;
};
sdhci@c8000200 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000200 0x200>;
interrupts = < 47 >;
};
sdhci@c8000400 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000400 0x200>;
interrupts = < 51 >;
};
sdhci@c8000600 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000600 0x200>;
interrupts = < 63 >;
};
usb@c5000000 {
compatible = "nvidia,tegra20-ehci", "usb-ehci";
reg = <0xc5000000 0x4000>;
interrupts = < 52 >;
phy_type = "utmi";
clocks = <&tegra_car 22>; /* PERIPH_ID_USBD */
nvidia,has-legacy-mode;
};
usb@c5004000 {
compatible = "nvidia,tegra20-ehci", "usb-ehci";
reg = <0xc5004000 0x4000>;
interrupts = < 53 >;
phy_type = "ulpi";
clocks = <&tegra_car 58>; /* PERIPH_ID_USB2 */
};
usb@c5008000 {
compatible = "nvidia,tegra20-ehci", "usb-ehci";
reg = <0xc5008000 0x4000>;
interrupts = < 129 >;
phy_type = "utmi";
clocks = <&tegra_car 59>; /* PERIPH_ID_USB3 */
};
emc@7000f400 {
#address-cells = < 1 >;
#size-cells = < 0 >;
compatible = "nvidia,tegra20-emc";
reg = <0x7000f400 0x200>;
};
kbc@7000e200 {
compatible = "nvidia,tegra20-kbc";
reg = <0x7000e200 0x0078>;
};
nand: nand-controller@70008000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-nand";
reg = <0x70008000 0x100>;
};
pwm: pwm@7000a000 {
compatible = "nvidia,tegra20-pwm";
reg = <0x7000a000 0x100>;
#pwm-cells = <2>;
};
host1x {
compatible = "nvidia,tegra20-host1x", "simple-bus";
reg = <0x50000000 0x00024000>;
@ -316,4 +102,240 @@
};
};
intc: interrupt-controller@50041000 {
compatible = "nvidia,tegra20-gic";
interrupt-controller;
#interrupt-cells = <1>;
reg = < 0x50041000 0x1000 >,
< 0x50040100 0x0100 >;
};
tegra_car: clock@60006000 {
compatible = "nvidia,tegra20-car";
reg = <0x60006000 0x1000>;
#clock-cells = <1>;
};
apbdma: dma {
compatible = "nvidia,tegra20-apbdma";
reg = <0x6000a000 0x1200>;
interrupts = <0 104 0x04
0 105 0x04
0 106 0x04
0 107 0x04
0 108 0x04
0 109 0x04
0 110 0x04
0 111 0x04
0 112 0x04
0 113 0x04
0 114 0x04
0 115 0x04
0 116 0x04
0 117 0x04
0 118 0x04
0 119 0x04>;
};
gpio: gpio@6000d000 {
compatible = "nvidia,tegra20-gpio";
reg = < 0x6000d000 0x1000 >;
interrupts = < 64 65 66 67 87 119 121 >;
#gpio-cells = <2>;
gpio-controller;
};
pinmux: pinmux@70000000 {
compatible = "nvidia,tegra20-pinmux";
reg = < 0x70000014 0x10 /* Tri-state registers */
0x70000080 0x20 /* Mux registers */
0x700000a0 0x14 /* Pull-up/down registers */
0x70000868 0xa8 >; /* Pad control registers */
};
das@70000c00 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-das";
reg = <0x70000c00 0x80>;
};
i2s@70002800 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2s";
reg = <0x70002800 0x200>;
interrupts = < 45 >;
dma-channel = < 2 >;
};
i2s@70002a00 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2s";
reg = <0x70002a00 0x200>;
interrupts = < 35 >;
dma-channel = < 1 >;
};
serial@70006000 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006000 0x40>;
reg-shift = <2>;
interrupts = < 68 >;
};
serial@70006040 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006040 0x40>;
reg-shift = <2>;
interrupts = < 69 >;
};
serial@70006200 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006200 0x100>;
reg-shift = <2>;
interrupts = < 78 >;
};
serial@70006300 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006300 0x100>;
reg-shift = <2>;
interrupts = < 122 >;
};
serial@70006400 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006400 0x100>;
reg-shift = <2>;
interrupts = < 123 >;
};
nand: nand-controller@70008000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-nand";
reg = <0x70008000 0x100>;
};
pwm: pwm@7000a000 {
compatible = "nvidia,tegra20-pwm";
reg = <0x7000a000 0x100>;
#pwm-cells = <2>;
};
i2c@7000c000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2c";
reg = <0x7000C000 0x100>;
interrupts = < 70 >;
/* PERIPH_ID_I2C1, PLL_P_OUT3 */
clocks = <&tegra_car 12>, <&tegra_car 124>;
};
spi@7000c380 {
compatible = "nvidia,tegra20-sflash";
reg = <0x7000c380 0x80>;
interrupts = <0 39 0x04>;
nvidia,dma-request-selector = <&apbdma 11>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
/* PERIPH_ID_SPI1, PLLP_OUT0 */
clocks = <&tegra_car 43>;
};
i2c@7000c400 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2c";
reg = <0x7000C400 0x100>;
interrupts = < 116 >;
/* PERIPH_ID_I2C2, PLL_P_OUT3 */
clocks = <&tegra_car 54>, <&tegra_car 124>;
};
i2c@7000c500 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2c";
reg = <0x7000C500 0x100>;
interrupts = < 124 >;
/* PERIPH_ID_I2C3, PLL_P_OUT3 */
clocks = <&tegra_car 67>, <&tegra_car 124>;
};
i2c@7000d000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra20-i2c-dvc";
reg = <0x7000D000 0x200>;
interrupts = < 85 >;
/* PERIPH_ID_DVC_I2C, PLL_P_OUT3 */
clocks = <&tegra_car 47>, <&tegra_car 124>;
};
kbc@7000e200 {
compatible = "nvidia,tegra20-kbc";
reg = <0x7000e200 0x0078>;
};
emc@7000f400 {
#address-cells = < 1 >;
#size-cells = < 0 >;
compatible = "nvidia,tegra20-emc";
reg = <0x7000f400 0x200>;
};
usb@c5000000 {
compatible = "nvidia,tegra20-ehci", "usb-ehci";
reg = <0xc5000000 0x4000>;
interrupts = < 52 >;
phy_type = "utmi";
clocks = <&tegra_car 22>; /* PERIPH_ID_USBD */
nvidia,has-legacy-mode;
};
usb@c5004000 {
compatible = "nvidia,tegra20-ehci", "usb-ehci";
reg = <0xc5004000 0x4000>;
interrupts = < 53 >;
phy_type = "ulpi";
clocks = <&tegra_car 58>; /* PERIPH_ID_USB2 */
};
usb@c5008000 {
compatible = "nvidia,tegra20-ehci", "usb-ehci";
reg = <0xc5008000 0x4000>;
interrupts = < 129 >;
phy_type = "utmi";
clocks = <&tegra_car 59>; /* PERIPH_ID_USB3 */
};
sdhci@c8000000 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000000 0x200>;
interrupts = < 46 >;
};
sdhci@c8000200 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000200 0x200>;
interrupts = < 47 >;
};
sdhci@c8000400 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000400 0x200>;
interrupts = < 51 >;
};
sdhci@c8000600 {
compatible = "nvidia,tegra20-sdhci";
reg = <0xc8000600 0x200>;
interrupts = < 63 >;
};
};

165
arch/arm/dts/tegra30.dtsi Normal file
View file

@ -0,0 +1,165 @@
/include/ "skeleton.dtsi"
/ {
compatible = "nvidia,tegra30";
tegra_car: clock@60006000 {
compatible = "nvidia,tegra30-car", "nvidia,tegra20-car";
reg = <0x60006000 0x1000>;
#clock-cells = <1>;
};
apbdma: dma {
compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
reg = <0x6000a000 0x1400>;
interrupts = <0 104 0x04
0 105 0x04
0 106 0x04
0 107 0x04
0 108 0x04
0 109 0x04
0 110 0x04
0 111 0x04
0 112 0x04
0 113 0x04
0 114 0x04
0 115 0x04
0 116 0x04
0 117 0x04
0 118 0x04
0 119 0x04
0 128 0x04
0 129 0x04
0 130 0x04
0 131 0x04
0 132 0x04
0 133 0x04
0 134 0x04
0 135 0x04
0 136 0x04
0 137 0x04
0 138 0x04
0 139 0x04
0 140 0x04
0 141 0x04
0 142 0x04
0 143 0x04>;
};
i2c@7000c000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
reg = <0x7000C000 0x100>;
/* PERIPH_ID_I2C1, CLK_M */
clocks = <&tegra_car 12>;
};
i2c@7000c400 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
reg = <0x7000C400 0x100>;
/* PERIPH_ID_I2C2, CLK_M */
clocks = <&tegra_car 54>;
};
i2c@7000c500 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
reg = <0x7000C500 0x100>;
/* PERIPH_ID_I2C3, CLK_M */
clocks = <&tegra_car 67>;
};
i2c@7000c700 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
reg = <0x7000C700 0x100>;
/* PERIPH_ID_I2C4, CLK_M */
clocks = <&tegra_car 103>;
};
i2c@7000d000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
reg = <0x7000D000 0x100>;
/* PERIPH_ID_I2C_DVC, CLK_M */
clocks = <&tegra_car 47>;
};
spi@7000d400 {
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
reg = <0x7000d400 0x200>;
interrupts = <0 59 0x04>;
nvidia,dma-request-selector = <&apbdma 15>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
/* PERIPH_ID_SBC1, PLLP_OUT0 */
clocks = <&tegra_car 41>;
};
spi@7000d600 {
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
reg = <0x7000d600 0x200>;
interrupts = <0 82 0x04>;
nvidia,dma-request-selector = <&apbdma 16>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
/* PERIPH_ID_SBC2, PLLP_OUT0 */
clocks = <&tegra_car 44>;
};
spi@7000d800 {
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
reg = <0x7000d480 0x200>;
interrupts = <0 83 0x04>;
nvidia,dma-request-selector = <&apbdma 17>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
/* PERIPH_ID_SBC3, PLLP_OUT0 */
clocks = <&tegra_car 46>;
};
spi@7000da00 {
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
reg = <0x7000da00 0x200>;
interrupts = <0 93 0x04>;
nvidia,dma-request-selector = <&apbdma 18>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
/* PERIPH_ID_SBC4, PLLP_OUT0 */
clocks = <&tegra_car 68>;
};
spi@7000dc00 {
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
reg = <0x7000dc00 0x200>;
interrupts = <0 94 0x04>;
nvidia,dma-request-selector = <&apbdma 27>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
/* PERIPH_ID_SBC5, PLLP_OUT0 */
clocks = <&tegra_car 104>;
};
spi@7000de00 {
compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
reg = <0x7000de00 0x200>;
interrupts = <0 79 0x04>;
nvidia,dma-request-selector = <&apbdma 28>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
/* PERIPH_ID_SBC6, PLLP_OUT0 */
clocks = <&tegra_car 105>;
};
};

View file

@ -37,23 +37,23 @@ int get_clocks(void)
#ifdef CONFIG_FSL_ESDHC
#ifdef CONFIG_FSL_USDHC
#if CONFIG_SYS_FSL_ESDHC_ADDR == USDHC2_BASE_ADDR
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
#elif CONFIG_SYS_FSL_ESDHC_ADDR == USDHC3_BASE_ADDR
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
#elif CONFIG_SYS_FSL_ESDHC_ADDR == USDHC4_BASE_ADDR
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
#else
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
#endif
#else
#if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC4_BASE_ADDR
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
#else
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
#endif
#endif
#endif

View file

@ -48,8 +48,8 @@ static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR;
DECLARE_GLOBAL_DATA_PTR;
#define timestamp (gd->tbl)
#define lastinc (gd->lastinc)
#define timestamp (gd->arch.tbl)
#define lastinc (gd->arch.lastinc)
static inline unsigned long long tick_to_time(unsigned long long tick)
{

View file

@ -65,6 +65,40 @@
#define MT41J128MJT125_PHY_FIFO_WE 0x100
#define MT41J128MJT125_IOCTRL_VALUE 0x18B
/* Micron MT41J256M8HX-15E */
#define MT41J256M8HX15E_EMIF_READ_LATENCY 0x06
#define MT41J256M8HX15E_EMIF_TIM1 0x0888A39B
#define MT41J256M8HX15E_EMIF_TIM2 0x26337FDA
#define MT41J256M8HX15E_EMIF_TIM3 0x501F830F
#define MT41J256M8HX15E_EMIF_SDCFG 0x61C04B32
#define MT41J256M8HX15E_EMIF_SDREF 0x0000093B
#define MT41J256M8HX15E_ZQ_CFG 0x50074BE4
#define MT41J256M8HX15E_DLL_LOCK_DIFF 0x1
#define MT41J256M8HX15E_RATIO 0x40
#define MT41J256M8HX15E_INVERT_CLKOUT 0x1
#define MT41J256M8HX15E_RD_DQS 0x3B
#define MT41J256M8HX15E_WR_DQS 0x85
#define MT41J256M8HX15E_PHY_WR_DATA 0xC1
#define MT41J256M8HX15E_PHY_FIFO_WE 0x100
#define MT41J256M8HX15E_IOCTRL_VALUE 0x18B
/* Micron MT41J512M8RH-125 on EVM v1.5 */
#define MT41J512M8RH125_EMIF_READ_LATENCY 0x06
#define MT41J512M8RH125_EMIF_TIM1 0x0888A39B
#define MT41J512M8RH125_EMIF_TIM2 0x26517FDA
#define MT41J512M8RH125_EMIF_TIM3 0x501F84EF
#define MT41J512M8RH125_EMIF_SDCFG 0x61C04BB2
#define MT41J512M8RH125_EMIF_SDREF 0x0000093B
#define MT41J512M8RH125_ZQ_CFG 0x50074BE4
#define MT41J512M8RH125_DLL_LOCK_DIFF 0x1
#define MT41J512M8RH125_RATIO 0x80
#define MT41J512M8RH125_INVERT_CLKOUT 0x0
#define MT41J512M8RH125_RD_DQS 0x3B
#define MT41J512M8RH125_WR_DQS 0x3C
#define MT41J512M8RH125_PHY_FIFO_WE 0xA5
#define MT41J512M8RH125_PHY_WR_DATA 0x74
#define MT41J512M8RH125_IOCTRL_VALUE 0x18B
/**
* Configure SDRAM
*/

View file

@ -25,7 +25,8 @@
/* PAD Control Fields */
#define SLEWCTRL (0x1 << 6)
#define RXACTIVE (0x1 << 5)
#define PULLUP_EN (0x1 << 4) /* Pull UP Selection */
#define PULLDOWN_EN (0x0 << 4) /* Pull Down Selection */
#define PULLUP_EN (0x1 << 4) /* Pull Up Selection */
#define PULLUDEN (0x0 << 3) /* Pull up enabled */
#define PULLUDDIS (0x1 << 3) /* Pull up disabled */
#define MODE(val) val /* used for Readability */

View file

@ -29,6 +29,7 @@
#define BOOT_DEVICE_MMC2 9 /* eMMC or daughter card */
#define BOOT_DEVICE_SPI 11
#define BOOT_DEVICE_UART 65
#define BOOT_DEVICE_USBETH 68
#define BOOT_DEVICE_CPGMAC 70
#define BOOT_DEVICE_MMC2_2 0xFF
#endif

View file

@ -31,37 +31,37 @@
static inline unsigned long get_cpu_clk_rate(void)
{
DECLARE_GLOBAL_DATA_PTR;
return gd->cpu_clk_rate_hz;
return gd->arch.cpu_clk_rate_hz;
}
static inline unsigned long get_main_clk_rate(void)
{
DECLARE_GLOBAL_DATA_PTR;
return gd->main_clk_rate_hz;
return gd->arch.main_clk_rate_hz;
}
static inline unsigned long get_mck_clk_rate(void)
{
DECLARE_GLOBAL_DATA_PTR;
return gd->mck_rate_hz;
return gd->arch.mck_rate_hz;
}
static inline unsigned long get_plla_clk_rate(void)
{
DECLARE_GLOBAL_DATA_PTR;
return gd->plla_rate_hz;
return gd->arch.plla_rate_hz;
}
static inline unsigned long get_pllb_clk_rate(void)
{
DECLARE_GLOBAL_DATA_PTR;
return gd->pllb_rate_hz;
return gd->arch.pllb_rate_hz;
}
static inline u32 get_pllb_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
return gd->at91_pllb_usb_init;
return gd->arch.at91_pllb_usb_init;
}
static inline unsigned long get_macb_pclk_rate(unsigned int dev_id)

View file

@ -67,7 +67,11 @@ struct davinci_gpio_bank {
#define gpio_status() gpio_info()
#define GPIO_NAME_SIZE 20
#if defined(CONFIG_SOC_DA8XX) && !defined(CONFIG_SOC_DA850)
#define MAX_NUM_GPIOS 128
#else
#define MAX_NUM_GPIOS 144
#endif
#define GPIO_BANK(gp) (davinci_gpio_bank01 + ((gp) >> 5))
#define GPIO_BIT(gp) ((gp) & 0x1F)

View file

@ -23,67 +23,27 @@
#include <asm/types.h>
/* Stabilization delays, in usec */
#define PLL_STABILIZATION_DELAY (300)
#define PLL_STABILIZATION_DELAY (300)
#define IO_STABILIZATION_DELAY (1000)
#define NVBL_PLLP_KHZ (216000)
#define PLLX_ENABLED (1 << 30)
#define CCLK_BURST_POLICY 0x20008888
#define SUPER_CCLK_DIVIDER 0x80000000
/* Calculate clock fractional divider value from ref and target frequencies */
#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / FREQ) - 2)
#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / FREQ) - 2)
/* Calculate clock frequency value from reference and clock divider value */
#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2))
#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2))
/* AVP/CPU ID */
#define PG_UP_TAG_0_PID_CPU 0x55555555 /* CPU aka "a9" aka "mpcore" */
#define PG_UP_TAG_0 0x0
#define PG_UP_TAG_0 0x0
#define CORESIGHT_UNLOCK 0xC5ACCE55;
/* AP20-Specific Base Addresses */
/* AP20 Base physical address of SDRAM. */
#define AP20_BASE_PA_SDRAM 0x00000000
/* AP20 Base physical address of internal SRAM. */
#define AP20_BASE_PA_SRAM 0x40000000
/* AP20 Size of internal SRAM (256KB). */
#define AP20_BASE_PA_SRAM_SIZE 0x00040000
/* AP20 Base physical address of flash. */
#define AP20_BASE_PA_NOR_FLASH 0xD0000000
/* AP20 Base physical address of boot information table. */
#define AP20_BASE_PA_BOOT_INFO AP20_BASE_PA_SRAM
/*
* Super-temporary stacks for EXTREMELY early startup. The values chosen for
* these addresses must be valid on ALL SOCs because this value is used before
* we are able to differentiate between the SOC types.
*
* NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
* stack is placed below the AVP stack. Once the CPU stack has been moved,
* the AVP is free to use the IRAM the CPU stack previously occupied if
* it should need to do so.
*
* NOTE: In multi-processor CPU complex configurations, each processor will have
* its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
* limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
* stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
* CPU.
*/
/* Common AVP early boot stack limit */
#define AVP_EARLY_BOOT_STACK_LIMIT \
(AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
/* Common AVP early boot stack size */
#define AVP_EARLY_BOOT_STACK_SIZE 0x1000
/* Common CPU early boot stack limit */
#define CPU_EARLY_BOOT_STACK_LIMIT \
(AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
/* Common CPU early boot stack size */
#define CPU_EARLY_BOOT_STACK_SIZE 0x1000
/* AP base physical address of internal SRAM */
#define NV_PA_BASE_SRAM 0x40000000
#define EXCEP_VECTOR_CPU_RESET_VECTOR (NV_PA_EVP_BASE + 0x100)
#define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0)

View file

@ -41,8 +41,9 @@ void gpio_early_init(void); /* overrideable GPIO config */
* an empty stub function will be called.
*/
void pin_mux_usb(void); /* overrideable USB pinmux setup */
void pin_mux_spi(void); /* overrideable SPI pinmux setup */
void pin_mux_nand(void); /* overrideable NAND pinmux setup */
void pin_mux_usb(void); /* overrideable USB pinmux setup */
void pin_mux_spi(void); /* overrideable SPI pinmux setup */
void pin_mux_nand(void); /* overrideable NAND pinmux setup */
void pin_mux_display(void); /* overrideable DISPLAY pinmux setup */
#endif

View file

@ -21,8 +21,8 @@
* MA 02111-1307 USA
*/
#ifndef _CLK_RST_H_
#define _CLK_RST_H_
#ifndef _TEGRA_CLK_RST_H_
#define _TEGRA_CLK_RST_H_
/* PLL registers - there are several PLLs in the clock controller */
struct clk_pll {
@ -37,6 +37,12 @@ struct clk_pll_simple {
uint pll_misc; /* other misc things */
};
/* RST_DEV_(L,H,U,V,W)_(SET,CLR) and CLK_ENB_(L,H,U,V,W)_(SET,CLR) */
struct clk_set_clr {
uint set;
uint clr;
};
/*
* 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-
@ -45,8 +51,10 @@ struct clk_pll_simple {
enum {
TEGRA_CLK_PLLS = 6, /* Number of normal PLLs */
TEGRA_CLK_SIMPLE_PLLS = 3, /* Number of simple PLLs */
TEGRA_CLK_REGS = 3, /* Number of clock enable registers */
TEGRA_CLK_SOURCES = 64, /* Number of peripheral clock sources */
TEGRA_CLK_REGS = 3, /* Number of clock enable regs L/H/U */
TEGRA_CLK_SOURCES = 64, /* Number of ppl clock sources L/H/U */
TEGRA_CLK_REGS_VW = 2, /* Number of clock enable regs V/W */
TEGRA_CLK_SOURCES_VW = 32, /* Number of ppl clock sources V/W*/
};
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
@ -82,14 +90,80 @@ struct clk_rst_ctlr {
uint crc_reserved11; /* _reserved_11, 0xFC */
uint crc_clk_src[TEGRA_CLK_SOURCES]; /*_I2S1_0... 0x100-1fc */
uint crc_reserved20[80]; /* 0x200-33C */
uint crc_cpu_cmplx_set; /* _CPU_CMPLX_SET_0, 0x340 */
uint crc_cpu_cmplx_clr; /* _CPU_CMPLX_CLR_0, 0x344 */
uint crc_reserved20[64]; /* _reserved_20, 0x200-2fc */
/* _RST_DEV_L/H/U_SET_0 0x300 ~ 0x314 */
struct clk_set_clr crc_rst_dev_ex[TEGRA_CLK_REGS];
uint crc_reserved30[2]; /* _reserved_30, 0x318, 0x31c */
/* _CLK_ENB_L/H/U_CLR_0 0x320 ~ 0x334 */
struct clk_set_clr crc_clk_enb_ex[TEGRA_CLK_REGS];
uint crc_reserved31[2]; /* _reserved_31, 0x338, 0x33c */
uint crc_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */
uint crc_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */
/* Additional (T30) registers */
uint crc_clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */
uint crc_clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
uint crc_reserved32[2]; /* _reserved_32, 0x350,0x354 */
uint crc_rst_dev_vw[TEGRA_CLK_REGS_VW]; /* _RST_DEVICES_V/W_0 */
uint crc_clk_out_enb_vw[TEGRA_CLK_REGS_VW]; /* _CLK_OUT_ENB_V/W_0 */
uint crc_cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
uint crc_super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */
uint crc_cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
uint crc_super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
uint crc_clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
uint crc_clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */
uint crc_cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
uint crc_cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTR1L_0, 0x384 */
uint crc_cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
uint crc_reserved33[9]; /* _reserved_33, 0x38c-3ac */
uint crc_clk_src_vw[TEGRA_CLK_SOURCES_VW]; /* _G3D2_0..., 0x3b0-0x42c */
/* _RST_DEV_V/W_SET_0 0x430 ~ 0x43c */
struct clk_set_clr crc_rst_dev_ex_vw[TEGRA_CLK_REGS_VW];
/* _CLK_ENB_V/W_CLR_0 0x440 ~ 0x44c */
struct clk_set_clr crc_clk_enb_ex_vw[TEGRA_CLK_REGS_VW];
/* Additional (T114) registers */
uint crc_rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */
uint crc_rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */
uint crc_rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */
uint crc_rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45C */
uint crc_clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */
uint crc_clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */
uint crc_clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */
uint crc_clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46C */
uint crc_cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */
uint crc_reserved40[1]; /* _reserved_40, 0x474 */
uint crc_intstatus; /* __INTSTATUS_0, 0x478 */
uint crc_intmask; /* __INTMASK_0, 0x47C */
uint crc_utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */
uint crc_utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */
uint crc_utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */
uint crc_plle_aux; /* _PLLE_AUX_0, 0x48C */
uint crc_sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */
uint crc_sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */
uint crc_pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */
uint crc_prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49C */
uint crc_audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4A0 */
uint crc_audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4A4 */
uint crc_audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4A8 */
uint crc_audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4AC */
uint crc_audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4B0 */
uint crc_audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4B4 */
};
/* CLK_RST_CONTROLLER_CLK_CPU_CMPLX_0 */
#define CPU3_CLK_STP_SHIFT 11
#define CPU2_CLK_STP_SHIFT 10
#define CPU1_CLK_STP_SHIFT 9
#define CPU0_CLK_STP_SHIFT 8
#define CPU0_CLK_STP_MASK (1U << CPU0_CLK_STP_SHIFT)
@ -120,6 +194,12 @@ struct clk_rst_ctlr {
#define PLL_OUT_RATIO_MASK (0xffU << PLL_OUT_RATIO_SHIFT)
/* CLK_RST_CONTROLLER_PLLx_MISC_0 */
#define PLL_DCCON_SHIFT 20
#define PLL_DCCON_MASK (1U << PLL_DCCON_SHIFT)
#define PLL_LOCK_ENABLE_SHIFT 18
#define PLL_LOCK_ENABLE_MASK (1U << PLL_LOCK_ENABLE_SHIFT)
#define PLL_CPCON_SHIFT 8
#define PLL_CPCON_MASK (15U << PLL_CPCON_SHIFT)
@ -129,9 +209,23 @@ struct clk_rst_ctlr {
#define PLLU_VCO_FREQ_SHIFT 20
#define PLLU_VCO_FREQ_MASK (1U << PLLU_VCO_FREQ_SHIFT)
#define PLLP_OUT1_OVR (1 << 2)
#define PLLP_OUT2_OVR (1 << 18)
#define PLLP_OUT3_OVR (1 << 2)
#define PLLP_OUT4_OVR (1 << 18)
#define PLLP_OUT1_RATIO 8
#define PLLP_OUT2_RATIO 24
#define PLLP_OUT3_RATIO 8
#define PLLP_OUT4_RATIO 24
enum {
IN_408_OUT_204_DIVISOR = 2,
IN_408_OUT_102_DIVISOR = 6,
IN_408_OUT_48_DIVISOR = 15,
IN_408_OUT_9_6_DIVISOR = 83,
};
/* CLK_RST_CONTROLLER_OSC_CTRL_0 */
#define OSC_FREQ_SHIFT 30
#define OSC_FREQ_MASK (3U << OSC_FREQ_SHIFT)
#define OSC_XOBP_SHIFT 1
#define OSC_XOBP_MASK (1U << OSC_XOBP_SHIFT)
@ -151,4 +245,84 @@ struct clk_rst_ctlr {
#define OUT_CLK_SOURCE4_SHIFT 28
#define OUT_CLK_SOURCE4_MASK (15U << OUT_CLK_SOURCE4_SHIFT)
#endif /* CLK_RST_H */
/* CLK_RST_CONTROLLER_SCLK_BURST_POLICY */
#define SCLK_SYS_STATE_SHIFT 28U
#define SCLK_SYS_STATE_MASK (15U << SCLK_SYS_STATE_SHIFT)
enum {
SCLK_SYS_STATE_STDBY,
SCLK_SYS_STATE_IDLE,
SCLK_SYS_STATE_RUN,
SCLK_SYS_STATE_IRQ = 4U,
SCLK_SYS_STATE_FIQ = 8U,
};
#define SCLK_COP_FIQ_MASK (1 << 27)
#define SCLK_CPU_FIQ_MASK (1 << 26)
#define SCLK_COP_IRQ_MASK (1 << 25)
#define SCLK_CPU_IRQ_MASK (1 << 24)
#define SCLK_SWAKEUP_FIQ_SOURCE_SHIFT 12
#define SCLK_SWAKEUP_FIQ_SOURCE_MASK \
(7 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT)
#define SCLK_SWAKEUP_IRQ_SOURCE_SHIFT 8
#define SCLK_SWAKEUP_IRQ_SOURCE_MASK \
(7 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT)
#define SCLK_SWAKEUP_RUN_SOURCE_SHIFT 4
#define SCLK_SWAKEUP_RUN_SOURCE_MASK \
(7 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT)
#define SCLK_SWAKEUP_IDLE_SOURCE_SHIFT 0
#define SCLK_SWAKEUP_IDLE_SOURCE_MASK \
(7 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT)
enum {
SCLK_SOURCE_CLKM,
SCLK_SOURCE_PLLC_OUT1,
SCLK_SOURCE_PLLP_OUT4,
SCLK_SOURCE_PLLP_OUT3,
SCLK_SOURCE_PLLP_OUT2,
SCLK_SOURCE_CLKD,
SCLK_SOURCE_CLKS,
SCLK_SOURCE_PLLM_OUT1,
};
#define SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 (7 << 12)
#define SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 (7 << 8)
#define SCLK_SWAKE_RUN_SRC_PLLM_OUT1 (7 << 4)
#define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 (7 << 0)
/* CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER */
#define SUPER_SCLK_ENB_SHIFT 31U
#define SUPER_SCLK_ENB_MASK (1U << 31)
#define SUPER_SCLK_DIVIDEND_SHIFT 8
#define SUPER_SCLK_DIVIDEND_MASK (0xff << SUPER_SCLK_DIVIDEND_SHIFT)
#define SUPER_SCLK_DIVISOR_SHIFT 0
#define SUPER_SCLK_DIVISOR_MASK (0xff << SUPER_SCLK_DIVISOR_SHIFT)
/* CLK_RST_CONTROLLER_CLK_SYSTEM_RATE */
#define CLK_SYS_RATE_HCLK_DISABLE_SHIFT 7
#define CLK_SYS_RATE_HCLK_DISABLE_MASK (1 << CLK_SYS_RATE_HCLK_DISABLE_SHIFT)
#define CLK_SYS_RATE_AHB_RATE_SHIFT 4
#define CLK_SYS_RATE_AHB_RATE_MASK (3 << CLK_SYS_RATE_AHB_RATE_SHIFT)
#define CLK_SYS_RATE_PCLK_DISABLE_SHIFT 3
#define CLK_SYS_RATE_PCLK_DISABLE_MASK (1 << CLK_SYS_RATE_PCLK_DISABLE_SHIFT)
#define CLK_SYS_RATE_APB_RATE_SHIFT 0
#define CLK_SYS_RATE_APB_RATE_MASK (3 << CLK_SYS_RATE_AHB_RATE_SHIFT)
/* CLK_RST_CONTROLLER_RST_CPUxx_CMPLX_CLR */
#define CLR_CPURESET0 (1 << 0)
#define CLR_CPURESET1 (1 << 1)
#define CLR_CPURESET2 (1 << 2)
#define CLR_CPURESET3 (1 << 3)
#define CLR_DBGRESET0 (1 << 12)
#define CLR_DBGRESET1 (1 << 13)
#define CLR_DBGRESET2 (1 << 14)
#define CLR_DBGRESET3 (1 << 15)
#define CLR_CORERESET0 (1 << 16)
#define CLR_CORERESET1 (1 << 17)
#define CLR_CORERESET2 (1 << 18)
#define CLR_CORERESET3 (1 << 19)
#define CLR_CXRESET0 (1 << 20)
#define CLR_CXRESET1 (1 << 21)
#define CLR_CXRESET2 (1 << 22)
#define CLR_CXRESET3 (1 << 23)
#define CLR_NONCPURESET (1 << 29)
#endif /* _TEGRA_CLK_RST_H_ */

View file

@ -21,8 +21,8 @@
/* Tegra clock control functions */
#ifndef _CLOCK_H
#define _CLOCK_H
#ifndef _TEGRA_CLOCK_H_
#define _TEGRA_CLOCK_H_
/* Set of oscillator frequencies supported in the internal API. */
enum clock_osc_freq {
@ -82,7 +82,7 @@ int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout,
* @returns 0 if ok, -1 on error (invalid clock id)
*/
int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
u32 *divp, u32 *cpcon, u32 *lfcon);
u32 *divp, u32 *cpcon, u32 *lfcon);
/*
* Enable a clock
@ -136,7 +136,7 @@ enum crc_reset_id {
/**
* Put parts of the CPU complex into or out of reset.\
*
* @param cpu cpu number (0 or 1 on Tegra2)
* @param cpu cpu number (0 or 1 on Tegra2, 0-3 on Tegra3)
* @param which which parts of the complex to affect (OR of crc_reset_id)
* @param reset 1 to assert reset, 0 to de-assert
*/
@ -262,4 +262,59 @@ void clock_init(void);
/* Initialize the PLLs */
void clock_early_init(void);
#endif /* _CLOCK_H_ */
/* Returns a pointer to the clock source register for a peripheral */
u32 *get_periph_source_reg(enum periph_id periph_id);
/**
* Given a peripheral ID and the required source clock, this returns which
* value should be programmed into the source mux for that peripheral.
*
* There is special code here to handle the one source type with 5 sources.
*
* @param periph_id peripheral to start
* @param source PLL id of required parent clock
* @param mux_bits Set to number of bits in mux register: 2 or 4
* @param divider_bits Set to number of divider bits (8 or 16)
* @return mux value (0-4, or -1 if not found)
*/
int get_periph_clock_source(enum periph_id periph_id,
enum clock_id parent, int *mux_bits, int *divider_bits);
/*
* Convert a device tree clock ID to our peripheral ID. They are mostly
* the same but we are very cautious so we check that a valid clock ID is
* provided.
*
* @param clk_id Clock ID according to tegra30 device tree binding
* @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
*/
enum periph_id clk_id_to_periph_id(int clk_id);
/**
* Set the output frequency you want for each PLL clock.
* PLL output frequencies are programmed by setting their N, M and P values.
* The governing equations are:
* VCO = (Fi / m) * n, Fo = VCO / (2^p)
* where Fo is the output frequency from the PLL.
* Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
* 216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
* Please see Tegra TRM section 5.3 to get the detail for PLL Programming
*
* @param n PLL feedback divider(DIVN)
* @param m PLL input divider(DIVN)
* @param p post divider(DIVP)
* @param cpcon base PLL charge pump(CPCON)
* @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
* be overriden), 1 if PLL is already correct
*/
int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon);
/* return 1 if a peripheral ID is in range */
#define clock_type_id_isvalid(id) ((id) >= 0 && \
(id) < CLOCK_TYPE_COUNT)
/* return 1 if a periphc_internal_id is in range */
#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
(id) < PERIPHC_COUNT)
#endif /* _TEGRA_CLOCK_H_ */

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra high-level function multiplexing */
#ifndef _TEGRA_FUNCMUX_H_
#define _TEGRA_FUNCMUX_H_
/**
* Select a config for a particular peripheral.
*
* Each peripheral can operate through a number of configurations,
* which are sets of pins that it uses to bring out its signals.
* The basic config is 0, and higher numbers indicate different
* pinmux settings to bring the peripheral out on other pins,
*
* This function also disables tristate for the function's pins,
* so that they operate in normal mode.
*
* @param id Peripheral id
* @param config Configuration to use (FUNCMUX_...), 0 for default
* @return 0 if ok, -1 on error (e.g. incorrect id or config)
*/
int funcmux_select(enum periph_id id, int config);
#endif /* _TEGRA_FUNCMUX_H_ */

View file

@ -0,0 +1,40 @@
/*
* (C) Copyright 2010-2012
* NVIDIA Corporation <www.nvidia.com>
*
* 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
*/
#ifndef _TEGRA_GP_PADCTRL_H_
#define _TEGRA_GP_PADCTRL_H_
#define GP_HIDREV 0x804
/* bit fields definitions for APB_MISC_GP_HIDREV register */
#define HIDREV_CHIPID_SHIFT 8
#define HIDREV_CHIPID_MASK (0xff << HIDREV_CHIPID_SHIFT)
#define HIDREV_MAJORPREV_SHIFT 4
#define HIDREV_MAJORPREV_MASK (0xf << HIDREV_MAJORPREV_SHIFT)
/* CHIPID field returned from APB_MISC_GP_HIDREV register */
#define CHIPID_TEGRA20 0x20
#define CHIPID_TEGRA30 0x30
#define CHIPID_TEGRA114 0x35
#endif /* _TEGRA_GP_PADCTRL_H_ */

View file

@ -128,5 +128,13 @@ struct pmc_ctlr {
#define START_CP (1 << 8)
#define CPUPWRREQ_OE (1 << 16)
#define CPUPWRREQ_POL (1 << 15)
#define CRAILID (0)
#define CE0ID (14)
#define C0NCID (15)
#define CRAIL (1 << CRAILID)
#define CE0 (1 << CE0ID)
#define C0NC (1 << C0NCID)
#endif /* PMC_H */

View file

@ -40,6 +40,12 @@
#define NV_PA_APB_UARTE_BASE (NV_PA_APB_MISC_BASE + 0x6400)
#define NV_PA_NAND_BASE (NV_PA_APB_MISC_BASE + 0x8000)
#define NV_PA_SPI_BASE (NV_PA_APB_MISC_BASE + 0xC380)
#define NV_PA_SLINK1_BASE (NV_PA_APB_MISC_BASE + 0xD400)
#define NV_PA_SLINK2_BASE (NV_PA_APB_MISC_BASE + 0xD600)
#define NV_PA_SLINK3_BASE (NV_PA_APB_MISC_BASE + 0xD800)
#define NV_PA_SLINK4_BASE (NV_PA_APB_MISC_BASE + 0xDA00)
#define NV_PA_SLINK5_BASE (NV_PA_APB_MISC_BASE + 0xDC00)
#define NV_PA_SLINK6_BASE (NV_PA_APB_MISC_BASE + 0xDE00)
#define TEGRA_DVC_BASE (NV_PA_APB_MISC_BASE + 0xD000)
#define NV_PA_PMC_BASE (NV_PA_APB_MISC_BASE + 0xE400)
#define NV_PA_EMC_BASE (NV_PA_APB_MISC_BASE + 0xF400)
@ -72,14 +78,23 @@ enum {
SKU_ID_T25 = 0x18,
SKU_ID_AP25E = 0x1b,
SKU_ID_T25E = 0x1c,
SKU_ID_T30 = 0x81, /* Cardhu value */
SKU_ID_T114_ENG = 0x00, /* Dalmore value, unfused */
};
/* These are the SOC categories that affect clocking */
/*
* These are used to distinguish SOC types for setting up clocks. Mostly
* we can tell the clocking required by looking at the SOC sku_id, but
* for T30 it is a user option as to whether to run PLLP in fast or slow
* mode, so we have two options there.
*/
enum {
TEGRA_SOC_T20,
TEGRA_SOC_T25,
TEGRA_SOC_T30,
TEGRA_SOC_T114,
TEGRA_SOC_COUNT,
TEGRA_SOC_CNT,
TEGRA_SOC_UNKNOWN = -1,
};

View file

@ -0,0 +1,84 @@
/*
* NVIDIA Tegra SPI-SLINK controller
*
* Copyright 2010-2013 NVIDIA Corporation
*
* This software may be used and distributed according to the
* terms of the GNU Public License, Version 2, incorporated
* herein by reference.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Version 2 as published by the Free Software Foundation.
*
* 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
*/
#ifndef _TEGRA_SLINK_H_
#define _TEGRA_SLINK_H_
#include <asm/types.h>
struct slink_tegra {
u32 command; /* SLINK_COMMAND_0 register */
u32 command2; /* SLINK_COMMAND2_0 reg */
u32 status; /* SLINK_STATUS_0 register */
u32 reserved; /* Reserved offset 0C */
u32 mas_data; /* SLINK_MAS_DATA_0 reg */
u32 slav_data; /* SLINK_SLAVE_DATA_0 reg */
u32 dma_ctl; /* SLINK_DMA_CTL_0 register */
u32 status2; /* SLINK_STATUS2_0 reg */
u32 rsvd[56]; /* 0x20 to 0xFF reserved */
u32 tx_fifo; /* SLINK_TX_FIFO_0 reg off 100h */
u32 rsvd2[31]; /* 0x104 to 0x17F reserved */
u32 rx_fifo; /* SLINK_RX_FIFO_0 reg off 180h */
};
/* COMMAND */
#define SLINK_CMD_ENB (1 << 31)
#define SLINK_CMD_GO (1 << 30)
#define SLINK_CMD_M_S (1 << 28)
#define SLINK_CMD_CK_SDA (1 << 21)
#define SLINK_CMD_CS_POL (1 << 13)
#define SLINK_CMD_CS_VAL (1 << 12)
#define SLINK_CMD_CS_SOFT (1 << 11)
#define SLINK_CMD_BIT_LENGTH (1 << 4)
#define SLINK_CMD_BIT_LENGTH_MASK 0x0000001F
/* COMMAND2 */
#define SLINK_CMD2_TXEN (1 << 30)
#define SLINK_CMD2_RXEN (1 << 31)
#define SLINK_CMD2_SS_EN (1 << 18)
#define SLINK_CMD2_SS_EN_SHIFT 18
#define SLINK_CMD2_SS_EN_MASK 0x000C0000
#define SLINK_CMD2_CS_ACTIVE_BETWEEN (1 << 17)
/* STATUS */
#define SLINK_STAT_BSY (1 << 31)
#define SLINK_STAT_RDY (1 << 30)
#define SLINK_STAT_ERR (1 << 29)
#define SLINK_STAT_RXF_FLUSH (1 << 27)
#define SLINK_STAT_TXF_FLUSH (1 << 26)
#define SLINK_STAT_RXF_OVF (1 << 25)
#define SLINK_STAT_TXF_UNR (1 << 24)
#define SLINK_STAT_RXF_EMPTY (1 << 23)
#define SLINK_STAT_RXF_FULL (1 << 22)
#define SLINK_STAT_TXF_EMPTY (1 << 21)
#define SLINK_STAT_TXF_FULL (1 << 20)
#define SLINK_STAT_TXF_OVF (1 << 19)
#define SLINK_STAT_RXF_UNR (1 << 18)
#define SLINK_STAT_CUR_BLKCNT (1 << 15)
/* STATUS2 */
#define SLINK_STAT2_RXF_FULL_CNT (1 << 16)
#define SLINK_STAT2_TXF_FULL_CNT (1 << 0)
#define SPI_TIMEOUT 1000
#define TEGRA_SPI_MAX_FREQ 52000000
#endif /* _TEGRA_SLINK_H_ */

View file

@ -0,0 +1,402 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra114 clock PLL tables */
#ifndef _TEGRA114_CLOCK_TABLES_H_
#define _TEGRA114_CLOCK_TABLES_H_
/* The PLLs supported by the hardware */
enum clock_id {
CLOCK_ID_FIRST,
CLOCK_ID_CGENERAL = CLOCK_ID_FIRST,
CLOCK_ID_MEMORY,
CLOCK_ID_PERIPH,
CLOCK_ID_AUDIO,
CLOCK_ID_USB,
CLOCK_ID_DISPLAY,
/* now the simple ones */
CLOCK_ID_FIRST_SIMPLE,
CLOCK_ID_XCPU = CLOCK_ID_FIRST_SIMPLE,
CLOCK_ID_EPCI,
CLOCK_ID_SFROM32KHZ,
/* These are the base clocks (inputs to the Tegra SOC) */
CLOCK_ID_32KHZ,
CLOCK_ID_OSC,
CLOCK_ID_COUNT, /* number of PLLs */
CLOCK_ID_DISPLAY2, /* placeholder */
CLOCK_ID_NONE = -1,
};
/* The clocks supported by the hardware */
enum periph_id {
PERIPH_ID_FIRST,
/* Low word: 31:0 (DEVICES_L) */
PERIPH_ID_CPU = PERIPH_ID_FIRST,
PERIPH_ID_COP,
PERIPH_ID_TRIGSYS,
PERIPH_ID_RESERVED3,
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_RESERVED16,
PERIPH_ID_PWM,
PERIPH_ID_I2S2,
PERIPH_ID_EPP,
PERIPH_ID_VI,
PERIPH_ID_2D,
PERIPH_ID_USBD,
PERIPH_ID_ISP,
/* 24 */
PERIPH_ID_3D,
PERIPH_ID_RESERVED24,
PERIPH_ID_DISP2,
PERIPH_ID_DISP1,
PERIPH_ID_HOST1X,
PERIPH_ID_VCP,
PERIPH_ID_I2S0,
PERIPH_ID_CACHE2,
/* Middle word: 63:32 (DEVICES_H) */
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_RESERVED43,
PERIPH_ID_SBC2,
PERIPH_ID_RESERVED45,
PERIPH_ID_SBC3,
PERIPH_ID_I2C5,
/* 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 (DEVICES_U) */
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_PCIEXCLK,
PERIPH_ID_AVPUCQ,
PERIPH_ID_RESERVED76,
PERIPH_ID_RESERVED77,
PERIPH_ID_RESERVED78,
PERIPH_ID_DTV,
/* 80 */
PERIPH_ID_NANDSPEED,
PERIPH_ID_I2CSLOW,
PERIPH_ID_DSIB,
PERIPH_ID_RESERVED83,
PERIPH_ID_IRAMA,
PERIPH_ID_IRAMB,
PERIPH_ID_IRAMC,
PERIPH_ID_IRAMD,
/* 88 */
PERIPH_ID_CRAM2,
PERIPH_ID_RESERVED89,
PERIPH_ID_MDOUBLER,
PERIPH_ID_RESERVED91,
PERIPH_ID_SUSOUT,
PERIPH_ID_RESERVED93,
PERIPH_ID_RESERVED94,
PERIPH_ID_RESERVED95,
PERIPH_ID_VW_FIRST,
/* V word: 31:0 */
PERIPH_ID_CPUG = PERIPH_ID_VW_FIRST,
PERIPH_ID_CPULP,
PERIPH_ID_3D2,
PERIPH_ID_MSELECT,
PERIPH_ID_TSENSOR,
PERIPH_ID_I2S3,
PERIPH_ID_I2S4,
PERIPH_ID_I2C4,
/* 104 */
PERIPH_ID_SBC5,
PERIPH_ID_SBC6,
PERIPH_ID_AUDIO,
PERIPH_ID_APBIF,
PERIPH_ID_DAM0,
PERIPH_ID_DAM1,
PERIPH_ID_DAM2,
PERIPH_ID_HDA2CODEC2X,
/* 112 */
PERIPH_ID_ATOMICS,
PERIPH_ID_EX_RESERVED17,
PERIPH_ID_EX_RESERVED18,
PERIPH_ID_EX_RESERVED19,
PERIPH_ID_EX_RESERVED20,
PERIPH_ID_EX_RESERVED21,
PERIPH_ID_EX_RESERVED22,
PERIPH_ID_ACTMON,
/* 120 */
PERIPH_ID_EX_RESERVED24,
PERIPH_ID_EX_RESERVED25,
PERIPH_ID_EX_RESERVED26,
PERIPH_ID_EX_RESERVED27,
PERIPH_ID_SATA,
PERIPH_ID_HDA,
PERIPH_ID_EX_RESERVED30,
PERIPH_ID_EX_RESERVED31,
/* W word: 31:0 */
PERIPH_ID_HDA2HDMICODEC,
PERIPH_ID_RESERVED1_SATACOLD,
PERIPH_ID_RESERVED2_PCIERX0,
PERIPH_ID_RESERVED3_PCIERX1,
PERIPH_ID_RESERVED4_PCIERX2,
PERIPH_ID_RESERVED5_PCIERX3,
PERIPH_ID_RESERVED6_PCIERX4,
PERIPH_ID_RESERVED7_PCIERX5,
/* 136 */
PERIPH_ID_CEC,
PERIPH_ID_PCIE2_IOBIST,
PERIPH_ID_EMC_IOBIST,
PERIPH_ID_HDMI_IOBIST,
PERIPH_ID_SATA_IOBIST,
PERIPH_ID_MIPI_IOBIST,
PERIPH_ID_EMC1_IOBIST,
PERIPH_ID_XUSB,
/* 144 */
PERIPH_ID_CILAB,
PERIPH_ID_CILCD,
PERIPH_ID_CILE,
PERIPH_ID_DSIA_LP,
PERIPH_ID_DSIB_LP,
PERIPH_ID_RESERVED21_ENTROPY,
PERIPH_ID_RESERVED22_W,
PERIPH_ID_RESERVED23_W,
/* 152 */
PERIPH_ID_RESERVED24_W,
PERIPH_ID_AMX0,
PERIPH_ID_ADX0,
PERIPH_ID_DVFS,
PERIPH_ID_XUSB_SS,
PERIPH_ID_EMC_DLL,
PERIPH_ID_MC1,
PERIPH_ID_EMC1,
PERIPH_ID_COUNT,
PERIPH_ID_NONE = -1,
};
enum pll_out_id {
PLL_OUT1,
PLL_OUT2,
PLL_OUT3,
PLL_OUT4
};
/*
* Clock peripheral IDs which sadly don't match up with PERIPH_ID. we want
* callers to use the PERIPH_ID for all access to peripheral clocks to avoid
* confusion bewteen PERIPH_ID_... and PERIPHC_...
*
* We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be
* confusing.
*/
enum periphc_internal_id {
/* 0x00 */
PERIPHC_I2S1,
PERIPHC_I2S2,
PERIPHC_SPDIF_OUT,
PERIPHC_SPDIF_IN,
PERIPHC_PWM,
PERIPHC_05h,
PERIPHC_SBC2,
PERIPHC_SBC3,
/* 0x08 */
PERIPHC_08h,
PERIPHC_I2C1,
PERIPHC_I2C5,
PERIPHC_0bh,
PERIPHC_0ch,
PERIPHC_SBC1,
PERIPHC_DISP1,
PERIPHC_DISP2,
/* 0x10 */
PERIPHC_CVE,
PERIPHC_11h,
PERIPHC_VI,
PERIPHC_13h,
PERIPHC_SDMMC1,
PERIPHC_SDMMC2,
PERIPHC_G3D,
PERIPHC_G2D,
/* 0x18 */
PERIPHC_NDFLASH,
PERIPHC_SDMMC4,
PERIPHC_VFIR,
PERIPHC_EPP,
PERIPHC_MPE,
PERIPHC_MIPI,
PERIPHC_UART1,
PERIPHC_UART2,
/* 0x20 */
PERIPHC_HOST1X,
PERIPHC_21h,
PERIPHC_TVO,
PERIPHC_HDMI,
PERIPHC_24h,
PERIPHC_TVDAC,
PERIPHC_I2C2,
PERIPHC_EMC,
/* 0x28 */
PERIPHC_UART3,
PERIPHC_29h,
PERIPHC_VI_SENSOR,
PERIPHC_2bh,
PERIPHC_2ch,
PERIPHC_SBC4,
PERIPHC_I2C3,
PERIPHC_SDMMC3,
/* 0x30 */
PERIPHC_UART4,
PERIPHC_UART5,
PERIPHC_VDE,
PERIPHC_OWR,
PERIPHC_NOR,
PERIPHC_CSITE,
PERIPHC_I2S0,
PERIPHC_37h,
PERIPHC_VW_FIRST,
/* 0x38 */
PERIPHC_G3D2 = PERIPHC_VW_FIRST,
PERIPHC_MSELECT,
PERIPHC_TSENSOR,
PERIPHC_I2S3,
PERIPHC_I2S4,
PERIPHC_I2C4,
PERIPHC_SBC5,
PERIPHC_SBC6,
/* 0x40 */
PERIPHC_AUDIO,
PERIPHC_41h,
PERIPHC_DAM0,
PERIPHC_DAM1,
PERIPHC_DAM2,
PERIPHC_HDA2CODEC2X,
PERIPHC_ACTMON,
PERIPHC_EXTPERIPH1,
/* 0x48 */
PERIPHC_EXTPERIPH2,
PERIPHC_EXTPERIPH3,
PERIPHC_NANDSPEED,
PERIPHC_I2CSLOW,
PERIPHC_SYS,
PERIPHC_SPEEDO,
PERIPHC_4eh,
PERIPHC_4fh,
/* 0x50 */
PERIPHC_50h,
PERIPHC_51h,
PERIPHC_52h,
PERIPHC_53h,
PERIPHC_SATAOOB,
PERIPHC_SATA,
PERIPHC_HDA,
PERIPHC_COUNT,
PERIPHC_NONE = -1,
};
/* Converts a clock number to a clock register: 0=L, 1=H, 2=U, 0=V, 1=W */
#define PERIPH_REG(id) \
(id < PERIPH_ID_VW_FIRST) ? \
((id) >> 5) : ((id - PERIPH_ID_VW_FIRST) >> 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_id_is_pll(id) ((id) >= CLOCK_ID_FIRST && (id) < CLOCK_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)
#endif /* _TEGRA114_CLOCK_TABLES_H_ */

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra114 clock control functions */
#ifndef _TEGRA114_CLOCK_H_
#define _TEGRA114_CLOCK_H_
#include <asm/arch-tegra/clock.h>
/* CLK_RST_CONTROLLER_OSC_CTRL_0 */
#define OSC_FREQ_SHIFT 28
#define OSC_FREQ_MASK (0xF << OSC_FREQ_SHIFT)
#endif /* _TEGRA114_CLOCK_H_ */

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TEGRA114_FLOW_H_
#define _TEGRA114_FLOW_H_
struct flow_ctlr {
u32 halt_cpu_events;
u32 halt_cop_events;
u32 cpu_csr;
u32 cop_csr;
u32 xrq_events;
u32 halt_cpu1_events;
u32 cpu1_csr;
u32 halt_cpu2_events;
u32 cpu2_csr;
u32 halt_cpu3_events;
u32 cpu3_csr;
u32 cluster_control;
};
#endif /* _TEGRA114_FLOW_H_ */

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
/* Tegra114 high-level function multiplexing */
#ifndef _TEGRA114_FUNCMUX_H_
#define _TEGRA114_FUNCMUX_H_
#include <asm/arch-tegra/funcmux.h>
/* Configs supported by the func mux */
enum {
FUNCMUX_DEFAULT = 0, /* default config */
/* UART configs */
FUNCMUX_UART4_GMI = 0,
};
#endif /* _TEGRA114_FUNCMUX_H_ */

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TEGRA114_GP_PADCTRL_H_
#define _TEGRA114_GP_PADCTRL_H_
#include <asm/arch-tegra/gp_padctrl.h>
/* APB_MISC_GP and padctrl registers */
struct apb_misc_gp_ctlr {
u32 modereg; /* 0x00: APB_MISC_GP_MODEREG */
u32 hidrev; /* 0x04: APB_MISC_GP_HIDREV */
u32 reserved0[22]; /* 0x08 - 0x5C: */
u32 emu_revid; /* 0x60: APB_MISC_GP_EMU_REVID */
u32 xactor_scratch; /* 0x64: APB_MISC_GP_XACTOR_SCRATCH */
u32 aocfg1; /* 0x68: APB_MISC_GP_AOCFG1PADCTRL */
u32 aocfg2; /* 0x6c: APB_MISC_GP_AOCFG2PADCTRL */
u32 atcfg1; /* 0x70: APB_MISC_GP_ATCFG1PADCTRL */
u32 atcfg2; /* 0x74: APB_MISC_GP_ATCFG2PADCTRL */
u32 atcfg3; /* 0x78: APB_MISC_GP_ATCFG3PADCTRL */
u32 atcfg4; /* 0x7C: APB_MISC_GP_ATCFG4PADCTRL */
u32 atcfg5; /* 0x80: APB_MISC_GP_ATCFG5PADCTRL */
u32 cdev1cfg; /* 0x84: APB_MISC_GP_CDEV1CFGPADCTRL */
u32 cdev2cfg; /* 0x88: APB_MISC_GP_CDEV2CFGPADCTRL */
u32 csuscfg; /* 0x8C: APB_MISC_GP_CSUSCFGPADCTRL */
u32 dap1cfg; /* 0x90: APB_MISC_GP_DAP1CFGPADCTRL */
u32 dap2cfg; /* 0x94: APB_MISC_GP_DAP2CFGPADCTRL */
u32 dap3cfg; /* 0x98: APB_MISC_GP_DAP3CFGPADCTRL */
u32 dap4cfg; /* 0x9C: APB_MISC_GP_DAP4CFGPADCTRL */
u32 dbgcfg; /* 0xA0: APB_MISC_GP_DBGCFGPADCTRL */
u32 lcdcfg1; /* 0xA4: APB_MISC_GP_LCDCFG1PADCTRL */
u32 lcdcfg2; /* 0xA8: APB_MISC_GP_LCDCFG2PADCTRL */
u32 sdio2cfg; /* 0xAC: APB_MISC_GP_SDIO2CFGPADCTRL */
u32 sdio3cfg; /* 0xB0: APB_MISC_GP_SDIO3CFGPADCTRL */
u32 spicfg; /* 0xB4: APB_MISC_GP_SPICFGPADCTRL */
u32 uaacfg; /* 0xB8: APB_MISC_GP_UAACFGPADCTRL */
u32 uabcfg; /* 0xBC: APB_MISC_GP_UABCFGPADCTRL */
u32 uart2cfg; /* 0xC0: APB_MISC_GP_UART2CFGPADCTRL */
u32 uart3cfg; /* 0xC4: APB_MISC_GP_UART3CFGPADCTRL */
u32 vicfg1; /* 0xC8: APB_MISC_GP_VICFG1PADCTRL */
u32 vivttgen; /* 0xCC: APB_MISC_GP_VIVTTGENPADCTRL */
u32 reserved1[7]; /* 0xD0-0xE8: */
u32 sdio1cfg; /* 0xEC: APB_MISC_GP_SDIO1CFGPADCTRL */
};
#endif /* _TEGRA114_GP_PADCTRL_H_ */

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TEGRA114_GPIO_H_
#define _TEGRA114_GPIO_H_
/*
* The Tegra114 GPIO controller has 246 GPIOS in 8 banks of 4 ports,
* each with 8 GPIOs.
*/
#define TEGRA_GPIO_PORTS 4 /* number of ports per bank */
#define TEGRA_GPIO_BANKS 8 /* number of banks */
#include <asm/arch-tegra/gpio.h>
#include <asm/arch-tegra30/gpio.h>
#endif /* _TEGRA114_GPIO_H_ */

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TEGRA114_HARDWARE_H_
#define _TEGRA114_HARDWARE_H_
/* include tegra specific hardware definitions */
#endif /* _TEGRA114_HARDWARE_H_ */

View file

@ -0,0 +1,618 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TEGRA114_PINMUX_H_
#define _TEGRA114_PINMUX_H_
/*
* Pin groups which we adjust. There are three basic attributes of each pin
* group which use this enum:
*
* - function
* - pullup / pulldown
* - tristate or normal
*/
enum pmux_pingrp {
PINGRP_ULPI_DATA0 = 0, /* offset 0x3000 */
PINGRP_ULPI_DATA1,
PINGRP_ULPI_DATA2,
PINGRP_ULPI_DATA3,
PINGRP_ULPI_DATA4,
PINGRP_ULPI_DATA5,
PINGRP_ULPI_DATA6,
PINGRP_ULPI_DATA7,
PINGRP_ULPI_CLK,
PINGRP_ULPI_DIR,
PINGRP_ULPI_NXT,
PINGRP_ULPI_STP,
PINGRP_DAP3_FS,
PINGRP_DAP3_DIN,
PINGRP_DAP3_DOUT,
PINGRP_DAP3_SCLK,
PINGRP_GPIO_PV0,
PINGRP_GPIO_PV1,
PINGRP_SDMMC1_CLK,
PINGRP_SDMMC1_CMD,
PINGRP_SDMMC1_DAT3,
PINGRP_SDMMC1_DAT2,
PINGRP_SDMMC1_DAT1,
PINGRP_SDMMC1_DAT0,
PINGRP_GPIO_PV2,
PINGRP_GPIO_PV3,
PINGRP_CLK2_OUT,
PINGRP_CLK2_REQ,
PINGRP_LCD_PWR1,
PINGRP_LCD_PWR2,
PINGRP_LCD_SDIN,
PINGRP_LCD_SDOUT,
PINGRP_LCD_WR_N,
PINGRP_LCD_CS0_N,
PINGRP_LCD_DC0,
PINGRP_LCD_SCK,
PINGRP_LCD_PWR0,
PINGRP_LCD_PCLK,
PINGRP_LCD_DE,
PINGRP_LCD_HSYNC,
PINGRP_LCD_VSYNC,
PINGRP_LCD_D0,
PINGRP_LCD_D1,
PINGRP_LCD_D2,
PINGRP_LCD_D3,
PINGRP_LCD_D4,
PINGRP_LCD_D5,
PINGRP_LCD_D6,
PINGRP_LCD_D7,
PINGRP_LCD_D8,
PINGRP_LCD_D9,
PINGRP_LCD_D10,
PINGRP_LCD_D11,
PINGRP_LCD_D12,
PINGRP_LCD_D13,
PINGRP_LCD_D14,
PINGRP_LCD_D15,
PINGRP_LCD_D16,
PINGRP_LCD_D17,
PINGRP_LCD_D18,
PINGRP_LCD_D19,
PINGRP_LCD_D20,
PINGRP_LCD_D21,
PINGRP_LCD_D22,
PINGRP_LCD_D23,
PINGRP_LCD_CS1_N,
PINGRP_LCD_M1,
PINGRP_LCD_DC1,
PINGRP_HDMI_INT,
PINGRP_DDC_SCL,
PINGRP_DDC_SDA,
PINGRP_CRT_HSYNC,
PINGRP_CRT_VSYNC,
PINGRP_VI_D0,
PINGRP_VI_D1,
PINGRP_VI_D2,
PINGRP_VI_D3,
PINGRP_VI_D4,
PINGRP_VI_D5,
PINGRP_VI_D6,
PINGRP_VI_D7,
PINGRP_VI_D8,
PINGRP_VI_D9,
PINGRP_VI_D10,
PINGRP_VI_D11,
PINGRP_VI_PCLK,
PINGRP_VI_MCLK,
PINGRP_VI_VSYNC,
PINGRP_VI_HSYNC,
PINGRP_UART2_RXD,
PINGRP_UART2_TXD,
PINGRP_UART2_RTS_N,
PINGRP_UART2_CTS_N,
PINGRP_UART3_TXD,
PINGRP_UART3_RXD,
PINGRP_UART3_CTS_N,
PINGRP_UART3_RTS_N,
PINGRP_GPIO_PU0,
PINGRP_GPIO_PU1,
PINGRP_GPIO_PU2,
PINGRP_GPIO_PU3,
PINGRP_GPIO_PU4,
PINGRP_GPIO_PU5,
PINGRP_GPIO_PU6,
PINGRP_GEN1_I2C_SDA,
PINGRP_GEN1_I2C_SCL,
PINGRP_DAP4_FS,
PINGRP_DAP4_DIN,
PINGRP_DAP4_DOUT,
PINGRP_DAP4_SCLK,
PINGRP_CLK3_OUT,
PINGRP_CLK3_REQ,
PINGRP_GMI_WP_N,
PINGRP_GMI_IORDY,
PINGRP_GMI_WAIT,
PINGRP_GMI_ADV_N,
PINGRP_GMI_CLK,
PINGRP_GMI_CS0_N,
PINGRP_GMI_CS1_N,
PINGRP_GMI_CS2_N,
PINGRP_GMI_CS3_N,
PINGRP_GMI_CS4_N,
PINGRP_GMI_CS6_N,
PINGRP_GMI_CS7_N,
PINGRP_GMI_AD0,
PINGRP_GMI_AD1,
PINGRP_GMI_AD2,
PINGRP_GMI_AD3,
PINGRP_GMI_AD4,
PINGRP_GMI_AD5,
PINGRP_GMI_AD6,
PINGRP_GMI_AD7,
PINGRP_GMI_AD8,
PINGRP_GMI_AD9,
PINGRP_GMI_AD10,
PINGRP_GMI_AD11,
PINGRP_GMI_AD12,
PINGRP_GMI_AD13,
PINGRP_GMI_AD14,
PINGRP_GMI_AD15,
PINGRP_GMI_A16,
PINGRP_GMI_A17,
PINGRP_GMI_A18,
PINGRP_GMI_A19,
PINGRP_GMI_WR_N,
PINGRP_GMI_OE_N,
PINGRP_GMI_DQS,
PINGRP_GMI_RST_N,
PINGRP_GEN2_I2C_SCL,
PINGRP_GEN2_I2C_SDA,
PINGRP_SDMMC4_CLK,
PINGRP_SDMMC4_CMD,
PINGRP_SDMMC4_DAT0,
PINGRP_SDMMC4_DAT1,
PINGRP_SDMMC4_DAT2,
PINGRP_SDMMC4_DAT3,
PINGRP_SDMMC4_DAT4,
PINGRP_SDMMC4_DAT5,
PINGRP_SDMMC4_DAT6,
PINGRP_SDMMC4_DAT7,
PINGRP_SDMMC4_RST_N,
PINGRP_CAM_MCLK,
PINGRP_GPIO_PCC1,
PINGRP_GPIO_PBB0,
PINGRP_CAM_I2C_SCL,
PINGRP_CAM_I2C_SDA,
PINGRP_GPIO_PBB3,
PINGRP_GPIO_PBB4,
PINGRP_GPIO_PBB5,
PINGRP_GPIO_PBB6,
PINGRP_GPIO_PBB7,
PINGRP_GPIO_PCC2,
PINGRP_JTAG_RTCK,
PINGRP_PWR_I2C_SCL,
PINGRP_PWR_I2C_SDA,
PINGRP_KB_ROW0,
PINGRP_KB_ROW1,
PINGRP_KB_ROW2,
PINGRP_KB_ROW3,
PINGRP_KB_ROW4,
PINGRP_KB_ROW5,
PINGRP_KB_ROW6,
PINGRP_KB_ROW7,
PINGRP_KB_ROW8,
PINGRP_KB_ROW9,
PINGRP_KB_ROW10,
PINGRP_KB_ROW11,
PINGRP_KB_ROW12,
PINGRP_KB_ROW13,
PINGRP_KB_ROW14,
PINGRP_KB_ROW15,
PINGRP_KB_COL0,
PINGRP_KB_COL1,
PINGRP_KB_COL2,
PINGRP_KB_COL3,
PINGRP_KB_COL4,
PINGRP_KB_COL5,
PINGRP_KB_COL6,
PINGRP_KB_COL7,
PINGRP_CLK_32K_OUT,
PINGRP_SYS_CLK_REQ,
PINGRP_CORE_PWR_REQ,
PINGRP_CPU_PWR_REQ,
PINGRP_PWR_INT_N,
PINGRP_CLK_32K_IN,
PINGRP_OWR,
PINGRP_DAP1_FS,
PINGRP_DAP1_DIN,
PINGRP_DAP1_DOUT,
PINGRP_DAP1_SCLK,
PINGRP_CLK1_REQ,
PINGRP_CLK1_OUT,
PINGRP_SPDIF_IN,
PINGRP_SPDIF_OUT,
PINGRP_DAP2_FS,
PINGRP_DAP2_DIN,
PINGRP_DAP2_DOUT,
PINGRP_DAP2_SCLK,
PINGRP_SPI2_MOSI,
PINGRP_SPI2_MISO,
PINGRP_SPI2_CS0_N,
PINGRP_SPI2_SCK,
PINGRP_SPI1_MOSI,
PINGRP_SPI1_SCK,
PINGRP_SPI1_CS0_N,
PINGRP_SPI1_MISO,
PINGRP_SPI2_CS1_N,
PINGRP_SPI2_CS2_N,
PINGRP_SDMMC3_CLK,
PINGRP_SDMMC3_CMD,
PINGRP_SDMMC3_DAT0,
PINGRP_SDMMC3_DAT1,
PINGRP_SDMMC3_DAT2,
PINGRP_SDMMC3_DAT3,
PINGRP_SDMMC3_DAT4,
PINGRP_SDMMC3_DAT5,
PINGRP_SDMMC3_DAT6,
PINGRP_SDMMC3_DAT7,
PINGRP_PEX_L0_PRSNT_N,
PINGRP_PEX_L0_RST_N,
PINGRP_PEX_L0_CLKREQ_N,
PINGRP_PEX_WAKE_N,
PINGRP_PEX_L1_PRSNT_N,
PINGRP_PEX_L1_RST_N,
PINGRP_PEX_L1_CLKREQ_N,
PINGRP_PEX_L2_PRSNT_N,
PINGRP_PEX_L2_RST_N,
PINGRP_PEX_L2_CLKREQ_N,
PINGRP_HDMI_CEC, /* offset 0x33e0 */
PINGRP_SDMMC1_WP_N,
PINGRP_SDMMC3_CD_N,
PINGRP_SPI1_CS1_N,
PINGRP_SPI1_CS2_N,
PINGRP_USB_VBUS_EN0, /* offset 0x33f4 */
PINGRP_USB_VBUS_EN1,
PINGRP_SDMMC3_CLK_LB_IN,
PINGRP_SDMMC3_CLK_LB_OUT,
PINGRP_NAND_GMI_CLK_LB,
PINGRP_RESET_OUT_N,
PINGRP_COUNT,
};
enum pdrive_pingrp {
PDRIVE_PINGROUP_AO1 = 0, /* offset 0x868 */
PDRIVE_PINGROUP_AO2,
PDRIVE_PINGROUP_AT1,
PDRIVE_PINGROUP_AT2,
PDRIVE_PINGROUP_AT3,
PDRIVE_PINGROUP_AT4,
PDRIVE_PINGROUP_AT5,
PDRIVE_PINGROUP_CDEV1,
PDRIVE_PINGROUP_CDEV2,
PDRIVE_PINGROUP_CSUS,
PDRIVE_PINGROUP_DAP1,
PDRIVE_PINGROUP_DAP2,
PDRIVE_PINGROUP_DAP3,
PDRIVE_PINGROUP_DAP4,
PDRIVE_PINGROUP_DBG,
PDRIVE_PINGROUP_LCD1,
PDRIVE_PINGROUP_LCD2,
PDRIVE_PINGROUP_SDIO2,
PDRIVE_PINGROUP_SDIO3,
PDRIVE_PINGROUP_SPI,
PDRIVE_PINGROUP_UAA,
PDRIVE_PINGROUP_UAB,
PDRIVE_PINGROUP_UART2,
PDRIVE_PINGROUP_UART3,
PDRIVE_PINGROUP_VI1 = 24, /* offset 0x8c8 */
PDRIVE_PINGROUP_SDIO1 = 33, /* offset 0x8ec */
PDRIVE_PINGROUP_CRT = 36, /* offset 0x8f8 */
PDRIVE_PINGROUP_DDC,
PDRIVE_PINGROUP_GMA,
PDRIVE_PINGROUP_GMB,
PDRIVE_PINGROUP_GMC,
PDRIVE_PINGROUP_GMD,
PDRIVE_PINGROUP_GME,
PDRIVE_PINGROUP_GMF,
PDRIVE_PINGROUP_GMG,
PDRIVE_PINGROUP_GMH,
PDRIVE_PINGROUP_OWR,
PDRIVE_PINGROUP_UAD,
PDRIVE_PINGROUP_GPV,
PDRIVE_PINGROUP_DEV3 = 49, /* offset 0x92c */
PDRIVE_PINGROUP_CEC = 52, /* offset 0x938 */
PDRIVE_PINGROUP_AT6,
PDRIVE_PINGROUP_DAP5,
PDRIVE_PINGROUP_VBUS,
PDRIVE_PINGROUP_COUNT,
};
/*
* Functions which can be assigned to each of the pin groups. The values here
* bear no relation to the values programmed into pinmux registers and are
* purely a convenience. The translation is done through a table search.
*/
enum pmux_func {
PMUX_FUNC_AHB_CLK,
PMUX_FUNC_APB_CLK,
PMUX_FUNC_AUDIO_SYNC,
PMUX_FUNC_CRT,
PMUX_FUNC_DAP1,
PMUX_FUNC_DAP2,
PMUX_FUNC_DAP3,
PMUX_FUNC_DAP4,
PMUX_FUNC_DAP5,
PMUX_FUNC_DISPA,
PMUX_FUNC_DISPB,
PMUX_FUNC_EMC_TEST0_DLL,
PMUX_FUNC_EMC_TEST1_DLL,
PMUX_FUNC_GMI,
PMUX_FUNC_GMI_INT,
PMUX_FUNC_HDMI,
PMUX_FUNC_I2C1,
PMUX_FUNC_I2C2,
PMUX_FUNC_I2C3,
PMUX_FUNC_IDE,
PMUX_FUNC_KBC,
PMUX_FUNC_MIO,
PMUX_FUNC_MIPI_HS,
PMUX_FUNC_NAND,
PMUX_FUNC_OSC,
PMUX_FUNC_OWR,
PMUX_FUNC_PCIE,
PMUX_FUNC_PLLA_OUT,
PMUX_FUNC_PLLC_OUT1,
PMUX_FUNC_PLLM_OUT1,
PMUX_FUNC_PLLP_OUT2,
PMUX_FUNC_PLLP_OUT3,
PMUX_FUNC_PLLP_OUT4,
PMUX_FUNC_PWM,
PMUX_FUNC_PWR_INTR,
PMUX_FUNC_PWR_ON,
PMUX_FUNC_RTCK,
PMUX_FUNC_SDMMC1,
PMUX_FUNC_SDMMC2,
PMUX_FUNC_SDMMC3,
PMUX_FUNC_SDMMC4,
PMUX_FUNC_SFLASH,
PMUX_FUNC_SPDIF,
PMUX_FUNC_SPI1,
PMUX_FUNC_SPI2,
PMUX_FUNC_SPI2_ALT,
PMUX_FUNC_SPI3,
PMUX_FUNC_SPI4,
PMUX_FUNC_TRACE,
PMUX_FUNC_TWC,
PMUX_FUNC_UARTA,
PMUX_FUNC_UARTB,
PMUX_FUNC_UARTC,
PMUX_FUNC_UARTD,
PMUX_FUNC_UARTE,
PMUX_FUNC_ULPI,
PMUX_FUNC_VI,
PMUX_FUNC_VI_SENSOR_CLK,
PMUX_FUNC_XIO,
PMUX_FUNC_BLINK,
PMUX_FUNC_CEC,
PMUX_FUNC_CLK12,
PMUX_FUNC_DAP,
PMUX_FUNC_DAPSDMMC2,
PMUX_FUNC_DDR,
PMUX_FUNC_DEV3,
PMUX_FUNC_DTV,
PMUX_FUNC_VI_ALT1,
PMUX_FUNC_VI_ALT2,
PMUX_FUNC_VI_ALT3,
PMUX_FUNC_EMC_DLL,
PMUX_FUNC_EXTPERIPH1,
PMUX_FUNC_EXTPERIPH2,
PMUX_FUNC_EXTPERIPH3,
PMUX_FUNC_GMI_ALT,
PMUX_FUNC_HDA,
PMUX_FUNC_HSI,
PMUX_FUNC_I2C4,
PMUX_FUNC_I2C5,
PMUX_FUNC_I2CPWR,
PMUX_FUNC_I2S0,
PMUX_FUNC_I2S1,
PMUX_FUNC_I2S2,
PMUX_FUNC_I2S3,
PMUX_FUNC_I2S4,
PMUX_FUNC_NAND_ALT,
PMUX_FUNC_POPSDIO4,
PMUX_FUNC_POPSDMMC4,
PMUX_FUNC_PWM0,
PMUX_FUNC_PWM1,
PMUX_FUNC_PWM2,
PMUX_FUNC_PWM3,
PMUX_FUNC_SATA,
PMUX_FUNC_SPI5,
PMUX_FUNC_SPI6,
PMUX_FUNC_SYSCLK,
PMUX_FUNC_VGP1,
PMUX_FUNC_VGP2,
PMUX_FUNC_VGP3,
PMUX_FUNC_VGP4,
PMUX_FUNC_VGP5,
PMUX_FUNC_VGP6,
PMUX_FUNC_USB,
PMUX_FUNC_SOC,
PMUX_FUNC_CPU,
PMUX_FUNC_CLK,
PMUX_FUNC_PWRON,
PMUX_FUNC_PMI,
PMUX_FUNC_CLDVFS,
PMUX_FUNC_RESET_OUT_N,
PMUX_FUNC_SAFE,
PMUX_FUNC_MAX,
PMUX_FUNC_RSVD1 = 0x8000,
PMUX_FUNC_RSVD2 = 0x8001,
PMUX_FUNC_RSVD3 = 0x8002,
PMUX_FUNC_RSVD4 = 0x8003,
};
/* return 1 if a pmux_func is in range */
#define pmux_func_isvalid(func) ((((func) >= 0) && ((func) < PMUX_FUNC_MAX)) \
|| (((func) >= PMUX_FUNC_RSVD1) && ((func) <= PMUX_FUNC_RSVD4)))
/* return 1 if a pingrp is in range */
#define pmux_pingrp_isvalid(pin) (((pin) >= 0) && ((pin) < PINGRP_COUNT))
/* The pullup/pulldown state of a pin group */
enum pmux_pull {
PMUX_PULL_NORMAL = 0,
PMUX_PULL_DOWN,
PMUX_PULL_UP,
};
/* return 1 if a pin_pupd_is in range */
#define pmux_pin_pupd_isvalid(pupd) (((pupd) >= PMUX_PULL_NORMAL) && \
((pupd) <= PMUX_PULL_UP))
/* Defines whether a pin group is tristated or in normal operation */
enum pmux_tristate {
PMUX_TRI_NORMAL = 0,
PMUX_TRI_TRISTATE = 1,
};
/* return 1 if a pin_tristate_is in range */
#define pmux_pin_tristate_isvalid(tristate) (((tristate) >= PMUX_TRI_NORMAL) \
&& ((tristate) <= PMUX_TRI_TRISTATE))
enum pmux_pin_io {
PMUX_PIN_OUTPUT = 0,
PMUX_PIN_INPUT = 1,
};
/* return 1 if a pin_io_is in range */
#define pmux_pin_io_isvalid(io) (((io) >= PMUX_PIN_OUTPUT) && \
((io) <= PMUX_PIN_INPUT))
enum pmux_pin_lock {
PMUX_PIN_LOCK_DEFAULT = 0,
PMUX_PIN_LOCK_DISABLE,
PMUX_PIN_LOCK_ENABLE,
};
/* return 1 if a pin_lock is in range */
#define pmux_pin_lock_isvalid(lock) (((lock) >= PMUX_PIN_LOCK_DEFAULT) && \
((lock) <= PMUX_PIN_LOCK_ENABLE))
enum pmux_pin_od {
PMUX_PIN_OD_DEFAULT = 0,
PMUX_PIN_OD_DISABLE,
PMUX_PIN_OD_ENABLE,
};
/* return 1 if a pin_od is in range */
#define pmux_pin_od_isvalid(od) (((od) >= PMUX_PIN_OD_DEFAULT) && \
((od) <= PMUX_PIN_OD_ENABLE))
enum pmux_pin_ioreset {
PMUX_PIN_IO_RESET_DEFAULT = 0,
PMUX_PIN_IO_RESET_DISABLE,
PMUX_PIN_IO_RESET_ENABLE,
};
/* return 1 if a pin_ioreset_is in range */
#define pmux_pin_ioreset_isvalid(ioreset) \
(((ioreset) >= PMUX_PIN_IO_RESET_DEFAULT) && \
((ioreset) <= PMUX_PIN_IO_RESET_ENABLE))
/* Available power domains used by pin groups */
enum pmux_vddio {
PMUX_VDDIO_BB = 0,
PMUX_VDDIO_LCD,
PMUX_VDDIO_VI,
PMUX_VDDIO_UART,
PMUX_VDDIO_DDR,
PMUX_VDDIO_NAND,
PMUX_VDDIO_SYS,
PMUX_VDDIO_AUDIO,
PMUX_VDDIO_SD,
PMUX_VDDIO_CAM,
PMUX_VDDIO_GMI,
PMUX_VDDIO_PEXCTL,
PMUX_VDDIO_SDMMC1,
PMUX_VDDIO_SDMMC3,
PMUX_VDDIO_SDMMC4,
PMUX_VDDIO_NONE
};
/* T114 pin drive group and pin mux registers */
#define PDRIVE_PINGROUP_OFFSET (0x868 >> 2)
#define PMUX_OFFSET ((0x3000 >> 2) - PDRIVE_PINGROUP_OFFSET - \
PDRIVE_PINGROUP_COUNT)
struct pmux_tri_ctlr {
uint pmt_reserved0; /* ABP_MISC_PP_ reserved offset 00 */
uint pmt_reserved1; /* ABP_MISC_PP_ reserved offset 04 */
uint pmt_strap_opt_a; /* _STRAPPING_OPT_A_0, offset 08 */
uint pmt_reserved2; /* ABP_MISC_PP_ reserved offset 0C */
uint pmt_reserved3; /* ABP_MISC_PP_ reserved offset 10 */
uint pmt_reserved4[4]; /* _TRI_STATE_REG_A/B/C/D in t20 */
uint pmt_cfg_ctl; /* _CONFIG_CTL_0, offset 24 */
uint pmt_reserved[528]; /* ABP_MISC_PP_ reserved offs 28-864 */
uint pmt_drive[PDRIVE_PINGROUP_COUNT]; /* pin drive grps offs 868 */
uint pmt_reserved5[PMUX_OFFSET];
uint pmt_ctl[PINGRP_COUNT]; /* mux/pupd/tri regs, offset 0x3000 */
};
/*
* This defines the configuration for a pin, including the function assigned,
* pull up/down settings and tristate settings. Having set up one of these
* you can call pinmux_config_pingroup() to configure a pin in one step. Also
* available is pinmux_config_table() to configure a list of pins.
*/
struct pingroup_config {
enum pmux_pingrp pingroup; /* pin group PINGRP_... */
enum pmux_func func; /* function to assign FUNC_... */
enum pmux_pull pull; /* pull up/down/normal PMUX_PULL_...*/
enum pmux_tristate tristate; /* tristate or normal PMUX_TRI_... */
enum pmux_pin_io io; /* input or output PMUX_PIN_... */
enum pmux_pin_lock lock; /* lock enable/disable PMUX_PIN... */
enum pmux_pin_od od; /* open-drain or push-pull driver */
enum pmux_pin_ioreset ioreset; /* input/output reset PMUX_PIN... */
};
/* Set a pin group to tristate */
void pinmux_tristate_enable(enum pmux_pingrp pin);
/* Set a pin group to normal (non tristate) */
void pinmux_tristate_disable(enum pmux_pingrp pin);
/* Set the pull up/down feature for a pin group */
void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd);
/* Set the mux function for a pin group */
void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func);
/* Set the complete configuration for a pin group */
void pinmux_config_pingroup(struct pingroup_config *config);
/* Set a pin group to tristate or normal */
void pinmux_set_tristate(enum pmux_pingrp pin, int enable);
/* Set a pin group as input or output */
void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io);
/**
* Configure a list of pin groups
*
* @param config List of config items
* @param len Number of config items in list
*/
void pinmux_config_table(struct pingroup_config *config, int len);
/* Set a group of pins from a table */
void pinmux_init(void);
#endif /* _TEGRA114_PINMUX_H_ */

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TEGRA114_PMU_H_
#define _TEGRA114_PMU_H_
/* Set core and CPU voltages to nominal levels */
int pmu_set_nominal(void);
#endif /* _TEGRA114_PMU_H_ */

Some files were not shown because too many files have changed in this diff Show more