Skip to content
Snippets Groups Projects
Commit b2871037 authored by Tom Warren's avatar Tom Warren Committed by Tom Warren
Browse files

Tegra30: Add common CPU (shared) files


These files are used by both SPL and main U-Boot.
Also made minor changes to shared Tegra code to support
T30 differences.

Signed-off-by: default avatarTom Warren <twarren@nvidia.com>
Reviewed-by: default avatarStephen Warren <swarren@nvidia.com>
parent 5576aab5
No related branches found
No related tags found
No related merge requests found
...@@ -20,10 +20,14 @@ ...@@ -20,10 +20,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA * MA 02111-1307 USA
*/ */
/* Tegra AP (Application Processor) code */
#include <common.h> #include <common.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/gp_padctrl.h> #include <asm/arch/gp_padctrl.h>
#include <asm/arch-tegra/ap.h> #include <asm/arch-tegra/ap.h>
#include <asm/arch-tegra/clock.h>
#include <asm/arch-tegra/fuse.h> #include <asm/arch-tegra/fuse.h>
#include <asm/arch-tegra/pmc.h> #include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/scu.h> #include <asm/arch-tegra/scu.h>
...@@ -58,6 +62,12 @@ int tegra_get_chip_type(void) ...@@ -58,6 +62,12 @@ int tegra_get_chip_type(void)
return TEGRA_SOC_T25; return TEGRA_SOC_T25;
} }
break; break;
case CHIPID_TEGRA30:
switch (tegra_sku_id) {
case SKU_ID_T30:
return TEGRA_SOC_T30;
}
break;
} }
/* unknown sku id */ /* unknown sku id */
return TEGRA_SOC_UNKNOWN; return TEGRA_SOC_UNKNOWN;
...@@ -93,7 +103,7 @@ static u32 get_odmdata(void) ...@@ -93,7 +103,7 @@ static u32 get_odmdata(void)
u32 bct_start, odmdata; 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); odmdata = readl(bct_start + BCT_ODMDATA_OFFSET);
return odmdata; return odmdata;
...@@ -127,5 +137,5 @@ void s_init(void) ...@@ -127,5 +137,5 @@ void s_init(void)
"orr r0, r0, #0x41\n" "orr r0, r0, #0x41\n"
"mcr p15, 0, r0, c1, c0, 1\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? */
} }
...@@ -54,16 +54,37 @@ unsigned int query_sdram_size(void) ...@@ -54,16 +54,37 @@ unsigned int query_sdram_size(void)
reg = readl(&pmc->pmc_scratch20); reg = readl(&pmc->pmc_scratch20);
debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg); 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) { switch ((reg) >> 28) {
case 1: case 1:
return 0x10000000; /* 256 MB */ return 0x10000000; /* 256 MB */
case 0:
case 2: case 2:
default: default:
return 0x20000000; /* 512 MB */ return 0x20000000; /* 512 MB */
case 3: case 3:
return 0x40000000; /* 1GB */ return 0x40000000; /* 1GB */
} }
#else /* Tegra30 */
/* 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) int dram_init(void)
...@@ -82,19 +103,27 @@ int checkboard(void) ...@@ -82,19 +103,27 @@ int checkboard(void)
#endif /* CONFIG_DISPLAY_BOARDINFO */ #endif /* CONFIG_DISPLAY_BOARDINFO */
static int uart_configs[] = { 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, FUNCMUX_UART1_UAA_UAB,
#elif defined(CONFIG_TEGRA_UARTA_GPU) #elif defined(CONFIG_TEGRA_UARTA_GPU)
FUNCMUX_UART1_GPU, FUNCMUX_UART1_GPU,
#elif defined(CONFIG_TEGRA_UARTA_SDIO1) #elif defined(CONFIG_TEGRA_UARTA_SDIO1)
FUNCMUX_UART1_SDIO1, FUNCMUX_UART1_SDIO1,
#else #else
FUNCMUX_UART1_IRRX_IRTX, FUNCMUX_UART1_IRRX_IRTX,
#endif #endif
FUNCMUX_UART2_IRDA, FUNCMUX_UART2_IRDA,
-1, -1,
FUNCMUX_UART4_GMC, FUNCMUX_UART4_GMC,
-1, -1,
#else /* Tegra30 */
FUNCMUX_UART1_ULPI, /* UARTA */
-1,
-1,
-1,
-1,
#endif
}; };
/** /**
......
...@@ -22,12 +22,26 @@ ...@@ -22,12 +22,26 @@
*/ */
#include <common.h> #include <common.h>
#include <linux/ctype.h>
#ifdef CONFIG_DISPLAY_CPUINFO #ifdef CONFIG_DISPLAY_CPUINFO
void upstring(char *s)
{
while (*s) {
*s = toupper(*s);
s++;
}
}
/* Print CPU information */ /* Print CPU information */
int print_cpuinfo(void) 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. */ /* TBD: Add printf of major/minor rev info, stepping, etc. */
return 0; return 0;
......
...@@ -46,7 +46,7 @@ DECLARE_GLOBAL_DATA_PTR; ...@@ -46,7 +46,7 @@ DECLARE_GLOBAL_DATA_PTR;
* This is the place in SRAM where the SDRAM parameters are stored. There * This is the place in SRAM where the SDRAM parameters are stored. There
* are 4 blocks, one for each RAM code * 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 */ /* TODO: If we later add support for the Misc GP controller, refactor this */
union xm2cfga_reg { union xm2cfga_reg {
......
#
# 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
#########################################################################
/*
* 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 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,
};
/*
* Clock types that we can use as a source. The Tegra3 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_PDCT,
CLOCK_TYPE_ACPT,
CLOCK_TYPE_ASPTE,
CLOCK_TYPE_PMDACD2T,
CLOCK_TYPE_PCST,
CLOCK_TYPE_COUNT,
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 = 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(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}
};
/* 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
*/
#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),
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_PCMT),
TYPE(PERIPHC_DVC_I2C, CLOCK_TYPE_PCMT),
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),
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_PCMT),
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_PCMT),
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 */
TYPE(PERIPHC_G3D2, CLOCK_TYPE_MCPA),
TYPE(PERIPHC_MSELECT, CLOCK_TYPE_PCMT),
TYPE(PERIPHC_TSENSOR, CLOCK_TYPE_PCM),
TYPE(PERIPHC_I2S3, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_I2S4, CLOCK_TYPE_AXPT),
TYPE(PERIPHC_I2C4, CLOCK_TYPE_PCMT),
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_PCM),
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_PCMT),
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_SATAOOB, CLOCK_TYPE_PCMT),
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),
NONE(SBC1), /* SBC1, 0x34, is this SPI1? */
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.
*/
enum clock_osc_freq clock_get_osc_freq(void)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
u32 reg;
reg = readl(&clkrst->crc_osc_ctrl);
return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
}
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;
}
/* Returns a pointer to the clock source register for a peripheral */
static 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];
}
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);
}
/**
* 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.
*
* 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)
*/
static 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];
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;
}
/**
* 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, source;
int divider, divider_bits = 0;
/* 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 =
(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 clock_enable(enum periph_id clkid)
{
clock_set_enable(clkid, 1);
}
void clock_disable(enum periph_id clkid)
{
clock_set_enable(clkid, 0);
}
void reset_set_enable(enum periph_id periph_id, int enable)
{
struct clk_rst_ctlr *clkrst =
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
u32 *reset;
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);
}
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. Tegra3 has 4 */
assert(cpu >= 0 && cpu < 4);
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
* the same but we are very cautious so we check that a valid clock ID is
* provided.
*
* @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)
{
if (clk_id > 95)
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:
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("PLLP %x is correct\n", reg);
return 0;
}
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;
}
}
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]);
}
/*
* 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;
}
/*
* 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]);
}
...@@ -23,67 +23,27 @@ ...@@ -23,67 +23,27 @@
#include <asm/types.h> #include <asm/types.h>
/* Stabilization delays, in usec */ /* Stabilization delays, in usec */
#define PLL_STABILIZATION_DELAY (300) #define PLL_STABILIZATION_DELAY (300)
#define IO_STABILIZATION_DELAY (1000) #define IO_STABILIZATION_DELAY (1000)
#define NVBL_PLLP_KHZ (216000)
#define PLLX_ENABLED (1 << 30) #define PLLX_ENABLED (1 << 30)
#define CCLK_BURST_POLICY 0x20008888 #define CCLK_BURST_POLICY 0x20008888
#define SUPER_CCLK_DIVIDER 0x80000000 #define SUPER_CCLK_DIVIDER 0x80000000
/* Calculate clock fractional divider value from ref and target frequencies */ /* 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 */ /* 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 */ /* AVP/CPU ID */
#define PG_UP_TAG_0_PID_CPU 0x55555555 /* CPU aka "a9" aka "mpcore" */ #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; #define CORESIGHT_UNLOCK 0xC5ACCE55;
/* AP20-Specific Base Addresses */ /* AP base physical address of internal SRAM */
#define NV_PA_BASE_SRAM 0x40000000
/* 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 EXCEP_VECTOR_CPU_RESET_VECTOR (NV_PA_EVP_BASE + 0x100)
#define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0) #define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment