GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,57 @@
if TEGRA124
choice
prompt "Tegra124 board select"
optional
config TARGET_APALIS_TK1
bool "Toradex Apalis TK1 module"
select ARCH_SUPPORT_PSCI
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
config TARGET_JETSON_TK1
bool "NVIDIA Tegra124 Jetson TK1 board"
select ARCH_SUPPORT_PSCI
select BOARD_LATE_INIT
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
config TARGET_CEI_TK1_SOM
bool "Colorado Engineering Inc Tegra124 TK1-som board"
select BOARD_LATE_INIT
select CPU_V7_HAS_NONSEC if !SPL_BUILD
select CPU_V7_HAS_VIRT if !SPL_BUILD
help
The Colorado Engineering Tegra TK1-SOM is a very compact
(51mmx58mm) board that is functionally almost the same as
the Jetson TK1. The main differences are in which balls on
the SoC are assigned to which functions, and the PCIEe
configuration.
config TARGET_NYAN_BIG
bool "Google/NVIDIA Nyan-big Chromebook"
select BOARD_LATE_INIT
help
Nyan Big is a Tegra124 clamshell board that is very similar
to venice2, but it has a different panel, the sdcard CD and WP
sense are flipped, and it has a different revision of the AS3722
PMIC. The retail name is the Acer Chromebook 13 CB5-311-T7NN
(13.3-inch HD, NVIDIA Tegra K1, 2GB).
config TARGET_VENICE2
bool "NVIDIA Tegra124 Venice2"
select BOARD_LATE_INIT
endchoice
config SYS_SOC
default "tegra124"
source "board/cei/cei-tk1-som/Kconfig"
source "board/nvidia/jetson-tk1/Kconfig"
source "board/nvidia/nyan-big/Kconfig"
source "board/nvidia/venice2/Kconfig"
source "board/toradex/apalis-tk1/Kconfig"
endif
@@ -0,0 +1,19 @@
#
# (C) Copyright 2013-2014
# NVIDIA Corporation <www.nvidia.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_SPL_BUILD) += cpu.o
obj-y += clock.o
obj-y += funcmux.o
obj-y += pinmux.o
obj-y += pmc.o
obj-y += xusb-padctl.o
obj-y += ../xusb-padctl-common.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_ARMV7_NONSEC) += psci.o
endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,346 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2013
* NVIDIA Corporation <www.nvidia.com>
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/ahb.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 <asm/arch-tegra/ap.h>
#include "../cpu.h"
/* Tegra124-specific CPU init code */
static void enable_cpu_power_rail(void)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
debug("%s entry\n", __func__);
/* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */
pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6);
pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SDA_PZ7);
pmic_enable_cpu_vdd();
/*
* Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz),
* set it for 5ms as per SysEng (102MHz*5ms = 510000 (7C830h).
*/
writel(0x7C830, &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);
}
static void enable_cpu_clocks(void)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU];
u32 reg;
debug("%s entry\n", __func__);
/* Wait for PLL-X to lock */
do {
reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
debug("%s: PLLX base = 0x%08X\n", __func__, reg);
} while ((reg & (1 << pllinfo->lock_det)) == 0);
debug("%s: PLLX locked, delay for stable clocks\n", __func__);
/* Wait until all clocks are stable */
udelay(PLL_STABILIZATION_DELAY);
debug("%s: Setting CCLK_BURST and DIVIDER\n", __func__);
writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
debug("%s: Enabling clock to all CPUs\n", __func__);
/* Enable the clock to all CPUs */
reg = CLR_CPU3_CLK_STP | CLR_CPU2_CLK_STP | CLR_CPU1_CLK_STP |
CLR_CPU0_CLK_STP;
writel(reg, &clkrst->crc_clk_cpu_cmplx_clr);
debug("%s: Enabling main CPU complex clocks\n", __func__);
/* Always enable the main CPU complex clocks */
clock_enable(PERIPH_ID_CPU);
clock_enable(PERIPH_ID_CPULP);
clock_enable(PERIPH_ID_CPUG);
debug("%s: Done\n", __func__);
}
static void remove_cpu_resets(void)
{
struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
u32 reg;
debug("%s entry\n", __func__);
/* Take the slow and fast partitions out of reset */
reg = CLR_NONCPURESET;
writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr);
writel(reg, &clkrst->crc_rst_cpug_cmplx_clr);
/* Clear the SW-controlled reset of the slow cluster */
reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 |
CLR_L2RESET | CLR_PRESETDBG;
writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr);
/* Clear the SW-controlled reset of the fast cluster */
reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 |
CLR_CPURESET1 | CLR_DBGRESET1 | CLR_CORERESET1 | CLR_CXRESET1 |
CLR_CPURESET2 | CLR_DBGRESET2 | CLR_CORERESET2 | CLR_CXRESET2 |
CLR_CPURESET3 | CLR_DBGRESET3 | CLR_CORERESET3 | CLR_CXRESET3 |
CLR_L2RESET | CLR_PRESETDBG;
writel(reg, &clkrst->crc_rst_cpug_cmplx_clr);
}
static void tegra124_ram_repair(void)
{
struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
u32 ram_repair_timeout; /*usec*/
u32 val;
/*
* Request the Flow Controller perform RAM repair whenever it turns on
* a power rail that requires RAM repair.
*/
clrbits_le32(&flow->ram_repair, RAM_REPAIR_BYPASS_EN);
/* Request SW trigerred RAM repair by setting req bit */
/* cluster 0 */
setbits_le32(&flow->ram_repair, RAM_REPAIR_REQ);
/* Wait for completion (status == 0) */
ram_repair_timeout = 500;
do {
udelay(1);
val = readl(&flow->ram_repair);
} while (!(val & RAM_REPAIR_STS) && ram_repair_timeout--);
if (!ram_repair_timeout)
debug("Ram Repair cluster0 failed\n");
/* cluster 1 */
setbits_le32(&flow->ram_repair_cluster1, RAM_REPAIR_REQ);
/* Wait for completion (status == 0) */
ram_repair_timeout = 500;
do {
udelay(1);
val = readl(&flow->ram_repair_cluster1);
} while (!(val & RAM_REPAIR_STS) && ram_repair_timeout--);
if (!ram_repair_timeout)
debug("Ram Repair cluster1 failed\n");
}
/**
* Tegra124 requires some special clock initialization, including setting up
* the DVC I2C, turning on MSELECT and selecting the G CPU cluster
*/
void tegra124_init_clocks(void)
{
struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
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 val;
debug("%s entry\n", __func__);
/* Set active CPU cluster to G */
clrbits_le32(&flow->cluster_control, 1);
/* Change the oscillator drive strength */
val = readl(&clkrst->crc_osc_ctrl);
val &= ~OSC_XOFS_MASK;
val |= (OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT);
writel(val, &clkrst->crc_osc_ctrl);
/* Update same value in PMC_OSC_EDPD_OVER XOFS field for warmboot */
val = readl(&pmc->pmc_osc_edpd_over);
val &= ~PMC_XOFS_MASK;
val |= (OSC_DRIVE_STRENGTH << PMC_XOFS_SHIFT);
writel(val, &pmc->pmc_osc_edpd_over);
/* Set HOLD_CKE_LOW_EN to 1 */
setbits_le32(&pmc->pmc_cntrl2, HOLD_CKE_LOW_EN);
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_CPU, 1);
clock_set_enable(PERIPH_ID_EMC, 1);
clock_set_enable(PERIPH_ID_I2C5, 1);
clock_set_enable(PERIPH_ID_APBDMA, 1);
clock_set_enable(PERIPH_ID_MEM, 1);
clock_set_enable(PERIPH_ID_CORESIGHT, 1);
clock_set_enable(PERIPH_ID_MSELECT, 1);
clock_set_enable(PERIPH_ID_DVFS, 1);
/*
* Set MSELECT clock source as PLLP (00), and ask for a clock
* divider that would set the MSELECT clock at 102MHz for a
* PLLP base of 408MHz.
*/
clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0,
CLK_DIVIDER(NVBL_PLLP_KHZ, 102000));
/* Give clock time to stabilize */
udelay(IO_STABILIZATION_DELAY);
/* I2C5 (DVC) gets CLK_M and a divisor of 17 */
clock_ll_set_source_divisor(PERIPH_ID_I2C5, 3, 16);
/* Give clock time to stabilize */
udelay(IO_STABILIZATION_DELAY);
/* 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_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_DVFS, 0);
debug("%s exit\n", __func__);
}
static bool is_partition_powered(u32 partid)
{
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 & (1 << partid));
}
static void unpower_partition(u32 partid)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
debug("%s: part ID = %08X\n", __func__, partid);
/* Is the partition on? */
if (is_partition_powered(partid)) {
/* Yes, toggle the partition power state (ON -> OFF) */
debug("power_partition, toggling state\n");
writel(START_CP | partid, &pmc->pmc_pwrgate_toggle);
/* Wait for the power to come down */
while (is_partition_powered(partid))
;
/* Give I/O signals time to stabilize */
udelay(IO_STABILIZATION_DELAY);
}
}
void unpower_cpus(void)
{
debug("%s entry: G cluster\n", __func__);
/* Power down the fast cluster rail partition */
debug("%s: CRAIL\n", __func__);
unpower_partition(CRAIL);
/* Power down the fast cluster non-CPU partition */
debug("%s: C0NC\n", __func__);
unpower_partition(C0NC);
/* Power down the fast cluster CPU0 partition */
debug("%s: CE0\n", __func__);
unpower_partition(CE0);
debug("%s: done\n", __func__);
}
static void power_partition(u32 partid)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
debug("%s: part ID = %08X\n", __func__, partid);
/* Is the partition already on? */
if (!is_partition_powered(partid)) {
/* No, toggle the partition power state (OFF -> ON) */
debug("power_partition, toggling state\n");
writel(START_CP | partid, &pmc->pmc_pwrgate_toggle);
/* Wait for the power to come up */
while (!is_partition_powered(partid))
;
/* Give I/O signals time to stabilize */
udelay(IO_STABILIZATION_DELAY);
}
}
void powerup_cpus(void)
{
/* We boot to the fast cluster */
debug("%s entry: G cluster\n", __func__);
/* Power up the fast cluster rail partition */
debug("%s: CRAIL\n", __func__);
power_partition(CRAIL);
/* Power up the fast cluster non-CPU partition */
debug("%s: C0NC\n", __func__);
power_partition(C0NC);
/* Power up the fast cluster CPU0 partition */
debug("%s: CE0\n", __func__);
power_partition(CE0);
debug("%s: done\n", __func__);
}
void start_cpu(u32 reset_vector)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
debug("%s entry, reset_vector = %x\n", __func__, reset_vector);
/*
* High power clusters are on after software reset,
* it may interfere with tegra124_ram_repair.
* unpower them.
*/
unpower_cpus();
tegra124_init_clocks();
/* Set power-gating timer multiplier */
writel((MULT_8 << TIMER_MULT_SHIFT) | (MULT_8 << TIMER_MULT_CPU_SHIFT),
&pmc->pmc_pwrgate_timer_mult);
enable_cpu_power_rail();
powerup_cpus();
tegra124_ram_repair();
enable_cpu_clocks();
clock_enable_coresight(1);
writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
remove_cpu_resets();
debug("%s exit, should continue @ reset_vector\n", __func__);
}
@@ -0,0 +1,70 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2013
* NVIDIA Corporation <www.nvidia.com>
*/
/* Tegra124 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_GPIO: /* TXD,RXD,CTS,RTS */
pinmux_set_func(PMUX_PINGRP_PJ7, PMUX_FUNC_UARTD);
pinmux_set_func(PMUX_PINGRP_PB0, PMUX_FUNC_UARTD);
pinmux_set_func(PMUX_PINGRP_PB1, PMUX_FUNC_UARTD);
pinmux_set_func(PMUX_PINGRP_PK7, PMUX_FUNC_UARTD);
pinmux_set_io(PMUX_PINGRP_PJ7, PMUX_PIN_OUTPUT);
pinmux_set_io(PMUX_PINGRP_PB0, PMUX_PIN_INPUT);
pinmux_set_io(PMUX_PINGRP_PB1, PMUX_PIN_INPUT);
pinmux_set_io(PMUX_PINGRP_PK7, PMUX_PIN_OUTPUT);
pinmux_tristate_disable(PMUX_PINGRP_PJ7);
pinmux_tristate_disable(PMUX_PINGRP_PB0);
pinmux_tristate_disable(PMUX_PINGRP_PB1);
pinmux_tristate_disable(PMUX_PINGRP_PK7);
break;
}
break;
case PERIPH_ID_UART1:
switch (config) {
case FUNCMUX_UART1_KBC:
pinmux_set_func(PMUX_PINGRP_KB_ROW9_PS1,
PMUX_FUNC_UARTA);
pinmux_set_func(PMUX_PINGRP_KB_ROW10_PS2,
PMUX_FUNC_UARTA);
pinmux_set_io(PMUX_PINGRP_KB_ROW9_PS1, PMUX_PIN_OUTPUT);
pinmux_set_io(PMUX_PINGRP_KB_ROW10_PS2, PMUX_PIN_INPUT);
pinmux_tristate_disable(PMUX_PINGRP_KB_ROW9_PS1);
pinmux_tristate_disable(PMUX_PINGRP_KB_ROW10_PS2);
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;
}
@@ -0,0 +1,322 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/pinmux.h>
#define PIN(pin, f0, f1, f2, f3) \
{ \
.funcs = { \
PMUX_FUNC_##f0, \
PMUX_FUNC_##f1, \
PMUX_FUNC_##f2, \
PMUX_FUNC_##f3, \
}, \
}
#define PIN_RESERVED {}
static const struct pmux_pingrp_desc tegra124_pingroups[] = {
/* pin, f0, f1, f2, f3 */
/* Offset 0x3000 */
PIN(ULPI_DATA0_PO1, SPI3, HSI, UARTA, ULPI),
PIN(ULPI_DATA1_PO2, SPI3, HSI, UARTA, ULPI),
PIN(ULPI_DATA2_PO3, SPI3, HSI, UARTA, ULPI),
PIN(ULPI_DATA3_PO4, SPI3, HSI, UARTA, ULPI),
PIN(ULPI_DATA4_PO5, SPI2, HSI, UARTA, ULPI),
PIN(ULPI_DATA5_PO6, SPI2, HSI, UARTA, ULPI),
PIN(ULPI_DATA6_PO7, SPI2, HSI, UARTA, ULPI),
PIN(ULPI_DATA7_PO0, SPI2, HSI, UARTA, ULPI),
PIN(ULPI_CLK_PY0, SPI1, SPI5, UARTD, ULPI),
PIN(ULPI_DIR_PY1, SPI1, SPI5, UARTD, ULPI),
PIN(ULPI_NXT_PY2, SPI1, SPI5, UARTD, ULPI),
PIN(ULPI_STP_PY3, SPI1, SPI5, UARTD, ULPI),
PIN(DAP3_FS_PP0, I2S2, SPI5, DISPLAYA, DISPLAYB),
PIN(DAP3_DIN_PP1, I2S2, SPI5, DISPLAYA, DISPLAYB),
PIN(DAP3_DOUT_PP2, I2S2, SPI5, DISPLAYA, RSVD4),
PIN(DAP3_SCLK_PP3, I2S2, SPI5, RSVD3, DISPLAYB),
PIN(PV0, RSVD1, RSVD2, RSVD3, RSVD4),
PIN(PV1, RSVD1, RSVD2, RSVD3, RSVD4),
PIN(SDMMC1_CLK_PZ0, SDMMC1, CLK12, RSVD3, RSVD4),
PIN(SDMMC1_CMD_PZ1, SDMMC1, SPDIF, SPI4, UARTA),
PIN(SDMMC1_DAT3_PY4, SDMMC1, SPDIF, SPI4, UARTA),
PIN(SDMMC1_DAT2_PY5, SDMMC1, PWM0, SPI4, UARTA),
PIN(SDMMC1_DAT1_PY6, SDMMC1, PWM1, SPI4, UARTA),
PIN(SDMMC1_DAT0_PY7, SDMMC1, RSVD2, SPI4, UARTA),
PIN_RESERVED,
PIN_RESERVED,
/* Offset 0x3068 */
PIN(CLK2_OUT_PW5, EXTPERIPH2, RSVD2, RSVD3, RSVD4),
PIN(CLK2_REQ_PCC5, DAP, RSVD2, RSVD3, RSVD4),
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
/* Offset 0x3110 */
PIN(HDMI_INT_PN7, RSVD1, RSVD2, RSVD3, RSVD4),
PIN(DDC_SCL_PV4, I2C4, RSVD2, RSVD3, RSVD4),
PIN(DDC_SDA_PV5, I2C4, RSVD2, RSVD3, RSVD4),
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
/* Offset 0x3164 */
PIN(UART2_RXD_PC3, IRDA, SPDIF, UARTA, SPI4),
PIN(UART2_TXD_PC2, IRDA, SPDIF, UARTA, SPI4),
PIN(UART2_RTS_N_PJ6, UARTA, UARTB, GMI, SPI4),
PIN(UART2_CTS_N_PJ5, UARTA, UARTB, GMI, SPI4),
PIN(UART3_TXD_PW6, UARTC, RSVD2, GMI, SPI4),
PIN(UART3_RXD_PW7, UARTC, RSVD2, GMI, SPI4),
PIN(UART3_CTS_N_PA1, UARTC, SDMMC1, DTV, GMI),
PIN(UART3_RTS_N_PC0, UARTC, PWM0, DTV, GMI),
PIN(PU0, OWR, UARTA, GMI, RSVD4),
PIN(PU1, RSVD1, UARTA, GMI, RSVD4),
PIN(PU2, RSVD1, UARTA, GMI, RSVD4),
PIN(PU3, PWM0, UARTA, GMI, DISPLAYB),
PIN(PU4, PWM1, UARTA, GMI, DISPLAYB),
PIN(PU5, PWM2, UARTA, GMI, DISPLAYB),
PIN(PU6, PWM3, UARTA, RSVD3, GMI),
PIN(GEN1_I2C_SDA_PC5, I2C1, RSVD2, RSVD3, RSVD4),
PIN(GEN1_I2C_SCL_PC4, I2C1, RSVD2, RSVD3, RSVD4),
PIN(DAP4_FS_PP4, I2S3, GMI, DTV, RSVD4),
PIN(DAP4_DIN_PP5, I2S3, GMI, RSVD3, RSVD4),
PIN(DAP4_DOUT_PP6, I2S3, GMI, DTV, RSVD4),
PIN(DAP4_SCLK_PP7, I2S3, GMI, RSVD3, RSVD4),
PIN(CLK3_OUT_PEE0, EXTPERIPH3, RSVD2, RSVD3, RSVD4),
PIN(CLK3_REQ_PEE1, DEV3, RSVD2, RSVD3, RSVD4),
PIN(PC7, RSVD1, RSVD2, GMI, GMI_ALT),
PIN(PI5, SDMMC2, RSVD2, GMI, RSVD4),
PIN(PI7, RSVD1, TRACE, GMI, DTV),
PIN(PK0, RSVD1, SDMMC3, GMI, SOC),
PIN(PK1, SDMMC2, TRACE, GMI, RSVD4),
PIN(PJ0, RSVD1, RSVD2, GMI, USB),
PIN(PJ2, RSVD1, RSVD2, GMI, SOC),
PIN(PK3, SDMMC2, TRACE, GMI, CCLA),
PIN(PK4, SDMMC2, RSVD2, GMI, GMI_ALT),
PIN(PK2, RSVD1, RSVD2, GMI, RSVD4),
PIN(PI3, RSVD1, RSVD2, GMI, SPI4),
PIN(PI6, RSVD1, RSVD2, GMI, SDMMC2),
PIN(PG0, RSVD1, RSVD2, GMI, RSVD4),
PIN(PG1, RSVD1, RSVD2, GMI, RSVD4),
PIN(PG2, RSVD1, TRACE, GMI, RSVD4),
PIN(PG3, RSVD1, TRACE, GMI, RSVD4),
PIN(PG4, RSVD1, TMDS, GMI, SPI4),
PIN(PG5, RSVD1, RSVD2, GMI, SPI4),
PIN(PG6, RSVD1, RSVD2, GMI, SPI4),
PIN(PG7, RSVD1, RSVD2, GMI, SPI4),
PIN(PH0, PWM0, TRACE, GMI, DTV),
PIN(PH1, PWM1, TMDS, GMI, DISPLAYA),
PIN(PH2, PWM2, TMDS, GMI, CLDVFS),
PIN(PH3, PWM3, SPI4, GMI, CLDVFS),
PIN(PH4, SDMMC2, RSVD2, GMI, RSVD4),
PIN(PH5, SDMMC2, RSVD2, GMI, RSVD4),
PIN(PH6, SDMMC2, TRACE, GMI, DTV),
PIN(PH7, SDMMC2, TRACE, GMI, DTV),
PIN(PJ7, UARTD, RSVD2, GMI, GMI_ALT),
PIN(PB0, UARTD, RSVD2, GMI, RSVD4),
PIN(PB1, UARTD, RSVD2, GMI, RSVD4),
PIN(PK7, UARTD, RSVD2, GMI, RSVD4),
PIN(PI0, RSVD1, RSVD2, GMI, RSVD4),
PIN(PI1, RSVD1, RSVD2, GMI, RSVD4),
PIN(PI2, SDMMC2, TRACE, GMI, RSVD4),
PIN(PI4, SPI4, TRACE, GMI, DISPLAYA),
PIN(GEN2_I2C_SCL_PT5, I2C2, RSVD2, GMI, RSVD4),
PIN(GEN2_I2C_SDA_PT6, I2C2, RSVD2, GMI, RSVD4),
PIN(SDMMC4_CLK_PCC4, SDMMC4, RSVD2, GMI, RSVD4),
PIN(SDMMC4_CMD_PT7, SDMMC4, RSVD2, GMI, RSVD4),
PIN(SDMMC4_DAT0_PAA0, SDMMC4, SPI3, GMI, RSVD4),
PIN(SDMMC4_DAT1_PAA1, SDMMC4, SPI3, GMI, RSVD4),
PIN(SDMMC4_DAT2_PAA2, SDMMC4, SPI3, GMI, RSVD4),
PIN(SDMMC4_DAT3_PAA3, SDMMC4, SPI3, GMI, RSVD4),
PIN(SDMMC4_DAT4_PAA4, SDMMC4, SPI3, GMI, RSVD4),
PIN(SDMMC4_DAT5_PAA5, SDMMC4, SPI3, RSVD3, RSVD4),
PIN(SDMMC4_DAT6_PAA6, SDMMC4, SPI3, GMI, RSVD4),
PIN(SDMMC4_DAT7_PAA7, SDMMC4, RSVD2, GMI, RSVD4),
PIN_RESERVED,
/* Offset 0x3284 */
PIN(CAM_MCLK_PCC0, VI, VI_ALT1, VI_ALT3, SDMMC2),
PIN(PCC1, I2S4, RSVD2, RSVD3, SDMMC2),
PIN(PBB0, VGP6, VIMCLK2, SDMMC2, VIMCLK2_ALT),
PIN(CAM_I2C_SCL_PBB1, VGP1, I2C3, RSVD3, SDMMC2),
PIN(CAM_I2C_SDA_PBB2, VGP2, I2C3, RSVD3, SDMMC2),
PIN(PBB3, VGP3, DISPLAYA, DISPLAYB, SDMMC2),
PIN(PBB4, VGP4, DISPLAYA, DISPLAYB, SDMMC2),
PIN(PBB5, VGP5, DISPLAYA, RSVD3, SDMMC2),
PIN(PBB6, I2S4, RSVD2, DISPLAYB, SDMMC2),
PIN(PBB7, I2S4, RSVD2, RSVD3, SDMMC2),
PIN(PCC2, I2S4, RSVD2, SDMMC3, SDMMC2),
PIN(JTAG_RTCK, RTCK, RSVD2, RSVD3, RSVD4),
PIN(PWR_I2C_SCL_PZ6, I2CPWR, RSVD2, RSVD3, RSVD4),
PIN(PWR_I2C_SDA_PZ7, I2CPWR, RSVD2, RSVD3, RSVD4),
PIN(KB_ROW0_PR0, KBC, RSVD2, RSVD3, RSVD4),
PIN(KB_ROW1_PR1, KBC, RSVD2, RSVD3, RSVD4),
PIN(KB_ROW2_PR2, KBC, RSVD2, RSVD3, RSVD4),
PIN(KB_ROW3_PR3, KBC, DISPLAYA, SYS, DISPLAYB),
PIN(KB_ROW4_PR4, KBC, DISPLAYA, RSVD3, DISPLAYB),
PIN(KB_ROW5_PR5, KBC, DISPLAYA, RSVD3, DISPLAYB),
PIN(KB_ROW6_PR6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB),
PIN(KB_ROW7_PR7, KBC, RSVD2, CLDVFS, UARTA),
PIN(KB_ROW8_PS0, KBC, RSVD2, CLDVFS, UARTA),
PIN(KB_ROW9_PS1, KBC, RSVD2, RSVD3, UARTA),
PIN(KB_ROW10_PS2, KBC, RSVD2, RSVD3, UARTA),
PIN(KB_ROW11_PS3, KBC, RSVD2, RSVD3, IRDA),
PIN(KB_ROW12_PS4, KBC, RSVD2, RSVD3, IRDA),
PIN(KB_ROW13_PS5, KBC, RSVD2, SPI2, RSVD4),
PIN(KB_ROW14_PS6, KBC, RSVD2, SPI2, RSVD4),
PIN(KB_ROW15_PS7, KBC, SOC, RSVD3, RSVD4),
PIN(KB_COL0_PQ0, KBC, RSVD2, SPI2, RSVD4),
PIN(KB_COL1_PQ1, KBC, RSVD2, SPI2, RSVD4),
PIN(KB_COL2_PQ2, KBC, RSVD2, SPI2, RSVD4),
PIN(KB_COL3_PQ3, KBC, DISPLAYA, PWM2, UARTA),
PIN(KB_COL4_PQ4, KBC, OWR, SDMMC3, UARTA),
PIN(KB_COL5_PQ5, KBC, RSVD2, SDMMC3, RSVD4),
PIN(KB_COL6_PQ6, KBC, RSVD2, SPI2, UARTD),
PIN(KB_COL7_PQ7, KBC, RSVD2, SPI2, UARTD),
PIN(CLK_32K_OUT_PA0, BLINK, SOC, RSVD3, RSVD4),
PIN_RESERVED,
/* Offset 0x3324 */
PIN(CORE_PWR_REQ, PWRON, RSVD2, RSVD3, RSVD4),
PIN(CPU_PWR_REQ, CPU, RSVD2, RSVD3, RSVD4),
PIN(PWR_INT_N, PMI, RSVD2, RSVD3, RSVD4),
PIN(CLK_32K_IN, CLK, RSVD2, RSVD3, RSVD4),
PIN(OWR, OWR, RSVD2, RSVD3, RSVD4),
PIN(DAP1_FS_PN0, I2S0, HDA, GMI, RSVD4),
PIN(DAP1_DIN_PN1, I2S0, HDA, GMI, RSVD4),
PIN(DAP1_DOUT_PN2, I2S0, HDA, GMI, SATA),
PIN(DAP1_SCLK_PN3, I2S0, HDA, GMI, RSVD4),
PIN(DAP_MCLK1_REQ_PEE2, DAP, DAP1, SATA, RSVD4),
PIN(DAP_MCLK1_PW4, EXTPERIPH1, DAP2, RSVD3, RSVD4),
PIN(SPDIF_IN_PK6, SPDIF, RSVD2, RSVD3, I2C3),
PIN(SPDIF_OUT_PK5, SPDIF, RSVD2, RSVD3, I2C3),
PIN(DAP2_FS_PA2, I2S1, HDA, GMI, RSVD4),
PIN(DAP2_DIN_PA4, I2S1, HDA, GMI, RSVD4),
PIN(DAP2_DOUT_PA5, I2S1, HDA, GMI, RSVD4),
PIN(DAP2_SCLK_PA3, I2S1, HDA, GMI, RSVD4),
PIN(DVFS_PWM_PX0, SPI6, CLDVFS, GMI, RSVD4),
PIN(GPIO_X1_AUD_PX1, SPI6, RSVD2, GMI, RSVD4),
PIN(GPIO_X3_AUD_PX3, SPI6, SPI1, GMI, RSVD4),
PIN(DVFS_CLK_PX2, SPI6, CLDVFS, GMI, RSVD4),
PIN(GPIO_X4_AUD_PX4, GMI, SPI1, SPI2, DAP2),
PIN(GPIO_X5_AUD_PX5, GMI, SPI1, SPI2, RSVD4),
PIN(GPIO_X6_AUD_PX6, SPI6, SPI1, SPI2, GMI),
PIN(GPIO_X7_AUD_PX7, RSVD1, SPI1, SPI2, RSVD4),
PIN_RESERVED,
PIN_RESERVED,
/* Offset 0x3390 */
PIN(SDMMC3_CLK_PA6, SDMMC3, RSVD2, RSVD3, SPI3),
PIN(SDMMC3_CMD_PA7, SDMMC3, PWM3, UARTA, SPI3),
PIN(SDMMC3_DAT0_PB7, SDMMC3, RSVD2, RSVD3, SPI3),
PIN(SDMMC3_DAT1_PB6, SDMMC3, PWM2, UARTA, SPI3),
PIN(SDMMC3_DAT2_PB5, SDMMC3, PWM1, DISPLAYA, SPI3),
PIN(SDMMC3_DAT3_PB4, SDMMC3, PWM0, DISPLAYB, SPI3),
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
/* Offset 0x33bc */
PIN(PEX_L0_RST_N_PDD1, PE0, RSVD2, RSVD3, RSVD4),
PIN(PEX_L0_CLKREQ_N_PDD2, PE0, RSVD2, RSVD3, RSVD4),
PIN(PEX_WAKE_N_PDD3, PE, RSVD2, RSVD3, RSVD4),
PIN_RESERVED,
/* Offset 0x33cc */
PIN(PEX_L1_RST_N_PDD5, PE1, RSVD2, RSVD3, RSVD4),
PIN(PEX_L1_CLKREQ_N_PDD6, PE1, RSVD2, RSVD3, RSVD4),
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
/* Offset 0x33e0 */
PIN(HDMI_CEC_PEE3, CEC, RSVD2, RSVD3, RSVD4),
PIN(SDMMC1_WP_N_PV3, SDMMC1, CLK12, SPI4, UARTA),
PIN(SDMMC3_CD_N_PV2, SDMMC3, OWR, RSVD3, RSVD4),
PIN(GPIO_W2_AUD_PW2, SPI6, RSVD2, SPI2, I2C1),
PIN(GPIO_W3_AUD_PW3, SPI6, SPI1, SPI2, I2C1),
PIN(USB_VBUS_EN0_PN4, USB, RSVD2, RSVD3, RSVD4),
PIN(USB_VBUS_EN1_PN5, USB, RSVD2, RSVD3, RSVD4),
PIN(SDMMC3_CLK_LB_IN_PEE5, SDMMC3, RSVD2, RSVD3, RSVD4),
PIN(SDMMC3_CLK_LB_OUT_PEE4, SDMMC3, RSVD2, RSVD3, RSVD4),
PIN(GMI_CLK_LB, SDMMC2, RSVD2, GMI, RSVD4),
PIN(RESET_OUT_N, RSVD1, RSVD2, RSVD3, RESET_OUT_N),
PIN(KB_ROW16_PT0, KBC, RSVD2, RSVD3, UARTC),
PIN(KB_ROW17_PT1, KBC, RSVD2, RSVD3, UARTC),
PIN(USB_VBUS_EN2_PFF1, USB, RSVD2, RSVD3, RSVD4),
PIN(PFF2, SATA, RSVD2, RSVD3, RSVD4),
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
PIN_RESERVED,
/* Offset 0x3430 */
PIN(DP_HPD_PFF0, DP, RSVD2, RSVD3, RSVD4),
};
const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra124_pingroups;
#define MIPIPADCTRL_GRP(grp, f0, f1) \
{ \
.funcs = { \
PMUX_FUNC_##f0, \
PMUX_FUNC_##f1, \
}, \
}
#define MIPIPADCTRL_RESERVED {}
static const struct pmux_mipipadctrlgrp_desc tegra124_mipipadctrl_groups[] = {
/* pin, f0, f1 */
/* Offset 0x820 */
MIPIPADCTRL_GRP(DSI_B, CSI, DSI_B),
};
const struct pmux_mipipadctrlgrp_desc *tegra_soc_mipipadctrl_groups = tegra124_mipipadctrl_groups;
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Google, Inc
*/
#include <common.h>
#include <dm.h>
#include <syscon.h>
static const struct udevice_id tegra124_syscon_ids[] = {
{ .compatible = "nvidia,tegra124-pmc", .data = TEGRA_SYSCON_PMC },
};
U_BOOT_DRIVER(syscon_tegra124) = {
.name = "tegra124_syscon",
.id = UCLASS_SYSCON,
.of_match = tegra124_syscon_ids,
};
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2015, Siemens AG
* Author: Jan Kiszka <jan.kiszka@siemens.com>
*/
#include <common.h>
#include <asm/io.h>
#include <asm/psci.h>
#include <asm/arch/flow.h>
#include <asm/arch/powergate.h>
#include <asm/arch-tegra/ap.h>
#include <asm/arch-tegra/pmc.h>
static void park_cpu(void)
{
while (1)
asm volatile("wfi");
}
/**
* Initialize power management for application processors
*/
void psci_board_init(void)
{
struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR);
/*
* The naturally expected order of putting these CPUs under Flow
* Controller regime would be
* - configure the Flow Controller
* - power up the CPUs
* - wait for the CPUs to hit wfi and be powered down again
*
* However, this doesn't work in practice. We rather need to power them
* up first and park them in wfi. While they are waiting there, we can
* indeed program the Flow Controller to powergate them on wfi, which
* will then happen immediately as they are already in that state.
*/
tegra_powergate_power_on(TEGRA_POWERGATE_CPU1);
tegra_powergate_power_on(TEGRA_POWERGATE_CPU2);
tegra_powergate_power_on(TEGRA_POWERGATE_CPU3);
writel((2 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu1_csr);
writel((4 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu2_csr);
writel((8 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu3_csr);
writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
writel(EVENT_MODE_STOP, &flow->halt_cpu2_events);
writel(EVENT_MODE_STOP, &flow->halt_cpu3_events);
while (!(readl(&flow->cpu1_csr) & CSR_PWR_OFF_STS) ||
!(readl(&flow->cpu2_csr) & CSR_PWR_OFF_STS) ||
!(readl(&flow->cpu3_csr) & CSR_PWR_OFF_STS))
/* wait */;
}
@@ -0,0 +1,350 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
*/
#define pr_fmt(fmt) "tegra-xusb-padctl: " fmt
#include <common.h>
#include <errno.h>
#include <dm/of_access.h>
#include <dm/ofnode.h>
#include "../xusb-padctl-common.h"
#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
enum tegra124_function {
TEGRA124_FUNC_SNPS,
TEGRA124_FUNC_XUSB,
TEGRA124_FUNC_UART,
TEGRA124_FUNC_PCIE,
TEGRA124_FUNC_USB3,
TEGRA124_FUNC_SATA,
TEGRA124_FUNC_RSVD,
};
static const char *const tegra124_functions[] = {
"snps",
"xusb",
"uart",
"pcie",
"usb3",
"sata",
"rsvd",
};
static const unsigned int tegra124_otg_functions[] = {
TEGRA124_FUNC_SNPS,
TEGRA124_FUNC_XUSB,
TEGRA124_FUNC_UART,
TEGRA124_FUNC_RSVD,
};
static const unsigned int tegra124_usb_functions[] = {
TEGRA124_FUNC_SNPS,
TEGRA124_FUNC_XUSB,
};
static const unsigned int tegra124_pci_functions[] = {
TEGRA124_FUNC_PCIE,
TEGRA124_FUNC_USB3,
TEGRA124_FUNC_SATA,
TEGRA124_FUNC_RSVD,
};
#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \
{ \
.name = _name, \
.offset = _offset, \
.shift = _shift, \
.mask = _mask, \
.iddq = _iddq, \
.num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \
.funcs = tegra124_##_funcs##_functions, \
}
static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg),
TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg),
TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg),
TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
};
static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
{
u32 value;
if (padctl->enable++ > 0)
return 0;
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
udelay(100);
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
udelay(100);
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
return 0;
}
static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
{
u32 value;
if (padctl->enable == 0) {
pr_err("unbalanced enable/disable");
return 0;
}
if (--padctl->enable > 0)
return 0;
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
udelay(100);
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
udelay(100);
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
return 0;
}
static int phy_prepare(struct tegra_xusb_phy *phy)
{
return tegra_xusb_padctl_enable(phy->padctl);
}
static int phy_unprepare(struct tegra_xusb_phy *phy)
{
return tegra_xusb_padctl_disable(phy->padctl);
}
static int pcie_phy_enable(struct tegra_xusb_phy *phy)
{
struct tegra_xusb_padctl *padctl = phy->padctl;
int err = -ETIMEDOUT;
unsigned long start;
u32 value;
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
start = get_timer(0);
while (get_timer(start) < 50) {
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
err = 0;
break;
}
}
return err;
}
static int pcie_phy_disable(struct tegra_xusb_phy *phy)
{
struct tegra_xusb_padctl *padctl = phy->padctl;
u32 value;
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
return 0;
}
static int sata_phy_enable(struct tegra_xusb_phy *phy)
{
struct tegra_xusb_padctl *padctl = phy->padctl;
int err = -ETIMEDOUT;
unsigned long start;
u32 value;
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
start = get_timer(0);
while (get_timer(start) < 50) {
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
err = 0;
break;
}
}
return err;
}
static int sata_phy_disable(struct tegra_xusb_phy *phy)
{
struct tegra_xusb_padctl *padctl = phy->padctl;
u32 value;
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
return 0;
}
static const struct tegra_xusb_phy_ops pcie_phy_ops = {
.prepare = phy_prepare,
.enable = pcie_phy_enable,
.disable = pcie_phy_disable,
.unprepare = phy_unprepare,
};
static const struct tegra_xusb_phy_ops sata_phy_ops = {
.prepare = phy_prepare,
.enable = sata_phy_enable,
.disable = sata_phy_disable,
.unprepare = phy_unprepare,
};
static struct tegra_xusb_phy tegra124_phys[] = {
{
.type = TEGRA_XUSB_PADCTL_PCIE,
.ops = &pcie_phy_ops,
.padctl = &padctl,
},
{
.type = TEGRA_XUSB_PADCTL_SATA,
.ops = &sata_phy_ops,
.padctl = &padctl,
},
};
static const struct tegra_xusb_padctl_soc tegra124_socdata = {
.lanes = tegra124_lanes,
.num_lanes = ARRAY_SIZE(tegra124_lanes),
.functions = tegra124_functions,
.num_functions = ARRAY_SIZE(tegra124_functions),
.phys = tegra124_phys,
.num_phys = ARRAY_SIZE(tegra124_phys),
};
void tegra_xusb_padctl_init(void)
{
ofnode nodes[1];
int count = 0;
int ret;
debug("%s: start\n", __func__);
if (of_live_active()) {
struct device_node *np = of_find_compatible_node(NULL, NULL,
"nvidia,tegra124-xusb-padctl");
debug("np=%p\n", np);
if (np) {
nodes[0] = np_to_ofnode(np);
count = 1;
}
} else {
int node_offsets[1];
int i;
count = fdtdec_find_aliases_for_id(gd->fdt_blob, "padctl",
COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
node_offsets, ARRAY_SIZE(node_offsets));
for (i = 0; i < count; i++)
nodes[i] = offset_to_ofnode(node_offsets[i]);
}
ret = tegra_xusb_process_nodes(nodes, count, &tegra124_socdata);
debug("%s: done, ret=%d\n", __func__, ret);
}