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:
parent
bca446d471
commit
2fc3b6281f
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
if (soc && 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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 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);
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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[] = {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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__ */
|
|
@ -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(®s->fifo_status, SPI_FIFO_STATUS_RX_FIFO_FLUSH |
|
||||
SPI_FIFO_STATUS_TX_FIFO_FLUSH);
|
||||
while (read32(®s->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(®s->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(®s->command1,
|
||||
clrbits_le32(&spi->regs->command1,
|
||||
SPI_CMD1_BIT_LEN_MASK | SPI_CMD1_PACKED);
|
||||
setbits_le32(®s->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;
|
||||
|
||||
/* BLOCK_SIZE in SPI_DMA_BLK register applies to both DMA and
|
||||
* PIO transfers */
|
||||
write32(from_fifo - 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--;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
udelay(delay_us);
|
||||
}
|
||||
|
||||
static int tegra_spi_fifo_send(struct tegra_spi_channel *spi,
|
||||
const u8 *dout, unsigned int out_bytes)
|
||||
static void tegra_spi_wait(struct tegra_spi_channel *spi)
|
||||
{
|
||||
unsigned int sent = 0, remaining = out_bytes;
|
||||
unsigned int count, dma_blk;
|
||||
|
||||
printk(BIOS_SPEW, "%s: Sending %d bytes\n", __func__, out_bytes);
|
||||
setbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN);
|
||||
dma_blk = 1 + (read32(&spi->regs->dma_blk) &
|
||||
(SPI_DMA_CTL_BLOCK_SIZE_MASK << SPI_DMA_CTL_BLOCK_SIZE_SHIFT));
|
||||
|
||||
while (remaining) {
|
||||
unsigned int to_fifo, tmp;
|
||||
while ((count = spi_byte_count(spi)) != dma_blk)
|
||||
spi_delay(spi, dma_blk - count);
|
||||
}
|
||||
|
||||
to_fifo = MIN(out_bytes, SPI_MAX_TRANSFER_BYTES_FIFO);
|
||||
|
||||
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(to_fifo - 1, &spi->regs->dma_blk);
|
||||
write32(todo - 1, &spi->regs->dma_blk);
|
||||
|
||||
tmp = to_fifo;
|
||||
while (tmp) {
|
||||
write32(*dout, &spi->regs->tx_fifo);
|
||||
dout++;
|
||||
tmp--;
|
||||
if (dir == SPI_SEND) {
|
||||
unsigned int to_fifo = bytes;
|
||||
while (to_fifo) {
|
||||
write32(*p, &spi->regs->tx_fifo);
|
||||
p++;
|
||||
to_fifo--;
|
||||
}
|
||||
}
|
||||
|
||||
return todo;
|
||||
}
|
||||
|
||||
static void tegra_spi_pio_start(struct tegra_spi_channel *spi)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
static int tegra_spi_dma_prepare(struct tegra_spi_channel *spi,
|
||||
unsigned int bytes, enum spi_direction dir)
|
||||
{
|
||||
unsigned int todo, wcount;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
spi->dma_in = NULL;
|
||||
spi->dma_out = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout,
|
||||
void *din, unsigned int bitsin)
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
|
@ -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_ */
|
Loading…
Reference in New Issue