tegra124/nyan: various fixes and additions

Tegra124: SDMMC: Configure base clock frequency.
Reviewed-on: https://chromium-review.googlesource.com/173841
(cherry picked from commit d3157e9a380cfb018cc69a1f23f277c3c5b680a6)

Tegra124: SDMMC: Configure pinmux for MMC 3/4.
Reviewed-on: https://chromium-review.googlesource.com/174011
(cherry picked from commit 55af9a86a56d6bc0ce9bcff4fd5226a60ae2033b)

tegra124: Move DMA-related #defines and definitions to header
Reviewed-on: https://chromium-review.googlesource.com/174444
(cherry picked from commit 9d917927a5b7151958289469b9049ac91efa41e3)

tegra124: Assign console address for kernel.
Reviewed-on: https://chromium-review.googlesource.com/174486
(cherry picked from commit 36e9370f30bd173879958d164156997841ec4e9c)

nyan: Fix up the gpio indices in chromeos.c.
Reviewed-on: https://chromium-review.googlesource.com/174418
(cherry picked from commit fba4ae1080c19f11abe1205b871ada14db996c61)

Nyan: turn on the backlight.
Reviewed-on: https://chromium-review.googlesource.com/174533
(cherry picked from commit 12649c9611981dd8d6567ba0238c8b8247c52215)

tegra124: Fix the disp1 source field.
Reviewed-on: https://chromium-review.googlesource.com/174701
(cherry picked from commit eed380e09075e1eef0bde7d1bb15c4343f30bfe0)

nyan: set up the aux channel i2c interface
Reviewed-on: https://chromium-review.googlesource.com/174620
(cherry picked from commit ea81cb44a1c11cd78643c69ac818304cd393749e)

tegra124: fix typos in the clock code.
Reviewed-on: https://chromium-review.googlesource.com/174684
(cherry picked from commit 72365c33693db4eb6e01032938221f592b7e5a02)

tegra124: Revamp clock source/divisor configuration
Reviewed-on: https://chromium-review.googlesource.com/174804
(cherry picked from commit 3f31a634f69595bcc6a473301d1492c97a767809)

tegra: Add gpio_output_open_drain() function
Reviewed-on: https://chromium-review.googlesource.com/174650
(cherry picked from commit bc1c28926810e722e9b82339ea0585d083e3fa8c)

tegra124: add nvidia-generated files
Reviewed-on: https://chromium-review.googlesource.com/174610
(cherry picked from commit 7706f3200f7fc11b7a443f336bff6a37afa94652)

nyan: Ignore the dev mode GPIO.
Reviewed-on: https://chromium-review.googlesource.com/174837
(cherry picked from commit 9513e608f3063fdb3e9d8bd04e6e5fe35a5bfcee)

Tegra124: Add support for the ARM architectural timer.
Reviewed-on: https://chromium-review.googlesource.com/174835
(cherry picked from commit 25a91fcf7e79cc450caa59bc6b65f954bb96ac6c)

nyan: Initialize the ARM architectural timer in the RAM stage.
Reviewed-on: https://chromium-review.googlesource.com/174836
(cherry picked from commit 581f592c12de91c0cf8279ede2850e38dd0cd2e8)

tegra124: nyan: Move mainboard level clock stuff into the mainboard source.
Reviewed-on: https://chromium-review.googlesource.com/174843
(cherry picked from commit 5ab100b0bad22814261f9b755b59394562c9145a)

tegra124: add some explanatory text about U7.1 computations.
Reviewed-on: https://chromium-review.googlesource.com/173910
(cherry picked from commit 822cad0ceeceeb5160c8216e05eec13fd04a6413)

Set the EC SPI clock source to PLLP and divide down to around 5MHz
Reviewed-on: https://chromium-review.googlesource.com/173954
(cherry picked from commit c0e22d76d3887ca1f727443a47db38dec12c0b74)

nyan: Move non-essential configuration out of bootblock and into ram stage.
Reviewed-on: https://chromium-review.googlesource.com/174844
(cherry picked from commit dad7f68c76f7b83edacd8b22c9dbd3f0ff027397)

tegra124: clocks: Save some IOs in clock_enable_clear_reset.
Reviewed-on: https://chromium-review.googlesource.com/174845
(cherry picked from commit 81b977a2758d42471667e2cbe31f160dfda5bca4)

tegra124: re-write SPI driver w/ full duplex support
Reviewed-on: https://chromium-review.googlesource.com/174446
(cherry picked from commit 51c9a34240d6a068780a7d1c27b032b56b2d3e54)

tegra124: move SPI-related structures from .c to .h
Reviewed-on: https://chromium-review.googlesource.com/174637
(cherry picked from commit 36760a4463c2c33f494ca7ea5a36810fa4502058)

tegra124: add frame header info to SPI channel struct
Reviewed-on: https://chromium-review.googlesource.com/174638
(cherry picked from commit e24773eb946e2c4cb5e828f055d45d92bd1a4f9f)

tegra124: re-factor tegra_spi_init()
Reviewed-on: https://chromium-review.googlesource.com/174639
(cherry picked from commit 88354b996459a702c36604f5f92c24e63df8de7e)

nyan: Set CrOS EC frame header parameters for SPI
Reviewed-on: https://chromium-review.googlesource.com/174710
(cherry picked from commit 29173ba5863eebb2864a8384435cde2f0d5ca233)

tegra124: Add Rx frame header support to SPI code
Reviewed-on: https://chromium-review.googlesource.com/174711
(cherry picked from commit 1d1630e770804649ef74d31db194d3bde9968832)

tegra124: add support for the Serial Output Resource (sor)
Reviewed-on: https://chromium-review.googlesource.com/174612
(cherry picked from commit 3eebd10afea4498380582e04560af89126911ed9)

nyan: tegra124: Enable I, D and L2 caches in romstage.
Reviewed-on: https://chromium-review.googlesource.com/173777
(cherry picked from commit 74512b7ecfbd50f01a25677307084699ee8c6007)

tegra and tegra124: Bring up graphics
Reviewed-on: https://chromium-review.googlesource.com/174613
(cherry picked from commit 7e944208a176cdac44a31e2a9961c8bd5dc4ece8)

nyan: Move the DMA memory region.
Reviewed-on: https://chromium-review.googlesource.com/174953
(cherry picked from commit c66e22859252eaebceb07a3118ac61f4cf6289eb)

tegra124: Increase CBFS cache buffer size
Reviewed-on: https://chromium-review.googlesource.com/174950
(cherry picked from commit 6dbb4e5f0d66c68df45ac73e3f223b856b715026)

tegra124: Add USB PLL, PHY and EHCI setup code
Reviewed-on: https://chromium-review.googlesource.com/174651
(cherry picked from commit ecd5c398ff6748a7d40089019471357b58d3a6ea)

tegra124: add in some undocument clock source and PLL registers
Reviewed-on: https://chromium-review.googlesource.com/174948
(cherry picked from commit 73fcc4981da6e4415b514eaafb42bc265ab0cd9a)

tegra124: small cleanups of the code
Reviewed-on: https://chromium-review.googlesource.com/174995
(cherry picked from commit 7256aba07e9567ef8d73f05e1f80c4d45fd57bda)

Squashed 34 commits for tegra124 / nyan support.

Change-Id: I050c7ad962e0d24550b0b33c9318e89c80d01f00
Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com>
Reviewed-on: http://review.coreboot.org/6870
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Tested-by: build bot (Jenkins)
This commit is contained in:
Hung-Te Lin 2013-10-21 21:43:03 +08:00 committed by Isaac Christensen
parent bca446d471
commit 2fc3b6281f
35 changed files with 59080 additions and 635 deletions

View File

@ -48,6 +48,9 @@ endif # CONFIG_ARCH_BOOTBLOCK_ARMV7
ifeq ($(CONFIG_ARCH_ROMSTAGE_ARMV7),y)
romstage-y += cache.c
romstage-y += exception.c
romstage-y += exception_asm.S
romstage-y += mmu.c
CFLAGS_romstage += $(armv7_flags)
CPPFLAGS_romstage += $(armv7_flags)

View File

@ -26,6 +26,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select EC_GOOGLE_CHROMEEC
select EC_GOOGLE_CHROMEEC_SPI
select MAINBOARD_HAS_BOOTBLOCK_INIT
select MAINBOARD_DO_NATIVE_VGA_INIT
select BOARD_ROMSIZE_KB_1024
config MAINBOARD_DIR
@ -40,6 +41,14 @@ config DRAM_SIZE_MB
int
default 2048
config DRAM_DMA_START
hex
default 0x90000000
config DRAM_DMA_SIZE
hex
default 0x00100000
choice
prompt "BCT boot media"
default BCT_CFG_SPI

View File

@ -17,50 +17,47 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <arch/io.h>
#include <bootblock_common.h>
#include <console/console.h>
#include <device/i2c.h>
#include <soc/addressmap.h>
#include <soc/clock.h>
#include <soc/nvidia/tegra/i2c.h>
#include <soc/nvidia/tegra124/clk_rst.h>
#include <soc/nvidia/tegra124/pinmux.h>
#include <soc/nvidia/tegra124/spi.h> /* FIXME: move back to soc code? */
#include "pmic.h"
static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
static void set_clock_sources(void)
{
/* UARTA gets PLLP, deactivate CLK_UART_DIV_OVERRIDE */
writel(PLLP << CLK_SOURCE_SHIFT, &clk_rst->clk_src_uarta);
clock_configure_source(mselect, PLLP, 102000);
/* TODO: is the 1.333MHz correct? This may have always been bogus... */
clock_configure_source(i2c5, CLK_M, 1333);
}
void bootblock_mainboard_init(void)
{
clock_config();
set_clock_sources();
clock_enable_clear_reset(CLK_L_CACHE2 | CLK_L_TMR,
CLK_H_I2C5 | CLK_H_APBDMA,
0, CLK_V_MSELECT, 0);
// I2C1 clock.
pinmux_set_config(PINMUX_GEN1_I2C_SCL_INDEX,
PINMUX_GEN1_I2C_SCL_FUNC_I2C1 | PINMUX_INPUT_ENABLE);
// I2C1 data.
pinmux_set_config(PINMUX_GEN1_I2C_SDA_INDEX,
PINMUX_GEN1_I2C_SDA_FUNC_I2C1 | PINMUX_INPUT_ENABLE);
// I2C2 clock.
pinmux_set_config(PINMUX_GEN2_I2C_SCL_INDEX,
PINMUX_GEN2_I2C_SCL_FUNC_I2C2 | PINMUX_INPUT_ENABLE);
// I2C2 data.
pinmux_set_config(PINMUX_GEN2_I2C_SDA_INDEX,
PINMUX_GEN2_I2C_SDA_FUNC_I2C2 | PINMUX_INPUT_ENABLE);
// I2C3 (cam) clock.
pinmux_set_config(PINMUX_CAM_I2C_SCL_INDEX,
PINMUX_CAM_I2C_SCL_FUNC_I2C3 | PINMUX_INPUT_ENABLE);
// I2C3 (cam) data.
pinmux_set_config(PINMUX_CAM_I2C_SDA_INDEX,
PINMUX_CAM_I2C_SDA_FUNC_I2C3 | PINMUX_INPUT_ENABLE);
// I2C5 (PMU) clock.
pinmux_set_config(PINMUX_PWR_I2C_SCL_INDEX,
PINMUX_PWR_I2C_SCL_FUNC_I2CPMU | PINMUX_INPUT_ENABLE);
// I2C5 (PMU) data.
pinmux_set_config(PINMUX_PWR_I2C_SDA_INDEX,
PINMUX_PWR_I2C_SDA_FUNC_I2CPMU | PINMUX_INPUT_ENABLE);
i2c_init(0);
i2c_init(1);
i2c_init(2);
i2c_init(4);
pmic_init(4);
/* SPI4 data out (MOSI) */
@ -75,6 +72,6 @@ void bootblock_mainboard_init(void)
/* SPI4 chip select 0 */
pinmux_set_config(PINMUX_SDMMC1_DAT3_INDEX,
PINMUX_SDMMC1_DAT3_FUNC_SPI4 | PINMUX_INPUT_ENABLE);
// spi_init();
tegra_spi_init(4);
}

View File

@ -33,7 +33,7 @@ void fill_lb_gpios(struct lb_gpios *gpios)
/* Write Protect: active low */
gpios->gpios[count].port = GPIO_R1_INDEX;
gpios->gpios[count].polarity = ACTIVE_LOW;
gpios->gpios[count].value = gpio_get_in_value(GPIO_R1_INDEX);
gpios->gpios[count].value = gpio_get_in_value(GPIO(R1));
strncpy((char *)gpios->gpios[count].name, "write protect",
GPIO_MAX_NAME_LENGTH);
count++;
@ -49,14 +49,14 @@ void fill_lb_gpios(struct lb_gpios *gpios)
/* Lid: active high */
gpios->gpios[count].port = GPIO_R4_INDEX;
gpios->gpios[count].polarity = ACTIVE_HIGH;
gpios->gpios[count].value = gpio_get_in_value(GPIO_R4_INDEX);
gpios->gpios[count].value = gpio_get_in_value(GPIO(R4));
strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH);
count++;
/* Power: active low */
gpios->gpios[count].port = GPIO_Q0_INDEX;
gpios->gpios[count].polarity = ACTIVE_LOW;
gpios->gpios[count].value = gpio_get_in_value(GPIO_Q0_INDEX);
gpios->gpios[count].value = gpio_get_in_value(GPIO(Q0));
strncpy((char *)gpios->gpios[count].name, "power",
GPIO_MAX_NAME_LENGTH);
count++;
@ -77,7 +77,7 @@ void fill_lb_gpios(struct lb_gpios *gpios)
int get_developer_mode_switch(void)
{
return gpio_get_in_value(GPIO_Q6_INDEX);
return 0;
}
int get_recovery_mode_switch(void)
@ -85,7 +85,7 @@ int get_recovery_mode_switch(void)
uint32_t ec_events;
/* The GPIO is active low. */
if (!gpio_get_in_value(GPIO_Q7_INDEX)) // RECMODE_GPIO
if (!gpio_get_in_value(GPIO(Q7))) // RECMODE_GPIO
return 1;
ec_events = google_chromeec_get_events_b();
@ -95,5 +95,5 @@ int get_recovery_mode_switch(void)
int get_write_protect_state(void)
{
return !gpio_get_in_value(GPIO_R1_INDEX);
return !gpio_get_in_value(GPIO(R1));
}

View File

@ -17,9 +17,47 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <arch/io.h>
#include <device/device.h>
#include <boot/coreboot_tables.h>
#include <soc/addressmap.h>
#include <soc/clock.h>
#include <soc/nvidia/tegra/i2c.h>
#include <soc/nvidia/tegra124/clk_rst.h>
#include <soc/nvidia/tegra124/gpio.h>
#include <soc/nvidia/tegra124/pmc.h>
#include <soc/nvidia/tegra124/spi.h>
#include <soc/nvidia/tegra124/usb.h>
static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
static void set_clock_sources(void)
{
clock_configure_source(i2c1, CLK_M, 1333);
clock_configure_source(i2c2, CLK_M, 1333);
clock_configure_source(i2c3, CLK_M, 1333);
clock_configure_source(i2c4, CLK_M, 1333);
clock_configure_source(sbc1, PLLP, 5000);
/*
* MMC3 and MMC4: Set base clock frequency for SD Clock to Tegra MMC's
* maximum speed (48MHz) so we can change SDCLK by second stage divisor
* in payloads, without touching base clock.
*/
clock_configure_source(sdmmc3, PLLP, 48000);
clock_configure_source(sdmmc4, PLLP, 48000);
/* PLLP and PLLM are switched for HOST1x for no apparent reason. */
write32(4 /* PLLP! */ << CLK_SOURCE_SHIFT |
/* TODO(rminnich): The divisor isn't accurate enough to get to
* 144MHz (it goes to 163 instead). What should we do here? */
CLK_DIVIDER(TEGRA_PLLP_KHZ, 144000),
&clk_rst->clk_src_host1x);
/* DISP1 doesn't support a divisor. Use PLLC which runs at 600MHz. */
clock_configure_source(disp1, PLLC, 600000);
}
static void setup_pinmux(void)
{
@ -52,11 +90,139 @@ static void setup_pinmux(void)
pinmux_set_config(PINMUX_ULPI_STP_INDEX, PINMUX_ULPI_STP_FUNC_SPI1 |
PINMUX_PULL_NONE |
PINMUX_INPUT_ENABLE);
// I2C1 clock.
pinmux_set_config(PINMUX_GEN1_I2C_SCL_INDEX,
PINMUX_GEN1_I2C_SCL_FUNC_I2C1 | PINMUX_INPUT_ENABLE);
// I2C1 data.
pinmux_set_config(PINMUX_GEN1_I2C_SDA_INDEX,
PINMUX_GEN1_I2C_SDA_FUNC_I2C1 | PINMUX_INPUT_ENABLE);
// I2C2 clock.
pinmux_set_config(PINMUX_GEN2_I2C_SCL_INDEX,
PINMUX_GEN2_I2C_SCL_FUNC_I2C2 | PINMUX_INPUT_ENABLE);
// I2C2 data.
pinmux_set_config(PINMUX_GEN2_I2C_SDA_INDEX,
PINMUX_GEN2_I2C_SDA_FUNC_I2C2 | PINMUX_INPUT_ENABLE);
// I2C3 (cam) clock.
pinmux_set_config(PINMUX_CAM_I2C_SCL_INDEX,
PINMUX_CAM_I2C_SCL_FUNC_I2C3 | PINMUX_INPUT_ENABLE);
// I2C3 (cam) data.
pinmux_set_config(PINMUX_CAM_I2C_SDA_INDEX,
PINMUX_CAM_I2C_SDA_FUNC_I2C3 | PINMUX_INPUT_ENABLE);
// I2C4 (DDC) clock.
pinmux_set_config(PINMUX_DDC_SCL_INDEX,
PINMUX_DDC_SCL_FUNC_I2C4 | PINMUX_INPUT_ENABLE);
// I2C4 (DDC) data.
pinmux_set_config(PINMUX_DDC_SDA_INDEX,
PINMUX_DDC_SDA_FUNC_I2C4 | PINMUX_INPUT_ENABLE);
// TODO(hungte) Revice pinmux setup, make nice little SoC functions for
// every single logical thing instead of dumping a wall of code below.
uint32_t pin_up = PINMUX_PULL_UP | PINMUX_INPUT_ENABLE,
pin_up3 = (PINMUX_PULL_UP | PINMUX_INPUT_ENABLE |
PINMUX_TRISTATE),
pin_down = PINMUX_PULL_DOWN | PINMUX_INPUT_ENABLE,
pin_none = PINMUX_PULL_NONE | PINMUX_INPUT_ENABLE;
// MMC3
pinmux_set_config(PINMUX_SDMMC3_CLK_INDEX,
PINMUX_SDMMC3_CLK_FUNC_SDMMC3 | pin_none);
pinmux_set_config(PINMUX_SDMMC3_CMD_INDEX,
PINMUX_SDMMC3_CMD_FUNC_SDMMC3 | pin_up);
pinmux_set_config(PINMUX_SDMMC3_DAT0_INDEX,
PINMUX_SDMMC3_DAT0_FUNC_SDMMC3 | pin_up);
pinmux_set_config(PINMUX_SDMMC3_DAT1_INDEX,
PINMUX_SDMMC3_DAT1_FUNC_SDMMC3 | pin_up);
pinmux_set_config(PINMUX_SDMMC3_DAT2_INDEX,
PINMUX_SDMMC3_DAT2_FUNC_SDMMC3 | pin_up);
pinmux_set_config(PINMUX_SDMMC3_DAT3_INDEX,
PINMUX_SDMMC3_DAT3_FUNC_SDMMC3 | pin_up);
pinmux_set_config(PINMUX_SDMMC3_CLK_LB_IN_INDEX,
PINMUX_SDMMC3_CLK_LB_IN_FUNC_SDMMC3 | pin_up3);
pinmux_set_config(PINMUX_SDMMC3_CLK_LB_OUT_INDEX,
PINMUX_SDMMC3_CLK_LB_OUT_FUNC_SDMMC3 | pin_down);
// MMC3 Card Detect pin.
gpio_input_pullup(GPIO(V2));
// Enable MMC power.
gpio_output(GPIO(R0), 1);
// MMC4
pinmux_set_config(PINMUX_SDMMC4_CLK_INDEX,
PINMUX_SDMMC4_CLK_FUNC_SDMMC4 | pin_none);
pinmux_set_config(PINMUX_SDMMC4_CMD_INDEX,
PINMUX_SDMMC4_CMD_FUNC_SDMMC4 | pin_up);
pinmux_set_config(PINMUX_SDMMC4_DAT0_INDEX,
PINMUX_SDMMC4_DAT0_FUNC_SDMMC4 | pin_up);
pinmux_set_config(PINMUX_SDMMC4_DAT1_INDEX,
PINMUX_SDMMC4_DAT1_FUNC_SDMMC4 | pin_up);
pinmux_set_config(PINMUX_SDMMC4_DAT2_INDEX,
PINMUX_SDMMC4_DAT2_FUNC_SDMMC4 | pin_up);
pinmux_set_config(PINMUX_SDMMC4_DAT3_INDEX,
PINMUX_SDMMC4_DAT3_FUNC_SDMMC4 | pin_up);
pinmux_set_config(PINMUX_SDMMC4_DAT4_INDEX,
PINMUX_SDMMC4_DAT4_FUNC_SDMMC4 | pin_up);
pinmux_set_config(PINMUX_SDMMC4_DAT5_INDEX,
PINMUX_SDMMC4_DAT5_FUNC_SDMMC4 | pin_up);
pinmux_set_config(PINMUX_SDMMC4_DAT6_INDEX,
PINMUX_SDMMC4_DAT6_FUNC_SDMMC4 | pin_up);
pinmux_set_config(PINMUX_SDMMC4_DAT7_INDEX,
PINMUX_SDMMC4_DAT7_FUNC_SDMMC4 | pin_up);
/* TODO: This is supposed to work with the USB special function pinmux,
* but it doesn't. Go with GPIOs for now and solve the problem later. */
gpio_output_open_drain(GPIO(N4), 1); /* USB VBUS EN0 */
gpio_output_open_drain(GPIO(N5), 1); /* USB VBUS EN1 */
}
static void setup_kernel_info(void)
{
// Setup required information for Linux kernel.
// pmc.odmdata: [18:19]: console type, [15:17]: UART id.
// TODO(hungte) This should be done by filling BCT values, or derived
// from CONFIG_CONSOLE_SERIAL_UART[A-E]. Right now we simply copy the
// value defined in BCT.
struct tegra_pmc_regs *pmc = (void*)TEGRA_PMC_BASE;
writel(0x80080000, &pmc->odmdata);
}
static void setup_ec_spi(void)
{
struct tegra_spi_channel *spi;
spi = tegra_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS);
/* Set frame header for use by CrOS EC */
spi->frame_header = 0xec;
spi->rx_frame_header_enable = 1;
}
static void mainboard_init(device_t dev)
{
set_clock_sources();
clock_enable_clear_reset(CLK_L_GPIO | CLK_L_I2C1 |
CLK_L_SDMMC4 | CLK_L_USBD,
CLK_H_EMC | CLK_H_I2C2 | CLK_H_SBC1 |
CLK_H_PMC | CLK_H_MEM | CLK_H_USB3,
CLK_U_I2C3 | CLK_U_CSITE | CLK_U_SDMMC3,
CLK_V_I2C4,
CLK_W_DVFS);
usb_setup_utmip1();
/* USB2 is the camera, we don't need it in firmware */
usb_setup_utmip3();
setup_pinmux();
i2c_init(0);
i2c_init(1);
i2c_init(2);
i2c_init(3);
setup_kernel_info();
clock_init_arm_generic_timer();
setup_ec_spi();
}
static void mainboard_enable(device_t dev)
@ -68,3 +234,14 @@ struct chip_operations mainboard_ops = {
.name = "nyan",
.enable_dev = mainboard_enable,
};
void lb_board(struct lb_header *header)
{
struct lb_range *dma;
dma = (struct lb_range *)lb_new_record(header);
dma->tag = LB_TAB_DMA;
dma->size = sizeof(*dma);
dma->range_start = CONFIG_DRAM_DMA_START;
dma->range_size = CONFIG_DRAM_DMA_SIZE;
}

View File

@ -61,9 +61,14 @@ static struct pmic_write pmic_writes[] =
* NOTE: We do this early because doing it later seems to hose the CPU
* power rail/partition startup. Need to debug.
*/
{ 0x16, 0x3f }
{ 0x16, 0x3f },
/* Don't write LDCONTROL - it's already 0xFF, i.e. all LDOs enabled. */
/* panel power GPIO O4. Set mode for GPIO4 (0x0c to 7), then set
* the value (register 0x20 bit 4)
*/
{ 0x0c, 0x07 },
{ 0x20, 0x10 },
};
void pmic_init(unsigned bus)

View File

@ -17,6 +17,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <arch/cache.h>
#include <arch/cpu.h>
#include <arch/exception.h>
#include <arch/stages.h>
#include <device/device.h>
#include <cbfs.h>
@ -25,11 +28,78 @@
#include "soc/nvidia/tegra124/chip.h"
#include <soc/display.h>
// Convenient shorthand (in MB)
#define DRAM_START (CONFIG_SYS_SDRAM_BASE >> 20)
#define DRAM_SIZE CONFIG_DRAM_SIZE_MB
#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */
enum {
L2CTLR_ECC_PARITY = 0x1 << 21,
L2CTLR_TAG_RAM_LATENCY_MASK = 0x7 << 6,
L2CTLR_TAG_RAM_LATENCY_CYCLES_3 = 2 << 6,
L2CTLR_DATA_RAM_LATENCY_MASK = 0x7 << 0,
L2CTLR_DATA_RAM_LATENCY_CYCLES_3 = 2 << 0
};
enum {
L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE = 0x1 << 27,
L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT = 0x1 << 7,
L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL = 0x1 << 3
};
/* Configures L2 Control Register to use 3 cycles for DATA/TAG RAM latency. */
static void configure_l2ctlr(void)
{
uint32_t val;
val = read_l2ctlr();
val &= ~(L2CTLR_DATA_RAM_LATENCY_MASK | L2CTLR_TAG_RAM_LATENCY_MASK);
val |= (L2CTLR_DATA_RAM_LATENCY_CYCLES_3 | L2CTLR_TAG_RAM_LATENCY_CYCLES_3 |
L2CTLR_ECC_PARITY);
write_l2ctlr(val);
}
/* Configures L2 Auxiliary Control Register for Cortex A15. */
static void configure_l2actlr(void)
{
uint32_t val;
val = read_l2actlr();
val |= (L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL |
L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT |
L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE);
write_l2actlr(val);
}
void main(void)
{
void *entry;
const struct device *soc;
const struct soc_nvidia_tegra124_config *config;
// Globally disable MMU, caches and branch prediction (these should
// already be disabled by default on reset).
uint32_t sctlr = read_sctlr();
sctlr &= ~(SCTLR_M | SCTLR_C | SCTLR_Z | SCTLR_I);
write_sctlr(sctlr);
arm_invalidate_caches();
// Renable icache and branch prediction.
sctlr = read_sctlr();
sctlr |= SCTLR_Z | SCTLR_I;
write_sctlr(sctlr);
configure_l2ctlr();
configure_l2actlr();
mmu_init();
mmu_config_range(0, DRAM_START, DCACHE_OFF);
mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK);
mmu_config_range(CONFIG_DRAM_DMA_START >> 20,
CONFIG_DRAM_DMA_SIZE >> 20, DCACHE_OFF);
mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF);
mmu_disable_range(0, 1);
dcache_invalidate_all();
dcache_mmu_enable();
exception_init();
/* for quality of the user interface, it's important to get
* the video going ASAP. Because there are long delays in some
@ -39,15 +109,17 @@ void main(void)
* early as we can in the RW stage, but never in the RO stage.
*/
soc = dev_find_slot(DEVICE_PATH_CPU_CLUSTER, 0);
const struct device *soc = dev_find_slot(DEVICE_PATH_CPU_CLUSTER, 0);
printk(BIOS_SPEW, "s%s: soc is %p\n", __func__, soc);
if (soc && soc->chip_info) {
config = soc->chip_info;
const struct soc_nvidia_tegra124_config *config =
soc->chip_info;
setup_display((struct soc_nvidia_tegra124_config *)config);
}
cbmem_initialize_empty();
entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram");
void *entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA,
"fallback/coreboot_ram");
stage_exit(entry);
}

View File

@ -561,4 +561,5 @@ struct disp_ctl_win {
};
void display_startup(device_t dev);
void dp_bringup(u32 winb_addr);
#endif /* __SOC_NVIDIA_TEGRA_DC_H */

View File

@ -0,0 +1,316 @@
/*
* drivers/video/tegra/dc/dpaux_regs.h
*
* Copyright (c) 2011, NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __SOC_NVIDIA_TEGRA_DISPLAYPORT_H__
#define __SOC_NVIDIA_TEGRA_DISPLAYPORT_H__
/* things we can't get rid of just yet. */
#define DPAUX_INTR_EN_AUX (0x1)
#define DPAUX_INTR_AUX (0x5)
#define DPAUX_DP_AUXDATA_WRITE_W(i) (0x9 + 4*(i))
#define DPAUX_DP_AUXDATA_READ_W(i) (0x19 + 4*(i))
#define DPAUX_DP_AUXADDR (0x29)
#define DPAUX_DP_AUXCTL (0x2d)
#define DPAUX_DP_AUXCTL_CMDLEN_SHIFT (0)
#define DPAUX_DP_AUXCTL_CMDLEN_FIELD (0xff)
#define DPAUX_DP_AUXCTL_CMD_SHIFT (12)
#define DPAUX_DP_AUXCTL_CMD_MASK (0xf << 12)
#define DPAUX_DP_AUXCTL_CMD_I2CWR (0 << 12)
#define DPAUX_DP_AUXCTL_CMD_I2CRD (1 << 12)
#define DPAUX_DP_AUXCTL_CMD_I2CREQWSTAT (2 << 12)
#define DPAUX_DP_AUXCTL_CMD_MOTWR (4 << 12)
#define DPAUX_DP_AUXCTL_CMD_MOTRD (5 << 12)
#define DPAUX_DP_AUXCTL_CMD_MOTREQWSTAT (6 << 12)
#define DPAUX_DP_AUXCTL_CMD_AUXWR (8 << 12)
#define DPAUX_DP_AUXCTL_CMD_AUXRD (9 << 12)
#define DPAUX_DP_AUXCTL_TRANSACTREQ_SHIFT (16)
#define DPAUX_DP_AUXCTL_TRANSACTREQ_MASK (0x1 << 16)
#define DPAUX_DP_AUXCTL_TRANSACTREQ_DONE (0 << 16)
#define DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING (1 << 16)
#define DPAUX_DP_AUXCTL_RST_SHIFT (31)
#define DPAUX_DP_AUXCTL_RST_DEASSERT (0 << 31)
#define DPAUX_DP_AUXCTL_RST_ASSERT (1 << 31)
#define DPAUX_DP_AUXSTAT (0x31)
#define DPAUX_DP_AUXSTAT_HPD_STATUS_SHIFT (28)
#define DPAUX_DP_AUXSTAT_HPD_STATUS_UNPLUG (0 << 28)
#define DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED (1 << 28)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_SHIFT (20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_MASK (0xf << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_IDLE (0 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_SYNC (1 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_START1 (2 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_COMMAND (3 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_ADDRESS (4 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_LENGTH (5 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_WRITE1 (6 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_READ1 (7 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_GET_M (8 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_STOP1 (9 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_STOP2 (10 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_REPLY (11 << 20)
#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_CLEANUP (12 << 20)
#define DPAUX_DP_AUXSTAT_REPLYTYPE_SHIFT (16)
#define DPAUX_DP_AUXSTAT_REPLYTYPE_MASK (0xf << 16)
#define DPAUX_DP_AUXSTAT_REPLYTYPE_ACK (0 << 16)
#define DPAUX_DP_AUXSTAT_REPLYTYPE_NACK (1 << 16)
#define DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER (2 << 16)
#define DPAUX_DP_AUXSTAT_REPLYTYPE_I2CNACK (4 << 16)
#define DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER (8 << 16)
#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR_SHIFT (11)
#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR_NOT_PENDING (0 << 11)
#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING (1 << 11)
#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_SHIFT (10)
#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_NOT_PENDING (0 << 10)
#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING (1 << 10)
#define DPAUX_DP_AUXSTAT_RX_ERROR_SHIFT (9)
#define DPAUX_DP_AUXSTAT_RX_ERROR_NOT_PENDING (0 << 9)
#define DPAUX_DP_AUXSTAT_RX_ERROR_PENDING (1 << 9)
#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_SHIFT (8)
#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_NOT_PENDING (0 << 8)
#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING (1 << 8)
#define DPAUX_DP_AUXSTAT_REPLY_M_SHIFT (0)
#define DPAUX_DP_AUXSTAT_REPLY_M_MASK (0xff << 0)
#define DPAUX_HPD_CONFIG (0x3d)
#define DPAUX_HPD_IRQ_CONFIG (0x41)
#define DPAUX_DP_AUX_CONFIG (0x45)
#define DPAUX_HYBRID_PADCTL (0x49)
#define DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_SHIFT (15)
#define DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_DISABLE (0 << 15)
#define DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_ENABLE (1 << 15)
#define DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_SHIFT (14)
#define DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_DISABLE (0 << 14)
#define DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_ENABLE (1 << 14)
#define DPAUX_HYBRID_PADCTL_AUX_CMH_SHIFT (12)
#define DPAUX_HYBRID_PADCTL_AUX_CMH_DEFAULT_MASK (0x3 << 12)
#define DPAUX_HYBRID_PADCTL_AUX_CMH_V0_60 (0 << 12)
#define DPAUX_HYBRID_PADCTL_AUX_CMH_V0_64 (1 << 12)
#define DPAUX_HYBRID_PADCTL_AUX_CMH_V0_70 (2 << 12)
#define DPAUX_HYBRID_PADCTL_AUX_CMH_V0_56 (3 << 12)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_SHIFT (8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_DEFAULT_MASK (0x7 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_78 (0 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_60 (1 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_54 (2 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_45 (3 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_50 (4 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_42 (5 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_39 (6 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_34 (7 << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVI_SHIFT (2)
#define DPAUX_HYBRID_PADCTL_AUX_DRVI_DEFAULT_MASK (0x3f << 2)
#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_SHIFT (1)
#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_DISABLE (0 << 1)
#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE (1 << 1)
#define DPAUX_HYBRID_PADCTL_MODE_SHIFT (0)
#define DPAUX_HYBRID_PADCTL_MODE_AUX (0)
#define DPAUX_HYBRID_PADCTL_MODE_I2C (1)
#define DPAUX_HYBRID_SPARE (0x4d)
#define DPAUX_HYBRID_SPARE_PAD_PWR_POWERUP (0)
#define DPAUX_HYBRID_SPARE_PAD_PWR_POWERDOWN (1)
/* TODO: figure out which of the NV_ constants are the same as all the other
* display port standard constants.
*/
#define DP_AUX_DEFER_MAX_TRIES 7
#define DP_AUX_TIMEOUT_MAX_TRIES 2
#define DP_POWER_ON_MAX_TRIES 3
#define DP_CLOCK_RECOVERY_MAX_TRIES 7
#define DP_CLOCK_RECOVERY_TOT_TRIES 15
#define DP_AUX_MAX_BYTES 16
#define DP_LCDVCC_TO_HPD_DELAY_MS 200
#define DP_AUX_TIMEOUT_MS 40
#define DP_DPCP_RETRY_SLEEP_NS 400
enum {
driveCurrent_Level0 = 0,
driveCurrent_Level1 = 1,
driveCurrent_Level2 = 2,
driveCurrent_Level3 = 3,
};
enum {
preEmphasis_Disabled = 0,
preEmphasis_Level1 = 1,
preEmphasis_Level2 = 2,
preEmphasis_Level3 = 3,
};
enum {
postCursor2_Level0 = 0,
postCursor2_Level1 = 1,
postCursor2_Level2 = 2,
postCursor2_Level3 = 3,
postCursor2_Supported
};
/* the +10ms is the time for power rail going up from 10-90% or
90%-10% on powerdown */
/* Time from power-rail is turned on and aux/12c-over-aux is available */
#define EDP_PWR_ON_TO_AUX_TIME_MS (200+10)
/* Time from power-rail is turned on and MainLink is available for LT */
#define EDP_PWR_ON_TO_ML_TIME_MS (200+10)
/* Time from turning off power to turn-it on again (does not include post
poweron time) */
#define EDP_PWR_OFF_TO_ON_TIME_MS (500+10)
struct tegra_dc_dp_data {
struct tegra_dc *dc;
struct tegra_dc_sor_data *sor;
void *aux_base;
struct tegra_dc_mode *mode;
struct tegra_dc_dp_link_config link_cfg;
};
/* DPCD definitions */
/* you know, all the vendors pick their own set of defines.
* All of them.
* FIXME so we can use the ones in include/device/drm_dp_helper.h
*/
#define NV_DPCD_REV (0x00000000)
#define NV_DPCD_REV_MAJOR_SHIFT (4)
#define NV_DPCD_REV_MAJOR_MASK (0xf << 4)
#define NV_DPCD_REV_MINOR_SHIFT (0)
#define NV_DPCD_REV_MINOR_MASK (0xf)
#define NV_DPCD_MAX_LINK_BANDWIDTH (0x00000001)
#define NV_DPCD_MAX_LINK_BANDWIDTH_VAL_1_62_GPBS (0x00000006)
#define NV_DPCD_MAX_LINK_BANDWIDTH_VAL_2_70_GPBS (0x0000000a)
#define NV_DPCD_MAX_LINK_BANDWIDTH_VAL_5_40_GPBS (0x00000014)
#define NV_DPCD_MAX_LANE_COUNT (0x00000002)
#define NV_DPCD_MAX_LANE_COUNT_MASK (0x1f)
#define NV_DPCD_MAX_LANE_COUNT_LANE_1 (0x00000001)
#define NV_DPCD_MAX_LANE_COUNT_LANE_2 (0x00000002)
#define NV_DPCD_MAX_LANE_COUNT_LANE_4 (0x00000004)
#define NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_NO (0x00000000 << 7)
#define NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_YES (0x00000001 << 7)
#define NV_DPCD_MAX_DOWNSPREAD (0x00000003)
#define NV_DPCD_MAX_DOWNSPREAD_VAL_NONE (0x00000000)
#define NV_DPCD_MAX_DOWNSPREAD_VAL_0_5_PCT (0x00000001)
#define NV_DPCD_MAX_DOWNSPREAD_NO_AUX_HANDSHAKE_LT_F (0x00000000 << 6)
#define NV_DPCD_MAX_DOWNSPREAD_NO_AUX_HANDSHAKE_LT_T (0x00000001 << 6)
#define NV_DPCD_EDP_CONFIG_CAP (0x0000000D)
#define NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_NO (0x00000000)
#define NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_YES (0x00000001)
#define NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_NO (0x00000000 << 1)
#define NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES (0x00000001 << 1)
#define NV_DPCD_LINK_BANDWIDTH_SET (0x00000100)
#define NV_DPCD_LANE_COUNT_SET (0x00000101)
#define NV_DPCD_LANE_COUNT_SET_ENHANCEDFRAMING_F (0x00000000 << 7)
#define NV_DPCD_LANE_COUNT_SET_ENHANCEDFRAMING_T (0x00000001 << 7)
#define NV_DPCD_TRAINING_PATTERN_SET (0x00000102)
#define NV_DPCD_TRAINING_PATTERN_SET_TPS_MASK 0x3
#define NV_DPCD_TRAINING_PATTERN_SET_TPS_NONE (0x00000000)
#define NV_DPCD_TRAINING_PATTERN_SET_TPS_TP1 (0x00000001)
#define NV_DPCD_TRAINING_PATTERN_SET_TPS_TP2 (0x00000002)
#define NV_DPCD_TRAINING_PATTERN_SET_TPS_TP3 (0x00000003)
#define NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_F (0x00000000 << 5)
#define NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_T (0x00000001 << 5)
#define NV_DPCD_TRAINING_LANE0_SET (0x00000103)
#define NV_DPCD_TRAINING_LANE1_SET (0x00000104)
#define NV_DPCD_TRAINING_LANE2_SET (0x00000105)
#define NV_DPCD_TRAINING_LANE3_SET (0x00000106)
#define NV_DPCD_TRAINING_LANEX_SET_DC_SHIFT 0
#define NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_T (0x00000001 << 2)
#define NV_DPCD_TRAINING_LANEX_SET_PE_SHIFT 3
#define NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_T (0x00000001 << 5)
#define NV_DPCD_DOWNSPREAD_CTRL (0x00000107)
#define NV_DPCD_DOWNSPREAD_CTRL_SPREAD_AMP_NONE (0x00000000 << 4)
#define NV_DPCD_DOWNSPREAD_CTRL_SPREAD_AMP_LT_0_5 (0x00000001 << 4)
#define NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET (0x00000108)
#define NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET_ANSI_8B10B 1
#define NV_DPCD_EDP_CONFIG_SET (0x0000010A)
#define NV_DPCD_EDP_CONFIG_SET_ASC_RESET_DISABLE (0x00000000)
#define NV_DPCD_EDP_CONFIG_SET_ASC_RESET_ENABLE (0x00000001)
#define NV_DPCD_EDP_CONFIG_SET_FRAMING_CHANGE_DISABLE (0x00000000 << 1)
#define NV_DPCD_EDP_CONFIG_SET_FRAMING_CHANGE_ENABLE (0x00000001 << 1)
#define NV_DPCD_TRAINING_LANE0_1_SET2 (0x0000010F)
#define NV_DPCD_TRAINING_LANE2_3_SET2 (0x00000110)
#define NV_DPCD_LANEX_SET2_PC2_SHIFT 0
#define NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_T (0x00000001 << 2)
#define NV_DPCD_LANEXPLUS1_SET2_PC2_SHIFT 4
#define NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_T (0x00000001 << 6)
#define NV_DPCD_SINK_COUNT (0x00000200)
#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR (0x00000201)
#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_AUTO_TEST_NO (0x00000000 << 1)
#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_AUTO_TEST_YES (0x00000001 << 1)
#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_CP_NO (0x00000000 << 2)
#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_CP_YES (0x00000001 << 2)
#define NV_DPCD_LANE0_1_STATUS (0x00000202)
#define NV_DPCD_LANE2_3_STATUS (0x00000203)
#define NV_DPCD_STATUS_LANEX_CR_DONE_SHIFT 0
#define NV_DPCD_STATUS_LANEX_CR_DONE_NO (0x00000000)
#define NV_DPCD_STATUS_LANEX_CR_DONE_YES (0x00000001)
#define NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT 1
#define NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_NO (0x00000000 << 1)
#define NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_YES (0x00000001 << 1)
#define NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT 2
#define NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_NO (0x00000000 << 2)
#define NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_YES (0x00000001 << 2)
#define NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_SHIFT 4
#define NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_NO (0x00000000 << 4)
#define NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES (0x00000001 << 4)
#define NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_SHIFT 5
#define NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_NO (0x00000000 << 5)
#define NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_YES (0x00000001 << 5)
#define NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_SHIFT 6
#define NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_NO (0x00000000 << 6)
#define NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_YES (0x00000001 << 6)
#define NV_DPCD_LANE_ALIGN_STATUS_UPDATED (0x00000204)
#define NV_DPCD_LANE_ALIGN_STATUS_UPDATED_DONE_NO (0x00000000)
#define NV_DPCD_LANE_ALIGN_STATUS_UPDATED_DONE_YES (0x00000001)
#define NV_DPCD_LANE0_1_ADJUST_REQ (0x00000206)
#define NV_DPCD_LANE2_3_ADJUST_REQ (0x00000207)
#define NV_DPCD_ADJUST_REQ_LANEX_DC_SHIFT 0
#define NV_DPCD_ADJUST_REQ_LANEX_DC_MASK 0x3
#define NV_DPCD_ADJUST_REQ_LANEX_PE_SHIFT 2
#define NV_DPCD_ADJUST_REQ_LANEX_PE_MASK (0x3 << 2)
#define NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_SHIFT 4
#define NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_MASK (0x3 << 4)
#define NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_SHIFT 6
#define NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_MASK (0x3 << 6)
#define NV_DPCD_ADJUST_REQ_POST_CURSOR2 (0x0000020C)
#define NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_MASK 0x3
#define NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_SHIFT(i) (i*2)
#define NV_DPCD_TEST_REQUEST (0x00000218)
#define NV_DPCD_SOURCE_IEEE_OUI (0x00000300)
#define NV_DPCD_SINK_IEEE_OUI (0x00000400)
#define NV_DPCD_BRANCH_IEEE_OUI (0x00000500)
#define NV_DPCD_SET_POWER (0x00000600)
#define NV_DPCD_SET_POWER_VAL_RESERVED (0x00000000)
#define NV_DPCD_SET_POWER_VAL_D0_NORMAL (0x00000001)
#define NV_DPCD_SET_POWER_VAL_D3_PWRDWN (0x00000002)
#define NV_DPCD_HDCP_BKSV_OFFSET (0x00068000)
#define NV_DPCD_HDCP_RPRIME_OFFSET (0x00068005)
#define NV_DPCD_HDCP_AKSV_OFFSET (0x00068007)
#define NV_DPCD_HDCP_AN_OFFSET (0x0006800C)
#define NV_DPCD_HDCP_VPRIME_OFFSET (0x00068014)
#define NV_DPCD_HDCP_BCAPS_OFFSET (0x00068028)
#define NV_DPCD_HDCP_BSTATUS_OFFSET (0x00068029)
#define NV_DPCD_HDCP_BINFO_OFFSET (0x0006802A)
#define NV_DPCD_HDCP_KSV_FIFO_OFFSET (0x0006802C)
#define NV_DPCD_HDCP_AINFO_OFFSET (0x0006803B)
int tegra_dc_dpaux_read(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr,
u8 *data, u32 *size, u32 *aux_stat);
int dpaux_write(u32 addr, u32 size, u32 data);
int dpaux_read(u32 addr, u32 size, u8 *data);
void debug_dpaux_print(u32 addr, u32 size);
void dp_link_training(u32 lanes, u32 speed);
#endif /* __SOC_NVIDIA_TEGRA_DISPLAYPORT_H__ */

586
src/soc/nvidia/tegra/dp.c Normal file
View File

@ -0,0 +1,586 @@
/*
* drivers/video/tegra/dc/dp.c
*
* Copyright (c) 2011-2013, NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <arch/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/i2c.h>
#include <stdlib.h>
#include <string.h>
#include <delay.h>
#include <soc/addressmap.h>
#include "i2c.h"
#include "dc.h"
/* shit. This is broken. */
#include <soc/nvidia/tegra124/sor.h>
// this is really broken. #include <soc/ardpaux.h>
#include <soc/nvidia/tegra/displayport.h>
extern int dump;
unsigned long READL(void* p);
void WRITEL(unsigned long value, void* p);
static inline u32 tegra_dpaux_readl(struct tegra_dc_dp_data *dp, u32 reg)
{
void *addr = dp->aux_base + (u32)(reg <<2);
u32 reg_val = READL(addr);
return reg_val;
}
static inline void tegra_dpaux_writel(struct tegra_dc_dp_data *dp,
u32 reg, u32 val)
{
void *addr = dp->aux_base + (u32)(reg <<2);
WRITEL(val, addr);
}
static inline u32 tegra_dc_dpaux_poll_register(struct tegra_dc_dp_data *dp,
u32 reg, u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_ms)
{
// unsigned long timeout_jf = jiffies + msecs_to_jiffies(timeout_ms);
u32 reg_val = 0;
printk(BIOS_SPEW, "JZ: %s: enter, poll_reg: %#x: timeout: 0x%x\n",
__func__, reg*4, timeout_ms);
do {
// udelay(poll_interval_us);
udelay(1);
reg_val = tegra_dpaux_readl(dp, reg);
} while (((reg_val & mask) != exp_val) && (--timeout_ms > 0));
if ((reg_val & mask) == exp_val)
return 0; /* success */
printk(BIOS_SPEW,"dpaux_poll_register 0x%x: timeout: (reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n", reg, reg_val, mask, exp_val);
return timeout_ms;
}
static inline int tegra_dpaux_wait_transaction(struct tegra_dc_dp_data *dp)
{
/* According to DP spec, each aux transaction needs to finish
within 40ms. */
if (tegra_dc_dpaux_poll_register(dp, DPAUX_DP_AUXCTL,
DPAUX_DP_AUXCTL_TRANSACTREQ_MASK,
DPAUX_DP_AUXCTL_TRANSACTREQ_DONE,
100, DP_AUX_TIMEOUT_MS*1000) != 0) {
printk(BIOS_SPEW,"dp: DPAUX transaction timeout\n");
return -1;
}
return 0;
}
static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
u32 addr, u8 *data, u32 *size, u32 *aux_stat)
{
int i;
u32 reg_val;
u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
u32 temp_data;
if (*size > DP_AUX_MAX_BYTES)
return -1; /* only write one chunk of data */
/* Make sure the command is write command */
switch (cmd) {
case DPAUX_DP_AUXCTL_CMD_I2CWR:
case DPAUX_DP_AUXCTL_CMD_MOTWR:
case DPAUX_DP_AUXCTL_CMD_AUXWR:
break;
default:
printk(BIOS_SPEW,"dp: aux write cmd 0x%x is invalid\n",
cmd);
return -1;
}
#if 0
/* interesting. */
if (tegra_platform_is_silicon()) {
*aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
printk(BIOS_SPEW,"dp: HPD is not detected\n");
return -EFAULT;
}
}
#endif
tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
for (i = 0; i < DP_AUX_MAX_BYTES/4; ++i) {
memcpy(&temp_data, data, 4);
tegra_dpaux_writel(dp, DPAUX_DP_AUXDATA_WRITE_W(i),
temp_data);
data += 4;
}
reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
reg_val |= cmd;
reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
reg_val |= ((*size-1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
while ((timeout_retries > 0) && (defer_retries > 0)) {
if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) ||
(defer_retries != DP_AUX_DEFER_MAX_TRIES))
udelay(1);
reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
if (tegra_dpaux_wait_transaction(dp))
printk(BIOS_SPEW,"dp: aux write transaction timeout\n");
*aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
(*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
(*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
(*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) {
if (timeout_retries-- > 0) {
printk(BIOS_SPEW,"dp: aux write retry (0x%x) -- %d\n",
*aux_stat, timeout_retries);
/* clear the error bits */
tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
*aux_stat);
continue;
} else {
printk(BIOS_SPEW,"dp: aux write got error (0x%x)\n",
*aux_stat);
return -1;
}
}
if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) ||
(*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) {
if (defer_retries-- > 0) {
printk(BIOS_SPEW, "dp: aux write defer (0x%x) -- %d\n",
*aux_stat, defer_retries);
/* clear the error bits */
tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
*aux_stat);
continue;
} else {
printk(BIOS_SPEW, "dp: aux write defer exceeds max retries "
"(0x%x)\n",
*aux_stat);
return -1;
}
}
if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) ==
DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) {
*size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
return 0;
} else {
printk(BIOS_SPEW,"dp: aux write failed (0x%x)\n", *aux_stat);
return -1;
}
}
/* Should never come to here */
return -1;
}
static int tegra_dc_dpaux_write(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr,
u8 *data, u32 *size, u32 *aux_stat)
{
u32 cur_size = 0;
u32 finished = 0;
u32 cur_left;
int ret = 0;
do {
cur_size = *size - finished;
if (cur_size > DP_AUX_MAX_BYTES)
cur_size = DP_AUX_MAX_BYTES;
cur_left = cur_size;
ret = tegra_dc_dpaux_write_chunk(dp, cmd, addr,
data, &cur_left, aux_stat);
cur_size -= cur_left;
finished += cur_size;
addr += cur_size;
data += cur_size;
if (ret)
break;
} while (*size > finished);
*size = finished;
return ret;
}
static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
u32 addr, u8 *data, u32 *size, u32 *aux_stat)
{
u32 reg_val;
u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
if (*size > DP_AUX_MAX_BYTES)
return -1; /* only read one chunk */
/* Check to make sure the command is read command */
switch (cmd) {
case DPAUX_DP_AUXCTL_CMD_I2CRD:
case DPAUX_DP_AUXCTL_CMD_I2CREQWSTAT:
case DPAUX_DP_AUXCTL_CMD_MOTRD:
case DPAUX_DP_AUXCTL_CMD_AUXRD:
break;
default:
printk(BIOS_SPEW,"dp: aux read cmd 0x%x is invalid\n", cmd);
return -1;
}
if (0){
*aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
printk(BIOS_SPEW,"dp: HPD is not detected\n");
//return EFAULT;
}
}
tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
reg_val |= cmd;
printk(BIOS_SPEW, "cmd = %08x\n", reg_val);
reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
reg_val |= ((*size-1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
printk(BIOS_SPEW, "cmd = %08x\n", reg_val);
while ((timeout_retries > 0) && (defer_retries > 0)) {
if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) ||
(defer_retries != DP_AUX_DEFER_MAX_TRIES))
udelay(DP_DPCP_RETRY_SLEEP_NS * 2);
reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
printk(BIOS_SPEW, "cmd = %08x\n", reg_val);
tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
if (tegra_dpaux_wait_transaction(dp))
printk(BIOS_SPEW,"dp: aux read transaction timeout\n");
*aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
printk(BIOS_SPEW, "dp: %s: aux stat: 0x%08x\n", __func__, *aux_stat);
if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
(*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
(*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
(*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) {
if (timeout_retries-- > 0) {
printk(BIOS_SPEW, "dp: aux read retry (0x%x) -- %d\n",
*aux_stat, timeout_retries);
/* clear the error bits */
tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
*aux_stat);
continue; /* retry */
} else {
printk(BIOS_SPEW,"dp: aux read got error (0x%x)\n",
*aux_stat);
return -1;
}
}
if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) ||
(*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) {
if (defer_retries-- > 0) {
printk(BIOS_SPEW, "dp: aux read defer (0x%x) -- %d\n",
*aux_stat, defer_retries);
/* clear the error bits */
tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
*aux_stat);
continue;
} else {
printk(BIOS_SPEW,"dp: aux read defer exceeds max retries "
"(0x%x)\n", *aux_stat);
return -1;
}
}
if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) ==
DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) {
int i;
u32 temp_data[4];
for (i = 0; i < DP_AUX_MAX_BYTES/4; ++i)
temp_data[i] = tegra_dpaux_readl(dp,
DPAUX_DP_AUXDATA_READ_W(i));
*size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
printk(BIOS_SPEW, "dp: aux read data %d bytes\n", *size);
memcpy(data, temp_data, *size);
return 0;
} else {
printk(BIOS_SPEW,"dp: aux read failed (0x%x\n", *aux_stat);
return -1;
}
}
/* Should never come to here */
printk(BIOS_SPEW, "%s: can't\n", __func__);
return -1;
}
int tegra_dc_dpaux_read(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr,
u8 *data, u32 *size, u32 *aux_stat)
{
u32 finished = 0;
u32 cur_size;
int ret = 0;
do {
cur_size = *size - finished;
if (cur_size > DP_AUX_MAX_BYTES)
cur_size = DP_AUX_MAX_BYTES;
ret = tegra_dc_dpaux_read_chunk(dp, cmd, addr,
data, &cur_size, aux_stat);
/* cur_size should be the real size returned */
addr += cur_size;
data += cur_size;
finished += cur_size;
if (ret)
break;
#if 0
if (cur_size == 0) {
printk(BIOS_SPEW,"JZ: no data found, ret\n");
break;
}
#endif
} while (*size > finished);
*size = finished;
return ret;
}
static int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd,
u8 *data_ptr)
{
u32 size = 1;
u32 status = 0;
int ret;
ret = tegra_dc_dpaux_read_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
cmd, data_ptr, &size, &status);
if (ret)
printk(BIOS_SPEW,"dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n",
cmd, status);
return ret;
}
static int tegra_dc_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp,
struct tegra_dc_dp_link_config *cfg)
{
u8 dpcd_data;
int ret;
ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LANE_COUNT,
&dpcd_data);
if (ret)
return ret;
cfg->max_lane_count = dpcd_data & NV_DPCD_MAX_LANE_COUNT_MASK;
printk(BIOS_SPEW, "JZ: %s: max_lane_count: %d\n", __func__, cfg->max_lane_count);
cfg->support_enhanced_framing =
(dpcd_data & NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_YES) ?
1 : 0;
printk(BIOS_SPEW, "JZ: %s: enh-framing: %d\n", __func__, cfg->support_enhanced_framing);
ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_DOWNSPREAD,
&dpcd_data);
if (ret)
return ret;
cfg->downspread = (dpcd_data & NV_DPCD_MAX_DOWNSPREAD_VAL_0_5_PCT) ?
1 : 0;
printk(BIOS_SPEW, "JZ: %s: downspread: %d\n", __func__, cfg->downspread);
ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LINK_BANDWIDTH,
&cfg->max_link_bw);
if (ret)
return ret;
printk(BIOS_SPEW, "JZ: %s: max_link_bw: %d\n", __func__, cfg->max_link_bw);
// jz, changed
// cfg->bits_per_pixel = dp->dc->pdata->default_out->depth;
cfg->bits_per_pixel = 24;
/* TODO: need to come from the board file */
/* Venice2 settings */
cfg->drive_current = 0x20202020;
cfg->preemphasis = 0;
cfg->postcursor = 0;
ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_EDP_CONFIG_CAP,
&dpcd_data);
if (ret)
return ret;
cfg->alt_scramber_reset_cap =
(dpcd_data & NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_YES) ?
1 : 0;
cfg->only_enhanced_framing =
(dpcd_data & NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES) ?
1 : 0;
printk(BIOS_SPEW, "JZ: %s: alt_reset_cap: %d, only_enh_framing: %d\n", __func__,
cfg->alt_scramber_reset_cap, cfg->only_enhanced_framing);
cfg->lane_count = cfg->max_lane_count;
cfg->link_bw = cfg->max_link_bw;
cfg->enhanced_framing = cfg->support_enhanced_framing;
return 0;
}
//struct tegra_dc dc_data = {0};
struct tegra_dc_sor_data sor_data = {0};
struct tegra_dc_dp_data dp_data = {0};
static int tegra_dc_dpcd_read_rev(struct tegra_dc_dp_data *dp,
u8 *rev)
{
u32 size;
int ret;
u32 status = 0;
size = 3;
ret = tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
NV_DPCD_REV, rev, &size, &status);
if (ret) {
printk(BIOS_SPEW,"dp: Failed to read NV_DPCD_REV\n");
return ret;
}
return 0;
}
u32 dp_setup_timing(u32 panel_id, u32 width, u32 height);
void dp_bringup(u32 winb_addr)
{
struct tegra_dc_dp_data *dp = &dp_data;
u32 dpcd_rev;
u32 pclk_freq;
// int ret;
printk(BIOS_SPEW, "JZ: %s: entry\n",__func__);
dp->sor = &sor_data;
// dp->sor->dc = dc;
dp->sor->base = (void *)TEGRA_ARM_SOR;
// dp->sor->base_res = base_res;
// dp->sor->sor_clk = clk;
dp->sor->link_cfg = &dp->link_cfg;
dp->sor->portnum = 0;
dp->aux_base = (void *)TEGRA_ARM_DPAUX;
/* dp->mode = 0; */ /* ???? */
/* read panel info */
if (!tegra_dc_dpcd_read_rev(dp, (u8 *)&dpcd_rev)) {
printk(BIOS_SPEW,"PANEL info: \n");
printk(BIOS_SPEW,"--DPCP version(%#x): %d.%d\n",
dpcd_rev, (dpcd_rev >> 4)&0x0f, (dpcd_rev & 0x0f));
}
if (tegra_dc_dp_init_max_link_cfg(dp, &dp->link_cfg))
printk(BIOS_SPEW,"dp: failed to init link configuration\n");
dp_link_training((u32)(dp->link_cfg.lane_count),
(u32)(dp->link_cfg.link_bw));
pclk_freq = dp_setup_timing(5, 2560, 1700); // W: 2560, H: 1700, use_plld2: 1
printk(BIOS_SPEW, "JZ: %s: pclk_freq: %d\n",__func__, pclk_freq);
// void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr)
void dp_misc_setting(u32 panel_bpp, u32 width, u32 height, u32 winb_addr,
u32 lane_count, u32 enhanced_framing, u32 panel_edp,
u32 pclkfreq, u32 linkfreq);
dp_misc_setting(dp->link_cfg.bits_per_pixel,
2560, 1700, winb_addr,
(u32)dp->link_cfg.lane_count,
(u32)dp->link_cfg.enhanced_framing,
(u32)dp->link_cfg.alt_scramber_reset_cap,
pclk_freq,
dp->link_cfg.link_bw * 27);
}
void debug_dpaux_print(u32 addr, u32 size)
{
struct tegra_dc_dp_data *dp = &dp_data;
u32 status = 0;
u8 buf[16];
int i;
if ((size == 0) || (size > 16)) {
printk(BIOS_SPEW,"dp: %s: invalid size %d\n", __func__, size);
return;
}
if (tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
addr, buf, &size, &status)) {
printk(BIOS_SPEW,"******AuxRead Error: 0x%04x: status 0x%08x\n", addr, status);
return;
}
printk(BIOS_SPEW, "%s: addr: 0x%04x, size: %d\n", __func__, addr, size);
for (i=0; i < size; ++i)
printk(BIOS_SPEW," %02x", buf[i]);
printk(BIOS_SPEW,"\n");
}
int dpaux_read(u32 addr, u32 size, u8 *data)
{
struct tegra_dc_dp_data *dp = &dp_data;
u32 status = 0;
if ((size == 0) || (size > 16)) {
printk(BIOS_SPEW,"dp: %s: invalid size %d\n", __func__, size);
return -1;
}
if (tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
addr, data, &size, &status)) {
printk(BIOS_SPEW,"dp: Failed to read reg %#x, status: %#x\n", addr, status);
return -1;
}
return 0;
}
int dpaux_write(u32 addr, u32 size, u32 data)
{
struct tegra_dc_dp_data *dp = &dp_data;
u32 status = 0;
int ret;
printk(BIOS_SPEW, "JZ: %s: entry, addr: 0x%08x, size: 0x%08x, data: %#x\n",
__func__, addr, size, data);
ret = tegra_dc_dpaux_write(dp, DPAUX_DP_AUXCTL_CMD_AUXWR,
addr, (u8 *)&data, &size, &status);
if (ret)
printk(BIOS_SPEW,"dp: Failed to write to reg %#x, status: 0x%x\n",
addr, status);
return ret;
}

View File

@ -36,15 +36,13 @@ void __gpio_input(gpio_t gpio, u32 pull)
pinmux_set_config(gpio >> GPIO_PINMUX_SHIFT, pinmux_config);
}
void gpio_output(gpio_t gpio, int value)
void __gpio_output(gpio_t gpio, int value, u32 od)
{
/* TODO: Set OPEN_DRAIN based on what pin it is? */
gpio_set_int_enable(gpio, 0);
gpio_set_out_value(gpio, value);
gpio_set_out_enable(gpio, 1);
gpio_set_mode(gpio, GPIO_MODE_GPIO);
pinmux_set_config(gpio >> GPIO_PINMUX_SHIFT, PINMUX_PULL_NONE);
pinmux_set_config(gpio >> GPIO_PINMUX_SHIFT, PINMUX_PULL_NONE | od);
}
enum {

View File

@ -31,10 +31,20 @@ typedef u32 gpio_t;
#define GPIO(name) ((gpio_t)(GPIO_##name##_INDEX | \
(PINMUX_GPIO_##name << GPIO_PINMUX_SHIFT)))
void __gpio_output(gpio_t gpio, int value, u32 open_drain);
void __gpio_input(gpio_t gpio, u32 pull);
/* Higher level function wrappers for common GPIO configurations. */
void gpio_output(gpio_t gpio, int value);
void __gpio_input(gpio_t gpio, u32 pull);
static inline void gpio_output(gpio_t gpio, int value)
{
__gpio_output(gpio, value, 0);
}
static inline void gpio_output_open_drain(gpio_t gpio, int value)
{
__gpio_output(gpio, value, PINMUX_OPEN_DRAIN);
}
static inline void gpio_input(gpio_t gpio)
{

120
src/soc/nvidia/tegra/usb.c Normal file
View File

@ -0,0 +1,120 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <delay.h>
#include <arch/io.h>
#include <console/console.h>
#include <soc/clock.h>
#include "usb.h"
/* Assume USBx clocked, out of reset, UTMI+ PLL set up, SAMP_x out of pwrdn */
void usb_setup_utmip(struct usb_ctlr *usb)
{
/* KHz formulas were guessed from U-Boot constants. Formats unclear. */
int khz = clock_get_osc_khz();
/* Stop UTMI+ crystal clock while we mess with its settings */
clrbits_le32(&usb->utmip.misc1, 1 << 30); /* PHY_XTAL_CLKEN */
udelay(1);
/* Take stuff out of pwrdn and add some magic numbers from U-Boot */
write32(0x8 << 25 | /* HS slew rate [10:4] */
0x3 << 22 | /* HS driver output 'SETUP' [6:4] */
0 << 21 | /* LS bias selection */
0 << 18 | /* PDZI pwrdn */
0 << 16 | /* PD2 pwrdn */
0 << 14 | /* PD pwrdn */
1 << 13 | /* (rst) HS receiver terminations */
0x1 << 10 | /* (rst) LS falling slew rate */
0x1 << 8 | /* (rst) LS rising slew rate */
0x4 << 0 | /* HS driver output 'SETUP' [3:0] */
0, &usb->utmip.xcvr0);
write32(0x7 << 18 | /* Termination range adjustment */
0 << 4 | /* PDDR pwrdn */
0 << 2 | /* PDCHRP pwrdn */
0 << 0 | /* PDDISC pwrdn */
0, &usb->utmip.xcvr1);
write32(1 << 19 | /* FS send initial J before sync(?) */
1 << 16 | /* (rst) Allow stuff error on SoP */
1 << 9 | /* (rst) Check disc only on EoP */
0, &usb->utmip.tx);
write32(0x2 << 30 | /* (rst) Keep pattern on active */
1 << 28 | /* (rst) Realign inertia on pkt */
0x1 << 24 | /* (rst) edges-1 to move sampling */
0x3 << 21 | /* (rst) squelch delay on EoP */
0x11 << 15 | /* cycles until IDLE */
0x10 << 10 | /* elastic input depth */
0, &usb->utmip.hsrx0);
/* U-Boot claims the USBD values for these are used across all UTMI+
* PHYs. That sounds so horribly wrong that I'm not going to implement
* it, but keep it in mind if we're ever not using the USBD port. */
write32(0x1 << 24 | /* HS disconnect detect level [2] */
1 << 23 | /* (rst) IDPD value */
1 << 22 | /* (rst) IDPD select */
1 << 11 | /* (rst) OTG pwrdn */
0 << 10 | /* bias pwrdn */
0x1 << 2 | /* HS disconnect detect level [1:0] */
0x2 << 0 | /* HS squelch detect level */
0, &usb->utmip.bias0);
write32(khz / 2200 << 3 | /* bias pwrdn cycles (20us?) */
1 << 2 | /* (rst) VBUS wakeup pwrdn */
0 << 0 | /* PDTRK pwrdn */
0, &usb->utmip.bias1);
write32(0xffff << 16 | /* (rst) */
25 * khz / 10 << 0 | /* TODO: what's this, really? */
0, &usb->utmip.debounce);
udelay(1);
setbits_le32(&usb->utmip.misc1, 1 << 30); /* PHY_XTAL_CLKEN */
write32(1 << 12 | /* UTMI+ enable */
0 << 11 | /* UTMI+ reset */
0, &usb->suspend_ctrl);
}
/*
* Tegra EHCI controllers need their usb_mode and lpm_ctrl registers initialized
* after every EHCI reset and before any other actions (such as Run/Stop bit)
* are taken. We reset the controller here, set those registers and rely on the
* fact that libpayload doesn't reset EHCI controllers on initialization for
* whatever weird reason. This is ugly, fragile, and I really don't like it, but
* making this work will require an ugly hack one way or another so we might as
* well take the path of least resistance for now.
*/
void usb_ehci_reset_and_prepare(struct usb_ctlr *usb, enum usb_phy_type type)
{
int timeout = 1000;
write32(1 << 1, &usb->ehci_usbcmd); /* Host Controller Reset */
/* TODO: Resets are long, find way to parallelize... or just use XHCI */
while (--timeout && (read32(&usb->ehci_usbcmd) & 1 << 1))
/* wait for HC to reset */;
if (!timeout) {
printk(BIOS_ERR, "ERROR: EHCI(%p) reset timeout", usb);
return;
}
write32(3 << 0, &usb->usb_mode); /* Controller mode: HOST */
write32(type << 29, &usb->lpm_ctrl); /* Parallel transceiver selct */
}

121
src/soc/nvidia/tegra/usb.h Normal file
View File

@ -0,0 +1,121 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __SOC_NVIDIA_TEGRA_USB_H__
#define __SOC_NVIDIA_TEGRA_USB_H__
#include <stdint.h>
struct utmip_ctlr {
u32 pll0;
u32 pll1;
u32 xcvr0;
u32 bias0;
u32 hsrx0;
u32 hsrx1;
u32 fslsrx0;
u32 fslsrx1;
u32 tx;
u32 misc0;
u32 misc1;
u32 debounce;
u32 batchrgr;
u32 spare;
u32 xcvr1;
u32 bias1;
u32 bias_sts;
u32 chrgr_debounce;
u32 misc_sts;
u32 pmc_wakeup;
};
struct usb_ctlr {
u32 id;
u32 _rsv0;
u32 host;
u32 device;
u32 txbuf; /* 0x010 */
u32 rxbuf;
u32 _rsv1[58];
u16 ehci_caplen; /* 0x100 */
u16 ehci_version;
u32 ehci_hcsp;
u32 ehci_hccp;
u32 _rsv2[5];
u32 dci_version; /* 0x120 */
u32 dcc_params;
u32 extsts;
u32 extintr;
u32 ehci_usbcmd; /* 0x130 */
u32 ehci_usbsts;
u32 ehci_usbintr;
u32 ehci_frindex;
u32 _rsv3; /* 0x140 */
u32 ehci_periodic_base;
u32 ehci_async_base;
u32 async_ttsts;
u32 burst_size; /* 0x150 */
u32 tx_fill_tuning;
u32 _rsv4;
u32 icusb_ctrl;
u32 ulpi_viewport; /* 0x160 */
u32 _rsv5[4];
u32 ehci_portsc;
u32 _rsv6[15];
u32 lpm_ctrl;
u32 _rsv7[15];
u32 otgsc;
u32 usb_mode;
u32 _rsv8;
u32 ep_nak; /* 0x200 */
u32 ep_nak_enable;
u32 ep_setup;
u32 ep_init;
u32 ep_deinit;
u32 ep_sts;
u32 ep_complete;
u32 ep_ctrl[16];
u32 _rsv9[105];
u32 suspend_ctrl; /* 0x400 */
u32 vbus_sensors;
u32 vbus_wakeup_id;
u32 alt_vbus_sts;
u32 legacy_ctrl;
u32 _rsv10[3];
u32 interpacket_delay;
u32 _rsv11[27];
u32 resume_delay;
u32 _rsv12;
u32 spare;
u32 _rsv13[9];
u32 new_ctrl;
u32 _rsv14[207];
struct utmip_ctlr utmip; /* 0x800 */
};
enum usb_phy_type { /* For use in lpm_ctrl[31:29] */
USB_PHY_UTMIP = 0,
USB_PHY_ULPI = 2,
USB_PHY_ICUSB_SER = 3,
USB_PHY_HSIC = 4,
};
void usb_setup_utmip(struct usb_ctlr *usb);
void usb_ehci_reset_and_prepare(struct usb_ctlr *usb, enum usb_phy_type type);
#endif

View File

@ -65,4 +65,17 @@ config STACK_SIZE
hex
default 0x800
# TTB needs to be aligned to 16KB. Stick it in iRAM.
config TTB_BUFFER
hex "memory address of the TTB buffer"
default 0x40000000
config CBFS_CACHE_ADDRESS
hex "memory address to put CBFS cache data"
default 0x803c0000
config CBFS_CACHE_SIZE
hex "size of CBFS cache data"
default 0x00020000
endif

View File

@ -35,15 +35,18 @@ ramstage-y += cbfs.c
ramstage-y += cbmem.c
ramstage-y += cpug.S
ramstage-y += clock.c
ramstage-y += display.c
ramstage-y += display.c displayhack.c
ramstage-y += dma.c
ramstage-y += i2c.c
ramstage-y += monotonic_timer.c
ramstage-y += soc.c
ramstage-y += sor.c
ramstage-y += spi.c
ramstage-y += ../tegra/dp.c
ramstage-y += ../tegra/gpio.c
ramstage-y += ../tegra/i2c.c
ramstage-y += ../tegra/pinmux.c
ramstage-y += ../tegra/usb.c
ramstage-y += timer.c
ramstage-$(CONFIG_CONSOLE_SERIAL) += uart.c

View File

@ -192,7 +192,9 @@ struct __attribute__ ((__packed__)) clk_rst_ctlr {
u32 clk_src_nand_speed; /* _CLK_SOURCE_NAND_SPEED, 0x3f8 */
u32 clk_src_i2c_slow; /* _CLK_SOURCE_I2C_SLOW, 0x3fc */
u32 clk_src_sys; /* _CLK_SOURCE_SYS, 0x400 */
u32 _rsv26[7]; /* 0x404-41c */
u32 _rsv26[4]; /* 0x404-410 */
u32 clk_src_sor; /* _CLK_SOURCE_SOR_0, 0x414 */
u32 _rsv261[2]; /* 0x404-410 */
u32 clk_src_sata_oob; /* _CLK_SOURCE_SATA_OOB, 0x420 */
u32 clk_src_sata; /* _CLK_SOURCE_SATA, 0x424 */
u32 clk_src_hda; /* _CLK_SOURCE_HDA, 0x428 */
@ -267,7 +269,11 @@ struct __attribute__ ((__packed__)) clk_rst_ctlr {
u32 _rsv31; /* 0x554 */
u32 super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER, 0x558 */
u32 spare_reg0; /* _SPARE_REG0, 0x55c */
u32 _rsv32[40]; /* 0x560-5fc */
u32 _rsv32[11]; /* 0x560-58c */
u32 plldp_base; /* _PLLDP_BASE, 0x590 */
u32 plldp_misc; /* _PLLDP_MISC, 0x594 */
u32 plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
u32 _rsrv321[26];
u32 clk_src_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST 0x600 */
u32 clk_src_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON 0x604 */
u32 clk_src_xusb_fs; /* _CLK_SOURCE_XUSB_FS 0x608 */
@ -425,24 +431,10 @@ enum {
#define OSC_XOFS_MASK (0x3F << OSC_XOFS_SHIFT)
#define OSC_DRIVE_STRENGTH 7
/*
* CLK_RST_CONTROLLER_CLK_SOURCE_x_OUT_0 - the mask here is normally 8 bits
* but can be 16. We could use knowledge we have to restrict the mask in
* the 8-bit cases (the divider_bits value returned by
* get_periph_clock_source()) but it does not seem worth it since the code
* already checks the ranges of values it is writing, in clk_get_divider().
*/
#define CLK_DIVISOR_SHIFT 0
#define CLK_DIVISOR_MASK (0xffff << CLK_DIVISOR_SHIFT)
#define CLK_DIVISOR_MASK (0xffff)
#define CLK_SOURCE_SHIFT 30
#define CLK_SOURCE_MASK (3U << CLK_SOURCE_SHIFT)
#define CLK_SOURCE3_SHIFT 29
#define CLK_SOURCE3_MASK (7U << CLK_SOURCE3_SHIFT)
#define CLK_SOURCE4_SHIFT 28
#define CLK_SOURCE4_MASK (15U << CLK_SOURCE4_SHIFT)
#define CLK_SOURCE_SHIFT 29
#define CLK_SOURCE_MASK (0x7 << CLK_SOURCE_SHIFT)
#define CLK_UART_DIV_OVERRIDE (1 << 24)

View File

@ -18,14 +18,17 @@
#include <arch/io.h>
#include <soc/addressmap.h>
#include <soc/clock.h>
#include <stdlib.h>
#include "clk_rst.h"
#include "cpug.h"
#include "flow.h"
#include "pmc.h"
#include "sysctr.h"
static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE;
static struct tegra_pmc_regs *pmc = (void *)TEGRA_PMC_BASE;
static struct sysctr_regs *sysctr = (void *)TEGRA_SYSCTR0_BASE;
struct pll_dividers {
u32 n : 10;
@ -143,21 +146,6 @@ struct {
},
};
void clock_ll_set_source_divisor(u32 *reg, u32 source, u32 divisor)
{
u32 value;
value = readl(reg);
value &= ~CLK_SOURCE_MASK;
value |= source << CLK_SOURCE_SHIFT;
value &= ~CLK_DIVISOR_MASK;
value |= divisor << CLK_DIVISOR_SHIFT;
writel(value, reg);
}
/* Get the oscillator frequency, from the corresponding hardware
* configuration field. This is actually a per-soc thing. Avoid the
* temptation to make it common.
@ -172,6 +160,20 @@ int clock_get_osc_khz(void)
return osc_table[clock_get_osc_bits()].khz;
}
void clock_init_arm_generic_timer(void)
{
uint32_t freq = clock_get_osc_khz() * 1000;
// Set the cntfrq register.
__asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0\n" :: "r"(freq));
// Record the system timer frequency.
write32(freq, &sysctr->cntfid0);
// Enable the system counter.
uint32_t cntcr = read32(&sysctr->cntcr);
cntcr |= SYSCTR_CNTCR_EN | SYSCTR_CNTCR_HDBG;
write32(cntcr, &sysctr->cntcr);
}
static void adjust_pllp_out_freqs(void)
{
u32 reg;
@ -204,6 +206,37 @@ static void init_pll(u32 *base, u32 *misc, const union pll_fields pll)
writel(dividers | PLL_BASE_ENABLE, base);
}
static void init_utmip_pll(void)
{
int khz = clock_get_osc_khz();
/* Shut off PLL crystal clock while we mess with it */
clrbits_le32(&clk_rst->utmip_pll_cfg2, 1 << 30); /* PHY_XTAL_CLKEN */
udelay(1);
write32(80 << 16 | /* (rst) phy_divn */
1 << 8 | /* (rst) phy_divm */
0, &clk_rst->utmip_pll_cfg0); /* 960MHz * 1 / 80 == 12 MHz */
write32(CEIL_DIV(khz, 8000) << 27 | /* pllu_enbl_cnt / 8 (1us) */
0 << 16 | /* PLLU pwrdn */
0 << 14 | /* pll_enable pwrdn */
0 << 12 | /* pll_active pwrdn */
CEIL_DIV(khz, 102) << 0 | /* phy_stbl_cnt / 256 (2.5ms) */
0, &clk_rst->utmip_pll_cfg1);
/* TODO: TRM can't decide if actv is 5us or 10us, keep an eye on it */
write32(0 << 24 | /* SAMP_D/XDEV pwrdn */
CEIL_DIV(khz, 3200) << 18 | /* phy_actv_cnt / 16 (5us) */
CEIL_DIV(khz, 256) << 6 | /* pllu_stbl_cnt / 256 (1ms) */
0 << 4 | /* SAMP_C/USB3 pwrdn */
0 << 2 | /* SAMP_B/XHOST pwrdn */
0 << 0 | /* SAMP_A/USBD pwrdn */
0, &clk_rst->utmip_pll_cfg2);
setbits_le32(&clk_rst->utmip_pll_cfg2, 1 << 30); /* PHY_XTAL_CLKEN */
}
/* Initialize the UART and put it on CLK_M so we can use it during clock_init().
* Will later move it to PLLP in clock_config(). The divisor must be very small
* to accomodate 12KHz OSCs, so we override the 16.0 UART divider with the 15.1
@ -212,8 +245,8 @@ static void init_pll(u32 *base, u32 *misc, const union pll_fields pll)
* been determined through trial and error (must lead to div 13 at 24MHz). */
void clock_early_uart(void)
{
clock_ll_set_source_divisor(&clk_rst->clk_src_uarta, 3,
CLK_UART_DIV_OVERRIDE | CLK_DIVIDER(clock_get_osc_khz(), 1800));
write32(CLK_M << CLK_SOURCE_SHIFT | CLK_UART_DIV_OVERRIDE |
CLK_DIVIDER(TEGRA_CLK_M_KHZ, 1800), &clk_rst->clk_src_uarta);
setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_UARTA);
udelay(2);
clrbits_le32(&clk_rst->rst_dev_l, CLK_L_UARTA);
@ -319,62 +352,26 @@ void clock_init(void)
init_pll(&clk_rst->pllc_base, &clk_rst->pllc_misc, osc_table[osc].pllc);
init_pll(&clk_rst->plld_base, &clk_rst->plld_misc, osc_table[osc].plld);
init_pll(&clk_rst->pllu_base, &clk_rst->pllu_misc, osc_table[osc].pllu);
init_utmip_pll();
val = (1 << CLK_SYS_RATE_AHB_RATE_SHIFT);
writel(val, &clk_rst->clk_sys_rate);
}
void clock_config(void)
void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w)
{
/* Enable clocks for the required peripherals. */
/* TODO: can (should?) we use the _SET and _CLR registers here? */
setbits_le32(&clk_rst->clk_out_enb_l,
CLK_L_CACHE2 | CLK_L_GPIO | CLK_L_TMR | CLK_L_I2C1 |
CLK_L_SDMMC4);
setbits_le32(&clk_rst->clk_out_enb_h,
CLK_H_EMC | CLK_H_I2C2 | CLK_H_I2C5 | CLK_H_SBC1 |
CLK_H_PMC | CLK_H_APBDMA | CLK_H_MEM);
setbits_le32(&clk_rst->clk_out_enb_u,
CLK_U_I2C3 | CLK_U_CSITE | CLK_U_SDMMC3);
setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_MSELECT);
setbits_le32(&clk_rst->clk_out_enb_w, CLK_W_DVFS);
if (l) writel(l, &clk_rst->clk_enb_l_set);
if (h) writel(h, &clk_rst->clk_enb_h_set);
if (u) writel(u, &clk_rst->clk_enb_u_set);
if (v) writel(v, &clk_rst->clk_enb_v_set);
if (w) writel(w, &clk_rst->clk_enb_w_set);
/*
* Set MSELECT clock source as PLLP (00)_REG, 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(&clk_rst->clk_src_mselect, 0,
CLK_DIVIDER(TEGRA_PLLP_KHZ, 102000));
/* Give clock time to stabilize */
/* Give clocks time to stabilize. */
udelay(IO_STABILIZATION_DELAY);
/* I2C1 gets CLK_M and a divisor of 17 */
clock_ll_set_source_divisor(&clk_rst->clk_src_i2c1, 3, 16);
/* I2C2 gets CLK_M and a divisor of 17 */
clock_ll_set_source_divisor(&clk_rst->clk_src_i2c2, 3, 16);
/* I2C3 (cam) gets CLK_M and a divisor of 17 */
clock_ll_set_source_divisor(&clk_rst->clk_src_i2c3, 3, 16);
/* I2C5 (PMU) gets CLK_M and a divisor of 17 */
clock_ll_set_source_divisor(&clk_rst->clk_src_i2c5, 3, 16);
/* UARTA gets PLLP, deactivate CLK_UART_DIV_OVERRIDE */
writel(0 << CLK_SOURCE_SHIFT, &clk_rst->clk_src_uarta);
/* Give clock time to stabilize. */
udelay(IO_STABILIZATION_DELAY);
/* Take required peripherals out of reset. */
clrbits_le32(&clk_rst->rst_dev_l,
CLK_L_CACHE2 | CLK_L_GPIO | CLK_L_TMR | CLK_L_I2C1 |
CLK_L_SDMMC4);
clrbits_le32(&clk_rst->rst_dev_h,
CLK_H_EMC | CLK_H_I2C2 | CLK_H_I2C5 | CLK_H_SBC1 |
CLK_H_PMC | CLK_H_APBDMA | CLK_H_MEM);
clrbits_le32(&clk_rst->rst_dev_u,
CLK_U_I2C3 | CLK_U_CSITE | CLK_U_SDMMC3);
clrbits_le32(&clk_rst->rst_dev_v, CLK_V_MSELECT);
clrbits_le32(&clk_rst->rst_dev_w, CLK_W_DVFS);
if (l) writel(l, &clk_rst->rst_dev_l_clr);
if (h) writel(h, &clk_rst->rst_dev_h_clr);
if (u) writel(u, &clk_rst->rst_dev_u_clr);
if (v) writel(v, &clk_rst->rst_dev_v_clr);
if (w) writel(w, &clk_rst->rst_dev_w_clr);
}

View File

@ -30,13 +30,30 @@
#include <cpu/cpu.h>
#include <boot/tables.h>
#include <cbmem.h>
#include <edid.h>
#include <soc/clock.h>
#include <soc/nvidia/tegra/dc.h>
#include "clk_rst.h"
#include "chip.h"
#include <soc/display.h>
static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
int dump = 0;
unsigned long READL(void * p);
void WRITEL(unsigned long value, void * p);
unsigned long READL(void * p)
{
unsigned long value = readl(p);
if (dump)
printk(BIOS_SPEW, "readl %p %08lx\n", p, value);
return value;
}
void WRITEL(unsigned long value, void * p)
{
if (dump)
printk(BIOS_SPEW, "writel %p %08lx\n", p, value);
writel(value, p);
}
static const u32 rgb_enb_tab[PIN_REG_COUNT] = {
0x00000000,
@ -76,25 +93,25 @@ static int update_display_mode(struct dc_disp_reg *disp,
u32 rate;
u32 div;
writel(0x0, &disp->disp_timing_opt);
WRITEL(0x0, &disp->disp_timing_opt);
writel(config->vref_to_sync << 16 | config->href_to_sync,
WRITEL(config->vref_to_sync << 16 | config->href_to_sync,
&disp->ref_to_sync);
writel(config->vsync_width << 16 | config->hsync_width, &disp->sync_width);
writel(config->vback_porch << 16 | config->hback_porch, &disp->back_porch);
writel(config->vfront_porch << 16 | config->hfront_porch,
WRITEL(config->vsync_width << 16 | config->hsync_width, &disp->sync_width);
WRITEL(config->vback_porch << 16 | config->hback_porch, &disp->back_porch);
WRITEL(config->vfront_porch << 16 | config->hfront_porch,
&disp->front_porch);
writel(config->xres | (config->yres << 16), &disp->disp_active);
WRITEL(config->xres | (config->yres << 16), &disp->disp_active);
val = DE_SELECT_ACTIVE << DE_SELECT_SHIFT;
val |= DE_CONTROL_NORMAL << DE_CONTROL_SHIFT;
writel(val, &disp->data_enable_opt);
WRITEL(val, &disp->data_enable_opt);
val = DATA_FORMAT_DF1P1C << DATA_FORMAT_SHIFT;
val |= DATA_ALIGNMENT_MSB << DATA_ALIGNMENT_SHIFT;
val |= DATA_ORDER_RED_BLUE << DATA_ORDER_SHIFT;
writel(val, &disp->disp_interface_ctrl);
WRITEL(val, &disp->disp_interface_ctrl);
/*
* The pixel clock divider is in 7.1 format (where the bottom bit
@ -107,11 +124,11 @@ static int update_display_mode(struct dc_disp_reg *disp,
div = ((rate * 2 + config->pixel_clock / 2) / config->pixel_clock) - 2;
printk(BIOS_SPEW, "Display clock %d, divider %d\n", rate, div);
writel(0x00010001, &disp->shift_clk_opt);
WRITEL(0x00010001, &disp->shift_clk_opt);
val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT;
val |= div << SHIFT_CLK_DIVIDER_SHIFT;
writel(val, &disp->disp_clk_ctrl);
WRITEL(val, &disp->disp_clk_ctrl);
return 0;
}
@ -157,55 +174,55 @@ static void update_window(struct display_controller *dc,
u32 h_dda, v_dda;
u32 val;
val = readl(&dc->cmd.disp_win_header);
val = READL(&dc->cmd.disp_win_header);
val |= WINDOW_A_SELECT;
writel(val, &dc->cmd.disp_win_header);
WRITEL(val, &dc->cmd.disp_win_header);
writel(win->fmt, &dc->win.color_depth);
WRITEL(win->fmt, &dc->win.color_depth);
clrsetbits_le32(&dc->win.byte_swap, BYTE_SWAP_MASK,
BYTE_SWAP_NOSWAP << BYTE_SWAP_SHIFT);
val = win->out_x << H_POSITION_SHIFT;
val |= win->out_y << V_POSITION_SHIFT;
writel(val, &dc->win.pos);
WRITEL(val, &dc->win.pos);
val = win->out_w << H_SIZE_SHIFT;
val |= win->out_h << V_SIZE_SHIFT;
writel(val, &dc->win.size);
WRITEL(val, &dc->win.size);
val = (win->w * win->bpp / 8) << H_PRESCALED_SIZE_SHIFT;
val |= win->h << V_PRESCALED_SIZE_SHIFT;
writel(val, &dc->win.prescaled_size);
WRITEL(val, &dc->win.prescaled_size);
writel(0, &dc->win.h_initial_dda);
writel(0, &dc->win.v_initial_dda);
WRITEL(0, &dc->win.h_initial_dda);
WRITEL(0, &dc->win.v_initial_dda);
h_dda = (win->w * 0x1000) / MAX(win->out_w - 1, 1);
v_dda = (win->h * 0x1000) / MAX(win->out_h - 1, 1);
val = h_dda << H_DDA_INC_SHIFT;
val |= v_dda << V_DDA_INC_SHIFT;
writel(val, &dc->win.dda_increment);
WRITEL(val, &dc->win.dda_increment);
writel(win->stride, &dc->win.line_stride);
writel(0, &dc->win.buf_stride);
WRITEL(win->stride, &dc->win.line_stride);
WRITEL(0, &dc->win.buf_stride);
val = WIN_ENABLE;
if (win->bpp < 24)
val |= COLOR_EXPAND;
writel(val, &dc->win.win_opt);
WRITEL(val, &dc->win.win_opt);
writel((u32) win->phys_addr, &dc->winbuf.start_addr);
writel(win->x, &dc->winbuf.addr_h_offset);
writel(win->y, &dc->winbuf.addr_v_offset);
WRITEL((u32) win->phys_addr, &dc->winbuf.start_addr);
WRITEL(win->x, &dc->winbuf.addr_h_offset);
WRITEL(win->y, &dc->winbuf.addr_v_offset);
writel(0xff00, &dc->win.blend_nokey);
writel(0xff00, &dc->win.blend_1win);
WRITEL(0xff00, &dc->win.blend_nokey);
WRITEL(0xff00, &dc->win.blend_1win);
val = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
val |= GENERAL_UPDATE | WIN_A_UPDATE;
writel(val, &dc->cmd.state_ctrl);
WRITEL(val, &dc->cmd.state_ctrl);
}
/* this is really aimed at the lcd panel. That said, there are two display
@ -222,7 +239,36 @@ void display_startup(device_t dev)
/* should probably just make it all MiB ... in future */
u32 framebuffer_size_mb = config->framebuffer_size / MiB;
u32 framebuffer_base_mb= config->framebuffer_base / MiB;
/* light it all up */
/* This one may have been done in romstage but that's ok for now. */
if (config->panel_vdd_gpio){
gpio_output(config->panel_vdd_gpio, 1);
printk(BIOS_SPEW,"%s: panel_vdd setting gpio %08x to %d\n",
__func__, config->panel_vdd_gpio, 1);
}
delay(1);
if (config->backlight_vdd_gpio){
gpio_output(config->backlight_vdd_gpio, 1);
printk(BIOS_SPEW,"%s: backlight vdd setting gpio %08x to %d\n",
__func__, config->backlight_vdd_gpio, 1);
}
delay(1);
if (config->lvds_shutdown_gpio){
gpio_output(config->lvds_shutdown_gpio, 0);
printk(BIOS_SPEW,"%s: lvds shutdown setting gpio %08x to %d\n",
__func__, config->lvds_shutdown_gpio, 0);
}
if (config->backlight_en_gpio){
gpio_output(config->backlight_en_gpio, 1);
printk(BIOS_SPEW,"%s: backlight enable setting gpio %08x to %d\n",
__func__, config->backlight_en_gpio, 1);
}
if (config->pwm){
gpio_output(config->pwm, 1);
printk(BIOS_SPEW,"%s: pwm setting gpio %08x to %d\n",
__func__, config->pwm, 1);
}
printk(BIOS_SPEW,
"%s: xres %d yres %d framebuffer_bits_per_pixel %d\n",
__func__,
@ -252,53 +298,73 @@ void display_startup(device_t dev)
* The panel_vdd is done in the romstage, so we need only
* light things up here once we're sure it's all working.
*/
setbits_le32(&clk_rst->rst_dev_l, CLK_L_DISP1 | CLK_L_HOST1X);
clock_ll_set_source_divisor(&clk_rst->clk_src_host1x, 4,
CLK_DIVIDER(TEGRA_PLLP_KHZ, 144000));
/* u-boot uses PLLC for DISP1.
* But the u-boot code does not work and we don't set up PLLC anyway.
* PLLP seems quite good enough, so run with that for now. */
clock_ll_set_source_divisor(&clk_rst->clk_src_disp1, 0 /* 4 */,
CLK_DIVIDER(TEGRA_PLLP_KHZ, 600000));
/* init dc_a */
init_dca_regs();
/* init sor */
init_sor_regs();
udelay(2);
/* init dpaux */
init_dpaux_regs();
clrbits_le32(&clk_rst->rst_dev_l, CLK_L_DISP1|CLK_L_HOST1X);
/* power up perip */
dp_io_powerup();
writel(0x00000100, &dc->cmd.gen_incr_syncpt_ctrl);
writel(0x0000011a, &dc->cmd.cont_syncpt_vsync);
writel(0x00000000, &dc->cmd.int_type);
writel(0x00000000, &dc->cmd.int_polarity);
writel(0x00000000, &dc->cmd.int_mask);
writel(0x00000000, &dc->cmd.int_enb);
/* bringup dp */
dp_bringup(framebuffer_base_mb*MiB);
{ u16 *cp = (void *)(framebuffer_base_mb*MiB);
for(i = 0; i < 1048576*8; i++)
if (i %(2560/2) < 1280/2)
cp[i] = 0x222;
else
cp[i] = 0x888;
}
/* tell depthcharge ...
*/
struct edid edid;
edid.x_resolution = 2560;
edid.y_resolution = 1700;
edid.bytes_per_line = 2560 * 2;
edid.framebuffer_bits_per_pixel = 16;
set_vbe_mode_info_valid(&edid, (uintptr_t)(framebuffer_base_mb*MiB));
if (0){
/* do we still need these? */
WRITEL(0x00000100, &dc->cmd.gen_incr_syncpt_ctrl);
WRITEL(0x0000011a, &dc->cmd.cont_syncpt_vsync);
WRITEL(0x00000000, &dc->cmd.int_type);
WRITEL(0x00000000, &dc->cmd.int_polarity);
WRITEL(0x00000000, &dc->cmd.int_mask);
WRITEL(0x00000000, &dc->cmd.int_enb);
val = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE;
val |= PW3_ENABLE | PW4_ENABLE | PM0_ENABLE;
val |= PM1_ENABLE;
writel(val, &dc->cmd.disp_pow_ctrl);
WRITEL(val, &dc->cmd.disp_pow_ctrl);
val = readl(&dc->cmd.disp_cmd);
val = READL(&dc->cmd.disp_cmd);
val |= CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT;
writel(val, &dc->cmd.disp_cmd);
WRITEL(val, &dc->cmd.disp_cmd);
writel(0x00000020, &dc->disp.mem_high_pri);
writel(0x00000001, &dc->disp.mem_high_pri_timer);
WRITEL(0x00000020, &dc->disp.mem_high_pri);
WRITEL(0x00000001, &dc->disp.mem_high_pri_timer);
for (i = 0; i < PIN_REG_COUNT; i++) {
writel(rgb_enb_tab[i], &dc->com.pin_output_enb[i]);
writel(rgb_polarity_tab[i], &dc->com.pin_output_polarity[i]);
writel(rgb_data_tab[i], &dc->com.pin_output_data[i]);
WRITEL(rgb_enb_tab[i], &dc->com.pin_output_enb[i]);
WRITEL(rgb_polarity_tab[i], &dc->com.pin_output_polarity[i]);
WRITEL(rgb_data_tab[i], &dc->com.pin_output_data[i]);
}
for (i = 0; i < PIN_OUTPUT_SEL_COUNT; i++)
writel(rgb_sel_tab[i], &dc->com.pin_output_sel[i]);
WRITEL(rgb_sel_tab[i], &dc->com.pin_output_sel[i]);
if (config->pixel_clock)
update_display_mode(&dc->disp, config);
if (!setup_window(&window, config))
update_window(dc, &window, config);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -26,95 +26,8 @@
#include "dma.h"
/*
* Note: Many APB DMA controller registers are laid out such that each
* bit controls or represents the status for the corresponding channel.
* So we will not bother to list each individual bit in this case.
*/
#define APBDMA_COMMAND_GEN (1 << 31)
#define APBDMA_CNTRL_REG_COUNT_VALUE_MASK 0xffff
#define APBDMA_CNTRL_REG_COUNT_VALUE_SHIFT 0
struct apb_dma {
u32 command; /* 0x00 */
u32 status; /* 0x04 */
u32 rsvd1[2];
u32 cntrl_reg; /* 0x10 */
u32 irq_sta_cpu; /* 0x14 */
u32 irq_sta_cop; /* 0x18 */
u32 irq_mask; /* 0x1c */
u32 irq_mask_set; /* 0x20 */
u32 irq_mask_clr; /* 0x24 */
u32 trig_reg; /* 0x28 */
u32 channel_trig_reg; /* 0x2c */
u32 dma_status; /* 0x30 */
u32 channel_en_reg; /* 0x34 */
u32 security_reg; /* 0x38 */
u32 channel_swid; /* 0x3c */
u32 rsvd[1];
u32 chan_wt_reg0; /* 0x44 */
u32 chan_wt_reg1; /* 0x48 */
u32 chan_wt_reg2; /* 0x4c */
u32 chan_wr_reg3; /* 0x50 */
u32 channel_swid1; /* 0x54 */
} __attribute__((packed));
struct apb_dma * const apb_dma = (struct apb_dma *)TEGRA_APB_DMA_BASE;
/*
* Naming in the doc included a superfluous _CHANNEL_n_ for
* each entry and was left out for the sake of conciseness.
*/
#define APBDMACHAN_CSR_ENB (1 << 31)
#define APBDMACHAN_CSR_IE_EOC (1 << 30)
#define APBDMACHAN_CSR_HOLD (1 << 29)
#define APBDMACHAN_CSR_DIR (1 << 28)
#define APBDMACHAN_CSR_ONCE (1 << 27)
#define APBDMACHAN_CSR_FLOW (1 << 21)
#define APBDMACHAN_CSR_REQ_SEL_MASK 0x1f
#define APBDMACHAN_CSR_REQ_SEL_SHIFT 16
#define APBDMACHAN_STA_BSY (1 << 31)
#define APBDMACHAN_STA_ISE_EOC (1 << 30)
#define APBDMACHAN_STA_HALT (1 << 29)
#define APBDMACHAN_STA_PING_PONG_STA (1 << 28)
#define APBDMACHAN_STA_DMA_ACTIVITY (1 << 27)
#define APBDMACHAN_STA_CHANNEL_PAUSE (1 << 26)
#define APBDMACHAN_CSRE_CHANNEL_PAUSE (1 << 31)
#define APBDMACHAN_CSRE_TRIG_SEL_MASK 0x3f
#define APBDMACHAN_CSRE_TRIG_SEL_SHIFT 14
#define APBDMACHAN_AHB_PTR_MASK (0x3fffffff)
#define APBDMACHAN_AHB_PTR_SHIFT 2
#define APBDMACHAN_AHB_SEQ_INTR_ENB (1 << 31)
#define APBDMACHAN_AHB_SEQ_AHB_BUS_WIDTH_MASK 0x7
#define APBDMACHAN_AHB_SEQ_AHB_BUS_WIDTH_SHIFT 28
#define APBDMACHAN_AHB_SEQ_AHB_DATA_SWAP (1 << 27)
#define APBDMACHAN_AHB_SEQ_AHB_BURST_MASK 0x7
#define APBDMACHAN_AHB_SEQ_AHB_BURST_SHIFT 24
#define APBDMACHAN_AHB_SEQ_DBL_BUF (1 << 19)
#define APBDMACHAN_AHB_SEQ_WRAP_MASK 0x7
#define APBDMACHAN_AHB_SEQ_WRAP_SHIFT 16
#define APBDMACHAN_AHB_SEQ_AHB_BUS_WIDTH_MASK 0x7
#define APBDMACHAN_AHB_SEQ_AHB_BUS_WIDTH_SHIFT 28
#define APBDMACHAN_APB_PTR_MASK 0x3fffffff
#define APBDMACHAN_APB_PTR_SHIFT 2
#define APBDMACHAN_APB_SEQ_APB_BUS_WIDTH_MASK 0x7
#define APBDMACHAN_APB_SEQ_APB_BUS_WIDTH_SHIFT 28
#define APBDMACHAN_APB_SEQ_APB_DATA_SWAP (1 << 27)
#define APBDMACHAN_APB_SEQ_APB_ADDR_WRAP_MASK 0x7
#define APBDMACHAN_APB_SEQ_APB_ADDR_WRAP_SHIFT 16
#define APBDMACHAN_WORD_TRANSFER_
#define APBDMACHAN_WORD_TRANSFER_MASK 0x0fffffff
#define APBDMACHAN_WORD_TRANSFER_SHIFT 2
#define APB_DMA_OFFSET(n) \
(struct apb_dma_channel_regs *)(TEGRA_APB_DMA_BASE + n)
struct apb_dma_channel apb_dma_channels[] = {

View File

@ -28,6 +28,138 @@
*/
#define TEGRA_DMA_ALIGN_BYTES 4
/*
* Note: Many APB DMA controller registers are laid out such that each
* bit controls or represents the status for the corresponding channel.
* So we will not bother to list each individual bit in this case.
*/
#define APBDMA_COMMAND_GEN (1 << 31)
#define APBDMA_CNTRL_REG_COUNT_VALUE_MASK 0xffff
#define APBDMA_CNTRL_REG_COUNT_VALUE_SHIFT 0
/*
* Note: Many APB DMA controller registers are laid out such that each
* bit controls or represents the status for the corresponding channel.
* So we will not bother to list each individual bit in this case.
*/
#define APBDMA_COMMAND_GEN (1 << 31)
#define APBDMA_CNTRL_REG_COUNT_VALUE_MASK 0xffff
#define APBDMA_CNTRL_REG_COUNT_VALUE_SHIFT 0
struct apb_dma {
u32 command; /* 0x00 */
u32 status; /* 0x04 */
u32 rsvd1[2];
u32 cntrl_reg; /* 0x10 */
u32 irq_sta_cpu; /* 0x14 */
u32 irq_sta_cop; /* 0x18 */
u32 irq_mask; /* 0x1c */
u32 irq_mask_set; /* 0x20 */
u32 irq_mask_clr; /* 0x24 */
u32 trig_reg; /* 0x28 */
u32 channel_trig_reg; /* 0x2c */
u32 dma_status; /* 0x30 */
u32 channel_en_reg; /* 0x34 */
u32 security_reg; /* 0x38 */
u32 channel_swid; /* 0x3c */
u32 rsvd[1];
u32 chan_wt_reg0; /* 0x44 */
u32 chan_wt_reg1; /* 0x48 */
u32 chan_wt_reg2; /* 0x4c */
u32 chan_wr_reg3; /* 0x50 */
u32 channel_swid1; /* 0x54 */
} __attribute__((packed));
/*
* Naming in the doc included a superfluous _CHANNEL_n_ for
* each entry and was left out for the sake of conciseness.
*/
#define APBDMACHAN_CSR_ENB (1 << 31)
#define APBDMACHAN_CSR_IE_EOC (1 << 30)
#define APBDMACHAN_CSR_HOLD (1 << 29)
#define APBDMACHAN_CSR_DIR (1 << 28)
#define APBDMACHAN_CSR_ONCE (1 << 27)
#define APBDMACHAN_CSR_FLOW (1 << 21)
#define APBDMACHAN_CSR_REQ_SEL_MASK 0x1f
#define APBDMACHAN_CSR_REQ_SEL_SHIFT 16
enum apbdmachan_req_sel {
APBDMA_SLAVE_CNTR_REQ = 0,
APBDMA_SLAVE_APBIF_CH0 = 1,
APBDMA_SLAVE_APBIF_CH1 = 2,
APBDMA_SLAVE_APBIF_CH2 = 3,
APBDMA_SLAVE_APBIF_CH3 = 4,
APBDMA_SLAVE_HSI = 5,
APBDMA_SLAVE_APBIF_CH4 = 6,
APBDMA_SLAVE_APBIF_CH5 = 7,
APBDMA_SLAVE_UART_A = 8,
APBDMA_SLAVE_UART_B = 9,
APBDMA_SLAVE_UART_C = 10,
APBDMA_SLAVE_DTV = 11,
APBDMA_SLAVE_APBIF_CH6 = 12,
APBDMA_SLAVE_APBIF_CH7 = 13,
APBDMA_SLAVE_APBIF_CH8 = 14,
APBDMA_SLAVE_SL2B1 = 15,
APBDMA_SLAVE_SL2B2 = 16,
APBDMA_SLAVE_SL2B3 = 17,
APBDMA_SLAVE_SL2B4 = 18,
APBDMA_SLAVE_UART_D = 19,
APBDMA_SLAVE_UART_E = 20,
APBDMA_SLAVE_I2C = 21,
APBDMA_SLAVE_I2C2 = 22,
APBDMA_SLAVE_I2C3 = 23,
APBDMA_SLAVE_DVC_I2C = 24,
APBDMA_SLAVE_OWR = 25,
APBDMA_SLAVE_I2C4 = 26,
APBDMA_SLAVE_SL2B5 = 27,
APBDMA_SLAVE_SL2B6 = 28,
APBDMA_SLAVE_APBIF_CH9 = 29,
APBDMA_SLAVE_I2C6 = 30,
APBDMA_SLAVE_NA31 = 31,
};
#define APBDMACHAN_STA_BSY (1 << 31)
#define APBDMACHAN_STA_ISE_EOC (1 << 30)
#define APBDMACHAN_STA_HALT (1 << 29)
#define APBDMACHAN_STA_PING_PONG_STA (1 << 28)
#define APBDMACHAN_STA_DMA_ACTIVITY (1 << 27)
#define APBDMACHAN_STA_CHANNEL_PAUSE (1 << 26)
#define APBDMACHAN_CSRE_CHANNEL_PAUSE (1 << 31)
#define APBDMACHAN_CSRE_TRIG_SEL_MASK 0x3f
#define APBDMACHAN_CSRE_TRIG_SEL_SHIFT 14
#define APBDMACHAN_AHB_PTR_MASK (0x3fffffff)
#define APBDMACHAN_AHB_PTR_SHIFT 2
#define APBDMACHAN_AHB_SEQ_INTR_ENB (1 << 31)
#define APBDMACHAN_AHB_SEQ_AHB_BUS_WIDTH_MASK 0x7
#define APBDMACHAN_AHB_SEQ_AHB_BUS_WIDTH_SHIFT 28
#define APBDMACHAN_AHB_SEQ_AHB_DATA_SWAP (1 << 27)
#define APBDMACHAN_AHB_SEQ_AHB_BURST_MASK 0x7
#define APBDMACHAN_AHB_SEQ_AHB_BURST_SHIFT 24
#define APBDMACHAN_AHB_SEQ_DBL_BUF (1 << 19)
#define APBDMACHAN_AHB_SEQ_WRAP_MASK 0x7
#define APBDMACHAN_AHB_SEQ_WRAP_SHIFT 16
#define APBDMACHAN_AHB_SEQ_AHB_BUS_WIDTH_MASK 0x7
#define APBDMACHAN_AHB_SEQ_AHB_BUS_WIDTH_SHIFT 28
#define APBDMACHAN_APB_PTR_MASK 0x3fffffff
#define APBDMACHAN_APB_PTR_SHIFT 2
#define APBDMACHAN_APB_SEQ_APB_BUS_WIDTH_MASK 0x7
#define APBDMACHAN_APB_SEQ_APB_BUS_WIDTH_SHIFT 28
#define APBDMACHAN_APB_SEQ_APB_DATA_SWAP (1 << 27)
#define APBDMACHAN_APB_SEQ_APB_ADDR_WRAP_MASK 0x7
#define APBDMACHAN_APB_SEQ_APB_ADDR_WRAP_SHIFT 16
#define APBDMACHAN_WORD_TRANSFER_
#define APBDMACHAN_WORD_TRANSFER_MASK 0x0fffffff
#define APBDMACHAN_WORD_TRANSFER_SHIFT 2
struct apb_dma_channel_regs {
u32 csr; /* 0x00 */
u32 sta; /* 0x04 */

View File

@ -32,6 +32,8 @@ enum {
TEGRA_ARM_PERIPHBASE = 0x50040000,
TEGRA_ARM_DISPLAYA = 0x54200000,
TEGRA_ARM_DISPLAYB = 0x54240000,
TEGRA_ARM_SOR = 0x54540000,
TEGRA_ARM_DPAUX = 0x545c0000,
TEGRA_PG_UP_BASE = 0x60000000,
TEGRA_TMRUS_BASE = 0x60005010,
TEGRA_CLK_RST_BASE = 0x60006000,
@ -67,7 +69,10 @@ enum {
TEGRA_EMC_BASE = TEGRA_APB_MISC_BASE + 0xF400,
TEGRA_FUSE_BASE = TEGRA_APB_MISC_BASE + 0xF800,
TEGRA_CSITE_BASE = 0x70040000,
TEGRA_USB_ADDR_MASK = 0xFFFFC000,
TEGRA_SYSCTR0_BASE = 0x700F0000,
TEGRA_USBD_BASE = 0x7D000000,
TEGRA_USB2_BASE = 0x7D004000,
TEGRA_USB3_BASE = 0x7D008000,
};
enum {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -149,13 +149,69 @@ enum {
#define CLOCK_PLL_STABLE_DELAY_US 300
#define IO_STABILIZATION_DELAY (2)
/* Calculate clock fractional divider value from ref and target frequencies */
/* Calculate clock fractional divider value from ref and target frequencies.
* This is for a U7.1 format. This is not well written up in the book and
* there have been some questions about this macro, so here we go.
* U7.1 format is defined as (ddddddd+1) + (h*.5)
* The lowest order bit is actually a fractional bit.
* Hence, the divider can be thought of as 9 bits.
* So:
* divider = ((ref/freq) << 1 - 1) (upper 7 bits) |
* (ref/freq & 1) (low order half-bit)
* however we can't do fractional arithmetic ... these are integers!
* So we normalize by shifting the result left 1 bit, and extracting
* ddddddd and h directly to the returned u8.
* divider = 2*(ref/freq);
* We want to
* preserve 7 bits of divisor and one bit of fraction, in 8 bits, as well as
* subtract one from ddddddd. Since we computed ref*2, the dddddd is now nicely
* situated in the upper 7 bits, and the h is sitting there in the low order
* bit. To subtract 1 from ddddddd, just subtract 2 from the 8-bit number
* and voila, upper 7 bits are (ref/freq-1), and lowest bit is h. Since you
* will assign this to a u8, it gets nicely truncated for you.
*/
#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
* The discussion in the book is pretty lacking.
* The idea is that we need to divide a ref clock by a divisor
* in U7.1 format, where 7 upper bits are the integer
* and lowest order bit is a fraction.
* from the book, U7.1 is (ddddddd+1) + (h*.5)
* To normalize to an actual number, we might do this:
* ((d>>7+1)&0x7f) + (d&1 >> 1)
* but as you might guess, the low order bit would be lost.
* Since we can't express the fractional bit, we need to multiply it all by 2.
* ((d + 2)&0xfe) + (d & 1)
* Since we're just adding +2, the lowest order bit is preserved. Hence
* (d+2) is the same as ((d + 2)&0xfe) + (d & 1)
*
* Since you multiply denominator * 2 (by NOT shifting it),
* you multiply numerator * 2 to cancel it out.
*/
#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2))
/* Warning: Some devices just use different bits for the same sources for no
* apparent reason. *Always* double-check the TRM before trusting this macro. */
#define clock_configure_source(device, src, freq) \
clrsetbits_le32(&clk_rst->clk_src_##device, \
CLK_SOURCE_MASK | CLK_DIVISOR_MASK, \
src << CLK_SOURCE_SHIFT | CLK_DIVIDER(TEGRA_##src##_KHZ, freq));
enum clock_source { /* Careful: Not true for all sources, always check TRM! */
PLLP = 0,
PLLC2 = 1,
PLLC = 2,
PLLD = 2,
PLLC3 = 3,
PLLA = 3,
PLLM = 4,
PLLD2 = 5,
CLK_M = 6,
};
/* soc-specific */
#define TEGRA_CLK_M_KHZ clock_get_osc_khz()
#define TEGRA_PLLX_KHZ (1900000)
#define TEGRA_PLLP_KHZ (408000)
#define TEGRA_PLLC_KHZ (600000)
@ -165,7 +221,7 @@ enum {
int clock_get_osc_khz(void);
void clock_early_uart(void);
void clock_cpu0_config_and_reset(void * entry);
void clock_config(void);
void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w);
void clock_init(void);
void clock_ll_set_source_divisor(u32 *reg, u32 source, u32 divisor);
void clock_init_arm_generic_timer(void);
#endif /* __SOC_NVIDIA_TEGRA124_CLOCK_H__ */

View File

@ -18,5 +18,8 @@
#define __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_DISPLAY_H__
void setup_display(struct soc_nvidia_tegra124_config *config);
void init_dca_regs(void);
void init_dpaux_regs(void);
void init_sor_regs(void);
void dp_io_powerup(void);
#endif /* __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_DISPLAY_H__ */

View File

@ -62,7 +62,9 @@ struct tegra_pmc_regs {
u32 no_iopower;
u32 pwr_det;
u32 pwr_det_latch;
u32 scratch[24];
u32 scratch[20];
u32 odmdata;
u32 scratch21[24 - 21];
u32 secure_scratch[6];
u32 cpupwrgood_timer;
u32 cpupwroff_timer;

View File

@ -0,0 +1,169 @@
/*
* drivers/video/tegra/dc/sor.c
*
* Copyright (c) 2011-2013, NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <console/console.h>
#include <arch/io.h>
#include <stdint.h>
#include <lib.h>
#include <stdlib.h>
#include <delay.h>
#include <soc/addressmap.h>
#include <device/device.h>
#include <stdlib.h>
#include <string.h>
#include <cpu/cpu.h>
#include <boot/tables.h>
#include <cbmem.h>
#include <soc/nvidia/tegra/dc.h>
#include "sor.h"
#include <soc/nvidia/tegra/displayport.h>
#include "clk_rst.h"
#include <soc/clock.h>
#include "chip.h"
#include <soc/display.h>
#define APBDEV_PMC_DPD_SAMPLE (0x20)
#define APBDEV_PMC_DPD_SAMPLE_ON_DISABLE (0)
#define APBDEV_PMC_DPD_SAMPLE_ON_ENABLE (1)
#define APBDEV_PMC_SEL_DPD_TIM (0x1c8)
#define APBDEV_PMC_SEL_DPD_TIM_SEL_DPD_TIM_DEFAULT (0x7f)
#define APBDEV_PMC_IO_DPD2_REQ (0x1c0)
#define APBDEV_PMC_IO_DPD2_REQ_LVDS_SHIFT (25)
#define APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF (0 << 25)
#define APBDEV_PMC_IO_DPD2_REQ_LVDS_ON (1 << 25)
#define APBDEV_PMC_IO_DPD2_REQ_CODE_SHIFT (30)
#define APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK (0x3 << 30)
#define APBDEV_PMC_IO_DPD2_REQ_CODE_IDLE (0 << 30)
#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF (1 << 30)
#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON (2 << 30)
#define APBDEV_PMC_IO_DPD2_STATUS (0x1c4)
#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_SHIFT (25)
#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_OFF (0 << 25)
#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON (1 << 25)
static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg)
{
u32 reg_val = readl((sor->base + reg * 4));
return reg_val;
}
static inline void tegra_sor_writel(struct tegra_dc_sor_data *sor,
u32 reg, u32 val)
{
writel(val, (sor->base + reg * 4));
}
static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor,
u32 reg, u32 mask, u32 val)
{
u32 reg_val = tegra_sor_readl(sor, reg);
reg_val &= ~mask;
reg_val |= val;
tegra_sor_writel(sor, reg, reg_val);
}
void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena,
u8 training_pattern, const struct tegra_dc_dp_link_config *cfg)
{
u32 reg_val;
reg_val = tegra_sor_readl(sor, NV_SOR_DP_LINKCTL(sor->portnum));
if (ena)
reg_val |= NV_SOR_DP_LINKCTL_ENABLE_YES;
else
reg_val &= NV_SOR_DP_LINKCTL_ENABLE_NO;
reg_val &= ~NV_SOR_DP_LINKCTL_TUSIZE_MASK;
reg_val |= (cfg->tu_size << NV_SOR_DP_LINKCTL_TUSIZE_SHIFT);
if (cfg->enhanced_framing)
reg_val |= NV_SOR_DP_LINKCTL_ENHANCEDFRAME_ENABLE;
tegra_sor_writel(sor, NV_SOR_DP_LINKCTL(sor->portnum), reg_val);
switch (training_pattern) {
case trainingPattern_1:
tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x41414141);
break;
case trainingPattern_2:
case trainingPattern_3:
reg_val = (cfg->link_bw == NV_SOR_LINK_SPEED_G5_4) ?
0x43434343 : 0x42424242;
tegra_sor_writel(sor, NV_SOR_DP_TPG, reg_val);
break;
default:
tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x50505050);
break;
}
}
void tegra_dc_sor_set_dp_lanedata(struct tegra_dc_sor_data *sor,
u32 lane, u32 pre_emphasis, u32 drive_current, u32 tx_pu)
{
u32 d_cur;
u32 p_emp;
d_cur = tegra_sor_readl(sor, NV_SOR_DC(sor->portnum));
p_emp = tegra_sor_readl(sor, NV_SOR_PR(sor->portnum));
switch (lane) {
case 0:
p_emp &= ~NV_SOR_PR_LANE2_DP_LANE0_MASK;
p_emp |= (pre_emphasis <<
NV_SOR_PR_LANE2_DP_LANE0_SHIFT);
d_cur &= ~NV_SOR_DC_LANE2_DP_LANE0_MASK;
d_cur |= (drive_current <<
NV_SOR_DC_LANE2_DP_LANE0_SHIFT);
break;
case 1:
p_emp &= ~NV_SOR_PR_LANE1_DP_LANE1_MASK;
p_emp |= (pre_emphasis <<
NV_SOR_PR_LANE1_DP_LANE1_SHIFT);
d_cur &= ~NV_SOR_DC_LANE1_DP_LANE1_MASK;
d_cur |= (drive_current <<
NV_SOR_DC_LANE1_DP_LANE1_SHIFT);
break;
case 2:
p_emp &= ~NV_SOR_PR_LANE0_DP_LANE2_MASK;
p_emp |= (pre_emphasis <<
NV_SOR_PR_LANE0_DP_LANE2_SHIFT);
d_cur &= ~NV_SOR_DC_LANE0_DP_LANE2_MASK;
d_cur |= (drive_current <<
NV_SOR_DC_LANE0_DP_LANE2_SHIFT);
break;
case 3:
p_emp &= ~NV_SOR_PR_LANE3_DP_LANE3_MASK;
p_emp |= (pre_emphasis <<
NV_SOR_PR_LANE3_DP_LANE3_SHIFT);
d_cur &= ~NV_SOR_DC_LANE3_DP_LANE3_MASK;
d_cur |= (drive_current <<
NV_SOR_DC_LANE3_DP_LANE3_SHIFT);
break;
default:
printk(BIOS_SPEW, "dp: sor lane count %d is invalid\n", lane);
}
tegra_sor_write_field(sor, NV_SOR_DP_LINKCTL(sor->portnum),
NV_SOR_DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK,
tx_pu << NV_SOR_DP_PADCTL_TX_PU_VALUE_SHIFT);
tegra_sor_writel(sor, NV_SOR_DC(sor->portnum), d_cur);
tegra_sor_writel(sor, NV_SOR_PR(sor->portnum), p_emp);
}

View File

@ -0,0 +1,908 @@
/*
* drivers/video/tegra/dc/sor_regs.h
*
* Copyright (c) 2011-2013, NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __TEGRA124_SOR_H__
#define __TEGRA124_SOR_H__
#define NV_SOR_SUPER_STATE0 (0x1)
#define NV_SOR_SUPER_STATE0_UPDATE_SHIFT (0)
#define NV_SOR_SUPER_STATE0_UPDATE_DEFAULT_MASK (0x1)
#define NV_SOR_SUPER_STATE1 (0x2)
#define NV_SOR_SUPER_STATE1_ATTACHED_SHIFT (3)
#define NV_SOR_SUPER_STATE1_ATTACHED_NO (0 << 3)
#define NV_SOR_SUPER_STATE1_ATTACHED_YES (1 << 3)
#define NV_SOR_SUPER_STATE1_ASY_ORMODE_SHIFT (2)
#define NV_SOR_SUPER_STATE1_ASY_ORMODE_SAFE (0 << 2)
#define NV_SOR_SUPER_STATE1_ASY_ORMODE_NORMAL (1 << 2)
#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SHIFT (0)
#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_DEFAULT_MASK (0x3)
#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SLEEP (0)
#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SNOOZE (1)
#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_AWAKE (2)
#define NV_SOR_STATE0 (0x3)
#define NV_SOR_STATE0_UPDATE_SHIFT (0)
#define NV_SOR_STATE0_UPDATE_DEFAULT_MASK (0x1)
#define NV_SOR_STATE1 (0x4)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_SHIFT (17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_DEFAULT_MASK (0xf << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_16_422 (1 << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_18_444 (2 << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_20_422 (3 << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_24_422 (4 << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_24_444 (5 << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_30_444 (6 << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_32_422 (7 << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_36_444 (8 << 17)
#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_48_444 (9 << 17)
#define NV_SOR_STATE1_ASY_REPLICATE_SHIFT (15)
#define NV_SOR_STATE1_ASY_REPLICATE_DEFAULT_MASK (0x3 << 15)
#define NV_SOR_STATE1_ASY_REPLICATE_OFF (0 << 15)
#define NV_SOR_STATE1_ASY_REPLICATE_X2 (1 << 15)
#define NV_SOR_STATE1_ASY_REPLICATE_X4 (2 << 15)
#define NV_SOR_STATE1_ASY_DEPOL_SHIFT (14)
#define NV_SOR_STATE1_ASY_DEPOL_DEFAULT_MASK (0x1 << 14)
#define NV_SOR_STATE1_ASY_DEPOL_POSITIVE_TRUE (0 << 14)
#define NV_SOR_STATE1_ASY_DEPOL_NEGATIVE_TRUE (1 << 14)
#define NV_SOR_STATE1_ASY_VSYNCPOL_SHIFT (13)
#define NV_SOR_STATE1_ASY_VSYNCPOL_DEFAULT_MASK (0x1 << 13)
#define NV_SOR_STATE1_ASY_VSYNCPOL_POSITIVE_TRUE (0 << 13)
#define NV_SOR_STATE1_ASY_VSYNCPOL_NEGATIVE_TRUE (1 << 13)
#define NV_SOR_STATE1_ASY_HSYNCPOL_SHIFT (12)
#define NV_SOR_STATE1_ASY_HSYNCPOL_DEFAULT_MASK (0x1 << 12)
#define NV_SOR_STATE1_ASY_HSYNCPOL_POSITIVE_TRUE (0 << 12)
#define NV_SOR_STATE1_ASY_HSYNCPOL_NEGATIVE_TRUE (1 << 12)
#define NV_SOR_STATE1_ASY_PROTOCOL_SHIFT (8)
#define NV_SOR_STATE1_ASY_PROTOCOL_DEFAULT_MASK (0xf << 8)
#define NV_SOR_STATE1_ASY_PROTOCOL_LVDS_CUSTOM (0 << 8)
#define NV_SOR_STATE1_ASY_PROTOCOL_DP_A (8 << 8)
#define NV_SOR_STATE1_ASY_PROTOCOL_DP_B (9 << 8)
#define NV_SOR_STATE1_ASY_PROTOCOL_CUSTOM (15 << 8)
#define NV_SOR_STATE1_ASY_CRCMODE_SHIFT (6)
#define NV_SOR_STATE1_ASY_CRCMODE_DEFAULT_MASK (0x3 << 6)
#define NV_SOR_STATE1_ASY_CRCMODE_ACTIVE_RASTER (0 << 6)
#define NV_SOR_STATE1_ASY_CRCMODE_COMPLETE_RASTER (1 << 6)
#define NV_SOR_STATE1_ASY_CRCMODE_NON_ACTIVE_RASTER (2 << 6)
#define NV_SOR_STATE1_ASY_SUBOWNER_SHIFT (4)
#define NV_SOR_STATE1_ASY_SUBOWNER_DEFAULT_MASK (0x3 << 4)
#define NV_SOR_STATE1_ASY_SUBOWNER_NONE (0 << 4)
#define NV_SOR_STATE1_ASY_SUBOWNER_SUBHEAD0 (1 << 4)
#define NV_SOR_STATE1_ASY_SUBOWNER_SUBHEAD1 (2 << 4)
#define NV_SOR_STATE1_ASY_SUBOWNER_BOTH (3 << 4)
#define NV_SOR_STATE1_ASY_OWNER_SHIFT (0)
#define NV_SOR_STATE1_ASY_OWNER_DEFAULT_MASK (0xf)
#define NV_SOR_STATE1_ASY_OWNER_NONE (0)
#define NV_SOR_STATE1_ASY_OWNER_HEAD0 (1)
#define NV_SOR_STATE1_ASY_OWNER_HEAD1 (2)
#define NV_HEAD_STATE0(i) (0x5)
#define NV_HEAD_STATE0_INTERLACED_SHIFT (4)
#define NV_HEAD_STATE0_INTERLACED_DEFAULT_MASK (0x3 << 4)
#define NV_HEAD_STATE0_INTERLACED_PROGRESSIVE (0 << 4)
#define NV_HEAD_STATE0_INTERLACED_INTERLACED (1 << 4)
#define NV_HEAD_STATE0_RANGECOMPRESS_SHIFT (3)
#define NV_HEAD_STATE0_RANGECOMPRESS_DEFAULT_MASK (0x1 << 3)
#define NV_HEAD_STATE0_RANGECOMPRESS_DISABLE (0 << 3)
#define NV_HEAD_STATE0_RANGECOMPRESS_ENABLE (1 << 3)
#define NV_HEAD_STATE0_DYNRANGE_SHIFT (2)
#define NV_HEAD_STATE0_DYNRANGE_DEFAULT_MASK (0x1 << 2)
#define NV_HEAD_STATE0_DYNRANGE_VESA (0 << 2)
#define NV_HEAD_STATE0_DYNRANGE_CEA (1 << 2)
#define NV_HEAD_STATE0_COLORSPACE_SHIFT (0)
#define NV_HEAD_STATE0_COLORSPACE_DEFAULT_MASK (0x3)
#define NV_HEAD_STATE0_COLORSPACE_RGB (0)
#define NV_HEAD_STATE0_COLORSPACE_YUV_601 (1)
#define NV_HEAD_STATE0_COLORSPACE_YUV_709 (2)
#define NV_HEAD_STATE1(i) (0x7 + i)
#define NV_HEAD_STATE1_VTOTAL_SHIFT (16)
#define NV_HEAD_STATE1_VTOTAL_DEFAULT_MASK (0x7fff << 16)
#define NV_HEAD_STATE1_HTOTAL_SHIFT (0)
#define NV_HEAD_STATE1_HTOTAL_DEFAULT_MASK (0x7fff)
#define NV_HEAD_STATE2(i) (0x9 + i)
#define NV_HEAD_STATE2_VSYNC_END_SHIFT (16)
#define NV_HEAD_STATE2_VSYNC_END_DEFAULT_MASK (0x7fff << 16)
#define NV_HEAD_STATE2_HSYNC_END_SHIFT (0)
#define NV_HEAD_STATE2_HSYNC_END_DEFAULT_MASK (0x7fff)
#define NV_HEAD_STATE3(i) (0xb + i)
#define NV_HEAD_STATE3_VBLANK_END_SHIFT (16)
#define NV_HEAD_STATE3_VBLANK_END_DEFAULT_MASK (0x7fff << 16)
#define NV_HEAD_STATE3_HBLANK_END_SHIFT (0)
#define NV_HEAD_STATE3_HBLANK_END_DEFAULT_MASK (0x7fff)
#define NV_HEAD_STATE4(i) (0xd + i)
#define NV_HEAD_STATE4_VBLANK_START_SHIFT (16)
#define NV_HEAD_STATE4_VBLANK_START_DEFAULT_MASK (0x7fff << 16)
#define NV_HEAD_STATE4_HBLANK_START_SHIFT (0)
#define NV_HEAD_STATE4_HBLANK_START_DEFAULT_MASK (0x7fff)
#define NV_HEAD_STATE5(i) (0xf + i)
#define NV_SOR_CRC_CNTRL (0x11)
#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_SHIFT (0)
#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_NO (0)
#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_YES (1)
#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_DIS (0)
#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_EN (1)
#define NV_SOR_CLK_CNTRL (0x13)
#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_SHIFT (0)
#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_MASK (0x3)
#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK (0)
#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_PCLK (1)
#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK (2)
#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_DPCLK (3)
#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_SHIFT (2)
#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_MASK (0x1f << 2)
#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62 (6 << 2)
#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_G2_7 (10 << 2)
#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_LVDS (7 << 2)
#define NV_SOR_CAP (0x14)
#define NV_SOR_CAP_DP_A_SHIFT (24)
#define NV_SOR_CAP_DP_A_DEFAULT_MASK (0x1 << 24)
#define NV_SOR_CAP_DP_A_FALSE (0 << 24)
#define NV_SOR_CAP_DP_A_TRUE (1 << 24)
#define NV_SOR_CAP_DP_B_SHIFT (25)
#define NV_SOR_CAP_DP_B_DEFAULT_MASK (0x1 << 24)
#define NV_SOR_CAP_DP_B_FALSE (0 << 24)
#define NV_SOR_CAP_DP_B_TRUE (1 << 24)
#define NV_SOR_PWR (0x15)
#define NV_SOR_PWR_SETTING_NEW_SHIFT (31)
#define NV_SOR_PWR_SETTING_NEW_DEFAULT_MASK (0x1 << 31)
#define NV_SOR_PWR_SETTING_NEW_DONE (0 << 31)
#define NV_SOR_PWR_SETTING_NEW_PENDING (1 << 31)
#define NV_SOR_PWR_SETTING_NEW_TRIGGER (1 << 31)
#define NV_SOR_PWR_MODE_SHIFT (28)
#define NV_SOR_PWR_MODE_DEFAULT_MASK (0x1 << 28)
#define NV_SOR_PWR_MODE_NORMAL (0 << 28)
#define NV_SOR_PWR_MODE_SAFE (1 << 28)
#define NV_SOR_PWR_HALT_DELAY_SHIFT (24)
#define NV_SOR_PWR_HALT_DELAY_DEFAULT_MASK (0x1 << 24)
#define NV_SOR_PWR_HALT_DELAY_DONE (0 << 24)
#define NV_SOR_PWR_HALT_DELAY_ACTIVE (1 << 24)
#define NV_SOR_PWR_SAFE_START_SHIFT (17)
#define NV_SOR_PWR_SAFE_START_DEFAULT_MASK (0x1 << 17)
#define NV_SOR_PWR_SAFE_START_NORMAL (0 << 17)
#define NV_SOR_PWR_SAFE_START_ALT (1 << 17)
#define NV_SOR_PWR_SAFE_STATE_SHIFT (16)
#define NV_SOR_PWR_SAFE_STATE_DEFAULT_MASK (0x1 << 16)
#define NV_SOR_PWR_SAFE_STATE_PD (0 << 16)
#define NV_SOR_PWR_SAFE_STATE_PU (1 << 16)
#define NV_SOR_PWR_NORMAL_START_SHIFT (1)
#define NV_SOR_PWR_NORMAL_START_DEFAULT_MASK (0x1 << 1)
#define NV_SOR_PWR_NORMAL_START_NORMAL (0 << 16)
#define NV_SOR_PWR_NORMAL_START_ALT (1 << 16)
#define NV_SOR_PWR_NORMAL_STATE_SHIFT (0)
#define NV_SOR_PWR_NORMAL_STATE_DEFAULT_MASK (0x1)
#define NV_SOR_PWR_NORMAL_STATE_PD (0)
#define NV_SOR_PWR_NORMAL_STATE_PU (1)
#define NV_SOR_TEST (0x16)
#define NV_SOR_TEST_TESTMUX_SHIFT (24)
#define NV_SOR_TEST_TESTMUX_DEFAULT_MASK (0xff << 24)
#define NV_SOR_TEST_TESTMUX_AVSS (0 << 24)
#define NV_SOR_TEST_TESTMUX_CLOCKIN (2 << 24)
#define NV_SOR_TEST_TESTMUX_PLL_VOL (4 << 24)
#define NV_SOR_TEST_TESTMUX_SLOWCLKINT (8 << 24)
#define NV_SOR_TEST_TESTMUX_AVDD (16 << 24)
#define NV_SOR_TEST_TESTMUX_VDDREG (32 << 24)
#define NV_SOR_TEST_TESTMUX_REGREF_VDDREG (64 << 24)
#define NV_SOR_TEST_TESTMUX_REGREF_AVDD (128 << 24)
#define NV_SOR_TEST_CRC_SHIFT (23)
#define NV_SOR_TEST_CRC_PRE_SERIALIZE (0 << 23)
#define NV_SOR_TEST_CRC_POST_DESERIALIZE (1 << 23)
#define NV_SOR_TEST_TPAT_SHIFT (20)
#define NV_SOR_TEST_TPAT_DEFAULT_MASK (0x7 << 20)
#define NV_SOR_TEST_TPAT_LO (0 << 20)
#define NV_SOR_TEST_TPAT_TDAT (1 << 20)
#define NV_SOR_TEST_TPAT_RAMP (2 << 20)
#define NV_SOR_TEST_TPAT_WALK (3 << 20)
#define NV_SOR_TEST_TPAT_MAXSTEP (4 << 20)
#define NV_SOR_TEST_TPAT_MINSTEP (5 << 20)
#define NV_SOR_TEST_DSRC_SHIFT (16)
#define NV_SOR_TEST_DSRC_DEFAULT_MASK (0x3 << 16)
#define NV_SOR_TEST_DSRC_NORMAL (0 << 16)
#define NV_SOR_TEST_DSRC_DEBUG (1 << 16)
#define NV_SOR_TEST_DSRC_TGEN (2 << 16)
#define NV_SOR_TEST_HEAD_NUMBER_SHIFT (12)
#define NV_SOR_TEST_HEAD_NUMBER_DEFAULT_MASK (0x3 << 12)
#define NV_SOR_TEST_HEAD_NUMBER_NONE (0 << 12)
#define NV_SOR_TEST_HEAD_NUMBER_HEAD0 (1 << 12)
#define NV_SOR_TEST_HEAD_NUMBER_HEAD1 (2 << 12)
#define NV_SOR_TEST_ATTACHED_SHIFT (10)
#define NV_SOR_TEST_ATTACHED_DEFAULT_MASK (0x1 << 10)
#define NV_SOR_TEST_ATTACHED_FALSE (0 << 10)
#define NV_SOR_TEST_ATTACHED_TRUE (1 << 10)
#define NV_SOR_TEST_ACT_HEAD_OPMODE_SHIFT (8)
#define NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK (0x3 << 8)
#define NV_SOR_TEST_ACT_HEAD_OPMODE_SLEEP (0 << 8)
#define NV_SOR_TEST_ACT_HEAD_OPMODE_SNOOZE (1 << 8)
#define NV_SOR_TEST_ACT_HEAD_OPMODE_AWAKE (2 << 8)
#define NV_SOR_TEST_INVD_SHIFT (6)
#define NV_SOR_TEST_INVD_DISABLE (0 << 6)
#define NV_SOR_TEST_INVD_ENABLE (1 << 6)
#define NV_SOR_TEST_TEST_ENABLE_SHIFT (1)
#define NV_SOR_TEST_TEST_ENABLE_DISABLE (0 << 1)
#define NV_SOR_TEST_TEST_ENABLE_ENABLE (1 << 1)
#define NV_SOR_PLL0 (0x17)
#define NV_SOR_PLL0_ICHPMP_SHFIT (24)
#define NV_SOR_PLL0_ICHPMP_DEFAULT_MASK (0xf << 24)
#define NV_SOR_PLL0_VCOCAP_SHIFT (8)
#define NV_SOR_PLL0_VCOCAP_DEFAULT_MASK (0xf << 8)
#define NV_SOR_PLL0_PLLREG_LEVEL_SHIFT (6)
#define NV_SOR_PLL0_PLLREG_LEVEL_DEFAULT_MASK (0x3 << 6)
#define NV_SOR_PLL0_PLLREG_LEVEL_V25 (0 << 6)
#define NV_SOR_PLL0_PLLREG_LEVEL_V15 (1 << 6)
#define NV_SOR_PLL0_PLLREG_LEVEL_V35 (2 << 6)
#define NV_SOR_PLL0_PLLREG_LEVEL_V45 (3 << 6)
#define NV_SOR_PLL0_PULLDOWN_SHIFT (5)
#define NV_SOR_PLL0_PULLDOWN_DEFAULT_MASK (0x1 << 5)
#define NV_SOR_PLL0_PULLDOWN_DISABLE (0 << 5)
#define NV_SOR_PLL0_PULLDOWN_ENABLE (1 << 5)
#define NV_SOR_PLL0_RESISTORSEL_SHIFT (4)
#define NV_SOR_PLL0_RESISTORSEL_DEFAULT_MASK (0x1 << 4)
#define NV_SOR_PLL0_RESISTORSEL_INT (0 << 4)
#define NV_SOR_PLL0_RESISTORSEL_EXT (1 << 4)
#define NV_SOR_PLL0_VCOPD_SHIFT (2)
#define NV_SOR_PLL0_VCOPD_MASK (1 << 2)
#define NV_SOR_PLL0_VCOPD_RESCIND (0 << 2)
#define NV_SOR_PLL0_VCOPD_ASSERT (1 << 2)
#define NV_SOR_PLL0_PWR_SHIFT (0)
#define NV_SOR_PLL0_PWR_MASK (1)
#define NV_SOR_PLL0_PWR_ON (0)
#define NV_SOR_PLL0_PWR_OFF (1)
#define NV_SOR_PLL1_TMDS_TERM_SHIFT (8)
#define NV_SOR_PLL1_TMDS_TERM_DISABLE (0 << 8)
#define NV_SOR_PLL1_TMDS_TERM_ENABLE (1 << 8)
#define NV_SOR_PLL1 (0x18)
#define NV_SOR_PLL1_TERM_COMPOUT_SHIFT (15)
#define NV_SOR_PLL1_TERM_COMPOUT_LOW (0 << 15)
#define NV_SOR_PLL1_TERM_COMPOUT_HIGH (1 << 15)
#define NV_SOR_PLL2 (0x19)
#define NV_SOR_PLL2_DCIR_PLL_RESET_SHIFT (0)
#define NV_SOR_PLL2_DCIR_PLL_RESET_OVERRIDE (0 << 0)
#define NV_SOR_PLL2_DCIR_PLL_RESET_ALLOW (1 << 0)
#define NV_SOR_PLL2_AUX1_SHIFT (17)
#define NV_SOR_PLL2_AUX1_SEQ_MASK (1 << 17)
#define NV_SOR_PLL2_AUX1_SEQ_PLLCAPPD_ALLOW (0 << 17)
#define NV_SOR_PLL2_AUX1_SEQ_PLLCAPPD_OVERRIDE (1 << 17)
#define NV_SOR_PLL2_AUX2_SHIFT (18)
#define NV_SOR_PLL2_AUX2_MASK (1 << 18)
#define NV_SOR_PLL2_AUX2_OVERRIDE_POWERDOWN (0 << 18)
#define NV_SOR_PLL2_AUX2_ALLOW_POWERDOWN (1 << 18)
#define NV_SOR_PLL2_AUX6_SHIFT (22)
#define NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK (1 << 22)
#define NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE (0 << 22)
#define NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_ENABLE (1 << 22)
#define NV_SOR_PLL2_AUX7_SHIFT (23)
#define NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK (1 << 23)
#define NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE (0 << 23)
#define NV_SOR_PLL2_AUX7_PORT_POWERDOWN_ENABLE (1 << 23)
#define NV_SOR_PLL2_AUX8_SHIFT (24)
#define NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK (1 << 24)
#define NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE (0 << 24)
#define NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_ENABLE (1 << 24)
#define NV_SOR_PLL2_AUX9_SHIFT (25)
#define NV_SOR_PLL2_AUX9_LVDSEN_ALLOW (0 << 25)
#define NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE (1 << 25)
#define NV_SOR_PLL3 (0x1a)
#define NV_SOR_PLL3_PLLVDD_MODE_SHIFT (13)
#define NV_SOR_PLL3_PLLVDD_MODE_MASK (1 << 13)
#define NV_SOR_PLL3_PLLVDD_MODE_V1_8 (0 << 13)
#define NV_SOR_PLL3_PLLVDD_MODE_V3_3 (1 << 13)
#define NV_SOR_CSTM (0x1b)
#define NV_SOR_CSTM_ROTDAT_SHIFT (28)
#define NV_SOR_CSTM_ROTDAT_DEFAULT_MASK (0x7 << 28)
#define NV_SOR_CSTM_ROTCLK_SHIFT (24)
#define NV_SOR_CSTM_ROTCLK_DEFAULT_MASK (0xf << 24)
#define NV_SOR_CSTM_LVDS_EN_SHIFT (16)
#define NV_SOR_CSTM_LVDS_EN_DISABLE (0 << 16)
#define NV_SOR_CSTM_LVDS_EN_ENABLE (1 << 16)
#define NV_SOR_CSTM_LINKACTB_SHIFT (15)
#define NV_SOR_CSTM_LINKACTB_DISABLE (0 << 15)
#define NV_SOR_CSTM_LINKACTB_ENABLE (1 << 15)
#define NV_SOR_CSTM_LINKACTA_SHIFT (14)
#define NV_SOR_CSTM_LINKACTA_DISABLE (0 << 14)
#define NV_SOR_CSTM_LINKACTA_ENABLE (1 << 14)
#define NV_SOR_LVDS (0x1c)
#define NV_SOR_LVDS_ROTDAT_SHIFT (28)
#define NV_SOR_LVDS_ROTDAT_DEFAULT_MASK (0x7 << 28)
#define NV_SOR_LVDS_ROTDAT_RST (0 << 28)
#define NV_SOR_LVDS_ROTCLK_SHIFT (24)
#define NV_SOR_LVDS_ROTCLK_DEFAULT_MASK (0xf << 24)
#define NV_SOR_LVDS_ROTCLK_RST (0 << 24)
#define NV_SOR_LVDS_PLLDIV_SHIFT (21)
#define NV_SOR_LVDS_PLLDIV_DEFAULT_MASK (0x1 << 21)
#define NV_SOR_LVDS_PLLDIV_BY_7 (0 << 21)
#define NV_SOR_LVDS_BALANCED_SHIFT (19)
#define NV_SOR_LVDS_BALANCED_DEFAULT_MASK (0x1 << 19)
#define NV_SOR_LVDS_BALANCED_DISABLE (0 << 19)
#define NV_SOR_LVDS_BALANCED_ENABLE (1 << 19)
#define NV_SOR_LVDS_NEW_MODE_SHIFT (18)
#define NV_SOR_LVDS_NEW_MODE_DEFAULT_MASK (0x1 << 18)
#define NV_SOR_LVDS_NEW_MODE_DISABLE (0 << 18)
#define NV_SOR_LVDS_NEW_MODE_ENABLE (1 << 18)
#define NV_SOR_LVDS_DUP_SYNC_SHIFT (17)
#define NV_SOR_LVDS_DUP_SYNC_DEFAULT_MASK (0x1 << 17)
#define NV_SOR_LVDS_DUP_SYNC_DISABLE (0 << 17)
#define NV_SOR_LVDS_DUP_SYNC_ENABLE (1 << 17)
#define NV_SOR_LVDS_LVDS_EN_SHIFT (16)
#define NV_SOR_LVDS_LVDS_EN_DEFAULT_MASK (0x1 << 16)
#define NV_SOR_LVDS_LVDS_EN_ENABLE (1 << 16)
#define NV_SOR_LVDS_LINKACTB_SHIFT (15)
#define NV_SOR_LVDS_LINKACTB_DEFAULT_MASK (0x1 << 15)
#define NV_SOR_LVDS_LINKACTB_DISABLE (0 << 15)
#define NV_SOR_LVDS_LINKACTB_ENABLE (1 << 15)
#define NV_SOR_LVDS_LINKACTA_SHIFT (14)
#define NV_SOR_LVDS_LINKACTA_DEFAULT_MASK (0x1 << 14)
#define NV_SOR_LVDS_LINKACTA_ENABLE (1 << 14)
#define NV_SOR_LVDS_MODE_SHIFT (12)
#define NV_SOR_LVDS_MODE_DEFAULT_MASK (0x3 << 12)
#define NV_SOR_LVDS_MODE_LVDS (0 << 12)
#define NV_SOR_LVDS_UPPER_SHIFT (11)
#define NV_SOR_LVDS_UPPER_DEFAULT_MASK (0x1 << 11)
#define NV_SOR_LVDS_UPPER_FALSE (0 << 11)
#define NV_SOR_LVDS_UPPER_TRUE (1 << 11)
#define NV_SOR_LVDS_PD_TXCB_SHIFT (9)
#define NV_SOR_LVDS_PD_TXCB_DEFAULT_MASK (0x1 << 9)
#define NV_SOR_LVDS_PD_TXCB_ENABLE (0 << 9)
#define NV_SOR_LVDS_PD_TXCB_DISABLE (1 << 9)
#define NV_SOR_LVDS_PD_TXCA_SHIFT (8)
#define NV_SOR_LVDS_PD_TXCA_DEFAULT_MASK (0x1 << 8)
#define NV_SOR_LVDS_PD_TXCA_ENABLE (0 << 8)
#define NV_SOR_LVDS_PD_TXDB_3_SHIFT (7)
#define NV_SOR_LVDS_PD_TXDB_3_DEFAULT_MASK (0x1 << 7)
#define NV_SOR_LVDS_PD_TXDB_3_ENABLE (0 << 7)
#define NV_SOR_LVDS_PD_TXDB_3_DISABLE (1 << 7)
#define NV_SOR_LVDS_PD_TXDB_2_SHIFT (6)
#define NV_SOR_LVDS_PD_TXDB_2_DEFAULT_MASK (0x1 << 6)
#define NV_SOR_LVDS_PD_TXDB_2_ENABLE (0 << 6)
#define NV_SOR_LVDS_PD_TXDB_2_DISABLE (1 << 6)
#define NV_SOR_LVDS_PD_TXDB_1_SHIFT (5)
#define NV_SOR_LVDS_PD_TXDB_1_DEFAULT_MASK (0x1 << 5)
#define NV_SOR_LVDS_PD_TXDB_1_ENABLE (0 << 5)
#define NV_SOR_LVDS_PD_TXDB_1_DISABLE (1 << 5)
#define NV_SOR_LVDS_PD_TXDB_0_SHIFT (4)
#define NV_SOR_LVDS_PD_TXDB_0_DEFAULT_MASK (0x1 << 4)
#define NV_SOR_LVDS_PD_TXDB_0_ENABLE (0 << 4)
#define NV_SOR_LVDS_PD_TXDB_0_DISABLE (1 << 4)
#define NV_SOR_LVDS_PD_TXDA_3_SHIFT (3)
#define NV_SOR_LVDS_PD_TXDA_3_DEFAULT_MASK (0x1 << 3)
#define NV_SOR_LVDS_PD_TXDA_3_ENABLE (0 << 3)
#define NV_SOR_LVDS_PD_TXDA_3_DISABLE (1 << 3)
#define NV_SOR_LVDS_PD_TXDA_2_SHIFT (2)
#define NV_SOR_LVDS_PD_TXDA_2_DEFAULT_MASK (0x1 << 2)
#define NV_SOR_LVDS_PD_TXDA_2_ENABLE (0 << 2)
#define NV_SOR_LVDS_PD_TXDA_1_SHIFT (1)
#define NV_SOR_LVDS_PD_TXDA_1_DEFAULT_MASK (0x1 << 1)
#define NV_SOR_LVDS_PD_TXDA_1_ENABLE (0 << 1)
#define NV_SOR_LVDS_PD_TXDA_0_SHIFT (0)
#define NV_SOR_LVDS_PD_TXDA_0_DEFAULT_MASK (0x1)
#define NV_SOR_LVDS_PD_TXDA_0_ENABLE (0)
#define NV_SOR_CRCA (0x1d)
#define NV_SOR_CRCA_VALID_FALSE (0)
#define NV_SOR_CRCA_VALID_TRUE (1)
#define NV_SOR_CRCA_VALID_RST (1)
#define NV_SOR_CRCB (0x1e)
#define NV_SOR_CRCB_CRC_DEFAULT_MASK (0xffffffff)
#define NV_SOR_SEQ_CTL (0x20)
#define NV_SOR_SEQ_CTL_SWITCH_SHIFT (30)
#define NV_SOR_SEQ_CTL_SWITCH_MASK (0x1 << 30)
#define NV_SOR_SEQ_CTL_SWITCH_WAIT (0 << 30)
#define NV_SOR_SEQ_CTL_SWITCH_FORCE (1 << 30)
#define NV_SOR_SEQ_CTL_STATUS_SHIFT (28)
#define NV_SOR_SEQ_CTL_STATUS_MASK (0x1 << 28)
#define NV_SOR_SEQ_CTL_STATUS_STOPPED (0 << 28)
#define NV_SOR_SEQ_CTL_STATUS_RUNNING (1 << 28)
#define NV_SOR_SEQ_CTL_PC_SHIFT (16)
#define NV_SOR_SEQ_CTL_PC_MASK (0xf << 16)
#define NV_SOR_SEQ_CTL_PD_PC_ALT_SHIFT (12)
#define NV_SOR_SEQ_CTL_PD_PC_ALT_MASK (0xf << 12)
#define NV_SOR_SEQ_CTL_PD_PC_SHIFT (8)
#define NV_SOR_SEQ_CTL_PD_PC_MASK (0xf << 8)
#define NV_SOR_SEQ_CTL_PU_PC_ALT_SHIFT (4)
#define NV_SOR_SEQ_CTL_PU_PC_ALT_MASK (0xf << 4)
#define NV_SOR_SEQ_CTL_PU_PC_SHIFT (0)
#define NV_SOR_SEQ_CTL_PU_PC_MASK (0xf)
#define NV_SOR_LANE_SEQ_CTL (0x21)
#define NV_SOR_LANE_SEQ_CTL_SETTING_NEW_SHIFT (31)
#define NV_SOR_LANE_SEQ_CTL_SETTING_MASK (1 << 31)
#define NV_SOR_LANE_SEQ_CTL_SETTING_NEW_DONE (0 << 31)
#define NV_SOR_LANE_SEQ_CTL_SETTING_NEW_PENDING (1 << 31)
#define NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER (1 << 31)
#define NV_SOR_LANE_SEQ_CTL_SEQ_STATE_SHIFT (28)
#define NV_SOR_LANE_SEQ_CTL_SEQ_STATE_IDLE (0 << 28)
#define NV_SOR_LANE_SEQ_CTL_SEQ_STATE_BUSY (1 << 28)
#define NV_SOR_LANE_SEQ_CTL_SEQUENCE_SHIFT (20)
#define NV_SOR_LANE_SEQ_CTL_SEQUENCE_UP (0 << 20)
#define NV_SOR_LANE_SEQ_CTL_SEQUENCE_DOWN (1 << 20)
#define NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_SHIFT (16)
#define NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PU (0 << 16)
#define NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PD (1 << 16)
#define NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT (12)
#define NV_SOR_LANE_SEQ_CTL_DELAY_DEFAULT_MASK (0xf << 12)
#define NV_SOR_LANE_SEQ_CTL_LANE9_STATE_SHIFT (9)
#define NV_SOR_LANE_SEQ_CTL_LANE9_STATE_POWERUP (0 << 9)
#define NV_SOR_LANE_SEQ_CTL_LANE9_STATE_POWERDOWN (1 << 9)
#define NV_SOR_LANE_SEQ_CTL_LANE8_STATE_SHIFT (8)
#define NV_SOR_LANE_SEQ_CTL_LANE8_STATE_POWERUP (0 << 8)
#define NV_SOR_LANE_SEQ_CTL_LANE8_STATE_POWERDOWN (1 << 8)
#define NV_SOR_LANE_SEQ_CTL_LANE7_STATE_SHIFT (7)
#define NV_SOR_LANE_SEQ_CTL_LANE7_STATE_POWERUP (0 << 7)
#define NV_SOR_LANE_SEQ_CTL_LANE7_STATE_POWERDOWN (1 << 7)
#define NV_SOR_LANE_SEQ_CTL_LANE6_STATE_SHIFT (6)
#define NV_SOR_LANE_SEQ_CTL_LANE6_STATE_POWERUP (0 << 6)
#define NV_SOR_LANE_SEQ_CTL_LANE6_STATE_POWERDOWN (1 << 6)
#define NV_SOR_LANE_SEQ_CTL_LANE5_STATE_SHIFT (5)
#define NV_SOR_LANE_SEQ_CTL_LANE5_STATE_POWERUP (0 << 5)
#define NV_SOR_LANE_SEQ_CTL_LANE5_STATE_POWERDOWN (1 << 5)
#define NV_SOR_LANE_SEQ_CTL_LANE4_STATE_SHIFT (4)
#define NV_SOR_LANE_SEQ_CTL_LANE4_STATE_POWERUP (0 << 4)
#define NV_SOR_LANE_SEQ_CTL_LANE4_STATE_POWERDOWN (1 << 4)
#define NV_SOR_LANE_SEQ_CTL_LANE3_STATE_SHIFT (3)
#define NV_SOR_LANE_SEQ_CTL_LANE3_STATE_POWERUP (0 << 3)
#define NV_SOR_LANE_SEQ_CTL_LANE3_STATE_POWERDOWN (1 << 3)
#define NV_SOR_LANE_SEQ_CTL_LANE2_STATE_SHIFT (2)
#define NV_SOR_LANE_SEQ_CTL_LANE2_STATE_POWERUP (0 << 2)
#define NV_SOR_LANE_SEQ_CTL_LANE2_STATE_POWERDOWN (1 << 2)
#define NV_SOR_LANE_SEQ_CTL_LANE1_STATE_SHIFT (1)
#define NV_SOR_LANE_SEQ_CTL_LANE1_STATE_POWERUP (0 << 1)
#define NV_SOR_LANE_SEQ_CTL_LANE1_STATE_POWERDOWN (1 << 1)
#define NV_SOR_LANE_SEQ_CTL_LANE0_STATE_SHIFT (0)
#define NV_SOR_LANE_SEQ_CTL_LANE0_STATE_POWERUP (0)
#define NV_SOR_LANE_SEQ_CTL_LANE0_STATE_POWERDOWN (1)
#define NV_SOR_SEQ_INST(i) (0x22 + i)
#define NV_SOR_SEQ_INST_PLL_PULLDOWN_SHIFT (31)
#define NV_SOR_SEQ_INST_PLL_PULLDOWN_DISABLE (0 << 31)
#define NV_SOR_SEQ_INST_PLL_PULLDOWN_ENABLE (1 << 31)
#define NV_SOR_SEQ_INST_POWERDOWN_MACRO_SHIFT (30)
#define NV_SOR_SEQ_INST_POWERDOWN_MACRO_NORMAL (0 << 30)
#define NV_SOR_SEQ_INST_POWERDOWN_MACRO_POWERDOWN (1 << 30)
#define NV_SOR_SEQ_INST_ASSERT_PLL_RESET_SHIFT (29)
#define NV_SOR_SEQ_INST_ASSERT_PLL_RESET_NORMAL (0 << 29)
#define NV_SOR_SEQ_INST_ASSERT_PLL_RESET_RST (1 << 29)
#define NV_SOR_SEQ_INST_BLANK_V_SHIFT (28)
#define NV_SOR_SEQ_INST_BLANK_V_NORMAL (0 << 28)
#define NV_SOR_SEQ_INST_BLANK_V_INACTIVE (1 << 28)
#define NV_SOR_SEQ_INST_BLANK_H_SHIFT (27)
#define NV_SOR_SEQ_INST_BLANK_H_NORMAL (0 << 27)
#define NV_SOR_SEQ_INST_BLANK_H_INACTIVE (1 << 27)
#define NV_SOR_SEQ_INST_BLANK_DE_SHIFT (26)
#define NV_SOR_SEQ_INST_BLANK_DE_NORMAL (0 << 26)
#define NV_SOR_SEQ_INST_BLANK_DE_INACTIVE (1 << 26)
#define NV_SOR_SEQ_INST_BLACK_DATA_SHIFT (25)
#define NV_SOR_SEQ_INST_BLACK_DATA_NORMAL (0 << 25)
#define NV_SOR_SEQ_INST_BLACK_DATA_BLACK (1 << 25)
#define NV_SOR_SEQ_INST_TRISTATE_IOS_SHIFT (24)
#define NV_SOR_SEQ_INST_TRISTATE_IOS_ENABLE_PINS (0 << 24)
#define NV_SOR_SEQ_INST_TRISTATE_IOS_TRISTATE (1 << 24)
#define NV_SOR_SEQ_INST_DRIVE_PWM_OUT_LO_SHIFT (23)
#define NV_SOR_SEQ_INST_DRIVE_PWM_OUT_LO_FALSE (0 << 23)
#define NV_SOR_SEQ_INST_DRIVE_PWM_OUT_LO_TRUE (1 << 23)
#define NV_SOR_SEQ_INST_PIN_B_SHIFT (22)
#define NV_SOR_SEQ_INST_PIN_B_LOW (0 << 22)
#define NV_SOR_SEQ_INST_PIN_B_HIGH (1 << 22)
#define NV_SOR_SEQ_INST_PIN_A_SHIFT (21)
#define NV_SOR_SEQ_INST_PIN_A_LOW (0 << 21)
#define NV_SOR_SEQ_INST_PIN_A_HIGH (1 << 21)
#define NV_SOR_SEQ_INST_SEQUENCE_SHIFT (19)
#define NV_SOR_SEQ_INST_SEQUENCE_UP (0 << 19)
#define NV_SOR_SEQ_INST_SEQUENCE_DOWN (1 << 19)
#define NV_SOR_SEQ_INST_LANE_SEQ_SHIFT (18)
#define NV_SOR_SEQ_INST_LANE_SEQ_STOP (0 << 18)
#define NV_SOR_SEQ_INST_LANE_SEQ_RUN (1 << 18)
#define NV_SOR_SEQ_INST_PDPORT_SHIFT (17)
#define NV_SOR_SEQ_INST_PDPORT_NO (0 << 17)
#define NV_SOR_SEQ_INST_PDPORT_YES (1 << 17)
#define NV_SOR_SEQ_INST_PDPLL_SHIFT (16)
#define NV_SOR_SEQ_INST_PDPLL_NO (0 << 16)
#define NV_SOR_SEQ_INST_PDPLL_YES (1 << 16)
#define NV_SOR_SEQ_INST_HALT_SHIFT (15)
#define NV_SOR_SEQ_INST_HALT_FALSE (0 << 15)
#define NV_SOR_SEQ_INST_HALT_TRUE (1 << 15)
#define NV_SOR_SEQ_INST_WAIT_UNITS_SHIFT (12)
#define NV_SOR_SEQ_INST_WAIT_UNITS_DEFAULT_MASK (0x3 << 12)
#define NV_SOR_SEQ_INST_WAIT_UNITS_US (0 << 12)
#define NV_SOR_SEQ_INST_WAIT_UNITS_MS (1 << 12)
#define NV_SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12)
#define NV_SOR_SEQ_INST_WAIT_TIME_SHIFT (0)
#define NV_SOR_SEQ_INST_WAIT_TIME_DEFAULT_MASK (0x3ff)
#define NV_SOR_PWM_DIV (0x32)
#define NV_SOR_PWM_DIV_DIVIDE_DEFAULT_MASK (0xffffff)
#define NV_SOR_PWM_CTL (0x33)
#define NV_SOR_PWM_CTL_SETTING_NEW_SHIFT (31)
#define NV_SOR_PWM_CTL_SETTING_NEW_DONE (0 << 31)
#define NV_SOR_PWM_CTL_SETTING_NEW_PENDING (1 << 31)
#define NV_SOR_PWM_CTL_SETTING_NEW_TRIGGER (1 << 31)
#define NV_SOR_PWM_CTL_CLKSEL_SHIFT (30)
#define NV_SOR_PWM_CTL_CLKSEL_PCLK (0 << 30)
#define NV_SOR_PWM_CTL_CLKSEL_XTAL (1 << 30)
#define NV_SOR_PWM_CTL_DUTY_CYCLE_SHIFT (0)
#define NV_SOR_PWM_CTL_DUTY_CYCLE_MASK (0xffffff)
#define NV_SOR_MSCHECK (0x49)
#define NV_SOR_MSCHECK_CTL_SHIFT (31)
#define NV_SOR_MSCHECK_CTL_CLEAR (0 << 31)
#define NV_SOR_MSCHECK_CTL_RUN (1 << 31)
#define NV_SOR_XBAR_CTRL (0x4a)
#define NV_SOR_DP_LINKCTL(i) (0x4c + (i))
#define NV_SOR_DP_LINKCTL_FORCE_IDLEPTTRN_SHIFT (31)
#define NV_SOR_DP_LINKCTL_FORCE_IDLEPTTRN_NO (0 << 31)
#define NV_SOR_DP_LINKCTL_FORCE_IDLEPTTRN_YES (1 << 31)
#define NV_SOR_DP_LINKCTL_COMPLIANCEPTTRN_SHIFT (28)
#define NV_SOR_DP_LINKCTL_COMPLIANCEPTTRN_NOPATTERN (0 << 28)
#define NV_SOR_DP_LINKCTL_COMPLIANCEPTTRN_COLORSQARE (1 << 28)
#define NV_SOR_DP_LINKCTL_LANECOUNT_SHIFT (16)
#define NV_SOR_DP_LINKCTL_LANECOUNT_MASK (0x1f << 16)
#define NV_SOR_DP_LINKCTL_LANECOUNT_ZERO (0 << 16)
#define NV_SOR_DP_LINKCTL_LANECOUNT_ONE (1 << 16)
#define NV_SOR_DP_LINKCTL_LANECOUNT_TWO (3 << 16)
#define NV_SOR_DP_LINKCTL_LANECOUNT_FOUR (15 << 16)
#define NV_SOR_DP_LINKCTL_ENHANCEDFRAME_SHIFT (14)
#define NV_SOR_DP_LINKCTL_ENHANCEDFRAME_DISABLE (0 << 14)
#define NV_SOR_DP_LINKCTL_ENHANCEDFRAME_ENABLE (1 << 14)
#define NV_SOR_DP_LINKCTL_SYNCMODE_SHIFT (10)
#define NV_SOR_DP_LINKCTL_SYNCMODE_DISABLE (0 << 10)
#define NV_SOR_DP_LINKCTL_SYNCMODE_ENABLE (1 << 10)
#define NV_SOR_DP_LINKCTL_TUSIZE_SHIFT (2)
#define NV_SOR_DP_LINKCTL_TUSIZE_MASK (0x7f << 2)
#define NV_SOR_DP_LINKCTL_ENABLE_SHIFT (0)
#define NV_SOR_DP_LINKCTL_ENABLE_NO (0)
#define NV_SOR_DP_LINKCTL_ENABLE_YES (1)
#define NV_SOR_DC(i) (0x4e + (i))
#define NV_SOR_DC_LANE3_DP_LANE3_SHIFT (24)
#define NV_SOR_DC_LANE3_DP_LANE3_MASK (0xff << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P0_LEVEL0 (17 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P1_LEVEL0 (21 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P2_LEVEL0 (26 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P3_LEVEL0 (34 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P0_LEVEL1 (26 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P1_LEVEL1 (32 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P2_LEVEL1 (39 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P0_LEVEL2 (34 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P1_LEVEL2 (43 << 24)
#define NV_SOR_DC_LANE3_DP_LANE3_P0_LEVEL3 (51 << 24)
#define NV_SOR_DC_LANE2_DP_LANE0_SHIFT (16)
#define NV_SOR_DC_LANE2_DP_LANE0_MASK (0xff << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P0_LEVEL0 (17 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P1_LEVEL0 (21 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P2_LEVEL0 (26 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P3_LEVEL0 (34 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P0_LEVEL1 (26 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P1_LEVEL1 (32 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P2_LEVEL1 (39 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P0_LEVEL2 (34 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P1_LEVEL2 (43 << 16)
#define NV_SOR_DC_LANE2_DP_LANE0_P0_LEVEL3 (51 << 16)
#define NV_SOR_DC_LANE1_DP_LANE1_SHIFT (8)
#define NV_SOR_DC_LANE1_DP_LANE1_MASK (0xff << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P0_LEVEL0 (17 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P1_LEVEL0 (21 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P2_LEVEL0 (26 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P3_LEVEL0 (34 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P0_LEVEL1 (26 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P1_LEVEL1 (32 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P2_LEVEL1 (39 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P0_LEVEL2 (34 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P1_LEVEL2 (43 << 8)
#define NV_SOR_DC_LANE1_DP_LANE1_P0_LEVEL3 (51 << 8)
#define NV_SOR_DC_LANE0_DP_LANE2_SHIFT (0)
#define NV_SOR_DC_LANE0_DP_LANE2_MASK (0xff)
#define NV_SOR_DC_LANE0_DP_LANE2_P0_LEVEL0 (17)
#define NV_SOR_DC_LANE0_DP_LANE2_P1_LEVEL0 (21)
#define NV_SOR_DC_LANE0_DP_LANE2_P2_LEVEL0 (26)
#define NV_SOR_DC_LANE0_DP_LANE2_P3_LEVEL0 (34)
#define NV_SOR_DC_LANE0_DP_LANE2_P0_LEVEL1 (26)
#define NV_SOR_DC_LANE0_DP_LANE2_P1_LEVEL1 (32)
#define NV_SOR_DC_LANE0_DP_LANE2_P2_LEVEL1 (39)
#define NV_SOR_DC_LANE0_DP_LANE2_P0_LEVEL2 (34)
#define NV_SOR_DC_LANE0_DP_LANE2_P1_LEVEL2 (43)
#define NV_SOR_DC_LANE0_DP_LANE2_P0_LEVEL3 (51)
#define NV_SOR_LANE_DRIVE_CURRENT(i) (0x4e + (i))
#define NV_SOR_PR(i) (0x52 + (i))
#define NV_SOR_PR_LANE3_DP_LANE3_SHIFT (24)
#define NV_SOR_PR_LANE3_DP_LANE3_MASK (0xff << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D0_LEVEL0 (0 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D1_LEVEL0 (0 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D2_LEVEL0 (0 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D3_LEVEL0 (0 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D0_LEVEL1 (4 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D1_LEVEL1 (6 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D2_LEVEL1 (17 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D0_LEVEL2 (8 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D1_LEVEL2 (13 << 24)
#define NV_SOR_PR_LANE3_DP_LANE3_D0_LEVEL3 (17 << 24)
#define NV_SOR_PR_LANE2_DP_LANE0_SHIFT (16)
#define NV_SOR_PR_LANE2_DP_LANE0_MASK (0xff << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D0_LEVEL0 (0 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D1_LEVEL0 (0 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D2_LEVEL0 (0 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D3_LEVEL0 (0 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D0_LEVEL1 (4 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D1_LEVEL1 (6 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D2_LEVEL1 (17 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D0_LEVEL2 (8 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D1_LEVEL2 (13 << 16)
#define NV_SOR_PR_LANE2_DP_LANE0_D0_LEVEL3 (17 << 16)
#define NV_SOR_PR_LANE1_DP_LANE1_SHIFT (8)
#define NV_SOR_PR_LANE1_DP_LANE1_MASK (0xff >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D0_LEVEL0 (0 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D1_LEVEL0 (0 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D2_LEVEL0 (0 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D3_LEVEL0 (0 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D0_LEVEL1 (4 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D1_LEVEL1 (6 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D2_LEVEL1 (17 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D0_LEVEL2 (8 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D1_LEVEL2 (13 >> 8)
#define NV_SOR_PR_LANE1_DP_LANE1_D0_LEVEL3 (17 >> 8)
#define NV_SOR_PR_LANE0_DP_LANE2_SHIFT (0)
#define NV_SOR_PR_LANE0_DP_LANE2_MASK (0xff)
#define NV_SOR_PR_LANE0_DP_LANE2_D0_LEVEL0 (0)
#define NV_SOR_PR_LANE0_DP_LANE2_D1_LEVEL0 (0)
#define NV_SOR_PR_LANE0_DP_LANE2_D2_LEVEL0 (0)
#define NV_SOR_PR_LANE0_DP_LANE2_D3_LEVEL0 (0)
#define NV_SOR_PR_LANE0_DP_LANE2_D0_LEVEL1 (4)
#define NV_SOR_PR_LANE0_DP_LANE2_D1_LEVEL1 (6)
#define NV_SOR_PR_LANE0_DP_LANE2_D2_LEVEL1 (17)
#define NV_SOR_PR_LANE0_DP_LANE2_D0_LEVEL2 (8)
#define NV_SOR_PR_LANE0_DP_LANE2_D1_LEVEL2 (13)
#define NV_SOR_PR_LANE0_DP_LANE2_D0_LEVEL3 (17)
#define NV_SOR_LANE4_PREEMPHASIS(i) (0x54 + (i))
#define NV_SOR_POSTCURSOR(i) (0x56 + (i))
#define NV_SOR_DP_CONFIG(i) (0x58 + (i))
#define NV_SOR_DP_CONFIG_RD_RESET_VAL_SHIFT (31)
#define NV_SOR_DP_CONFIG_RD_RESET_VAL_POSITIVE (0 << 31)
#define NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE (1 << 31)
#define NV_SOR_DP_CONFIG_IDLE_BEFORE_ATTACH_SHIFT (28)
#define NV_SOR_DP_CONFIG_IDLE_BEFORE_ATTACH_DISABLE (0 << 28)
#define NV_SOR_DP_CONFIG_IDLE_BEFORE_ATTACH_ENABLE (1 << 28)
#define NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_SHIFT (26)
#define NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_DISABLE (0 << 26)
#define NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE (1 << 26)
#define NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_SHIFT (24)
#define NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_NEGATIVE (0 << 24)
#define NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE (1 << 24)
#define NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_SHIFT (16)
#define NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_MASK (0xf << 16)
#define NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_SHIFT (8)
#define NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_MASK (0x7f << 8)
#define NV_SOR_DP_CONFIG_WATERMARK_SHIFT (0)
#define NV_SOR_DP_CONFIG_WATERMARK_MASK (0x3f)
#define NV_SOR_DP_MN(i) (0x5a + i)
#define NV_SOR_DP_MN_M_MOD_SHIFT (30)
#define NV_SOR_DP_MN_M_MOD_DEFAULT_MASK (0x3 << 30)
#define NV_SOR_DP_MN_M_MOD_NONE (0 << 30)
#define NV_SOR_DP_MN_M_MOD_INC (1 << 30)
#define NV_SOR_DP_MN_M_MOD_DEC (2 << 30)
#define NV_SOR_DP_MN_M_DELTA_SHIFT (24)
#define NV_SOR_DP_MN_M_DELTA_DEFAULT_MASK (0xf << 24)
#define NV_SOR_DP_MN_N_VAL_SHIFT (0)
#define NV_SOR_DP_MN_N_VAL_DEFAULT_MASK (0xffffff)
#define NV_SOR_DP_PADCTL(i) (0x5c + (i))
#define NV_SOR_DP_PADCTL_SPARE_SHIFT (25)
#define NV_SOR_DP_PADCTL_SPARE_DEFAULT_MASK (0x7f << 25)
#define NV_SOR_DP_PADCTL_VCO_2X_SHIFT (24)
#define NV_SOR_DP_PADCTL_VCO_2X_DISABLE (0 << 24)
#define NV_SOR_DP_PADCTL_VCO_2X_ENABLE (1 << 24)
#define NV_SOR_DP_PADCTL_PAD_CAL_PD_SHIFT (23)
#define NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERUP (0 << 23)
#define NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN (1 << 23)
#define NV_SOR_DP_PADCTL_TX_PU_SHIFT (22)
#define NV_SOR_DP_PADCTL_TX_PU_DISABLE (0 << 22)
#define NV_SOR_DP_PADCTL_TX_PU_ENABLE (1 << 22)
#define NV_SOR_DP_PADCTL_REG_CTRL_SHIFT (20)
#define NV_SOR_DP_PADCTL_REG_CTRL_DEFAULT_MASK (0x3 << 20)
#define NV_SOR_DP_PADCTL_VCMMODE_SHIFT (16)
#define NV_SOR_DP_PADCTL_VCMMODE_DEFAULT_MASK (0xf << 16)
#define NV_SOR_DP_PADCTL_VCMMODE_TRISTATE (0 << 16)
#define NV_SOR_DP_PADCTL_VCMMODE_TEST_MUX (1 << 16)
#define NV_SOR_DP_PADCTL_VCMMODE_WEAK_PULLDOWN (2 << 16)
#define NV_SOR_DP_PADCTL_VCMMODE_STRONG_PULLDOWN (4 << 16)
#define NV_SOR_DP_PADCTL_TX_PU_VALUE_SHIFT (8)
#define NV_SOR_DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK (0xff << 8)
#define NV_SOR_DP_PADCTL_COMODE_TXD_3_DP_TXD_3_SHIFT (7)
#define NV_SOR_DP_PADCTL_COMODE_TXD_3_DP_TXD_3_DISABLE (0 << 7)
#define NV_SOR_DP_PADCTL_COMODE_TXD_3_DP_TXD_3_ENABLE (1 << 7)
#define NV_SOR_DP_PADCTL_COMODE_TXD_2_DP_TXD_0_SHIFT (6)
#define NV_SOR_DP_PADCTL_COMODE_TXD_2_DP_TXD_0_DISABLE (0 << 6)
#define NV_SOR_DP_PADCTL_COMODE_TXD_2_DP_TXD_0_ENABLE (1 << 6)
#define NV_SOR_DP_PADCTL_COMODE_TXD_1_DP_TXD_1_SHIFT (5)
#define NV_SOR_DP_PADCTL_COMODE_TXD_1_DP_TXD_1_DISABLE (0 << 5)
#define NV_SOR_DP_PADCTL_COMODE_TXD_1_DP_TXD_1_ENABLE (1 << 5)
#define NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT (4)
#define NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_DISABLE (0 << 4)
#define NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_ENABLE (1 << 4)
#define NV_SOR_DP_PADCTL_PD_TXD_3_SHIFT (3)
#define NV_SOR_DP_PADCTL_PD_TXD_3_YES (0 << 3)
#define NV_SOR_DP_PADCTL_PD_TXD_3_NO (1 << 3)
#define NV_SOR_DP_PADCTL_PD_TXD_0_SHIFT (2)
#define NV_SOR_DP_PADCTL_PD_TXD_0_YES (0 << 2)
#define NV_SOR_DP_PADCTL_PD_TXD_0_NO (1 << 2)
#define NV_SOR_DP_PADCTL_PD_TXD_1_SHIFT (1)
#define NV_SOR_DP_PADCTL_PD_TXD_1_YES (0 << 1)
#define NV_SOR_DP_PADCTL_PD_TXD_1_NO (1 << 1)
#define NV_SOR_DP_PADCTL_PD_TXD_2_SHIFT (0)
#define NV_SOR_DP_PADCTL_PD_TXD_2_YES (0)
#define NV_SOR_DP_PADCTL_PD_TXD_2_NO (1)
#define NV_SOR_DP_DEBUG(i) (0x5e + i)
#define NV_SOR_DP_SPARE(i) (0x60 + (i))
#define NV_SOR_DP_SPARE_REG_SHIFT (3)
#define NV_SOR_DP_SPARE_REG_DEFAULT_MASK (0x1fffffff << 3)
#define NV_SOR_DP_SPARE_SOR_CLK_SEL_SHIFT (2)
#define NV_SOR_DP_SPARE_SOR_CLK_SEL_DEFAULT_MASK (0x1 << 2)
#define NV_SOR_DP_SPARE_SOR_CLK_SEL_SAFE_SORCLK (0 << 2)
#define NV_SOR_DP_SPARE_SOR_CLK_SEL_MACRO_SORCLK (1 << 2)
#define NV_SOR_DP_SPARE_PANEL_SHIFT (1)
#define NV_SOR_DP_SPARE_PANEL_EXTERNAL (0 << 1)
#define NV_SOR_DP_SPARE_PANEL_INTERNAL (1 << 1)
#define NV_SOR_DP_SPARE_SEQ_ENABLE_SHIFT (0)
#define NV_SOR_DP_SPARE_SEQ_ENABLE_NO (0)
#define NV_SOR_DP_SPARE_SEQ_ENABLE_YES (1)
#define NV_SOR_DP_AUDIO_CTRL (0x62)
#define NV_SOR_DP_AUDIO_HBLANK_SYMBOLS (0x63)
#define NV_SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK (0x1ffff)
#define NV_SOR_DP_AUDIO_HBLANK_SYMBOLS_VALUE_SHIFT (0)
#define NV_SOR_DP_AUDIO_VBLANK_SYMBOLS (0x64)
#define NV_SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK (0x1ffff)
#define NV_SOR_DP_AUDIO_VBLANK_SYMBOLS_SHIFT (0)
#define NV_SOR_DP_GENERIC_INFOFRAME_HEADER (0x65)
#define NV_SOR_DP_GENERIC_INFOFRAME_SUBPACK(i) (0x66 + (i))
#define NV_SOR_DP_TPG (0x6d)
#define NV_SOR_DP_TPG_LANE3_CHANNELCODING_SHIFT (30)
#define NV_SOR_DP_TPG_LANE3_CHANNELCODING_DISABLE (0 << 30)
#define NV_SOR_DP_TPG_LANE3_CHANNELCODING_ENABLE (1 << 30)
#define NV_SOR_DP_TPG_LANE3_SCRAMBLEREN_SHIFT (28)
#define NV_SOR_DP_TPG_LANE3_SCRAMBLEREN_ENABLE_GALIOS (1 << 28)
#define NV_SOR_DP_TPG_LANE3_SCRAMBLEREN_ENABLE_FIBONACCI (2 << 28)
#define NV_SOR_DP_TPG_LANE3_PATTERN_SHIFT (24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_DEFAULT_MASK (0xf << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_NOPATTERN (0 << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_TRAINING1 (1 << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_TRAINING2 (2 << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_TRAINING3 (3 << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_D102 (4 << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_SBLERRRATE (5 << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_PRBS7 (6 << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_CSTM (7 << 24)
#define NV_SOR_DP_TPG_LANE3_PATTERN_HBR2_COMPLIANCE (8 << 24)
#define NV_SOR_DP_TPG_LANE2_CHANNELCODING_SHIFT (22)
#define NV_SOR_DP_TPG_LANE2_CHANNELCODING_DISABLE (0 << 22)
#define NV_SOR_DP_TPG_LANE2_CHANNELCODING_ENABLE (1 << 22)
#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_SHIFT (20)
#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_DEFAULT_MASK (0x3 << 20)
#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_DISABLE (0 << 20)
#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_ENABLE_GALIOS (1 << 20)
#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_ENABLE_FIBONACCI (2 << 20)
#define NV_SOR_DP_TPG_LANE2_PATTERN_SHIFT (16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_DEFAULT_MASK (0xf << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_NOPATTERN (0 << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_TRAINING1 (1 << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_TRAINING2 (2 << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_TRAINING3 (3 << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_D102 (4 << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_SBLERRRATE (5 << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_PRBS7 (6 << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_CSTM (7 << 16)
#define NV_SOR_DP_TPG_LANE2_PATTERN_HBR2_COMPLIANCE (8 << 16)
#define NV_SOR_DP_TPG_LANE1_CHANNELCODING_SHIFT (14)
#define NV_SOR_DP_TPG_LANE1_CHANNELCODING_DISABLE (0 << 14)
#define NV_SOR_DP_TPG_LANE1_CHANNELCODING_ENABLE (1 << 14)
#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_SHIFT (12)
#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_DEFAULT_MASK (0x3 << 12)
#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_DISABLE (0 << 12)
#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_ENABLE_GALIOS (1 << 12)
#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_ENABLE_FIBONACCI (2 << 12)
#define NV_SOR_DP_TPG_LANE1_PATTERN_SHIFT (8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_DEFAULT_MASK (0xf << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_NOPATTERN (0 << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_TRAINING1 (1 << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_TRAINING2 (2 << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_TRAINING3 (3 << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_D102 (4 << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_SBLERRRATE (5 << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_PRBS7 (6 << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_CSTM (7 << 8)
#define NV_SOR_DP_TPG_LANE1_PATTERN_HBR2_COMPLIANCE (8 << 8)
#define NV_SOR_DP_TPG_LANE0_CHANNELCODING_SHIFT (6)
#define NV_SOR_DP_TPG_LANE0_CHANNELCODING_DISABLE (0 << 6)
#define NV_SOR_DP_TPG_LANE0_CHANNELCODING_ENABLE (1 << 6)
#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_SHIFT (4)
#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_DEFAULT_MASK (0x3 << 4)
#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_DISABLE (0 << 4)
#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_ENABLE_GALIOS (1 << 4)
#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_ENABLE_FIBONACCI (2 << 4)
#define NV_SOR_DP_TPG_LANE0_PATTERN_SHIFT (0)
#define NV_SOR_DP_TPG_LANE0_PATTERN_DEFAULT_MASK (0xf)
#define NV_SOR_DP_TPG_LANE0_PATTERN_NOPATTERN (0)
#define NV_SOR_DP_TPG_LANE0_PATTERN_TRAINING1 (1)
#define NV_SOR_DP_TPG_LANE0_PATTERN_TRAINING2 (2)
#define NV_SOR_DP_TPG_LANE0_PATTERN_TRAINING3 (3)
#define NV_SOR_DP_TPG_LANE0_PATTERN_D102 (4)
#define NV_SOR_DP_TPG_LANE0_PATTERN_SBLERRRATE (5)
#define NV_SOR_DP_TPG_LANE0_PATTERN_PRBS7 (6)
#define NV_SOR_DP_TPG_LANE0_PATTERN_CSTM (7)
#define NV_SOR_DP_TPG_LANE0_PATTERN_HBR2_COMPLIANCE (8)
enum {
trainingPattern_Disabled = 0,
trainingPattern_1 = 1,
trainingPattern_2 = 2,
trainingPattern_3 = 3,
trainingPattern_None = 0xff
};
enum tegra_dc_sor_protocol {
SOR_DP,
SOR_LVDS,
};
#define NV_SOR_LINK_SPEED_G1_62 6
#define NV_SOR_LINK_SPEED_G2_7 10
#define NV_SOR_LINK_SPEED_G5_4 20
#define NV_SOR_LINK_SPEED_LVDS 7
/* todo: combine this and the intel_dp struct into one struct. */
struct tegra_dc_dp_link_config {
int is_valid;
/* Supported configuration */
u8 max_link_bw;
u8 max_lane_count;
int downspread;
int support_enhanced_framing;
u32 bits_per_pixel;
int alt_scramber_reset_cap; /* true for eDP */
int only_enhanced_framing; /* enhanced_frame_en ignored */
/* Actual configuration */
u8 link_bw;
u8 lane_count;
int enhanced_framing;
int scramble_ena;
u32 activepolarity;
u32 active_count;
u32 tu_size;
u32 active_frac;
u32 watermark;
s32 hblank_sym;
s32 vblank_sym;
/* Training data */
u32 drive_current;
u32 preemphasis;
u32 postcursor;
};
/* TODO: just pull these up into one struct? Need to see how this impacts
* having two channels.
*/
struct tegra_dc_sor_data {
struct tegra_dc *dc;
void *base;
u8 portnum; /* 0 or 1 */
const struct tegra_dc_dp_link_config *link_cfg;
int power_is_up;
};
#define TEGRA_SOR_TIMEOUT_MS 1000
#define TEGRA_SOR_ATTACH_TIMEOUT_MS 100000
void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor,
int ena,
u8 training_pattern,
const struct tegra_dc_dp_link_config *cfg);
void tegra_dc_sor_set_dp_lanedata(struct tegra_dc_sor_data *sor,
u32 lane, u32 pre_emphasis,
u32 drive_current, u32 tx_pu);
#endif /*__TEGRA124_SOR_H__ */

View File

@ -26,6 +26,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <arch/cache.h>
#include <arch/io.h>
#include <console/console.h>
#include <soc/addressmap.h>
@ -46,8 +47,7 @@
*/
#define SPI_PACKET_SIZE_BYTES 1
#define SPI_MAX_TRANSFER_BYTES_FIFO (64 * SPI_PACKET_SIZE_BYTES)
#define SPI_MAX_TRANSFER_BYTES_DMA ((65536 * SPI_PACKET_SIZE_BYTES) - \
TEGRA_DMA_ALIGN_BYTES)
#define SPI_MAX_TRANSFER_BYTES_DMA (65535 * SPI_PACKET_SIZE_BYTES)
/* COMMAND1 */
#define SPI_CMD1_GO (1 << 31)
@ -114,32 +114,9 @@
#define SPI_DMA_CTL_TX_TRIG_SHIFT 15
/* SPI_DMA_BLK */
#define SPI_DMA_CTL_BLOCK_SIZE_MASK 0xff
#define SPI_DMA_CTL_BLOCK_SIZE_MASK 0xffff
#define SPI_DMA_CTL_BLOCK_SIZE_SHIFT 0
struct tegra_spi_regs {
u32 command1; /* 0x000: SPI_COMMAND1 */
u32 command2; /* 0x004: SPI_COMMAND2 */
u32 timing1; /* 0x008: SPI_CS_TIM1 */
u32 timing2; /* 0x00c: SPI_CS_TIM2 */
u32 trans_status; /* 0x010: SPI_TRANS_STATUS */
u32 fifo_status; /* 0x014: SPI_FIFO_STATUS */
u32 tx_data; /* 0x018: SPI_TX_DATA */
u32 rx_data; /* 0x01c: SPI_RX_DATA */
u32 dma_ctl; /* 0x020: SPI_DMA_CTL */
u32 dma_blk; /* 0x024: SPI_DMA_BLK */
u32 rsvd[56]; /* 0x028-0x107: reserved */
u32 tx_fifo; /* 0x108: SPI_FIFO1 */
u32 rsvd2[31]; /* 0x10c-0x187 reserved */
u32 rx_fifo; /* 0x188: SPI_FIFO2 */
u32 spare_ctl; /* 0x18c: SPI_SPARE_CTRL */
} __attribute__((packed));
struct tegra_spi_channel {
struct spi_slave slave;
struct tegra_spi_regs *regs;
};
static struct tegra_spi_channel tegra_spi_channels[] = {
/*
* Note: Tegra pinmux must be setup for corresponding SPI channel in
@ -175,40 +152,35 @@ static struct tegra_spi_channel tegra_spi_channels[] = {
},
};
static void flush_fifos(struct tegra_spi_regs *regs)
{
setbits_le32(&regs->fifo_status, SPI_FIFO_STATUS_RX_FIFO_FLUSH |
SPI_FIFO_STATUS_TX_FIFO_FLUSH);
while (read32(&regs->fifo_status) &
(SPI_FIFO_STATUS_RX_FIFO_FLUSH | SPI_FIFO_STATUS_TX_FIFO_FLUSH))
;
}
enum spi_direction {
SPI_SEND,
SPI_RECEIVE,
};
void tegra_spi_init(unsigned int bus)
struct tegra_spi_channel *tegra_spi_init(unsigned int bus)
{
int i;
struct tegra_spi_channel *spi = NULL;
for (i = 0; i < ARRAY_SIZE(tegra_spi_channels); i++) {
struct tegra_spi_regs *regs;
if (tegra_spi_channels[i].slave.bus == bus)
regs = tegra_spi_channels[i].regs;
else
continue;
if (tegra_spi_channels[i].slave.bus == bus) {
spi = &tegra_spi_channels[i];
break;
}
}
if (!spi)
return NULL;
/* software drives chip-select, set value to high */
setbits_le32(&regs->command1,
setbits_le32(&spi->regs->command1,
SPI_CMD1_CS_SW_HW | SPI_CMD1_CS_SW_VAL);
/* 8-bit transfers, unpacked mode, most significant bit first */
clrbits_le32(&regs->command1,
clrbits_le32(&spi->regs->command1,
SPI_CMD1_BIT_LEN_MASK | SPI_CMD1_PACKED);
setbits_le32(&regs->command1, 7 << SPI_CMD1_BIT_LEN_SHIFT);
flush_fifos(regs);
}
printk(BIOS_INFO, "Tegra SPI bus %d initialized.\n", bus);
setbits_le32(&spi->regs->command1, 7 << SPI_CMD1_BIT_LEN_SHIFT);
return spi;
}
static struct tegra_spi_channel * const to_tegra_spi(int bus) {
@ -221,27 +193,6 @@ static unsigned int tegra_spi_speed(unsigned int bus)
return 50000000;
}
/*
* This calls udelay() with a calculated value based on the SPI speed and
* number of bytes remaining to be transferred. It assumes that if the
* calculated delay period is less than MIN_DELAY_US then it is probably
* not worth the overhead of yielding.
*/
#define MIN_DELAY_US 250
static void tegra_spi_delay(struct tegra_spi_channel *spi,
unsigned int bytes_remaining)
{
unsigned int ns_per_byte, delay_us;
ns_per_byte = 1000000000 / (tegra_spi_speed(spi->slave.bus) / 8);
delay_us = (ns_per_byte * bytes_remaining) / 1000;
if (delay_us < MIN_DELAY_US)
return;
udelay(delay_us);
}
void spi_cs_activate(struct spi_slave *slave)
{
struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs;
@ -343,22 +294,6 @@ static void dump_dma_regs(struct apb_dma_channel *dma)
read32(&dma->regs->word_transfer));
}
static void dump_regs(struct tegra_spi_channel *spi,
struct apb_dma_channel *dma)
{
if (dma)
dump_dma_regs(dma);
if (spi) {
dump_spi_regs(spi);
dump_fifo_status(spi);
}
}
static int fifo_error(struct tegra_spi_channel *spi)
{
return read32(&spi->regs->fifo_status) & SPI_FIFO_STATUS_ERR ? 1 : 0;
}
static inline unsigned int spi_byte_count(struct tegra_spi_channel *spi)
{
/* FIXME: Make this take total packet size into account */
@ -366,102 +301,111 @@ static inline unsigned int spi_byte_count(struct tegra_spi_channel *spi)
(SPI_STATUS_BLOCK_COUNT << SPI_STATUS_BLOCK_COUNT_SHIFT);
}
static int tegra_spi_fifo_receive(struct tegra_spi_channel *spi,
u8 *din, unsigned int in_bytes)
/*
* This calls udelay() with a calculated value based on the SPI speed and
* number of bytes remaining to be transferred. It assumes that if the
* calculated delay period is less than MIN_DELAY_US then it is probably
* not worth the overhead of yielding.
*/
#define MIN_DELAY_US 250
static void spi_delay(struct tegra_spi_channel *spi,
unsigned int bytes_remaining)
{
unsigned int received = 0, remaining = in_bytes;
unsigned int ns_per_byte, delay_us;
printk(BIOS_SPEW, "%s: Receiving %d bytes\n", __func__, in_bytes);
setbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN);
ns_per_byte = 1000000000 / (tegra_spi_speed(spi->slave.bus) / 8);
delay_us = (ns_per_byte * bytes_remaining) / 1000;
while (remaining) {
unsigned int from_fifo, count;
if (delay_us < MIN_DELAY_US)
return;
from_fifo = MIN(in_bytes, SPI_MAX_TRANSFER_BYTES_FIFO);
remaining -= from_fifo;
udelay(delay_us);
}
static void tegra_spi_wait(struct tegra_spi_channel *spi)
{
unsigned int count, dma_blk;
dma_blk = 1 + (read32(&spi->regs->dma_blk) &
(SPI_DMA_CTL_BLOCK_SIZE_MASK << SPI_DMA_CTL_BLOCK_SIZE_SHIFT));
while ((count = spi_byte_count(spi)) != dma_blk)
spi_delay(spi, dma_blk - count);
}
static int fifo_error(struct tegra_spi_channel *spi)
{
return read32(&spi->regs->fifo_status) & SPI_FIFO_STATUS_ERR ? 1 : 0;
}
static int tegra_spi_pio_prepare(struct tegra_spi_channel *spi,
unsigned int bytes, enum spi_direction dir)
{
u8 *p = spi->out_buf;
unsigned int todo = MIN(bytes, SPI_MAX_TRANSFER_BYTES_FIFO);
u32 flush_mask, enable_mask;
if (dir == SPI_SEND) {
flush_mask = SPI_FIFO_STATUS_TX_FIFO_FLUSH;
enable_mask = SPI_CMD1_TX_EN;
} else {
flush_mask = SPI_FIFO_STATUS_RX_FIFO_FLUSH;
enable_mask = SPI_CMD1_RX_EN;
}
setbits_le32(&spi->regs->fifo_status, flush_mask);
while (read32(&spi->regs->fifo_status) & flush_mask)
;
setbits_le32(&spi->regs->command1, enable_mask);
/* BLOCK_SIZE in SPI_DMA_BLK register applies to both DMA and
* PIO transfers */
write32(from_fifo - 1, &spi->regs->dma_blk);
write32(todo - 1, &spi->regs->dma_blk);
setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY);
setbits_le32(&spi->regs->command1, SPI_CMD1_GO);
while ((count = spi_byte_count(spi)) != from_fifo) {
tegra_spi_delay(spi, from_fifo - count);
if (fifo_error(spi))
goto done;
}
received += from_fifo;
while (from_fifo) {
*din = read8(&spi->regs->rx_fifo);
din++;
from_fifo--;
if (dir == SPI_SEND) {
unsigned int to_fifo = bytes;
while (to_fifo) {
write32(*p, &spi->regs->tx_fifo);
p++;
to_fifo--;
}
}
done:
clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN);
if ((received != in_bytes) || fifo_error(spi)) {
printk(BIOS_ERR, "%s: ERROR: Received %u bytes, expected %u\n",
__func__, received, in_bytes);
dump_regs(spi, NULL);
return -1;
}
return in_bytes;
return todo;
}
static int tegra_spi_fifo_send(struct tegra_spi_channel *spi,
const u8 *dout, unsigned int out_bytes)
static void tegra_spi_pio_start(struct tegra_spi_channel *spi)
{
unsigned int sent = 0, remaining = out_bytes;
printk(BIOS_SPEW, "%s: Sending %d bytes\n", __func__, out_bytes);
setbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN);
while (remaining) {
unsigned int to_fifo, tmp;
to_fifo = MIN(out_bytes, SPI_MAX_TRANSFER_BYTES_FIFO);
/* BLOCK_SIZE in SPI_DMA_BLK register applies to both DMA and
* PIO transfers */
write32(to_fifo - 1, &spi->regs->dma_blk);
tmp = to_fifo;
while (tmp) {
write32(*dout, &spi->regs->tx_fifo);
dout++;
tmp--;
}
setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY);
setbits_le32(&spi->regs->command1, SPI_CMD1_GO);
}
static int tegra_spi_pio_finish(struct tegra_spi_channel *spi)
{
u8 *p = spi->in_buf;
clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN | SPI_CMD1_TX_EN);
while (!(read32(&spi->regs->fifo_status) &
SPI_FIFO_STATUS_TX_FIFO_EMPTY)) {
tegra_spi_delay(spi, to_fifo - spi_byte_count(spi));
if (fifo_error(spi))
goto done;
SPI_FIFO_STATUS_RX_FIFO_EMPTY)) {
*p = read8(&spi->regs->rx_fifo);
p++;
}
remaining -= to_fifo;
sent += to_fifo;
}
done:
clrbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN);
if ((sent != out_bytes) || fifo_error(spi)) {
printk(BIOS_ERR, "%s: ERROR: Sent %u bytes, expected "
"to send %u\n", __func__, sent, out_bytes);
dump_regs(spi, NULL);
if (fifo_error(spi)) {
printk(BIOS_ERR, "%s: ERROR:\n", __func__);
dump_spi_regs(spi);
dump_fifo_status(spi);
return -1;
}
return out_bytes;
return 0;
}
static void tegra2_spi_dma_setup(struct apb_dma_channel *dma)
static void setup_dma_params(struct tegra_spi_channel *spi,
struct apb_dma_channel *dma)
{
/* APB bus width = 8-bits, address wrap for each word */
clrbits_le32(&dma->regs->apb_seq, 0x7 << 28);
@ -473,219 +417,365 @@ static void tegra2_spi_dma_setup(struct apb_dma_channel *dma)
setbits_le32(&dma->regs->csr, 1 << 27);
}
static int tegra_spi_dma_prepare(struct tegra_spi_channel *spi,
unsigned int bytes, enum spi_direction dir)
{
unsigned int todo, wcount;
/*
* Notes for DMA transmit and receive, experimentally determined (need to
* verify):
* - WCOUNT seems to be an "n-1" count, but the documentation does not
* make this clear. Without the -1 dma_byte_sta will show 1 AHB word
* (4 bytes) higher than it should and Tx overrun / Rx underrun will
* likely occur.
* For DMA we need to think of things in terms of word count.
* AHB width is fixed at 32-bits. To avoid overrunning
* the in/out buffers we must align down. (Note: lowest 2-bits
* in WCOUNT register are ignored, and WCOUNT seems to count
* words starting at n-1)
*
* - dma_byte_sta is always a multiple 4, so we check for
* dma_byte_sta < length
*
* - The RDY bit in SPI_TRANS_STATUS needs to be cleared manually
* Example: If "bytes" is 7 and we are transferring 1-byte at a time,
* WCOUNT should be 4. The remaining 3 bytes must be transferred
* using PIO.
*/
todo = MIN(bytes, SPI_MAX_TRANSFER_BYTES_DMA - TEGRA_DMA_ALIGN_BYTES);
todo = ALIGN_DOWN(todo, TEGRA_DMA_ALIGN_BYTES);
wcount = ALIGN_DOWN(todo - TEGRA_DMA_ALIGN_BYTES, TEGRA_DMA_ALIGN_BYTES);
if (dir == SPI_SEND) {
spi->dma_out = dma_claim();
if (!spi->dma_out)
return -1;
/* ensure bytes to send will be visible to DMA controller */
dcache_clean_by_mva(spi->out_buf, bytes);
write32((u32)&spi->regs->tx_fifo, &spi->dma_out->regs->apb_ptr);
write32((u32)spi->out_buf, &spi->dma_out->regs->ahb_ptr);
setbits_le32(&spi->dma_out->regs->csr, APBDMACHAN_CSR_DIR);
setup_dma_params(spi, spi->dma_out);
write32(wcount, &spi->dma_out->regs->wcount);
} else {
spi->dma_in = dma_claim();
if (!spi->dma_in)
return -1;
/* avoid data collisions */
dcache_clean_invalidate_by_mva(spi->in_buf, bytes);
write32((u32)&spi->regs->rx_fifo, &spi->dma_in->regs->apb_ptr);
write32((u32)spi->in_buf, &spi->dma_in->regs->ahb_ptr);
clrbits_le32(&spi->dma_in->regs->csr, APBDMACHAN_CSR_DIR);
setup_dma_params(spi, spi->dma_in);
write32(wcount, &spi->dma_in->regs->wcount);
}
/* BLOCK_SIZE starts at n-1 */
write32(todo - 1, &spi->regs->dma_blk);
return todo;
}
static void tegra_spi_dma_start(struct tegra_spi_channel *spi)
{
/*
* The RDY bit in SPI_TRANS_STATUS needs to be cleared manually
* (set bit to clear) between each transaction. Otherwise the next
* transaction does not start.
*/
setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY);
static int tegra_spi_dma_receive(struct tegra_spi_channel *spi,
const void *din, unsigned int in_bytes)
{
struct apb_dma_channel *dma;
dma = dma_claim();
if (!dma) {
printk(BIOS_ERR, "%s: Unable to claim DMA channel\n", __func__);
return -1;
}
printk(BIOS_SPEW, "%s: Receiving %d bytes\n", __func__, in_bytes);
tegra2_spi_dma_setup(dma);
/* set AHB & APB address pointers */
write32((u32)din, &dma->regs->ahb_ptr);
write32((u32)&spi->regs->rx_fifo, &dma->regs->apb_ptr);
if (spi->dma_out)
setbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN);
if (spi->dma_in)
setbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN);
/* FIXME: calculate word count so that it corresponds to bus width */
write32(in_bytes - 1, &dma->regs->wcount);
/* specify BLOCK_SIZE in SPI_DMA_BLK */
write32(in_bytes - 1, &spi->regs->dma_blk);
/* Set DMA direction for APB (SPI) --> AHB (DRAM) */
clrbits_le32(&dma->regs->csr, 1 << 28);
/* write to SPI_TRANS_STATUS RDY bit to clear it */
setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY);
/* set DMA bit in SPI_DMA_CTL to start */
/*
* To avoid underrun conditions, enable APB DMA before SPI DMA for
* Tx and enable SPI DMA before APB DMA before Rx.
*/
if (spi->dma_out)
dma_start(spi->dma_out);
setbits_le32(&spi->regs->dma_ctl, SPI_DMA_CTL_DMA);
if (spi->dma_in)
dma_start(spi->dma_in);
/* start APBDMA after SPI DMA so we don't read empty bytes
* from Rx FIFO */
dma_start(dma);
while (spi_byte_count(spi) != in_bytes)
tegra_spi_delay(spi, in_bytes - spi_byte_count(spi));
clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN);
while ((read32(&dma->regs->dma_byte_sta) < in_bytes) || dma_busy(dma))
; /* this shouldn't take long, no udelay */
dma_stop(dma);
dma_release(dma);
if ((spi_byte_count(spi) != in_bytes) || fifo_error(spi)) {
printk(BIOS_ERR, "%s: ERROR: Received %u bytes, expected %u\n",
__func__, spi_byte_count(spi), in_bytes);
dump_regs(spi, dma);
return -1;
}
return in_bytes;
}
static int tegra_spi_dma_send(struct tegra_spi_channel *spi,
const u8 *dout, unsigned int out_bytes)
static int tegra_spi_dma_finish(struct tegra_spi_channel *spi)
{
struct apb_dma_channel *dma;
unsigned int count;
int ret;
unsigned int todo;
dma = dma_claim();
if (!dma) {
printk(BIOS_ERR, "%s: Unable to claim DMA channel\n", __func__);
return -1;
todo = read32(&spi->dma_in->regs->wcount);
if (spi->dma_in) {
while ((read32(&spi->dma_in->regs->dma_byte_sta) < todo) ||
dma_busy(spi->dma_in))
; /* this shouldn't take long, no udelay */
dma_stop(spi->dma_in);
clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN);
}
printk(BIOS_SPEW, "%s: Sending %d bytes\n", __func__, out_bytes);
tegra2_spi_dma_setup(dma);
/* set AHB & APB address pointers */
write32((u32)dout, &dma->regs->ahb_ptr);
write32((u32)&spi->regs->tx_fifo, &dma->regs->apb_ptr);
setbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN);
/* FIXME: calculate word count so that it corresponds to bus width */
write32(out_bytes - 1, &dma->regs->wcount);
/* specify BLOCK_SIZE in SPI_DMA_BLK */
write32(out_bytes - 1, &spi->regs->dma_blk);
/* Set DMA direction for AHB (DRAM) --> APB (SPI) */
setbits_le32(&dma->regs->csr, (1 << 28));
/* write to SPI_TRANS_STATUS RDY bit to clear it */
setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY);
dma_start(dma);
/* set DMA bit in SPI_DMA_CTL to start */
setbits_le32(&spi->regs->dma_ctl, SPI_DMA_CTL_DMA);
while ((read32(&dma->regs->dma_byte_sta) < out_bytes) || dma_busy(dma))
tegra_spi_delay(spi, out_bytes - spi_byte_count(spi));
dma_stop(dma);
while ((count = spi_byte_count(spi)) != out_bytes)
tegra_spi_delay(spi, out_bytes - count);
if (spi->dma_out) {
while ((read32(&spi->dma_out->regs->dma_byte_sta) < todo) ||
dma_busy(spi->dma_out))
spi_delay(spi, todo - spi_byte_count(spi));
clrbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN);
dma_release(dma);
if ((spi_byte_count(spi) != out_bytes) || fifo_error(spi)) {
printk(BIOS_ERR, "%s: ERROR: Sent %u bytes, expected %u\n",
__func__, spi_byte_count(spi), out_bytes);
dump_regs(spi, dma);
return -1;
dma_stop(spi->dma_out);
}
return out_bytes;
if (fifo_error(spi)) {
printk(BIOS_ERR, "%s: ERROR:\n", __func__);
dump_dma_regs(spi->dma_out);
dump_dma_regs(spi->dma_in);
dump_spi_regs(spi);
dump_fifo_status(spi);
ret = -1;
goto done;
}
int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout,
void *din, unsigned int bitsin)
ret = 0;
done:
spi->dma_in = NULL;
spi->dma_out = NULL;
return ret;
}
/*
* xfer_setup() prepares a transfer. It does sanity checking, alignment, and
* sets transfer mode used by this channel (if not set already).
*
* A few caveats to watch out for:
* - The number of bytes which can be transferred may be smaller than the
* number of bytes the caller specifies. The number of bytes ready for
* a transfer will be returned (unless an error occurs).
*
* - Only one mode can be used for both RX and TX. The transfer mode of the
* SPI channel (spi->xfer_mode) is checked each time this function is called.
* If conflicting modes are detected, spi->xfer_mode will be set to
* XFER_MODE_NONE and an error will be returned.
*
* Returns bytes ready for transfer if successful, <0 to indicate error.
*/
static int xfer_setup(struct tegra_spi_channel *spi, void *buf,
unsigned int bytes, enum spi_direction dir)
{
unsigned int line_size = dcache_line_bytes();
unsigned int align;
int ret = -1;
if (!bytes)
return 0;
if (dir == SPI_SEND)
spi->out_buf = buf;
else if (dir == SPI_RECEIVE)
spi->in_buf = buf;
/*
* Alignment consideratons:
* When we enable caching we'll need to clean/invalidate portions of
* memory. So we need to be careful about memory alignment. Also, DMA
* likes to operate on 4-bytes at a time on the AHB side. So for
* example, if we only want to receive 1 byte, 4 bytes will be be
* written in memory even if those extra 3 bytes are beyond the length
* we want.
*
* For now we'll use PIO to send/receive unaligned bytes. We may
* consider setting aside some space for a kind of bounce buffer to
* stay in DMA mode once we have a chance to benchmark the two
* approaches.
*/
if (bytes < line_size) {
if (spi->xfer_mode == XFER_MODE_DMA) {
spi->xfer_mode = XFER_MODE_NONE;
ret = -1;
} else {
spi->xfer_mode = XFER_MODE_PIO;
ret = tegra_spi_pio_prepare(spi, bytes, dir);
}
goto done;
}
/* transfer bytes before the aligned boundary */
align = line_size - ((uintptr_t)buf % line_size);
if ((align != 0) && (align != line_size)) {
if (spi->xfer_mode == XFER_MODE_DMA) {
spi->xfer_mode = XFER_MODE_NONE;
ret = -1;
} else {
spi->xfer_mode = XFER_MODE_PIO;
ret = tegra_spi_pio_prepare(spi, align, dir);
}
goto done;
}
/* do aligned DMA transfer */
align = (((uintptr_t)buf + bytes) % line_size);
if (bytes - align > 0) {
unsigned int dma_bytes = bytes - align;
if (spi->xfer_mode == XFER_MODE_PIO) {
spi->xfer_mode = XFER_MODE_NONE;
ret = -1;
} else {
spi->xfer_mode = XFER_MODE_DMA;
ret = tegra_spi_dma_prepare(spi, dma_bytes, dir);
}
goto done;
}
/* transfer any remaining unaligned bytes */
if (align) {
if (spi->xfer_mode == XFER_MODE_DMA) {
spi->xfer_mode = XFER_MODE_NONE;
ret = -1;
} else {
spi->xfer_mode = XFER_MODE_PIO;
ret = tegra_spi_pio_prepare(spi, align, dir);
}
goto done;
}
done:
return ret;
}
static void xfer_start(struct tegra_spi_channel *spi)
{
if (spi->xfer_mode == XFER_MODE_DMA)
tegra_spi_dma_start(spi);
else
tegra_spi_pio_start(spi);
}
static void xfer_wait(struct tegra_spi_channel *spi)
{
tegra_spi_wait(spi);
}
static int xfer_finish(struct tegra_spi_channel *spi)
{
int ret;
if (spi->xfer_mode == XFER_MODE_DMA)
ret = tegra_spi_dma_finish(spi);
else
ret = tegra_spi_pio_finish(spi);
spi->xfer_mode = XFER_MODE_NONE;
return ret;
}
int spi_xfer(struct spi_slave *slave, const void *dout,
unsigned int bitsout, void *din, unsigned int bitsin)
{
unsigned int out_bytes = bitsout / 8, in_bytes = bitsin / 8;
struct tegra_spi_channel *spi = to_tegra_spi(slave->bus);
int ret = 0;
u8 *out_buf = (u8 *)dout;
u8 *in_buf = (u8 *)din;
unsigned int todo;
int ret = 0, frame_started = 1;
ASSERT(bitsout % 8 == 0 && bitsin % 8 == 0);
/* tegra bus numbers start at 1 */
ASSERT(slave->bus >= 1 && slave->bus <= ARRAY_SIZE(tegra_spi_channels));
flush_fifos(spi->regs);
if (spi->rx_frame_header_enable) {
memset(in_buf, ~spi->frame_header, in_bytes);
frame_started = 0;
}
while (out_bytes || in_bytes) {
int x = 0;
if (out_bytes == 0)
todo = in_bytes;
else if (in_bytes == 0)
todo = out_bytes;
else
todo = MIN(out_bytes, in_bytes);
if (out_bytes) {
x = xfer_setup(spi, out_buf, todo, SPI_SEND);
if (x < 0) {
if (spi->xfer_mode == XFER_MODE_NONE) {
spi->xfer_mode = XFER_MODE_PIO;
continue;
} else {
ret = -1;
break;
}
}
}
if (in_bytes) {
x = xfer_setup(spi, in_buf, todo, SPI_RECEIVE);
if (x < 0) {
if (spi->xfer_mode == XFER_MODE_NONE) {
spi->xfer_mode = XFER_MODE_PIO;
continue;
} else {
ret = -1;
break;
}
}
}
/*
* DMA operates on 4 bytes at a time, so to avoid accessing memory
* outside the specified buffers we'll only use DMA for 4-byte aligned
* transactions accesses and transfer remaining bytes manually using
* the Rx/Tx FIFOs.
* Note: Some devices (such as Chrome EC) are sensitive to
* delays, so be careful when adding debug prints not to
* cause timeouts between transfers.
*/
while (out_bytes > 0) {
unsigned int dma_out, fifo_out;
dma_out = MIN(out_bytes, SPI_MAX_TRANSFER_BYTES_DMA);
fifo_out = dma_out % TEGRA_DMA_ALIGN_BYTES;
dma_out -= fifo_out;
if (dma_out) {
ret = tegra_spi_dma_send(spi, out_buf, dma_out);
if (ret != dma_out) {
xfer_start(spi);
xfer_wait(spi);
if (xfer_finish(spi)) {
ret = -1;
goto spi_xfer_exit;
break;
}
out_buf += dma_out;
out_bytes -= dma_out;
/*
* Post-processing. For output, we only need to increment
* the buffer and decrement the counter. Same for input if
* there is no frame header to be concerned with.
*
* If a frame header is used and is found, the input buffer
* is shifted so that the header starts at offset 0, and
* in_bytes and in_buf are incremented/decremented according
* to the offset where the header was originally found.
*/
if (out_bytes) {
out_bytes -= x;
out_buf += x;
}
if (fifo_out) {
ret = tegra_spi_fifo_send(spi, out_buf, fifo_out);
if (ret != fifo_out) {
ret = -1;
goto spi_xfer_exit;
}
out_buf += fifo_out;
out_bytes -= fifo_out;
if (in_bytes) {
if (spi->rx_frame_header_enable && !frame_started) {
int i;
for (i = 0; i < x; i++) {
if (in_buf[i] == spi->frame_header) {
frame_started = 1;
i++; /* discard frame header */
break;
}
}
while (in_bytes > 0) {
unsigned int dma_in, fifo_in;
dma_in = MIN(in_bytes, SPI_MAX_TRANSFER_BYTES_DMA);
fifo_in = dma_in % TEGRA_DMA_ALIGN_BYTES;
dma_in -= fifo_in;
if (dma_in) {
ret = tegra_spi_dma_receive(spi, in_buf, dma_in);
if (ret != dma_in) {
ret = -1;
goto spi_xfer_exit;
if (frame_started) {
memmove(&in_buf[0], &in_buf[i], x - i);
in_bytes -= x - i;
in_buf += x - i;
}
in_buf += dma_in;
in_bytes -= dma_in;
} else {
in_bytes -= x;
in_buf += x;
}
if (fifo_in) {
ret = tegra_spi_fifo_receive(spi, in_buf, fifo_in);
if (ret != fifo_in) {
ret = -1;
goto spi_xfer_exit;
}
in_buf += fifo_in;
in_bytes -= fifo_in;
}
}
ret = 0;
spi_xfer_exit:
if (ret < 0)
if (ret < 0) {
printk(BIOS_ERR, "%s: Error detected\n", __func__);
printk(BIOS_ERR, "Transaction size: %u, bytes remaining: "
"%u out / %u in\n", todo, out_bytes, in_bytes);
clear_fifo_status(spi);
}
return ret;
}

View File

@ -17,13 +17,55 @@
#ifndef __NVIDIA_TEGRA124_SPI_H__
#define __NVIDIA_TEGRA124_SPI_H__
#include <spi-generic.h>
#include <stddef.h>
#include "dma.h"
struct tegra_spi_regs {
u32 command1; /* 0x000: SPI_COMMAND1 */
u32 command2; /* 0x004: SPI_COMMAND2 */
u32 timing1; /* 0x008: SPI_CS_TIM1 */
u32 timing2; /* 0x00c: SPI_CS_TIM2 */
u32 trans_status; /* 0x010: SPI_TRANS_STATUS */
u32 fifo_status; /* 0x014: SPI_FIFO_STATUS */
u32 tx_data; /* 0x018: SPI_TX_DATA */
u32 rx_data; /* 0x01c: SPI_RX_DATA */
u32 dma_ctl; /* 0x020: SPI_DMA_CTL */
u32 dma_blk; /* 0x024: SPI_DMA_BLK */
u32 rsvd[56]; /* 0x028-0x107: reserved */
u32 tx_fifo; /* 0x108: SPI_FIFO1 */
u32 rsvd2[31]; /* 0x10c-0x187 reserved */
u32 rx_fifo; /* 0x188: SPI_FIFO2 */
u32 spare_ctl; /* 0x18c: SPI_SPARE_CTRL */
} __attribute__((packed));
enum spi_xfer_mode {
XFER_MODE_NONE = 0,
XFER_MODE_PIO,
XFER_MODE_DMA,
};
struct tegra_spi_channel {
struct spi_slave slave;
struct tegra_spi_regs *regs;
/* stuff that is specific to the attached device */
int rx_frame_header_enable;
u8 frame_header;
/* context (used internally) */
u8 *in_buf, *out_buf;
struct apb_dma_channel *dma_out, *dma_in;
enum spi_xfer_mode xfer_mode;
};
struct cbfs_media;
int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
void *buffer_address,
size_t buffer_size);
void tegra_spi_init(unsigned int bus);
struct tegra_spi_channel *tegra_spi_init(unsigned int bus);
#endif /* __NVIDIA_TEGRA124_SPI_H__ */

View File

@ -0,0 +1,54 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __SOC_NVIDIA_TEGRA124_SYSCTR_H__
#define __SOC_NVIDIA_TEGRA124_SYSCTR_H__
#include <stdint.h>
enum {
SYSCTR_CNTCR_EN = 1 << 0,
SYSCTR_CNTCR_HDBG = 1 << 1,
SYSCTR_CNTCR_FCREQ = 1 << 8
};
struct sysctr_regs {
uint32_t cntcr;
uint32_t cntsr;
uint32_t cntcv0;
uint32_t cntcv1;
uint8_t _rsv0[0x10];
uint32_t cntfid0;
uint32_t cntfid1;
uint8_t _rsv1[0xfa8];
uint32_t counterid4;
uint32_t counterid5;
uint32_t counterid6;
uint32_t counterid7;
uint32_t counterid0;
uint32_t counterid1;
uint32_t counterid2;
uint32_t counterid3;
uint32_t counterid8;
uint32_t counterid9;
uint32_t counterid10;
uint32_t counterid11;
};
#endif /* __SOC_NVIDIA_TEGRA124_SYSCTR_H__ */

View File

@ -0,0 +1,50 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013, Google Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SOC_NVIDIA_TEGRA124_USB_H_
#define __SOC_NVIDIA_TEGRA124_USB_H_
#include <console/console.h>
#include <soc/addressmap.h>
#include <soc/nvidia/tegra/usb.h>
static inline void usb_setup_utmip1(void)
{
struct usb_ctlr *usb = (void *)TEGRA_USBD_BASE;
usb_setup_utmip(usb);
usb_ehci_reset_and_prepare(usb, USB_PHY_UTMIP);
printk(BIOS_DEBUG, "USBD controller set up with UTMI+ PHY\n");
}
static inline void usb_setup_utmip2(void)
{
struct usb_ctlr *usb = (void *)TEGRA_USB2_BASE;
usb_setup_utmip(usb);
usb_ehci_reset_and_prepare(usb, USB_PHY_UTMIP);
printk(BIOS_DEBUG, "USB2 controller set up with UTMI+ PHY\n");
}
static inline void usb_setup_utmip3(void)
{
struct usb_ctlr *usb = (void *)TEGRA_USB3_BASE;
usb_setup_utmip(usb);
usb_ehci_reset_and_prepare(usb, USB_PHY_UTMIP);
printk(BIOS_DEBUG, "USB3 controller set up with UTMI+ PHY\n");
}
#endif /* __SOC_NVIDIA_TEGRA124_USB_H_ */