Initial Commit

This commit is contained in:
Niklas080208
2026-01-17 19:39:53 +01:00
commit 75b2b603ab
148 changed files with 45979 additions and 0 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
buy_me_a_coffee: sthetixofficial

22
.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
# Build outputs
build/
output/
release/
# Release zip
*.zip
# DevkitPro / devkitARM
*.a
*.elf
*.o
*.bin
# OS files
.DS_Store
Thumbs.db
.claude
# Version file is tracked, ignore local edits
# VERSION

17
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,17 @@
{
"claudeCode.disableLoginPrompt": false,
"claudeCode.environmentVariables": [
{
"name": "ANTHROPIC_BASE_URL",
"value": "https://api.z.ai/api/anthropic"
},
{
"name": "ANTHROPIC_AUTH_TOKEN",
"value": "caceb12fd1a740c68631842764f1b38a.kBX5z6hfW95z8QHj"
},
{
"name": "CLAUDE_CODE_SKIP_AUTH_LOGIN",
"value": "true"
}
]
}

90
Makefile Normal file
View File

@@ -0,0 +1,90 @@
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/base_rules
################################################################################
IPL_LOAD_ADDR := 0x40008000
VERSION := $(shell cat VERSION)
################################################################################
TARGET := omninx-installer
OUTPUT_NAME := OmniNX-Installer.bin
BUILDDIR := build
OUTPUTDIR := output
SOURCEDIR := source
BDKDIR := bdk
BDKINC := -I./$(BDKDIR)
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
# All source files
OBJS = $(patsubst $(SOURCEDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
$(patsubst $(SOURCEDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \
$(call rwildcard, $(SOURCEDIR), *.S *.c)))
OBJS += $(patsubst $(BDKDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
$(patsubst $(BDKDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \
$(call rwildcard, $(BDKDIR), *.S *.c)))
GFX_INC := '"../$(SOURCEDIR)/gfx.h"'
FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
################################################################################
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
CUSTOMDEFINES += -DVERSION='"$(VERSION)"'
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall -Wno-missing-braces $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
################################################################################
.PHONY: all clean release
all: $(OUTPUTDIR)/$(OUTPUT_NAME)
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(OUTPUT_NAME)))
@echo "Payload size is $(BIN_SIZE) bytes"
@echo "Max size is 126296 bytes."
clean:
@rm -rf $(BUILDDIR)
@rm -rf $(OUTPUTDIR)
@rm -rf release
@rm -f $(TARGET)-*.zip
$(OUTPUTDIR)/$(OUTPUT_NAME): $(BUILDDIR)/$(TARGET)/$(TARGET).elf
@mkdir -p "$(@D)"
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(TARGET).bin
@mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(OUTPUT_NAME)
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.c
@mkdir -p "$(@D)"
$(CC) $(CFLAGS) $(BDKINC) -I$(SOURCEDIR) -c $< -o $@
$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.S
@mkdir -p "$(@D)"
$(CC) $(CFLAGS) -c $< -o $@
$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.c
@mkdir -p "$(@D)"
$(CC) $(CFLAGS) $(BDKINC) -I$(SOURCEDIR) -c $< -o $@
$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.S
@mkdir -p "$(@D)"
$(CC) $(CFLAGS) -c $< -o $@
release: $(OUTPUTDIR)/$(OUTPUT_NAME)
@mkdir -p release/bootloader/payloads
@cp $(OUTPUTDIR)/$(OUTPUT_NAME) release/bootloader/payloads/$(OUTPUT_NAME)
@cd release && zip -r ../$(TARGET)-$(VERSION).zip bootloader
@echo "Release package created: $(TARGET)-$(VERSION).zip"

152
README.md Normal file
View File

@@ -0,0 +1,152 @@
# OmniNX Installer Payload
A minimal payload for installing OmniNX CFW Pack files on Nintendo Switch outside of Horizon OS.
Based on [TegraExplorer](https://github.com/shchmue/TegraExplorer) and [hekate](https://github.com/CTCaer/hekate) by CTCaer, naehrwert, and shchmue.
Based on [HATS-Installer-Payload](https://github.com/sthetix/HATS-Installer-Payload) by sthetix.
## Features
- **Automatic Variant Detection**: Detects which OmniNX pack variant is present (Standard/Light/OC)
- **Smart Installation Modes**:
- **Update Mode**: Selective deletion when OmniNX is already installed
- **Clean Install**: Full wipe with backup/restore of user data (DBI, Tinfoil, prod.keys)
- **Version Detection**: Detects installed OmniNX version via marker files (`1.0.0s`, `1.0.0l`, `1.0.0oc`)
- **Progress Display**: Visual status messages during installation
- **Error Handling**: Detailed error reporting on screen
- **Payload Chaining**: Automatically launch hekate after installation
## Installation Modes
### Update Mode (OmniNX Detected)
- Detected when version marker files (`1.0.0s`, `1.0.0l`, or `1.0.0oc`) are found
- Performs selective deletion of specific directories/files
- Preserves user data, savegames, and installed games
- Updates only necessary CFW components
### Clean Install (No OmniNX Detected)
- Detected when no version marker files are found
- Performs full wipe of `/atmosphere`, `/bootloader`, `/config`, and `/switch`
- **Backs up and restores**:
- `sd:/switch/DBI` → preserved
- `sd:/switch/tinfoil` → preserved
- `sd:/switch/prod.keys` → preserved
- Fresh installation of all CFW components
## Building
### Prerequisites
- **devkitARM** - ARM toolchain for Nintendo Switch development
- **BDK** - Blue Development Kit (included in this repo)
### Build Commands
```bash
make clean
make
```
The built payload will be output to `output/omninx-installer.bin`.
## Usage
### 1. Extract OmniNX Pack to SD Card
Extract the OmniNX pack zip file directly to your SD card. The pack should contain one of:
```
sd:/OmniNX Standard/
├── atmosphere/
├── bootloader/
├── config/
├── switch/
├── TegraExplorer/
├── warmboot_mariko/
├── boot.dat
├── boot.ini
├── exosphere.ini
├── hbmenu.nro
├── loader.bin
├── payload.bin
└── 1.0.0s
```
Or `sd:/OmniNX Light/` or `sd:/OmniNX OC/` for other variants.
**Important**: Extract both the OmniNX pack zip AND this payload to your SD card.
### 2. Launch Payload
Use hekate or another bootloader to launch the payload:
1. Place `omninx-installer.bin` in `sd:/bootloader/payloads/`
2. Launch the payload from hekate's payload menu
3. The payload will automatically:
- Detect which pack variant is present
- Detect if OmniNX is already installed
- Perform appropriate installation (update or clean)
- Launch hekate after completion
### 3. What Happens
1. Payload mounts the SD card
2. Detects current OmniNX installation (if any)
3. Detects which pack variant is on SD card
4. Determines installation mode (update vs clean)
5. Performs cleanup based on mode:
- **Update**: Selective deletion of specific paths
- **Clean**: Full wipe with backup/restore
6. Copies files from pack directory to SD root
7. Creates version marker file
8. Cleans up old version markers
9. Launches hekate (`sd:/bootloader/update.bin`)
## Variant Support
The payload supports three OmniNX variants:
- **Standard** (`1.0.0s`): Full CFW pack
- **Light** (`1.0.0l`): Lightweight CFW pack
- **OC** (`1.0.0oc`): Overclock-enabled CFW pack (includes SaltySD)
The payload automatically detects which variant is present on the SD card and installs accordingly.
## Project Structure
```
OmniNX-Installer-Payload/
├── source/ # Main source code
│ ├── main.c # Entry point and main flow
│ ├── version.c # Version/variant detection
│ ├── version.h
│ ├── install.c # Installation logic
│ ├── install.h
│ ├── backup.c # Backup/restore operations
│ ├── backup.h
│ ├── deletion_lists.h # Arrays of paths to delete
│ ├── fs.c # File system operations
│ ├── fs.h
│ ├── gfx.c # Graphics utilities
│ ├── gfx.h
│ ├── nx_sd.c # SD card operations
│ ├── nx_sd.h
│ ├── link.ld # Linker script
│ └── start.S # Startup assembly
├── bdk/ # Blue Development Kit
├── Makefile # Build configuration
├── VERSION # Version file
└── README.md # This file
```
## License
This project is based on TegraExplorer and hekate. Please refer to those projects for their respective licenses.
## Credits
- **CTCaer** - [hekate](https://github.com/CTCaer/hekate)
- **naehrwert** - Tegra exploration work
- **shchmue** - [TegraExplorer](https://github.com/shchmue/TegraExplorer)
- **sthetix** - [HATS-Installer-Payload](https://github.com/sthetix/HATS-Installer-Payload) (inspiration and base structure)
- **Woody2408** - OmniNX CFW Pack creator

1
VERSION Normal file
View File

@@ -0,0 +1 @@
1.0.0

867
bdk/display/di.c Normal file
View File

@@ -0,0 +1,867 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "di.h"
#include <power/max77620.h>
#include <power/max7762x.h>
#include <mem/heap.h>
#include <soc/clock.h>
#include <soc/fuse.h>
#include <soc/gpio.h>
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/pinmux.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <utils/util.h>
#include "di.inl"
extern volatile nyx_storage_t *nyx_str;
static u32 _display_id = 0;
static bool nx_aula = false;
static void _display_panel_and_hw_end(bool no_panel_deinit);
static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
{
u32 end = get_tmr_us() + timeout;
while (get_tmr_us() < end && DSI(off) & mask)
;
usleep(5);
}
static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait)
{
DSI(_DSIREG(DSI_WR_DATA)) = (param << 8) | cmd;
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
if (wait)
usleep(wait);
}
static void _display_dsi_read_rx_fifo(u32 *data)
{
u32 fifo_count = DSI(_DSIREG(DSI_STATUS)) & DSI_STATUS_RX_FIFO_SIZE;
for (u32 i = 0; i < fifo_count; i++)
{
// Read or Drain RX FIFO.
if (data)
data[i] = DSI(_DSIREG(DSI_RD_DATA));
else
(void)DSI(_DSIREG(DSI_RD_DATA));
}
}
int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
{
int res = 0;
u32 host_control = 0;
u32 cmd_timeout = video_enabled ? 0 : 250000;
u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0};
// Drain RX FIFO.
_display_dsi_read_rx_fifo(NULL);
// Save host control and enable host cmd packets during video.
if (video_enabled)
{
host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
// Enable vblank interrupt.
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = DC_CMD_INT_FRAME_END_INT;
// Use the 4th line to transmit the host cmd packet.
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE | DSI_DSI_LINE_TYPE(4);
// Wait for vblank before starting the transfer.
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
;
}
// Set reply size.
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
_display_dsi_wait(cmd_timeout, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
// Request register read.
_display_dsi_send_cmd(MIPI_DSI_DCS_READ, cmd, 0);
_display_dsi_wait(cmd_timeout, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
// Transfer bus control to device for transmitting the reply.
u32 high_speed = video_enabled ? DSI_HOST_CONTROL_HS : 0;
DSI(_DSIREG(DSI_HOST_CONTROL)) = DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC | high_speed;
_display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA);
// Wait a bit for the reply.
usleep(5000);
// Read RX FIFO.
_display_dsi_read_rx_fifo(fifo);
// Parse packet and copy over the data.
if ((fifo[0] & 0xFF) == DSI_ESCAPE_CMD)
{
// Act based on reply type.
switch (fifo[1] & 0xFF)
{
case GEN_LONG_RD_RES:
case DCS_LONG_RD_RES:
memcpy(data, &fifo[2], MIN((fifo[1] >> 8) & 0xFFFF, len));
break;
case GEN_1_BYTE_SHORT_RD_RES:
case DCS_1_BYTE_SHORT_RD_RES:
memcpy(data, &fifo[2], 1);
break;
case GEN_2_BYTE_SHORT_RD_RES:
case DCS_2_BYTE_SHORT_RD_RES:
memcpy(data, &fifo[2], 2);
break;
case ACK_ERROR_RES:
default:
res = 1;
break;
}
}
else
res = 1;
// Disable host cmd packets during video and restore host control.
if (video_enabled)
{
// Wait for vblank before reseting sync points.
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
;
// Reset all states of syncpt block.
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET;
usleep(300); // Stabilization delay.
// Clear syncpt block reset.
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0;
usleep(300); // Stabilization delay.
// Restore video mode and host control.
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
// Disable and clear vblank interrupt.
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0;
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT;
}
return res;
}
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
{
u8 *fifo8;
u32 *fifo32;
u32 host_control;
// Enable host cmd packets during video and save host control.
if (video_enabled)
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE;
host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
// Enable host transfer trigger.
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control | DSI_HOST_CONTROL_TX_TRIG_HOST;
switch (len)
{
case 0:
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
break;
case 1:
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd | (*(u8 *)data << 8), 0);
break;
default:
fifo32 = calloc(DSI_STATUS_RX_FIFO_SIZE * 8, 4);
fifo8 = (u8 *)fifo32;
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
fifo8[4] = cmd;
memcpy(&fifo8[5], data, len);
len += 4 + 1; // Increase length by CMD/length word and DCS CMD.
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
free(fifo32);
break;
}
// Wait for the write to happen.
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST);
// Disable host cmd packets during video and restore host control.
if (video_enabled)
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
}
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
{
u8 *fifo8;
u32 *fifo32;
// Enable vblank interrupt.
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = DC_CMD_INT_FRAME_END_INT;
// Use the 4th line to transmit the host cmd packet.
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE | DSI_DSI_LINE_TYPE(4);
// Wait for vblank before starting the transfer.
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
;
switch (len)
{
case 0:
DSI(_DSIREG(DSI_WR_DATA)) = (cmd << 8) | MIPI_DSI_DCS_SHORT_WRITE;
break;
case 1:
DSI(_DSIREG(DSI_WR_DATA)) = ((cmd | (*(u8 *)data << 8)) << 8) | MIPI_DSI_DCS_SHORT_WRITE_PARAM;
break;
default:
fifo32 = calloc(DSI_STATUS_RX_FIFO_SIZE * 8, 4);
fifo8 = (u8 *)fifo32;
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
fifo8[4] = cmd;
memcpy(&fifo8[5], data, len);
len += 4 + 1; // Increase length by CMD/length word and DCS CMD.
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
free(fifo32);
break;
}
// Wait for vblank before reseting sync points.
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
;
// Reset all states of syncpt block.
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET;
usleep(300); // Stabilization delay.
// Clear syncpt block reset.
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0;
usleep(300); // Stabilization delay.
// Restore video mode and host control.
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
// Disable and clear vblank interrupt.
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0;
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT;
}
void display_init()
{
// Get Hardware type, as it's used in various DI functions.
nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA;
// Check if display is already initialized.
if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1))
_display_panel_and_hw_end(true);
// Get Chip ID.
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
// T210B01: Power on SD2 regulator for supplying LDO0.
if (!tegra_t210)
{
// Set SD2 regulator voltage.
max7762x_regulator_set_voltage(REGULATOR_SD2, 1325000);
// Set slew rate and enable SD2 regulator.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE);
max7762x_regulator_enable(REGULATOR_SD2, true);
}
// Enable power to display panel controller.
max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000);
max7762x_regulator_enable(REGULATOR_LDO0, true);
if (tegra_t210)
max77620_config_gpio(7, MAX77620_GPIO_OUTPUT_ENABLE); // T210: LD0 -> GPIO7 -> Display panel.
// Enable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_UART_FST_MIPI_CAL);
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = 10; // Set PLLP_OUT3 and div 6 (17MHz).
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP);
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
// Bring every IO rail out of deep power down.
PMC(APBDEV_PMC_IO_DPD_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
PMC(APBDEV_PMC_IO_DPD2_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
// Configure LCD pins.
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; // PULL_DOWN
// Configure Backlight pins.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; // PULL_DOWN | 1
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
if (nx_aula)
{
// Configure LCD RST pin.
gpio_config(GPIO_PORT_V, GPIO_PIN_2, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
}
else
{
// Set LCD +-5V pins mode and direction
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE);
// Enable LCD power.
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // LCD +5V enable.
usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // LCD -5V enable.
usleep(10000);
// Configure Backlight PWM/EN and LCD RST pins (BL PWM, BL EN, LCD RST).
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
// Enable Backlight power.
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH);
}
// Power up supply regulator for display interface.
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0;
if (!tegra_t210)
{
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG0)) = 0;
APB_MISC(APB_MISC_GP_DSI_PAD_CONTROL) = 0;
}
// Set DISP1 clock source and parent clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT.
u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 97.5 MHz (offset).
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
if (tegra_t210)
{
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP.
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2D0AAA; // PLLD_ENABLE_CLK.
}
else
{
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0;
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // PLLD_ENABLE_CLK.
}
// Setup Display Interface initial window configuration.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_dc_setup_win_config, 94);
// Setup display communication interfaces.
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part1, 8);
if (tegra_t210)
DSI(_DSIREG(DSI_INIT_SEQ_DATA_15)) = 0;
else
DSI(_DSIREG(DSI_INIT_SEQ_DATA_15_B01)) = 0;
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part2, 14);
if (!tegra_t210)
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part3_t210b01, 7);
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part4, 10);
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603;
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part5, 12);
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603;
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part6, 14);
usleep(10000);
// Enable LCD Reset.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH);
usleep(60000);
// Setup DSI device takeover timeout.
DSI(_DSIREG(DSI_BTA_TIMING)) = nx_aula ? 0x40103 : 0x50204;
// Get Display ID.
_display_id = 0xCCCCCC;
for (u32 i = 0; i < 3; i++)
{
if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED))
break;
usleep(10000);
}
// Save raw Display ID to Nyx storage.
nyx_str->info.disp_id = _display_id;
// Decode Display ID.
_display_id = ((_display_id >> 8) & 0xFF00) | (_display_id & 0xFF);
if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
_display_id = PANEL_JDI_XXX062M;
// For Aula ensure that we have a compatible panel id.
if (nx_aula && _display_id == 0xCCCC)
_display_id = PANEL_SAM_AMS699VC01;
// Initialize display panel.
switch (_display_id)
{
case PANEL_SAM_AMS699VC01:
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0xA0, 0); // Write 0 to 0xA0.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_SET_CONTROL_DISPLAY | (DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL << 8), 0); // Enable brightness control.
DSI(_DSIREG(DSI_WR_DATA)) = 0x339; // MIPI_DSI_DCS_LONG_WRITE: 3 bytes.
DSI(_DSIREG(DSI_WR_DATA)) = 0x000051; // MIPI_DCS_SET_BRIGHTNESS 0000: 0%. FF07: 100%.
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
usleep(5000);
break;
case PANEL_JDI_XXX062M:
exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43);
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
break;
case PANEL_INL_P062CCA_AZ1:
case PANEL_AUO_A062TAN01:
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
// Unlock extension cmds.
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
usleep(5000);
// Set Power control.
DSI(_DSIREG(DSI_WR_DATA)) = 0x739; // MIPI_DSI_DCS_LONG_WRITE: 7 bytes.
if (_display_id == PANEL_INL_P062CCA_AZ1)
DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
else // PANEL_AUO_A062TAN01.
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
DSI(_DSIREG(DSI_WR_DATA)) = 0x143209; // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32).
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
usleep(5000);
break;
case PANEL_INL_2J055IA_27A:
case PANEL_AUO_A055TAN01:
case PANEL_V40_55_UNK:
default: // Allow spare part displays to work.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 120000);
break;
}
// Unblank display.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
// Configure PLLD for DISP1.
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset, it's ddr btw, so normally div2).
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
if (tegra_t210)
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP.
else
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0;
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN.
// Finalize DSI configuration.
DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0;
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603;
exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 19);
// Set pixel clock dividers: 234 / 3 / 1 = 78 MHz (offset) for 60 Hz.
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3.
exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10);
usleep(10000);
// Calibrate display communication pads.
u32 loops = tegra_t210 ? 1 : 2; // Find out why this is done 2 times on Mariko.
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_pad_cal_config, 4);
for (u32 i = 0; i < loops; i++)
{
// Set MIPI bias pad config.
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0x10010;
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG1)) = tegra_t210 ? 0x300 : 0;
// Set pad trimmers and set MIPI DSI cal offsets.
if (tegra_t210)
{
exec_cfg((u32 *)DSI_BASE, _display_dsi_pad_cal_config_t210, 4);
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_dsi_cal_offsets_config_t210, 4);
}
else
{
exec_cfg((u32 *)DSI_BASE, _display_dsi_pad_cal_config_t210b01, 7);
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_dsi_cal_offsets_config_t210b01, 4);
}
// Set the rest of MIPI cal offsets and apply calibration.
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_apply_dsi_cal_config, 12);
}
usleep(10000);
// Enable video display controller.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_enable_config, 113);
}
void display_backlight_pwm_init()
{
if (_display_id == PANEL_SAM_AMS699VC01)
return;
clock_enable_pwm();
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM. 29.5KHz is stock.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
}
void display_backlight(bool enable)
{
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); // Backlight PWM GPIO.
}
void display_dsi_backlight_brightness(u32 brightness)
{
// Normalize brightness value by 82% and a base of 45 duty.
if (brightness)
brightness = (brightness * PANEL_OLED_BL_COEFF / 100) + PANEL_OLED_BL_OFFSET;
u16 bl_ctrl = byte_swap_16((u16)(brightness * 8));
display_dsi_vblank_write(MIPI_DCS_SET_BRIGHTNESS, 2, &bl_ctrl);
}
void display_pwm_backlight_brightness(u32 brightness, u32 step_delay)
{
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF;
if (brightness == old_value)
return;
if (old_value < brightness)
{
for (u32 i = old_value; i < brightness + 1; i++)
{
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
usleep(step_delay);
}
}
else
{
for (u32 i = old_value; i > brightness; i--)
{
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
usleep(step_delay);
}
}
if (!brightness)
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
}
void display_backlight_brightness(u32 brightness, u32 step_delay)
{
if (brightness > 255)
brightness = 255;
if (_display_id != PANEL_SAM_AMS699VC01)
display_pwm_backlight_brightness(brightness, step_delay);
else
display_dsi_backlight_brightness(brightness);
}
u32 display_get_backlight_brightness()
{
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
}
static void _display_panel_and_hw_end(bool no_panel_deinit)
{
if (no_panel_deinit)
goto skip_panel_deinit;
display_backlight_brightness(0, 1000);
// Enable host cmd packets during video.
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE;
// Blank display.
DSI(_DSIREG(DSI_WR_DATA)) = (MIPI_DCS_SET_DISPLAY_OFF << 8) | MIPI_DSI_DCS_SHORT_WRITE;
// Propagate changes to all register buffers and disable host cmd packets during video.
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
// De-initialize video controller.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_disable_config, 17);
exec_cfg((u32 *)DSI_BASE, _display_dsi_timing_deinit_config, 16);
if (_display_id != PANEL_SAM_AMS699VC01)
usleep(10000);
// De-initialize display panel.
switch (_display_id)
{
case PANEL_JDI_XXX062M:
exec_cfg((u32 *)DSI_BASE, _display_deinit_config_jdi, 22);
break;
case PANEL_AUO_A062TAN01:
exec_cfg((u32 *)DSI_BASE, _display_deinit_config_auo, 37);
break;
case PANEL_INL_2J055IA_27A:
case PANEL_AUO_A055TAN01:
case PANEL_V40_55_UNK:
// Unlock extension cmds.
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
usleep(5000);
// Set Power control.
DSI(_DSIREG(DSI_WR_DATA)) = 0xB39; // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
if (_display_id == PANEL_INL_2J055IA_27A)
DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
else if (_display_id == PANEL_AUO_A055TAN01)
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
else // PANEL_V40_55_UNK.
DSI(_DSIREG(DSI_WR_DATA)) = 0x731348B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT3 / XDK, VRH gamma volt adj 51 / x40).
if (_display_id == PANEL_INL_2J055IA_27A || _display_id == PANEL_AUO_A055TAN01)
{
// (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG).
DSI(_DSIREG(DSI_WR_DATA)) = 0x71143209;
DSI(_DSIREG(DSI_WR_DATA)) = 0x114D31; // (Unknown).
}
else // PANEL_V40_55_UNK.
{
// (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/48, Enter standby / PON / VCOMG).
DSI(_DSIREG(DSI_WR_DATA)) = 0x71243209;
DSI(_DSIREG(DSI_WR_DATA)) = 0x004C31; // (Unknown).
}
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
usleep(5000);
break;
case PANEL_INL_P062CCA_AZ1:
default:
break;
}
// Blank - powerdown.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE,
(_display_id == PANEL_SAM_AMS699VC01) ? 120000 : 50000);
skip_panel_deinit:
// Disable LCD power pins.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); // LCD Reset disable.
if (!nx_aula) // HOS uses panel id.
{
usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD -5V disable.
usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD +5V disable.
usleep(10000);
}
else
usleep(30000); // Aula Panel.
// Disable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
// Power down pads.
DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
// Switch LCD PWM backlight pin to special function mode and enable PWM0 mode.
if (!nx_aula)
{
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode.
}
}
void display_end() { _display_panel_and_hw_end(false); };
u16 display_get_decoded_panel_id()
{
return _display_id;
}
void display_set_decoded_panel_id(u32 id)
{
// Get Hardware type, as it's used in various DI functions.
nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA;
// Decode Display ID.
_display_id = ((id >> 8) & 0xFF00) | (id & 0xFF);
if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
_display_id = PANEL_JDI_XXX062M;
// For Aula ensure that we have a compatible panel id.
if (nx_aula && _display_id == 0xCCCC)
_display_id = PANEL_SAM_AMS699VC01;
}
void display_color_screen(u32 color)
{
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8);
// Configure display to show single color.
DISPLAY_A(_DIREG(DC_WIN_AD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_WIN_BD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ;
usleep(35000); // No need to wait on Aula.
if (_display_id != PANEL_SAM_AMS699VC01)
display_backlight(true);
else
display_backlight_brightness(255, 0);
}
u32 *display_init_framebuffer_pitch()
{
// Sanitize framebuffer area.
memset((u32 *)IPL_FB_ADDRESS, 0, 0x3C0000);
// This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 32);
usleep(35000); // No need to wait on Aula.
return (u32 *)IPL_FB_ADDRESS;
}
u32 *display_init_framebuffer_pitch_inv()
{
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch_inv, 34);
usleep(35000); // No need to wait on Aula.
return (u32 *)NYX_FB_ADDRESS;
}
u32 *display_init_framebuffer_block()
{
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_block, 34);
usleep(35000); // No need to wait on Aula.
return (u32 *)NYX_FB_ADDRESS;
}
u32 *display_init_framebuffer_log()
{
// This configures the framebuffer @ LOG_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_log, 20);
return (u32 *)LOG_FB_ADDRESS;
}
void display_activate_console()
{
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window D.
DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = WIN_ENABLE; // Enable window DD.
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0xFF80;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
for (u32 i = 0xFF80; i < 0x10000; i++)
{
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
usleep(1000);
}
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
}
void display_deactivate_console()
{
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window D.
for (u32 i = 0xFFFF; i > 0xFF7F; i--)
{
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
usleep(500);
}
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0; // Disable window DD.
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
}
void display_init_cursor(void *crs_fb, u32 size)
{
// Setup cursor.
DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10);
DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) =
CURSOR_BLEND_R8G8B8A8 | CURSOR_BLEND_DST_FACTOR(CURSOR_BLEND_K1) | CURSOR_BLEND_SRC_FACTOR(CURSOR_BLEND_K1) | 0xFF;
DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) |= CURSOR_ENABLE;
// Arm and activate changes.
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
}
void display_set_pos_cursor(u32 x, u32 y)
{
DISPLAY_A(_DIREG(DC_DISP_CURSOR_POSITION)) = x | (y << 16);
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
}
void display_deinit_cursor()
{
DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = 0;
DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) &= ~CURSOR_ENABLE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
}

742
bdk/display/di.h Normal file
View File

@@ -0,0 +1,742 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* 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 _DI_H_
#define _DI_H_
#include <memory_map.h>
#include <utils/types.h>
#define DSI_VIDEO_DISABLED 0
#define DSI_VIDEO_ENABLED 1
/*! Display registers. */
#define _DIREG(reg) ((reg) * 4)
// Display controller scratch registers.
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_0 0xED
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_1 0xEE
#define DC_T_WINBUF_TD_SCRATCH_REGISTER_0 0x16D
#define DC_T_WINBUF_TD_SCRATCH_REGISTER_1 0x16E
#define DC_COM_SCRATCH_REGISTER_A 0x325
#define DC_COM_SCRATCH_REGISTER_B 0x326
#define DC_A_WINBUF_AD_SCRATCH_REGISTER_0 0xBED
#define DC_A_WINBUF_AD_SCRATCH_REGISTER_1 0xBEE
#define DC_B_WINBUF_BD_SCRATCH_REGISTER_0 0xDED
#define DC_B_WINBUF_BD_SCRATCH_REGISTER_1 0xDEE
#define DC_C_WINBUF_CD_SCRATCH_REGISTER_0 0xFED
#define DC_C_WINBUF_CD_SCRATCH_REGISTER_1 0xFEE
// DC_CMD non-shadowed command/sync registers.
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
#define SYNCPT_CNTRL_SOFT_RESET BIT(0)
#define SYNCPT_CNTRL_NO_STALL BIT(8)
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
#define SYNCPT_VSYNC_ENABLE BIT(8)
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
#define DC_CMD_DISPLAY_COMMAND 0x32
#define DISP_CTRL_MODE_STOP (0 << 5)
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
#define DISP_CTRL_MODE_MASK (3 << 5)
#define DC_CMD_DISPLAY_POWER_CONTROL 0x36
#define PW0_ENABLE BIT(0)
#define PW1_ENABLE BIT(2)
#define PW2_ENABLE BIT(4)
#define PW3_ENABLE BIT(6)
#define PW4_ENABLE BIT(8)
#define PM0_ENABLE BIT(16)
#define PM1_ENABLE BIT(18)
#define DC_CMD_INT_STATUS 0x37
#define DC_CMD_INT_MASK 0x38
#define DC_CMD_INT_ENABLE 0x39
#define DC_CMD_INT_FRAME_END_INT BIT(1)
#define DC_CMD_STATE_ACCESS 0x40
#define READ_MUX BIT(0)
#define WRITE_MUX BIT(2)
#define DC_CMD_STATE_CONTROL 0x41
#define GENERAL_ACT_REQ BIT(0)
#define WIN_A_ACT_REQ BIT(1)
#define WIN_B_ACT_REQ BIT(2)
#define WIN_C_ACT_REQ BIT(3)
#define WIN_D_ACT_REQ BIT(4)
#define CURSOR_ACT_REQ BIT(7)
#define GENERAL_UPDATE BIT(8)
#define WIN_A_UPDATE BIT(9)
#define WIN_B_UPDATE BIT(10)
#define WIN_C_UPDATE BIT(11)
#define WIN_D_UPDATE BIT(12)
#define CURSOR_UPDATE BIT(15)
#define NC_HOST_TRIG BIT(24)
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
#define WINDOW_A_SELECT BIT(4)
#define WINDOW_B_SELECT BIT(5)
#define WINDOW_C_SELECT BIT(6)
#define WINDOW_D_SELECT BIT(7)
#define DC_CMD_REG_ACT_CONTROL 0x043
// DC_D_WIN_DD window D instance of DC_WIN
#define DC_D_WIN_DD_WIN_OPTIONS 0x80
#define DC_D_WIN_DD_COLOR_DEPTH 0x83
#define DC_D_WIN_DD_POSITION 0x84
#define DC_D_WIN_DD_SIZE 0x85
#define DC_D_WIN_DD_LINE_STRIDE 0x8A
#define DC_D_WIN_DD_BLEND_LAYER_CONTROL 0x96
#define DC_D_WIN_DD_BLEND_MATCH_SELECT 0x97
#define DC_D_WIN_DD_BLEND_ALPHA_1BIT 0x99
// DC_D_WINBUF_DD window D instance of DC_WINBUF
#define DC_D_WINBUF_DD_START_ADDR 0xC0
#define DC_D_WINBUF_DD_ADDR_H_OFFSET 0xC6
#define DC_D_WINBUF_DD_ADDR_V_OFFSET 0xC8
#define DC_D_WINBUF_DD_START_ADDR_HI 0xCD
#define DC_D_WINBUF_DD_MEMFETCH_CONTROL 0xEB
// DC_T_WIN_TD macro for using DD defines.
#define _DC_T(reg) ((reg) + 0x80)
// DC_COM non-shadowed registers.
#define DC_COM_CRC_CONTROL 0x300
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
#define DC_COM_DSC_TOP_CTL 0x33E
// DC_DISP shadowed registers.
#define DC_DISP_DISP_WIN_OPTIONS 0x402
#define CURSOR_ENABLE BIT(16)
#define SOR_ENABLE BIT(25)
#define SOR1_ENABLE BIT(26)
#define SOR1_TIMING_CYA BIT(27)
#define DSI_ENABLE BIT(29)
#define HDMI_ENABLE BIT(30)
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
#define DC_DISP_DISP_TIMING_OPTIONS 0x405
#define DC_DISP_REF_TO_SYNC 0x406
#define DC_DISP_SYNC_WIDTH 0x407
#define DC_DISP_BACK_PORCH 0x408
#define DC_DISP_ACTIVE 0x409
#define DC_DISP_FRONT_PORCH 0x40A
#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F
#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
#define DISP_DATA_FORMAT_DF2S (4 << 0)
#define DISP_DATA_FORMAT_DF3S (5 << 0)
#define DISP_DATA_FORMAT_DFSPI (6 << 0)
#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
#define DISP_ALIGNMENT_MSB (0 << 8)
#define DISP_ALIGNMENT_LSB (1 << 8)
#define DISP_ORDER_RED_BLUE (0 << 9)
#define DISP_ORDER_BLUE_RED (1 << 9)
#define DC_DISP_DISP_COLOR_CONTROL 0x430
#define DITHER_CONTROL_MASK (3 << 8)
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
#define DITHER_CONTROL_ERRDIFF (3 << 8)
#define BASE_COLOR_SIZE_MASK (0xf << 0)
#define BASE_COLOR_SIZE_666 (0 << 0)
#define BASE_COLOR_SIZE_111 (1 << 0)
#define BASE_COLOR_SIZE_222 (2 << 0)
#define BASE_COLOR_SIZE_333 (3 << 0)
#define BASE_COLOR_SIZE_444 (4 << 0)
#define BASE_COLOR_SIZE_555 (5 << 0)
#define BASE_COLOR_SIZE_565 (6 << 0)
#define BASE_COLOR_SIZE_332 (7 << 0)
#define BASE_COLOR_SIZE_888 (8 << 0)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC0_H_QUALIFIER_NONE BIT(0)
#define SC1_H_QUALIFIER_NONE BIT(16)
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
#define DE_SELECT_ACTIVE (1 << 0)
#define DE_SELECT_ACTIVE_IS (2 << 0)
#define DE_CONTROL_ONECLK (0 << 2)
#define DE_CONTROL_NORMAL (1 << 2)
#define DE_CONTROL_EARLY_EXT (2 << 2)
#define DE_CONTROL_EARLY (3 << 2)
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
// Cursor configuration registers.
#define DC_DISP_CURSOR_FOREGROUND 0x43C
#define DC_DISP_CURSOR_BACKGROUND 0x43D
#define CURSOR_COLOR(r,g,b) (((r) & 0xFF) | (((g) & 0xFF) << 8) | (((b) & 0xFF) << 16))
#define DC_DISP_CURSOR_START_ADDR 0x43E
#define CURSOR_CLIPPING(w) ((w) << 28)
#define CURSOR_CLIP_WIN_A 1
#define CURSOR_CLIP_WIN_B 2
#define CURSOR_CLIP_WIN_C 3
#define CURSOR_SIZE_32 (0 << 24)
#define CURSOR_SIZE_64 (1 << 24)
#define CURSOR_SIZE_128 (2 << 24)
#define CURSOR_SIZE_256 (3 << 24)
#define DC_DISP_CURSOR_POSITION 0x440
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_DISP_CURSOR_START_ADDR_HI 0x4EC
#define DC_DISP_BLEND_CURSOR_CONTROL 0x4F1
#define CURSOR_BLEND_2BIT (0 << 24)
#define CURSOR_BLEND_R8G8B8A8 (1 << 24)
#define CURSOR_BLEND_SRC_FACTOR(n) ((n) << 8)
#define CURSOR_BLEND_DST_FACTOR(n) ((n) << 16)
#define CURSOR_BLEND_ZRO 0
#define CURSOR_BLEND_K1 1
#define CURSOR_BLEND_NK1 2
// End of cursor cfg regs.
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
#define DC_DISP_SD_BL_PARAMETERS 0x4D7
#define DC_DISP_SD_BL_CONTROL 0x4DC
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
#define DC_WIN_CSC_YOF 0x611
#define DC_WIN_CSC_KYRGB 0x612
#define DC_WIN_CSC_KUR 0x613
#define DC_WIN_CSC_KVR 0x614
#define DC_WIN_CSC_KUG 0x615
#define DC_WIN_CSC_KVG 0x616
#define DC_WIN_CSC_KUB 0x617
#define DC_WIN_CSC_KVB 0x618
#define DC_WIN_AD_WIN_OPTIONS 0xB80
#define DC_WIN_BD_WIN_OPTIONS 0xD80
#define DC_WIN_CD_WIN_OPTIONS 0xF80
// The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION BIT(0)
#define V_DIRECTION BIT(2)
#define SCAN_COLUMN BIT(4)
#define COLOR_EXPAND BIT(6)
#define CSC_ENABLE BIT(18)
#define WIN_ENABLE BIT(30)
#define DC_WIN_BUFFER_CONTROL 0x702
#define BUFFER_CONTROL_HOST 0
#define BUFFER_CONTROL_VI 1
#define BUFFER_CONTROL_EPP 2
#define BUFFER_CONTROL_MPEGE 3
#define BUFFER_CONTROL_SB2D 4
#define DC_WIN_COLOR_DEPTH 0x703
#define WIN_COLOR_DEPTH_P1 0x0
#define WIN_COLOR_DEPTH_P2 0x1
#define WIN_COLOR_DEPTH_P4 0x2
#define WIN_COLOR_DEPTH_P8 0x3
#define WIN_COLOR_DEPTH_B4G4R4A4 0x4
#define WIN_COLOR_DEPTH_B5G5R5A 0x5
#define WIN_COLOR_DEPTH_B5G6R5 0x6
#define WIN_COLOR_DEPTH_AB5G5R5 0x7
#define WIN_COLOR_DEPTH_B8G8R8A8 0xC
#define WIN_COLOR_DEPTH_R8G8B8A8 0xD
#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE
#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF
#define WIN_COLOR_DEPTH_YCbCr422 0x10
#define WIN_COLOR_DEPTH_YUV422 0x11
#define WIN_COLOR_DEPTH_YCbCr420P 0x12
#define WIN_COLOR_DEPTH_YUV420P 0x13
#define WIN_COLOR_DEPTH_YCbCr422P 0x14
#define WIN_COLOR_DEPTH_YUV422P 0x15
#define WIN_COLOR_DEPTH_YCbCr422R 0x16
#define WIN_COLOR_DEPTH_YUV422R 0x17
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
#define WIN_COLOR_DEPTH_YUV422RA 0x19
#define DC_WIN_POSITION 0x704
#define H_POSITION(x) (((x) & 0xFfff) << 0)
#define V_POSITION(x) (((x) & 0x1fff) << 16)
#define DC_WIN_SIZE 0x705
#define H_SIZE(x) (((x) & 0x1fff) << 0)
#define V_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_PRESCALED_SIZE 0x706
#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_H_INITIAL_DDA 0x707
#define DC_WIN_V_INITIAL_DDA 0x708
#define DC_WIN_DDA_INC 0x709
#define H_DDA_INC(x) (((x) & 0xffff) << 0)
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
#define DC_WIN_LINE_STRIDE 0x70A
#define LINE_STRIDE(x) (x)
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
#define DC_WIN_DV_CONTROL 0x70E
#define DC_WINBUF_BLEND_LAYER_CONTROL 0x716
#define WIN_K1(x) (((x) & 0xff) << 8)
#define WIN_K2(x) (((x) & 0xff) << 16)
#define WIN_BLEND_ENABLE (0 << 24)
#define WIN_BLEND_BYPASS (1 << 24)
#define DC_WINBUF_BLEND_MATCH_SELECT 0x717
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ZERO (0 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ONE (1 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 (2 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_DST (3 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_NEG_K1_TIMES_DST (4 << 0)
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_SRC (5 << 0)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ZERO (0 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ONE (1 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1 (2 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K2 (3 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1_TIMES_DST (4 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_DST (5 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_SRC (6 << 4)
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1 (7 << 4)
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_ZERO (0 << 8)
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K1 (1 << 8)
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 (2 << 8)
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO (0 << 12)
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ONE (1 << 12)
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_NEG_K1_TIMES_SRC (2 << 12)
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_K2 (3 << 12)
#define DC_WINBUF_BLEND_ALPHA_1BIT 0x719
#define WIN_ALPHA_1BIT_WEIGHT0(x) (((x) & 0xff) << 0)
#define WIN_ALPHA_1BIT_WEIGHT1(x) (((x) & 0xff) << 8)
/*! The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
#define DC_WINBUF_START_ADDR 0x800
#define DC_WINBUF_ADDR_H_OFFSET 0x806
#define DC_WINBUF_ADDR_V_OFFSET 0x808
#define DC_WINBUF_SURFACE_KIND 0x80B
#define PITCH (0 << 0)
#define TILED (1 << 0)
#define BLOCK (2 << 0)
#define BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
/*! Display serial interface registers. */
#define _DSIREG(reg) ((reg) * 4)
#define DSI_INCR_SYNCPT_CNTRL 0x1
#define DSI_INCR_SYNCPT_SOFT_RESET BIT(0)
#define DSI_INCR_SYNCPT_NO_STALL BIT(8)
#define DSI_RD_DATA 0x9
#define DSI_WR_DATA 0xA
#define DSI_POWER_CONTROL 0xB
#define DSI_POWER_CONTROL_ENABLE 1
#define DSI_INT_ENABLE 0xC
#define DSI_INT_STATUS 0xD
#define DSI_INT_MASK 0xE
#define DSI_HOST_CONTROL 0xF
#define DSI_HOST_CONTROL_ECC BIT(0)
#define DSI_HOST_CONTROL_CS BIT(1)
#define DSI_HOST_CONTROL_PKT_BTA BIT(2)
#define DSI_HOST_CONTROL_IMM_BTA BIT(3)
#define DSI_HOST_CONTROL_FIFO_SEL BIT(4)
#define DSI_HOST_CONTROL_HS BIT(5)
#define DSI_HOST_CONTROL_RAW BIT(6)
#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
#define DSI_HOST_CONTROL_CRC_RESET BIT(20)
#define DSI_HOST_CONTROL_FIFO_RESET BIT(21)
#define DSI_CONTROL 0x10
#define DSI_CONTROL_HOST_ENABLE BIT(0)
#define DSI_CONTROL_VIDEO_ENABLE BIT(1)
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
#define DSI_CONTROL_DCS_ENABLE BIT(3)
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
#define DSI_CONTROL_HS_CLK_CTRL BIT(20)
#define DSI_SOL_DELAY 0x11
#define DSI_MAX_THRESHOLD 0x12
#define DSI_TRIGGER 0x13
#define DSI_TRIGGER_VIDEO BIT(0)
#define DSI_TRIGGER_HOST BIT(1)
#define DSI_TX_CRC 0x14
#define DSI_STATUS 0x15
#define DSI_STATUS_RX_FIFO_SIZE 0x1F
#define DSI_INIT_SEQ_CONTROL 0x1A
#define DSI_INIT_SEQ_DATA_0 0x1B
#define DSI_INIT_SEQ_DATA_1 0x1C
#define DSI_INIT_SEQ_DATA_2 0x1D
#define DSI_INIT_SEQ_DATA_3 0x1E
#define DSI_PKT_SEQ_0_LO 0x23
#define DSI_PKT_SEQ_0_HI 0x24
#define DSI_PKT_SEQ_1_LO 0x25
#define DSI_PKT_SEQ_1_HI 0x26
#define DSI_PKT_SEQ_2_LO 0x27
#define DSI_PKT_SEQ_2_HI 0x28
#define DSI_PKT_SEQ_3_LO 0x29
#define DSI_PKT_SEQ_3_HI 0x2A
#define DSI_PKT_SEQ_4_LO 0x2B
#define DSI_PKT_SEQ_4_HI 0x2C
#define DSI_PKT_SEQ_5_LO 0x2D
#define DSI_PKT_SEQ_5_HI 0x2E
#define DSI_DCS_CMDS 0x33
#define DSI_PKT_LEN_0_1 0x34
#define DSI_PKT_LEN_2_3 0x35
#define DSI_PKT_LEN_4_5 0x36
#define DSI_PKT_LEN_6_7 0x37
#define DSI_PHY_TIMING_0 0x3C
#define DSI_PHY_TIMING_1 0x3D
#define DSI_PHY_TIMING_2 0x3E
#define DSI_BTA_TIMING 0x3F
#define DSI_TIMEOUT_0 0x44
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_1 0x45
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
#define DSI_TO_TALLY 0x46
#define DSI_PAD_CONTROL_0 0x4B
#define DSI_PAD_CONTROL_VS1_PDIO_CLK BIT(8)
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK BIT(24)
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
#define DSI_PAD_CONTROL_CD 0x4C
#define DSI_VIDEO_MODE_CONTROL 0x4E
#define DSI_CMD_PKT_VID_ENABLE 1
#define DSI_DSI_LINE_TYPE(x) ((x) << 1)
#define DSI_PAD_CONTROL_1 0x4F
#define DSI_PAD_CONTROL_2 0x50
#define DSI_PAD_CONTROL_3 0x51
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
#define DSI_PAD_CONTROL_4 0x52
#define DSI_PAD_CONTROL_5_B01 0x53
#define DSI_PAD_CONTROL_6_B01 0x54
#define DSI_PAD_CONTROL_7_B01 0x55
#define DSI_INIT_SEQ_DATA_15 0x5F
#define DSI_INIT_SEQ_DATA_15_B01 0x62
/*! DSI packet defines */
#define DSI_ESCAPE_CMD 0x87
#define DSI_ACK_NO_ERR 0x84
#define ACK_ERROR_RES 0x02
#define GEN_LONG_RD_RES 0x1A
#define DCS_LONG_RD_RES 0x1C
#define GEN_1_BYTE_SHORT_RD_RES 0x11
#define DCS_1_BYTE_SHORT_RD_RES 0x21
#define GEN_2_BYTE_SHORT_RD_RES 0x12
#define DCS_2_BYTE_SHORT_RD_RES 0x22
/*! MIPI registers. */
#define MIPI_CAL_MIPI_CAL_CTRL (0x00 / 0x4)
#define MIPI_CAL_CIL_MIPI_CAL_STATUS (0x08 / 0x4)
#define MIPI_CAL_CILA_MIPI_CAL_CONFIG (0x14 / 0x4)
#define MIPI_CAL_CILB_MIPI_CAL_CONFIG (0x18 / 0x4)
#define MIPI_CAL_CILC_MIPI_CAL_CONFIG (0x1C / 0x4)
#define MIPI_CAL_CILD_MIPI_CAL_CONFIG (0x20 / 0x4)
#define MIPI_CAL_CILE_MIPI_CAL_CONFIG (0x24 / 0x4)
#define MIPI_CAL_CILF_MIPI_CAL_CONFIG (0x28 / 0x4)
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG (0x38 / 0x4)
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG (0x3C / 0x4)
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG (0x40 / 0x4)
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG (0x44 / 0x4)
#define MIPI_CAL_MIPI_BIAS_PAD_CFG0 (0x58 / 0x4)
#define MIPI_CAL_MIPI_BIAS_PAD_CFG1 (0x5C / 0x4)
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 (0x60 / 0x4)
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2 (0x64 / 0x4)
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2 (0x68 / 0x4)
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2 (0x70 / 0x4)
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG_2 (0x74 / 0x4)
/*! MIPI CMDs. */
#define MIPI_DSI_V_SYNC_START 0x01
#define MIPI_DSI_COLOR_MODE_OFF 0x02
#define MIPI_DSI_END_OF_TRANSMISSION 0x08
#define MIPI_DSI_NULL_PACKET 0x09
#define MIPI_DSI_V_SYNC_END 0x11
#define MIPI_DSI_COLOR_MODE_ON 0x12
#define MIPI_DSI_BLANKING_PACKET 0x19
#define MIPI_DSI_H_SYNC_START 0x21
#define MIPI_DSI_SHUTDOWN_PERIPHERAL 0x22
#define MIPI_DSI_H_SYNC_END 0x31
#define MIPI_DSI_TURN_ON_PERIPHERAL 0x32
#define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37
#define MIPI_DSI_DCS_SHORT_WRITE 0x05
#define MIPI_DSI_DCS_READ 0x06
#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15
#define MIPI_DSI_DCS_LONG_WRITE 0x39
#define MIPI_DSI_GENERIC_LONG_WRITE 0x29
#define MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM 0x03
#define MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM 0x13
#define MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM 0x23
#define MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM 0x04
#define MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM 0x14
#define MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM 0x24
/*! MIPI DCS CMDs. */
#define MIPI_DCS_NOP 0x00
#define MIPI_DCS_SOFT_RESET 0x01
#define MIPI_DCS_GET_COMPRESSION_MODE 0x03
#define MIPI_DCS_GET_DISPLAY_ID 0x04
#define MIPI_DCS_GET_DISPLAY_ID1 0xDA // GET_DISPLAY_ID Byte0, Module Manufacturer ID.
#define MIPI_DCS_GET_DISPLAY_ID2 0xDB // GET_DISPLAY_ID Byte1, Module/Driver Version ID.
#define MIPI_DCS_GET_DISPLAY_ID3 0xDC // GET_DISPLAY_ID Byte2, Module/Driver ID.
#define MIPI_DCS_GET_NUM_ERRORS 0x05 // 1 byte.
#define MIPI_DCS_GET_RED_CHANNEL 0x06
#define MIPI_DCS_GET_GREEN_CHANNEL 0x07
#define MIPI_DCS_GET_BLUE_CHANNEL 0x08
#define MIPI_DCS_GET_DISPLAY_STATUS 0x09 // 4 bytes.
#define MIPI_DCS_GET_POWER_MODE 0x0A // 1 byte. 2: DISON, 3: NORON, 4: SLPOUT, 7: BSTON.
#define MIPI_DCS_GET_ADDRESS_MODE 0x0B // Display Access Control. 1 byte. 0: GS, 1: SS, 3: BGR.
#define MIPI_DCS_GET_PIXEL_FORMAT 0x0C // 1 byte. 4-6: DPI.
#define MIPI_DCS_GET_DISPLAY_MODE 0x0D // 1 byte. 0-2: GCS, 3: ALLPOFF, 4: ALLPON, 5: INVON.
#define MIPI_DCS_GET_SIGNAL_MODE 0x0E // 1 byte. 0: EODSI, 2: DEON, 3: PCLKON, 4: VSON, 5: HSON, 7: TEON.
#define MIPI_DCS_GET_DIAGNOSTIC_RESULT 0x0F // 1 byte. 6: FUNDT, 7: REGLD.
#define MIPI_DCS_ENTER_SLEEP_MODE 0x10
#define MIPI_DCS_EXIT_SLEEP_MODE 0x11
#define MIPI_DCS_ENTER_PARTIAL_MODE 0x12
#define MIPI_DCS_ENTER_NORMAL_MODE 0x13
#define MIPI_DCS_EXIT_INVERT_MODE 0x20
#define MIPI_DCS_ENTER_INVERT_MODE 0x21
#define MIPI_DCS_ALL_PIXELS_OFF 0x22
#define MIPI_DCS_ALL_PIXELS_ON 0x23
#define MIPI_DCS_SET_CONTRAST 0x25 // VCON in 40mV steps. 7-bit integer.
#define MIPI_DCS_SET_GAMMA_CURVE 0x26 // 1 byte. 0-7: GC.
#define MIPI_DCS_SET_DISPLAY_OFF 0x28
#define MIPI_DCS_SET_DISPLAY_ON 0x29
#define MIPI_DCS_SET_COLUMN_ADDRESS 0x2A
#define MIPI_DCS_SET_PAGE_ADDRESS 0x2B
#define MIPI_DCS_WRITE_MEMORY_START 0x2C
#define MIPI_DCS_WRITE_LUT 0x2D // 24-bit: 192 bytes.
#define MIPI_DCS_READ_MEMORY_START 0x2E
#define MIPI_DCS_SET_PARTIAL_ROWS 0x30
#define MIPI_DCS_SET_PARTIAL_COLUMNS 0x31
#define MIPI_DCS_SET_SCROLL_AREA 0x33
#define MIPI_DCS_SET_TEAR_OFF 0x34
#define MIPI_DCS_SET_TEAR_ON 0x35
#define MIPI_DCS_SET_ADDRESS_MODE 0x36 // Display Access Control. 1 byte. 0: GS, 1: SS, 3: BGR.
#define MIPI_DCS_SET_SCROLL_START 0x37
#define MIPI_DCS_EXIT_IDLE_MODE 0x38
#define MIPI_DCS_ENTER_IDLE_MODE 0x39
#define MIPI_DCS_SET_PIXEL_FORMAT 0x3A // 1 byte. 4-6: DPI.
#define MIPI_DCS_WRITE_MEMORY_CONTINUE 0x3C
#define MIPI_DCS_READ_MEMORY_CONTINUE 0x3E
#define MIPI_DCS_GET_3D_CONTROL 0x3F
#define MIPI_DCS_SET_VSYNC_TIMING 0x40
#define MIPI_DCS_SET_TEAR_SCANLINE 0x44
#define MIPI_DCS_GET_SCANLINE 0x45
#define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46
#define MIPI_DCS_GET_SCANLINE_WIDTH 0x47
#define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. 1 byte. 0-7: DBV.
#define MIPI_DCS_GET_BRIGHTNESS 0x52 // 1 byte. 0-7: DBV.
#define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
#define MIPI_DCS_GET_CONTROL_DISPLAY 0x54 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
#define MIPI_DCS_SET_CABC_VALUE 0x55 // 1 byte. 0-32: C, 4-7: C.
#define MIPI_DCS_GET_CABC_VALUE 0x56 // 1 byte. 0-32: C, 4-7: C.
#define MIPI_DCS_SET_CABC_MIN_BRI 0x5E // 1 byte. 0-7: CMB.
#define MIPI_DCS_GET_CABC_MIN_BRI 0x5F // 1 byte. 0-7: CMB.
#define MIPI_DCS_GET_AUTO_BRI_DIAG_RES 0x68 // 1 byte. 6-7: D.
#define MIPI_DCS_READ_DDB_START 0xA1
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
/*! MIPI DCS Panel Private CMDs. */
#define MIPI_DCS_PRIV_UNK_A0 0xA0
#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
#define MIPI_DCS_PRIV_SET_EXTC 0xB9 // Enable extended commands.
#define MIPI_DCS_PRIV_UNK_BD 0xBD
#define MIPI_DCS_PRIV_UNK_D5 0xD5
#define MIPI_DCS_PRIV_UNK_D6 0xD6
#define MIPI_DCS_PRIV_UNK_D8 0xD8
#define MIPI_DCS_PRIV_UNK_D9 0xD9
#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
#define MIPI_DCS_PRIV_SET_EXTC_CMD_REG 0xFF // EXTC Command Set enable register. 5 bytes. Pass: FF 98 06 04, PAGE.
/*! MIPI DCS Panel Private CMDs PAGE 1. */
#define MIPI_DCS_PRIV_GET_DISPLAY_ID4 0x00
#define MIPI_DCS_PRIV_GET_DISPLAY_ID5 0x01
#define MIPI_DCS_PRIV_GET_DISPLAY_ID6 0x02
/*! MIPI DCS CMD Defines. */
#define DCS_POWER_MODE_DISPLAY_ON BIT(2)
#define DCS_POWER_MODE_NORMAL_MODE BIT(3)
#define DCS_POWER_MODE_SLEEP_MODE BIT(4)
#define DCS_POWER_MODE_PARTIAL_MODE BIT(5)
#define DCS_POWER_MODE_IDLE_MODE BIT(6)
#define DCS_ADDRESS_MODE_V_FLIP BIT(0)
#define DCS_ADDRESS_MODE_H_FLIP BIT(1)
#define DCS_ADDRESS_MODE_LATCH_RL BIT(2) // Latch Data Order.
#define DCS_ADDRESS_MODE_BGR_COLOR BIT(3)
#define DCS_ADDRESS_MODE_LINE_ORDER BIT(4) // Line Refresh Order.
#define DCS_ADDRESS_MODE_SWAP_XY BIT(5) // Page/Column Addressing Reverse Order.
#define DCS_ADDRESS_MODE_MIRROR_X BIT(6) // Column Address Order.
#define DCS_ADDRESS_MODE_MIRROR_Y BIT(7) // Page Address Order.
#define DCS_ADDRESS_MODE_ROTATION_MASK (0xF << 4)
#define DCS_ADDRESS_MODE_ROTATION_90 (DCS_ADDRESS_MODE_SWAP_XY | DCS_ADDRESS_MODE_LINE_ORDER)
#define DCS_ADDRESS_MODE_ROTATION_180 (DCS_ADDRESS_MODE_MIRROR_X | DCS_ADDRESS_MODE_LINE_ORDER)
#define DCS_ADDRESS_MODE_ROTATION_270 (DCS_ADDRESS_MODE_SWAP_XY)
#define DCS_GAMMA_CURVE_NONE 0
#define DCS_GAMMA_CURVE_GC0_1_8 BIT(0)
#define DCS_GAMMA_CURVE_GC1_2_5 BIT(1)
#define DCS_GAMMA_CURVE_GC2_1_0 BIT(2)
#define DCS_GAMMA_CURVE_GC3_1_0 BIT(3) // Are there more?
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2)
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3)
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
#define PANEL_OLED_BL_COEFF 82 // 82%.
#define PANEL_OLED_BL_OFFSET 45 // Least legible backlight duty.
/* Switch Panels:
*
* 6.2" panels for Icosa and Iowa skus:
* [10] 81 [26]: JDI LPM062M326A
* [10] 96 [09]: JDI LAM062M109A
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
* [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1)
* [20] 96 [0F]: InnoLux P062CCA-AZ3 [UNCONFIRMED MODEL REV]
* [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV]
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
* [30] XX [0F]: AUO A062TAN03 (59.06A33.003) [UNCONFIRMED ID]
*
* 5.5" panels for Hoag skus:
* [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1)
* [30] 93 [10]: AUO A055TAN01 (59.05A30.001)
* [40] XX [10]: Vendor 40 [UNCONFIRMED ID]
*
* 7.0" OLED panels for Aula skus:
* [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5)
*/
/* Display ID Decoding:
*
* byte0: Vendor
* byte1: Model
* byte2: Board
*
* Vendors:
* 10h: Japan Display Inc.
* 20h: InnoLux Corporation
* 30h: AU Optronics
* 40h: Unknown0
* 50h: Samsung
*
* Boards, Panel Size:
* 0Fh: Icosa/Iowa, 6.2"
* 10h: Hoag, 5.5"
* 20h: Aula, 7.0"
*/
enum
{
PANEL_JDI_XXX062M = 0x10,
PANEL_JDI_LAM062M109A = 0x0910,
PANEL_JDI_LPM062M326A = 0x2610,
PANEL_INL_P062CCA_AZ1 = 0x0F20,
PANEL_AUO_A062TAN01 = 0x0F30,
PANEL_INL_2J055IA_27A = 0x1020,
PANEL_AUO_A055TAN01 = 0x1030,
PANEL_V40_55_UNK = 0x1040,
PANEL_SAM_AMS699VC01 = 0x2050
};
void display_init();
void display_backlight_pwm_init();
void display_end();
/*! Get/Set Display panel ID. */
u16 display_get_decoded_panel_id();
void display_set_decoded_panel_id(u32 id);
/*! Show one single color on the display. */
void display_color_screen(u32 color);
/*! Switches screen backlight ON/OFF. */
void display_backlight(bool enable);
void display_backlight_brightness(u32 brightness, u32 step_delay);
u32 display_get_backlight_brightness();
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
u32 *display_init_framebuffer_pitch();
u32 *display_init_framebuffer_pitch_inv();
u32 *display_init_framebuffer_block();
u32 *display_init_framebuffer_log();
void display_activate_console();
void display_deactivate_console();
void display_init_cursor(void *crs_fb, u32 size);
void display_set_pos_cursor(u32 x, u32 y);
void display_deinit_cursor();
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled);
int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled);
#endif

746
bdk/display/di.inl Normal file
View File

@@ -0,0 +1,746 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* 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/>.
*/
//Display A config.
static const cfg_op_t _display_dc_setup_win_config[94] = {
{DC_CMD_STATE_ACCESS, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_REG_ACT_CONTROL, 0x54}, // Select H counter for win A/B/C.
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_DISP_DC_MCCIF_FIFOCTRL, 0},
{DC_DISP_DISP_MEM_HIGH_PRIORITY, 0},
{DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0},
{DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE},
{DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL},
{DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | 0x9}, // 9: SYNCPT
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_STATE_ACCESS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{DC_WIN_CSC_YOF, 0xF0},
{DC_WIN_CSC_KYRGB, 0x12A},
{DC_WIN_CSC_KUR, 0},
{DC_WIN_CSC_KVR, 0x198},
{DC_WIN_CSC_KUG, 0x39B},
{DC_WIN_CSC_KVG, 0x32F},
{DC_WIN_CSC_KUB, 0x204},
{DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{DC_WIN_CSC_YOF, 0xF0},
{DC_WIN_CSC_KYRGB, 0x12A},
{DC_WIN_CSC_KUR, 0},
{DC_WIN_CSC_KVR, 0x198},
{DC_WIN_CSC_KUG, 0x39B},
{DC_WIN_CSC_KVG, 0x32F},
{DC_WIN_CSC_KUB, 0x204},
{DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{DC_WIN_CSC_YOF, 0xF0},
{DC_WIN_CSC_KYRGB, 0x12A},
{DC_WIN_CSC_KUR, 0},
{DC_WIN_CSC_KVR, 0x198},
{DC_WIN_CSC_KUG, 0x39B},
{DC_WIN_CSC_KVG, 0x32F},
{DC_WIN_CSC_KUB, 0x204},
{DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{DC_DISP_BLEND_BACKGROUND_COLOR, 0},
{DC_COM_CRC_CONTROL, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}
};
//DSI Init config.
static const cfg_op_t _display_dsi_init_config_part1[8] = {
{DSI_WR_DATA, 0},
{DSI_INT_ENABLE, 0},
{DSI_INT_STATUS, 0},
{DSI_INT_MASK, 0},
{DSI_INIT_SEQ_DATA_0, 0},
{DSI_INIT_SEQ_DATA_1, 0},
{DSI_INIT_SEQ_DATA_2, 0},
{DSI_INIT_SEQ_DATA_3, 0}
};
static const cfg_op_t _display_dsi_init_config_part2[14] = {
{DSI_DCS_CMDS, 0},
{DSI_PKT_SEQ_0_LO, 0},
{DSI_PKT_SEQ_1_LO, 0},
{DSI_PKT_SEQ_2_LO, 0},
{DSI_PKT_SEQ_3_LO, 0},
{DSI_PKT_SEQ_4_LO, 0},
{DSI_PKT_SEQ_5_LO, 0},
{DSI_PKT_SEQ_0_HI, 0},
{DSI_PKT_SEQ_1_HI, 0},
{DSI_PKT_SEQ_2_HI, 0},
{DSI_PKT_SEQ_3_HI, 0},
{DSI_PKT_SEQ_4_HI, 0},
{DSI_PKT_SEQ_5_HI, 0},
{DSI_CONTROL, 0}
};
static const cfg_op_t _display_dsi_init_config_part3_t210b01[7] = {
{DSI_PAD_CONTROL_1, 0},
{DSI_PAD_CONTROL_2, 0},
{DSI_PAD_CONTROL_3, 0},
{DSI_PAD_CONTROL_4, 0},
{DSI_PAD_CONTROL_5_B01, 0},
{DSI_PAD_CONTROL_6_B01, 0},
{DSI_PAD_CONTROL_7_B01, 0}
};
static const cfg_op_t _display_dsi_init_config_part4[10] = {
{DSI_PAD_CONTROL_CD, 0},
{DSI_SOL_DELAY, 0x18},
{DSI_MAX_THRESHOLD, 0x1E0},
{DSI_TRIGGER, 0},
{DSI_INIT_SEQ_CONTROL, 0},
{DSI_PKT_LEN_0_1, 0},
{DSI_PKT_LEN_2_3, 0},
{DSI_PKT_LEN_4_5, 0},
{DSI_PKT_LEN_6_7, 0},
{DSI_PAD_CONTROL_1, 0}
};
static const cfg_op_t _display_dsi_init_config_part5[12] = {
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30109},
{DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0},
{DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Enable
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_POWER_CONTROL, 0},
{DSI_POWER_CONTROL, 0},
{DSI_PAD_CONTROL_1, 0}
};
static const cfg_op_t _display_dsi_init_config_part6[14] = {
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30118},
{DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_MAX_THRESHOLD, 0x40},
{DSI_TRIGGER, 0},
{DSI_TX_CRC, 0},
{DSI_INIT_SEQ_CONTROL, 0}
};
//DSI panel config.
static const cfg_op_t _display_init_config_jdi[43] = {
{DSI_WR_DATA, 0x0439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
{DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0xBD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD.
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x1939}, // MIPI_DSI_DCS_LONG_WRITE: 25 bytes.
{DSI_WR_DATA, 0xAAAAAAD8}, // Register: 0xD8.
{DSI_WR_DATA, 0xAAAAAAEB},
{DSI_WR_DATA, 0xAAEBAAAA},
{DSI_WR_DATA, 0xAAAAAAAA},
{DSI_WR_DATA, 0xAAAAAAEB},
{DSI_WR_DATA, 0xAAEBAAAA},
{DSI_WR_DATA, 0xAA},
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x01BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 1 to 0xBD.
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x2739}, // MIPI_DSI_DCS_LONG_WRITE: 39 bytes.
{DSI_WR_DATA, 0xFFFFFFD8}, // Register: 0xD8.
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFF},
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x02BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 2 to 0xBD.
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0xF39}, // MIPI_DSI_DCS_LONG_WRITE: 15 bytes.
{DSI_WR_DATA, 0xFFFFFFD8}, // Register: 0xD8.
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFFFF},
{DSI_WR_DATA, 0xFFFFFF},
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD.
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x06D915}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 6 to 0xD9.
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
{DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable.
{DSI_TRIGGER, DSI_TRIGGER_HOST}
};
//DSI packet config.
static const cfg_op_t _display_dsi_packet_config[19] = {
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30172},
{DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0},
{DSI_PKT_SEQ_0_LO, 0x40000208},
{DSI_PKT_SEQ_2_LO, 0x40000308},
{DSI_PKT_SEQ_4_LO, 0x40000308},
{DSI_PKT_SEQ_1_LO, 0x40000308},
{DSI_PKT_SEQ_3_LO, 0x3F3B2B08},
{DSI_PKT_SEQ_3_HI, 0x2CC},
{DSI_PKT_SEQ_5_LO, 0x3F3B2B08},
{DSI_PKT_SEQ_5_HI, 0x2CC},
{DSI_PKT_LEN_0_1, 0xCE0000},
{DSI_PKT_LEN_2_3, 0x87001A2},
{DSI_PKT_LEN_4_5, 0x190},
{DSI_PKT_LEN_6_7, 0x190},
{DSI_HOST_CONTROL, 0}
};
//DSI mode config.
static const cfg_op_t _display_dsi_mode_config[10] = {
{DSI_TRIGGER, 0},
{DSI_CONTROL, 0},
{DSI_SOL_DELAY, 6},
{DSI_MAX_THRESHOLD, 0x1E0},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL| DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}
};
//MIPI CAL config.
static const cfg_op_t _display_mipi_pad_cal_config[4] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
{MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
{MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0},
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0}
};
//DSI config.
static const cfg_op_t _display_dsi_pad_cal_config_t210[4] = {
{DSI_PAD_CONTROL_1, 0},
{DSI_PAD_CONTROL_2, 0},
{DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)},
{DSI_PAD_CONTROL_4, 0}
};
static const cfg_op_t _display_dsi_pad_cal_config_t210b01[7] = {
{DSI_PAD_CONTROL_1, 0},
{DSI_PAD_CONTROL_2, 0},
{DSI_PAD_CONTROL_3, 0},
{DSI_PAD_CONTROL_4, 0x77777},
{DSI_PAD_CONTROL_5_B01, 0x77777},
{DSI_PAD_CONTROL_6_B01, 0x1111},
{DSI_PAD_CONTROL_7_B01, 0}
};
//MIPI CAL config.
static const cfg_op_t _display_mipi_dsi_cal_offsets_config_t210[4] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002}
};
static const cfg_op_t _display_mipi_dsi_cal_offsets_config_t210b01[4] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000}
};
static const cfg_op_t _display_mipi_apply_dsi_cal_config[12] = {
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILD_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILE_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILF_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001}
};
//Display A config.
static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
{DC_CMD_STATE_ACCESS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{DC_WIN_CSC_YOF, 0xF0},
{DC_WIN_CSC_KYRGB, 0x12A},
{DC_WIN_CSC_KUR, 0},
{DC_WIN_CSC_KVR, 0x198},
{DC_WIN_CSC_KUG, 0x39B},
{DC_WIN_CSC_KVG, 0x32F},
{DC_WIN_CSC_KUB, 0x204},
{DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{DC_WIN_CSC_YOF, 0xF0},
{DC_WIN_CSC_KYRGB, 0x12A},
{DC_WIN_CSC_KUR, 0},
{DC_WIN_CSC_KVR, 0x198},
{DC_WIN_CSC_KUG, 0x39B},
{DC_WIN_CSC_KVG, 0x32F},
{DC_WIN_CSC_KUB, 0x204},
{DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
/* Setup default YUV colorspace conversion coefficients */
{DC_WIN_CSC_YOF, 0xF0},
{DC_WIN_CSC_KYRGB, 0x12A},
{DC_WIN_CSC_KUR, 0},
{DC_WIN_CSC_KVR, 0x198},
{DC_WIN_CSC_KUG, 0x39B},
{DC_WIN_CSC_KVG, 0x32F},
{DC_WIN_CSC_KUB, 0x204},
{DC_WIN_CSC_KVB, 0},
/* End of color coefficients */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{DC_DISP_BLEND_BACKGROUND_COLOR, 0},
{DC_COM_CRC_CONTROL, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_STATE_ACCESS, 0},
/* Set Display timings
*
* DC_DISP_REF_TO_SYNC:
* V_REF_TO_SYNC - 1
* H_REF_TO_SYNC - 0
*
* DC_DISP_SYNC_WIDTH:
* V_SYNC_WIDTH - 1
* H_SYNC_WIDTH - 72
*
* DC_DISP_BACK_PORCH:
* V_BACK_PORCH - 9
* H_BACK_PORCH - 72
*
* DC_DISP_ACTIVE:
* V_DISP_ACTIVE - 1280
* H_DISP_ACTIVE - 720
*
* DC_DISP_FRONT_PORCH:
* V_FRONT_PORCH - 10
* H_FRONT_PORCH - 136
*/
{DC_DISP_DISP_TIMING_OPTIONS, 0},
{DC_DISP_REF_TO_SYNC, 0x10000},
{DC_DISP_SYNC_WIDTH, 0x10048},
{DC_DISP_BACK_PORCH, 0x90048},
{DC_DISP_ACTIVE, 0x50002D0},
{DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should happen before DC_DISP_ACTIVE cmd.
/* End of Display timings */
{DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE},
{DC_COM_PIN_OUTPUT_ENABLE(1), 0},
{DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL},
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_DISP_DISP_CLOCK_CONTROL, 0},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX},
{DC_DISP_FRONT_PORCH, 0xA0088},
{DC_CMD_STATE_ACCESS, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_STATE_ACCESS, 0},
{DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)},
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0}
};
////Display A config.
static const cfg_op_t _display_video_disp_controller_disable_config[17] = {
{DC_DISP_FRONT_PORCH, 0xA0088},
{DC_CMD_INT_MASK, 0},
{DC_CMD_STATE_ACCESS, 0},
{DC_CMD_INT_ENABLE, 0},
{DC_CMD_CONT_SYNCPT_VSYNC, 0},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_DISPLAY_POWER_CONTROL, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
};
//DSI config.
static const cfg_op_t _display_dsi_timing_deinit_config[16] = {
{DSI_POWER_CONTROL, 0},
{DSI_PAD_CONTROL_1, 0},
{DSI_PHY_TIMING_0, 0x6070601},
{DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30118},
{DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_MAX_THRESHOLD, 0x40},
{DSI_TRIGGER, 0},
{DSI_TX_CRC, 0},
{DSI_INIT_SEQ_CONTROL, 0}
};
//DSI config (if ver == 0x10).
static const cfg_op_t _display_deinit_config_jdi[22] = {
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
{DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x2139}, // MIPI_DSI_DCS_LONG_WRITE: 33 bytes.
{DSI_WR_DATA, 0x191919D5}, // Register: 0xD5.
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19},
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
{DSI_WR_DATA, 0x4F0F41B1}, // MIPI_DCS_PRIV_SET_POWER_CONTROL.
{DSI_WR_DATA, 0xF179A433},
{DSI_WR_DATA, 0x002D81},
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
{DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable.
{DSI_TRIGGER, DSI_TRIGGER_HOST}
};
static const cfg_op_t _display_deinit_config_auo[37] = {
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
{DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
{DSI_WR_DATA, 0x191919D5}, // Register: 0xD5.
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
{DSI_WR_DATA, 0x191919D6}, // Register: 0xD6.
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_WR_DATA, 0x19191919},
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
{DSI_WR_DATA, 0x711148B1}, // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
// (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG).
{DSI_WR_DATA, 0x71143209},
{DSI_WR_DATA, 0x114D31}, // (Unknown).
{DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
{DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable.
{DSI_TRIGGER, DSI_TRIGGER_HOST}
};
static const cfg_op_t _display_init_config_invert[3] = {
{DSI_WR_DATA, 0x239},
{DSI_WR_DATA, 0x02C1}, // INV_EN.
{DSI_TRIGGER, DSI_TRIGGER_HOST},
};
//Display A config.
static const cfg_op_t cfg_display_one_color[8] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display.
};
//Display A config linear pitch.
static const cfg_op_t cfg_display_framebuffer_pitch[32] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, PITCH},
{DC_WINBUF_START_ADDR, IPL_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0},
{DC_WINBUF_ADDR_V_OFFSET, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD.
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
};
//Display A config linear pitch inverse + Win D support.
static const cfg_op_t cfg_display_framebuffer_pitch_inv[34] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, PITCH},
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0}, // Linear: 0x383FFC, Block: 0x3813FC.
{DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0.
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD.
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
};
//Display A config block linear.
static const cfg_op_t cfg_display_framebuffer_block[34] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK},
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC.
{DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0.
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | SCAN_COLUMN | H_DIRECTION}, // Enable window AD. | SCAN_COLUMN | H_DIRECTION.
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
};
//Display D config.
static const cfg_op_t cfg_display_framebuffer_log[20] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8},
{DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, PITCH},
{DC_WINBUF_START_ADDR, LOG_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0},
{DC_WINBUF_ADDR_V_OFFSET, 0},
{DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200)},
{DC_WINBUF_BLEND_MATCH_SELECT, WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 | WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1},
{DC_WIN_WIN_OPTIONS, 0}, // Enable window DD.
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ}
};

233
bdk/exception_handlers.S Normal file
View File

@@ -0,0 +1,233 @@
/*
* Copyright (c) 2019 CTCaer
*
* 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/>.
*/
/*
* Armv7tdmi Status register.
*
* bit0: Mode 0.
* bit1: Mode 1.
* bit2: Mode 2.
* bit3: Mode 3.
* bit4: Mode 4.
* bit5: Thumb state.
* bit6: FIQ disable.
* bit7: IRQ disable.
* bit8-27: Reserved.
* bit28: Overflow condition.
* bit29: Carry/Borrow/Extend condition.
* bit30: Zero condition.
* bit31: Negative/Less than condition.
*
* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers
* 10000 | USER | r0r7, SP, LR, PC, CPSR | r0r14, PC, CPSR
* 10001 | FIQ | r0r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0r7, r8_fiqr14_fiq, PC, CPSR, SPSR_fiq
* 10010 | IRQ | r0r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
* 10011 | SVC | r0r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
* 10111 | ABRT | r0r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
* 11011 | UNDF | r0r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0r12, r13_und, r14_und, PC, CPSR, SPSR_und
* 11111 | SYS | r0r7, SP, LR, PC, CPSR | r0r14, PC, CPSR
*/
#define EXCP_EN_ADDR 0x4003FFFC
#define EXCP_TYPE_ADDR 0x4003FFF8
#define EXCP_LR_ADDR 0x4003FFF4
#define EXCP_VEC_BASE 0x6000F000
#define EVP_COP_RESET_VECTOR 0x200
#define EVP_COP_UNDEF_VECTOR 0x204
#define EVP_COP_SWI_VECTOR 0x208
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
#define EVP_COP_DATA_ABORT_VECTOR 0x210
#define EVP_COP_RSVD_VECTOR 0x214
#define EVP_COP_IRQ_VECTOR 0x218
#define EVP_COP_FIQ_VECTOR 0x21C
#define MODE_USR 0x10
#define MODE_FIQ 0x11
#define MODE_IRQ 0x12
#define MODE_SVC 0x13
#define MODE_ABT 0x17
#define MODE_UDF 0x1B
#define MODE_SYS 0x1F
#define MODE_MASK 0x1F
#define FIQ 0x40
#define IRQ 0x80
.section .text._irq_setup
.arm
.extern ipl_main
.type ipl_main, %function
.extern svc_handler
.type svc_handler, %function
.extern irq_handler
.type irq_handler, %function
.extern fiq_setup
.type fiq_setup, %function
.extern fiq_handler
.type fiq_handler, %function
.globl _irq_setup
.type _irq_setup, %function
_irq_setup:
MRS R0, CPSR
BIC R0, R0, #MODE_MASK /* Clear mode bits */
ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */
MSR CPSR, R0
/* Setup IRQ stack pointer */
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
LDR SP, =0x40040000
/* Setup SYS stack pointer */
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
MOV LR, PC
BL setup_vectors
/*BL fiq_setup*/
/* Enable interrupts */
BL irq_enable_cpu_irq_exceptions
B ipl_main
B .
_reset:
LDR R0, =EXCP_EN_ADDR
LDR R1, =0x30505645 /* EVP0 */
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
LDR R0, =EXCP_LR_ADDR
MOV R1, LR
STR R1, [R0] /* Save LR in EXCP_LR_ADDR */
LDR R0, =__bss_start
EOR R1, R1, R1
LDR R2, =__bss_end
SUB R2, R2, R0
BL memset
B _irq_setup
_reset_handler:
LDR R0, =EXCP_TYPE_ADDR
LDR R1, =0x545352 /* RST */
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
B _reset
_undefined_handler:
LDR R0, =EXCP_TYPE_ADDR
LDR R1, =0x464455 /* UDF */
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
B _reset
_prefetch_abort_handler:
LDR R0, =EXCP_TYPE_ADDR
LDR R1, =0x54424150 /* PABT */
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
B _reset
_data_abort_handler:
LDR R0, =EXCP_TYPE_ADDR
LDR R1, =0x54424144 /* DABT */
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
B _reset
.globl irq_enable_cpu_irq_exceptions
.type irq_enable_cpu_irq_exceptions, %function
irq_enable_cpu_irq_exceptions:
MRS R12, CPSR
BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */
MSR CPSR, R12
BX LR
.globl irq_disable_cpu_irq_exceptions
.type irq_disable_cpu_irq_exceptions, %function
irq_disable_cpu_irq_exceptions:
MRS R12, CPSR
ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */
MSR CPSR, R12
BX LR
_irq_handler:
MOV R13, R0 /* Save R0 in R13_IRQ */
SUB R0, LR, #4 /* Put return address in R0_SYS */
MOV LR, R1 /* Save R1 in R14_IRQ (LR) */
MRS R1, SPSR /* Put the SPSR in R1_SYS */
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
STMFD SP!, {R0, R1} /* SPSR and PC */
STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
SUB SP, SP, #8 /* Make room for stacking R0 and R1 */
MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */
STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
LDR R12, =irq_handler
MOV LR, PC /* Copy the return address to link register */
BX R12 /* Call the C IRQ handler (ARM/THUMB) */
MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */
MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
MOV SP, R0 /* Copy SP_SYS to SP_IRQ */
LDR R0, [SP, #28] /* Load the saved SPSR from the stack */
MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */
LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */
NOP /* Cant access barked registers immediately */
LDR LR, [SP, #24] /* Load return address from the SYS stack */
MOVS PC, LR /* Return restoring CPSR from SPSR */
_fiq_handler:
BL fiq_handler
setup_vectors:
/* Setup vectors */
LDR R0, =EXCP_VEC_BASE
LDR R1, =_reset_handler
STR R1, [R0, #EVP_COP_RESET_VECTOR]
LDR R1, =_undefined_handler
STR R1, [R0, #EVP_COP_UNDEF_VECTOR]
LDR R1, =_reset_handler
STR R1, [R0, #EVP_COP_SWI_VECTOR]
LDR R1, =_prefetch_abort_handler
STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]
LDR R1, =_data_abort_handler
STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]
LDR R1, =_reset_handler
STR R1, [R0, #EVP_COP_RSVD_VECTOR]
LDR R1, =_irq_handler
STR R1, [R0, #EVP_COP_IRQ_VECTOR]
LDR R1, =_fiq_handler
STR R1, [R0, #EVP_COP_FIQ_VECTOR]
BX LR

24
bdk/fatfs_cfg.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2020 CTCaer
*
* 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 _FATFS_CFG_H_
#define _FATFS_CFG_H_
#ifdef FFCFG_INC
#include FFCFG_INC
#endif
#endif

24
bdk/gfx_utils.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2020 CTCaer
*
* 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 _GFX_UTILS_H_
#define _GFX_UTILS_H_
#ifdef GFX_INC
#include GFX_INC
#endif
#endif

589
bdk/ianos/elfload/elf.h Normal file
View File

@@ -0,0 +1,589 @@
/* $OpenBSD: exec_elf.h,v 1.53 2014/01/03 03:00:39 guenther Exp $ */
/*
* Copyright (c) 1995, 1996 Erik Theisen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* imported sys/exec_elf.h from OpenBSD */
#ifndef ELF_H
#define ELF_H
#include <stdint.h>
typedef uint8_t Elf_Byte;
typedef uint32_t Elf32_Addr; /* Unsigned program address */
typedef uint32_t Elf32_Off; /* Unsigned file offset */
typedef int32_t Elf32_Sword; /* Signed large integer */
typedef uint32_t Elf32_Word; /* Unsigned large integer */
typedef uint16_t Elf32_Half; /* Unsigned medium integer */
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
typedef int32_t Elf64_Shalf;
#ifdef __alpha__
typedef int64_t Elf64_Sword;
typedef uint64_t Elf64_Word;
#else
typedef int32_t Elf64_Sword;
typedef uint32_t Elf64_Word;
#endif
typedef int64_t Elf64_Sxword;
typedef uint64_t Elf64_Xword;
typedef uint32_t Elf64_Half;
typedef uint16_t Elf64_Quarter;
/*
* e_ident[] identification indexes
* See http://www.sco.com/developers/gabi/latest/ch4.eheader.html
*/
#define EI_MAG0 0 /* file ID */
#define EI_MAG1 1 /* file ID */
#define EI_MAG2 2 /* file ID */
#define EI_MAG3 3 /* file ID */
#define EI_CLASS 4 /* file class */
#define EI_DATA 5 /* data encoding */
#define EI_VERSION 6 /* ELF header version */
#define EI_OSABI 7 /* OS/ABI ID */
#define EI_ABIVERSION 8 /* ABI version */
#define EI_PAD 9 /* start of pad bytes */
#define EI_NIDENT 16 /* Size of e_ident[] */
/* e_ident[] magic number */
#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
#define ELFMAG "\177ELF" /* magic */
#define SELFMAG 4 /* size of magic */
/* e_ident[] file class */
#define ELFCLASSNONE 0 /* invalid */
#define ELFCLASS32 1 /* 32-bit objs */
#define ELFCLASS64 2 /* 64-bit objs */
#define ELFCLASSNUM 3 /* number of classes */
/* e_ident[] data encoding */
#define ELFDATANONE 0 /* invalid */
#define ELFDATA2LSB 1 /* Little-Endian */
#define ELFDATA2MSB 2 /* Big-Endian */
#define ELFDATANUM 3 /* number of data encode defines */
/* e_ident[] Operating System/ABI */
#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
#define ELFOSABI_HPUX 1 /* HP-UX operating system */
#define ELFOSABI_NETBSD 2 /* NetBSD */
#define ELFOSABI_LINUX 3 /* GNU/Linux */
#define ELFOSABI_HURD 4 /* GNU/Hurd */
#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
#define ELFOSABI_SOLARIS 6 /* Solaris */
#define ELFOSABI_MONTEREY 7 /* Monterey */
#define ELFOSABI_IRIX 8 /* IRIX */
#define ELFOSABI_FREEBSD 9 /* FreeBSD */
#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
#define ELFOSABI_MODESTO 11 /* Novell Modesto */
#define ELFOSABI_OPENBSD 12 /* OpenBSD */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
/* e_ident */
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
(ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
(ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
(ehdr).e_ident[EI_MAG3] == ELFMAG3)
/* ELF Header */
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
Elf32_Half e_type; /* object file type */
Elf32_Half e_machine; /* machine */
Elf32_Word e_version; /* object file version */
Elf32_Addr e_entry; /* virtual entry point */
Elf32_Off e_phoff; /* program header table offset */
Elf32_Off e_shoff; /* section header table offset */
Elf32_Word e_flags; /* processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size */
Elf32_Half e_phentsize; /* program header entry size */
Elf32_Half e_phnum; /* number of program header entries */
Elf32_Half e_shentsize; /* section header entry size */
Elf32_Half e_shnum; /* number of section header entries */
Elf32_Half e_shstrndx; /* section header table's "section
header string table" entry offset */
} Elf32_Ehdr;
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Id bytes */
Elf64_Quarter e_type; /* file type */
Elf64_Quarter e_machine; /* machine type */
Elf64_Half e_version; /* version number */
Elf64_Addr e_entry; /* entry point */
Elf64_Off e_phoff; /* Program hdr offset */
Elf64_Off e_shoff; /* Section hdr offset */
Elf64_Half e_flags; /* Processor flags */
Elf64_Quarter e_ehsize; /* sizeof ehdr */
Elf64_Quarter e_phentsize; /* Program header entry size */
Elf64_Quarter e_phnum; /* Number of program headers */
Elf64_Quarter e_shentsize; /* Section header entry size */
Elf64_Quarter e_shnum; /* Number of section headers */
Elf64_Quarter e_shstrndx; /* String table index */
} Elf64_Ehdr;
/* e_type */
#define ET_NONE 0 /* No file type */
#define ET_REL 1 /* relocatable file */
#define ET_EXEC 2 /* executable file */
#define ET_DYN 3 /* shared object file */
#define ET_CORE 4 /* core file */
#define ET_NUM 5 /* number of types */
#define ET_LOPROC 0xff00 /* reserved range for processor */
#define ET_HIPROC 0xffff /* specific e_type */
/* e_machine */
#define EM_NONE 0 /* No Machine */
#define EM_M32 1 /* AT&T WE 32100 */
#define EM_SPARC 2 /* SPARC */
#define EM_386 3 /* Intel 80386 */
#define EM_68K 4 /* Motorola 68000 */
#define EM_88K 5 /* Motorola 88000 */
#define EM_486 6 /* Intel 80486 - unused? */
#define EM_860 7 /* Intel 80860 */
#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
/*
* Don't know if EM_MIPS_RS4_BE,
* EM_SPARC64, EM_PARISC,
* or EM_PPC are ABI compliant
*/
#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */
#define EM_PARISC 15 /* HPPA */
#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
#define EM_PPC 20 /* PowerPC */
#define EM_ARM 40 /* ARM AArch32 */
#define EM_ALPHA 41 /* DEC ALPHA */
#define EM_SH 42 /* Hitachi/Renesas Super-H */
#define EM_SPARCV9 43 /* SPARC version 9 */
#define EM_IA_64 50 /* Intel IA-64 Processor */
#define EM_AMD64 62 /* AMD64 architecture */
#define EM_VAX 75 /* DEC VAX */
#define EM_AARCH64 183 /* ARM AArch64 */
/* Non-standard */
#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */
/* Version */
#define EV_NONE 0 /* Invalid */
#define EV_CURRENT 1 /* Current */
#define EV_NUM 2 /* number of versions */
/* Section Header */
typedef struct
{
Elf32_Word sh_name; /* name - index into section header
* string table section */
Elf32_Word sh_type; /* type */
Elf32_Word sh_flags; /* flags */
Elf32_Addr sh_addr; /* address */
Elf32_Off sh_offset; /* file offset */
Elf32_Word sh_size; /* section size */
Elf32_Word sh_link; /* section header table index link */
Elf32_Word sh_info; /* extra information */
Elf32_Word sh_addralign; /* address alignment */
Elf32_Word sh_entsize; /* section entry size */
} Elf32_Shdr;
typedef struct
{
Elf64_Half sh_name; /* section name */
Elf64_Half sh_type; /* section type */
Elf64_Xword sh_flags; /* section flags */
Elf64_Addr sh_addr; /* virtual address */
Elf64_Off sh_offset; /* file offset */
Elf64_Xword sh_size; /* section size */
Elf64_Half sh_link; /* link to another */
Elf64_Half sh_info; /* misc info */
Elf64_Xword sh_addralign; /* memory alignment */
Elf64_Xword sh_entsize; /* table entry size */
} Elf64_Shdr;
/* Special Section Indexes */
#define SHN_UNDEF 0 /* undefined */
#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */
#define SHN_LOPROC 0xff00 /* reserved range for processor */
#define SHN_HIPROC 0xff1f /* specific section indexes */
#define SHN_ABS 0xfff1 /* absolute value */
#define SHN_COMMON 0xfff2 /* common symbol */
#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */
/* sh_type */
#define SHT_NULL 0 /* inactive */
#define SHT_PROGBITS 1 /* program defined information */
#define SHT_SYMTAB 2 /* symbol table section */
#define SHT_STRTAB 3 /* string table section */
#define SHT_RELA 4 /* relocation section with addends*/
#define SHT_HASH 5 /* symbol hash table section */
#define SHT_DYNAMIC 6 /* dynamic section */
#define SHT_NOTE 7 /* note section */
#define SHT_NOBITS 8 /* no space section */
#define SHT_REL 9 /* relation section without addends */
#define SHT_SHLIB 10 /* reserved - purpose unknown */
#define SHT_DYNSYM 11 /* dynamic symbol table section */
#define SHT_NUM 12 /* number of section types */
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
#define SHT_HIPROC 0x7fffffff /* specific section header types */
#define SHT_LOUSER 0x80000000 /* reserved range for application */
#define SHT_HIUSER 0xffffffff /* specific indexes */
/* Section names */
#define ELF_BSS ".bss" /* uninitialized data */
#define ELF_DATA ".data" /* initialized data */
#define ELF_DEBUG ".debug" /* debug */
#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */
#define ELF_DYNSTR ".dynstr" /* dynamic string table */
#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */
#define ELF_FINI ".fini" /* termination code */
#define ELF_GOT ".got" /* global offset table */
#define ELF_HASH ".hash" /* symbol hash table */
#define ELF_INIT ".init" /* initialization code */
#define ELF_REL_DATA ".rel.data" /* relocation data */
#define ELF_REL_FINI ".rel.fini" /* relocation termination code */
#define ELF_REL_INIT ".rel.init" /* relocation initialization code */
#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */
#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */
#define ELF_REL_TEXT ".rel.text" /* relocation code */
#define ELF_RODATA ".rodata" /* read-only data */
#define ELF_SHSTRTAB ".shstrtab" /* section header string table */
#define ELF_STRTAB ".strtab" /* string table */
#define ELF_SYMTAB ".symtab" /* symbol table */
#define ELF_TEXT ".text" /* code */
/* Section Attribute Flags - sh_flags */
#define SHF_WRITE 0x1 /* Writable */
#define SHF_ALLOC 0x2 /* occupies memory */
#define SHF_EXECINSTR 0x4 /* executable */
#define SHF_TLS 0x400 /* thread local storage */
#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor \
* specific section attributes */
/* Symbol Table Entry */
typedef struct elf32_sym
{
Elf32_Word st_name; /* name - index into string table */
Elf32_Addr st_value; /* symbol value */
Elf32_Word st_size; /* symbol size */
unsigned char st_info; /* type and binding */
unsigned char st_other; /* 0 - no defined meaning */
Elf32_Half st_shndx; /* section header index */
} Elf32_Sym;
typedef struct
{
Elf64_Half st_name; /* Symbol name index in str table */
Elf_Byte st_info; /* type / binding attrs */
Elf_Byte st_other; /* unused */
Elf64_Quarter st_shndx; /* section index of symbol */
Elf64_Xword st_value; /* value of symbol */
Elf64_Xword st_size; /* size of symbol */
} Elf64_Sym;
/* Symbol table index */
#define STN_UNDEF 0 /* undefined */
/* Extract symbol info - st_info */
#define ELF32_ST_BIND(x) ((x) >> 4)
#define ELF32_ST_TYPE(x) (((unsigned int)x) & 0xf)
#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
#define ELF64_ST_BIND(x) ((x) >> 4)
#define ELF64_ST_TYPE(x) (((unsigned int)x) & 0xf)
#define ELF64_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
/* Symbol Binding - ELF32_ST_BIND - st_info */
#define STB_LOCAL 0 /* Local symbol */
#define STB_GLOBAL 1 /* Global symbol */
#define STB_WEAK 2 /* like global - lower precedence */
#define STB_NUM 3 /* number of symbol bindings */
#define STB_LOPROC 13 /* reserved range for processor */
#define STB_HIPROC 15 /* specific symbol bindings */
/* Symbol type - ELF32_ST_TYPE - st_info */
#define STT_NOTYPE 0 /* not specified */
#define STT_OBJECT 1 /* data object */
#define STT_FUNC 2 /* function */
#define STT_SECTION 3 /* section */
#define STT_FILE 4 /* file */
#define STT_TLS 6 /* thread local storage */
#define STT_LOPROC 13 /* reserved range for processor */
#define STT_HIPROC 15 /* specific symbol types */
/* Relocation entry with implicit addend */
typedef struct
{
Elf32_Addr r_offset; /* offset of relocation */
Elf32_Word r_info; /* symbol table index and type */
} Elf32_Rel;
/* Relocation entry with explicit addend */
typedef struct
{
Elf32_Addr r_offset; /* offset of relocation */
Elf32_Word r_info; /* symbol table index and type */
Elf32_Sword r_addend;
} Elf32_Rela;
/* Extract relocation info - r_info */
#define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
typedef struct
{
Elf64_Xword r_offset; /* where to do it */
Elf64_Xword r_info; /* index & type of relocation */
} Elf64_Rel;
typedef struct
{
Elf64_Xword r_offset; /* where to do it */
Elf64_Xword r_info; /* index & type of relocation */
Elf64_Sxword r_addend; /* adjustment value */
} Elf64_Rela;
#define ELF64_R_SYM(info) ((info) >> 32)
#define ELF64_R_TYPE(info) ((info)&0xFFFFFFFF)
#define ELF64_R_INFO(s, t) (((s) << 32) + (__uint32_t)(t))
#if defined(__mips64__) && defined(__MIPSEL__)
/*
* The 64-bit MIPS ELF ABI uses a slightly different relocation format
* than the regular ELF ABI: the r_info field is split into several
* pieces (see gnu/usr.bin/binutils/include/elf/mips.h for details).
*/
#undef ELF64_R_SYM
#undef ELF64_R_TYPE
#undef ELF64_R_INFO
#define ELF64_R_TYPE(info) (swap32((info) >> 32))
#define ELF64_R_SYM(info) ((info)&0xFFFFFFFF)
#define ELF64_R_INFO(s, t) (((__uint64_t)swap32(t) << 32) + (__uint32_t)(s))
#endif /* __mips64__ && __MIPSEL__ */
/* Program Header */
typedef struct
{
Elf32_Word p_type; /* segment type */
Elf32_Off p_offset; /* segment offset */
Elf32_Addr p_vaddr; /* virtual address of segment */
Elf32_Addr p_paddr; /* physical address - ignored? */
Elf32_Word p_filesz; /* number of bytes in file for seg. */
Elf32_Word p_memsz; /* number of bytes in mem. for seg. */
Elf32_Word p_flags; /* flags */
Elf32_Word p_align; /* memory alignment */
} Elf32_Phdr;
typedef struct
{
Elf64_Half p_type; /* entry type */
Elf64_Half p_flags; /* flags */
Elf64_Off p_offset; /* offset */
Elf64_Addr p_vaddr; /* virtual address */
Elf64_Addr p_paddr; /* physical address */
Elf64_Xword p_filesz; /* file size */
Elf64_Xword p_memsz; /* memory size */
Elf64_Xword p_align; /* memory & file alignment */
} Elf64_Phdr;
/* Segment types - p_type */
#define PT_NULL 0 /* unused */
#define PT_LOAD 1 /* loadable segment */
#define PT_DYNAMIC 2 /* dynamic linking section */
#define PT_INTERP 3 /* the RTLD */
#define PT_NOTE 4 /* auxiliary information */
#define PT_SHLIB 5 /* reserved - purpose undefined */
#define PT_PHDR 6 /* program header */
#define PT_TLS 7 /* thread local storage */
#define PT_LOOS 0x60000000 /* reserved range for OS */
#define PT_HIOS 0x6fffffff /* specific segment types */
#define PT_LOPROC 0x70000000 /* reserved range for processor */
#define PT_HIPROC 0x7fffffff /* specific segment types */
#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */
#define PT_GANDR_KERNEL 0x67646b6c /* gdkl */
/* Segment flags - p_flags */
#define PF_X 0x1 /* Executable */
#define PF_W 0x2 /* Writable */
#define PF_R 0x4 /* Readable */
#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */
/* specific segment flags */
/* Dynamic structure */
typedef struct
{
Elf32_Sword d_tag; /* controls meaning of d_val */
union {
Elf32_Word d_val; /* Multiple meanings - see d_tag */
Elf32_Addr d_ptr; /* program virtual address */
} d_un;
} Elf32_Dyn;
typedef struct
{
Elf64_Xword d_tag; /* controls meaning of d_val */
union {
Elf64_Addr d_ptr;
Elf64_Xword d_val;
} d_un;
} Elf64_Dyn;
/* Dynamic Array Tags - d_tag */
#define DT_NULL 0 /* marks end of _DYNAMIC array */
#define DT_NEEDED 1 /* string table offset of needed lib */
#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */
#define DT_PLTGOT 3 /* address PLT/GOT */
#define DT_HASH 4 /* address of symbol hash table */
#define DT_STRTAB 5 /* address of string table */
#define DT_SYMTAB 6 /* address of symbol table */
#define DT_RELA 7 /* address of relocation table */
#define DT_RELASZ 8 /* size of relocation table */
#define DT_RELAENT 9 /* size of relocation entry */
#define DT_STRSZ 10 /* size of string table */
#define DT_SYMENT 11 /* size of symbol table entry */
#define DT_INIT 12 /* address of initialization func. */
#define DT_FINI 13 /* address of termination function */
#define DT_SONAME 14 /* string table offset of shared obj */
#define DT_RPATH 15 /* string table offset of library \
* search path */
#define DT_SYMBOLIC 16 /* start sym search in shared obj. */
#define DT_REL 17 /* address of rel. tbl. w addends */
#define DT_RELSZ 18 /* size of DT_REL relocation table */
#define DT_RELENT 19 /* size of DT_REL relocation entry */
#define DT_PLTREL 20 /* PLT referenced relocation entry */
#define DT_DEBUG 21 /* bugger */
#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */
#define DT_JMPREL 23 /* add. of PLT's relocation entries */
#define DT_BIND_NOW 24 /* Bind now regardless of env setting */
#define DT_LOOS 0x6000000d /* reserved range for OS */
#define DT_HIOS 0x6ffff000 /* specific dynamic array tags */
#define DT_LOPROC 0x70000000 /* reserved range for processor */
#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
/* some other useful tags */
#define DT_RELACOUNT 0x6ffffff9 /* if present, number of RELATIVE */
#define DT_RELCOUNT 0x6ffffffa /* relocs, which must come first */
#define DT_FLAGS_1 0x6ffffffb
/* Dynamic Flags - DT_FLAGS_1 .dynamic entry */
#define DF_1_NOW 0x00000001
#define DF_1_GLOBAL 0x00000002
#define DF_1_GROUP 0x00000004
#define DF_1_NODELETE 0x00000008
#define DF_1_LOADFLTR 0x00000010
#define DF_1_INITFIRST 0x00000020
#define DF_1_NOOPEN 0x00000040
#define DF_1_ORIGIN 0x00000080
#define DF_1_DIRECT 0x00000100
#define DF_1_TRANS 0x00000200
#define DF_1_INTERPOSE 0x00000400
#define DF_1_NODEFLIB 0x00000800
#define DF_1_NODUMP 0x00001000
#define DF_1_CONLFAT 0x00002000
/* ld.so: number of low tags that are used saved internally (0 .. DT_NUM-1) */
#define DT_NUM (DT_JMPREL + 1)
/*
* Note Definitions
*/
typedef struct
{
Elf32_Word namesz;
Elf32_Word descsz;
Elf32_Word type;
} Elf32_Note;
typedef struct
{
Elf64_Half namesz;
Elf64_Half descsz;
Elf64_Half type;
} Elf64_Note;
#if defined(ELFSIZE) && (ELFSIZE == 32)
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Rel Elf32_Rel
#define Elf_RelA Elf32_Rela
#define Elf_Dyn Elf32_Dyn
#define Elf_Half Elf32_Half
#define Elf_Word Elf32_Word
#define Elf_Sword Elf32_Sword
#define Elf_Addr Elf32_Addr
#define Elf_Off Elf32_Off
#define Elf_Nhdr Elf32_Nhdr
#define Elf_Note Elf32_Note
#define ELF_R_SYM ELF32_R_SYM
#define ELF_R_TYPE ELF32_R_TYPE
#define ELF_R_INFO ELF32_R_INFO
#define ELFCLASS ELFCLASS32
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_TYPE ELF32_ST_TYPE
#define ELF_ST_INFO ELF32_ST_INFO
#elif defined(ELFSIZE) && (ELFSIZE == 64)
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Phdr Elf64_Phdr
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#define Elf_Rel Elf64_Rel
#define Elf_RelA Elf64_Rela
#define Elf_Dyn Elf64_Dyn
#define Elf_Half Elf64_Half
#define Elf_Word Elf64_Word
#define Elf_Sword Elf64_Sword
#define Elf_Addr Elf64_Addr
#define Elf_Off Elf64_Off
#define Elf_Nhdr Elf64_Nhdr
#define Elf_Note Elf64_Note
#define ELF_R_SYM ELF64_R_SYM
#define ELF_R_TYPE ELF64_R_TYPE
#define ELF_R_INFO ELF64_R_INFO
#define ELFCLASS ELFCLASS64
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
#define ELF_ST_INFO ELF64_ST_INFO
#endif
#endif

View File

@@ -0,0 +1,49 @@
/*
* Copyright © 2014, Owen Shepherd
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ELFARCH_H
#define ELFARCH_H
#if defined(__i386__)
#define EM_THIS EM_386
#define EL_ARCH_USES_REL
#elif defined(__amd64__)
#define EM_THIS EM_AMD64
#define EL_ARCH_USES_RELA
#elif defined(__arm__)
#define EM_THIS EM_ARM
#define EL_ARCH_USES_REL
#elif defined(__aarch64__)
#define EM_THIS EM_AARCH64
#define EL_ARCH_USES_RELA
#define EL_ARCH_USES_REL
#else
#error specify your ELF architecture
#endif
#if defined(__LP64__) || defined(__LLP64__)
#define ELFSIZE 64
#else
#define ELFSIZE 32
#endif
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define ELFDATATHIS ELFDATA2LSB
#else
#define ELFDATATHIS ELFDATA2MSB
#endif
#endif

324
bdk/ianos/elfload/elfload.c Normal file
View File

@@ -0,0 +1,324 @@
/*
* Copyright © 2018, M4xw
* Copyright © 2014, Owen Shepherd
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <string.h>
#include "elfload.h"
el_status el_pread(el_ctx *ctx, void *def, size_t nb, size_t offset)
{
return ctx->pread(ctx, def, nb, offset) ? EL_OK : EL_EIO;
}
#define EL_PHOFF(ctx, num) (((ctx)->ehdr.e_phoff + (num) *(ctx)->ehdr.e_phentsize))
el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i)
{
el_status rv = EL_OK;
for (; *i < ctx->ehdr.e_phnum; (*i)++)
{
if ((rv = el_pread(ctx, phdr, sizeof *phdr, EL_PHOFF(ctx, *i))))
return rv;
if (phdr->p_type == type)
{
return rv;
}
}
*i = -1;
return rv;
}
#define EL_SHOFF(ctx, num) (((ctx)->ehdr.e_shoff + (num) *(ctx)->ehdr.e_shentsize))
el_status el_findshdr(el_ctx *ctx, Elf_Shdr *shdr, uint32_t type, unsigned *i)
{
el_status rv = EL_OK;
for (; *i < ctx->ehdr.e_shnum; (*i)++)
{
if ((rv = el_pread(ctx, shdr, sizeof *shdr, EL_SHOFF(ctx, *i))))
return rv;
if (shdr->sh_type == type)
{
return rv;
}
}
*i = -1;
return rv;
}
el_status el_init(el_ctx *ctx)
{
el_status rv = EL_OK;
if ((rv = el_pread(ctx, &ctx->ehdr, sizeof ctx->ehdr, 0)))
return rv;
/* validate header */
if (!IS_ELF(ctx->ehdr))
return EL_NOTELF;
if (ctx->ehdr.e_ident[EI_CLASS] != ELFCLASS)
return EL_WRONGBITS;
if (ctx->ehdr.e_ident[EI_DATA] != ELFDATATHIS)
return EL_WRONGENDIAN;
if (ctx->ehdr.e_ident[EI_VERSION] != EV_CURRENT)
return EL_NOTELF;
if (ctx->ehdr.e_type != ET_EXEC && ctx->ehdr.e_type != ET_DYN)
return EL_NOTEXEC;
if (ctx->ehdr.e_machine != EM_THIS)
return EL_WRONGARCH;
if (ctx->ehdr.e_version != EV_CURRENT)
return EL_NOTELF;
/* load phdrs */
Elf_Phdr ph;
/* iterate through, calculate extents */
ctx->base_load_paddr = ctx->base_load_vaddr = 0;
ctx->align = 1;
ctx->memsz = 0;
unsigned i = 0;
for (;;)
{
if ((rv = el_findphdr(ctx, &ph, PT_LOAD, &i)))
return rv;
if (i == (unsigned)-1)
break;
Elf_Addr phend = ph.p_vaddr + ph.p_memsz;
if (phend > ctx->memsz)
ctx->memsz = phend;
if (ph.p_align > ctx->align)
ctx->align = ph.p_align;
i++;
}
// Program Header
if (ctx->ehdr.e_type == ET_DYN)
{
i = 0;
if ((rv = el_findphdr(ctx, &ph, PT_DYNAMIC, &i)))
return rv;
if (i == (unsigned)-1)
return EL_NODYN;
ctx->dynoff = ph.p_offset;
ctx->dynsize = ph.p_filesz;
}
else
{
ctx->dynoff = 0;
ctx->dynsize = 0;
}
// Section String Table
if (ctx->ehdr.e_type == ET_DYN)
{
i = ctx->ehdr.e_shstrndx - 1;
if ((rv = el_findshdr(ctx, &ctx->shstr, SHT_STRTAB, &i)))
return rv;
// Reset
i = 0;
if ((rv = el_findshdr(ctx, &ctx->symtab, SHT_SYMTAB, &i)))
return rv;
if (i == (unsigned)-1)
return EL_NODYN;
}
return rv;
}
/*
typedef void* (*el_alloc_cb)(
el_ctx *ctx,
Elf_Addr phys,
Elf_Addr virt,
Elf_Addr size);
*/
el_status el_load(el_ctx *ctx, el_alloc_cb alloc)
{
el_status rv = EL_OK;
/* address deltas */
Elf_Addr pdelta = ctx->base_load_paddr;
Elf_Addr vdelta = ctx->base_load_vaddr;
/* iterate paddrs */
Elf_Phdr ph;
unsigned i = 0;
for (;;)
{
if ((rv = el_findphdr(ctx, &ph, PT_LOAD, &i)))
return rv;
if (i == (unsigned)-1)
break;
Elf_Addr pload = ph.p_paddr + pdelta;
Elf_Addr vload = ph.p_vaddr + vdelta;
/* allocate mem */
char *dest = alloc(ctx, pload, vload, ph.p_memsz);
if (!dest)
return EL_ENOMEM;
EL_DEBUG("Loading seg fileoff %x, vaddr %x to %p\n",
ph.p_offset, ph.p_vaddr, dest);
/* read loaded portion */
if ((rv = el_pread(ctx, dest, ph.p_filesz, ph.p_offset)))
return rv;
/* zero mem-only portion */
memset(dest + ph.p_filesz, 0, ph.p_memsz - ph.p_filesz);
i++;
}
return rv;
}
el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t tag)
{
el_status rv = EL_OK;
size_t ndyn = ctx->dynsize / sizeof(Elf_Dyn);
for (unsigned i = 0; i < ndyn; i++)
{
if ((rv = el_pread(ctx, dyn, sizeof *dyn, ctx->dynoff + i * sizeof *dyn)))
return rv;
if (dyn->d_tag == tag)
return EL_OK;
}
dyn->d_tag = DT_NULL;
return EL_OK;
}
el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type)
{
el_status rv = EL_OK;
Elf_Dyn rel, relsz, relent;
if ((rv = el_finddyn(ctx, &rel, type)))
return rv;
if ((rv = el_finddyn(ctx, &relsz, type + 1)))
return rv;
if ((rv = el_finddyn(ctx, &relent, type + 2)))
return rv;
if (rel.d_tag == DT_NULL || relsz.d_tag == DT_NULL || relent.d_tag == DT_NULL)
{
ri->entrysize = 0;
ri->tablesize = 0;
ri->tableoff = 0;
}
else
{
ri->tableoff = rel.d_un.d_ptr;
ri->tablesize = relsz.d_un.d_val;
ri->entrysize = relent.d_un.d_val;
}
return rv;
}
extern el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel);
extern el_status el_applyrela(el_ctx *ctx, Elf_RelA *rela);
el_status el_relocate(el_ctx *ctx)
{
el_status rv = EL_OK;
// not dynamic
if (ctx->ehdr.e_type != ET_DYN)
return EL_OK;
char *base = (char *)ctx->base_load_paddr;
el_relocinfo ri;
#ifdef EL_ARCH_USES_REL
if ((rv = el_findrelocs(ctx, &ri, DT_REL)))
return rv;
if (ri.entrysize != sizeof(Elf_Rel) && ri.tablesize)
{
EL_DEBUG("Relocation size %u doesn't match expected %u\n",
ri.entrysize, sizeof(Elf_Rel));
return EL_BADREL;
}
size_t relcnt = ri.tablesize / sizeof(Elf_Rel);
Elf_Rel *reltab = (Elf_Rel *)(base + ri.tableoff);
for (size_t i = 0; i < relcnt; i++)
{
if ((rv = el_applyrel(ctx, &reltab[i])))
return rv;
}
#endif
#ifdef EL_ARCH_USES_RELA
if ((rv = el_findrelocs(ctx, &ri, DT_RELA)))
return rv;
if (ri.entrysize != sizeof(Elf_RelA) && ri.tablesize)
{
EL_DEBUG("Relocation size %u doesn't match expected %u\n",
ri.entrysize, sizeof(Elf_RelA));
return EL_BADREL;
}
size_t relacnt = ri.tablesize / sizeof(Elf_RelA);
Elf_RelA *relatab = (Elf_RelA *)(base + ri.tableoff);
for (size_t i = 0; i < relacnt; i++)
{
if ((rv = el_applyrela(ctx, &relatab[i])))
return rv;
}
#endif
#if !defined(EL_ARCH_USES_REL) && !defined(EL_ARCH_USES_RELA)
#error No relocation type defined!
#endif
return rv;
}

127
bdk/ianos/elfload/elfload.h Normal file
View File

@@ -0,0 +1,127 @@
/*
* Copyright © 2018, M4xw
* Copyright © 2014, Owen Shepherd
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ELFLOAD_H
#define ELFLOAD_H
#include <stddef.h>
#include "elfarch.h"
#include "elf.h"
#include <utils/types.h>
#ifdef DEBUG
#include <gfx_utils.h>
#define EL_DEBUG(format, ...) \
gfx_printf(format __VA_OPT__(, ) __VA_ARGS__)
#else
#define EL_DEBUG(...) \
do \
{ \
} while (0)
#endif
typedef enum
{
EL_OK = 0,
EL_EIO,
EL_ENOMEM,
EL_NOTELF,
EL_WRONGBITS,
EL_WRONGENDIAN,
EL_WRONGARCH,
EL_WRONGOS,
EL_NOTEXEC,
EL_NODYN,
EL_BADREL,
} el_status;
typedef struct el_ctx
{
bool (*pread)(struct el_ctx *ctx, void *dest, size_t nb, size_t offset);
/* base_load_* -> address we are actually going to load at
*/
Elf_Addr
base_load_paddr,
base_load_vaddr;
/* size in memory of binary */
Elf_Addr memsz;
/* required alignment */
Elf_Addr align;
/* ELF header */
Elf_Ehdr ehdr;
// Section Header Str Table
Elf_Shdr shstr;
Elf_Shdr symtab;
/* Offset of dynamic table (0 if not ET_DYN) */
Elf_Off dynoff;
/* Size of dynamic table (0 if not ET_DYN) */
Elf_Addr dynsize;
} el_ctx;
el_status el_pread(el_ctx *ctx, void *def, size_t nb, size_t offset);
el_status el_init(el_ctx *ctx);
typedef void *(*el_alloc_cb)(
el_ctx *ctx,
Elf_Addr phys,
Elf_Addr virt,
Elf_Addr size);
el_status el_load(el_ctx *ctx, el_alloc_cb alloccb);
/* find the next phdr of type \p type, starting at \p *i.
* On success, returns EL_OK with *i set to the phdr number, and the phdr loaded
* in *phdr.
*
* If the end of the phdrs table was reached, *i is set to -1 and the contents
* of *phdr are undefined
*/
el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i);
/* Relocate the loaded executable */
el_status el_relocate(el_ctx *ctx);
/* find a dynamic table entry
* returns the entry on success, dyn->d_tag = DT_NULL on failure
*/
el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t type);
typedef struct
{
Elf_Off tableoff;
Elf_Addr tablesize;
Elf_Addr entrysize;
} el_relocinfo;
/* find all information regarding relocations of a specific type.
*
* pass DT_REL or DT_RELA for type
* sets ri->entrysize = 0 if not found
*/
el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type);
#endif

View File

@@ -0,0 +1,84 @@
/*
* Copyright © 2014, Owen Shepherd
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "elfload.h"
#if defined(__aarch64__)
#define R_AARCH64_NONE 0
#define R_AARCH64_RELATIVE 1027
el_status el_applyrela(el_ctx *ctx, Elf_RelA *rel)
{
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr);
uint32_t type = ELF_R_TYPE(rel->r_info);
uint32_t sym = ELF_R_SYM(rel->r_info);
switch (type)
{
case R_AARCH64_NONE:
EL_DEBUG("R_AARCH64_NONE\n");
break;
case R_AARCH64_RELATIVE:
if (sym)
{
EL_DEBUG("R_AARCH64_RELATIVE with symbol ref!\n");
return EL_BADREL;
}
EL_DEBUG("Applying R_AARCH64_RELATIVE reloc @%p\n", p);
*p = rel->r_addend + ctx->base_load_vaddr;
break;
default:
EL_DEBUG("Bad relocation %u\n", type);
return EL_BADREL;
}
return EL_OK;
}
el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel)
{
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr);
uint32_t type = ELF_R_TYPE(rel->r_info);
uint32_t sym = ELF_R_SYM(rel->r_info);
switch (type)
{
case R_AARCH64_NONE:
EL_DEBUG("R_AARCH64_NONE\n");
break;
case R_AARCH64_RELATIVE:
if (sym)
{
EL_DEBUG("R_AARCH64_RELATIVE with symbol ref!\n");
return EL_BADREL;
}
EL_DEBUG("Applying R_AARCH64_RELATIVE reloc @%p\n", p);
*p += ctx->base_load_vaddr;
break;
default:
EL_DEBUG("Bad relocation %u\n", type);
return EL_BADREL;
}
return EL_OK;
}
#endif

View File

@@ -0,0 +1,66 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <m4x@m4xw.net> wrote this file. As long as you retain this notice you can do
* whatever you want with this stuff. If we meet some day, and you think this
* stuff is worth it, you can buy me a beer in return. M4xw
* ----------------------------------------------------------------------------
*/
#include "elfload.h"
#if defined(__arm__)
// Taken from http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf
#define R_ARM_NONE 0
#define R_ARM_ABS32 2
#define R_ARM_JUMP_SLOT 22
#define R_ARM_GLOB_DAT 21
#define R_ARM_RELATIVE 23
el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel)
{
uint32_t sym = ELF_R_SYM(rel->r_info); // Symbol offset
uint32_t type = ELF_R_TYPE(rel->r_info); // Relocation Type
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr); // Target Addr
#if 0 // For later symbol usage
Elf32_Sym *elfSym;
const char *symbolName;
// We resolve relocs from the originating elf-image
elfSym = (Elf32_Sym *)(ctx->symtab.sh_offset + (char *)buffteg) + sym;
int strtab_offset = ctx->shstr.sh_offset;
char *strtab = (char *)buffteg + strtab_offset;
symbolName = strtab + elfSym->st_name;
//EL_DEBUG("Str: %s sz: %x val: %x\n", symbolName, elfSym->st_size, elfSym->st_value);
#endif
switch (type)
{
case R_ARM_NONE:
EL_DEBUG("R_ARM_NONE\n");
break;
case R_ARM_JUMP_SLOT:
case R_ARM_ABS32:
case R_ARM_GLOB_DAT:
// Stubbed for later purpose
//*p += elfSym->st_value; // + vaddr from sec
//*p |= 0; // 1 if Thumb && STT_FUNC, ignored for now
break;
case R_ARM_RELATIVE: // Needed for PIE
if (sym)
{
return EL_BADREL;
}
*p += ctx->base_load_vaddr;
break;
default:
return EL_BADREL;
}
return EL_OK;
}
#endif

126
bdk/ianos/ianos.c Normal file
View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2018 M4xw
* Copyright (c) 2018-2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "ianos.h"
#include "elfload/elfload.h"
#include <module.h>
#include <mem/heap.h>
#include <power/max7762x.h>
#include <storage/nx_sd.h>
#include <utils/types.h>
#include <gfx_utils.h>
#define IRAM_LIB_ADDR 0x4002B000
#define DRAM_LIB_ADDR 0xE0000000
extern heap_t _heap;
void *elfBuf = NULL;
void *fileBuf = NULL;
static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
{
bdkParams_t bdkParameters = (bdkParams_t)malloc(sizeof(struct _bdkParams_t));
bdkParameters->gfxCon = (void *)&gfx_con;
bdkParameters->gfxCtx = (void *)&gfx_ctxt;
bdkParameters->memcpy = (memcpy_t)&memcpy;
bdkParameters->memset = (memset_t)&memset;
bdkParameters->sharedHeap = &_heap;
// Extra functions.
bdkParameters->extension_magic = IANOS_EXT0;
bdkParameters->reg_voltage_set = (reg_voltage_set_t)&max7762x_regulator_set_voltage;
entrypoint(moduleConfig, bdkParameters);
}
static void *_ianos_alloc_cb(el_ctx *ctx, Elf_Addr phys, Elf_Addr virt, Elf_Addr size)
{
(void)ctx;
(void)phys;
(void)size;
return (void *)virt;
}
static bool _ianos_read_cb(el_ctx *ctx, void *dest, size_t numberBytes, size_t offset)
{
(void)ctx;
memcpy(dest, fileBuf + offset, numberBytes);
return true;
}
//TODO: Support shared libraries.
uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig)
{
el_ctx ctx;
uintptr_t epaddr = 0;
if (!sd_mount())
goto elfLoadFinalOut;
// Read library.
fileBuf = sd_file_read(path, NULL);
if (!fileBuf)
goto elfLoadFinalOut;
ctx.pread = _ianos_read_cb;
if (el_init(&ctx))
goto elfLoadFinalOut;
// Set our relocated library's buffer.
switch (type & 0xFFFF)
{
case EXEC_ELF:
case AR64_ELF:
elfBuf = (void *)DRAM_LIB_ADDR;
break;
default:
elfBuf = malloc(ctx.memsz); // Aligned to 0x10 by default.
}
if (!elfBuf)
goto elfLoadFinalOut;
// Load and relocate library.
ctx.base_load_vaddr = ctx.base_load_paddr = (uintptr_t)elfBuf;
if (el_load(&ctx, _ianos_alloc_cb))
goto elfFreeOut;
if (el_relocate(&ctx))
goto elfFreeOut;
// Launch.
epaddr = ctx.ehdr.e_entry + (uintptr_t)elfBuf;
moduleEntrypoint_t ep = (moduleEntrypoint_t)epaddr;
_ianos_call_ep(ep, moduleConfig);
elfFreeOut:
free(fileBuf);
elfBuf = NULL;
fileBuf = NULL;
elfLoadFinalOut:
return epaddr;
}

34
bdk/ianos/ianos.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018 M4xw
* Copyright (c) 2018 CTCaer
*
* 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 IANOS_H
#define IANOS_H
#include <utils/types.h>
typedef enum
{
DRAM_LIB = 0, // DRAM library.
EXEC_ELF = 1, // Executable elf that does not return.
DR64_LIB = 2, // AARCH64 DRAM library.
AR64_ELF = 3, // Executable elf that does not return.
KEEP_IN_RAM = (1 << 31) // Shared library mask.
} elfType_t;
uintptr_t ianos_loader(char *path, elfType_t type, void* config);
#endif

156
bdk/input/als.c Normal file
View File

@@ -0,0 +1,156 @@
/*
* Ambient light sensor driver for Nintendo Switch's Rohm BH1730
*
* Copyright (c) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "als.h"
#include <power/max7762x.h>
#include <soc/clock.h>
#include <soc/i2c.h>
#include <soc/pinmux.h>
#include <utils/util.h>
#define BH1730_DEFAULT_GAIN BH1730_GAIN_64X
#define BH1730_DEFAULT_ICYCLE 38
#define BH1730_INTERNAL_CLOCK_NS 2800
#define BH1730_ADC_CALC_DELAY_US 2000 /* BH1730_INTERNAL_CLOCK_MS * 714 */
#define BH1730_ITIME_CYCLE_TO_US 2700 /* BH1730_INTERNAL_CLOCK_MS * 964 */
#define BH1730_DEFAULT_ITIME_MS 100
#define BH1730_LUX_MULTIPLIER 3600
#define BH1730_LUX_MULTIPLIER_AULA 1410
#define BH1730_LUX_MAX 100000
typedef struct _opt_win_cal_t
{
u32 rc;
u32 cv;
u32 ci;
} opt_win_cal_t;
// Nintendo Switch Icosa/Iowa Optical Window calibration.
const opt_win_cal_t opt_win_cal_default[] = {
{ 500, 5002, 7502 },
{ 754, 2250, 2000 },
{ 1029, 1999, 1667 },
{ 1373, 884, 583 },
{ 1879, 309, 165 }
};
// Nintendo Switch Aula Optical Window calibration.
const opt_win_cal_t opt_win_cal_aula[] = {
{ 231, 9697, 30300 },
{ 993, 3333, 2778 },
{ 1478, 1621, 1053 },
{ 7500, 81, 10 }
};
const u32 als_gain_idx_tbl[4] = { 1, 2, 64, 128 };
void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
{
if (gain > BH1730_GAIN_128X)
gain = BH1730_GAIN_128X;
if (!cycle)
cycle = 1;
else if (cycle > 255)
cycle = 255;
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle));
als_ctxt->gain = gain;
als_ctxt->cycle = cycle;
}
void get_als_lux(als_ctxt_t *als_ctxt)
{
u32 data[2];
u32 visible_light;
u32 ir_light;
u64 lux = 0;
u32 itime_us = BH1730_ITIME_CYCLE_TO_US * als_ctxt->cycle;
// Get visible and ir light raw data. Mode is continuous so waiting for new values doesn't matter.
data[0] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0LOW_REG)) +
(i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8);
data[1] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1LOW_REG)) +
(i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8);
visible_light = data[0];
ir_light = data[1];
als_ctxt->over_limit = visible_light > 65534 || ir_light > 65534;
als_ctxt->vi_light = visible_light;
als_ctxt->ir_light = ir_light;
if (!visible_light)
{
als_ctxt->lux = 0;
return;
}
// Set calibration parameters.
u32 lux_multiplier = BH1730_LUX_MULTIPLIER;
u32 opt_win_cal_count = ARRAY_SIZE(opt_win_cal_default);
const opt_win_cal_t *opt_win_cal = opt_win_cal_default;
// Apply optical window calibration coefficients.
for (u32 i = 0; i < opt_win_cal_count; i++)
{
if (1000 * ir_light / visible_light < opt_win_cal[i].rc)
{
lux = ((u64)opt_win_cal[i].cv * data[0]) - (opt_win_cal[i].ci * data[1]);
break;
}
}
lux *= BH1730_DEFAULT_ITIME_MS * lux_multiplier;
lux /= als_gain_idx_tbl[als_ctxt->gain] * itime_us;
lux /= 1000;
if (lux > BH1730_LUX_MAX)
lux = BH1730_LUX_MAX;
als_ctxt->lux = lux;
}
u8 als_power_on(als_ctxt_t *als_ctxt)
{
// Enable power to ALS IC.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
max7762x_regulator_enable(REGULATOR_LDO6, true);
// Init I2C2.
pinmux_config_i2c(I2C_2);
clock_enable_i2c(I2C_2);
i2c_init(I2C_2);
// Initialize ALS.
u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12));
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0);
set_als_cfg(als_ctxt, BH1730_DEFAULT_GAIN, BH1730_DEFAULT_ICYCLE);
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG), BH1730_CTL_POWER_ON | BH1730_CTL_ADC_EN);
return id;
}

65
bdk/input/als.h Normal file
View File

@@ -0,0 +1,65 @@
/*
* Ambient light sensor driver for Nintendo Switch's Rohm BH1730
*
* Copyright (c) 2018 CTCaer
*
* 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 __ALS_H_
#define __ALS_H_
#include <utils/types.h>
#define BH1730_I2C_ADDR 0x29
#define BH1730_CMD_MAGIC 0x80
#define BH1730_CMD_SETADDR 0x00
#define BH1730_CMD_SPECCMD 0x60
#define BH1730_SPECCMD_RESET 0x4
#define BH1730_CONTROL_REG 0x00
#define BH1730_CTL_ADC_VALID 0x10
#define BH1730_CTL_ONE_TIME 0x08
#define BH1730_CTL_DAT0_ONLY 0x04
#define BH1730_CTL_ADC_EN 0x02
#define BH1730_CTL_POWER_ON 0x01
#define BH1730_TIMING_REG 0x01
#define BH1730_GAIN_REG 0x07
#define BH1730_GAIN_1X 0x00
#define BH1730_GAIN_2X 0x01
#define BH1730_GAIN_64X 0x02
#define BH1730_GAIN_128X 0x03
#define BH1730_DATA0LOW_REG 0x14
#define BH1730_DATA0HIGH_REG 0x15
#define BH1730_DATA1LOW_REG 0x16
#define BH1730_DATA1HIGH_REG 0x17
#define BH1730_ADDR(reg) (BH1730_CMD_MAGIC | BH1730_CMD_SETADDR | (reg))
#define BH1730_SPEC(cmd) (BH1730_CMD_MAGIC | BH1730_CMD_SPECCMD | (cmd))
typedef struct _als_ctxt_t
{
u32 lux;
bool over_limit;
u32 vi_light;
u32 ir_light;
u8 gain;
u8 cycle;
} als_ctxt_t;
void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle);
void get_als_lux(als_ctxt_t *als_ctxt);
u8 als_power_on(als_ctxt_t *als_ctxt);
#endif /* __ALS_H_ */

928
bdk/input/joycon.c Normal file
View File

@@ -0,0 +1,928 @@
/*
* Joy-Con UART driver for Nintendo Switch
*
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "joycon.h"
#include <gfx_utils.h>
#include <power/max17050.h>
#include <power/regulator_5v.h>
#include <soc/bpmp.h>
#include <soc/clock.h>
#include <soc/fuse.h>
#include <soc/gpio.h>
#include <soc/pinmux.h>
#include <soc/uart.h>
#include <soc/t210.h>
#include <utils/util.h>
// For disabling driver when logging is enabled.
#include <libs/lv_conf.h>
#define JC_WIRED_CMD 0x91
#define JC_WIRED_HID 0x92
#define JC_WIRED_INIT_REPLY 0x94
#define JC_INIT_HANDSHAKE 0xA5
#define JC_HORI_INPUT_RPT_CMD 0x9A
#define JC_HORI_INPUT_RPT 0x00
#define JC_WIRED_CMD_MAC 0x01
#define JC_WIRED_CMD_10 0x10
#define JC_HID_OUTPUT_RPT 0x01
#define JC_HID_RUMBLE_RPT 0x10
#define JC_HID_INPUT_RPT 0x30
#define JC_HID_SUBMCD_RPT 0x21
#define JC_HID_SUBCMD_HCI_STATE 0x06
#define HCI_STATE_SLEEP 0x00
#define HCI_STATE_RECONNECT 0x01
#define HCI_STATE_PAIR 0x02
#define HCI_STATE_HOME 0x04
#define JC_HID_SUBCMD_SPI_READ 0x10
#define SPI_READ_OFFSET 0x20
#define JC_HID_SUBCMD_RUMBLE_CTL 0x48
#define JC_HID_SUBCMD_SND_RUMBLE 0xFF
#define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status.
#define JC_BTN_MASK_R 0x0056FF
#define JC_ID_L 0x01
#define JC_ID_R 0x02
#define JC_ID_HORI 0x20
#define JC_CRC8_INIT 0x00
#define JC_CRC8_POLY 0x8D
enum
{
JC_BATT_EMTPY = 0,
JC_BATT_CRIT = 2,
JC_BATT_LOW = 4,
JC_BATT_MID = 6,
JC_BATT_FULL = 8
};
static const u8 init_jc[] = {
0xA1, 0xA2, 0xA3, 0xA4
};
static const u8 init_handshake[] = {
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
JC_INIT_HANDSHAKE, 0x02, // Wired cmd and wired subcmd.
0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data and crc.
};
static const u8 init_get_info[] = {
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd.
0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc.
};
static const u8 init_finalize[] = {
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd.
0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data and crc.
};
static const u8 nx_pad_status[] = {
0x19, 0x01, 0x03, 0x08, 0x00, // Uart header.
JC_WIRED_HID, 0x00, // Wired cmd and hid cmd.
0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data and crc.
};
static const u8 hori_pad_status[] = {
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
JC_HORI_INPUT_RPT_CMD, 0x01, // Hori cmd and hori subcmd.
0x00, 0x00, 0x00, 0x00, 0x48 // Hori cmd data and crc.
};
typedef struct _jc_uart_hdr_t
{
u8 magic[3];
u8 total_size_lsb;
u8 total_size_msb;
} jc_uart_hdr_t;
typedef struct _jc_wired_hdr_t
{
jc_uart_hdr_t uart_hdr;
u8 cmd;
u8 data[5];
u8 crc;
u8 payload[];
} jc_wired_hdr_t;
typedef struct _jc_hid_out_rpt_t
{
u8 cmd;
u8 pkt_id;
u8 rumble[8];
u8 subcmd;
u8 subcmd_data[];
} jc_hid_out_rpt_t;
typedef struct _jc_hid_out_spi_read_t
{
u32 addr;
u8 size;
} jc_hid_out_spi_read_t;
typedef struct _jc_hid_in_rpt_t
{
u8 cmd;
u8 pkt_id;
u8 conn_info:4;
u8 batt_info:4;
u8 btn_right;
u8 btn_shared;
u8 btn_left;
u8 stick_h_left;
u8 stick_m_left;
u8 stick_v_left;
u8 stick_h_right;
u8 stick_m_right;
u8 stick_v_right;
u8 vib_decider;
u8 submcd_ack;
u8 subcmd;
u8 subcmd_data[];
} jc_hid_in_rpt_t;
typedef struct _jc_hid_in_spi_read_t
{
u32 addr;
u8 size;
u8 data[];
} jc_hid_in_spi_read_t;
typedef struct _jc_hid_in_pair_data_t
{
u8 magic;
u8 size;
u16 checksum;
u8 mac[6];
u8 ltk[16];
u8 pad0[10];
u8 bt_caps; // bit3: Secure conn supported host, bit5: Paired to TBFC supported host, bit6: iTBFC page supported
u8 pad1;
} jc_hid_in_pair_data_t;
typedef struct _joycon_ctxt_t
{
u8 buf[0x100]; //FIXME: If heap is used, dumping breaks.
u8 uart;
u8 type;
u8 mac[6];
u32 hw_init_done;
u32 last_received_time;
u32 last_status_req_time;
u8 rumble_sent;
u8 connected;
} joycon_ctxt_t;
static joycon_ctxt_t jc_l = {0};
static joycon_ctxt_t jc_r = {0};
static bool jc_init_done = false;
static u32 hid_pkt_inc = 0;
static jc_gamepad_rpt_t jc_gamepad;
void jc_power_supply(u8 uart, bool enable);
static u8 jc_crc(u8 *data, u16 len)
{
u8 crc = JC_CRC8_INIT;
u16 i, j;
for (i = 0; i < len; i++) {
crc ^= data[i];
for (j = 0; j < 8; j++) {
if ((crc & 0x80) != 0)
crc = (u8)((crc << 1) ^ JC_CRC8_POLY);
else
crc <<= 1;
}
}
return crc;
}
void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size)
{
uart_send(uart_port, buf, size);
uart_wait_idle(uart_port, UART_TX_IDLE);
}
static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc)
{
out->uart_hdr.magic[0] = 0x19;
out->uart_hdr.magic[1] = 0x01;
out->uart_hdr.magic[2] = 0x3;
out->uart_hdr.total_size_lsb = sizeof(jc_wired_hdr_t) - sizeof(jc_uart_hdr_t);
out->uart_hdr.total_size_msb = 0;
out->cmd = wired_cmd;
if (data)
memcpy(out->data, data, size);
out->crc = crc ? jc_crc(&out->uart_hdr.total_size_msb, sizeof(out->uart_hdr.total_size_msb) + sizeof(out->cmd) + sizeof(out->data)) : 0;
return sizeof(jc_wired_hdr_t);
}
static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc)
{
u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc);
pkt_size += size;
rpt->uart_hdr.total_size_lsb += size;
rpt->data[0] = size >> 8;
rpt->data[1] = size & 0xFF;
if (payload)
memcpy(rpt->payload, payload, size);
return pkt_size;
}
void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc)
{
u8 rpt[0x50];
memset(rpt, 0, sizeof(rpt));
u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc);
joycon_send_raw(uart, rpt, rpt_size);
}
static u8 jc_hid_pkt_id_incr()
{
u8 curr_id = hid_pkt_inc;
hid_pkt_inc++;
return (curr_id & 0xF);
}
void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
{
u8 temp[0x30];
u8 rumble_neutral[8] = {0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40};
u8 rumble_init[8] = {0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72};
memset(temp, 0, sizeof(temp));
jc_hid_out_rpt_t *hid_pkt = (jc_hid_out_rpt_t *)temp;
memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
if (subcmd == JC_HID_SUBCMD_SND_RUMBLE)
{
bool send_r_rumble = jc_r.connected && !jc_r.rumble_sent;
bool send_l_rumble = jc_l.connected && !jc_l.rumble_sent;
// Enable rumble.
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
hid_pkt->subcmd_data[0] = 1;
if (send_r_rumble)
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
if (send_l_rumble)
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
// Send rumble.
hid_pkt->cmd = JC_HID_RUMBLE_RPT;
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init));
if (send_r_rumble)
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false);
if (send_l_rumble)
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false);
msleep(15);
// Disable rumble.
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
hid_pkt->subcmd_data[0] = 0;
memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
if (send_r_rumble)
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
if (send_l_rumble)
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
}
else
{
bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI);
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
hid_pkt->subcmd = subcmd;
if (data)
memcpy(hid_pkt->subcmd_data, data, size);
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
}
}
static void jc_charging_decider(u8 batt, u8 uart)
{
u32 system_batt_enough = max17050_get_cached_batt_volt() > 4000;
// Power supply control based on battery levels and charging.
if ((batt >> 1 << 1) < JC_BATT_LOW) // Level without checking charging.
jc_power_supply(uart, true);
else if (batt > (system_batt_enough ? JC_BATT_FULL : JC_BATT_MID)) // Addresses the charging bit.
jc_power_supply(uart, false);
}
static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
{
u32 btn_tmp;
jc_hid_in_rpt_t *hid_pkt = (jc_hid_in_rpt_t *)packet;
switch (hid_pkt->cmd)
{
case JC_HORI_INPUT_RPT:
case JC_HID_INPUT_RPT:
btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
if (jc->type & JC_ID_L)
{
jc_gamepad.buttons &= ~JC_BTN_MASK_L;
jc_gamepad.buttons |= (btn_tmp & JC_BTN_MASK_L);
jc_gamepad.lstick_x = hid_pkt->stick_h_left | ((hid_pkt->stick_m_left & 0xF) << 8);
jc_gamepad.lstick_y = (hid_pkt->stick_m_left >> 4) | (hid_pkt->stick_v_left << 4);
jc_gamepad.batt_info_l = hid_pkt->batt_info;
}
else if (jc->type & JC_ID_R)
{
jc_gamepad.buttons &= ~JC_BTN_MASK_R;
jc_gamepad.buttons |= (btn_tmp & JC_BTN_MASK_R);
jc_gamepad.rstick_x = hid_pkt->stick_h_right | ((hid_pkt->stick_m_right & 0xF) << 8);
jc_gamepad.rstick_y = (hid_pkt->stick_m_right >> 4) | (hid_pkt->stick_v_right << 4);
jc_gamepad.batt_info_r = hid_pkt->batt_info;
}
jc_gamepad.conn_l = jc_l.connected;
jc_gamepad.conn_r = jc_r.connected;
jc_charging_decider(hid_pkt->batt_info, jc->uart);
break;
case JC_HID_SUBMCD_RPT:
if (hid_pkt->subcmd == JC_HID_SUBCMD_SPI_READ)
{
jc_bt_conn_t *bt_conn;
if (jc->type & JC_ID_L)
bt_conn = &jc_gamepad.bt_conn_l;
else
bt_conn = &jc_gamepad.bt_conn_r;
jc_hid_in_spi_read_t *spi_info = (jc_hid_in_spi_read_t *)hid_pkt->subcmd_data;
jc_hid_in_pair_data_t *pair_data = (jc_hid_in_pair_data_t *)spi_info->data;
// Check if we reply is pairing info.
if (spi_info->size == 0x1A && pair_data->magic == 0x95 && pair_data->size == 0x22)
{
bt_conn->type = jc->type;
memcpy(bt_conn->mac, jc->mac, 6);
memcpy(bt_conn->host_mac, pair_data->mac, 6);
for (u32 i = 16; i > 0; i--)
bt_conn->ltk[16 - i] = pair_data->ltk[i - 1];
}
}
break;
default:
break;
}
jc->last_received_time = get_tmr_ms();
}
static void jc_parse_wired_init(joycon_ctxt_t *jc, const u8* data, u32 size)
{
switch (data[0])
{
case JC_WIRED_CMD_MAC:
for (int i = 12; i > 6; i--)
jc->mac[12 - i] = data[i];
jc->type = data[6];
jc->connected = true;
default:
break;
}
}
static void jc_uart_pkt_parse(joycon_ctxt_t *jc, const u8* packet, size_t size)
{
jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet;
switch (pkt->cmd)
{
case JC_HORI_INPUT_RPT_CMD:
case JC_WIRED_HID:
jc_parse_wired_hid(jc, pkt->payload, (pkt->data[0] << 8) | pkt->data[1]);
break;
case JC_WIRED_INIT_REPLY:
jc_parse_wired_init(jc, pkt->data, size - sizeof(jc_uart_hdr_t) - 1);
break;
default:
break;
}
}
static void jc_rcv_pkt(joycon_ctxt_t *jc)
{
if (gpio_read(GPIO_PORT_E, GPIO_PIN_6) && jc->uart == UART_C)
return;
else if (gpio_read(GPIO_PORT_H, GPIO_PIN_6) && jc->uart == UART_B)
return;
// Check if device stopped sending data.
u32 uart_irq = uart_get_IIR(jc->uart);
if (uart_irq != UART_IIR_REDI)
return;
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
// Check valid size and uart reply magic.
if (len > 7 && !memcmp(jc->buf, "\x19\x81\x03", 3))
{
jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)(jc->buf);
jc_uart_pkt_parse(jc, jc->buf, pkt->uart_hdr.total_size_lsb + sizeof(jc_uart_hdr_t));
}
}
static bool jc_send_init_rumble(joycon_ctxt_t *jc)
{
// Send init rumble or request nx pad status report.
if ((jc_r.connected && !jc_r.rumble_sent) || (jc_l.connected && !jc_l.rumble_sent))
{
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
jc_send_hid_cmd(jc->uart, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0);
if (jc_l.connected)
jc_l.rumble_sent = true;
if (jc_r.connected)
jc_r.rumble_sent = true;
if (jc->uart != UART_B)
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
else
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
return 1;
}
return 0;
}
static void jc_req_nx_pad_status(joycon_ctxt_t *jc)
{
bool is_nxpad = !(jc->type & JC_ID_HORI);
if (is_nxpad)
{
bool sent_rumble = jc_send_init_rumble(jc);
if (sent_rumble)
return;
}
if (jc->last_status_req_time > get_tmr_ms() || !jc->connected)
return;
// Turn off Joy-Con detect.
if (jc->uart == UART_B)
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
else
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
if (is_nxpad)
joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status));
else
joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status));
// Turn Joy-Con detect on.
if (jc->uart == UART_B)
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
else
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
jc->last_status_req_time = get_tmr_ms() + 15;
}
static bool _jc_validate_pairing_info(u8 *buf, bool *is_hos)
{
u8 crc = 0;
for (u32 i = 0; i < 0x22; i++)
crc += buf[4 + i];
crc += 0x68; // Host is Switch.
if ((crc ^ 0x55) == buf[2])
*is_hos = true;
crc -= 0x68;
crc += 0x08; // Host is PC.
if (*is_hos || (crc ^ 0x55) == buf[2])
return true;
return false;
}
jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos)
{
u8 retries;
jc_bt_conn_t *bt_conn;
if (!jc_init_done)
return NULL;
bt_conn = &jc_gamepad.bt_conn_l;
memset(bt_conn->host_mac, 0, 6);
memset(bt_conn->ltk, 0, 16);
bt_conn = &jc_gamepad.bt_conn_r;
memset(bt_conn->host_mac, 0, 6);
memset(bt_conn->ltk, 0, 16);
while (jc_l.last_status_req_time > get_tmr_ms())
{
jc_rcv_pkt(&jc_r);
jc_rcv_pkt(&jc_l);
}
jc_hid_in_spi_read_t subcmd_data_l;
subcmd_data_l.addr = 0x2000;
subcmd_data_l.size = 0x1A;
jc_hid_in_spi_read_t subcmd_data_r;
subcmd_data_r.addr = 0x2000;
subcmd_data_r.size = 0x1A;
// Turn off Joy-Con detect.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
bool jc_r_found = jc_r.connected ? false : true;
bool jc_l_found = jc_l.connected ? false : true;
u32 total_retries = 10;
retry:
retries = 10;
while (retries)
{
u32 time_now = get_tmr_ms();
if ((!jc_l_found && jc_l.last_status_req_time < time_now) || (!jc_r_found && jc_r.last_status_req_time < time_now))
{
if (!jc_l_found)
{
jc_send_hid_cmd(jc_l.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5);
jc_l.last_status_req_time = get_tmr_ms() + 15;
}
if (!jc_r_found)
{
jc_send_hid_cmd(jc_r.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5);
jc_r.last_status_req_time = get_tmr_ms() + 15;
}
retries--;
}
if (!jc_l_found)
{
memset(jc_l.buf, 0, 0x100);
jc_rcv_pkt(&jc_l);
bool is_hos = false;
if (_jc_validate_pairing_info(&jc_l.buf[SPI_READ_OFFSET], &is_hos))
{
bool is_active = jc_l.buf[SPI_READ_OFFSET] == 0x95;
if (!is_active)
subcmd_data_l.addr += 0x26; // Get next slot.
else
jc_l_found = true; // Entry is active.
if (jc_l_found && is_hos)
*is_l_hos = true;
}
}
if (!jc_r_found)
{
memset(jc_r.buf, 0, 0x100);
jc_rcv_pkt(&jc_r);
bool is_hos = false;
if (_jc_validate_pairing_info(&jc_r.buf[SPI_READ_OFFSET], &is_hos))
{
bool is_active = jc_r.buf[SPI_READ_OFFSET] == 0x95;
if (!is_active)
subcmd_data_r.addr += 0x26; // Get next slot.
else
jc_r_found = true; // Entry is active.
if (jc_r_found && is_hos)
*is_r_hos = true;
}
}
if (jc_l_found && jc_r_found)
break;
}
if (!jc_l_found || !jc_r_found)
{
if (total_retries)
{
total_retries--;
goto retry;
}
if (!jc_l_found)
{
bt_conn = &jc_gamepad.bt_conn_l;
memset(bt_conn->host_mac, 0, 6);
memset(bt_conn->ltk, 0, 16);
}
if (!jc_r_found)
{
bt_conn = &jc_gamepad.bt_conn_r;
memset(bt_conn->host_mac, 0, 6);
memset(bt_conn->ltk, 0, 16);
}
}
// Turn Joy-Con detect on.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
return &jc_gamepad;
}
void jc_deinit()
{
// Disable power.
jc_power_supply(UART_B, false);
jc_power_supply(UART_C, false);
// Turn off Joy-Con detect.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
// Send sleep command.
u8 data = HCI_STATE_SLEEP;
if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
{
jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1);
jc_rcv_pkt(&jc_r);
}
if (jc_l.connected && !(jc_l.type & JC_ID_HORI))
{
jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
jc_rcv_pkt(&jc_l);
}
// Disable UART B and C clocks.
clock_disable_uart(UART_B);
clock_disable_uart(UART_C);
}
static void jc_init_conn(joycon_ctxt_t *jc)
{
if (((u32)get_tmr_ms() - jc->last_received_time) > 1000)
{
jc_power_supply(jc->uart, true);
// Turn off Joy-Con detect.
if (jc->uart == UART_B)
{
jc_gamepad.buttons &= ~JC_BTN_MASK_R;
jc_gamepad.conn_r = false;
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
}
else
{
jc_gamepad.buttons &= ~JC_BTN_MASK_L;
jc_gamepad.conn_l = false;
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
}
uart_init(jc->uart, 1000000);
uart_invert(jc->uart, true, UART_INVERT_TXD);
uart_set_IIR(jc->uart);
joycon_send_raw(jc->uart, init_jc, 4);
joycon_send_raw(jc->uart, init_handshake, sizeof(init_handshake));
msleep(5);
jc_rcv_pkt(jc);
joycon_send_raw(jc->uart, init_get_info, sizeof(init_get_info));
msleep(5);
jc_rcv_pkt(jc);
if (!(jc->type & JC_ID_HORI))
{
joycon_send_raw(jc->uart, init_finalize, sizeof(init_finalize));
msleep(5);
jc_rcv_pkt(jc);
}
// Turn Joy-Con detect on.
if (jc->uart == UART_B)
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
else
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
jc->last_received_time = get_tmr_ms();
if (jc->connected)
jc_power_supply(jc->uart, false);
}
}
static void jc_conn_check()
{
// Check if a Joy-Con was disconnected.
if (gpio_read(GPIO_PORT_E, GPIO_PIN_6))
{
jc_power_supply(UART_C, false);
hid_pkt_inc = 0;
jc_l.connected = false;
jc_l.rumble_sent = false;
jc_gamepad.buttons &= ~JC_BTN_MASK_L;
jc_gamepad.conn_l = false;
jc_gamepad.batt_info_l = 0;
jc_gamepad.bt_conn_l.type = 0;
}
if (gpio_read(GPIO_PORT_H, GPIO_PIN_6))
{
jc_power_supply(UART_B, false);
hid_pkt_inc = 0;
jc_r.connected = false;
jc_r.rumble_sent = false;
jc_gamepad.buttons &= ~JC_BTN_MASK_R;
jc_gamepad.conn_r = false;
jc_gamepad.batt_info_r = 0;
jc_gamepad.bt_conn_r.type = 0;
}
}
void jc_power_supply(u8 uart, bool enable)
{
if (enable)
{
if (regulator_5v_get_dev_enabled(1 << uart))
return;
regulator_5v_enable(1 << uart);
if (jc_init_done)
{
if (uart == UART_C)
gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_HIGH);
else
gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_HIGH);
return;
}
if (uart == UART_C)
{
// Joy-Con(L) Charge Detect.
PINMUX_AUX(PINMUX_AUX_SPDIF_IN) = PINMUX_PULL_DOWN | 1;
gpio_config(GPIO_PORT_CC, GPIO_PIN_3, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_3, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_HIGH);
}
else
{
// Joy-Con(R) Charge Detect.
PINMUX_AUX(PINMUX_AUX_GPIO_PK3) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN | 2;
gpio_config(GPIO_PORT_K, GPIO_PIN_3, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_K, GPIO_PIN_3, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_HIGH);
}
}
else
{
if (!regulator_5v_get_dev_enabled(1 << uart))
return;
regulator_5v_disable(1 << uart);
if (uart == UART_C)
gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW);
else
gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_LOW);
}
}
void jc_init_hw()
{
jc_l.uart = UART_C;
jc_r.uart = UART_B;
#if !defined(DEBUG_UART_PORT) || !(DEBUG_UART_PORT)
if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG)
return;
jc_power_supply(UART_C, true);
jc_power_supply(UART_B, true);
// Joy-Con (R) IsAttached.
PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO);
// Joy-Con (L) IsAttached.
PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO);
// Configure pinmuxing for UART B and C.
pinmux_config_uart(UART_B);
pinmux_config_uart(UART_C);
// Ease the stress to APB.
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
// Enable UART B and C clocks.
clock_enable_uart(UART_B);
clock_enable_uart(UART_C);
// Restore OC.
bpmp_clk_rate_set(prev_fid);
// Turn Joy-Con detect on.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
jc_init_done = true;
#endif
}
jc_gamepad_rpt_t *joycon_poll()
{
if (!jc_init_done)
return NULL;
if (!gpio_read(GPIO_PORT_H, GPIO_PIN_6))
jc_init_conn(&jc_r);
if (!gpio_read(GPIO_PORT_E, GPIO_PIN_6))
jc_init_conn(&jc_l);
if (!gpio_read(GPIO_PORT_H, GPIO_PIN_6))
jc_req_nx_pad_status(&jc_r);
if (!gpio_read(GPIO_PORT_E, GPIO_PIN_6))
jc_req_nx_pad_status(&jc_l);
if (!gpio_read(GPIO_PORT_H, GPIO_PIN_6))
jc_rcv_pkt(&jc_r);
if (!gpio_read(GPIO_PORT_E, GPIO_PIN_6))
jc_rcv_pkt(&jc_l);
jc_conn_check();
return &jc_gamepad;
}

98
bdk/input/joycon.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* Ambient light sensor driver for Nintendo Switch's Rohm BH1730
*
* Copyright (c) 2018 CTCaer
*
* 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 __JOYCON_H_
#define __JOYCON_H_
#include <utils/types.h>
#define JC_BTNS_DIRECTION_PAD 0xF0000
#define JC_BTNS_PREV_NEXT 0x800080
#define JC_BTNS_ENTER 0x400008
#define JC_BTNS_ESC 0x4
#define JC_BTNS_ALL (JC_BTNS_PREV_NEXT | JC_BTNS_ENTER | JC_BTNS_DIRECTION_PAD | JC_BTNS_ESC)
typedef struct _jc_bt_conn_t
{
u8 type;
u8 mac[6];
u8 host_mac[6];
u8 ltk[16];
} jc_bt_conn_t;
typedef struct _jc_gamepad_rpt_t
{
union
{
struct
{
// Joy-Con (R).
u32 y:1;
u32 x:1;
u32 b:1;
u32 a:1;
u32 sr_r:1;
u32 sl_r:1;
u32 r:1;
u32 zr:1;
// Shared
u32 minus:1;
u32 plus:1;
u32 r3:1;
u32 l3:1;
u32 home:1;
u32 cap:1;
u32 pad:1;
u32 wired:1;
// Joy-Con (L).
u32 down:1;
u32 up:1;
u32 right:1;
u32 left:1;
u32 sr_l:1;
u32 sl_l:1;
u32 l:1;
u32 zl:1;
};
u32 buttons;
};
u16 lstick_x;
u16 lstick_y;
u16 rstick_x;
u16 rstick_y;
bool center_stick_l;
bool center_stick_r;
bool conn_l;
bool conn_r;
u8 batt_info_l;
u8 batt_info_r;
jc_bt_conn_t bt_conn_l;
jc_bt_conn_t bt_conn_r;
} jc_gamepad_rpt_t;
void jc_power_supply(u8 uart, bool enable);
void jc_init_hw();
void jc_deinit();
jc_gamepad_rpt_t *joycon_poll();
jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos);
#endif

461
bdk/input/touch.c Normal file
View File

@@ -0,0 +1,461 @@
/*
* Touch driver for Nintendo Switch's STM FingerTip S (4CD60D) touch controller
*
* Copyright (c) 2018 langerhans
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <soc/clock.h>
#include <soc/i2c.h>
#include <soc/pinmux.h>
#include <power/max7762x.h>
#include <soc/gpio.h>
#include <soc/t210.h>
#include <utils/btn.h>
#include <utils/util.h>
#include "touch.h"
#include <gfx_utils.h>
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
static touch_panel_info_t _panels[] =
{
{ 0, 1, 1, 1, "NISSHA NFT-K12D" },
{ 1, 0, 1, 1, "GiS GGM6 B2X" },
{ 2, 0, 0, 0, "NISSHA NBF-K9A" },
{ 3, 1, 0, 0, "GiS 5.5\"" },
{ 4, 0, 0, 1, "Samsung BH2109" },
{ -1, 1, 0, 1, "GiS VA 6.2\"" }
};
static int touch_command(u8 cmd, u8 *buf, u8 size)
{
int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd, buf, size);
if (!res)
return 1;
return 0;
}
static int touch_read_reg(u8 *cmd, u32 csize, u8 *buf, u32 size)
{
int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd[0], &cmd[1], csize - 1);
if (res)
res = i2c_recv_buf(buf, size, I2C_3, STMFTS_I2C_ADDR);
if (!res)
return 1;
return 0;
}
static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf)
{
u32 timer = get_tmr_ms() + timeout;
while (true)
{
u8 tmp[8] = {0};
i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT);
if (tmp[1] == event && tmp[2] == status)
{
if (buf)
memcpy(buf, &tmp[3], 5);
return 0;
}
if (get_tmr_ms() > timer)
return 1;
}
}
#define X_REAL_MAX 1264
#define Y_REAL_MAX 704
#define EDGE_OFFSET 15
static void _touch_compensate_limits(touch_event *event, bool touching)
{
event->x = MAX(event->x, EDGE_OFFSET);
event->x = MIN(event->x, X_REAL_MAX);
event->x -= EDGE_OFFSET;
u32 x_adj = (1280 * 1000) / (X_REAL_MAX - EDGE_OFFSET);
event->x = ((u32)event->x * x_adj) / 1000;
if (touching)
{
event->y = MAX(event->y, EDGE_OFFSET);
event->y = MIN(event->y, Y_REAL_MAX);
event->y -= EDGE_OFFSET;
u32 y_adj = (720 * 1000) / (Y_REAL_MAX - EDGE_OFFSET);
event->y = ((u32)event->y * y_adj) / 1000;
}
}
static void _touch_process_contact_event(touch_event *event, bool touching)
{
event->x = (event->raw[2] << 4) | ((event->raw[4] & STMFTS_MASK_Y_LSB) >> 4);
// Normally, GUI elements have bigger horizontal estate.
// Avoid parsing y axis when finger is removed to minimize touch noise.
if (touching)
{
event->y = (event->raw[3] << 4) | (event->raw[4] & STMFTS_MASK_X_MSB);
event->z = event->raw[5] | (event->raw[6] << 8);
event->z = event->z << 6;
u16 tmp = 0x40;
if ((event->raw[7] & 0x3F) != 1 && (event->raw[7] & 0x3F) != 0x3F)
tmp = event->raw[7] & 0x3F;
event->z /= tmp + 0x40;
event->fingers = ((event->raw[1] & STMFTS_MASK_TOUCH_ID) >> 4) + 1;
}
else
event->fingers = 0;
_touch_compensate_limits(event, touching);
}
static void _touch_parse_event(touch_event *event)
{
event->type = event->raw[1] & STMFTS_MASK_EVENT_ID;
switch (event->type)
{
case STMFTS_EV_MULTI_TOUCH_ENTER:
case STMFTS_EV_MULTI_TOUCH_MOTION:
_touch_process_contact_event(event, true);
if (event->z < 255) // Reject palm rest.
event->touch = true;
else
{
event->touch = false;
event->type = STMFTS_EV_MULTI_TOUCH_LEAVE;
}
break;
case STMFTS_EV_MULTI_TOUCH_LEAVE:
event->touch = false;
_touch_process_contact_event(event, false);
break;
case STMFTS_EV_NO_EVENT:
if (event->touch)
event->type = STMFTS_EV_MULTI_TOUCH_MOTION;
break;
default:
if (event->touch && event->raw[0] == STMFTS_EV_MULTI_TOUCH_MOTION)
event->type = STMFTS_EV_MULTI_TOUCH_MOTION;
else
event->type = STMFTS_EV_MULTI_TOUCH_LEAVE;
}
// gfx_con_setpos(0, 300);
// DPRINTF("x = %d \ny = %d \nz = %d \n", event->x, event->y, event->z);
// DPRINTF("0 = %02X\n1 = %02X\n2 = %02X\n3 = %02X\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]);
// DPRINTF("4 = %02X\n5 = %02X\n6 = %02X\n7 = %02X\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]);
}
void touch_poll(touch_event *event)
{
i2c_recv_buf_small(event->raw, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_LATEST_EVENT);
_touch_parse_event(event);
}
touch_event touch_poll_wait()
{
touch_event event;
do
{
touch_poll(&event);
} while (event.type != STMFTS_EV_MULTI_TOUCH_LEAVE);
return event;
}
touch_info touch_get_info()
{
touch_info info;
u8 buf[8];
memset(&buf, 0, 8);
i2c_recv_buf_small(buf, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_INFO);
info.chip_id = buf[0] << 8 | buf[1];
info.fw_ver = buf[2] << 8 | buf[3];
info.config_id = buf[4];
info.config_ver = buf[5];
//DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02X, Cfg Ver: %d\n",
// info.chip_id, info.fw_ver >> 8, info.fw_ver & 0xFF, info.config_id, info.config_ver);
return info;
}
touch_panel_info_t *touch_get_panel_vendor()
{
u8 buf[5] = {0};
u8 cmd = STMFTS_VENDOR_GPIO_STATE;
static touch_panel_info_t panel_info = { -2, 0, 0, 0, ""};
if (touch_command(STMFTS_VENDOR, &cmd, 1))
return NULL;
if (touch_wait_event(STMFTS_EV_VENDOR, STMFTS_VENDOR_GPIO_STATE, 2000, buf))
return NULL;
for (u32 i = 0; i < ARRAY_SIZE(_panels); i++)
{
touch_panel_info_t *panel = &_panels[i];
if (buf[0] == panel->gpio0 && buf[1] == panel->gpio1 && buf[2] == panel->gpio2)
return panel;
}
// Touch panel not found, return current gpios.
panel_info.gpio0 = buf[0];
panel_info.gpio1 = buf[1];
panel_info.gpio2 = buf[2];
return &panel_info;
}
int touch_get_fw_info(touch_fw_info_t *fw)
{
u8 buf[8] = {0};
memset(fw, 0, sizeof(touch_fw_info_t));
// Get fw address info.
u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 };
int res = touch_read_reg(cmd, 3, buf, 3);
if (!res)
{
// Get fw info.
cmd[1] = buf[2]; cmd[2] = buf[1];
res = touch_read_reg(cmd, 3, buf, 8);
if (!res)
{
fw->fw_id = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4];
fw->ftb_ver = (buf[6] << 8) | buf[5];
}
cmd[2]++;
res = touch_read_reg(cmd, 3, buf, 8);
if (!res)
fw->fw_rev = (buf[7] << 8) | buf[6];
}
return res;
}
int touch_sys_reset()
{
u8 cmd[3] = { 0, 0x28, 0x80 }; // System reset cmd.
for (u8 retries = 0; retries < 3; retries++)
{
if (touch_command(STMFTS_WRITE_REG, cmd, 3))
{
msleep(10);
continue;
}
msleep(10);
if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL))
continue;
else
return 0;
}
return 1;
}
int touch_panel_ito_test(u8 *err)
{
int res = 0;
// Reset touchscreen module.
if (touch_sys_reset())
return res;
// Do ITO Production test.
u8 cmd[2] = { 1, 0 };
if (touch_command(STMFTS_ITO_CHECK, cmd, 2))
return res;
u32 timer = get_tmr_ms() + 2000;
while (true)
{
u8 tmp[8] = {0};
i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT);
if (tmp[1] == 0xF && tmp[2] == 0x5)
{
if (err)
{
err[0] = tmp[3];
err[1] = tmp[4];
}
res = 1;
break;
}
if (get_tmr_ms() > timer)
break;
}
// Reset touchscreen module.
touch_sys_reset();
return res;
}
int touch_get_fb_info(u8 *buf)
{
u8 tmp[5];
u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0 };
int res = 0;
for (u32 i = 0; i < 0x10000; i += 4)
{
if (!res)
{
cmd[1] = (i >> 8) & 0xFF;
cmd[2] = i & 0xFF;
memset(tmp, 0xCC, 5);
res = touch_read_reg(cmd, 3, tmp, 5);
memcpy(&buf[i], tmp + 1, 4);
}
}
return res;
}
int touch_sense_enable()
{
// Switch sense mode and enable multi-touch sensing.
u8 cmd = STMFTS_FINGER_MODE;
if (touch_command(STMFTS_SWITCH_SENSE_MODE, &cmd, 1))
return 0;
if (touch_command(STMFTS_MS_MT_SENSE_ON, NULL, 0))
return 0;
if (touch_command(STMFTS_CLEAR_EVENT_STACK, NULL, 0))
return 0;
return 1;
}
int touch_execute_autotune()
{
// Reset touchscreen module.
if (touch_sys_reset())
return 0;
// Trim low power oscillator.
if (touch_command(STMFTS_LP_TIMER_CALIB, NULL, 0))
return 0;
msleep(200);
// Apply Mutual Sense Compensation tuning.
if (touch_command(STMFTS_MS_CX_TUNING, NULL, 0))
return 0;
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000, NULL))
return 0;
// Apply Self Sense Compensation tuning.
if (touch_command(STMFTS_SS_CX_TUNING, NULL, 0))
return 0;
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000, NULL))
return 0;
// Save Compensation data to EEPROM.
if (touch_command(STMFTS_SAVE_CX_TUNING, NULL, 0))
return 0;
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000, NULL))
return 0;
return touch_sense_enable();
}
static int touch_init()
{
// Initialize touchscreen module.
if (touch_sys_reset())
return 0;
return touch_sense_enable();
}
int touch_power_on()
{
// Enable LDO6 for touchscreen AVDD supply.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
max7762x_regulator_enable(REGULATOR_LDO6, true);
// Configure touchscreen VDD GPIO.
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH);
// IRQ and more.
// PINMUX_AUX(PINMUX_AUX_TOUCH_INT) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 3;
// gpio_config(GPIO_PORT_X, GPIO_PIN_1, GPIO_MODE_GPIO);
// gpio_write(GPIO_PORT_X, GPIO_PIN_1, GPIO_LOW);
// Configure Touscreen and GCAsic shared GPIO.
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2;
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
// Initialize I2C3.
pinmux_config_i2c(I2C_3);
clock_enable_i2c(I2C_3);
i2c_init(I2C_3);
// Wait for the touchscreen module to get ready.
touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL);
// Check for forced boot time calibration.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
{
u8 err[2];
if (touch_panel_ito_test(err))
if (!err[0] && !err[1])
return touch_execute_autotune();
}
// Initialize touchscreen.
u32 retries = 3;
while (retries)
{
if (touch_init())
return 1;
retries--;
}
return 0;
}
void touch_power_off()
{
// Disable touchscreen power.
gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW);
// Disables LDO6 for touchscreen VDD, AVDD supply
max7762x_regulator_enable(REGULATOR_LDO6, false);
clock_disable_i2c(I2C_3);
}

176
bdk/input/touch.h Normal file
View File

@@ -0,0 +1,176 @@
/*
* Touch driver for Nintendo Switch's STM FingerTip S (4CD60D) touch controller
*
* Copyright (c) 2018 langerhans
* Copyright (c) 2018-2020 CTCaer
*
* 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 __TOUCH_H_
#define __TOUCH_H_
#include <utils/types.h>
#define STMFTS_I2C_ADDR 0x49
/* I2C commands */
#define STMFTS_READ_INFO 0x80
#define STMFTS_READ_STATUS 0x84
#define STMFTS_READ_ONE_EVENT 0x85
#define STMFTS_READ_ALL_EVENT 0x86
#define STMFTS_LATEST_EVENT 0x87
#define STMFTS_SLEEP_IN 0x90
#define STMFTS_SLEEP_OUT 0x91
#define STMFTS_MS_MT_SENSE_OFF 0x92
#define STMFTS_MS_MT_SENSE_ON 0x93
#define STMFTS_SS_HOVER_SENSE_OFF 0x94
#define STMFTS_SS_HOVER_SENSE_ON 0x95
#define STMFTS_LP_TIMER_CALIB 0x97
#define STMFTS_MS_KEY_SENSE_OFF 0x9A
#define STMFTS_MS_KEY_SENSE_ON 0x9B
#define STMFTS_SYSTEM_RESET 0xA0
#define STMFTS_CLEAR_EVENT_STACK 0xA1
#define STMFTS_FULL_FORCE_CALIBRATION 0xA2
#define STMFTS_MS_CX_TUNING 0xA3
#define STMFTS_SS_CX_TUNING 0xA4
#define STMFTS_ITO_CHECK 0xA7
#define STMFTS_RELEASEINFO 0xAA
#define STMFTS_WRITE_REG 0xB6
#define STMFTS_SWITCH_SENSE_MODE 0xC3
#define STMFTS_NOISE_WRITE 0xC7
#define STMFTS_NOISE_READ 0xC8
#define STMFTS_RW_FRAMEBUFFER_REG 0xD0
#define STMFTS_SAVE_CX_TUNING 0xFC
#define STMFTS_DETECTION_CONFIG 0xB0
#define STMFTS_REQU_COMP_DATA 0xB8
#define STMFTS_VENDOR 0xCF
#define STMFTS_FLASH_UNLOCK 0xF7
#define STMFTS_FLASH_WRITE_64K 0xF8
#define STMFTS_FLASH_STATUS 0xF9
#define STMFTS_FLASH_OP 0xFA
#define STMFTS_UNK5 0x62
/* cmd parameters */
#define STMFTS_VENDOR_GPIO_STATE 0x01
#define STMFTS_VENDOR_SENSE_MODE 0x02
#define STMFTS_STYLUS_MODE 0x00
#define STMFTS_FINGER_MODE 0x01
#define STMFTS_HOVER_MODE 0x02
/* events */
#define STMFTS_EV_NO_EVENT 0x00
#define STMFTS_EV_MULTI_TOUCH_DETECTED 0x02
#define STMFTS_EV_MULTI_TOUCH_ENTER 0x03
#define STMFTS_EV_MULTI_TOUCH_LEAVE 0x04
#define STMFTS_EV_MULTI_TOUCH_MOTION 0x05
#define STMFTS_EV_HOVER_ENTER 0x07
#define STMFTS_EV_HOVER_LEAVE 0x08
#define STMFTS_EV_HOVER_MOTION 0x09
#define STMFTS_EV_KEY_STATUS 0x0e
#define STMFTS_EV_ERROR 0x0f
#define STMFTS_EV_NOISE_READ 0x17
#define STMFTS_EV_NOISE_WRITE 0x18
#define STMFTS_EV_VENDOR 0x20
#define STMFTS_EV_CONTROLLER_READY 0x10
#define STMFTS_EV_STATUS 0x16
#define STMFTS_EV_DEBUG 0xDB
#define STMFTS_EV_STATUS_MS_CX_TUNING_DONE 1
#define STMFTS_EV_STATUS_SS_CX_TUNING_DONE 2
#define STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE 4
/* multi touch related event masks */
#define STMFTS_MASK_EVENT_ID 0x0F
#define STMFTS_MASK_TOUCH_ID 0xF0
#define STMFTS_MASK_LEFT_EVENT 0x0F
#define STMFTS_MASK_X_MSB 0x0F
#define STMFTS_MASK_Y_LSB 0xF0
/* key related event masks */
#define STMFTS_MASK_KEY_NO_TOUCH 0x00
#define STMFTS_MASK_KEY_MENU 0x01
#define STMFTS_MASK_KEY_BACK 0x02
#define STMFTS_EVENT_SIZE 8
#define STMFTS_STACK_DEPTH 32
#define STMFTS_DATA_MAX_SIZE (STMFTS_EVENT_SIZE * STMFTS_STACK_DEPTH)
#define STMFTS_MAX_FINGERS 10
typedef enum _touch_ito_error {
ITO_NO_ERROR = 0,
ITO_FORCE_OPEN,
ITO_SENSE_OPEN,
ITO_FORCE_SHRT_GND,
ITO_SENSE_SHRT_GND,
ITO_FORCE_SHRT_VCM,
ITO_SENSE_SHRT_VCM,
ITO_FORCE_SHRT_FORCE,
ITO_SENSE_SHRT_SENSE,
ITO_F2E_SENSE,
ITO_FPC_FORCE_OPEN,
ITO_FPC_SENSE_OPEN,
ITO_KEY_FORCE_OPEN,
ITO_KEY_SENSE_OPEN,
ITO_RESERVED0,
ITO_RESERVED1,
ITO_RESERVED2,
ITO_MAX_ERR_REACHED = 0xFF
} touch_ito_error;
typedef struct _touch_event {
u8 raw[8];
u16 type; // Event type.
u16 x; // Horizontal coordinates.
u16 y; // Vertical coordinates.
u32 z;
u8 fingers;
bool touch;
} touch_event;
typedef struct _touch_panel_info_t
{
u8 idx;
u8 gpio0;
u8 gpio1;
u8 gpio2;
char *vendor;
} touch_panel_info_t;
typedef struct _touch_info {
u16 chip_id;
u16 fw_ver;
u16 config_id;
u16 config_ver;
} touch_info;
typedef struct _touch_fw_info_t {
u32 fw_id;
u16 ftb_ver;
u16 fw_rev;
} touch_fw_info_t;
void touch_poll(touch_event *event);
touch_event touch_poll_wait();
touch_panel_info_t *touch_get_panel_vendor();
int touch_get_fw_info(touch_fw_info_t *fw);
touch_info touch_get_info();
int touch_panel_ito_test(u8 *err);
int touch_execute_autotune();
int touch_sense_enable();
int touch_power_on();
void touch_power_off();
#endif /* __TOUCH_H_ */

90
bdk/libs/fatfs/diskio.h Normal file
View File

@@ -0,0 +1,90 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#include <utils/types.h>
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
typedef enum {
DRIVE_SD = 0,
DRIVE_RAM = 1,
DRIVE_EMMC = 2,
DRIVE_BIS = 3,
DRIVE_EMU = 4
} DDRIVE;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define SET_SECTOR_COUNT 1 /* Set media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
#define SET_SECTOR_OFFSET 5 /* Set media logical offset */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

6937
bdk/libs/fatfs/ff.c Normal file

File diff suppressed because it is too large Load Diff

391
bdk/libs/fatfs/ff.h Normal file
View File

@@ -0,0 +1,391 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.13c /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2018, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/
/----------------------------------------------------------------------------*/
#ifndef FF_DEFINED
#define FF_DEFINED 86604 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include <utils/types.h> /* Basic integer types */
#include <fatfs_cfg.h> /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U ## x
#define _TEXT(x) U ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size variables */
#if FF_FS_EXFAT
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if FF_MAX_SS != FF_MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if FF_USE_LFN
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if FF_FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if FF_FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#if FF_FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
#if FF_FS_EXFAT
DWORD bitbase; /* Allocation bitmap base sector */
#endif
DWORD winsect; /* Current sector appearing in the win[] */
} FATFS;
/* Object ID and allocation information (FFOBJID) */
typedef struct {
FATFS* fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if FF_FS_EXFAT
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */
#endif
#if FF_FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} FFOBJID;
/* File object structure (FIL) */
typedef struct {
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !FF_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
#endif
#if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FFOBJID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector (0:Read operation has terminated) */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if FF_USE_LFN
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if FF_USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
#if FF_FASTFS
FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */
FR_CLTBL_NO_INIT /* (20) The cluster table for fast seek/read/write was not created */
#else
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
#endif
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */
FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, FSIZE_t ofs); /* Expand file and populate cluster table */
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
FRESULT f_fdisk_mod (BYTE pdrv, const DWORD* szt, void* work); // Modded version of f_fdisk that works:tm:
FRESULT f_setcp (WORD cp); /* Set current code page */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);
#endif
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
#endif
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#define AM_DEV 0x40 /* Device */
#define AM_RVD 0x80 /* Reserved */
#ifdef __cplusplus
}
#endif
#endif /* FF_DEFINED */

625
bdk/libs/fatfs/ffunicode.c Normal file
View File

@@ -0,0 +1,625 @@
/*------------------------------------------------------------------------*/
/* Unicode handling functions for FatFs R0.13c */
/*------------------------------------------------------------------------*/
/* This module will occupy a huge memory in the .const section when the /
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
/ utilitiy for the code conversion, this module should be modified to use /
/ that function to avoid silly memory consumption. /
/-------------------------------------------------------------------------*/
/*
/ Copyright (C) 2018, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
*/
#include "ff.h"
#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */
#if FF_DEFINED != 86604 /* Revision ID */
#error Wrong include file (ff.h).
#endif
#define MERGE2(a, b) a ## b
#define CVTBL(tbl, cp) MERGE2(tbl, cp)
/*------------------------------------------------------------------------*/
/* Code Conversion Tables */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0
static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0
static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0
static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0
static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0
static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0
static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0
static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0
static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0
static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0
static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0
static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0
static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0
static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0
static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F,
0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9,
0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9,
0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1,
0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000
};
#endif
#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0
static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0
static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
};
#endif
#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0
static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3,
0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580,
0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384,
0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0
};
#endif
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* SBCS fixed code page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
WCHAR c = 0;
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else { /* Non-ASCII */
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
for (c = 0; c < 0x80 && uni != p[c]; c++) ;
c = (c + 0x80) & 0xFF;
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR oem, /* OEM code to be converted */
WORD cp /* Code page for the conversion */
)
{
WCHAR c = 0;
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
if (oem < 0x100) c = p[oem - 0x80];
}
}
return c;
}
#endif
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* DBCS fixed code page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE >= 900
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0, uc;
UINT i = 0, n, li, hi;
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else { /* Non-ASCII */
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
uc = (WCHAR)uni;
p = CVTBL(uni2oem, FF_CODE_PAGE);
hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1;
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (uc == p[i * 2]) break;
if (uc > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR oem, /* OEM code to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0;
UINT i = 0, n, li, hi;
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
if (cp == FF_CODE_PAGE) { /* Is it valid code page? */
p = CVTBL(oem2uni, FF_CODE_PAGE);
hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1;
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (oem == p[i * 2]) break;
if (oem > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
}
return c;
}
#endif
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for dynamic code page configuration */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 0
static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0};
static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0};
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0, uc;
UINT i, n, li, hi;
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else { /* Non-ASCII */
if (uni < 0x10000) { /* Is it in BMP? */
uc = (WCHAR)uni;
p = 0;
if (cp < 900) { /* SBCS */
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */
p = cp_table[i];
if (p) { /* Is it valid code page ? */
for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */
c = (c + 0x80) & 0xFF;
}
} else { /* DBCS */
switch (cp) { /* Get conversion table */
case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break;
case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break;
case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break;
case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break;
}
if (p) { /* Is it valid code page? */
li = 0;
for (n = 16; n; n--) { /* Find OEM code */
i = li + (hi - li) / 2;
if (uc == p[i * 2]) break;
if (uc > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
}
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0;
UINT i, n, li, hi;
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
p = 0;
if (cp < 900) { /* SBCS */
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */
p = cp_table[i];
if (p) { /* Is it a valid CP ? */
if (oem < 0x100) c = p[oem - 0x80];
}
} else { /* DBCS */
switch (cp) {
case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break;
case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break;
case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break;
case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break;
}
if (p) {
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (oem == p[i * 2]) break;
if (oem > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
}
}
return c;
}
#endif
/*------------------------------------------------------------------------*/
/* Unicode up-case conversion */
/*------------------------------------------------------------------------*/
DWORD ff_wtoupper ( /* Returns up-converted code point */
DWORD uni /* Unicode code point to be up-converted */
)
{
const WORD *p;
WORD uc, bc, nc, cmd;
static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */
/* Basic Latin */
0x0061,0x031A,
/* Latin-1 Supplement */
0x00E0,0x0317,
0x00F8,0x0307,
0x00FF,0x0001,0x0178,
/* Latin Extended-A */
0x0100,0x0130,
0x0132,0x0106,
0x0139,0x0110,
0x014A,0x012E,
0x0179,0x0106,
/* Latin Extended-B */
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
0x01CD,0x0110,
0x01DD,0x0001,0x018E,
0x01DE,0x0112,
0x01F3,0x0003,0x01F1,0x01F4,0x01F4,
0x01F8,0x0128,
0x0222,0x0112,
0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241,
0x0246,0x010A,
/* IPA Extensions */
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
/* Greek, Coptic */
0x037B,0x0003,0x03FD,0x03FE,0x03FF,
0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A,
0x03B1,0x0311,
0x03C2,0x0002,0x03A3,0x03A3,
0x03C4,0x0308,
0x03CC,0x0003,0x038C,0x038E,0x038F,
0x03D8,0x0118,
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
/* Cyrillic */
0x0430,0x0320,
0x0450,0x0710,
0x0460,0x0122,
0x048A,0x0136,
0x04C1,0x010E,
0x04CF,0x0001,0x04C0,
0x04D0,0x0144,
/* Armenian */
0x0561,0x0426,
0x0000 /* EOT */
};
static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */
/* Phonetic Extensions */
0x1D7D,0x0001,0x2C63,
/* Latin Extended Additional */
0x1E00,0x0196,
0x1EA0,0x015A,
/* Greek Extended */
0x1F00,0x0608,
0x1F10,0x0606,
0x1F20,0x0608,
0x1F30,0x0608,
0x1F40,0x0606,
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F,
0x1F60,0x0608,
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
0x1F80,0x0608,
0x1F90,0x0608,
0x1FA0,0x0608,
0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
0x1FCC,0x0001,0x1FC3,
0x1FD0,0x0602,
0x1FE0,0x0602,
0x1FE5,0x0001,0x1FEC,
0x1FF3,0x0001,0x1FFC,
/* Letterlike Symbols */
0x214E,0x0001,0x2132,
/* Number forms */
0x2170,0x0210,
0x2184,0x0001,0x2183,
/* Enclosed Alphanumerics */
0x24D0,0x051A,
0x2C30,0x042F,
/* Latin Extended-C */
0x2C60,0x0102,
0x2C67,0x0106, 0x2C75,0x0102,
/* Coptic */
0x2C80,0x0164,
/* Georgian Supplement */
0x2D00,0x0826,
/* Full-width */
0xFF41,0x031A,
0x0000 /* EOT */
};
if (uni < 0x10000) { /* Is it in BMP? */
uc = (WORD)uni;
p = uc < 0x1000 ? cvt1 : cvt2;
for (;;) {
bc = *p++; /* Get the block base */
if (bc == 0 || uc < bc) break; /* Not matched? */
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
if (uc < bc + nc) { /* In the block? */
switch (cmd) {
case 0: uc = p[uc - bc]; break; /* Table conversion */
case 1: uc -= (uc - bc) & 1; break; /* Case pairs */
case 2: uc -= 16; break; /* Shift -16 */
case 3: uc -= 32; break; /* Shift -32 */
case 4: uc -= 48; break; /* Shift -48 */
case 5: uc -= 26; break; /* Shift -26 */
case 6: uc += 8; break; /* Shift +8 */
case 7: uc -= 80; break; /* Shift -80 */
case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */
}
break;
}
if (cmd == 0) p += nc; /* Skip table if needed */
}
uni = uc;
}
return uni;
}
#endif /* #if FF_USE_LFN */

373
bdk/libs/lv_conf.h Normal file
View File

@@ -0,0 +1,373 @@
/*
* Copyright (c) 2018 CTCaer
*
* 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 LV_CONF_H
#define LV_CONF_H
#include <utils/types.h>
#include <memory_map.h>
/*===================
Dynamic memory
*===================*/
/* Memory size which will be used by the library
* to store the graphical objects and other data */
#define LV_MEM_CUSTOM 0 /*1: use custom malloc/free, 0: use the built-in lv_mem_alloc/lv_mem_free*/
#if LV_MEM_CUSTOM == 0
# define LV_MEM_SIZE NYX_LV_MEM_SZ /*Size memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
# define LV_MEM_ATTR /*Complier prefix for big array declaration*/
# define LV_MEM_ADR NYX_LV_MEM_ADR /*Set an address for memory pool instead of allocation it as an array. Can be in external SRAM too.*/
# define LV_MEM_AUTO_DEFRAG 1 /*Automatically defrag on free*/
#else /*LV_MEM_CUSTOM*/
# define LV_MEM_CUSTOM_INCLUDE <mem/heap.h> /*Header for the dynamic memory function*/
# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/
# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/
#endif /*LV_MEM_CUSTOM*/
/* Garbage Collector settings
* Used if lvgl is binded to higher language and the memory is managed by that language */
#define LV_ENABLE_GC 0
#if LV_ENABLE_GC != 0
# define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/
# define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/
# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
#endif /* LV_ENABLE_GC */
/*===================
Graphical settings
*===================*/
/* Horizontal and vertical resolution of the library.*/
#define LV_HOR_RES (1280)
#define LV_VER_RES (720)
/* Dot Per Inch: used to initialize default sizes. E.g. a button with width = LV_DPI / 2 -> half inch wide
* (Not so important, you can adjust it to modify default sizes and spaces)*/
#define LV_DPI 100
/* Enable anti-aliasing (lines, and radiuses will be smoothed) */
#define LV_ANTIALIAS 1 /*1: Enable anti-aliasing*/
/*Screen refresh period in milliseconds*/
#define LV_REFR_PERIOD 33
/*-----------------
* VDB settings
*----------------*/
/* VDB (Virtual Display Buffer) is an internal graphics buffer.
* The GUI will be drawn into this buffer first and then
* the buffer will be passed to your `disp_drv.disp_flush` function to
* copy it to your frame buffer.
* VDB is required for: buffered drawing, opacity, anti-aliasing and shadows
* Learn more: https://docs.littlevgl.com/#Drawing*/
/* Size of the VDB in pixels. Typical size: ~1/10 screen. Must be >= LV_HOR_RES
* Setting it to 0 will disable VDB and `disp_drv.disp_fill` and `disp_drv.disp_map` functions
* will be called to draw to the frame buffer directly*/
#define LV_VDB_SIZE (LV_VER_RES * LV_HOR_RES)
/* Bit-per-pixel of VDB. Useful for monochrome or non-standard color format displays.
* Special formats are handled with `disp_drv.vdb_wr`)*/
#define LV_VDB_PX_BPP LV_COLOR_SIZE /*LV_COLOR_SIZE comes from LV_COLOR_DEPTH below to set 8, 16 or 32 bit pixel size automatically */
/* Place VDB to a specific address (e.g. in external RAM)
* 0: allocate automatically into RAM
* LV_VDB_ADR_INV: to replace it later with `lv_vdb_set_adr()`*/
#define LV_VDB_ADR NYX_LV_VDB_ADR
/* Use two Virtual Display buffers (VDB) to parallelize rendering and flushing
* The flushing should use DMA to write the frame buffer in the background */
#define LV_VDB_DOUBLE 0
/* Place VDB2 to a specific address (e.g. in external RAM)
* 0: allocate automatically into RAM
* LV_VDB_ADR_INV: to replace it later with `lv_vdb_set_adr()`*/
#define LV_VDB2_ADR 0
/* Using true double buffering in `disp_drv.disp_flush` you will always get the image of the whole screen.
* Your only task is to set the rendered image (`color_p` parameter) as frame buffer address or send it to your display.
* The best if you do in the blank period of you display to avoid tearing effect.
* Requires:
* - LV_VDB_SIZE = LV_HOR_RES * LV_VER_RES
* - LV_VDB_DOUBLE = 1
*/
#define LV_VDB_TRUE_DOUBLE_BUFFERED 0
/*=================
Misc. setting
*=================*/
/*Input device settings*/
#define LV_INDEV_READ_PERIOD 33 /*Input device read period in milliseconds*/
#define LV_INDEV_POINT_MARKER 0 /*Mark the pressed points (required: USE_LV_REAL_DRAW = 1)*/
#define LV_INDEV_DRAG_LIMIT 10 /*Drag threshold in pixels */
#define LV_INDEV_DRAG_THROW 20 /*Drag throw slow-down in [%]. Greater value means faster slow-down */
#define LV_INDEV_LONG_PRESS_TIME 400 /*Long press time in milliseconds*/
#define LV_INDEV_LONG_PRESS_REP_TIME 1000 //Fix keyb /*Repeated trigger period in long press [ms] */
/*Color settings*/
#define LV_COLOR_DEPTH 32 /*Color depth: 1/8/16/32*/
#define LV_COLOR_16_SWAP 0 /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
#define LV_COLOR_SCREEN_TRANSP 0 /*1: Enable screen transparency. Useful for OSD or other overlapping GUIs. Requires ARGB8888 colors*/
#define LV_COLOR_TRANSP LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma keying)*/
/*Text settings*/
#define LV_TXT_UTF8 0 /*Enable UTF-8 coded Unicode character usage */
#define LV_TXT_BREAK_CHARS " ,.;:-_" /*Can break texts on these chars*/
#define LV_TXT_LINE_BREAK_LONG_LEN 12 /* If a character is at least this long, will break wherever "prettiest" */
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 /* Minimum number of characters of a word to put on a line before a break */
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 1 /* Minimum number of characters of a word to put on a line after a break */
/*Feature usage*/
#define USE_LV_ANIMATION 1 /*1: Enable all animations*/
#define USE_LV_SHADOW 1 /*1: Enable shadows*/
#define USE_LV_GROUP 0 /*1: Enable object groups (for keyboards)*/
#define USE_LV_GPU 0 /*1: Enable GPU interface*/
#define USE_LV_REAL_DRAW 0 /*1: Enable function which draw directly to the frame buffer instead of VDB (required if LV_VDB_SIZE = 0)*/
#define USE_LV_FILESYSTEM 0 /*1: Enable file system (might be required for images*/
#define USE_LV_MULTI_LANG 0 /* Number of languages for labels to store (0: to disable this feature)*/
/*Compiler settings*/
#define LV_ATTRIBUTE_TICK_INC /* Define a custom attribute to `lv_tick_inc` function */
#define LV_ATTRIBUTE_TASK_HANDLER /* Define a custom attribute to `lv_task_handler` function */
#define LV_COMPILER_VLA_SUPPORTED 1 /* 1: Variable length array is supported*/
/*HAL settings*/
#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */
#if LV_TICK_CUSTOM == 1
#define LV_TICK_CUSTOM_INCLUDE <utils/util.h> /*Header for the sys time function*/
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (get_tmr_ms()) /*Expression evaluating to current systime in ms*/
#endif /*LV_TICK_CUSTOM*/
/*Log settings*/
#ifdef DEBUG_UART_LV_LOG
# define USE_LV_LOG 1 /*Enable/disable the log module*/
#else
# define USE_LV_LOG 0 /*Enable/disable the log module*/
#endif
#if USE_LV_LOG
/* How important log should be added:
* LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
* LV_LOG_LEVEL_INFO Log important events
* LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't caused problem
* LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
*/
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
/* 1: Print the log with 'printf'; 0: user need to register a callback*/
# define LV_LOG_PRINTF 1
#endif /*USE_LV_LOG*/
/*================
* THEME USAGE
*================*/
#define LV_THEME_LIVE_UPDATE 0 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/
#define USE_LV_THEME_HEKATE 1 /*Flat theme with bold colors and light shadows*/
/*==================
* FONT USAGE
*===================*/
/* More info about fonts: https://docs.littlevgl.com/#Fonts
* To enable a built-in font use 1,2,4 or 8 values
* which will determine the bit-per-pixel. Higher value means smoother fonts */
#define LV_FONT_QUALITY 8
#define USE_UBUNTU_MONO LV_FONT_QUALITY
#define USE_INTERUI_20 LV_FONT_QUALITY
#define USE_INTERUI_30 LV_FONT_QUALITY
#define USE_HEKATE_SYMBOL_20 USE_INTERUI_20
#define USE_HEKATE_SYMBOL_30 USE_INTERUI_30
#define USE_HEKATE_SYMBOL_120 LV_FONT_QUALITY
/* Optionally declare your custom fonts here.
* You can use these fonts as default font too
* and they will be available globally. E.g.
* #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \
* LV_FONT_DECLARE(my_font_2) \
*/
#define LV_FONT_CUSTOM_DECLARE
#define LV_FONT_DEFAULT &interui_30 /*Always set a default font from the built-in fonts*/
/*===================
* LV_OBJ SETTINGS
*==================*/
#define LV_OBJ_FREE_NUM_TYPE uint32_t /*Type of free number attribute (comment out disable free number)*/
#define LV_OBJ_FREE_PTR 1 /*Enable the free pointer attribute*/
#define LV_OBJ_REALIGN 1 // 0 in OG gui /*Enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/
/*==================
* LV OBJ X USAGE
*================*/
/*
* Documentation of the object types: https://docs.littlevgl.com/#Object-types
*/
/*****************
* Simple object
*****************/
/*Label (dependencies: -*/
#define USE_LV_LABEL 1
#if USE_LV_LABEL != 0
# define LV_LABEL_SCROLL_SPEED 25 /*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_SCROLL/ROLL' mode*/
#endif
/*Image (dependencies: lv_label*/
#define USE_LV_IMG 1
#if USE_LV_IMG != 0
# define LV_IMG_CF_INDEXED 0 /*Enable indexed (palette) images*/
# define LV_IMG_CF_ALPHA 0 /*Enable alpha indexed images*/
#endif
/*Line (dependencies: -*/
#define USE_LV_LINE 1
/*Arc (dependencies: -)*/
#define USE_LV_ARC 0
/*******************
* Container objects
*******************/
/*Container (dependencies: -*/
#define USE_LV_CONT 1
/*Page (dependencies: lv_cont)*/
#define USE_LV_PAGE 1
/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/
#define USE_LV_WIN 1
/*Tab (dependencies: lv_page, lv_btnm)*/
#define USE_LV_TABVIEW 1
# if USE_LV_TABVIEW != 0
# define LV_TABVIEW_ANIM_TIME 0 /*Time of slide animation [ms] (0: no animation)*/
#endif
/*Tileview (dependencies: lv_page) */
#define USE_LV_TILEVIEW 0
#if USE_LV_TILEVIEW
# define LV_TILEVIEW_ANIM_TIME 0 /*Time of slide animation [ms] (0: no animation)*/
#endif
/*************************
* Data visualizer objects
*************************/
/*Bar (dependencies: -)*/
#define USE_LV_BAR 1
/*Line meter (dependencies: *;)*/
#define USE_LV_LMETER 0
/*Gauge (dependencies:lv_bar, lv_lmeter)*/
#define USE_LV_GAUGE 0
/*Chart (dependencies: -)*/
#define USE_LV_CHART 0
/*Table (dependencies: lv_label)*/
#define USE_LV_TABLE 1
#if USE_LV_TABLE
# define LV_TABLE_COL_MAX 12
#endif
/*LED (dependencies: -)*/
#define USE_LV_LED 0
/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/
#define USE_LV_MBOX 1
/*Text area (dependencies: lv_label, lv_page)*/
#define USE_LV_TA 1
#if USE_LV_TA != 0
# define LV_TA_CURSOR_BLINK_TIME 400 /*ms*/
# define LV_TA_PWD_SHOW_TIME 1500 /*ms*/
#endif
/*Spinbox (dependencies: lv_ta)*/
#define USE_LV_SPINBOX 0
/*Calendar (dependencies: -)*/
#define USE_LV_CALENDAR 0
/*Preload (dependencies: lv_arc)*/
#define USE_LV_PRELOAD 0
#if USE_LV_PRELOAD != 0
# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/
# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/
# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC
#endif
/*Canvas (dependencies: lv_img)*/
#define USE_LV_CANVAS 0
/*************************
* User input objects
*************************/
/*Button (dependencies: lv_cont*/
#define USE_LV_BTN 1
#if USE_LV_BTN != 0
# define LV_BTN_INK_EFFECT 0 /*Enable button-state animations - draw a circle on click (dependencies: USE_LV_ANIMATION)*/
#endif
/*Image Button (dependencies: lv_btn*/
#define USE_LV_IMGBTN 1
#if USE_LV_IMGBTN
# define LV_IMGBTN_TILED 0 /*1: The imgbtn requires left, mid and right parts and the width can be set freely*/
#endif
/*Button matrix (dependencies: -)*/
#define USE_LV_BTNM 1
/*Keyboard (dependencies: lv_btnm)*/
#define USE_LV_KB 0
/*Check box (dependencies: lv_btn, lv_label)*/
#define USE_LV_CB 1
/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/
#define USE_LV_LIST 1
#if USE_LV_LIST != 0
# define LV_LIST_FOCUS_TIME 100 /*Default animation time of focusing to a list element [ms] (0: no animation) */
#endif
/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/
#define USE_LV_DDLIST 1
#if USE_LV_DDLIST != 0
# define LV_DDLIST_ANIM_TIME 100 /*Open and close default animation time [ms] (0: no animation)*/
#endif
/*Roller (dependencies: lv_ddlist)*/
#define USE_LV_ROLLER 1
#if USE_LV_ROLLER != 0
# define LV_ROLLER_ANIM_TIME 200 /*Focus animation time [ms] (0: no animation)*/
#endif
/*Slider (dependencies: lv_bar)*/
#define USE_LV_SLIDER 1
/*Switch (dependencies: lv_slider)*/
#define USE_LV_SW 1
#endif /*LV_CONF_H*/

724
bdk/mem/emc.h Normal file
View File

@@ -0,0 +1,724 @@
/*
* arch/arm/mach-tegra/tegra21_emc.h
*
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2019-2020, CTCaer.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _EMC_H_
#define _EMC_H_
#define EMC_DBG 0x8
#define EMC_CFG 0xC
#define EMC_CONFIG_SAMPLE_DELAY 0x5f0
#define EMC_CFG_UPDATE 0x5f4
#define EMC_ADR_CFG 0x10
#define EMC_REFCTRL 0x20
#define EMC_PIN 0x24
#define EMC_TIMING_CONTROL 0x28
#define EMC_RC 0x2c
#define EMC_RFC 0x30
#define EMC_RFCPB 0x590
#define EMC_RAS 0x34
#define EMC_RP 0x38
#define EMC_R2W 0x3c
#define EMC_W2R 0x40
#define EMC_R2P 0x44
#define EMC_W2P 0x48
#define EMC_CCDMW 0x5c0
#define EMC_RD_RCD 0x4c
#define EMC_WR_RCD 0x50
#define EMC_RRD 0x54
#define EMC_REXT 0x58
#define EMC_WDV 0x5c
#define EMC_QUSE 0x60
#define EMC_QRST 0x64
#define EMC_ISSUE_QRST 0x428
#define EMC_QSAFE 0x68
#define EMC_RDV 0x6c
#define EMC_REFRESH 0x70
#define EMC_BURST_REFRESH_NUM 0x74
#define EMC_PDEX2WR 0x78
#define EMC_PDEX2RD 0x7c
#define EMC_PDEX2CKE 0x118
#define EMC_PCHG2PDEN 0x80
#define EMC_ACT2PDEN 0x84
#define EMC_AR2PDEN 0x88
#define EMC_RW2PDEN 0x8c
#define EMC_CKE2PDEN 0x11c
#define EMC_TXSR 0x90
#define EMC_TCKE 0x94
#define EMC_TFAW 0x98
#define EMC_TRPAB 0x9c
#define EMC_TCLKSTABLE 0xa0
#define EMC_TCLKSTOP 0xa4
#define EMC_TREFBW 0xa8
#define EMC_TPPD 0xac
#define EMC_PDEX2MRR 0xb4
#define EMC_ODT_WRITE 0xb0
#define EMC_WEXT 0xb8
#define EMC_CTT 0xBC
#define EMC_RFC_SLR 0xc0
#define EMC_MRS_WAIT_CNT2 0xc4
#define EMC_MRS_WAIT_CNT 0xc8
#define EMC_MRS 0xcc
#define EMC_EMRS 0xd0
#define EMC_REF 0xd4
#define EMC_PRE 0xd8
#define EMC_NOP 0xdc
#define EMC_SELF_REF 0xe0
#define EMC_DPD 0xe4
#define EMC_MRW 0xe8
#define EMC_MRR 0xec
#define EMC_CMDQ 0xf0
#define EMC_MC2EMCQ 0xf4
#define EMC_FBIO_TWTM 0xF8
#define EMC_FBIO_TRATM 0xFC
#define EMC_FBIO_TWATM 0x108
#define EMC_FBIO_TR2REF 0x10C
#define EMC_FBIO_SPARE 0x100
#define EMC_FBIO_CFG5 0x104
#define EMC_FBIO_CFG6 0x114
#define EMC_CFG_RSV 0x120
#define EMC_ACPD_CONTROL 0x124
#define EMC_MPC 0x128
#define EMC_EMRS2 0x12c
#define EMC_EMRS3 0x130
#define EMC_MRW2 0x134
#define EMC_MRW3 0x138
#define EMC_MRW4 0x13c
#define EMC_MRW5 0x4a0
#define EMC_MRW6 0x4a4
#define EMC_MRW7 0x4a8
#define EMC_MRW8 0x4ac
#define EMC_MRW9 0x4b0
#define EMC_MRW10 0x4b4
#define EMC_MRW11 0x4b8
#define EMC_MRW12 0x4bc
#define EMC_MRW13 0x4c0
#define EMC_MRW14 0x4c4
#define EMC_MRW15 0x4d0
#define EMC_CFG_SYNC 0x4d4
#define EMC_CLKEN_OVERRIDE 0x140
#define EMC_R2R 0x144
#define EMC_W2W 0x148
#define EMC_EINPUT 0x14c
#define EMC_EINPUT_DURATION 0x150
#define EMC_PUTERM_EXTRA 0x154
#define EMC_TCKESR 0x158
#define EMC_TPD 0x15c
#define EMC_STAT_CONTROL 0x160
#define EMC_STAT_STATUS 0x164
#define EMC_STAT_DRAM_CLOCK_LIMIT_LO 0x19c
#define EMC_STAT_DRAM_CLOCK_LIMIT_HI 0x1a0
#define EMC_STAT_DRAM_CLOCKS_LO 0x1a4
#define EMC_STAT_DRAM_CLOCKS_HI 0x1a8
#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_LO 0x1ac
#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_HI 0x1b0
#define EMC_STAT_DRAM_DEV0_READ_CNT_LO 0x1b4
#define EMC_STAT_DRAM_DEV0_READ_CNT_HI 0x1b8
#define EMC_STAT_DRAM_DEV0_READ8_CNT_LO 0x1bc
#define EMC_STAT_DRAM_DEV0_READ8_CNT_HI 0x1c0
#define EMC_STAT_DRAM_DEV0_WRITE_CNT_LO 0x1c4
#define EMC_STAT_DRAM_DEV0_WRITE_CNT_HI 0x1c8
#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_LO 0x1cc
#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_HI 0x1d0
#define EMC_STAT_DRAM_DEV0_REF_CNT_LO 0x1d4
#define EMC_STAT_DRAM_DEV0_REF_CNT_HI 0x1d8
#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1dc
#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e0
#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1e4
#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e8
#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1ec
#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f0
#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1f4
#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f8
#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x1fc
#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x200
#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x204
#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x208
#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x20c
#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x210
#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x214
#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x218
#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_LO 0x21c
#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_HI 0x220
#define EMC_STAT_DRAM_DEV0_DSR 0x224
#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_LO 0x228
#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_HI 0x22c
#define EMC_STAT_DRAM_DEV1_READ_CNT_LO 0x230
#define EMC_STAT_DRAM_DEV1_READ_CNT_HI 0x234
#define EMC_STAT_DRAM_DEV1_READ8_CNT_LO 0x238
#define EMC_STAT_DRAM_DEV1_READ8_CNT_HI 0x23c
#define EMC_STAT_DRAM_DEV1_WRITE_CNT_LO 0x240
#define EMC_STAT_DRAM_DEV1_WRITE_CNT_HI 0x244
#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_LO 0x248
#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_HI 0x24c
#define EMC_STAT_DRAM_DEV1_REF_CNT_LO 0x250
#define EMC_STAT_DRAM_DEV1_REF_CNT_HI 0x254
#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x258
#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x25c
#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x260
#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x264
#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x268
#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x26c
#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x270
#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x274
#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x278
#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x27c
#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x280
#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x284
#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x288
#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x28c
#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x290
#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x294
#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_LO 0x298
#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_HI 0x29c
#define EMC_STAT_DRAM_DEV1_DSR 0x2a0
#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc8c
#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc90
#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc94
#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc98
#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xc9c
#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca0
#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xca4
#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca8
#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcac
#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb0
#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcb4
#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb8
#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcbc
#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc0
#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcc4
#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc8
#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_LO 0xccc
#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_HI 0xcd0
#define EMC_STAT_DRAM_IO_DSR 0xcd4
#define EMC_AUTO_CAL_CONFIG 0x2a4
#define EMC_AUTO_CAL_CONFIG2 0x458
#define EMC_AUTO_CAL_CONFIG3 0x45c
#define EMC_AUTO_CAL_CONFIG4 0x5b0
#define EMC_AUTO_CAL_CONFIG5 0x5b4
#define EMC_AUTO_CAL_CONFIG6 0x5cc
#define EMC_AUTO_CAL_CONFIG7 0x574
#define EMC_AUTO_CAL_CONFIG8 0x2dc
#define EMC_AUTO_CAL_CONFIG9 0x42C
#define EMC_AUTO_CAL_VREF_SEL_0 0x2f8
#define EMC_AUTO_CAL_VREF_SEL_1 0x300
#define EMC_AUTO_CAL_INTERVAL 0x2a8
#define EMC_AUTO_CAL_STATUS 0x2ac
#define EMC_AUTO_CAL_STATUS2 0x3d4
#define EMC_AUTO_CAL_CHANNEL 0x464
#define EMC_PMACRO_RX_TERM 0xc48
#define EMC_PMACRO_DQ_TX_DRV 0xc70
#define EMC_PMACRO_CA_TX_DRV 0xc74
#define EMC_PMACRO_CMD_TX_DRV 0xc4c
#define EMC_PMACRO_AUTOCAL_CFG_0 0x700
#define EMC_PMACRO_AUTOCAL_CFG_1 0x704
#define EMC_PMACRO_AUTOCAL_CFG_2 0x708
#define EMC_PMACRO_AUTOCAL_CFG_COMMON 0xc78
#define EMC_PMACRO_ZCTRL 0xc44
#define EMC_XM2COMPPADCTRL 0x30c
#define EMC_XM2COMPPADCTRL2 0x578
#define EMC_XM2COMPPADCTRL3 0x2f4
#define EMC_COMP_PAD_SW_CTRL 0x57c
#define EMC_REQ_CTRL 0x2b0
#define EMC_EMC_STATUS 0x2b4
#define EMC_STATUS_MRR_DIVLD BIT(20)
#define EMC_CFG_2 0x2b8
#define EMC_CFG_DIG_DLL 0x2bc
#define EMC_CFG_DIG_DLL_PERIOD 0x2c0
#define EMC_DIG_DLL_STATUS 0x2c4
#define EMC_CFG_DIG_DLL_1 0x2c8
#define EMC_RDV_MASK 0x2cc
#define EMC_WDV_MASK 0x2d0
#define EMC_RDV_EARLY_MASK 0x2d4
#define EMC_RDV_EARLY 0x2d8
#define EMC_WDV_CHK 0x4e0
#define EMC_ZCAL_INTERVAL 0x2e0
#define EMC_ZCAL_WAIT_CNT 0x2e4
#define EMC_ZCAL_MRW_CMD 0x2e8
#define EMC_ZQ_CAL 0x2ec
#define EMC_SCRATCH0 0x324
#define EMC_STALL_THEN_EXE_BEFORE_CLKCHANGE 0x3c8
#define EMC_STALL_THEN_EXE_AFTER_CLKCHANGE 0x3cc
#define EMC_UNSTALL_RW_AFTER_CLKCHANGE 0x3d0
#define EMC_FDPD_CTRL_CMD_NO_RAMP 0x4d8
#define EMC_SEL_DPD_CTRL 0x3d8
#define EMC_FDPD_CTRL_DQ 0x310
#define EMC_FDPD_CTRL_CMD 0x314
#define EMC_PRE_REFRESH_REQ_CNT 0x3dc
#define EMC_REFCTRL2 0x580
#define EMC_FBIO_CFG7 0x584
#define EMC_DATA_BRLSHFT_0 0x588
#define EMC_DATA_BRLSHFT_1 0x58c
#define EMC_DQS_BRLSHFT_0 0x594
#define EMC_DQS_BRLSHFT_1 0x598
#define EMC_CMD_BRLSHFT_0 0x59c
#define EMC_CMD_BRLSHFT_1 0x5a0
#define EMC_CMD_BRLSHFT_2 0x5a4
#define EMC_CMD_BRLSHFT_3 0x5a8
#define EMC_QUSE_BRLSHFT_0 0x5ac
#define EMC_QUSE_BRLSHFT_1 0x5b8
#define EMC_QUSE_BRLSHFT_2 0x5bc
#define EMC_QUSE_BRLSHFT_3 0x5c4
#define EMC_FBIO_CFG8 0x5c8
#define EMC_CMD_MAPPING_CMD0_0 0x380
#define EMC_CMD_MAPPING_CMD0_1 0x384
#define EMC_CMD_MAPPING_CMD0_2 0x388
#define EMC_CMD_MAPPING_CMD1_0 0x38c
#define EMC_CMD_MAPPING_CMD1_1 0x390
#define EMC_CMD_MAPPING_CMD1_2 0x394
#define EMC_CMD_MAPPING_CMD2_0 0x398
#define EMC_CMD_MAPPING_CMD2_1 0x39c
#define EMC_CMD_MAPPING_CMD2_2 0x3a0
#define EMC_CMD_MAPPING_CMD3_0 0x3a4
#define EMC_CMD_MAPPING_CMD3_1 0x3a8
#define EMC_CMD_MAPPING_CMD3_2 0x3ac
#define EMC_CMD_MAPPING_BYTE 0x3b0
#define EMC_DYN_SELF_REF_CONTROL 0x3e0
#define EMC_TXSRDLL 0x3e4
#define EMC_CCFIFO_ADDR 0x3e8
#define EMC_CCFIFO_DATA 0x3ec
#define EMC_CCFIFO_STATUS 0x3f0
#define EMC_SWIZZLE_RANK0_BYTE0 0x404
#define EMC_SWIZZLE_RANK0_BYTE1 0x408
#define EMC_SWIZZLE_RANK0_BYTE2 0x40c
#define EMC_SWIZZLE_RANK0_BYTE3 0x410
#define EMC_SWIZZLE_RANK1_BYTE0 0x418
#define EMC_SWIZZLE_RANK1_BYTE1 0x41c
#define EMC_SWIZZLE_RANK1_BYTE2 0x420
#define EMC_SWIZZLE_RANK1_BYTE3 0x424
#define EMC_TR_TIMING_0 0x3b4
#define EMC_TR_CTRL_0 0x3b8
#define EMC_TR_CTRL_1 0x3bc
#define EMC_TR_DVFS 0x460
#define EMC_SWITCH_BACK_CTRL 0x3c0
#define EMC_TR_RDV 0x3c4
#define EMC_TR_QPOP 0x3f4
#define EMC_TR_RDV_MASK 0x3f8
#define EMC_TR_QSAFE 0x3fc
#define EMC_TR_QRST 0x400
#define EMC_IBDLY 0x468
#define EMC_OBDLY 0x46c
#define EMC_TXDSRVTTGEN 0x480
#define EMC_WE_DURATION 0x48c
#define EMC_WS_DURATION 0x490
#define EMC_WEV 0x494
#define EMC_WSV 0x498
#define EMC_CFG_3 0x49c
#define EMC_CFG_PIPE_2 0x554
#define EMC_CFG_PIPE_CLK 0x558
#define EMC_CFG_PIPE_1 0x55c
#define EMC_CFG_PIPE 0x560
#define EMC_QPOP 0x564
#define EMC_QUSE_WIDTH 0x568
#define EMC_PUTERM_WIDTH 0x56c
#define EMC_PROTOBIST_CONFIG_ADR_1 0x5d0
#define EMC_PROTOBIST_CONFIG_ADR_2 0x5d4
#define EMC_PROTOBIST_MISC 0x5d8
#define EMC_PROTOBIST_WDATA_LOWER 0x5dc
#define EMC_PROTOBIST_WDATA_UPPER 0x5e0
#define EMC_PROTOBIST_RDATA 0x5ec
#define EMC_DLL_CFG_0 0x5e4
#define EMC_DLL_CFG_1 0x5e8
#define EMC_TRAINING_CMD 0xe00
#define EMC_TRAINING_CTRL 0xe04
#define EMC_TRAINING_STATUS 0xe08
#define EMC_TRAINING_QUSE_CORS_CTRL 0xe0c
#define EMC_TRAINING_QUSE_FINE_CTRL 0xe10
#define EMC_TRAINING_QUSE_CTRL_MISC 0xe14
#define EMC_TRAINING_WRITE_FINE_CTRL 0xe18
#define EMC_TRAINING_WRITE_CTRL_MISC 0xe1c
#define EMC_TRAINING_WRITE_VREF_CTRL 0xe20
#define EMC_TRAINING_READ_FINE_CTRL 0xe24
#define EMC_TRAINING_READ_CTRL_MISC 0xe28
#define EMC_TRAINING_READ_VREF_CTRL 0xe2c
#define EMC_TRAINING_CA_FINE_CTRL 0xe30
#define EMC_TRAINING_CA_CTRL_MISC 0xe34
#define EMC_TRAINING_CA_CTRL_MISC1 0xe38
#define EMC_TRAINING_CA_VREF_CTRL 0xe3c
#define EMC_TRAINING_CA_TADR_CTRL 0xe40
#define EMC_TRAINING_SETTLE 0xe44
#define EMC_TRAINING_DEBUG_CTRL 0xe48
#define EMC_TRAINING_DEBUG_DQ0 0xe4c
#define EMC_TRAINING_DEBUG_DQ1 0xe50
#define EMC_TRAINING_DEBUG_DQ2 0xe54
#define EMC_TRAINING_DEBUG_DQ3 0xe58
#define EMC_TRAINING_MPC 0xe5c
#define EMC_TRAINING_PATRAM_CTRL 0xe60
#define EMC_TRAINING_PATRAM_DQ 0xe64
#define EMC_TRAINING_PATRAM_DMI 0xe68
#define EMC_TRAINING_VREF_SETTLE 0xe6c
#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE0 0xe70
#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE1 0xe74
#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE2 0xe78
#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE3 0xe7c
#define EMC_TRAINING_RW_EYE_CENTER_IB_MISC 0xe80
#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE0 0xe84
#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE1 0xe88
#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE2 0xe8c
#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE3 0xe90
#define EMC_TRAINING_RW_EYE_CENTER_OB_MISC 0xe94
#define EMC_TRAINING_RW_OFFSET_IB_BYTE0 0xe98
#define EMC_TRAINING_RW_OFFSET_IB_BYTE1 0xe9c
#define EMC_TRAINING_RW_OFFSET_IB_BYTE2 0xea0
#define EMC_TRAINING_RW_OFFSET_IB_BYTE3 0xea4
#define EMC_TRAINING_RW_OFFSET_IB_MISC 0xea8
#define EMC_TRAINING_RW_OFFSET_OB_BYTE0 0xeac
#define EMC_TRAINING_RW_OFFSET_OB_BYTE1 0xeb0
#define EMC_TRAINING_RW_OFFSET_OB_BYTE2 0xeb4
#define EMC_TRAINING_RW_OFFSET_OB_BYTE3 0xeb8
#define EMC_TRAINING_RW_OFFSET_OB_MISC 0xebc
#define EMC_TRAINING_OPT_CA_VREF 0xec0
#define EMC_TRAINING_OPT_DQ_OB_VREF 0xec4
#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK0 0xec8
#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK1 0xecc
#define EMC_TRAINING_QUSE_VREF_CTRL 0xed0
#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4
#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8
#define EMC_TRAINING_DRAMC_TIMING 0xedc
#define EMC_PMACRO_DATA_PI_CTRL 0x110
#define EMC_PMACRO_CMD_PI_CTRL 0x114
#define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600
#define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604
#define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608
#define EMC_PMACRO_QUSE_DDLL_RANK0_3 0x60c
#define EMC_PMACRO_QUSE_DDLL_RANK0_4 0x610
#define EMC_PMACRO_QUSE_DDLL_RANK0_5 0x614
#define EMC_PMACRO_QUSE_DDLL_RANK1_0 0x620
#define EMC_PMACRO_QUSE_DDLL_RANK1_1 0x624
#define EMC_PMACRO_QUSE_DDLL_RANK1_2 0x628
#define EMC_PMACRO_QUSE_DDLL_RANK1_3 0x62c
#define EMC_PMACRO_QUSE_DDLL_RANK1_4 0x630
#define EMC_PMACRO_QUSE_DDLL_RANK1_5 0x634
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 0x640
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 0x644
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 0x648
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 0x64c
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4 0x650
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5 0x654
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 0x660
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 0x664
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 0x668
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 0x66c
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4 0x670
#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5 0x674
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0 0x680
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1 0x684
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2 0x688
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3 0x68c
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4 0x690
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5 0x694
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0 0x6a0
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1 0x6a4
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2 0x6a8
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3 0x6ac
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4 0x6b0
#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5 0x6b4
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0 0x6c0
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1 0x6c4
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2 0x6c8
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3 0x6cc
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_4 0x6d0
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_5 0x6d4
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0 0x6e0
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1 0x6e4
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2 0x6e8
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3 0x6ec
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_4 0x6f0
#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_5 0x6f4
#define EMC_PMACRO_TX_PWRD_0 0x720
#define EMC_PMACRO_TX_PWRD_1 0x724
#define EMC_PMACRO_TX_PWRD_2 0x728
#define EMC_PMACRO_TX_PWRD_3 0x72c
#define EMC_PMACRO_TX_PWRD_4 0x730
#define EMC_PMACRO_TX_PWRD_5 0x734
#define EMC_PMACRO_TX_SEL_CLK_SRC_0 0x740
#define EMC_PMACRO_TX_SEL_CLK_SRC_1 0x744
#define EMC_PMACRO_TX_SEL_CLK_SRC_3 0x74c
#define EMC_PMACRO_TX_SEL_CLK_SRC_2 0x748
#define EMC_PMACRO_TX_SEL_CLK_SRC_4 0x750
#define EMC_PMACRO_TX_SEL_CLK_SRC_5 0x754
#define EMC_PMACRO_DDLL_BYPASS 0x760
#define EMC_PMACRO_DDLL_PWRD_0 0x770
#define EMC_PMACRO_DDLL_PWRD_1 0x774
#define EMC_PMACRO_DDLL_PWRD_2 0x778
#define EMC_PMACRO_CMD_CTRL_0 0x780
#define EMC_PMACRO_CMD_CTRL_1 0x784
#define EMC_PMACRO_CMD_CTRL_2 0x788
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0x800
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0x804
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0x808
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3 0x80c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0x810
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0x814
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0x818
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3 0x81c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0x820
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0x824
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0x828
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3 0x82c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0x830
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0x834
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0x838
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3 0x83c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0x840
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0x844
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0x848
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3 0x84c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0x850
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0x854
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0x858
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3 0x85c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0x860
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0x864
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0x868
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3 0x86c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0x870
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0x874
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0x878
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3 0x87c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0 0x880
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1 0x884
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2 0x888
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3 0x88c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0 0x890
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1 0x894
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2 0x898
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3 0x89c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0 0x8a0
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1 0x8a4
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2 0x8a8
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3 0x8ac
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0 0x8b0
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1 0x8b4
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2 0x8b8
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3 0x8bc
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0x900
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0x904
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0x908
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3 0x90c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0x910
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0x914
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0x918
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3 0x91c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0x920
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0x924
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0x928
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3 0x92c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0x930
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0x934
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0x938
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3 0x93c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0x940
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0x944
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0x948
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3 0x94c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0x950
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0x954
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0x958
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3 0x95c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0x960
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0x964
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0x968
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3 0x96c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0x970
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0x974
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0x978
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3 0x97c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0 0x980
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1 0x984
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2 0x988
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3 0x98c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0 0x990
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1 0x994
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2 0x998
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3 0x99c
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0 0x9a0
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1 0x9a4
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2 0x9a8
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3 0x9ac
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0 0x9b0
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1 0x9b4
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2 0x9b8
#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3 0x9bc
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0xa00
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0xa04
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0xa08
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0xa10
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0xa14
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0xa18
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0xa20
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0xa24
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0xa28
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0xa30
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0xa34
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0xa38
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0xa40
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0xa44
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0xa48
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0xa50
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0xa54
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0xa58
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0xa60
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0xa64
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0xa68
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0xa70
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0xa74
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0xa78
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_0 0xa80
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_1 0xa84
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_2 0xa88
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_0 0xa90
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_1 0xa94
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_2 0xa98
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_0 0xaa0
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_1 0xaa4
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_2 0xaa8
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_0 0xab0
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_1 0xab4
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_2 0xab8
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0xb00
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0xb04
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0xb08
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0xb10
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0xb14
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0xb18
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0xb20
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0xb24
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0xb28
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0xb30
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0xb34
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0xb38
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0xb40
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0xb44
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0xb48
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0xb50
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0xb54
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0xb58
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0xb60
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0xb64
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0xb68
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0xb70
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0xb74
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0xb78
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_0 0xb80
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_1 0xb84
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_2 0xb88
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_0 0xb90
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_1 0xb94
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_2 0xb98
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_0 0xba0
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_1 0xba4
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_2 0xba8
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_0 0xbb0
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_1 0xbb4
#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_2 0xbb8
#define EMC_PMACRO_IB_VREF_DQ_0 0xbe0
#define EMC_PMACRO_IB_VREF_DQ_1 0xbe4
#define EMC_PMACRO_IB_VREF_DQ_2 0xbe8
#define EMC_PMACRO_IB_VREF_DQS_0 0xbf0
#define EMC_PMACRO_IB_VREF_DQS_1 0xbf4
#define EMC_PMACRO_IB_VREF_DQS_2 0xbf8
#define EMC_PMACRO_IB_RXRT 0xcf4
#define EMC_PMACRO_DDLL_LONG_CMD_0 0xc00
#define EMC_PMACRO_DDLL_LONG_CMD_1 0xc04
#define EMC_PMACRO_DDLL_LONG_CMD_2 0xc08
#define EMC_PMACRO_DDLL_LONG_CMD_3 0xc0c
#define EMC_PMACRO_DDLL_LONG_CMD_4 0xc10
#define EMC_PMACRO_DDLL_LONG_CMD_5 0xc14
#define EMC_PMACRO_DDLL_SHORT_CMD_0 0xc20
#define EMC_PMACRO_DDLL_SHORT_CMD_1 0xc24
#define EMC_PMACRO_DDLL_SHORT_CMD_2 0xc28
#define EMC_PMACRO_CFG_PM_GLOBAL_0 0xc30
#define EMC_PMACRO_VTTGEN_CTRL_0 0xc34
#define EMC_PMACRO_VTTGEN_CTRL_1 0xc38
#define EMC_PMACRO_VTTGEN_CTRL_2 0xcf0
#define EMC_PMACRO_BG_BIAS_CTRL_0 0xc3c
#define EMC_PMACRO_PAD_CFG_CTRL 0xc40
#define EMC_PMACRO_CMD_PAD_RX_CTRL 0xc50
#define EMC_PMACRO_DATA_PAD_RX_CTRL 0xc54
#define EMC_PMACRO_CMD_RX_TERM_MODE 0xc58
#define EMC_PMACRO_DATA_RX_TERM_MODE 0xc5c
#define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60
#define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64
#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68
#define EMC_PMACRO_DSR_VTTGEN_CTRL0 0xC6C
#define EMC_PMACRO_BRICK_MAPPING_0 0xc80
#define EMC_PMACRO_BRICK_MAPPING_1 0xc84
#define EMC_PMACRO_BRICK_MAPPING_2 0xc88
#define EMC_PMACRO_DDLLCAL_CAL 0xce0
#define EMC_PMACRO_DDLL_OFFSET 0xce4
#define EMC_PMACRO_DDLL_PERIODIC_OFFSET 0xce8
#define EMC_PMACRO_BRICK_CTRL_RFU1 0x330
#define EMC_PMACRO_BRICK_CTRL_RFU2 0x334
#define EMC_PMACRO_CMD_BRICK_CTRL_FDPD 0x318
#define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c
#define EMC_PMACRO_TRAINING_CTRL_0 0xcf8
#define EMC_PMACRO_TRAINING_CTRL_1 0xcfc
#define EMC_PMACRO_PERBIT_FGCG_CTRL_0 0xD40
#define EMC_PMACRO_PERBIT_FGCG_CTRL_1 0xD44
#define EMC_PMACRO_PERBIT_FGCG_CTRL_2 0xD48
#define EMC_PMACRO_PERBIT_FGCG_CTRL_3 0xD4C
#define EMC_PMACRO_PERBIT_FGCG_CTRL_4 0xD50
#define EMC_PMACRO_PERBIT_FGCG_CTRL_5 0xD54
#define EMC_PMACRO_PERBIT_RFU_CTRL_0 0xD60
#define EMC_PMACRO_PERBIT_RFU_CTRL_1 0xD64
#define EMC_PMACRO_PERBIT_RFU_CTRL_2 0xD68
#define EMC_PMACRO_PERBIT_RFU_CTRL_3 0xD6C
#define EMC_PMACRO_PERBIT_RFU_CTRL_4 0xD70
#define EMC_PMACRO_PERBIT_RFU_CTRL_5 0xD74
#define EMC_PMACRO_PERBIT_RFU1_CTRL_0 0xD80
#define EMC_PMACRO_PERBIT_RFU1_CTRL_1 0xD84
#define EMC_PMACRO_PERBIT_RFU1_CTRL_2 0xD88
#define EMC_PMACRO_PERBIT_RFU1_CTRL_3 0xD8C
#define EMC_PMACRO_PERBIT_RFU1_CTRL_4 0xD90
#define EMC_PMACRO_PERBIT_RFU1_CTRL_5 0xD94
#define EMC_PMC_SCRATCH1 0x440
#define EMC_PMC_SCRATCH2 0x444
#define EMC_PMC_SCRATCH3 0x448
#define EMC_STATUS_UPDATE_TIMEOUT 1000
typedef enum _emc_mr_t
{
MR5_MAN_ID = 5,
MR6_REV_ID1 = 6,
MR7_REV_ID2 = 7,
MR8_DENSITY = 8,
} emc_mr_t;
enum
{
EMC_CHAN0 = 0,
EMC_CHAN1 = 1
};
typedef struct _emc_mr_data_t
{
// Device 0.
u8 rank0_ch0;
u8 rank0_ch1;
// Device 1.
u8 rank1_ch0;
u8 rank1_ch1;
} emc_mr_data_t;
#endif

177
bdk/mem/heap.c Normal file
View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "heap.h"
#include <gfx_utils.h>
static void _heap_create(heap_t *heap, u32 start)
{
heap->start = start;
heap->first = NULL;
}
// Node info is before node address.
static u32 _heap_alloc(heap_t *heap, u32 size)
{
hnode_t *node, *new_node;
// Align to cache line size.
size = ALIGN(size, sizeof(hnode_t));
if (!heap->first)
{
node = (hnode_t *)heap->start;
node->used = 1;
node->size = size;
node->prev = NULL;
node->next = NULL;
heap->first = node;
return (u32)node + sizeof(hnode_t);
}
node = heap->first;
while (true)
{
// Check if there's available unused node.
if (!node->used && (size <= node->size))
{
// Size and offset of the new unused node.
u32 new_size = node->size - size;
new_node = (hnode_t *)((u32)node + sizeof(hnode_t) + size);
// If there's aligned unused space from the old node,
// create a new one and set the leftover size.
if (new_size >= (sizeof(hnode_t) << 2))
{
new_node->size = new_size - sizeof(hnode_t);
new_node->used = 0;
new_node->next = node->next;
// Check that we are not on first node.
if (new_node->next)
new_node->next->prev = new_node;
new_node->prev = node;
node->next = new_node;
}
else // Unused node size is just enough.
size += new_size;
node->size = size;
node->used = 1;
return (u32)node + sizeof(hnode_t);
}
// No unused node found, try the next one.
if (node->next)
node = node->next;
else
break;
}
// No unused node found, create a new one.
new_node = (hnode_t *)((u32)node + sizeof(hnode_t) + node->size);
new_node->used = 1;
new_node->size = size;
new_node->prev = node;
new_node->next = NULL;
node->next = new_node;
return (u32)new_node + sizeof(hnode_t);
}
static void _heap_free(heap_t *heap, u32 addr)
{
hnode_t *node = (hnode_t *)(addr - sizeof(hnode_t));
node->used = 0;
node = heap->first;
while (node)
{
if (!node->used)
{
if (node->prev && !node->prev->used)
{
node->prev->size += node->size + sizeof(hnode_t);
node->prev->next = node->next;
if (node->next)
node->next->prev = node->prev;
}
}
node = node->next;
}
}
heap_t _heap;
void heap_init(u32 base)
{
_heap_create(&_heap, base);
}
void heap_copy(heap_t *heap)
{
memcpy(&_heap, heap, sizeof(heap_t));
}
void *malloc(u32 size)
{
return (void *)_heap_alloc(&_heap, size);
}
void *calloc(u32 num, u32 size)
{
void *res = (void *)_heap_alloc(&_heap, num * size);
memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size.
return res;
}
void free(void *buf)
{
if ((u32)buf >= _heap.start)
_heap_free(&_heap, (u32)buf);
}
void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
{
u32 count = 0;
memset(mon, 0, sizeof(heap_monitor_t));
hnode_t *node = _heap.first;
while (true)
{
if (node->used)
mon->used += node->size + sizeof(hnode_t);
else
mon->total += node->size + sizeof(hnode_t);
if (print_node_stats)
gfx_printf("%3d - %d, addr: 0x%08X, size: 0x%X\n",
count, node->used, (u32)node + sizeof(hnode_t), node->size);
count++;
if (node->next)
node = node->next;
else
break;
}
mon->total += mon->used;
}

51
bdk/mem/heap.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* 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 _HEAP_H_
#define _HEAP_H_
#include <utils/types.h>
typedef struct _hnode
{
int used;
u32 size;
struct _hnode *prev;
struct _hnode *next;
u32 align[4]; // Align to arch cache line size.
} hnode_t;
typedef struct _heap
{
u32 start;
hnode_t *first;
} heap_t;
typedef struct
{
u32 total;
u32 used;
} heap_monitor_t;
void heap_init(u32 base);
void heap_copy(heap_t *heap);
void *malloc(u32 size);
void *calloc(u32 num, u32 size);
void free(void *buf);
void heap_monitor(heap_monitor_t *mon, bool print_node_stats);
#endif

164
bdk/mem/mc.c Normal file
View File

@@ -0,0 +1,164 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <memory_map.h>
#include <mem/mc.h>
#include <soc/t210.h>
#include <soc/clock.h>
#include <utils/util.h>
//#define CONFIG_ENABLE_AHB_REDIRECT
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock)
{
MC(MC_SEC_CARVEOUT_BOM) = bom;
MC(MC_SEC_CARVEOUT_SIZE_MB) = size1mb;
if (lock)
MC(MC_SEC_CARVEOUT_REG_CTRL) = 1;
}
void mc_config_carveout()
{
*(vu32 *)0x8005FFFC = 0xC0EDBBCC;
MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1;
MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0;
MC(MC_VIDEO_PROTECT_BOM) = 0;
MC(MC_VIDEO_PROTECT_SIZE_MB) = 0;
MC(MC_VIDEO_PROTECT_REG_CTRL) = 1;
// Configure TSEC carveout @ 0x90000000, 1MB.
//mc_config_tsec_carveout(0x90000000, 1, false);
mc_config_tsec_carveout(0, 0, true);
MC(MC_MTS_CARVEOUT_BOM) = 0;
MC(MC_MTS_CARVEOUT_SIZE_MB) = 0;
MC(MC_MTS_CARVEOUT_ADR_HI) = 0;
MC(MC_MTS_CARVEOUT_REG_CTRL) = 1;
MC(MC_SECURITY_CARVEOUT1_BOM) = 0;
MC(MC_SECURITY_CARVEOUT1_BOM_HI) = 0;
MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT1_CFG0) = 0x4000006;
MC(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000;
MC(MC_SECURITY_CARVEOUT2_BOM_HI) = 0;
MC(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = 0x3100000;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = 0x300;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT2_CFG0) = 0x440167E;
MC(MC_SECURITY_CARVEOUT3_BOM) = 0;
MC(MC_SECURITY_CARVEOUT3_BOM_HI) = 0;
MC(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0x3000000;
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0x300;
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT3_CFG0) = 0x4401E7E;
MC(MC_SECURITY_CARVEOUT4_BOM) = 0;
MC(MC_SECURITY_CARVEOUT4_BOM_HI) = 0;
MC(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT4_CFG0) = 0x8F;
MC(MC_SECURITY_CARVEOUT5_BOM) = 0;
MC(MC_SECURITY_CARVEOUT5_BOM_HI) = 0;
MC(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F;
}
void mc_enable_ahb_redirect(bool full_aperture)
{
// Enable ARC_CLK_OVR_ON.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = (CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) & 0xFFF7FFFF) | 0x80000;
//MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE;
MC(MC_IRAM_BOM) = 0x40000000;
MC(MC_IRAM_TOM) = full_aperture ? DRAM_START : 0x4003F000;
}
void mc_disable_ahb_redirect()
{
MC(MC_IRAM_BOM) = 0xFFFFF000;
MC(MC_IRAM_TOM) = 0;
// Disable IRAM_CFG_WRITE_ACCESS (sticky).
//MC(MC_IRAM_REG_CTRL) = MC(MC_IRAM_REG_CTRL) & 0xFFFFFFFE | 1;
// Disable ARC_CLK_OVR_ON.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) &= 0xFFF7FFFF;
}
void mc_enable()
{
// Reset EMC source to PLLP.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
// Enable memory clocks.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
// Clear clock resets for memory.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
usleep(5);
#ifdef CONFIG_ENABLE_AHB_REDIRECT
mc_enable_ahb_redirect();
#else
mc_disable_ahb_redirect();
#endif
}

30
bdk/mem/mc.h Normal file
View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _MC_H_
#define _MC_H_
#include <utils/types.h>
#include <mem/mc_t210.h>
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock);
void mc_config_carveout();
void mc_config_carveout_finalize();
void mc_enable_ahb_redirect(bool full_aperture);
void mc_disable_ahb_redirect();
void mc_enable();
#endif

517
bdk/mem/mc_t210.h Normal file
View File

@@ -0,0 +1,517 @@
/*
* Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
*
* 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 _MC_T210_H_
#define _MC_T210_H_
#define MC_INTSTATUS 0x0
#define MC_INTMASK 0x4
#define MC_ERR_STATUS 0x8
#define MC_ERR_ADR 0xc
#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0
#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4
#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8
#define MC_PCFIFO_CLIENT_CONFIG3 0xddc
#define MC_PCFIFO_CLIENT_CONFIG4 0xde0
#define MC_EMEM_CFG 0x50
#define MC_EMEM_ADR_CFG 0x54
#define MC_EMEM_ADR_CFG_DEV0 0x58
#define MC_EMEM_ADR_CFG_DEV1 0x5c
#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60
#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64
#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68
#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c
#define MC_SECURITY_CFG0 0x70
#define MC_SECURITY_CFG1 0x74
#define MC_SECURITY_CFG3 0x9bc
#define MC_SECURITY_RSV 0x7c
#define MC_EMEM_ARB_CFG 0x90
#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
#define MC_EMEM_ARB_TIMING_RCD 0x98
#define MC_EMEM_ARB_TIMING_RP 0x9c
#define MC_EMEM_ARB_TIMING_RC 0xa0
#define MC_EMEM_ARB_TIMING_RAS 0xa4
#define MC_EMEM_ARB_TIMING_FAW 0xa8
#define MC_EMEM_ARB_TIMING_RRD 0xac
#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
#define MC_EMEM_ARB_TIMING_R2R 0xb8
#define MC_EMEM_ARB_TIMING_W2W 0xbc
#define MC_EMEM_ARB_TIMING_R2W 0xc0
#define MC_EMEM_ARB_TIMING_W2R 0xc4
#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0
#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4
#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0
#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4
#define MC_EMEM_ARB_DA_TURNS 0xd0
#define MC_EMEM_ARB_DA_COVERS 0xd4
#define MC_EMEM_ARB_MISC0 0xd8
#define MC_EMEM_ARB_MISC1 0xdc
#define MC_EMEM_ARB_MISC2 0xc8
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0
#define MC_EMEM_ARB_OVERRIDE 0xe8
#define MC_EMEM_ARB_RSV 0xec
#define MC_CLKEN_OVERRIDE 0xf4
#define MC_TIMING_CONTROL_DBG 0xf8
#define MC_TIMING_CONTROL 0xfc
#define MC_STAT_CONTROL 0x100
#define MC_STAT_STATUS 0x104
#define MC_STAT_EMC_CLOCK_LIMIT 0x108
#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c
#define MC_STAT_EMC_CLOCKS 0x110
#define MC_STAT_EMC_CLOCKS_MSBS 0x114
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c
#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0
#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0
#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120
#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160
#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128
#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168
#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c
#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c
#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130
#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170
#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134
#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88
#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174
#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c
#define MC_STAT_EMC_SET0_COUNT 0x138
#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c
#define MC_STAT_EMC_SET1_COUNT 0x178
#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c
#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140
#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144
#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180
#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184
#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148
#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c
#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188
#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c
#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150
#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190
#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8
#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc
#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8
#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc
#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0
#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0
#define MC_CLIENT_HOTRESET_CTRL 0x200
#define MC_CLIENT_HOTRESET_CTRL_1 0x970
#define MC_CLIENT_HOTRESET_STATUS 0x204
#define MC_CLIENT_HOTRESET_STATUS_1 0x974
#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208
#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c
#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210
#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214
#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94
#define MC_EMEM_ARB_HYSTERESIS_0 0x218
#define MC_EMEM_ARB_HYSTERESIS_1 0x21c
#define MC_EMEM_ARB_HYSTERESIS_2 0x220
#define MC_EMEM_ARB_HYSTERESIS_3 0x224
#define MC_EMEM_ARB_HYSTERESIS_4 0xb84
#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0
#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4
#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8
#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc
#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0
#define MC_EMEM_ARB_DHYST_CTRL 0xbcc
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec
#define MC_RESERVED_RSV 0x3fc
#define MC_DISB_EXTRA_SNAP_LEVELS 0x408
#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4
#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0
#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18
#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08
#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10
#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c
#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40
#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414
#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc
#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c
#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14
#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0
#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac
#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c
#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48
#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8
#define MC_USBX_EXTRA_SNAP_LEVELS 0x404
#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8
#define MC_SD_EXTRA_SNAP_LEVELS 0xa04
#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c
#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8
#define MC_GK_EXTRA_SNAP_LEVELS 0xa00
#define MC_VE2_EXTRA_SNAP_LEVELS 0x410
#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44
#define MC_VIDEO_PROTECT_BOM 0x648
#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978
#define MC_VIDEO_PROTECT_REG_CTRL 0x650
#define MC_ERR_VPR_STATUS 0x654
#define MC_ERR_VPR_ADR 0x658
#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418
#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590
#define MC_IRAM_BOM 0x65c
#define MC_IRAM_TOM 0x660
#define MC_IRAM_ADR_HI 0x980
#define MC_IRAM_REG_CTRL 0x964
#define MC_EMEM_CFG_ACCESS_CTRL 0x664
#define MC_TZ_SECURITY_CTRL 0x668
#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c
#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4
#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc
#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8
#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80
#define MC_SEC_CARVEOUT_BOM 0x670
#define MC_SEC_CARVEOUT_SIZE_MB 0x674
#define MC_SEC_CARVEOUT_ADR_HI 0x9d4
#define MC_SEC_CARVEOUT_REG_CTRL 0x678
#define MC_ERR_SEC_STATUS 0x67c
#define MC_ERR_SEC_ADR 0x680
#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684
#define MC_STUTTER_CONTROL 0x688
#define MC_RESERVED_RSV_1 0x958
#define MC_DVFS_PIPE_SELECT 0x95c
#define MC_AHB_PTSA_MIN 0x4e0
#define MC_AUD_PTSA_MIN 0x54c
#define MC_MLL_MPCORER_PTSA_RATE 0x44c
#define MC_RING2_PTSA_RATE 0x440
#define MC_USBD_PTSA_RATE 0x530
#define MC_USBX_PTSA_MIN 0x528
#define MC_USBD_PTSA_MIN 0x534
#define MC_APB_PTSA_MAX 0x4f0
#define MC_JPG_PTSA_RATE 0x584
#define MC_DIS_PTSA_MIN 0x420
#define MC_AVP_PTSA_MAX 0x4fc
#define MC_AVP_PTSA_RATE 0x4f4
#define MC_RING1_PTSA_MIN 0x480
#define MC_DIS_PTSA_MAX 0x424
#define MC_SD_PTSA_MAX 0x4d8
#define MC_MSE_PTSA_RATE 0x4c4
#define MC_VICPC_PTSA_MIN 0x558
#define MC_PCX_PTSA_MAX 0x4b4
#define MC_ISP_PTSA_RATE 0x4a0
#define MC_A9AVPPC_PTSA_MIN 0x48c
#define MC_RING2_PTSA_MAX 0x448
#define MC_AUD_PTSA_RATE 0x548
#define MC_HOST_PTSA_MIN 0x51c
#define MC_MLL_MPCORER_PTSA_MAX 0x454
#define MC_SD_PTSA_MIN 0x4d4
#define MC_RING1_PTSA_RATE 0x47c
#define MC_JPG_PTSA_MIN 0x588
#define MC_HDAPC_PTSA_MIN 0x62c
#define MC_AVP_PTSA_MIN 0x4f8
#define MC_JPG_PTSA_MAX 0x58c
#define MC_VE_PTSA_MAX 0x43c
#define MC_DFD_PTSA_MAX 0x63c
#define MC_VICPC_PTSA_RATE 0x554
#define MC_GK_PTSA_MAX 0x544
#define MC_VICPC_PTSA_MAX 0x55c
#define MC_SDM_PTSA_MAX 0x624
#define MC_SAX_PTSA_RATE 0x4b8
#define MC_PCX_PTSA_MIN 0x4b0
#define MC_APB_PTSA_MIN 0x4ec
#define MC_GK2_PTSA_MIN 0x614
#define MC_PCX_PTSA_RATE 0x4ac
#define MC_RING1_PTSA_MAX 0x484
#define MC_HDAPC_PTSA_RATE 0x628
#define MC_MLL_MPCORER_PTSA_MIN 0x450
#define MC_GK2_PTSA_MAX 0x618
#define MC_AUD_PTSA_MAX 0x550
#define MC_GK2_PTSA_RATE 0x610
#define MC_ISP_PTSA_MAX 0x4a8
#define MC_DISB_PTSA_RATE 0x428
#define MC_VE2_PTSA_MAX 0x49c
#define MC_DFD_PTSA_MIN 0x638
#define MC_FTOP_PTSA_RATE 0x50c
#define MC_A9AVPPC_PTSA_RATE 0x488
#define MC_VE2_PTSA_MIN 0x498
#define MC_USBX_PTSA_MAX 0x52c
#define MC_DIS_PTSA_RATE 0x41c
#define MC_USBD_PTSA_MAX 0x538
#define MC_A9AVPPC_PTSA_MAX 0x490
#define MC_USBX_PTSA_RATE 0x524
#define MC_FTOP_PTSA_MAX 0x514
#define MC_HDAPC_PTSA_MAX 0x630
#define MC_SD_PTSA_RATE 0x4d0
#define MC_DFD_PTSA_RATE 0x634
#define MC_FTOP_PTSA_MIN 0x510
#define MC_SDM_PTSA_RATE 0x61c
#define MC_AHB_PTSA_RATE 0x4dc
#define MC_SMMU_SMMU_PTSA_MAX 0x460
#define MC_RING2_PTSA_MIN 0x444
#define MC_SDM_PTSA_MIN 0x620
#define MC_APB_PTSA_RATE 0x4e8
#define MC_MSE_PTSA_MIN 0x4c8
#define MC_HOST_PTSA_RATE 0x518
#define MC_VE_PTSA_RATE 0x434
#define MC_AHB_PTSA_MAX 0x4e4
#define MC_SAX_PTSA_MIN 0x4bc
#define MC_SMMU_SMMU_PTSA_MIN 0x45c
#define MC_ISP_PTSA_MIN 0x4a4
#define MC_HOST_PTSA_MAX 0x520
#define MC_SAX_PTSA_MAX 0x4c0
#define MC_VE_PTSA_MIN 0x438
#define MC_GK_PTSA_MIN 0x540
#define MC_MSE_PTSA_MAX 0x4cc
#define MC_DISB_PTSA_MAX 0x430
#define MC_DISB_PTSA_MIN 0x42c
#define MC_SMMU_SMMU_PTSA_RATE 0x458
#define MC_VE2_PTSA_RATE 0x494
#define MC_GK_PTSA_RATE 0x53c
#define MC_PTSA_GRANT_DECREMENT 0x960
#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4
#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0
#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380
#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384
#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc
#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8
#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370
#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0
#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374
#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8
#define MC_LATENCY_ALLOWANCE_VIC_0 0x394
#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8
#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8
#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc
#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390
#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694
#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348
#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c
#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344
#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0
#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698
#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec
#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0
#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4
#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8
#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4
#define MC_LATENCY_ALLOWANCE_HC_1 0x314
#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0
#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4
#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c
#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec
#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320
#define MC_LATENCY_ALLOWANCE_VI2_0 0x398
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4
#define MC_LATENCY_ALLOWANCE_SATA_0 0x350
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690
#define MC_LATENCY_ALLOWANCE_HC_0 0x310
#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8
#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac
#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4
#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388
#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328
#define MC_LATENCY_ALLOWANCE_HDA_0 0x318
#define MC_MIN_LENGTH_APE_0 0xb34
#define MC_MIN_LENGTH_DCB_2 0x8a8
#define MC_MIN_LENGTH_A9AVP_0 0x950
#define MC_MIN_LENGTH_TSEC_0 0x93c
#define MC_MIN_LENGTH_DC_1 0x898
#define MC_MIN_LENGTH_AXIAP_0 0x94c
#define MC_MIN_LENGTH_ISP2B_0 0x930
#define MC_MIN_LENGTH_VI2_0 0x944
#define MC_MIN_LENGTH_DCB_0 0x8a0
#define MC_MIN_LENGTH_DCB_1 0x8a4
#define MC_MIN_LENGTH_PPCS_1 0x8f4
#define MC_MIN_LENGTH_NVJPG_0 0xb3c
#define MC_MIN_LENGTH_HDA_0 0x8c4
#define MC_MIN_LENGTH_NVENC_0 0x8d4
#define MC_MIN_LENGTH_SDMMC_0 0xb18
#define MC_MIN_LENGTH_ISP2B_1 0x934
#define MC_MIN_LENGTH_HC_1 0x8c0
#define MC_MIN_LENGTH_DC_3 0xb20
#define MC_MIN_LENGTH_AVPC_0 0x890
#define MC_MIN_LENGTH_VIC_0 0x940
#define MC_MIN_LENGTH_ISP2_0 0x91c
#define MC_MIN_LENGTH_HC_0 0x8bc
#define MC_MIN_LENGTH_SE_0 0xb38
#define MC_MIN_LENGTH_NVDEC_0 0xb30
#define MC_MIN_LENGTH_SATA_0 0x8fc
#define MC_MIN_LENGTH_DC_0 0x894
#define MC_MIN_LENGTH_XUSB_1 0x92c
#define MC_MIN_LENGTH_DC_2 0x89c
#define MC_MIN_LENGTH_SDMMCAA_0 0xb14
#define MC_MIN_LENGTH_GPU_0 0xb04
#define MC_MIN_LENGTH_ETR_0 0xb44
#define MC_MIN_LENGTH_AFI_0 0x88c
#define MC_MIN_LENGTH_PPCS_0 0x8f0
#define MC_MIN_LENGTH_ISP2_1 0x920
#define MC_MIN_LENGTH_XUSB_0 0x928
#define MC_MIN_LENGTH_MPCORE_0 0x8cc
#define MC_MIN_LENGTH_TSECB_0 0xb48
#define MC_MIN_LENGTH_SDMMCA_0 0xb10
#define MC_MIN_LENGTH_GPU2_0 0xb40
#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c
#define MC_MIN_LENGTH_PTC_0 0x8f8
#define MC_EMEM_ARB_OVERRIDE_1 0x968
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988
#define MC_EMEM_ARB_STATS_0 0x990
#define MC_EMEM_ARB_STATS_1 0x994
#define MC_MTS_CARVEOUT_BOM 0x9a0
#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4
#define MC_MTS_CARVEOUT_ADR_HI 0x9a8
#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac
#define MC_ERR_MTS_STATUS 0x9b0
#define MC_ERR_MTS_ADR 0x9b4
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74
#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10
#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c
#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4
#define MC_SECURITY_CARVEOUT2_CFG0 0xc58
#define MC_SECURITY_CARVEOUT1_CFG0 0xc08
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68
#define MC_SECURITY_CARVEOUT3_BOM 0xcac
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60
#define MC_SECURITY_CARVEOUT3_CFG0 0xca8
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88
#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64
#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50
#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14
#define MC_SECURITY_CARVEOUT1_BOM 0xc0c
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c
#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8
#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60
#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80
#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc
#define MC_SECURITY_CARVEOUT4_BOM 0xcfc
#define MC_SECURITY_CARVEOUT5_CFG0 0xd48
#define MC_SECURITY_CARVEOUT2_BOM 0xc5c
#define MC_SECURITY_CARVEOUT5_BOM 0xd4c
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0
#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08
#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
#define MC_UNTRANSLATED_REGION_CHECK 0x948
#define MC_DA_CONFIG0 0x9dc
// MC_SECURITY_CARVEOUTX_CFG0
// Mode of LOCK_MODE.
#define PROTECT_MODE_SHIFT 0
#define SEC_CARVEOUT_CFG_SECURE (0 << PROTECT_MODE_SHIFT0)
#define SEC_CARVEOUT_CFG_TZ_SECURE (1 << PROTECT_MODE_SHIFT0)
// Enables PROTECT_MODE.
#define LOCK_MODE_SHIFT 1
#define SEC_CARVEOUT_CFG_UNLOCKED (0 << LOCK_MODE_SHIFT)
#define SEC_CARVEOUT_CFG_LOCKED (1 << LOCK_MODE_SHIFT)
#define ADDRESS_TYPE_SHIFT 2
#define SEC_CARVEOUT_CFG_ANY_ADDRESS (0 << ADDRESS_TYPE_SHIFT)
#define SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY (1 << ADDRESS_TYPE_SHIFT)
#define READ_ACCESS_LEVEL_SHIFT 3
#define SEC_CARVEOUT_CFG_RD_ALL (1 << READ_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_RD_UNK (2 << READ_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_RD_FALCON_LS (4 << READ_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_RD_FALCON_HS (8 << READ_ACCESS_LEVEL_SHIFT)
#define WRITE_ACCESS_LEVEL_SHIFT 7
#define SEC_CARVEOUT_CFG_WR_ALL (1 << WRITE_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_WR_UNK (2 << WRITE_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_WR_FALCON_LS (4 << WRITE_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_WR_FALCON_HS (8 << WRITE_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_APERTURE_ID_MASK (3 << 11)
#define DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT 14
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L0 (1 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L1 (2 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L2 (4 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L3 (8 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
#define DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT 18
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L0 (1 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L1 (2 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L2 (4 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L3 (8 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU BIT(22)
#define SEC_CARVEOUT_CFG_TZ_GLOBAL_WR_EN_BYPASS_CHECK BIT(23)
#define SEC_CARVEOUT_CFG_TZ_GLOBAL_RD_EN_BYPASS_CHECK BIT(24)
#define SEC_CARVEOUT_CFG_ALLOW_APERTURE_ID_MISMATCH BIT(25)
#define SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH BIT(26)
#define SEC_CARVEOUT_CFG_IS_WPR BIT(27)
#endif

170
bdk/mem/minerva.c Normal file
View File

@@ -0,0 +1,170 @@
/*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdlib.h>
#include "minerva.h"
#include <soc/clock.h>
#include <ianos/ianos.h>
#include <soc/clock.h>
#include <soc/fuse.h>
#include <soc/hw_init.h>
#include <soc/t210.h>
#include <utils/util.h>
extern volatile nyx_storage_t *nyx_str;
void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init()
{
u32 curr_ram_idx = 0;
minerva_cfg = NULL;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
//!TODO: Not supported on T210B01 yet.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
return 0;
#ifdef NYX
// Set table to nyx storage.
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
// Check if Minerva is already initialized.
if (mtc_cfg->init_done == MTC_INIT_MAGIC)
{
mtc_cfg->train_mode = OP_PERIODIC_TRAIN; // Retrain if needed.
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
minerva_cfg = (void *)ep_addr;
return !minerva_cfg ? 1 : 0;
}
else
{
mtc_config_t mtc_tmp;
mtc_tmp.mtc_table = mtc_cfg->mtc_table;
mtc_tmp.sdram_id = fuse_read_dramid(false);
mtc_tmp.init_done = MTC_NEW_MAGIC;
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp);
// Ensure that Minerva is new.
if (mtc_tmp.init_done == MTC_INIT_MAGIC)
minerva_cfg = (void *)ep_addr;
else
mtc_cfg->init_done = 0;
// Copy Minerva context to Nyx storage.
if (minerva_cfg)
memcpy(mtc_cfg, (void *)&mtc_tmp, sizeof(mtc_config_t));
}
#else
memset(mtc_cfg, 0, sizeof(mtc_config_t));
// Set table to nyx storage.
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
mtc_cfg->sdram_id = fuse_read_dramid(false);
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
// Ensure that Minerva is new.
if (mtc_cfg->init_done == MTC_INIT_MAGIC)
minerva_cfg = (void *)ep_addr;
else
mtc_cfg->init_done = 0;
#endif
if (!minerva_cfg)
return 1;
// Get current frequency
for (curr_ram_idx = 0; curr_ram_idx < 10; curr_ram_idx++)
{
if (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) == mtc_cfg->mtc_table[curr_ram_idx].clk_src_emc)
break;
}
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
mtc_cfg->rate_to = FREQ_204;
mtc_cfg->train_mode = OP_TRAIN;
minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = FREQ_800;
minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = FREQ_1600;
minerva_cfg(mtc_cfg, NULL);
// FSP WAR.
mtc_cfg->train_mode = OP_SWITCH;
mtc_cfg->rate_to = FREQ_800;
minerva_cfg(mtc_cfg, NULL);
// Switch to max.
mtc_cfg->rate_to = FREQ_1600;
minerva_cfg(mtc_cfg, NULL);
return 0;
}
void minerva_change_freq(minerva_freq_t freq)
{
if (!minerva_cfg)
return;
// Check if requested frequency is different. Do not allow otherwise because it will hang.
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
if (mtc_cfg->rate_from != freq)
{
mtc_cfg->rate_to = freq;
mtc_cfg->train_mode = OP_SWITCH;
minerva_cfg(mtc_cfg, NULL);
}
}
void minerva_prep_boot_freq()
{
if (!minerva_cfg)
return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
// Check if there's RAM OC. If not exit.
if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
return;
// FSP WAR.
minerva_change_freq(FREQ_204);
// Scale down to 800 MHz boot freq.
minerva_change_freq(FREQ_800);
}
void minerva_periodic_training()
{
if (!minerva_cfg)
return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
if (mtc_cfg->rate_from == FREQ_1600)
{
mtc_cfg->train_mode = OP_PERIODIC_TRAIN;
minerva_cfg(mtc_cfg, NULL);
}
}

66
bdk/mem/minerva.h Normal file
View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2019 CTCaer
*
* 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 _FE_MINERVA_H_
#define _FE_MINERVA_H_
#include "mtc_table.h"
#include <utils/types.h>
#define MTC_INIT_MAGIC 0x3043544D
#define MTC_NEW_MAGIC 0x5243544D
#define EMC_PERIODIC_TRAIN_MS 250
typedef struct
{
u32 rate_to;
u32 rate_from;
emc_table_t *mtc_table;
u32 table_entries;
emc_table_t *current_emc_table;
u32 train_mode;
u32 sdram_id;
u32 prev_temp;
bool emc_2X_clk_src_is_pllmb;
bool fsp_for_src_freq;
bool train_ram_patterns;
bool init_done;
} mtc_config_t;
enum train_mode_t
{
OP_SWITCH = 0,
OP_TRAIN = 1,
OP_TRAIN_SWITCH = 2,
OP_PERIODIC_TRAIN = 3,
OP_TEMP_COMP = 4
};
typedef enum
{
FREQ_204 = 204000,
FREQ_800 = 800000,
FREQ_1600 = 1600000
} minerva_freq_t;
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init();
void minerva_change_freq(minerva_freq_t freq);
void minerva_prep_boot_freq();
void minerva_periodic_training();
#endif

560
bdk/mem/mtc_table.h Normal file
View File

@@ -0,0 +1,560 @@
/*
* Minerva Training Cell
* DRAM Training for Tegra X1 SoC. Supports DDR2/3 and LPDDR3/4.
*
* Copyright (c) 2018 CTCaer <ctcaer@gmail.com>
*
* 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 _MTC_TABLE_H_
#define _MTC_TABLE_H_
#include <utils/types.h>
typedef struct
{
s32 pll_osc_in;
s32 pll_out;
u32 pll_feedback_div;
u32 pll_input_div;
u32 pll_post_div;
} pllm_clk_config_t;
typedef struct
{
u32 emc_rc_idx;
u32 emc_rfc_idx;
u32 emc_rfcpb_idx;
u32 emc_refctrl2_idx;
u32 emc_rfc_slr_idx;
u32 emc_ras_idx;
u32 emc_rp_idx;
u32 emc_r2w_idx;
u32 emc_w2r_idx;
u32 emc_r2p_idx;
u32 emc_w2p_idx;
u32 emc_r2r_idx;
u32 emc_tppd_idx;
u32 emc_ccdmw_idx;
u32 emc_rd_rcd_idx;
u32 emc_wr_rcd_idx;
u32 emc_rrd_idx;
u32 emc_rext_idx;
u32 emc_wext_idx;
u32 emc_wdv_chk_idx;
u32 emc_wdv_idx;
u32 emc_wsv_idx;
u32 emc_wev_idx;
u32 emc_wdv_mask_idx;
u32 emc_ws_duration_idx;
u32 emc_we_duration_idx;
u32 emc_quse_idx;
u32 emc_quse_width_idx;
u32 emc_ibdly_idx;
u32 emc_obdly_idx;
u32 emc_einput_idx;
u32 emc_mrw6_idx;
u32 emc_einput_duration_idx;
u32 emc_puterm_extra_idx;
u32 emc_puterm_width_idx;
u32 emc_qrst_idx;
u32 emc_qsafe_idx;
u32 emc_rdv_idx;
u32 emc_rdv_mask_idx;
u32 emc_rdv_early_idx;
u32 emc_rdv_early_mask_idx;
u32 emc_refresh_idx;
u32 emc_burst_refresh_num_idx;
u32 emc_pre_refresh_req_cnt_idx;
u32 emc_pdex2wr_idx;
u32 emc_pdex2rd_idx;
u32 emc_pchg2pden_idx;
u32 emc_act2pden_idx;
u32 emc_ar2pden_idx;
u32 emc_rw2pden_idx;
u32 emc_cke2pden_idx;
u32 emc_pdex2cke_idx;
u32 emc_pdex2mrr_idx;
u32 emc_txsr_idx;
u32 emc_txsrdll_idx;
u32 emc_tcke_idx;
u32 emc_tckesr_idx;
u32 emc_tpd_idx;
u32 emc_tfaw_idx;
u32 emc_trpab_idx;
u32 emc_tclkstable_idx;
u32 emc_tclkstop_idx;
u32 emc_mrw7_idx;
u32 emc_trefbw_idx;
u32 emc_odt_write_idx;
u32 emc_fbio_cfg5_idx;
u32 emc_fbio_cfg7_idx;
u32 emc_cfg_dig_dll_idx;
u32 emc_cfg_dig_dll_period_idx;
u32 emc_pmacro_ib_rxrt_idx;
u32 emc_cfg_pipe_1_idx;
u32 emc_cfg_pipe_2_idx;
u32 emc_pmacro_quse_ddll_rank0_4_idx;
u32 emc_pmacro_quse_ddll_rank0_5_idx;
u32 emc_pmacro_quse_ddll_rank1_4_idx;
u32 emc_pmacro_quse_ddll_rank1_5_idx;
u32 emc_mrw8_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank1_4_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank1_5_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_0_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_1_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_2_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_3_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_4_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_5_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_0_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_1_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_2_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_3_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_4_idx;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_5_idx;
u32 emc_pmacro_ddll_long_cmd_0_idx;
u32 emc_pmacro_ddll_long_cmd_1_idx;
u32 emc_pmacro_ddll_long_cmd_2_idx;
u32 emc_pmacro_ddll_long_cmd_3_idx;
u32 emc_pmacro_ddll_long_cmd_4_idx;
u32 emc_pmacro_ddll_short_cmd_0_idx;
u32 emc_pmacro_ddll_short_cmd_1_idx;
u32 emc_pmacro_ddll_short_cmd_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte0_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte1_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte2_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte3_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte4_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte5_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte6_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte7_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd0_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd1_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd2_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd3_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte0_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte1_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte2_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte3_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte4_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte5_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte6_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte7_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd0_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd0_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd0_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd0_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd1_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd1_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd1_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd1_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd2_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd2_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd2_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd2_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd3_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd3_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd3_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd3_3_idx;
u32 emc_txdsrvttgen_idx;
u32 emc_fdpd_ctrl_dq_idx;
u32 emc_fdpd_ctrl_cmd_idx;
u32 emc_fbio_spare_idx;
u32 emc_zcal_interval_idx;
u32 emc_zcal_wait_cnt_idx;
u32 emc_mrs_wait_cnt_idx;
u32 emc_mrs_wait_cnt2_idx;
u32 emc_auto_cal_channel_idx;
u32 emc_dll_cfg_0_idx;
u32 emc_dll_cfg_1_idx;
u32 emc_pmacro_autocal_cfg_common_idx;
u32 emc_pmacro_zctrl_idx;
u32 emc_cfg_idx;
u32 emc_cfg_pipe_idx;
u32 emc_dyn_self_ref_control_idx;
u32 emc_qpop_idx;
u32 emc_dqs_brlshft_0_idx;
u32 emc_dqs_brlshft_1_idx;
u32 emc_cmd_brlshft_2_idx;
u32 emc_cmd_brlshft_3_idx;
u32 emc_pmacro_pad_cfg_ctrl_idx;
u32 emc_pmacro_data_pad_rx_ctrl_idx;
u32 emc_pmacro_cmd_pad_rx_ctrl_idx;
u32 emc_pmacro_data_rx_term_mode_idx;
u32 emc_pmacro_cmd_rx_term_mode_idx;
u32 emc_pmacro_cmd_pad_tx_ctrl_idx;
u32 emc_pmacro_data_pad_tx_ctrl_idx;
u32 emc_pmacro_common_pad_tx_ctrl_idx;
u32 emc_pmacro_vttgen_ctrl_0_idx;
u32 emc_pmacro_vttgen_ctrl_1_idx;
u32 emc_pmacro_vttgen_ctrl_2_idx;
u32 emc_pmacro_brick_ctrl_rfu1_idx;
u32 emc_pmacro_cmd_brick_ctrl_fdpd_idx;
u32 emc_pmacro_brick_ctrl_rfu2_idx;
u32 emc_pmacro_data_brick_ctrl_fdpd_idx;
u32 emc_pmacro_bg_bias_ctrl_0_idx;
u32 emc_cfg_3_idx;
u32 emc_pmacro_tx_pwrd_0_idx;
u32 emc_pmacro_tx_pwrd_1_idx;
u32 emc_pmacro_tx_pwrd_2_idx;
u32 emc_pmacro_tx_pwrd_3_idx;
u32 emc_pmacro_tx_pwrd_4_idx;
u32 emc_pmacro_tx_pwrd_5_idx;
u32 emc_config_sample_delay_idx;
u32 emc_pmacro_tx_sel_clk_src_0_idx;
u32 emc_pmacro_tx_sel_clk_src_1_idx;
u32 emc_pmacro_tx_sel_clk_src_2_idx;
u32 emc_pmacro_tx_sel_clk_src_3_idx;
u32 emc_pmacro_tx_sel_clk_src_4_idx;
u32 emc_pmacro_tx_sel_clk_src_5_idx;
u32 emc_pmacro_ddll_bypass_idx;
u32 emc_pmacro_ddll_pwrd_0_idx;
u32 emc_pmacro_ddll_pwrd_1_idx;
u32 emc_pmacro_ddll_pwrd_2_idx;
u32 emc_pmacro_cmd_ctrl_0_idx;
u32 emc_pmacro_cmd_ctrl_1_idx;
u32 emc_pmacro_cmd_ctrl_2_idx;
u32 emc_tr_timing_0_idx;
u32 emc_tr_dvfs_idx;
u32 emc_tr_ctrl_1_idx;
u32 emc_tr_rdv_idx;
u32 emc_tr_qpop_idx;
u32 emc_tr_rdv_mask_idx;
u32 emc_mrw14_idx;
u32 emc_tr_qsafe_idx;
u32 emc_tr_qrst_idx;
u32 emc_training_ctrl_idx;
u32 emc_training_settle_idx;
u32 emc_training_vref_settle_idx;
u32 emc_training_ca_fine_ctrl_idx;
u32 emc_training_ca_ctrl_misc_idx;
u32 emc_training_ca_ctrl_misc1_idx;
u32 emc_training_ca_vref_ctrl_idx;
u32 emc_training_quse_cors_ctrl_idx;
u32 emc_training_quse_fine_ctrl_idx;
u32 emc_training_quse_ctrl_misc_idx;
u32 emc_training_quse_vref_ctrl_idx;
u32 emc_training_read_fine_ctrl_idx;
u32 emc_training_read_ctrl_misc_idx;
u32 emc_training_read_vref_ctrl_idx;
u32 emc_training_write_fine_ctrl_idx;
u32 emc_training_write_ctrl_misc_idx;
u32 emc_training_write_vref_ctrl_idx;
u32 emc_training_mpc_idx;
u32 emc_mrw15_idx;
} burst_regs_t;
typedef struct
{
u32 burst_regs[221];
u32 burst_reg_per_ch[8];
u32 shadow_regs_ca_train[221];
u32 shadow_regs_quse_train[221];
u32 shadow_regs_rdwr_train[221];
} burst_regs_table_t;
typedef struct
{
u32 ptfv_dqsosc_movavg_c0d0u0_idx;
u32 ptfv_dqsosc_movavg_c0d0u1_idx;
u32 ptfv_dqsosc_movavg_c0d1u0_idx;
u32 ptfv_dqsosc_movavg_c0d1u1_idx;
u32 ptfv_dqsosc_movavg_c1d0u0_idx;
u32 ptfv_dqsosc_movavg_c1d0u1_idx;
u32 ptfv_dqsosc_movavg_c1d1u0_idx;
u32 ptfv_dqsosc_movavg_c1d1u1_idx;
u32 ptfv_write_samples_idx;
u32 ptfv_dvfs_samples_idx;
u32 ptfv_movavg_weight_idx;
u32 ptfv_config_ctrl_idx;
} ptfv_list_table_t;
typedef struct
{
u32 emc0_mrw10_idx;
u32 emc1_mrw10_idx;
u32 emc0_mrw11_idx;
u32 emc1_mrw11_idx;
u32 emc0_mrw12_idx;
u32 emc1_mrw12_idx;
u32 emc0_mrw13_idx;
u32 emc1_mrw13_idx;
} burst_reg_per_ch_t;
typedef struct
{
u32 emc_pmacro_ib_ddll_long_dqs_rank0_0_idx;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_1_idx;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_2_idx;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_3_idx;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_0_idx;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_1_idx;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_2_idx;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_3_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte0_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte0_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte0_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte1_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte1_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte1_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte2_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte2_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte2_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte3_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte3_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte3_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte4_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte4_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte4_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte5_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte5_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte5_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte6_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte6_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte6_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte7_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte7_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank0_byte7_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte0_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte0_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte0_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte1_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte1_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte1_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte2_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte2_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte2_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte3_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte3_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte3_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte4_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte4_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte4_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte5_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte5_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte5_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte6_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte6_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte6_2_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte7_0_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte7_1_idx;
u32 emc_pmacro_ib_ddll_short_dq_rank1_byte7_2_idx;
u32 emc_pmacro_ib_vref_dqs_0_idx;
u32 emc_pmacro_ib_vref_dqs_1_idx;
u32 emc_pmacro_ib_vref_dq_0_idx;
u32 emc_pmacro_ib_vref_dq_1_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank0_0_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank0_1_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank0_2_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank0_3_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank0_4_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank0_5_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank1_0_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank1_1_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank1_2_idx;
u32 emc_pmacro_ob_ddll_long_dq_rank1_3_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte0_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte0_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte0_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte1_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte1_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte1_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte2_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte2_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte2_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte3_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte3_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte3_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte4_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte4_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte4_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte5_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte5_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte5_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte6_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte6_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte6_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte7_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte7_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_byte7_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd0_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd0_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd0_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd1_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd1_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd1_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd2_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd2_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd2_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd3_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd3_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd3_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte0_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte0_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte0_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte1_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte1_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte1_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte2_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte2_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte2_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte3_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte3_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte3_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte4_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte4_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte4_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte5_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte5_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte5_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte6_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte6_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte6_2_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte7_0_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte7_1_idx;
u32 emc_pmacro_ob_ddll_short_dq_rank1_byte7_2_idx;
u32 emc_pmacro_quse_ddll_rank0_0_idx;
u32 emc_pmacro_quse_ddll_rank0_1_idx;
u32 emc_pmacro_quse_ddll_rank0_2_idx;
u32 emc_pmacro_quse_ddll_rank0_3_idx;
u32 emc_pmacro_quse_ddll_rank1_0_idx;
u32 emc_pmacro_quse_ddll_rank1_1_idx;
u32 emc_pmacro_quse_ddll_rank1_2_idx;
u32 emc_pmacro_quse_ddll_rank1_3_idx;
} trim_regs_t;
typedef struct
{
u32 emc_cmd_brlshft_0_idx;
u32 emc_cmd_brlshft_1_idx;
u32 emc0_data_brlshft_0_idx;
u32 emc1_data_brlshft_0_idx;
u32 emc0_data_brlshft_1_idx;
u32 emc1_data_brlshft_1_idx;
u32 emc_quse_brlshft_0_idx;
u32 emc_quse_brlshft_1_idx;
u32 emc_quse_brlshft_2_idx;
u32 emc_quse_brlshft_3_idx;
} trim_perch_regs_t;
typedef struct
{
u32 t_rp;
u32 t_fc_lpddr4;
u32 t_rfc;
u32 t_pdex;
u32 rl;
} dram_timings_t;
typedef struct
{
u32 emc0_training_opt_dqs_ib_vref_rank0_idx;
u32 emc1_training_opt_dqs_ib_vref_rank0_idx;
u32 emc0_training_opt_dqs_ib_vref_rank1_idx;
u32 emc1_training_opt_dqs_ib_vref_rank1_idx;
} vref_perch_regs_t;
typedef struct
{
u32 trim_regs[138];
u32 trim_perch_regs[10];
u32 vref_perch_regs[4];
} trim_regs_table_t;
typedef struct
{
u32 rev;
char dvfs_ver[60];
u32 rate_khz;
u32 min_volt;
u32 gpu_min_volt;
char clock_src[32];
u32 clk_src_emc;
u32 needs_training;
u32 training_pattern;
u32 trained;
u32 periodic_training;
u32 trained_dram_clktree_c0d0u0;
u32 trained_dram_clktree_c0d0u1;
u32 trained_dram_clktree_c0d1u0;
u32 trained_dram_clktree_c0d1u1;
u32 trained_dram_clktree_c1d0u0;
u32 trained_dram_clktree_c1d0u1;
u32 trained_dram_clktree_c1d1u0;
u32 trained_dram_clktree_c1d1u1;
u32 current_dram_clktree_c0d0u0;
u32 current_dram_clktree_c0d0u1;
u32 current_dram_clktree_c0d1u0;
u32 current_dram_clktree_c0d1u1;
u32 current_dram_clktree_c1d0u0;
u32 current_dram_clktree_c1d0u1;
u32 current_dram_clktree_c1d1u0;
u32 current_dram_clktree_c1d1u1;
u32 run_clocks;
u32 tree_margin;
u32 num_burst;
u32 num_burst_per_ch;
u32 num_trim;
u32 num_trim_per_ch;
u32 num_mc_regs;
u32 num_up_down;
u32 vref_num;
u32 training_mod_num;
u32 dram_timing_num;
ptfv_list_table_t ptfv_list;
burst_regs_t burst_regs;
burst_reg_per_ch_t burst_reg_per_ch;
burst_regs_t shadow_regs_ca_train;
burst_regs_t shadow_regs_quse_train;
burst_regs_t shadow_regs_rdwr_train;
trim_regs_t trim_regs;
trim_perch_regs_t trim_perch_regs;
vref_perch_regs_t vref_perch_regs;
dram_timings_t dram_timings;
u32 training_mod_regs[20];
u32 save_restore_mod_regs[12];
u32 burst_mc_regs[33];
u32 la_scale_regs[24];
u32 min_mrs_wait;
u32 emc_mrw;
u32 emc_mrw2;
u32 emc_mrw3;
u32 emc_mrw4;
u32 emc_mrw9;
u32 emc_mrs;
u32 emc_emrs;
u32 emc_emrs2;
u32 emc_auto_cal_config;
u32 emc_auto_cal_config2;
u32 emc_auto_cal_config3;
u32 emc_auto_cal_config4;
u32 emc_auto_cal_config5;
u32 emc_auto_cal_config6;
u32 emc_auto_cal_config7;
u32 emc_auto_cal_config8;
u32 emc_cfg_2;
u32 emc_sel_dpd_ctrl;
u32 emc_fdpd_ctrl_cmd_no_ramp;
u32 dll_clk_src;
u32 clk_out_enb_x_0_clk_enb_emc_dll;
u32 latency;
} emc_table_t;
#endif

1510
bdk/mem/sdram.c Normal file

File diff suppressed because it is too large Load Diff

129
bdk/mem/sdram.h Normal file
View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2020-2021 CTCaer
*
* 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 _SDRAM_H_
#define _SDRAM_H_
#include <mem/emc.h>
/*
* Tegra X1/X1+ EMC/DRAM Bandwidth Chart:
*
* Note: BWbits T210 = Hz x ddr x bus width x channels = Hz x 2 x 32 x 2.
* BWbits T210B01 = Hz x ddr x bus width x channels = Hz x 2 x 64 x 2.
* Both assume that both sub-partitions are used and thus reaching max
* bandwidth per channel. (T210: 2x16-bit, T210B01: 2x32-bit).
* Retail Mariko use one sub-partition, in order to meet Erista perf.
*
* T210 T210B01
* 40.8 MHz: 0.61 1.22 GiB/s
* 68.0 MHz: 1.01 2.02 GiB/s
* 102.0 MHz: 1.52 3.04 GiB/s
* 204.0 MHz: 3.04 6.08 GiB/s <-- Tegra X1/X1+ Init/SC7 Frequency
* 408.0 MHz: 6.08 12.16 GiB/s
* 665.6 MHz: 9.92 19.84 GiB/s
* 800.0 MHz: 11.92 23.84 GiB/s <-- Tegra X1/X1+ Nvidia OS Boot Frequency
* 1065.6 MHz: 15.89 31.78 GiB/s
* 1331.2 MHz: 19.84 39.68 GiB/s
* 1600.0 MHz: 23.84 47.68 GiB/s <-- Tegra X1/X1+ HOS Max Frequency
* 1862.4 MHz: 27.75 55.50 GiB/s <-- Tegra X1 Official Max Frequency
* 2131.2 MHz: 31.76 63.52 GiB/s <-- Tegra X1+ Official Max Frequency
*
*/
enum sdram_ids_erista
{
// LPDDR4 3200Mbps.
LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0,
LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1,
LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, // WT:C.
LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to Iowa Hynix 4GB 1Y-A.
LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4,
LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, // Changed to Hoag Hynix 4GB 1Y-A.
LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, // Changed to Aula Hynix 4GB 1Y-A.
};
enum sdram_ids_mariko
{
// LPDDR4X 4266Mbps.
LPDDR4X_IOWA_4GB_HYNIX_1Y_A = 3, // Replaced from Copper.
LPDDR4X_HOAG_4GB_HYNIX_1Y_A = 5, // Replaced from Copper.
LPDDR4X_AULA_4GB_HYNIX_1Y_A = 6, // Replaced from Copper.
// LPDDR4X 3733Mbps.
LPDDR4X_IOWA_4GB_SAMSUNG_X1X2 = 7,
LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, // Die-M.
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, // Die-M.
LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, // Die-M.
LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, // 4266Mbps. Die-E.
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, // Die-M.
LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, // Die-M.
LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, // Die-M.
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, // 4266Mbps. Die-E.
// LPDDR4X 4266Mbps.
LPDDR4X_IOWA_4GB_SAMSUNG_Y = 16,
LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, // Die-A.
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, // Die-A.
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, // Die-A.
LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20,
LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21,
// LPDDR4X_AULA_8GB_SAMSUNG_1Y_A = 22, // Unused.
LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, // Die-A.
LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, // Die-A.
LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, // 4266Mbps. Die-F.
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, // 4266Mbps. Die-F.
LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, // 4266Mbps. Die-F.
LPDDR4X_AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, // Die-A.
};
enum sdram_codes_mariko
{
LPDDR4X_NO_PATCH = 0,
LPDDR4X_UNUSED = 0,
// LPDDR4X_4GB_SAMSUNG_K4U6E3S4AM_MGCJ DRAM IDs: 08, 12.
// LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLHR_NME DRAM IDs: 10, 14.
LPDDR4X_4GB_SAMSUNG_X1X2 = 1, // DRAM IDs: 07.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 2, // DRAM IDs: 09, 13.
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE = 3, // DRAM IDs: 11, 15.
LPDDR4X_4GB_SAMSUNG_Y = 4, // DRAM IDs: 16.
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 5, // DRAM IDs: 17, 19, 24.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 6, // DRAM IDs: 18, 23, 28.
LPDDR4X_4GB_SAMSUNG_1Y_Y = 7, // DRAM IDs: 20.
LPDDR4X_8GB_SAMSUNG_1Y_Y = 8, // DRAM IDs: 21.
//LPDDR4X_8GB_SAMSUNG_1Y_A = 9, // DRAM IDs: 22. Unused.
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF = 10, // DRAM IDs: 25, 26, 27.
LPDDR4X_4GB_HYNIX_1Y_A = 11, // DRAM IDs: 03, 05, 06.
};
void sdram_init();
void *sdram_get_params_patched();
void *sdram_get_params_t210b01();
void sdram_lp0_save_params(const void *params);
emc_mr_data_t sdram_read_mrx(emc_mr_t mrx);
#endif

696
bdk/mem/sdram_config.inl Normal file
View File

@@ -0,0 +1,696 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2020-2021 CTCaer
*
* 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/>.
*/
#define DRAM_CFG_T210_SIZE 1896
#define DRAM_ID(x) BIT(x)
static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
/* Specifies the type of memory device */
.memory_type = MEMORY_TYPE_LPDDR4,
/* MC/EMC clock source configuration */
.pllm_input_divider = 0x00000001, // M div.
.pllm_feedback_divider = 0x00000022, // N div.
.pllm_stable_time = 0x0000012C,
.pllm_setup_control = 0x00000000,
.pllm_post_divider = 0x00000000, // P div.
.pllm_kcp = 0x00000000,
.pllm_kvco = 0x00000000,
/* Spare BCT params */
.emc_bct_spare0 = 0x00000000,
.emc_bct_spare1 = 0x00000000,
.emc_bct_spare2 = 0x00000000,
.emc_bct_spare3 = 0x00000000,
.emc_bct_spare4 = 0x7001BC68, // EMC_PMACRO_COMMON_PAD_TX_CTRL.
.emc_bct_spare5 = 0x0000000A,
.emc_bct_spare6 = 0x7001B404, // EMC_SWIZZLE_RANK0_BYTE0.
.emc_bct_spare7 = 0x76543201,
.emc_bct_spare8 = 0x7000E6C8, // APBDEV_PMC_WEAK_BIAS.
.emc_bct_spare9 = 0x00000000,
.emc_bct_spare10 = 0x00000000,
.emc_bct_spare11 = 0x00000000,
.emc_bct_spare12 = 0x00000000, // Used to hold EMC_PMACRO_BG_BIAS_CTRL.
.emc_bct_spare13 = 0x00000034,
/* EMC clock configuration */
.emc_clock_source = 0x40188002,
.emc_clock_source_dll = 0x40000000,
.clk_rst_pllm_misc20_override = 0x00000000,
.clk_rst_pllm_misc20_override_enable = 0x00000000,
.clear_clock2_mc1 = 0x00000000,
/* Auto-calibration of EMC pads */
.emc_auto_cal_interval = 0x001FFFFF,
.emc_auto_cal_config = 0xA01A51D8,
.emc_auto_cal_config2 = 0x05500000,
.emc_auto_cal_config3 = 0x00770000,
.emc_auto_cal_config4 = 0x00770000,
.emc_auto_cal_config5 = 0x00770000,
.emc_auto_cal_config6 = 0x00770000,
.emc_auto_cal_config7 = 0x00770000,
.emc_auto_cal_config8 = 0x00770000,
.emc_auto_cal_vref_sel0 = 0xB3AFA6A6,
.emc_auto_cal_vref_sel1 = 0x00009E3C,
.emc_auto_cal_channel = 0xC1E00303,
.emc_pmacro_auto_cal_cfg0 = 0x04040404,
.emc_pmacro_auto_cal_cfg1 = 0x04040404,
.emc_pmacro_auto_cal_cfg2 = 0x00000000,
.emc_pmacro_rx_term = 0x1F1F1F1F,
.emc_pmacro_dq_tx_drive = 0x1F1F1F1F,
.emc_pmacro_ca_tx_drive = 0x1F1F1F1F,
.emc_pmacro_cmd_tx_drive = 0x00001F1F,
.emc_pmacro_auto_cal_common = 0x00000804,
.emc_pmacro_zcrtl = 0x00000550,
/* Specifies the time for the calibration to stabilize (in microseconds) */
.emc_auto_cal_wait = 0x000001A1,
.emc_xm2_comp_pad_ctrl = 0x00000032,
.emc_xm2_comp_pad_ctrl2 = 0x00000000,
.emc_xm2_comp_pad_ctrl3 = 0x00000000,
/*
* DRAM size information
* Specifies the value for EMC_ADR_CFG
*/
.emc_adr_cfg = 0x00000001, // 2 Ranks.
/*
* Specifies the time to wait after asserting pin
* CKE (in microseconds)
*/
.emc_pin_program_wait = 0x00000002,
/* Specifies the extra delay before/after pin RESET/CKE command */
.emc_pin_extra_wait = 0x00000000,
.emc_pin_gpio_enable = 0x00000003,
.emc_pin_gpio = 0x00000003,
/* Specifies the extra delay after the first writing of EMC_TIMING_CONTROL */
.emc_timing_control_wait = 0x0000001E,
/* Timing parameters required for the SDRAM */
.emc_rc = 0x0000000D,
.emc_rfc = 0x00000025,
.emc_rfc_pb = 0x00000013,
.emc_ref_ctrl2 = 0x00000000,
.emc_rfc_slr = 0x00000000,
.emc_ras = 0x00000009,
.emc_rp = 0x00000004,
.emc_r2r = 0x00000000,
.emc_w2w = 0x00000000,
.emc_r2w = 0x0000000B,
.emc_w2r = 0x0000000D,
.emc_r2p = 0x00000008,
.emc_w2p = 0x0000000B,
.emc_tppd = 0x00000004,
.emc_ccdmw = 0x00000020,
.emc_rd_rcd = 0x00000006,
.emc_wr_rcd = 0x00000006,
.emc_rrd = 0x00000006,
.emc_rext = 0x00000003,
.emc_wext = 0x00000000,
.emc_wdv = 0x00000004,
.emc_wdv_chk = 0x00000006,
.emc_wsv = 0x00000002,
.emc_wev = 0x00000000,
.emc_wdv_mask = 0x00000004,
.emc_ws_duration = 0x00000008,
.emc_we_duration = 0x0000000D,
.emc_quse = 0x00000005,
.emc_quse_width = 0x00000006,
.emc_ibdly = 0x00000000,
.emc_obdly = 0x00000000,
.emc_einput = 0x00000002,
.emc_einput_duration = 0x0000000D,
.emc_puterm_extra = 0x00000000,
.emc_puterm_width = 0x0000000B,
.emc_qrst = 0x00010000,
.emc_qsafe = 0x00000012,
.emc_rdv = 0x00000014,
.emc_rdv_mask = 0x00000016,
.emc_rdv_early = 0x00000012,
.emc_rdv_early_mask = 0x00000014,
.emc_qpop = 0x0000000A,
.emc_refresh = 0x00000304,
.emc_burst_refresh_num = 0x00000000,
.emc_prerefresh_req_cnt = 0x000000C1,
.emc_pdex2wr = 0x00000008,
.emc_pdex2rd = 0x00000008,
.emc_pchg2pden = 0x00000003,
.emc_act2pden = 0x00000003,
.emc_ar2pden = 0x00000003,
.emc_rw2pden = 0x00000014,
.emc_cke2pden = 0x00000005,
.emc_pdex2che = 0x00000002,
.emc_pdex2mrr = 0x0000000D,
.emc_txsr = 0x00000027,
.emc_txsr_dll = 0x00000027,
.emc_tcke = 0x00000005,
.emc_tckesr = 0x00000005,
.emc_tpd = 0x00000004,
.emc_tfaw = 0x00000009,
.emc_trpab = 0x00000005,
.emc_tclkstable = 0x00000004,
.emc_tclkstop = 0x00000009,
.emc_trefbw = 0x0000031C,
/* FBIO configuration values */
.emc_fbio_cfg5 = 0x9160A00D,
.emc_fbio_cfg7 = 0x00003BBF,
.emc_fbio_cfg8 = 0x0CF30000,
/* Command mapping for CMD brick 0 */
.emc_cmd_mapping_cmd0_0 = 0x061B0504,
.emc_cmd_mapping_cmd0_1 = 0x1C070302,
.emc_cmd_mapping_cmd0_2 = 0x05252523,
.emc_cmd_mapping_cmd1_0 = 0x0A091D08,
.emc_cmd_mapping_cmd1_1 = 0x0D1E0B24,
.emc_cmd_mapping_cmd1_2 = 0x0326260C,
.emc_cmd_mapping_cmd2_0 = 0x231C1B02,
.emc_cmd_mapping_cmd2_1 = 0x05070403,
.emc_cmd_mapping_cmd2_2 = 0x02252506,
.emc_cmd_mapping_cmd3_0 = 0x0D1D0B0A,
.emc_cmd_mapping_cmd3_1 = 0x1E090C08,
.emc_cmd_mapping_cmd3_2 = 0x08262624,
.emc_cmd_mapping_byte = 0x9A070624,
.emc_fbio_spare = 0x00000012,
.emc_cfg_rsv = 0xFF00FF00,
/* MRS command values */
.emc_mrs = 0x00000000,
.emc_emrs = 0x00000000,
.emc_emrs2 = 0x00000000,
.emc_emrs3 = 0x00000000,
.emc_mrw1 = 0x08010004,
.emc_mrw2 = 0x08020000,
.emc_mrw3 = 0x080D0000,
.emc_mrw4 = 0xC0000000,
.emc_mrw6 = 0x08037171,
.emc_mrw8 = 0x080B0000,
.emc_mrw9 = 0x0C0E7272,
.emc_mrw10 = 0x00000000,
.emc_mrw12 = 0x0C0D0808,
.emc_mrw13 = 0x0C0D0000,
.emc_mrw14 = 0x08161414,
.emc_mrw_extra = 0x08010004,
.emc_warm_boot_mrw_extra = 0x08110000,
.emc_warm_boot_extramode_reg_write_enable = 0x00000001,
.emc_extramode_reg_write_enable = 0x00000000,
.emc_mrw_reset_command = 0x00000000,
.emc_mrw_reset_ninit_wait = 0x00000000,
.emc_mrs_wait_cnt = 0x00CC0015,
.emc_mrs_wait_cnt2 = 0x0033000A,
/* EMC miscellaneous configurations */
.emc_cfg = 0xF3200000,
.emc_cfg2 = 0x00110805,
.emc_cfg_pipe = 0x0FFF0FFF,
.emc_cfg_pipe_clk = 0x00000000,
.emc_fdpd_ctrl_cmd_no_ramp = 0x00000001,
.emc_cfg_update = 0x70000301,
.emc_dbg = 0x01000C00,
.emc_dbg_write_mux = 0x00000001,
.emc_cmd_q = 0x10004408,
.emc_mc2emc_q = 0x06000404,
.emc_dyn_self_ref_control = 0x80000713,
.ahb_arbitration_xbar_ctrl_meminit_done = 0x00000001,
.emc_cfg_dig_dll = 0x002C00A0,
.emc_cfg_dig_dll_1 = 0x00003701,
.emc_cfg_dig_dll_period = 0x00008000,
.emc_dev_select = 0x00000000, // Both Ranks.
.emc_sel_dpd_ctrl = 0x00040008,
/* Pads trimmer delays */
.emc_fdpd_ctrl_dq = 0x8020221F,
.emc_fdpd_ctrl_cmd = 0x0220F40F,
.emc_pmacro_ib_vref_dq_0 = 0x28282828,
.emc_pmacro_ib_vref_dq_1 = 0x28282828,
.emc_pmacro_ib_vref_dqs_0 = 0x11111111,
.emc_pmacro_ib_vref_dqs_1 = 0x11111111,
.emc_pmacro_ib_rxrt = 0x000000BE,
.emc_cfg_pipe1 = 0x0FFF0FFF,
.emc_cfg_pipe2 = 0x0FFF0FFF,
.emc_pmacro_quse_ddll_rank0_0 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_1 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_2 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_3 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_4 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_5 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_0 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_1 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_2 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_3 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_4 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_5 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_0 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_1 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_2 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_3 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_4 = 0x00120014,
.emc_pmacro_ob_ddll_long_dq_rank0_5 = 0x00140010,
.emc_pmacro_ob_ddll_long_dq_rank1_0 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank1_1 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank1_2 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank1_3 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank1_4 = 0x00120014,
.emc_pmacro_ob_ddll_long_dq_rank1_5 = 0x00140010,
.emc_pmacro_ob_ddll_long_dqs_rank0_0 = 0x002E0030,
.emc_pmacro_ob_ddll_long_dqs_rank0_1 = 0x00300033,
.emc_pmacro_ob_ddll_long_dqs_rank0_2 = 0x00350033,
.emc_pmacro_ob_ddll_long_dqs_rank0_3 = 0x00320030,
.emc_pmacro_ob_ddll_long_dqs_rank0_4 = 0x00000005,
.emc_pmacro_ob_ddll_long_dqs_rank0_5 = 0x00000000,
.emc_pmacro_ob_ddll_long_dqs_rank1_0 = 0x002E0030,
.emc_pmacro_ob_ddll_long_dqs_rank1_1 = 0x00300033,
.emc_pmacro_ob_ddll_long_dqs_rank1_2 = 0x00350033,
.emc_pmacro_ob_ddll_long_dqs_rank1_3 = 0x00320030,
.emc_pmacro_ob_ddll_long_dqs_rank1_4 = 0x00000005,
.emc_pmacro_ob_ddll_long_dqs_rank1_5 = 0x00000000,
.emc_pmacro_ib_ddll_long_dqs_rank0_0 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank0_1 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank0_2 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank0_3 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank1_0 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank1_1 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank1_2 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank1_3 = 0x00280028,
.emc_pmacro_ddll_long_cmd_0 = 0x00140014,
.emc_pmacro_ddll_long_cmd_1 = 0x00120012,
.emc_pmacro_ddll_long_cmd_2 = 0x00100010,
.emc_pmacro_ddll_long_cmd_3 = 0x00140014,
.emc_pmacro_ddll_long_cmd_4 = 0x00000014,
.emc_pmacro_ddll_short_cmd_0 = 0x00000000,
.emc_pmacro_ddll_short_cmd_1 = 0x00000000,
.emc_pmacro_ddll_short_cmd_2 = 0x00000000,
/*
* Specifies the delay after asserting CKE pin during a WarmBoot0
* sequence (in microseconds)
*/
.warm_boot_wait = 0x00000001,
.emc_odt_write = 0x00000000,
/* Periodic ZQ calibration */
/*
* Specifies the value for EMC_ZCAL_INTERVAL
* Value 0 disables ZQ calibration
*/
.emc_zcal_interval = 0x00064000,
.emc_zcal_wait_cnt = 0x000900CC,
.emc_zcal_mrw_cmd = 0x0051004F,
/* DRAM initialization sequence flow control */
.emc_mrs_reset_dll = 0x00000000,
.emc_zcal_init_dev0 = 0x80000001,
.emc_zcal_init_dev1 = 0x40000001,
/*
* Specifies the wait time after programming a ZQ initialization
* command (in microseconds)
*/
.emc_zcal_init_wait = 0x00000001,
/*
* Specifies the enable for ZQ calibration at cold boot [bit 0]
* and warm boot [bit 1]
*/
.emc_zcal_warm_cold_boot_enables = 0x00000003,
/*
* Specifies the MRW command to LPDDR2 for ZQ calibration
* on warmboot
*/
/* Is issued to both devices separately */
.emc_mrw_lpddr2zcal_warm_boot = 0x040A00AB,
/*
* Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
* Is issued to both devices separately
*/
.emc_zqcal_ddr3_warm_boot = 0x00000011,
.emc_zqcal_lpddr4_warm_boot = 0x00000001,
/*
* Specifies the wait time for ZQ calibration on warmboot
* (in microseconds)
*/
.emc_zcal_warm_boot_wait = 0x00000001,
/*
* Specifies the enable for DRAM Mode Register programming
* at warm boot
*/
.emc_mrs_warm_boot_enable = 0x00000001,
.emc_mrs_reset_dll_wait = 0x00000000,
.emc_mrs_extra = 0x00000000,
.emc_warm_boot_mrs_extra = 0x00000000,
.emc_emrs_ddr2_dll_enable = 0x00000000,
.emc_mrs_ddr2_dll_reset = 0x00000000,
.emc_emrs_ddr2_ocd_calib = 0x00000000,
/*
* Specifies the wait between initializing DDR and setting OCD
* calibration (in microseconds)
*/
.emc_ddr2_wait = 0x00000000,
.emc_clken_override = 0x00000000,
/*
* Specifies LOG2 of the extra refresh numbers after booting
* Program 0 to disable
*/
.emc_extra_refresh_num = 0x00000002,
.emc_clken_override_allwarm_boot = 0x00000000,
.mc_clken_override_allwarm_boot = 0x00000000,
/* Specifies digital dll period, choosing between 4 to 64 ms */
.emc_cfg_dig_dll_period_warm_boot = 0x00000003,
/* Pad controls */
.pmc_vddp_sel = 0x00000001,
.pmc_vddp_sel_wait = 0x00000002,
.pmc_ddr_pwr = 0x0000000F,
.pmc_ddr_cfg = 0x04220100,
.pmc_io_dpd3_req = 0x4FAFFFFF,
.pmc_io_dpd3_req_wait = 0x00000001,
.pmc_io_dpd4_req_wait = 0x00000002,
.pmc_reg_short = 0x00000000,
.pmc_no_io_power = 0x00000000,
.pmc_ddr_ctrl_wait = 0x00000000,
.pmc_ddr_ctrl = 0x0007FF8B,
.emc_acpd_control = 0x00000000,
.emc_swizzle_rank0_byte0 = 0x76543201, // Overridden to 0x76543201 by spare6/7.
.emc_swizzle_rank0_byte1 = 0x65324710,
.emc_swizzle_rank0_byte2 = 0x25763410,
.emc_swizzle_rank0_byte3 = 0x25673401,
.emc_swizzle_rank1_byte0 = 0x32647501,
.emc_swizzle_rank1_byte1 = 0x34567201,
.emc_swizzle_rank1_byte2 = 0x56742310,
.emc_swizzle_rank1_byte3 = 0x67324501,
.emc_txdsrvttgen = 0x00000000,
.emc_data_brlshft0 = 0x00249249,
.emc_data_brlshft1 = 0x00249249,
.emc_dqs_brlshft0 = 0x00000000,
.emc_dqs_brlshft1 = 0x00000000,
.emc_cmd_brlshft0 = 0x00000000,
.emc_cmd_brlshft1 = 0x00000000,
.emc_cmd_brlshft2 = 0x0000001B,
.emc_cmd_brlshft3 = 0x0000001B,
.emc_quse_brlshft0 = 0x00000000,
.emc_quse_brlshft1 = 0x00000000,
.emc_quse_brlshft2 = 0x00000000,
.emc_quse_brlshft3 = 0x00000000,
.emc_dll_cfg0 = 0x1F13412F,
.emc_dll_cfg1 = 0x00010014,
.emc_pmc_scratch1 = 0x4FAFFFFF,
.emc_pmc_scratch2 = 0x7FFFFFFF,
.emc_pmc_scratch3 = 0x4006D70B,
.emc_pmacro_pad_cfg_ctrl = 0x00020000,
.emc_pmacro_vttgen_ctrl0 = 0x00030808,
.emc_pmacro_vttgen_ctrl1 = 0x00015C00,
.emc_pmacro_vttgen_ctrl2 = 0x00101010,
.emc_pmacro_brick_ctrl_rfu1 = 0x00001600,
.emc_pmacro_cmd_brick_ctrl_fdpd = 0x00000000,
.emc_pmacro_brick_ctrl_rfu2 = 0x00000000,
.emc_pmacro_data_brick_ctrl_fdpd = 0x00000000,
.emc_pmacro_bg_bias_ctrl0 = 0x00000034,
.emc_pmacro_data_pad_rx_ctrl = 0x00050037,
.emc_pmacro_cmd_pad_rx_ctrl = 0x00000000,
.emc_pmacro_data_rx_term_mode = 0x00000010,
.emc_pmacro_cmd_rx_term_mode = 0x00003000,
.emc_pmacro_data_pad_tx_ctrl = 0x02000111,
.emc_pmacro_common_pad_tx_ctrl = 0x00000008, // Overridden to 0x0000000A by spare4/5.
.emc_pmacro_cmd_pad_tx_ctrl = 0x0A000000,
.emc_cfg3 = 0x00000040,
.emc_pmacro_tx_pwrd0 = 0x10000000,
.emc_pmacro_tx_pwrd1 = 0x08000000,
.emc_pmacro_tx_pwrd2 = 0x08000000,
.emc_pmacro_tx_pwrd3 = 0x00000000,
.emc_pmacro_tx_pwrd4 = 0x00000000,
.emc_pmacro_tx_pwrd5 = 0x00001000,
.emc_config_sample_delay = 0x00000020,
.emc_pmacro_brick_mapping0 = 0x28091081,
.emc_pmacro_brick_mapping1 = 0x44A53293,
.emc_pmacro_brick_mapping2 = 0x76678A5B,
.emc_pmacro_tx_sel_clk_src0 = 0x00000000,
.emc_pmacro_tx_sel_clk_src1 = 0x00000000,
.emc_pmacro_tx_sel_clk_src2 = 0x00000000,
.emc_pmacro_tx_sel_clk_src3 = 0x00000000,
.emc_pmacro_tx_sel_clk_src4 = 0x00000000,
.emc_pmacro_tx_sel_clk_src5 = 0x00000000,
.emc_pmacro_ddll_bypass = 0xEFFFEFFF,
.emc_pmacro_ddll_pwrd0 = 0xC0C0C0C0,
.emc_pmacro_ddll_pwrd1 = 0xC0C0C0C0,
.emc_pmacro_ddll_pwrd2 = 0xDCDCDCDC,
.emc_pmacro_cmd_ctrl0 = 0x0A0A0A0A,
.emc_pmacro_cmd_ctrl1 = 0x0A0A0A0A,
.emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A,
/* DRAM size information */
.mc_emem_adr_cfg = 0x00000001, // 2 Ranks.
.mc_emem_adr_cfg_dev0 = 0x00070302, // Rank 0 Density 512MB.
.mc_emem_adr_cfg_dev1 = 0x00070302, // Rank 1 Density 512MB.
.mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
.mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
.mc_emem_adr_cfg_bank_mask1 = 0x39722800,
.mc_emem_adr_cfg_bank_mask2 = 0x4B9C1000,
/*
* Specifies the value for MC_EMEM_CFG which holds the external memory
* size (in KBytes)
*/
.mc_emem_cfg = 0x00001000, // 4GB total density.
/* MC arbitration configuration */
.mc_emem_arb_cfg = 0x08000001,
.mc_emem_arb_outstanding_req = 0x8000004C,
.emc_emem_arb_refpb_hp_ctrl = 0x000A1020,
.emc_emem_arb_refpb_bank_ctrl = 0x80001028,
.mc_emem_arb_timing_rcd = 0x00000001,
.mc_emem_arb_timing_rp = 0x00000000,
.mc_emem_arb_timing_rc = 0x00000003,
.mc_emem_arb_timing_ras = 0x00000001,
.mc_emem_arb_timing_faw = 0x00000002,
.mc_emem_arb_timing_rrd = 0x00000001,
.mc_emem_arb_timing_rap2pre = 0x00000002,
.mc_emem_arb_timing_wap2pre = 0x00000005,
.mc_emem_arb_timing_r2r = 0x00000002,
.mc_emem_arb_timing_w2w = 0x00000001,
.mc_emem_arb_timing_r2w = 0x00000004,
.mc_emem_arb_timing_w2r = 0x00000005,
.mc_emem_arb_timing_rfcpb = 0x00000004,
.mc_emem_arb_da_turns = 0x02020001,
.mc_emem_arb_da_covers = 0x00030201,
.mc_emem_arb_misc0 = 0x71C30504,
.mc_emem_arb_misc1 = 0x70000F0F,
.mc_emem_arb_misc2 = 0x00000000,
.mc_emem_arb_ring1_throttle = 0x001F0000,
.mc_emem_arb_override = 0x10000000,
.mc_emem_arb_override1 = 0x00000000,
.mc_emem_arb_rsv = 0xFF00FF00,
.mc_da_cfg0 = 0x00000001,
.mc_emem_arb_timing_ccdmw = 0x00000008,
.mc_clken_override = 0x00008000,
.mc_stat_control = 0x00000000,
.mc_video_protect_bom = 0xFFF00000,
.mc_video_protect_bom_adr_hi = 0x00000000,
.mc_video_protect_size_mb = 0x00000000,
.mc_video_protect_vpr_override = 0xE4BAC343,
.mc_video_protect_vpr_override1 = 0x00001ED3,
.mc_video_protect_gpu_override0 = 0x00000000,
.mc_video_protect_gpu_override1 = 0x00000000,
.mc_sec_carveout_bom = 0xFFF00000,
.mc_sec_carveout_adr_hi = 0x00000000,
.mc_sec_carveout_size_mb = 0x00000000,
.mc_video_protect_write_access = 0x00000000,
.mc_sec_carveout_protect_write_access = 0x00000000,
.mc_generalized_carveout1_bom = 0x00000000,
.mc_generalized_carveout1_bom_hi = 0x00000000,
.mc_generalized_carveout1_size_128kb = 0x00000008,
.mc_generalized_carveout1_access0 = 0x00000000,
.mc_generalized_carveout1_access1 = 0x00000000,
.mc_generalized_carveout1_access2 = 0x00300000,
.mc_generalized_carveout1_access3 = 0x03000000,
.mc_generalized_carveout1_access4 = 0x00000000,
.mc_generalized_carveout1_force_internal_access0 = 0x00000000,
.mc_generalized_carveout1_force_internal_access1 = 0x00000000,
.mc_generalized_carveout1_force_internal_access2 = 0x00000000,
.mc_generalized_carveout1_force_internal_access3 = 0x00000000,
.mc_generalized_carveout1_force_internal_access4 = 0x00000000,
.mc_generalized_carveout1_cfg0 = 0x04000C76,
.mc_generalized_carveout2_bom = 0x00000000,
.mc_generalized_carveout2_bom_hi = 0x00000000,
.mc_generalized_carveout2_size_128kb = 0x00000002,
.mc_generalized_carveout2_access0 = 0x00000000,
.mc_generalized_carveout2_access1 = 0x00000000,
.mc_generalized_carveout2_access2 = 0x03000000,
.mc_generalized_carveout2_access3 = 0x00000000,
.mc_generalized_carveout2_access4 = 0x00000300,
.mc_generalized_carveout2_force_internal_access0 = 0x00000000,
.mc_generalized_carveout2_force_internal_access1 = 0x00000000,
.mc_generalized_carveout2_force_internal_access2 = 0x00000000,
.mc_generalized_carveout2_force_internal_access3 = 0x00000000,
.mc_generalized_carveout2_force_internal_access4 = 0x00000000,
.mc_generalized_carveout2_cfg0 = 0x0440167E,
.mc_generalized_carveout3_bom = 0x00000000,
.mc_generalized_carveout3_bom_hi = 0x00000000,
.mc_generalized_carveout3_size_128kb = 0x00000000,
.mc_generalized_carveout3_access0 = 0x00000000,
.mc_generalized_carveout3_access1 = 0x00000000,
.mc_generalized_carveout3_access2 = 0x03000000,
.mc_generalized_carveout3_access3 = 0x00000000,
.mc_generalized_carveout3_access4 = 0x00000300,
.mc_generalized_carveout3_force_internal_access0 = 0x00000000,
.mc_generalized_carveout3_force_internal_access1 = 0x00000000,
.mc_generalized_carveout3_force_internal_access2 = 0x00000000,
.mc_generalized_carveout3_force_internal_access3 = 0x00000000,
.mc_generalized_carveout3_force_internal_access4 = 0x00000000,
.mc_generalized_carveout3_cfg0 = 0x04401E7E,
.mc_generalized_carveout4_bom = 0x00000000,
.mc_generalized_carveout4_bom_hi = 0x00000000,
.mc_generalized_carveout4_size_128kb = 0x00000008,
.mc_generalized_carveout4_access0 = 0x00000000,
.mc_generalized_carveout4_access1 = 0x00000000,
.mc_generalized_carveout4_access2 = 0x00300000,
.mc_generalized_carveout4_access3 = 0x00000000,
.mc_generalized_carveout4_access4 = 0x000000C0,
.mc_generalized_carveout4_force_internal_access0 = 0x00000000,
.mc_generalized_carveout4_force_internal_access1 = 0x00000000,
.mc_generalized_carveout4_force_internal_access2 = 0x00000000,
.mc_generalized_carveout4_force_internal_access3 = 0x00000000,
.mc_generalized_carveout4_force_internal_access4 = 0x00000000,
.mc_generalized_carveout4_cfg0 = 0x04002446,
.mc_generalized_carveout5_bom = 0x00000000,
.mc_generalized_carveout5_bom_hi = 0x00000000,
.mc_generalized_carveout5_size_128kb = 0x00000008,
.mc_generalized_carveout5_access0 = 0x00000000,
.mc_generalized_carveout5_access1 = 0x00000000,
.mc_generalized_carveout5_access2 = 0x00300000,
.mc_generalized_carveout5_access3 = 0x00000000,
.mc_generalized_carveout5_access4 = 0x00000000,
.mc_generalized_carveout5_force_internal_access0 = 0x00000000,
.mc_generalized_carveout5_force_internal_access1 = 0x00000000,
.mc_generalized_carveout5_force_internal_access2 = 0x00000000,
.mc_generalized_carveout5_force_internal_access3 = 0x00000000,
.mc_generalized_carveout5_force_internal_access4 = 0x00000000,
.mc_generalized_carveout5_cfg0 = 0x04002C46,
/* Specifies enable for CA training */
.emc_ca_training_enable = 0x00000000,
/* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */
.swizzle_rank_byte_encode = 0x000000EC,
/* Specifies enable and offset for patched boot rom write */
.boot_rom_patch_control = 0x00000000,
/* Specifies data for patched boot rom write */
.boot_rom_patch_data = 0x00000000,
.mc_mts_carveout_bom = 0xFFF00000,
.mc_mts_carveout_adr_hi = 0x00000000,
.mc_mts_carveout_size_mb = 0x00000000,
.mc_mts_carveout_reg_ctrl = 0x00000000
};
static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = {
// Hynix timing config.
{ 0x0000000D, 0x10C / 4, DRAM_ID(1) }, // emc_r2w.
{ 0x00000001, 0x16C / 4, DRAM_ID(1) }, // emc_puterm_extra.
{ 0x80000000, 0x170 / 4, DRAM_ID(1) }, // emc_puterm_width.
{ 0x00000210, 0x4F4 / 4, DRAM_ID(1) }, // emc_pmacro_data_rx_term_mode.
{ 0x00000005, 0x5C0 / 4, DRAM_ID(1) }, // mc_emem_arb_timing_r2w.
// Samsung 6GB density config.
{ 0x000C0302, 0x56C / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB Rank 0 density.
{ 0x000C0302, 0x570 / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density.
{ 0x00001800, 0x584 / 4, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density.
#ifdef CONFIG_SDRAM_COPPER_SUPPORT
// Copper prototype Samsung/Hynix/Micron timing configs.
{ 0x0000003A, 0xEC / 4, DRAM_ID(6) }, // emc_rfc. Auto refresh.
{ 0x0000001D, 0xF0 / 4, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh.
{ 0x0000000D, 0x10C / 4, DRAM_ID(5) }, // emc_r2w.
{ 0x00000001, 0x16C / 4, DRAM_ID(5) }, // emc_puterm_extra.
{ 0x80000000, 0x170 / 4, DRAM_ID(5) }, // emc_puterm_width.
{ 0x00000012, 0x1B0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden.
{ 0x0000003B, 0x1C0 / 4, DRAM_ID(6) }, // emc_txsr.
{ 0x0000003B, 0x1C4 / 4, DRAM_ID(6) }, // emc_txsr_dll.
{ 0x00000003, 0x1DC / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_tclkstable.
{ 0x00120015, 0x334 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x00160012, 0x338 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
{ 0x00120015, 0x34C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00160012, 0x350 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
{ 0x002F0032, 0x354 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00310032, 0x358 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00360034, 0x35C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0033002F, 0x360 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
{ 0x00000006, 0x364 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x002F0032, 0x36C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00310032, 0x370 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00360034, 0x374 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0033002F, 0x378 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
{ 0x00000006, 0x37C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00150015, 0x3A4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_0.
{ 0x00120012, 0x3AC / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_2.
{ 0x00160016, 0x3B0 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_3.
{ 0x00000015, 0x3B4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4.
{ 0x00000012, 0x49C / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2.
{ 0x00000012, 0x4A0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3.
{ 0x00000210, 0x4F4 / 4, DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode.
{ 0x00000005, 0x5C0 / 4, DRAM_ID(5) }, // mc_emem_arb_timing_r2w.
{ 0x00000007, 0x5C8 / 4, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh.
{ 0x72A30504, 0x5D4 / 4, DRAM_ID(6) }, // mc_emem_arb_misc0.
#endif
};

124
bdk/mem/sdram_config_lz.inl Normal file
View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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/>.
*/
static const u8 _dram_cfg_lz[1262] = {
0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
0x00, 0x2C, 0x17, 0x04, 0x09, 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08,
0x17, 0x10, 0x10, 0x00, 0x00, 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00,
0x00, 0x04, 0xB4, 0x01, 0x70, 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00,
0x70, 0x17, 0x10, 0x24, 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40,
0x00, 0x00, 0x00, 0x17, 0x04, 0x04, 0x17, 0x09, 0x18, 0xFF, 0xFF, 0x1F,
0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x77,
0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, 0x17, 0x08, 0x08, 0xA6, 0xA6,
0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x04, 0x04,
0x04, 0x04, 0x17, 0x04, 0x04, 0x17, 0x04, 0x3C, 0x1F, 0x1F, 0x1F, 0x1F,
0x17, 0x04, 0x04, 0x17, 0x06, 0x06, 0x00, 0x00, 0x04, 0x08, 0x17, 0x06,
0x46, 0xA1, 0x01, 0x00, 0x00, 0x32, 0x17, 0x0B, 0x64, 0x01, 0x17, 0x04,
0x7C, 0x17, 0x07, 0x0C, 0x03, 0x17, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1E,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13,
0x17, 0x0B, 0x2C, 0x09, 0x00, 0x00, 0x00, 0x17, 0x05, 0x5D, 0x17, 0x07,
0x10, 0x0B, 0x17, 0x07, 0x28, 0x08, 0x17, 0x07, 0x0C, 0x17, 0x04, 0x1C,
0x20, 0x00, 0x00, 0x00, 0x06, 0x17, 0x04, 0x04, 0x17, 0x07, 0x08, 0x17,
0x04, 0x50, 0x17, 0x04, 0x2C, 0x17, 0x04, 0x1C, 0x17, 0x04, 0x10, 0x17,
0x08, 0x6C, 0x17, 0x04, 0x10, 0x17, 0x04, 0x38, 0x17, 0x04, 0x40, 0x05,
0x17, 0x07, 0x1C, 0x17, 0x08, 0x58, 0x17, 0x04, 0x24, 0x17, 0x04, 0x18,
0x17, 0x08, 0x64, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14,
0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x09, 0x0C, 0x17, 0x05, 0x82,
0x58, 0x17, 0x07, 0x61, 0xC1, 0x17, 0x07, 0x50, 0x17, 0x04, 0x04, 0x17,
0x08, 0x81, 0x48, 0x17, 0x04, 0x04, 0x17, 0x04, 0x28, 0x17, 0x04, 0x60,
0x17, 0x08, 0x54, 0x27, 0x17, 0x04, 0x04, 0x17, 0x07, 0x14, 0x17, 0x04,
0x04, 0x04, 0x17, 0x07, 0x81, 0x58, 0x17, 0x0C, 0x0C, 0x1C, 0x03, 0x00,
0x00, 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x17, 0x04, 0x5A, 0xF3, 0x0C,
0x04, 0x05, 0x1B, 0x06, 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05,
0x08, 0x1D, 0x09, 0x0A, 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03,
0x02, 0x1B, 0x1C, 0x23, 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02,
0x0A, 0x0B, 0x1D, 0x0D, 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08,
0x24, 0x06, 0x07, 0x9A, 0x12, 0x17, 0x05, 0x83, 0x41, 0x00, 0xFF, 0x17,
0x10, 0x83, 0x6C, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00,
0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00,
0x00, 0x0B, 0x08, 0x72, 0x72, 0x0E, 0x0C, 0x17, 0x04, 0x20, 0x08, 0x08,
0x0D, 0x0C, 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x17, 0x06,
0x2C, 0x11, 0x08, 0x17, 0x10, 0x84, 0x67, 0x15, 0x00, 0xCC, 0x00, 0x0A,
0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, 0xFF,
0x0F, 0xFF, 0x0F, 0x17, 0x08, 0x83, 0x4C, 0x01, 0x03, 0x00, 0x70, 0x00,
0x0C, 0x00, 0x01, 0x17, 0x04, 0x0C, 0x08, 0x44, 0x00, 0x10, 0x04, 0x04,
0x00, 0x06, 0x13, 0x07, 0x00, 0x80, 0x17, 0x04, 0x10, 0xA0, 0x00, 0x2C,
0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x80, 0x17, 0x06, 0x48, 0x08, 0x00,
0x04, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28,
0x28, 0x28, 0x17, 0x04, 0x04, 0x11, 0x11, 0x11, 0x11, 0x17, 0x04, 0x04,
0xBE, 0x00, 0x00, 0x17, 0x05, 0x58, 0x17, 0x08, 0x5C, 0x17, 0x22, 0x85,
0x6A, 0x17, 0x1A, 0x1A, 0x14, 0x00, 0x12, 0x00, 0x10, 0x17, 0x05, 0x83,
0x0A, 0x17, 0x16, 0x18, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00,
0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x17, 0x05, 0x83, 0x0C, 0x17,
0x04, 0x20, 0x17, 0x18, 0x18, 0x28, 0x00, 0x28, 0x17, 0x04, 0x04, 0x17,
0x08, 0x08, 0x17, 0x10, 0x10, 0x00, 0x14, 0x17, 0x05, 0x5A, 0x17, 0x04,
0x5C, 0x17, 0x04, 0x5E, 0x17, 0x04, 0x0E, 0x17, 0x0E, 0x78, 0x17, 0x09,
0x82, 0x50, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51,
0x17, 0x08, 0x18, 0x80, 0x01, 0x00, 0x00, 0x40, 0x17, 0x04, 0x20, 0x03,
0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, 0x11, 0x17, 0x08, 0x82, 0x58,
0x17, 0x0C, 0x38, 0x17, 0x1B, 0x81, 0x6C, 0x17, 0x08, 0x85, 0x60, 0x17,
0x08, 0x86, 0x50, 0x17, 0x08, 0x86, 0x60, 0x17, 0x06, 0x83, 0x21, 0x22,
0x04, 0xFF, 0xFF, 0xAF, 0x4F, 0x17, 0x0C, 0x86, 0x74, 0x17, 0x08, 0x2C,
0x8B, 0xFF, 0x07, 0x17, 0x06, 0x81, 0x04, 0x32, 0x54, 0x76, 0x10, 0x47,
0x32, 0x65, 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75,
0x64, 0x32, 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45,
0x32, 0x67, 0x17, 0x04, 0x24, 0x49, 0x92, 0x24, 0x17, 0x04, 0x04, 0x17,
0x11, 0x7C, 0x1B, 0x17, 0x04, 0x04, 0x17, 0x13, 0x81, 0x14, 0x2F, 0x41,
0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x17, 0x04, 0x7C, 0xFF, 0xFF, 0xFF,
0x7F, 0x0B, 0xD7, 0x06, 0x40, 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03,
0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x17, 0x06, 0x86, 0x59,
0x17, 0x0F, 0x89, 0x14, 0x37, 0x17, 0x07, 0x82, 0x72, 0x10, 0x17, 0x06,
0x83, 0x0D, 0x00, 0x11, 0x01, 0x17, 0x05, 0x85, 0x39, 0x17, 0x04, 0x0E,
0x0A, 0x17, 0x07, 0x89, 0x29, 0x17, 0x04, 0x1B, 0x17, 0x08, 0x86, 0x77,
0x17, 0x09, 0x12, 0x20, 0x00, 0x00, 0x00, 0x81, 0x10, 0x09, 0x28, 0x93,
0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, 0x17, 0x18, 0x82, 0x2C, 0xFF,
0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0x17, 0x04, 0x04, 0xDC, 0xDC,
0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x17, 0x04, 0x04, 0x17, 0x04, 0x04,
0x17, 0x05, 0x82, 0x24, 0x03, 0x07, 0x17, 0x04, 0x04, 0x00, 0x00, 0x24,
0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, 0x00, 0x28, 0x72, 0x39, 0x00, 0x10,
0x9C, 0x4B, 0x17, 0x04, 0x64, 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00,
0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x17, 0x06, 0x85, 0x60, 0x17,
0x10, 0x82, 0x74, 0x17, 0x08, 0x08, 0x17, 0x08, 0x88, 0x00, 0x17, 0x04,
0x10, 0x04, 0x17, 0x0B, 0x87, 0x6C, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02,
0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x17, 0x08, 0x8B, 0x18,
0x1F, 0x17, 0x09, 0x81, 0x73, 0x00, 0xFF, 0x00, 0xFF, 0x17, 0x05, 0x86,
0x48, 0x17, 0x04, 0x0C, 0x17, 0x07, 0x86, 0x34, 0x00, 0x00, 0xF0, 0x17,
0x09, 0x87, 0x54, 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x17, 0x0C, 0x81,
0x52, 0x17, 0x0A, 0x1C, 0x17, 0x10, 0x81, 0x6C, 0x17, 0x0A, 0x82, 0x21,
0x17, 0x07, 0x82, 0x4D, 0x17, 0x0A, 0x8A, 0x1B, 0x17, 0x11, 0x2C, 0x76,
0x0C, 0x17, 0x0A, 0x8A, 0x67, 0x17, 0x0F, 0x84, 0x28, 0x17, 0x06, 0x34,
0x17, 0x17, 0x3A, 0x7E, 0x16, 0x40, 0x17, 0x0C, 0x8B, 0x1F, 0x17, 0x2A,
0x38, 0x1E, 0x17, 0x0A, 0x38, 0x17, 0x13, 0x81, 0x28, 0x00, 0xC0, 0x17,
0x17, 0x55, 0x46, 0x24, 0x17, 0x0A, 0x81, 0x28, 0x17, 0x14, 0x38, 0x17,
0x18, 0x81, 0x60, 0x46, 0x2C, 0x17, 0x06, 0x38, 0xEC, 0x17, 0x0D, 0x16,
0x17, 0x0E, 0x82, 0x3C, 0x17, 0x82, 0x0C, 0x8E, 0x68, 0x17, 0x04, 0x24,
0x17, 0x5C, 0x8E, 0x68, 0x17, 0x07, 0x82, 0x5F, 0x80, 0x17, 0x87, 0x01,
0x8E, 0x68, 0x02, 0x17, 0x81, 0x4A, 0x8E, 0x68, 0x17, 0x0C, 0x87, 0x78,
0x17, 0x85, 0x28, 0x8E, 0x68, 0x17, 0x8E, 0x68, 0x9D, 0x50, 0x17, 0x81,
0x24, 0x8E, 0x68, 0x17, 0x04, 0x2C, 0x17, 0x28, 0x8E, 0x68, 0x17, 0x04,
0x30, 0x17, 0x85, 0x3C, 0x8E, 0x68, 0x12, 0x17, 0x07, 0x85, 0x70, 0x17,
0x88, 0x74, 0x8E, 0x68, 0x17, 0x87, 0x3E, 0x9D, 0x50, 0x0C, 0x17, 0x04,
0x04, 0x17, 0x12, 0x8E, 0x68, 0x18, 0x17, 0x87, 0x12, 0xBB, 0x20, 0x17,
0x83, 0x04, 0x9D, 0x50, 0x15, 0x17, 0x05, 0x8D, 0x76, 0x17, 0x0F, 0x8B,
0x49, 0x17, 0x0B, 0x18, 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00,
0x34, 0x00, 0x36, 0x00, 0x2F, 0x00, 0x33, 0x17, 0x09, 0x84, 0x0C, 0x17,
0x18, 0x18, 0x17, 0x20, 0x8E, 0x68, 0x15, 0x17, 0x07, 0x5A, 0x17, 0x06,
0x5E, 0x16, 0x00, 0x15, 0x17, 0x82, 0x40, 0x9D, 0x50, 0x17, 0x86, 0x5F,
0xBB, 0x20, 0x3A, 0x00, 0x00, 0x00, 0x1D, 0x17, 0x81, 0x4F, 0xAC, 0x38,
0x3B, 0x17, 0x04, 0x04, 0x17, 0x86, 0x30, 0x8E, 0x68, 0x17, 0x81, 0x53,
0xAC, 0x38, 0x07, 0x17, 0x0D, 0x8E, 0x68, 0xA3, 0x72, 0x17, 0x83, 0x10,
0x8E, 0x68
};

View File

@@ -0,0 +1,992 @@
/*
* Copyright (c) 2020-2021 CTCaer
*
* 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/>.
*/
#define DRAM_CFG_T210B01_SIZE 2104
static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
/* Specifies the type of memory device */
.memory_type = MEMORY_TYPE_LPDDR4,
/* MC/EMC clock source configuration */
.pllm_input_divider = 0x00000001, // M div.
.pllm_feedback_divider = 0x00000022, // N div.
.pllm_stable_time = 0x0000012C,
.pllm_setup_control = 0x00000000,
.pllm_post_divider = 0x00000000, // P div.
.pllm_kcp = 0x00000000,
.pllm_kvco = 0x00000000,
/* Spare BCT params */
.emc_bct_spare0 = 0x00000000,
.emc_bct_spare1 = 0x00000000,
.emc_bct_spare2 = 0x00000000,
.emc_bct_spare3 = 0x00000000,
.emc_bct_spare4 = 0x00000000,
.emc_bct_spare5 = 0x00000000,
.emc_bct_spare6 = 0x00000000,
.emc_bct_spare7 = 0x00000000,
.emc_bct_spare8 = 0x00000000,
.emc_bct_spare9 = 0x00000000,
.emc_bct_spare10 = 0x00000000,
.emc_bct_spare11 = 0x00000000,
.emc_bct_spare12 = 0x00000000,
.emc_bct_spare13 = 0x00000000,
.emc_bct_spare_secure0 = 0x00000000,
.emc_bct_spare_secure1 = 0x00000000,
.emc_bct_spare_secure2 = 0x00000000,
.emc_bct_spare_secure3 = 0x00000000,
.emc_bct_spare_secure4 = 0x00000000,
.emc_bct_spare_secure5 = 0x00000000,
.emc_bct_spare_secure6 = 0x00000000,
.emc_bct_spare_secure7 = 0x00000000,
.emc_bct_spare_secure8 = 0x00000000,
.emc_bct_spare_secure9 = 0x00000000,
.emc_bct_spare_secure10 = 0x00000000,
.emc_bct_spare_secure11 = 0x00000000,
.emc_bct_spare_secure12 = 0x00000000,
.emc_bct_spare_secure13 = 0x00000000,
.emc_bct_spare_secure14 = 0x00000000,
.emc_bct_spare_secure15 = 0x00000000,
.emc_bct_spare_secure16 = 0x00000000,
.emc_bct_spare_secure17 = 0x00000000,
.emc_bct_spare_secure18 = 0x00000000,
.emc_bct_spare_secure19 = 0x00000000,
.emc_bct_spare_secure20 = 0x00000000,
.emc_bct_spare_secure21 = 0x00000000,
.emc_bct_spare_secure22 = 0x00000000,
.emc_bct_spare_secure23 = 0x00000000,
/* EMC clock configuration */
.emc_clock_source = 0x40188002,
.emc_clock_source_dll = 0x40000000,
.clk_rst_pllm_misc20_override = 0x00000000,
.clk_rst_pllm_misc20_override_enable = 0x00000000,
.clear_clock2_mc1 = 0x00000000,
/* Auto-calibration of EMC pads */
.emc_auto_cal_interval = 0x001FFFFF,
.emc_auto_cal_config = 0xA01A51D8,
.emc_auto_cal_config2 = 0x00000000,
.emc_auto_cal_config3 = 0x00880000,
.emc_auto_cal_config4 = 0x00880000,
.emc_auto_cal_config5 = 0x00001220,
.emc_auto_cal_config6 = 0x00880000,
.emc_auto_cal_config7 = 0x00880000,
.emc_auto_cal_config8 = 0x00880000,
.emc_auto_cal_config9 = 0x00000000,
.emc_auto_cal_vref_sel0 = 0xB3C5BCBC,
.emc_auto_cal_vref_sel1 = 0x00009E3C,
.emc_auto_cal_channel = 0xC1E00302,
.emc_pmacro_auto_cal_cfg0 = 0x04040404,
.emc_pmacro_auto_cal_cfg1 = 0x04040404,
.emc_pmacro_auto_cal_cfg2 = 0x04040404,
.emc_pmacro_rx_term = 0x3F3F3F3F,
.emc_pmacro_dq_tx_drive = 0x3F3F3F3F,
.emc_pmacro_ca_tx_drive = 0x3F3F3F3F,
.emc_pmacro_cmd_tx_drive = 0x00001220,
.emc_pmacro_auto_cal_common = 0x00000804,
.emc_pmacro_zcrtl = 0x00505050,
/* Specifies the time for the calibration to stabilize (in microseconds) */
.emc_auto_cal_wait = 0x000001A1,
.emc_xm2_comp_pad_ctrl = 0x00000030,
.emc_xm2_comp_pad_ctrl2 = 0x16001000,
.emc_xm2_comp_pad_ctrl3 = 0x00901000,
/*
* DRAM size information
* Specifies the value for EMC_ADR_CFG
*/
.emc_adr_cfg = 0x00000000, // 1 Rank.
/*
* Specifies the time to wait after asserting pin
* CKE (in microseconds)
*/
.emc_pin_program_wait = 0x00000002,
/* Specifies the extra delay before/after pin RESET/CKE command */
.emc_pin_extra_wait = 0x00000000,
.emc_pin_gpio_enable = 0x00000003,
.emc_pin_gpio = 0x00000003,
/* Specifies the extra delay after the first writing of EMC_TIMING_CONTROL */
.emc_timing_control_wait = 0x0000001E,
/* Timing parameters required for the SDRAM */
.emc_rc = 0x0000000D,
.emc_rfc = 0x0000003A,
.emc_rfc_pb = 0x0000001D,
.emc_ref_ctrl2 = 0x00000000,
.emc_rfc_slr = 0x00000000,
.emc_ras = 0x00000009,
.emc_rp = 0x00000004,
.emc_r2r = 0x00000000,
.emc_w2w = 0x00000000,
.emc_r2w = 0x0000000B,
.emc_w2r = 0x0000000D,
.emc_r2p = 0x00000008,
.emc_w2p = 0x0000000B,
.emc_tppd = 0x00000004,
.emc_trtm = 0x00000017,
.emc_twtm = 0x00000015,
.emc_tratm = 0x00000017,
.emc_twatm = 0x0000001B,
.emc_tr2ref = 0x00000000,
.emc_ccdmw = 0x00000020,
.emc_rd_rcd = 0x00000006,
.emc_wr_rcd = 0x00000006,
.emc_rrd = 0x00000006,
.emc_rext = 0x00000003,
.emc_wext = 0x00000000,
.emc_wdv = 0x00000004,
.emc_wdv_chk = 0x00000006,
.emc_wsv = 0x00000002,
.emc_wev = 0x00000000,
.emc_wdv_mask = 0x00000004,
.emc_ws_duration = 0x00000008,
.emc_we_duration = 0x0000000E,
.emc_quse = 0x00000005,
.emc_quse_width = 0x00000006,
.emc_ibdly = 0x00000000,
.emc_obdly = 0x00000000,
.emc_einput = 0x00000002,
.emc_einput_duration = 0x0000000D,
.emc_puterm_extra = 0x00000001,
.emc_puterm_width = 0x80000000,
.emc_qrst = 0x00010000,
.emc_qsafe = 0x00000012,
.emc_rdv = 0x00000018,
.emc_rdv_mask = 0x0000001A,
.emc_rdv_early = 0x00000016,
.emc_rdv_early_mask = 0x00000018,
.emc_qpop = 0x0000000A,
.emc_refresh = 0x00000304,
.emc_burst_refresh_num = 0x00000000,
.emc_prerefresh_req_cnt = 0x000000C1,
.emc_pdex2wr = 0x00000008,
.emc_pdex2rd = 0x00000008,
.emc_pchg2pden = 0x00000003,
.emc_act2pden = 0x0000000A,
.emc_ar2pden = 0x00000003,
.emc_rw2pden = 0x00000014,
.emc_cke2pden = 0x00000005,
.emc_pdex2che = 0x00000002,
.emc_pdex2mrr = 0x0000000D,
.emc_txsr = 0x0000003B,
.emc_txsr_dll = 0x0000003B,
.emc_tcke = 0x00000005,
.emc_tckesr = 0x00000005,
.emc_tpd = 0x00000004,
.emc_tfaw = 0x00000009,
.emc_trpab = 0x00000005,
.emc_tclkstable = 0x00000004,
.emc_tclkstop = 0x00000009,
.emc_trefbw = 0x0000031C,
/* FBIO configuration values */
.emc_fbio_cfg5 = 0x9160A00D,
.emc_fbio_cfg7 = 0x00003A3F,
.emc_fbio_cfg8 = 0x0CF30000,
/* Command mapping for CMD brick 0 */
.emc_cmd_mapping_cmd0_0 = 0x061B0504,
.emc_cmd_mapping_cmd0_1 = 0x1C070302,
.emc_cmd_mapping_cmd0_2 = 0x05252523,
.emc_cmd_mapping_cmd1_0 = 0x0A091D08,
.emc_cmd_mapping_cmd1_1 = 0x0D1E0B24,
.emc_cmd_mapping_cmd1_2 = 0x0326260C,
.emc_cmd_mapping_cmd2_0 = 0x231C1B02,
.emc_cmd_mapping_cmd2_1 = 0x05070403,
.emc_cmd_mapping_cmd2_2 = 0x02252506,
.emc_cmd_mapping_cmd3_0 = 0x0D1D0B0A,
.emc_cmd_mapping_cmd3_1 = 0x1E090C08,
.emc_cmd_mapping_cmd3_2 = 0x08262624,
.emc_cmd_mapping_byte = 0x9A070624,
.emc_fbio_spare = 0x00000012,
.emc_cfg_rsv = 0xFF00FF00,
/* MRS command values */
.emc_mrs = 0x00000000,
.emc_emrs = 0x00000000,
.emc_emrs2 = 0x00000000,
.emc_emrs3 = 0x00000000,
.emc_mrw1 = 0x88010004,
.emc_mrw2 = 0x88020000,
.emc_mrw3 = 0x880D0000,
.emc_mrw4 = 0xC0000000,
.emc_mrw6 = 0x88033131,
.emc_mrw8 = 0x880B0000,
.emc_mrw9 = 0x8C0E5D5D,
.emc_mrw10 = 0x880C5D5D,
.emc_mrw12 = 0x8C0D0808,
.emc_mrw13 = 0x8C0D0000,
.emc_mrw14 = 0x88161616,
.emc_mrw_extra = 0x88010004,
.emc_warm_boot_mrw_extra = 0x08110000,
.emc_warm_boot_extramode_reg_write_enable = 0x00000001,
.emc_extramode_reg_write_enable = 0x00000000,
.emc_mrw_reset_command = 0x00000000,
.emc_mrw_reset_ninit_wait = 0x00000000,
.emc_mrs_wait_cnt = 0x00CC0010,
.emc_mrs_wait_cnt2 = 0x0033000A,
/* EMC miscellaneous configurations */
.emc_cfg = 0xF3200000,
.emc_cfg2 = 0x00110825,
.emc_cfg_pipe = 0x0FFF0000,
.emc_cfg_pipe_clk = 0x00000000,
.emc_fdpd_ctrl_cmd_no_ramp = 0x00000001,
.emc_cfg_update = 0x70000301,
.emc_dbg = 0x01000C00,
.emc_dbg_write_mux = 0x00000001,
.emc_cmd_q = 0x10004408,
.emc_mc2emc_q = 0x06000404,
.emc_dyn_self_ref_control = 0x00000713,
.ahb_arbitration_xbar_ctrl_meminit_done = 0x00000001,
.emc_cfg_dig_dll = 0x002C00A0,
.emc_cfg_dig_dll_1 = 0x000F3701,
.emc_cfg_dig_dll_period = 0x00008000,
.emc_dev_select = 0x00000002, // Rank 0 only.
.emc_sel_dpd_ctrl = 0x0004000C,
/* Pads trimmer delays */
.emc_fdpd_ctrl_dq = 0x8020221F,
.emc_fdpd_ctrl_cmd = 0x0220F40F,
.emc_pmacro_ib_vref_dq_0 = 0x29292929,
.emc_pmacro_ib_vref_dq_1 = 0x29292929,
.emc_pmacro_ib_vref_dqs_0 = 0x29292929,
.emc_pmacro_ib_vref_dqs_1 = 0x29292929,
.emc_pmacro_ib_rxrt = 0x00000078,
.emc_cfg_pipe1 = 0x0FFF0000,
.emc_cfg_pipe2 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_0 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_1 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_2 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_3 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_4 = 0x00000000,
.emc_pmacro_quse_ddll_rank0_5 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_0 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_1 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_2 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_3 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_4 = 0x00000000,
.emc_pmacro_quse_ddll_rank1_5 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_0 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_1 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_2 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_3 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank0_4 = 0x000D0016,
.emc_pmacro_ob_ddll_long_dq_rank0_5 = 0x0017000B,
.emc_pmacro_ob_ddll_long_dq_rank1_0 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank1_1 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank1_2 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank1_3 = 0x00000000,
.emc_pmacro_ob_ddll_long_dq_rank1_4 = 0x000D0016,
.emc_pmacro_ob_ddll_long_dq_rank1_5 = 0x0017000B,
.emc_pmacro_ob_ddll_long_dqs_rank0_0 = 0x00450043,
.emc_pmacro_ob_ddll_long_dqs_rank0_1 = 0x00430045,
.emc_pmacro_ob_ddll_long_dqs_rank0_2 = 0x00470046,
.emc_pmacro_ob_ddll_long_dqs_rank0_3 = 0x00460041,
.emc_pmacro_ob_ddll_long_dqs_rank0_4 = 0x0003000C,
.emc_pmacro_ob_ddll_long_dqs_rank0_5 = 0x000D0000,
.emc_pmacro_ob_ddll_long_dqs_rank1_0 = 0x00450043,
.emc_pmacro_ob_ddll_long_dqs_rank1_1 = 0x00430045,
.emc_pmacro_ob_ddll_long_dqs_rank1_2 = 0x00470046,
.emc_pmacro_ob_ddll_long_dqs_rank1_3 = 0x00460041,
.emc_pmacro_ob_ddll_long_dqs_rank1_4 = 0x0003000C,
.emc_pmacro_ob_ddll_long_dqs_rank1_5 = 0x000D0000,
.emc_pmacro_ib_ddll_long_dqs_rank0_0 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank0_1 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank0_2 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank0_3 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank1_0 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank1_1 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank1_2 = 0x00280028,
.emc_pmacro_ib_ddll_long_dqs_rank1_3 = 0x00280028,
.emc_pmacro_ddll_long_cmd_0 = 0x00160016,
.emc_pmacro_ddll_long_cmd_1 = 0x000D000D,
.emc_pmacro_ddll_long_cmd_2 = 0x000B000B,
.emc_pmacro_ddll_long_cmd_3 = 0x00170017,
.emc_pmacro_ddll_long_cmd_4 = 0x00000016,
.emc_pmacro_ddll_short_cmd_0 = 0x00000000,
.emc_pmacro_ddll_short_cmd_1 = 0x00000000,
.emc_pmacro_ddll_short_cmd_2 = 0x00000000,
.emc_pmacro_ddll_periodic_offset = 0x00000000,
/*
* Specifies the delay after asserting CKE pin during a WarmBoot0
* sequence (in microseconds)
*/
.warm_boot_wait = 0x00000001,
.emc_odt_write = 0x00000000,
/* Periodic ZQ calibration */
/*
* Specifies the value for EMC_ZCAL_INTERVAL
* Value 0 disables ZQ calibration
*/
.emc_zcal_interval = 0x00064000,
.emc_zcal_wait_cnt = 0x000900CC,
.emc_zcal_mrw_cmd = 0x8051004F,
/* DRAM initialization sequence flow control */
.emc_mrs_reset_dll = 0x00000000,
.emc_zcal_init_dev0 = 0x80000001,
.emc_zcal_init_dev1 = 0x00000000,
/*
* Specifies the wait time after programming a ZQ initialization
* command (in microseconds)
*/
.emc_zcal_init_wait = 0x00000001,
/*
* Specifies the enable for ZQ calibration at cold boot [bit 0]
* and warm boot [bit 1]
*/
.emc_zcal_warm_cold_boot_enables = 0x00000003,
/*
* Specifies the MRW command to LPDDR2 for ZQ calibration
* on warmboot
*/
/* Is issued to both devices separately */
.emc_mrw_lpddr2zcal_warm_boot = 0x040A00AB,
/*
* Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
* Is issued to both devices separately
*/
.emc_zqcal_ddr3_warm_boot = 0x00000011,
.emc_zqcal_lpddr4_warm_boot = 0x00000001,
/*
* Specifies the wait time for ZQ calibration on warmboot
* (in microseconds)
*/
.emc_zcal_warm_boot_wait = 0x00000001,
/*
* Specifies the enable for DRAM Mode Register programming
* at warm boot
*/
.emc_mrs_warm_boot_enable = 0x00000001,
.emc_mrs_reset_dll_wait = 0x00000000,
.emc_mrs_extra = 0x00000000,
.emc_warm_boot_mrs_extra = 0x00000000,
.emc_emrs_ddr2_dll_enable = 0x00000000,
.emc_mrs_ddr2_dll_reset = 0x00000000,
.emc_emrs_ddr2_ocd_calib = 0x00000000,
/*
* Specifies the wait between initializing DDR and setting OCD
* calibration (in microseconds)
*/
.emc_ddr2_wait = 0x00000000,
.emc_clken_override = 0x00000000,
/*
* Specifies LOG2 of the extra refresh numbers after booting
* Program 0 to disable
*/
.emc_extra_refresh_num = 0x00000002,
.emc_clken_override_allwarm_boot = 0x00000000,
.mc_clken_override_allwarm_boot = 0x00000000,
/* Specifies digital dll period, choosing between 4 to 64 ms */
.emc_cfg_dig_dll_period_warm_boot = 0x00000003,
/* Pad controls */
.pmc_vddp_sel = 0x00000001,
.pmc_vddp_sel_wait = 0x00000002,
.pmc_ddr_cfg = 0x04220100,
.pmc_io_dpd3_req = 0x4FAF9FFF,
.pmc_io_dpd3_req_wait = 0x00000001,
.pmc_io_dpd4_req_wait = 0x00000002,
.pmc_reg_short = 0x00000000,
.pmc_no_io_power = 0x00000000,
.pmc_ddr_ctrl_wait = 0x00000000,
.pmc_ddr_ctrl = 0x0037FF9F,
.emc_acpd_control = 0x00000000,
.emc_swizzle_rank0_byte0 = 0x76543201,
.emc_swizzle_rank0_byte1 = 0x65324710,
.emc_swizzle_rank0_byte2 = 0x25763410,
.emc_swizzle_rank0_byte3 = 0x25673401,
.emc_swizzle_rank1_byte0 = 0x32647501,
.emc_swizzle_rank1_byte1 = 0x34567201,
.emc_swizzle_rank1_byte2 = 0x56742310,
.emc_swizzle_rank1_byte3 = 0x67324501,
.emc_txdsrvttgen = 0x00000000,
.emc_data_brlshft0 = 0x00249249,
.emc_data_brlshft1 = 0x00249249,
.emc_dqs_brlshft0 = 0x00000000,
.emc_dqs_brlshft1 = 0x00000000,
.emc_cmd_brlshft0 = 0x00000000,
.emc_cmd_brlshft1 = 0x00000000,
.emc_cmd_brlshft2 = 0x00000012,
.emc_cmd_brlshft3 = 0x00000012,
.emc_quse_brlshft0 = 0x00000000,
.emc_quse_brlshft1 = 0x00000000,
.emc_quse_brlshft2 = 0x00000000,
.emc_quse_brlshft3 = 0x00000000,
.emc_dll_cfg0 = 0x1F134120,
.emc_dll_cfg1 = 0x00010014,
.emc_pmc_scratch1 = 0x4FAF9FFF,
.emc_pmc_scratch2 = 0x7FFFFFFF,
.emc_pmc_scratch3 = 0x4036D71F,
.emc_pmacro_pad_cfg_ctrl = 0x00000000,
.emc_pmacro_vttgen_ctrl0 = 0x00090000,
.emc_pmacro_vttgen_ctrl1 = 0x00103400,
.emc_pmacro_vttgen_ctrl2 = 0x00000000,
.emc_pmacro_dsr_vttgen_ctrl0 = 0x00000009,
.emc_pmacro_brick_ctrl_rfu1 = 0x00000000,
.emc_pmacro_cmd_brick_ctrl_fdpd = 0x00000000,
.emc_pmacro_brick_ctrl_rfu2 = 0x00000000,
.emc_pmacro_data_brick_ctrl_fdpd = 0x00000000,
.emc_pmacro_bg_bias_ctrl0 = 0x00000000,
.emc_pmacro_data_pad_rx_ctrl = 0x05050003,
.emc_pmacro_cmd_pad_rx_ctrl = 0x05000000,
.emc_pmacro_data_rx_term_mode = 0x00000210,
.emc_pmacro_cmd_rx_term_mode = 0x00002000,
.emc_pmacro_data_pad_tx_ctrl = 0x00000421,
.emc_pmacro_cmd_pad_tx_ctrl = 0x00000000,
.emc_cfg3 = 0x00000040,
.emc_pmacro_tx_pwrd0 = 0x10000000,
.emc_pmacro_tx_pwrd1 = 0x00000000,
.emc_pmacro_tx_pwrd2 = 0x00000000,
.emc_pmacro_tx_pwrd3 = 0x00000000,
.emc_pmacro_tx_pwrd4 = 0x00400080,
.emc_pmacro_tx_pwrd5 = 0x00801004,
.emc_config_sample_delay = 0x00000020,
.emc_pmacro_brick_mapping0 = 0x28091081,
.emc_pmacro_brick_mapping1 = 0x44A53293,
.emc_pmacro_brick_mapping2 = 0x76678A5B,
.emc_pmacro_tx_sel_clk_src0 = 0x00000000,
.emc_pmacro_tx_sel_clk_src1 = 0x00000000,
.emc_pmacro_tx_sel_clk_src2 = 0x00000000,
.emc_pmacro_tx_sel_clk_src3 = 0x00000000,
.emc_pmacro_tx_sel_clk_src4 = 0x00000000,
.emc_pmacro_tx_sel_clk_src5 = 0x00000000,
.emc_pmacro_perbit_fgcg_ctrl0 = 0x00000000,
.emc_pmacro_perbit_fgcg_ctrl1 = 0x00000000,
.emc_pmacro_perbit_fgcg_ctrl2 = 0x00000000,
.emc_pmacro_perbit_fgcg_ctrl3 = 0x00000000,
.emc_pmacro_perbit_fgcg_ctrl4 = 0x00000000,
.emc_pmacro_perbit_fgcg_ctrl5 = 0x00000000,
.emc_pmacro_perbit_rfu_ctrl0 = 0x00000000,
.emc_pmacro_perbit_rfu_ctrl1 = 0x00000000,
.emc_pmacro_perbit_rfu_ctrl2 = 0x00000000,
.emc_pmacro_perbit_rfu_ctrl3 = 0x00000000,
.emc_pmacro_perbit_rfu_ctrl4 = 0x00000000,
.emc_pmacro_perbit_rfu_ctrl5 = 0x00000000,
.emc_pmacro_perbit_rfu1_ctrl0 = 0x00000000,
.emc_pmacro_perbit_rfu1_ctrl1 = 0x00000000,
.emc_pmacro_perbit_rfu1_ctrl2 = 0x00000000,
.emc_pmacro_perbit_rfu1_ctrl3 = 0x00000000,
.emc_pmacro_perbit_rfu1_ctrl4 = 0x00000000,
.emc_pmacro_perbit_rfu1_ctrl5 = 0x00000000,
.emc_pmacro_data_pi_ctrl = 0x00001010,
.emc_pmacro_cmd_pi_ctrl = 0x00001010,
.emc_pmacro_ddll_bypass = 0xEF00EF00,
.emc_pmacro_ddll_pwrd0 = 0x00000000,
.emc_pmacro_ddll_pwrd1 = 0x00000000,
.emc_pmacro_ddll_pwrd2 = 0x1C1C1C1C,
.emc_pmacro_cmd_ctrl0 = 0x00000000,
.emc_pmacro_cmd_ctrl1 = 0x00000000,
.emc_pmacro_cmd_ctrl2 = 0x00000000,
/* DRAM size information */
.mc_emem_adr_cfg = 0x00000000, // 1 Rank.
.mc_emem_adr_cfg_dev0 = 0x00080302, // Rank 0 Density 1024MB.
.mc_emem_adr_cfg_dev1 = 0x00080302, // Rank 1 Density 1024MB.
.mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
.mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
.mc_emem_adr_cfg_bank_mask1 = 0x39722800,
.mc_emem_adr_cfg_bank_mask2 = 0x4B9C1000,
/*
* Specifies the value for MC_EMEM_CFG which holds the external memory
* size (in KBytes)
*/
.mc_emem_cfg = 0x00001000, // 4GB total density.
/* MC arbitration configuration */
.mc_emem_arb_cfg = 0x08000001,
.mc_emem_arb_outstanding_req = 0x8000004C,
.emc_emem_arb_refpb_hp_ctrl = 0x000A1020,
.emc_emem_arb_refpb_bank_ctrl = 0x80001028,
.mc_emem_arb_timing_rcd = 0x00000001,
.mc_emem_arb_timing_rp = 0x00000000,
.mc_emem_arb_timing_rc = 0x00000003,
.mc_emem_arb_timing_ras = 0x00000001,
.mc_emem_arb_timing_faw = 0x00000002,
.mc_emem_arb_timing_rrd = 0x00000001,
.mc_emem_arb_timing_rap2pre = 0x00000002,
.mc_emem_arb_timing_wap2pre = 0x00000005,
.mc_emem_arb_timing_r2r = 0x00000001,
.mc_emem_arb_timing_w2w = 0x00000001,
.mc_emem_arb_timing_r2w = 0x00000004,
.mc_emem_arb_timing_w2r = 0x00000005,
.mc_emem_arb_timing_rfcpb = 0x00000007,
.mc_emem_arb_da_turns = 0x02020000,
.mc_emem_arb_da_covers = 0x00030201,
.mc_emem_arb_misc0 = 0x72A30504,
.mc_emem_arb_misc1 = 0x70000F0F,
.mc_emem_arb_misc2 = 0x00000000,
.mc_emem_arb_ring1_throttle = 0x001F0000,
.mc_emem_arb_override = 0x10000000,
.mc_emem_arb_override1 = 0x00000000,
.mc_emem_arb_rsv = 0xFF00FF00,
.mc_da_cfg0 = 0x00000001,
.mc_emem_arb_timing_ccdmw = 0x00000008,
.mc_clken_override = 0x00008000,
.mc_stat_control = 0x00000000,
.mc_video_protect_bom = 0xFFF00000,
.mc_video_protect_bom_adr_hi = 0x00000000,
.mc_video_protect_size_mb = 0x00000000,
.mc_video_protect_vpr_override = 0xE4BAC343,
.mc_video_protect_vpr_override1 = 0x06001ED3, // Add SE2, SE2B.
.mc_video_protect_gpu_override0 = 0x00000000,
.mc_video_protect_gpu_override1 = 0x00000000,
.mc_sec_carveout_bom = 0xFFF00000,
.mc_sec_carveout_adr_hi = 0x00000000,
.mc_sec_carveout_size_mb = 0x00000000,
.mc_video_protect_write_access = 0x00000000,
.mc_sec_carveout_protect_write_access = 0x00000000,
.mc_generalized_carveout1_bom = 0x00000000,
.mc_generalized_carveout1_bom_hi = 0x00000000,
.mc_generalized_carveout1_size_128kb = 0x00000008,
.mc_generalized_carveout1_access0 = 0x00000000,
.mc_generalized_carveout1_access1 = 0x00000000,
.mc_generalized_carveout1_access2 = 0x00300000,
.mc_generalized_carveout1_access3 = 0x03000000,
.mc_generalized_carveout1_access4 = 0x00000000,
.mc_generalized_carveout1_force_internal_access0 = 0x00000000,
.mc_generalized_carveout1_force_internal_access1 = 0x00000000,
.mc_generalized_carveout1_force_internal_access2 = 0x00000000,
.mc_generalized_carveout1_force_internal_access3 = 0x00000000,
.mc_generalized_carveout1_force_internal_access4 = 0x00000000,
.mc_generalized_carveout1_cfg0 = 0x04000C76,
.mc_generalized_carveout2_bom = 0x00000000,
.mc_generalized_carveout2_bom_hi = 0x00000000,
.mc_generalized_carveout2_size_128kb = 0x00000002,
.mc_generalized_carveout2_access0 = 0x00000000,
.mc_generalized_carveout2_access1 = 0x00000000,
.mc_generalized_carveout2_access2 = 0x03000000,
.mc_generalized_carveout2_access3 = 0x00000000,
.mc_generalized_carveout2_access4 = 0x00000300,
.mc_generalized_carveout2_force_internal_access0 = 0x00000000,
.mc_generalized_carveout2_force_internal_access1 = 0x00000000,
.mc_generalized_carveout2_force_internal_access2 = 0x00000000,
.mc_generalized_carveout2_force_internal_access3 = 0x00000000,
.mc_generalized_carveout2_force_internal_access4 = 0x00000000,
.mc_generalized_carveout2_cfg0 = 0x0440167E,
.mc_generalized_carveout3_bom = 0x00000000,
.mc_generalized_carveout3_bom_hi = 0x00000000,
.mc_generalized_carveout3_size_128kb = 0x00000000,
.mc_generalized_carveout3_access0 = 0x00000000,
.mc_generalized_carveout3_access1 = 0x00000000,
.mc_generalized_carveout3_access2 = 0x03000000,
.mc_generalized_carveout3_access3 = 0x00000000,
.mc_generalized_carveout3_access4 = 0x00000300,
.mc_generalized_carveout3_force_internal_access0 = 0x00000000,
.mc_generalized_carveout3_force_internal_access1 = 0x00000000,
.mc_generalized_carveout3_force_internal_access2 = 0x00000000,
.mc_generalized_carveout3_force_internal_access3 = 0x00000000,
.mc_generalized_carveout3_force_internal_access4 = 0x00000000,
.mc_generalized_carveout3_cfg0 = 0x04401E7E,
.mc_generalized_carveout4_bom = 0x00000000,
.mc_generalized_carveout4_bom_hi = 0x00000000,
.mc_generalized_carveout4_size_128kb = 0x00000008,
.mc_generalized_carveout4_access0 = 0x00000000,
.mc_generalized_carveout4_access1 = 0x00000000,
.mc_generalized_carveout4_access2 = 0x00300000,
.mc_generalized_carveout4_access3 = 0x00000000,
.mc_generalized_carveout4_access4 = 0x000000C0,
.mc_generalized_carveout4_force_internal_access0 = 0x00000000,
.mc_generalized_carveout4_force_internal_access1 = 0x00000000,
.mc_generalized_carveout4_force_internal_access2 = 0x00000000,
.mc_generalized_carveout4_force_internal_access3 = 0x00000000,
.mc_generalized_carveout4_force_internal_access4 = 0x00000000,
.mc_generalized_carveout4_cfg0 = 0x04002446,
.mc_generalized_carveout5_bom = 0x00000000,
.mc_generalized_carveout5_bom_hi = 0x00000000,
.mc_generalized_carveout5_size_128kb = 0x00000008,
.mc_generalized_carveout5_access0 = 0x00000000,
.mc_generalized_carveout5_access1 = 0x00000000,
.mc_generalized_carveout5_access2 = 0x00300000,
.mc_generalized_carveout5_access3 = 0x00000000,
.mc_generalized_carveout5_access4 = 0x00000000,
.mc_generalized_carveout5_force_internal_access0 = 0x00000000,
.mc_generalized_carveout5_force_internal_access1 = 0x00000000,
.mc_generalized_carveout5_force_internal_access2 = 0x00000000,
.mc_generalized_carveout5_force_internal_access3 = 0x00000000,
.mc_generalized_carveout5_force_internal_access4 = 0x00000000,
.mc_generalized_carveout5_cfg0 = 0x04002C46,
/* Specifies enable for CA training */
.emc_ca_training_enable = 0x00000000,
/* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */
.swizzle_rank_byte_encode = 0x000000EC,
/* Specifies enable and offset for patched boot rom write */
.boot_rom_patch_control = 0x00000000,
/* Specifies data for patched boot rom write */
.boot_rom_patch_data = 0x00000000,
.mc_mts_carveout_bom = 0xFFF00000,
.mc_mts_carveout_adr_hi = 0x00000000,
.mc_mts_carveout_size_mb = 0x00000000,
.mc_mts_carveout_reg_ctrl = 0x00000000,
/* Specifies the untranslated memory access control */
.mc_untranslated_region_check = 0x00000000,
/* Just a place holder for special usage when there is no BCT for certain registers */
.bct_na = 0x00000000,
};
//!TODO Find out what mc_video_protect_gpu_override0 and mc_video_protect_gpu_override1 new bits are.
static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
// Samsung LPDDR4X 4GB X1X2 for prototype Iowa.
{ 0x000E0022, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x001B0010, 0x3B0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
{ 0x000E0022, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x001B0010, 0x3C8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
{ 0x00490043, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00420045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00490047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x00460047, 0x3D8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
{ 0x00000016, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00100000, 0x3E0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_5.
{ 0x00490043, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00420045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00490047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x00460047, 0x3F0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
{ 0x00000016, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00100000, 0x3F8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_5.
{ 0x00220022, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000E000E, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00100010, 0x424 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_2.
{ 0x001B001B, 0x428 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_3.
{ 0x00000022, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_4.
// Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ Die-M for SDEV Iowa and Hoag.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_adr_cfg. 2 Ranks.
{ 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput_duration.
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_dev_select. Both devices.
{ 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_0.
{ 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_1.
{ 0x00100010, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x00100010, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00100010, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x00100010, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x00100010, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x00100010, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x00100010, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x00100010, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_cfg. 8GB total density.
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override1.
// Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:E Die-E for retail Iowa and Hoag.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_auto_cal_vref_sel0.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_dyn_self_ref_control.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB (Y01) Die-? for Iowa.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_vref_sel0.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_dyn_self_ref_control.
{ 0x32323232, 0x350 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_0.
{ 0x32323232, 0x354 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_1.
{ 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00780078, 0x3FC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x00780078, 0x400 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00780078, 0x404 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x00780078, 0x408 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x00780078, 0x40C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x00780078, 0x410 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x00780078, 0x414 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x00780078, 0x418 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB K4U6E3S4AA-MGCL 10nm-class (1y-X03) Die-A for retail Iowa, Hoag and Aula.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput_duration.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_dyn_self_ref_control.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 8GB K4UBE3D4AA-MGCL 10nm-class (1y-X03) Die-A for SDEV Iowa, Hoag and Aula.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_adr_cfg. 2 Ranks.
{ 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_tfaw.
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_dev_select. Both devices.
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_cfg. 8GB total density.
{ 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB 10nm-class (1y-Y01) Die-? for Iowa.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0.
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_dyn_self_ref_control.
{ 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 8GB 10nm-class (1y-Y01) Die-? for SDEV Iowa.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_adr_cfg. 2 Ranks.
{ 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_tfaw.
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_dev_select. Both devices.
{ 0x32323232, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_0.
{ 0x32323232, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_1.
{ 0x000F0018, 0x3AC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00440048, 0x3CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00180018, 0x41C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_cfg. 8GB total density.
{ 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1.
/*
// Samsung LPDDR4X 8GB 10nm-class (1y-A01) Die-? for SDEV Aula?
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_adr_cfg. 2 Ranks.
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_dev_select. Both devices.
{ 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_0.
{ 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_1.
{ 0x35353535, 0x358 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_0.
{ 0x35353535, 0x35C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_1.
{ 0x00480048, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x00480048, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00480048, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x00480048, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x00480048, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x00480048, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x00480048, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x00480048, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_init_dev1.
{ 0x00010100, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd4.
{ 0x00400010, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_cfg. 8GB total density.
{ 0x00000002, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_da_turns.
*/
// Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:F 10nm-class (1y-01) Die-F for Newer Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_dyn_self_ref_control.
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_emem_arb_timing_faw.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override1.
// Hynix LPDDR4X 4GB 10nm-class (1y-01) Die-A for Unknown Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_dyn_self_ref_control.
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_emem_arb_timing_faw.
{ 0xE4FACB43, 0x6D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override. + TSEC, NVENC.
{ 0x0600FED3, 0x6D8 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override1.
//!TODO: Too many duplicates.
};

1538
bdk/mem/sdram_lp0.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,964 @@
/*
* Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved.
* Copyright 2014 Google Inc.
* Copyright (c) 2018 CTCaer
*
* 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.
*/
/**
* Defines the SDRAM parameter structure.
*
* Note that PLLM is used by EMC. The field names are in camel case to ease
* directly converting BCT config files (*.cfg) into C structure.
*/
#ifndef __TEGRA210_SDRAM_PARAM_H__
#define __TEGRA210_SDRAM_PARAM_H__
#include <utils/types.h>
enum
{
/* Specifies the memory type to be undefined */
NvBootMemoryType_None = 0,
/* Specifies the memory type to be DDR SDRAM */
NvBootMemoryType_Ddr = 0,
/* Specifies the memory type to be LPDDR SDRAM */
NvBootMemoryType_LpDdr = 0,
/* Specifies the memory type to be DDR2 SDRAM */
NvBootMemoryType_Ddr2 = 0,
/* Specifies the memory type to be LPDDR2 SDRAM */
NvBootMemoryType_LpDdr2,
/* Specifies the memory type to be DDR3 SDRAM */
NvBootMemoryType_Ddr3,
/* Specifies the memory type to be LPDDR4 SDRAM */
NvBootMemoryType_LpDdr4,
NvBootMemoryType_Num,
/* Specifies an entry in the ram_code table that's not in use */
NvBootMemoryType_Unused = 0X7FFFFFF,
};
/**
* Defines the SDRAM parameter structure
*/
struct sdram_params_t210
{
/* Specifies the type of memory device */
u32 MemoryType;
/* MC/EMC clock source configuration */
/* Specifies the M value for PllM */
u32 PllMInputDivider;
/* Specifies the N value for PllM */
u32 PllMFeedbackDivider;
/* Specifies the time to wait for PLLM to lock (in microseconds) */
u32 PllMStableTime;
/* Specifies misc. control bits */
u32 PllMSetupControl;
/* Specifies the P value for PLLM */
u32 PllMPostDivider;
/* Specifies value for Charge Pump Gain Control */
u32 PllMKCP;
/* Specifies VCO gain */
u32 PllMKVCO;
/* Spare BCT param */
u32 EmcBctSpare0;
/* Spare BCT param */
u32 EmcBctSpare1;
/* Spare BCT param */
u32 EmcBctSpare2;
/* Spare BCT param */
u32 EmcBctSpare3;
/* Spare BCT param */
u32 EmcBctSpare4;
/* Spare BCT param */
u32 EmcBctSpare5;
/* Spare BCT param */
u32 EmcBctSpare6;
/* Spare BCT param */
u32 EmcBctSpare7;
/* Spare BCT param */
u32 EmcBctSpare8;
/* Spare BCT param */
u32 EmcBctSpare9;
/* Spare BCT param */
u32 EmcBctSpare10;
/* Spare BCT param */
u32 EmcBctSpare11;
/* Spare BCT param */
u32 EmcBctSpare12;
/* Spare BCT param */
u32 EmcBctSpare13;
/* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */
u32 EmcClockSource;
u32 EmcClockSourceDll;
/* Defines possible override for PLLLM_MISC2 */
u32 ClkRstControllerPllmMisc2Override;
/* enables override for PLLLM_MISC2 */
u32 ClkRstControllerPllmMisc2OverrideEnable;
/* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */
u32 ClearClk2Mc1;
/* Auto-calibration of EMC pads */
/* Specifies the value for EMC_AUTO_CAL_INTERVAL */
u32 EmcAutoCalInterval;
/*
* Specifies the value for EMC_AUTO_CAL_CONFIG
* Note: Trigger bits are set by the SDRAM code.
*/
u32 EmcAutoCalConfig;
/* Specifies the value for EMC_AUTO_CAL_CONFIG2 */
u32 EmcAutoCalConfig2;
/* Specifies the value for EMC_AUTO_CAL_CONFIG3 */
u32 EmcAutoCalConfig3;
/* Specifies the values for EMC_AUTO_CAL_CONFIG4-8 */
u32 EmcAutoCalConfig4;
u32 EmcAutoCalConfig5;
u32 EmcAutoCalConfig6;
u32 EmcAutoCalConfig7;
u32 EmcAutoCalConfig8;
/* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */
u32 EmcAutoCalVrefSel0;
u32 EmcAutoCalVrefSel1;
/* Specifies the value for EMC_AUTO_CAL_CHANNEL */
u32 EmcAutoCalChannel;
/* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */
u32 EmcPmacroAutocalCfg0;
u32 EmcPmacroAutocalCfg1;
u32 EmcPmacroAutocalCfg2;
u32 EmcPmacroRxTerm;
u32 EmcPmacroDqTxDrv;
u32 EmcPmacroCaTxDrv;
u32 EmcPmacroCmdTxDrv;
u32 EmcPmacroAutocalCfgCommon;
u32 EmcPmacroZctrl;
/*
* Specifies the time for the calibration
* to stabilize (in microseconds)
*/
u32 EmcAutoCalWait;
u32 EmcXm2CompPadCtrl;
u32 EmcXm2CompPadCtrl2;
u32 EmcXm2CompPadCtrl3;
/*
* DRAM size information
* Specifies the value for EMC_ADR_CFG
*/
u32 EmcAdrCfg;
/*
* Specifies the time to wait after asserting pin
* CKE (in microseconds)
*/
u32 EmcPinProgramWait;
/* Specifies the extra delay before/after pin RESET/CKE command */
u32 EmcPinExtraWait;
u32 EmcPinGpioEn;
u32 EmcPinGpio;
/*
* Specifies the extra delay after the first writing
* of EMC_TIMING_CONTROL
*/
u32 EmcTimingControlWait;
/* Timing parameters required for the SDRAM */
/* Specifies the value for EMC_RC */
u32 EmcRc;
/* Specifies the value for EMC_RFC */
u32 EmcRfc;
/* Specifies the value for EMC_RFC_PB */
u32 EmcRfcPb;
/* Specifies the value for EMC_RFC_CTRL2 */
u32 EmcRefctrl2;
/* Specifies the value for EMC_RFC_SLR */
u32 EmcRfcSlr;
/* Specifies the value for EMC_RAS */
u32 EmcRas;
/* Specifies the value for EMC_RP */
u32 EmcRp;
/* Specifies the value for EMC_R2R */
u32 EmcR2r;
/* Specifies the value for EMC_W2W */
u32 EmcW2w;
/* Specifies the value for EMC_R2W */
u32 EmcR2w;
/* Specifies the value for EMC_W2R */
u32 EmcW2r;
/* Specifies the value for EMC_R2P */
u32 EmcR2p;
/* Specifies the value for EMC_W2P */
u32 EmcW2p;
u32 EmcTppd;
u32 EmcCcdmw;
/* Specifies the value for EMC_RD_RCD */
u32 EmcRdRcd;
/* Specifies the value for EMC_WR_RCD */
u32 EmcWrRcd;
/* Specifies the value for EMC_RRD */
u32 EmcRrd;
/* Specifies the value for EMC_REXT */
u32 EmcRext;
/* Specifies the value for EMC_WEXT */
u32 EmcWext;
/* Specifies the value for EMC_WDV */
u32 EmcWdv;
u32 EmcWdvChk;
u32 EmcWsv;
u32 EmcWev;
/* Specifies the value for EMC_WDV_MASK */
u32 EmcWdvMask;
u32 EmcWsDuration;
u32 EmcWeDuration;
/* Specifies the value for EMC_QUSE */
u32 EmcQUse;
/* Specifies the value for EMC_QUSE_WIDTH */
u32 EmcQuseWidth;
/* Specifies the value for EMC_IBDLY */
u32 EmcIbdly;
/* Specifies the value for EMC_OBDLY */
u32 EmcObdly;
/* Specifies the value for EMC_EINPUT */
u32 EmcEInput;
/* Specifies the value for EMC_EINPUT_DURATION */
u32 EmcEInputDuration;
/* Specifies the value for EMC_PUTERM_EXTRA */
u32 EmcPutermExtra;
/* Specifies the value for EMC_PUTERM_WIDTH */
u32 EmcPutermWidth;
/* Specifies the value for EMC_PUTERM_ADJ */
////u32 EmcPutermAdj;
/* Specifies the value for EMC_QRST */
u32 EmcQRst;
/* Specifies the value for EMC_QSAFE */
u32 EmcQSafe;
/* Specifies the value for EMC_RDV */
u32 EmcRdv;
/* Specifies the value for EMC_RDV_MASK */
u32 EmcRdvMask;
/* Specifies the value for EMC_RDV_EARLY */
u32 EmcRdvEarly;
/* Specifies the value for EMC_RDV_EARLY_MASK */
u32 EmcRdvEarlyMask;
/* Specifies the value for EMC_QPOP */
u32 EmcQpop;
/* Specifies the value for EMC_REFRESH */
u32 EmcRefresh;
/* Specifies the value for EMC_BURST_REFRESH_NUM */
u32 EmcBurstRefreshNum;
/* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */
u32 EmcPreRefreshReqCnt;
/* Specifies the value for EMC_PDEX2WR */
u32 EmcPdEx2Wr;
/* Specifies the value for EMC_PDEX2RD */
u32 EmcPdEx2Rd;
/* Specifies the value for EMC_PCHG2PDEN */
u32 EmcPChg2Pden;
/* Specifies the value for EMC_ACT2PDEN */
u32 EmcAct2Pden;
/* Specifies the value for EMC_AR2PDEN */
u32 EmcAr2Pden;
/* Specifies the value for EMC_RW2PDEN */
u32 EmcRw2Pden;
/* Specifies the value for EMC_CKE2PDEN */
u32 EmcCke2Pden;
/* Specifies the value for EMC_PDEX2CKE */
u32 EmcPdex2Cke;
/* Specifies the value for EMC_PDEX2MRR */
u32 EmcPdex2Mrr;
/* Specifies the value for EMC_TXSR */
u32 EmcTxsr;
/* Specifies the value for EMC_TXSRDLL */
u32 EmcTxsrDll;
/* Specifies the value for EMC_TCKE */
u32 EmcTcke;
/* Specifies the value for EMC_TCKESR */
u32 EmcTckesr;
/* Specifies the value for EMC_TPD */
u32 EmcTpd;
/* Specifies the value for EMC_TFAW */
u32 EmcTfaw;
/* Specifies the value for EMC_TRPAB */
u32 EmcTrpab;
/* Specifies the value for EMC_TCLKSTABLE */
u32 EmcTClkStable;
/* Specifies the value for EMC_TCLKSTOP */
u32 EmcTClkStop;
/* Specifies the value for EMC_TREFBW */
u32 EmcTRefBw;
/* FBIO configuration values */
/* Specifies the value for EMC_FBIO_CFG5 */
u32 EmcFbioCfg5;
/* Specifies the value for EMC_FBIO_CFG7 */
u32 EmcFbioCfg7;
/* Specifies the value for EMC_FBIO_CFG8 */
u32 EmcFbioCfg8;
/* Command mapping for CMD brick 0 */
u32 EmcCmdMappingCmd0_0;
u32 EmcCmdMappingCmd0_1;
u32 EmcCmdMappingCmd0_2;
u32 EmcCmdMappingCmd1_0;
u32 EmcCmdMappingCmd1_1;
u32 EmcCmdMappingCmd1_2;
u32 EmcCmdMappingCmd2_0;
u32 EmcCmdMappingCmd2_1;
u32 EmcCmdMappingCmd2_2;
u32 EmcCmdMappingCmd3_0;
u32 EmcCmdMappingCmd3_1;
u32 EmcCmdMappingCmd3_2;
u32 EmcCmdMappingByte;
/* Specifies the value for EMC_FBIO_SPARE */
u32 EmcFbioSpare;
/* Specifies the value for EMC_CFG_RSV */
u32 EmcCfgRsv;
/* MRS command values */
/* Specifies the value for EMC_MRS */
u32 EmcMrs;
/* Specifies the MP0 command to initialize mode registers */
u32 EmcEmrs;
/* Specifies the MP2 command to initialize mode registers */
u32 EmcEmrs2;
/* Specifies the MP3 command to initialize mode registers */
u32 EmcEmrs3;
/* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */
u32 EmcMrw1;
/* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */
u32 EmcMrw2;
/* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */
u32 EmcMrw3;
/* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */
u32 EmcMrw4;
/* Specifies the programming to LPDDR2 Mode Register 3? at cold boot */
u32 EmcMrw6;
/* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */
u32 EmcMrw8;
/* Specifies the programming to LPDDR2 Mode Register 11? at cold boot */
u32 EmcMrw9;
/* Specifies the programming to LPDDR2 Mode Register 12 at cold boot */
u32 EmcMrw10;
/* Specifies the programming to LPDDR2 Mode Register 14 at cold boot */
u32 EmcMrw12;
/* Specifies the programming to LPDDR2 Mode Register 14? at cold boot */
u32 EmcMrw13;
/* Specifies the programming to LPDDR2 Mode Register 22 at cold boot */
u32 EmcMrw14;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at cold boot
*/
u32 EmcMrwExtra;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at warm boot
*/
u32 EmcWarmBootMrwExtra;
/*
* Specify the enable of extra Mode Register programming at
* warm boot
*/
u32 EmcWarmBootExtraModeRegWriteEnable;
/*
* Specify the enable of extra Mode Register programming at
* cold boot
*/
u32 EmcExtraModeRegWriteEnable;
/* Specifies the EMC_MRW reset command value */
u32 EmcMrwResetCommand;
/* Specifies the EMC Reset wait time (in microseconds) */
u32 EmcMrwResetNInitWait;
/* Specifies the value for EMC_MRS_WAIT_CNT */
u32 EmcMrsWaitCnt;
/* Specifies the value for EMC_MRS_WAIT_CNT2 */
u32 EmcMrsWaitCnt2;
/* EMC miscellaneous configurations */
/* Specifies the value for EMC_CFG */
u32 EmcCfg;
/* Specifies the value for EMC_CFG_2 */
u32 EmcCfg2;
/* Specifies the pipe bypass controls */
u32 EmcCfgPipe;
u32 EmcCfgPipeClk;
u32 EmcFdpdCtrlCmdNoRamp;
u32 EmcCfgUpdate;
/* Specifies the value for EMC_DBG */
u32 EmcDbg;
u32 EmcDbgWriteMux;
/* Specifies the value for EMC_CMDQ */
u32 EmcCmdQ;
/* Specifies the value for EMC_MC2EMCQ */
u32 EmcMc2EmcQ;
/* Specifies the value for EMC_DYN_SELF_REF_CONTROL */
u32 EmcDynSelfRefControl;
/* Specifies the value for MEM_INIT_DONE */
u32 AhbArbitrationXbarCtrlMemInitDone;
/* Specifies the value for EMC_CFG_DIG_DLL */
u32 EmcCfgDigDll;
u32 EmcCfgDigDll_1;
/* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */
u32 EmcCfgDigDllPeriod;
/* Specifies the value of *DEV_SELECTN of various EMC registers */
u32 EmcDevSelect;
/* Specifies the value for EMC_SEL_DPD_CTRL */
u32 EmcSelDpdCtrl;
/* Pads trimmer delays */
u32 EmcFdpdCtrlDq;
u32 EmcFdpdCtrlCmd;
u32 EmcPmacroIbVrefDq_0;
u32 EmcPmacroIbVrefDq_1;
u32 EmcPmacroIbVrefDqs_0;
u32 EmcPmacroIbVrefDqs_1;
u32 EmcPmacroIbRxrt;
u32 EmcCfgPipe1;
u32 EmcCfgPipe2;
/* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */
u32 EmcPmacroQuseDdllRank0_0;
u32 EmcPmacroQuseDdllRank0_1;
u32 EmcPmacroQuseDdllRank0_2;
u32 EmcPmacroQuseDdllRank0_3;
u32 EmcPmacroQuseDdllRank0_4;
u32 EmcPmacroQuseDdllRank0_5;
u32 EmcPmacroQuseDdllRank1_0;
u32 EmcPmacroQuseDdllRank1_1;
u32 EmcPmacroQuseDdllRank1_2;
u32 EmcPmacroQuseDdllRank1_3;
u32 EmcPmacroQuseDdllRank1_4;
u32 EmcPmacroQuseDdllRank1_5;
u32 EmcPmacroObDdllLongDqRank0_0;
u32 EmcPmacroObDdllLongDqRank0_1;
u32 EmcPmacroObDdllLongDqRank0_2;
u32 EmcPmacroObDdllLongDqRank0_3;
u32 EmcPmacroObDdllLongDqRank0_4;
u32 EmcPmacroObDdllLongDqRank0_5;
u32 EmcPmacroObDdllLongDqRank1_0;
u32 EmcPmacroObDdllLongDqRank1_1;
u32 EmcPmacroObDdllLongDqRank1_2;
u32 EmcPmacroObDdllLongDqRank1_3;
u32 EmcPmacroObDdllLongDqRank1_4;
u32 EmcPmacroObDdllLongDqRank1_5;
u32 EmcPmacroObDdllLongDqsRank0_0;
u32 EmcPmacroObDdllLongDqsRank0_1;
u32 EmcPmacroObDdllLongDqsRank0_2;
u32 EmcPmacroObDdllLongDqsRank0_3;
u32 EmcPmacroObDdllLongDqsRank0_4;
u32 EmcPmacroObDdllLongDqsRank0_5;
u32 EmcPmacroObDdllLongDqsRank1_0;
u32 EmcPmacroObDdllLongDqsRank1_1;
u32 EmcPmacroObDdllLongDqsRank1_2;
u32 EmcPmacroObDdllLongDqsRank1_3;
u32 EmcPmacroObDdllLongDqsRank1_4;
u32 EmcPmacroObDdllLongDqsRank1_5;
u32 EmcPmacroIbDdllLongDqsRank0_0;
u32 EmcPmacroIbDdllLongDqsRank0_1;
u32 EmcPmacroIbDdllLongDqsRank0_2;
u32 EmcPmacroIbDdllLongDqsRank0_3;
u32 EmcPmacroIbDdllLongDqsRank1_0;
u32 EmcPmacroIbDdllLongDqsRank1_1;
u32 EmcPmacroIbDdllLongDqsRank1_2;
u32 EmcPmacroIbDdllLongDqsRank1_3;
u32 EmcPmacroDdllLongCmd_0;
u32 EmcPmacroDdllLongCmd_1;
u32 EmcPmacroDdllLongCmd_2;
u32 EmcPmacroDdllLongCmd_3;
u32 EmcPmacroDdllLongCmd_4;
u32 EmcPmacroDdllShortCmd_0;
u32 EmcPmacroDdllShortCmd_1;
u32 EmcPmacroDdllShortCmd_2;
/*
* Specifies the delay after asserting CKE pin during a WarmBoot0
* sequence (in microseconds)
*/
u32 WarmBootWait;
/* Specifies the value for EMC_ODT_WRITE */
u32 EmcOdtWrite;
/* Periodic ZQ calibration */
/*
* Specifies the value for EMC_ZCAL_INTERVAL
* Value 0 disables ZQ calibration
*/
u32 EmcZcalInterval;
/* Specifies the value for EMC_ZCAL_WAIT_CNT */
u32 EmcZcalWaitCnt;
/* Specifies the value for EMC_ZCAL_MRW_CMD */
u32 EmcZcalMrwCmd;
/* DRAM initialization sequence flow control */
/* Specifies the MRS command value for resetting DLL */
u32 EmcMrsResetDll;
/* Specifies the command for ZQ initialization of device 0 */
u32 EmcZcalInitDev0;
/* Specifies the command for ZQ initialization of device 1 */
u32 EmcZcalInitDev1;
/*
* Specifies the wait time after programming a ZQ initialization
* command (in microseconds)
*/
u32 EmcZcalInitWait;
/*
* Specifies the enable for ZQ calibration at cold boot [bit 0]
* and warm boot [bit 1]
*/
u32 EmcZcalWarmColdBootEnables;
/*
* Specifies the MRW command to LPDDR2 for ZQ calibration
* on warmboot
*/
/* Is issued to both devices separately */
u32 EmcMrwLpddr2ZcalWarmBoot;
/*
* Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
* Is issued to both devices separately
*/
u32 EmcZqCalDdr3WarmBoot;
u32 EmcZqCalLpDdr4WarmBoot;
/*
* Specifies the wait time for ZQ calibration on warmboot
* (in microseconds)
*/
u32 EmcZcalWarmBootWait;
/*
* Specifies the enable for DRAM Mode Register programming
* at warm boot
*/
u32 EmcMrsWarmBootEnable;
/*
* Specifies the wait time after sending an MRS DLL reset command
* in microseconds)
*/
u32 EmcMrsResetDllWait;
/* Specifies the extra MRS command to initialize mode registers */
u32 EmcMrsExtra;
/* Specifies the extra MRS command at warm boot */
u32 EmcWarmBootMrsExtra;
/* Specifies the EMRS command to enable the DDR2 DLL */
u32 EmcEmrsDdr2DllEnable;
/* Specifies the MRS command to reset the DDR2 DLL */
u32 EmcMrsDdr2DllReset;
/* Specifies the EMRS command to set OCD calibration */
u32 EmcEmrsDdr2OcdCalib;
/*
* Specifies the wait between initializing DDR and setting OCD
* calibration (in microseconds)
*/
u32 EmcDdr2Wait;
/* Specifies the value for EMC_CLKEN_OVERRIDE */
u32 EmcClkenOverride;
/*
* Specifies LOG2 of the extra refresh numbers after booting
* Program 0 to disable
*/
u32 EmcExtraRefreshNum;
/* Specifies the master override for all EMC clocks */
u32 EmcClkenOverrideAllWarmBoot;
/* Specifies the master override for all MC clocks */
u32 McClkenOverrideAllWarmBoot;
/* Specifies digital dll period, choosing between 4 to 64 ms */
u32 EmcCfgDigDllPeriodWarmBoot;
/* Pad controls */
/* Specifies the value for PMC_VDDP_SEL */
u32 PmcVddpSel;
/* Specifies the wait time after programming PMC_VDDP_SEL */
u32 PmcVddpSelWait;
/* Specifies the value for PMC_DDR_PWR */
u32 PmcDdrPwr;
/* Specifies the value for PMC_DDR_CFG */
u32 PmcDdrCfg;
/* Specifies the value for PMC_IO_DPD3_REQ */
u32 PmcIoDpd3Req;
/* Specifies the wait time after programming PMC_IO_DPD3_REQ */
u32 PmcIoDpd3ReqWait;
u32 PmcIoDpd4ReqWait;
/* Specifies the value for PMC_REG_SHORT */
u32 PmcRegShort;
/* Specifies the value for PMC_NO_IOPOWER */
u32 PmcNoIoPower;
u32 PmcDdrCntrlWait;
u32 PmcDdrCntrl;
/* Specifies the value for EMC_ACPD_CONTROL */
u32 EmcAcpdControl;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE_CFG */
////u32 EmcSwizzleRank0ByteCfg;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */
u32 EmcSwizzleRank0Byte0;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */
u32 EmcSwizzleRank0Byte1;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */
u32 EmcSwizzleRank0Byte2;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */
u32 EmcSwizzleRank0Byte3;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE_CFG */
////u32 EmcSwizzleRank1ByteCfg;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */
u32 EmcSwizzleRank1Byte0;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */
u32 EmcSwizzleRank1Byte1;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */
u32 EmcSwizzleRank1Byte2;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */
u32 EmcSwizzleRank1Byte3;
/* Specifies the value for EMC_TXDSRVTTGEN */
u32 EmcTxdsrvttgen;
/* Specifies the value for EMC_DATA_BRLSHFT_0 */
u32 EmcDataBrlshft0;
u32 EmcDataBrlshft1;
u32 EmcDqsBrlshft0;
u32 EmcDqsBrlshft1;
u32 EmcCmdBrlshft0;
u32 EmcCmdBrlshft1;
u32 EmcCmdBrlshft2;
u32 EmcCmdBrlshft3;
u32 EmcQuseBrlshft0;
u32 EmcQuseBrlshft1;
u32 EmcQuseBrlshft2;
u32 EmcQuseBrlshft3;
u32 EmcDllCfg0;
u32 EmcDllCfg1;
u32 EmcPmcScratch1;
u32 EmcPmcScratch2;
u32 EmcPmcScratch3;
u32 EmcPmacroPadCfgCtrl;
u32 EmcPmacroVttgenCtrl0;
u32 EmcPmacroVttgenCtrl1;
u32 EmcPmacroVttgenCtrl2;
u32 EmcPmacroBrickCtrlRfu1;
u32 EmcPmacroCmdBrickCtrlFdpd;
u32 EmcPmacroBrickCtrlRfu2;
u32 EmcPmacroDataBrickCtrlFdpd;
u32 EmcPmacroBgBiasCtrl0;
u32 EmcPmacroDataPadRxCtrl;
u32 EmcPmacroCmdPadRxCtrl;
u32 EmcPmacroDataRxTermMode;
u32 EmcPmacroCmdRxTermMode;
u32 EmcPmacroDataPadTxCtrl;
u32 EmcPmacroCommonPadTxCtrl;
u32 EmcPmacroCmdPadTxCtrl;
u32 EmcCfg3;
u32 EmcPmacroTxPwrd0;
u32 EmcPmacroTxPwrd1;
u32 EmcPmacroTxPwrd2;
u32 EmcPmacroTxPwrd3;
u32 EmcPmacroTxPwrd4;
u32 EmcPmacroTxPwrd5;
u32 EmcConfigSampleDelay;
u32 EmcPmacroBrickMapping0;
u32 EmcPmacroBrickMapping1;
u32 EmcPmacroBrickMapping2;
u32 EmcPmacroTxSelClkSrc0;
u32 EmcPmacroTxSelClkSrc1;
u32 EmcPmacroTxSelClkSrc2;
u32 EmcPmacroTxSelClkSrc3;
u32 EmcPmacroTxSelClkSrc4;
u32 EmcPmacroTxSelClkSrc5;
u32 EmcPmacroDdllBypass;
u32 EmcPmacroDdllPwrd0;
u32 EmcPmacroDdllPwrd1;
u32 EmcPmacroDdllPwrd2;
u32 EmcPmacroCmdCtrl0;
u32 EmcPmacroCmdCtrl1;
u32 EmcPmacroCmdCtrl2;
/* DRAM size information */
/* Specifies the value for MC_EMEM_ADR_CFG */
u32 McEmemAdrCfg;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */
u32 McEmemAdrCfgDev0;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */
u32 McEmemAdrCfgDev1;
u32 McEmemAdrCfgChannelMask;
/* Specifies the value for MC_EMEM_BANK_SWIZZLECfg0 */
u32 McEmemAdrCfgBankMask0;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */
u32 McEmemAdrCfgBankMask1;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */
u32 McEmemAdrCfgBankMask2;
/*
* Specifies the value for MC_EMEM_CFG which holds the external memory
* size (in KBytes)
*/
u32 McEmemCfg;
/* MC arbitration configuration */
/* Specifies the value for MC_EMEM_ARB_CFG */
u32 McEmemArbCfg;
/* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */
u32 McEmemArbOutstandingReq;
u32 McEmemArbRefpbHpCtrl;
u32 McEmemArbRefpbBankCtrl;
/* Specifies the value for MC_EMEM_ARB_TIMING_RCD */
u32 McEmemArbTimingRcd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RP */
u32 McEmemArbTimingRp;
/* Specifies the value for MC_EMEM_ARB_TIMING_RC */
u32 McEmemArbTimingRc;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAS */
u32 McEmemArbTimingRas;
/* Specifies the value for MC_EMEM_ARB_TIMING_FAW */
u32 McEmemArbTimingFaw;
/* Specifies the value for MC_EMEM_ARB_TIMING_RRD */
u32 McEmemArbTimingRrd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */
u32 McEmemArbTimingRap2Pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */
u32 McEmemArbTimingWap2Pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2R */
u32 McEmemArbTimingR2R;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2W */
u32 McEmemArbTimingW2W;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2W */
u32 McEmemArbTimingR2W;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2R */
u32 McEmemArbTimingW2R;
u32 McEmemArbTimingRFCPB;
/* Specifies the value for MC_EMEM_ARB_DA_TURNS */
u32 McEmemArbDaTurns;
/* Specifies the value for MC_EMEM_ARB_DA_COVERS */
u32 McEmemArbDaCovers;
/* Specifies the value for MC_EMEM_ARB_MISC0 */
u32 McEmemArbMisc0;
/* Specifies the value for MC_EMEM_ARB_MISC1 */
u32 McEmemArbMisc1;
u32 McEmemArbMisc2;
/* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */
u32 McEmemArbRing1Throttle;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE */
u32 McEmemArbOverride;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */
u32 McEmemArbOverride1;
/* Specifies the value for MC_EMEM_ARB_RSV */
u32 McEmemArbRsv;
u32 McDaCfg0;
u32 McEmemArbTimingCcdmw;
/* Specifies the value for MC_CLKEN_OVERRIDE */
u32 McClkenOverride;
/* Specifies the value for MC_STAT_CONTROL */
u32 McStatControl;
/* Specifies the value for MC_VIDEO_PROTECT_BOM */
u32 McVideoProtectBom;
/* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */
u32 McVideoProtectBomAdrHi;
/* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */
u32 McVideoProtectSizeMb;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */
u32 McVideoProtectVprOverride;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */
u32 McVideoProtectVprOverride1;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */
u32 McVideoProtectGpuOverride0;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */
u32 McVideoProtectGpuOverride1;
/* Specifies the value for MC_SEC_CARVEOUT_BOM */
u32 McSecCarveoutBom;
/* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */
u32 McSecCarveoutAdrHi;
/* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */
u32 McSecCarveoutSizeMb;
/* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.
VIDEO_PROTECT_WRITEAccess */
u32 McVideoProtectWriteAccess;
/* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.
SEC_CARVEOUT_WRITEAccess */
u32 McSecCarveoutProtectWriteAccess;
/* Write-Protect Regions (WPR) */
u32 McGeneralizedCarveout1Bom;
u32 McGeneralizedCarveout1BomHi;
u32 McGeneralizedCarveout1Size128kb;
u32 McGeneralizedCarveout1Access0;
u32 McGeneralizedCarveout1Access1;
u32 McGeneralizedCarveout1Access2;
u32 McGeneralizedCarveout1Access3;
u32 McGeneralizedCarveout1Access4;
u32 McGeneralizedCarveout1ForceInternalAccess0;
u32 McGeneralizedCarveout1ForceInternalAccess1;
u32 McGeneralizedCarveout1ForceInternalAccess2;
u32 McGeneralizedCarveout1ForceInternalAccess3;
u32 McGeneralizedCarveout1ForceInternalAccess4;
u32 McGeneralizedCarveout1Cfg0;
u32 McGeneralizedCarveout2Bom;
u32 McGeneralizedCarveout2BomHi;
u32 McGeneralizedCarveout2Size128kb;
u32 McGeneralizedCarveout2Access0;
u32 McGeneralizedCarveout2Access1;
u32 McGeneralizedCarveout2Access2;
u32 McGeneralizedCarveout2Access3;
u32 McGeneralizedCarveout2Access4;
u32 McGeneralizedCarveout2ForceInternalAccess0;
u32 McGeneralizedCarveout2ForceInternalAccess1;
u32 McGeneralizedCarveout2ForceInternalAccess2;
u32 McGeneralizedCarveout2ForceInternalAccess3;
u32 McGeneralizedCarveout2ForceInternalAccess4;
u32 McGeneralizedCarveout2Cfg0;
u32 McGeneralizedCarveout3Bom;
u32 McGeneralizedCarveout3BomHi;
u32 McGeneralizedCarveout3Size128kb;
u32 McGeneralizedCarveout3Access0;
u32 McGeneralizedCarveout3Access1;
u32 McGeneralizedCarveout3Access2;
u32 McGeneralizedCarveout3Access3;
u32 McGeneralizedCarveout3Access4;
u32 McGeneralizedCarveout3ForceInternalAccess0;
u32 McGeneralizedCarveout3ForceInternalAccess1;
u32 McGeneralizedCarveout3ForceInternalAccess2;
u32 McGeneralizedCarveout3ForceInternalAccess3;
u32 McGeneralizedCarveout3ForceInternalAccess4;
u32 McGeneralizedCarveout3Cfg0;
u32 McGeneralizedCarveout4Bom;
u32 McGeneralizedCarveout4BomHi;
u32 McGeneralizedCarveout4Size128kb;
u32 McGeneralizedCarveout4Access0;
u32 McGeneralizedCarveout4Access1;
u32 McGeneralizedCarveout4Access2;
u32 McGeneralizedCarveout4Access3;
u32 McGeneralizedCarveout4Access4;
u32 McGeneralizedCarveout4ForceInternalAccess0;
u32 McGeneralizedCarveout4ForceInternalAccess1;
u32 McGeneralizedCarveout4ForceInternalAccess2;
u32 McGeneralizedCarveout4ForceInternalAccess3;
u32 McGeneralizedCarveout4ForceInternalAccess4;
u32 McGeneralizedCarveout4Cfg0;
u32 McGeneralizedCarveout5Bom;
u32 McGeneralizedCarveout5BomHi;
u32 McGeneralizedCarveout5Size128kb;
u32 McGeneralizedCarveout5Access0;
u32 McGeneralizedCarveout5Access1;
u32 McGeneralizedCarveout5Access2;
u32 McGeneralizedCarveout5Access3;
u32 McGeneralizedCarveout5Access4;
u32 McGeneralizedCarveout5ForceInternalAccess0;
u32 McGeneralizedCarveout5ForceInternalAccess1;
u32 McGeneralizedCarveout5ForceInternalAccess2;
u32 McGeneralizedCarveout5ForceInternalAccess3;
u32 McGeneralizedCarveout5ForceInternalAccess4;
u32 McGeneralizedCarveout5Cfg0;
/* Specifies enable for CA training */
u32 EmcCaTrainingEnable;
/* Set if bit 6 select is greater than bit 7 select; uses aremc.
spec packet SWIZZLE_BIT6_GT_BIT7 */
u32 SwizzleRankByteEncode;
/* Specifies enable and offset for patched boot ROM write */
u32 BootRomPatchControl;
/* Specifies data for patched boot ROM write */
u32 BootRomPatchData;
/* Specifies the value for MC_MTS_CARVEOUT_BOM */
u32 McMtsCarveoutBom;
/* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */
u32 McMtsCarveoutAdrHi;
/* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */
u32 McMtsCarveoutSizeMb;
/* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */
u32 McMtsCarveoutRegCtrl;
/* End */
};
#endif /* __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ */

View File

@@ -0,0 +1,990 @@
/*
* Copyright (c) 2020 CTCaer
*
* 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.
*/
#ifndef __TEGRA210B01_SDRAM_PARAM_H__
#define __TEGRA210B01_SDRAM_PARAM_H__
#include <utils/types.h>
struct sdram_params_t210b01
{
/* Specifies the type of memory device */
u32 memory_type;
/* MC/EMC clock source configuration */
/* Specifies the M value for PllM */
u32 pllm_input_divider;
/* Specifies the N value for PllM */
u32 pllm_feedback_divider;
/* Specifies the time to wait for PLLM to lock (in microseconds) */
u32 pllm_stable_time;
/* Specifies misc. control bits */
u32 pllm_setup_control;
/* Specifies the P value for PLLM */
u32 pllm_post_divider;
/* Specifies value for Charge Pump Gain Control */
u32 pllm_kcp;
/* Specifies VCO gain */
u32 pllm_kvco;
/* Spare BCT param */
u32 emc_bct_spare0;
/* Spare BCT param */
u32 emc_bct_spare1;
/* Spare BCT param */
u32 emc_bct_spare2;
/* Spare BCT param */
u32 emc_bct_spare3;
/* Spare BCT param */
u32 emc_bct_spare4;
/* Spare BCT param */
u32 emc_bct_spare5;
/* Spare BCT param */
u32 emc_bct_spare6;
/* Spare BCT param */
u32 emc_bct_spare7;
/* Spare BCT param */
u32 emc_bct_spare8;
/* Spare BCT param */
u32 emc_bct_spare9;
/* Spare BCT param */
u32 emc_bct_spare10;
/* Spare BCT param */
u32 emc_bct_spare11;
/* Spare BCT param */
u32 emc_bct_spare12;
/* Spare BCT param */
u32 emc_bct_spare13;
/* Spare BCT param */
u32 emc_bct_spare_secure0;
/* Spare BCT param */
u32 emc_bct_spare_secure1;
/* Spare BCT param */
u32 emc_bct_spare_secure2;
/* Spare BCT param */
u32 emc_bct_spare_secure3;
/* Spare BCT param */
u32 emc_bct_spare_secure4;
/* Spare BCT param */
u32 emc_bct_spare_secure5;
/* Spare BCT param */
u32 emc_bct_spare_secure6;
/* Spare BCT param */
u32 emc_bct_spare_secure7;
/* Spare BCT param */
u32 emc_bct_spare_secure8;
/* Spare BCT param */
u32 emc_bct_spare_secure9;
/* Spare BCT param */
u32 emc_bct_spare_secure10;
/* Spare BCT param */
u32 emc_bct_spare_secure11;
/* Spare BCT param */
u32 emc_bct_spare_secure12;
/* Spare BCT param */
u32 emc_bct_spare_secure13;
/* Spare BCT param */
u32 emc_bct_spare_secure14;
/* Spare BCT param */
u32 emc_bct_spare_secure15;
/* Spare BCT param */
u32 emc_bct_spare_secure16;
/* Spare BCT param */
u32 emc_bct_spare_secure17;
/* Spare BCT param */
u32 emc_bct_spare_secure18;
/* Spare BCT param */
u32 emc_bct_spare_secure19;
/* Spare BCT param */
u32 emc_bct_spare_secure20;
/* Spare BCT param */
u32 emc_bct_spare_secure21;
/* Spare BCT param */
u32 emc_bct_spare_secure22;
/* Spare BCT param */
u32 emc_bct_spare_secure23;
/* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */
u32 emc_clock_source;
u32 emc_clock_source_dll;
/* Defines possible override for PLLLM_MISC2 */
u32 clk_rst_pllm_misc20_override;
/* enables override for PLLLM_MISC2 */
u32 clk_rst_pllm_misc20_override_enable;
/* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */
u32 clear_clock2_mc1;
/* Auto-calibration of EMC pads */
/* Specifies the value for EMC_AUTO_CAL_INTERVAL */
u32 emc_auto_cal_interval;
/*
* Specifies the value for EMC_AUTO_CAL_CONFIG
* Note: Trigger bits are set by the SDRAM code.
*/
u32 emc_auto_cal_config;
/* Specifies the value for EMC_AUTO_CAL_CONFIG2 */
u32 emc_auto_cal_config2;
/* Specifies the value for EMC_AUTO_CAL_CONFIG3 */
u32 emc_auto_cal_config3;
u32 emc_auto_cal_config4;
u32 emc_auto_cal_config5;
u32 emc_auto_cal_config6;
u32 emc_auto_cal_config7;
u32 emc_auto_cal_config8;
u32 emc_auto_cal_config9;
/* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */
u32 emc_auto_cal_vref_sel0;
u32 emc_auto_cal_vref_sel1;
/* Specifies the value for EMC_AUTO_CAL_CHANNEL */
u32 emc_auto_cal_channel;
/* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */
u32 emc_pmacro_auto_cal_cfg0;
u32 emc_pmacro_auto_cal_cfg1;
u32 emc_pmacro_auto_cal_cfg2;
u32 emc_pmacro_rx_term;
u32 emc_pmacro_dq_tx_drive;
u32 emc_pmacro_ca_tx_drive;
u32 emc_pmacro_cmd_tx_drive;
u32 emc_pmacro_auto_cal_common;
u32 emc_pmacro_zcrtl;
/*
* Specifies the time for the calibration
* to stabilize (in microseconds)
*/
u32 emc_auto_cal_wait;
u32 emc_xm2_comp_pad_ctrl;
u32 emc_xm2_comp_pad_ctrl2;
u32 emc_xm2_comp_pad_ctrl3;
/*
* DRAM size information
* Specifies the value for EMC_ADR_CFG
*/
u32 emc_adr_cfg;
/*
* Specifies the time to wait after asserting pin
* CKE (in microseconds)
*/
u32 emc_pin_program_wait;
/* Specifies the extra delay before/after pin RESET/CKE command */
u32 emc_pin_extra_wait;
u32 emc_pin_gpio_enable;
u32 emc_pin_gpio;
/*
* Specifies the extra delay after the first writing
* of EMC_TIMING_CONTROL
*/
u32 emc_timing_control_wait;
/* Timing parameters required for the SDRAM */
/* Specifies the value for EMC_RC */
u32 emc_rc;
/* Specifies the value for EMC_RFC */
u32 emc_rfc;
u32 emc_rfc_pb;
u32 emc_ref_ctrl2;
/* Specifies the value for EMC_RFC_SLR */
u32 emc_rfc_slr;
/* Specifies the value for EMC_RAS */
u32 emc_ras;
/* Specifies the value for EMC_RP */
u32 emc_rp;
/* Specifies the value for EMC_R2R */
u32 emc_r2r;
/* Specifies the value for EMC_W2W */
u32 emc_w2w;
/* Specifies the value for EMC_R2W */
u32 emc_r2w;
/* Specifies the value for EMC_W2R */
u32 emc_w2r;
/* Specifies the value for EMC_R2P */
u32 emc_r2p;
/* Specifies the value for EMC_W2P */
u32 emc_w2p;
/* Specifies the value for EMC_RD_RCD */
u32 emc_tppd;
u32 emc_trtm;
u32 emc_twtm;
u32 emc_tratm;
u32 emc_twatm;
u32 emc_tr2ref;
u32 emc_ccdmw;
u32 emc_rd_rcd;
/* Specifies the value for EMC_WR_RCD */
u32 emc_wr_rcd;
/* Specifies the value for EMC_RRD */
u32 emc_rrd;
/* Specifies the value for EMC_REXT */
u32 emc_rext;
/* Specifies the value for EMC_WEXT */
u32 emc_wext;
/* Specifies the value for EMC_WDV */
u32 emc_wdv;
u32 emc_wdv_chk;
u32 emc_wsv;
u32 emc_wev;
/* Specifies the value for EMC_WDV_MASK */
u32 emc_wdv_mask;
u32 emc_ws_duration;
u32 emc_we_duration;
/* Specifies the value for EMC_QUSE */
u32 emc_quse;
/* Specifies the value for EMC_QUSE_WIDTH */
u32 emc_quse_width;
/* Specifies the value for EMC_IBDLY */
u32 emc_ibdly;
u32 emc_obdly;
/* Specifies the value for EMC_EINPUT */
u32 emc_einput;
/* Specifies the value for EMC_EINPUT_DURATION */
u32 emc_einput_duration;
/* Specifies the value for EMC_PUTERM_EXTRA */
u32 emc_puterm_extra;
/* Specifies the value for EMC_PUTERM_WIDTH */
u32 emc_puterm_width;
u32 emc_qrst;
u32 emc_qsafe;
u32 emc_rdv;
u32 emc_rdv_mask;
u32 emc_rdv_early;
u32 emc_rdv_early_mask;
/* Specifies the value for EMC_QPOP */
u32 emc_qpop;
/* Specifies the value for EMC_REFRESH */
u32 emc_refresh;
/* Specifies the value for EMC_BURST_REFRESH_NUM */
u32 emc_burst_refresh_num;
/* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */
u32 emc_prerefresh_req_cnt;
/* Specifies the value for EMC_PDEX2WR */
u32 emc_pdex2wr;
/* Specifies the value for EMC_PDEX2RD */
u32 emc_pdex2rd;
/* Specifies the value for EMC_PCHG2PDEN */
u32 emc_pchg2pden;
/* Specifies the value for EMC_ACT2PDEN */
u32 emc_act2pden;
/* Specifies the value for EMC_AR2PDEN */
u32 emc_ar2pden;
/* Specifies the value for EMC_RW2PDEN */
u32 emc_rw2pden;
u32 emc_cke2pden;
u32 emc_pdex2che;
u32 emc_pdex2mrr;
/* Specifies the value for EMC_TXSR */
u32 emc_txsr;
/* Specifies the value for EMC_TXSRDLL */
u32 emc_txsr_dll;
/* Specifies the value for EMC_TCKE */
u32 emc_tcke;
/* Specifies the value for EMC_TCKESR */
u32 emc_tckesr;
/* Specifies the value for EMC_TPD */
u32 emc_tpd;
/* Specifies the value for EMC_TFAW */
u32 emc_tfaw;
/* Specifies the value for EMC_TRPAB */
u32 emc_trpab;
/* Specifies the value for EMC_TCLKSTABLE */
u32 emc_tclkstable;
/* Specifies the value for EMC_TCLKSTOP */
u32 emc_tclkstop;
/* Specifies the value for EMC_TREFBW */
u32 emc_trefbw;
/* FBIO configuration values */
/* Specifies the value for EMC_FBIO_CFG5 */
u32 emc_fbio_cfg5;
/* Specifies the value for EMC_FBIO_CFG7 */
u32 emc_fbio_cfg7;
u32 emc_fbio_cfg8;
/* Command mapping for CMD brick 0 */
u32 emc_cmd_mapping_cmd0_0;
u32 emc_cmd_mapping_cmd0_1;
u32 emc_cmd_mapping_cmd0_2;
u32 emc_cmd_mapping_cmd1_0;
u32 emc_cmd_mapping_cmd1_1;
u32 emc_cmd_mapping_cmd1_2;
u32 emc_cmd_mapping_cmd2_0;
u32 emc_cmd_mapping_cmd2_1;
u32 emc_cmd_mapping_cmd2_2;
u32 emc_cmd_mapping_cmd3_0;
u32 emc_cmd_mapping_cmd3_1;
u32 emc_cmd_mapping_cmd3_2;
u32 emc_cmd_mapping_byte;
/* Specifies the value for EMC_FBIO_SPARE */
u32 emc_fbio_spare;
/* Specifies the value for EMC_CFG_RSV */
u32 emc_cfg_rsv;
/* MRS command values */
/* Specifies the value for EMC_MRS */
u32 emc_mrs;
/* Specifies the MP0 command to initialize mode registers */
u32 emc_emrs;
/* Specifies the MP2 command to initialize mode registers */
u32 emc_emrs2;
/* Specifies the MP3 command to initialize mode registers */
u32 emc_emrs3;
/* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */
u32 emc_mrw1;
/* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */
u32 emc_mrw2;
/* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */
u32 emc_mrw3;
/* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */
u32 emc_mrw4;
/* Specifies the programming to LPDDR4 Mode Register 3 at cold boot */
u32 emc_mrw6;
/* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */
u32 emc_mrw8;
/* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */
u32 emc_mrw9;
/* Specifies the programming to LPDDR4 Mode Register 12 at cold boot */
u32 emc_mrw10;
/* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */
u32 emc_mrw12;
/* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */
u32 emc_mrw13;
/* Specifies the programming to LPDDR4 Mode Register 22 at cold boot */
u32 emc_mrw14;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at cold boot
*/
u32 emc_mrw_extra;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at warm boot
*/
u32 emc_warm_boot_mrw_extra;
/*
* Specify the enable of extra Mode Register programming at
* warm boot
*/
u32 emc_warm_boot_extramode_reg_write_enable;
/*
* Specify the enable of extra Mode Register programming at
* cold boot
*/
u32 emc_extramode_reg_write_enable;
/* Specifies the EMC_MRW reset command value */
u32 emc_mrw_reset_command;
/* Specifies the EMC Reset wait time (in microseconds) */
u32 emc_mrw_reset_ninit_wait;
/* Specifies the value for EMC_MRS_WAIT_CNT */
u32 emc_mrs_wait_cnt;
/* Specifies the value for EMC_MRS_WAIT_CNT2 */
u32 emc_mrs_wait_cnt2;
/* EMC miscellaneous configurations */
/* Specifies the value for EMC_CFG */
u32 emc_cfg;
/* Specifies the value for EMC_CFG_2 */
u32 emc_cfg2;
/* Specifies the pipe bypass controls */
u32 emc_cfg_pipe;
u32 emc_cfg_pipe_clk;
u32 emc_fdpd_ctrl_cmd_no_ramp;
u32 emc_cfg_update;
/* Specifies the value for EMC_DBG */
u32 emc_dbg;
u32 emc_dbg_write_mux;
/* Specifies the value for EMC_CMDQ */
u32 emc_cmd_q;
/* Specifies the value for EMC_MC2EMCQ */
u32 emc_mc2emc_q;
/* Specifies the value for EMC_DYN_SELF_REF_CONTROL */
u32 emc_dyn_self_ref_control;
/* Specifies the value for MEM_INIT_DONE */
u32 ahb_arbitration_xbar_ctrl_meminit_done;
/* Specifies the value for EMC_CFG_DIG_DLL */
u32 emc_cfg_dig_dll;
u32 emc_cfg_dig_dll_1;
/* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */
u32 emc_cfg_dig_dll_period;
/* Specifies the value of *DEV_SELECTN of various EMC registers */
u32 emc_dev_select;
/* Specifies the value for EMC_SEL_DPD_CTRL */
u32 emc_sel_dpd_ctrl;
/* Pads trimmer delays */
u32 emc_fdpd_ctrl_dq;
u32 emc_fdpd_ctrl_cmd;
u32 emc_pmacro_ib_vref_dq_0;
u32 emc_pmacro_ib_vref_dq_1;
u32 emc_pmacro_ib_vref_dqs_0;
u32 emc_pmacro_ib_vref_dqs_1;
u32 emc_pmacro_ib_rxrt;
u32 emc_cfg_pipe1;
u32 emc_cfg_pipe2;
/* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */
u32 emc_pmacro_quse_ddll_rank0_0;
u32 emc_pmacro_quse_ddll_rank0_1;
u32 emc_pmacro_quse_ddll_rank0_2;
u32 emc_pmacro_quse_ddll_rank0_3;
u32 emc_pmacro_quse_ddll_rank0_4;
u32 emc_pmacro_quse_ddll_rank0_5;
u32 emc_pmacro_quse_ddll_rank1_0;
u32 emc_pmacro_quse_ddll_rank1_1;
u32 emc_pmacro_quse_ddll_rank1_2;
u32 emc_pmacro_quse_ddll_rank1_3;
u32 emc_pmacro_quse_ddll_rank1_4;
u32 emc_pmacro_quse_ddll_rank1_5;
u32 emc_pmacro_ob_ddll_long_dq_rank0_0;
u32 emc_pmacro_ob_ddll_long_dq_rank0_1;
u32 emc_pmacro_ob_ddll_long_dq_rank0_2;
u32 emc_pmacro_ob_ddll_long_dq_rank0_3;
u32 emc_pmacro_ob_ddll_long_dq_rank0_4;
u32 emc_pmacro_ob_ddll_long_dq_rank0_5;
u32 emc_pmacro_ob_ddll_long_dq_rank1_0;
u32 emc_pmacro_ob_ddll_long_dq_rank1_1;
u32 emc_pmacro_ob_ddll_long_dq_rank1_2;
u32 emc_pmacro_ob_ddll_long_dq_rank1_3;
u32 emc_pmacro_ob_ddll_long_dq_rank1_4;
u32 emc_pmacro_ob_ddll_long_dq_rank1_5;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_0;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_1;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_2;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_3;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_4;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_5;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_0;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_1;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_2;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_3;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_4;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_5;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_0;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_1;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_2;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_3;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_0;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_1;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_2;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_3;
u32 emc_pmacro_ddll_long_cmd_0;
u32 emc_pmacro_ddll_long_cmd_1;
u32 emc_pmacro_ddll_long_cmd_2;
u32 emc_pmacro_ddll_long_cmd_3;
u32 emc_pmacro_ddll_long_cmd_4;
u32 emc_pmacro_ddll_short_cmd_0;
u32 emc_pmacro_ddll_short_cmd_1;
u32 emc_pmacro_ddll_short_cmd_2;
u32 emc_pmacro_ddll_periodic_offset;
/*
* Specifies the delay after asserting CKE pin during a WarmBoot0
* sequence (in microseconds)
*/
u32 warm_boot_wait;
/* Specifies the value for EMC_ODT_WRITE */
u32 emc_odt_write;
/* Periodic ZQ calibration */
/*
* Specifies the value for EMC_ZCAL_INTERVAL
* Value 0 disables ZQ calibration
*/
u32 emc_zcal_interval;
/* Specifies the value for EMC_ZCAL_WAIT_CNT */
u32 emc_zcal_wait_cnt;
/* Specifies the value for EMC_ZCAL_MRW_CMD */
u32 emc_zcal_mrw_cmd;
/* DRAM initialization sequence flow control */
/* Specifies the MRS command value for resetting DLL */
u32 emc_mrs_reset_dll;
/* Specifies the command for ZQ initialization of device 0 */
u32 emc_zcal_init_dev0;
/* Specifies the command for ZQ initialization of device 1 */
u32 emc_zcal_init_dev1;
/*
* Specifies the wait time after programming a ZQ initialization
* command (in microseconds)
*/
u32 emc_zcal_init_wait;
/*
* Specifies the enable for ZQ calibration at cold boot [bit 0]
* and warm boot [bit 1]
*/
u32 emc_zcal_warm_cold_boot_enables;
/*
* Specifies the MRW command to LPDDR2 for ZQ calibration
* on warmboot
*/
/* Is issued to both devices separately */
u32 emc_mrw_lpddr2zcal_warm_boot;
/*
* Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
* Is issued to both devices separately
*/
u32 emc_zqcal_ddr3_warm_boot;
u32 emc_zqcal_lpddr4_warm_boot;
/*
* Specifies the wait time for ZQ calibration on warmboot
* (in microseconds)
*/
u32 emc_zcal_warm_boot_wait;
/*
* Specifies the enable for DRAM Mode Register programming
* at warm boot
*/
u32 emc_mrs_warm_boot_enable;
/*
* Specifies the wait time after sending an MRS DLL reset command
* in microseconds)
*/
u32 emc_mrs_reset_dll_wait;
/* Specifies the extra MRS command to initialize mode registers */
u32 emc_mrs_extra;
/* Specifies the extra MRS command at warm boot */
u32 emc_warm_boot_mrs_extra;
/* Specifies the EMRS command to enable the DDR2 DLL */
u32 emc_emrs_ddr2_dll_enable;
/* Specifies the MRS command to reset the DDR2 DLL */
u32 emc_mrs_ddr2_dll_reset;
/* Specifies the EMRS command to set OCD calibration */
u32 emc_emrs_ddr2_ocd_calib;
/*
* Specifies the wait between initializing DDR and setting OCD
* calibration (in microseconds)
*/
u32 emc_ddr2_wait;
/* Specifies the value for EMC_CLKEN_OVERRIDE */
u32 emc_clken_override;
/*
* Specifies LOG2 of the extra refresh numbers after booting
* Program 0 to disable
*/
u32 emc_extra_refresh_num;
/* Specifies the master override for all EMC clocks */
u32 emc_clken_override_allwarm_boot;
/* Specifies the master override for all MC clocks */
u32 mc_clken_override_allwarm_boot;
/* Specifies digital dll period, choosing between 4 to 64 ms */
u32 emc_cfg_dig_dll_period_warm_boot;
/* Pad controls */
/* Specifies the value for PMC_VDDP_SEL */
u32 pmc_vddp_sel;
/* Specifies the wait time after programming PMC_VDDP_SEL */
u32 pmc_vddp_sel_wait;
/* Specifies the value for PMC_DDR_CFG */
u32 pmc_ddr_cfg;
/* Specifies the value for PMC_IO_DPD3_REQ */
u32 pmc_io_dpd3_req;
/* Specifies the wait time after programming PMC_IO_DPD3_REQ */
u32 pmc_io_dpd3_req_wait;
u32 pmc_io_dpd4_req_wait;
/* Specifies the value for PMC_REG_SHORT */
u32 pmc_reg_short;
/* Specifies the value for PMC_NO_IOPOWER */
u32 pmc_no_io_power;
u32 pmc_ddr_ctrl_wait;
u32 pmc_ddr_ctrl;
/* Specifies the value for EMC_ACPD_CONTROL */
u32 emc_acpd_control;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */
u32 emc_swizzle_rank0_byte0;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */
u32 emc_swizzle_rank0_byte1;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */
u32 emc_swizzle_rank0_byte2;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */
u32 emc_swizzle_rank0_byte3;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */
u32 emc_swizzle_rank1_byte0;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */
u32 emc_swizzle_rank1_byte1;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */
u32 emc_swizzle_rank1_byte2;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */
u32 emc_swizzle_rank1_byte3;
/* Specifies the value for EMC_TXDSRVTTGEN */
u32 emc_txdsrvttgen;
/* Specifies the value for EMC_DATA_BRLSHFT_0 */
u32 emc_data_brlshft0;
u32 emc_data_brlshft1;
u32 emc_dqs_brlshft0;
u32 emc_dqs_brlshft1;
u32 emc_cmd_brlshft0;
u32 emc_cmd_brlshft1;
u32 emc_cmd_brlshft2;
u32 emc_cmd_brlshft3;
u32 emc_quse_brlshft0;
u32 emc_quse_brlshft1;
u32 emc_quse_brlshft2;
u32 emc_quse_brlshft3;
u32 emc_dll_cfg0;
u32 emc_dll_cfg1;
u32 emc_pmc_scratch1;
u32 emc_pmc_scratch2;
u32 emc_pmc_scratch3;
u32 emc_pmacro_pad_cfg_ctrl;
u32 emc_pmacro_vttgen_ctrl0;
u32 emc_pmacro_vttgen_ctrl1;
u32 emc_pmacro_vttgen_ctrl2;
u32 emc_pmacro_dsr_vttgen_ctrl0;
u32 emc_pmacro_brick_ctrl_rfu1;
u32 emc_pmacro_cmd_brick_ctrl_fdpd;
u32 emc_pmacro_brick_ctrl_rfu2;
u32 emc_pmacro_data_brick_ctrl_fdpd;
u32 emc_pmacro_bg_bias_ctrl0;
u32 emc_pmacro_data_pad_rx_ctrl;
u32 emc_pmacro_cmd_pad_rx_ctrl;
u32 emc_pmacro_data_rx_term_mode;
u32 emc_pmacro_cmd_rx_term_mode;
u32 emc_pmacro_data_pad_tx_ctrl;
u32 emc_pmacro_cmd_pad_tx_ctrl;
u32 emc_cfg3;
u32 emc_pmacro_tx_pwrd0;
u32 emc_pmacro_tx_pwrd1;
u32 emc_pmacro_tx_pwrd2;
u32 emc_pmacro_tx_pwrd3;
u32 emc_pmacro_tx_pwrd4;
u32 emc_pmacro_tx_pwrd5;
u32 emc_config_sample_delay;
u32 emc_pmacro_brick_mapping0;
u32 emc_pmacro_brick_mapping1;
u32 emc_pmacro_brick_mapping2;
u32 emc_pmacro_tx_sel_clk_src0;
u32 emc_pmacro_tx_sel_clk_src1;
u32 emc_pmacro_tx_sel_clk_src2;
u32 emc_pmacro_tx_sel_clk_src3;
u32 emc_pmacro_tx_sel_clk_src4;
u32 emc_pmacro_tx_sel_clk_src5;
u32 emc_pmacro_perbit_fgcg_ctrl0;
u32 emc_pmacro_perbit_fgcg_ctrl1;
u32 emc_pmacro_perbit_fgcg_ctrl2;
u32 emc_pmacro_perbit_fgcg_ctrl3;
u32 emc_pmacro_perbit_fgcg_ctrl4;
u32 emc_pmacro_perbit_fgcg_ctrl5;
u32 emc_pmacro_perbit_rfu_ctrl0;
u32 emc_pmacro_perbit_rfu_ctrl1;
u32 emc_pmacro_perbit_rfu_ctrl2;
u32 emc_pmacro_perbit_rfu_ctrl3;
u32 emc_pmacro_perbit_rfu_ctrl4;
u32 emc_pmacro_perbit_rfu_ctrl5;
u32 emc_pmacro_perbit_rfu1_ctrl0;
u32 emc_pmacro_perbit_rfu1_ctrl1;
u32 emc_pmacro_perbit_rfu1_ctrl2;
u32 emc_pmacro_perbit_rfu1_ctrl3;
u32 emc_pmacro_perbit_rfu1_ctrl4;
u32 emc_pmacro_perbit_rfu1_ctrl5;
u32 emc_pmacro_data_pi_ctrl;
u32 emc_pmacro_cmd_pi_ctrl;
u32 emc_pmacro_ddll_bypass;
u32 emc_pmacro_ddll_pwrd0;
u32 emc_pmacro_ddll_pwrd1;
u32 emc_pmacro_ddll_pwrd2;
u32 emc_pmacro_cmd_ctrl0;
u32 emc_pmacro_cmd_ctrl1;
u32 emc_pmacro_cmd_ctrl2;
/* DRAM size information */
/* Specifies the value for MC_EMEM_ADR_CFG */
u32 mc_emem_adr_cfg;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */
u32 mc_emem_adr_cfg_dev0;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */
u32 mc_emem_adr_cfg_dev1;
u32 mc_emem_adr_cfg_channel_mask;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */
u32 mc_emem_adr_cfg_bank_mask0;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */
u32 mc_emem_adr_cfg_bank_mask1;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */
u32 mc_emem_adr_cfg_bank_mask2;
/*
* Specifies the value for MC_EMEM_CFG which holds the external memory
* size (in KBytes)
*/
u32 mc_emem_cfg;
/* MC arbitration configuration */
/* Specifies the value for MC_EMEM_ARB_CFG */
u32 mc_emem_arb_cfg;
/* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */
u32 mc_emem_arb_outstanding_req;
u32 emc_emem_arb_refpb_hp_ctrl;
u32 emc_emem_arb_refpb_bank_ctrl;
/* Specifies the value for MC_EMEM_ARB_TIMING_RCD */
u32 mc_emem_arb_timing_rcd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RP */
u32 mc_emem_arb_timing_rp;
/* Specifies the value for MC_EMEM_ARB_TIMING_RC */
u32 mc_emem_arb_timing_rc;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAS */
u32 mc_emem_arb_timing_ras;
/* Specifies the value for MC_EMEM_ARB_TIMING_FAW */
u32 mc_emem_arb_timing_faw;
/* Specifies the value for MC_EMEM_ARB_TIMING_RRD */
u32 mc_emem_arb_timing_rrd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */
u32 mc_emem_arb_timing_rap2pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */
u32 mc_emem_arb_timing_wap2pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2R */
u32 mc_emem_arb_timing_r2r;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2W */
u32 mc_emem_arb_timing_w2w;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2W */
u32 mc_emem_arb_timing_r2w;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2R */
u32 mc_emem_arb_timing_w2r;
u32 mc_emem_arb_timing_rfcpb;
/* Specifies the value for MC_EMEM_ARB_DA_TURNS */
u32 mc_emem_arb_da_turns;
/* Specifies the value for MC_EMEM_ARB_DA_COVERS */
u32 mc_emem_arb_da_covers;
/* Specifies the value for MC_EMEM_ARB_MISC0 */
u32 mc_emem_arb_misc0;
/* Specifies the value for MC_EMEM_ARB_MISC1 */
u32 mc_emem_arb_misc1;
u32 mc_emem_arb_misc2;
/* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */
u32 mc_emem_arb_ring1_throttle;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE */
u32 mc_emem_arb_override;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */
u32 mc_emem_arb_override1;
/* Specifies the value for MC_EMEM_ARB_RSV */
u32 mc_emem_arb_rsv;
u32 mc_da_cfg0;
u32 mc_emem_arb_timing_ccdmw;
/* Specifies the value for MC_CLKEN_OVERRIDE */
u32 mc_clken_override;
/* Specifies the value for MC_STAT_CONTROL */
u32 mc_stat_control;
/* Specifies the value for MC_VIDEO_PROTECT_BOM */
u32 mc_video_protect_bom;
/* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */
u32 mc_video_protect_bom_adr_hi;
/* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */
u32 mc_video_protect_size_mb;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */
u32 mc_video_protect_vpr_override;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */
u32 mc_video_protect_vpr_override1;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */
u32 mc_video_protect_gpu_override0;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */
u32 mc_video_protect_gpu_override1;
/* Specifies the value for MC_SEC_CARVEOUT_BOM */
u32 mc_sec_carveout_bom;
/* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */
u32 mc_sec_carveout_adr_hi;
/* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */
u32 mc_sec_carveout_size_mb;
/* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */
u32 mc_video_protect_write_access;
/* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */
u32 mc_sec_carveout_protect_write_access;
u32 mc_generalized_carveout1_bom;
u32 mc_generalized_carveout1_bom_hi;
u32 mc_generalized_carveout1_size_128kb;
u32 mc_generalized_carveout1_access0;
u32 mc_generalized_carveout1_access1;
u32 mc_generalized_carveout1_access2;
u32 mc_generalized_carveout1_access3;
u32 mc_generalized_carveout1_access4;
u32 mc_generalized_carveout1_force_internal_access0;
u32 mc_generalized_carveout1_force_internal_access1;
u32 mc_generalized_carveout1_force_internal_access2;
u32 mc_generalized_carveout1_force_internal_access3;
u32 mc_generalized_carveout1_force_internal_access4;
u32 mc_generalized_carveout1_cfg0;
u32 mc_generalized_carveout2_bom;
u32 mc_generalized_carveout2_bom_hi;
u32 mc_generalized_carveout2_size_128kb;
u32 mc_generalized_carveout2_access0;
u32 mc_generalized_carveout2_access1;
u32 mc_generalized_carveout2_access2;
u32 mc_generalized_carveout2_access3;
u32 mc_generalized_carveout2_access4;
u32 mc_generalized_carveout2_force_internal_access0;
u32 mc_generalized_carveout2_force_internal_access1;
u32 mc_generalized_carveout2_force_internal_access2;
u32 mc_generalized_carveout2_force_internal_access3;
u32 mc_generalized_carveout2_force_internal_access4;
u32 mc_generalized_carveout2_cfg0;
u32 mc_generalized_carveout3_bom;
u32 mc_generalized_carveout3_bom_hi;
u32 mc_generalized_carveout3_size_128kb;
u32 mc_generalized_carveout3_access0;
u32 mc_generalized_carveout3_access1;
u32 mc_generalized_carveout3_access2;
u32 mc_generalized_carveout3_access3;
u32 mc_generalized_carveout3_access4;
u32 mc_generalized_carveout3_force_internal_access0;
u32 mc_generalized_carveout3_force_internal_access1;
u32 mc_generalized_carveout3_force_internal_access2;
u32 mc_generalized_carveout3_force_internal_access3;
u32 mc_generalized_carveout3_force_internal_access4;
u32 mc_generalized_carveout3_cfg0;
u32 mc_generalized_carveout4_bom;
u32 mc_generalized_carveout4_bom_hi;
u32 mc_generalized_carveout4_size_128kb;
u32 mc_generalized_carveout4_access0;
u32 mc_generalized_carveout4_access1;
u32 mc_generalized_carveout4_access2;
u32 mc_generalized_carveout4_access3;
u32 mc_generalized_carveout4_access4;
u32 mc_generalized_carveout4_force_internal_access0;
u32 mc_generalized_carveout4_force_internal_access1;
u32 mc_generalized_carveout4_force_internal_access2;
u32 mc_generalized_carveout4_force_internal_access3;
u32 mc_generalized_carveout4_force_internal_access4;
u32 mc_generalized_carveout4_cfg0;
u32 mc_generalized_carveout5_bom;
u32 mc_generalized_carveout5_bom_hi;
u32 mc_generalized_carveout5_size_128kb;
u32 mc_generalized_carveout5_access0;
u32 mc_generalized_carveout5_access1;
u32 mc_generalized_carveout5_access2;
u32 mc_generalized_carveout5_access3;
u32 mc_generalized_carveout5_access4;
u32 mc_generalized_carveout5_force_internal_access0;
u32 mc_generalized_carveout5_force_internal_access1;
u32 mc_generalized_carveout5_force_internal_access2;
u32 mc_generalized_carveout5_force_internal_access3;
u32 mc_generalized_carveout5_force_internal_access4;
u32 mc_generalized_carveout5_cfg0;
/* Specifies enable for CA training */
u32 emc_ca_training_enable;
/* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */
u32 swizzle_rank_byte_encode;
/* Specifies enable and offset for patched boot rom write */
u32 boot_rom_patch_control;
/* Specifies data for patched boot rom write */
u32 boot_rom_patch_data;
/* Specifies the value for MC_MTS_CARVEOUT_BOM */
u32 mc_mts_carveout_bom;
/* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */
u32 mc_mts_carveout_adr_hi;
/* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */
u32 mc_mts_carveout_size_mb;
/* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */
u32 mc_mts_carveout_reg_ctrl;
u32 mc_untranslated_region_check;
/* Just a place holder for special usage when there is no BCT for certain registers */
u32 bct_na;
};
#endif

930
bdk/mem/sdram_param_t210.h Normal file
View File

@@ -0,0 +1,930 @@
/*
* Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* See file CREDITS for list of people who contributed to this
* project.
*/
/**
* Defines the SDRAM parameter structure.
*
* Note that PLLM is used by EMC.
*/
#ifndef _SDRAM_PARAM_T210_H_
#define _SDRAM_PARAM_T210_H_
#define MEMORY_TYPE_NONE 0
#define MEMORY_TYPE_DDR 0
#define MEMORY_TYPE_LPDDR 0
#define MEMORY_TYPE_DDR2 0
#define MEMORY_TYPE_LPDDR2 1
#define MEMORY_TYPE_DDR3L 2
#define MEMORY_TYPE_LPDDR4 3
/**
* Defines the SDRAM parameter structure
*/
typedef struct _sdram_params_t210_t
{
/* Specifies the type of memory device */
u32 memory_type;
/* MC/EMC clock source configuration */
/* Specifies the M value for PllM */
u32 pllm_input_divider;
/* Specifies the N value for PllM */
u32 pllm_feedback_divider;
/* Specifies the time to wait for PLLM to lock (in microseconds) */
u32 pllm_stable_time;
/* Specifies misc. control bits */
u32 pllm_setup_control;
/* Specifies the P value for PLLM */
u32 pllm_post_divider;
/* Specifies value for Charge Pump Gain Control */
u32 pllm_kcp;
/* Specifies VCO gain */
u32 pllm_kvco;
/* Spare BCT param */
u32 emc_bct_spare0;
/* Spare BCT param */
u32 emc_bct_spare1;
/* Spare BCT param */
u32 emc_bct_spare2;
/* Spare BCT param */
u32 emc_bct_spare3;
/* Spare BCT param */
u32 emc_bct_spare4;
/* Spare BCT param */
u32 emc_bct_spare5;
/* Spare BCT param */
u32 emc_bct_spare6;
/* Spare BCT param */
u32 emc_bct_spare7;
/* Spare BCT param */
u32 emc_bct_spare8;
/* Spare BCT param */
u32 emc_bct_spare9;
/* Spare BCT param */
u32 emc_bct_spare10;
/* Spare BCT param */
u32 emc_bct_spare11;
/* Spare BCT param */
u32 emc_bct_spare12;
/* Spare BCT param */
u32 emc_bct_spare13;
/* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */
u32 emc_clock_source;
u32 emc_clock_source_dll;
/* Defines possible override for PLLLM_MISC2 */
u32 clk_rst_pllm_misc20_override;
/* enables override for PLLLM_MISC2 */
u32 clk_rst_pllm_misc20_override_enable;
/* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */
u32 clear_clock2_mc1;
/* Auto-calibration of EMC pads */
/* Specifies the value for EMC_AUTO_CAL_INTERVAL */
u32 emc_auto_cal_interval;
/*
* Specifies the value for EMC_AUTO_CAL_CONFIG
* Note: Trigger bits are set by the SDRAM code.
*/
u32 emc_auto_cal_config;
/* Specifies the value for EMC_AUTO_CAL_CONFIG2 */
u32 emc_auto_cal_config2;
/* Specifies the value for EMC_AUTO_CAL_CONFIG3 */
u32 emc_auto_cal_config3;
u32 emc_auto_cal_config4;
u32 emc_auto_cal_config5;
u32 emc_auto_cal_config6;
u32 emc_auto_cal_config7;
u32 emc_auto_cal_config8;
/* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */
u32 emc_auto_cal_vref_sel0;
u32 emc_auto_cal_vref_sel1;
/* Specifies the value for EMC_AUTO_CAL_CHANNEL */
u32 emc_auto_cal_channel;
/* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */
u32 emc_pmacro_auto_cal_cfg0;
u32 emc_pmacro_auto_cal_cfg1;
u32 emc_pmacro_auto_cal_cfg2;
u32 emc_pmacro_rx_term;
u32 emc_pmacro_dq_tx_drive;
u32 emc_pmacro_ca_tx_drive;
u32 emc_pmacro_cmd_tx_drive;
u32 emc_pmacro_auto_cal_common;
u32 emc_pmacro_zcrtl;
/*
* Specifies the time for the calibration
* to stabilize (in microseconds)
*/
u32 emc_auto_cal_wait;
u32 emc_xm2_comp_pad_ctrl;
u32 emc_xm2_comp_pad_ctrl2;
u32 emc_xm2_comp_pad_ctrl3;
/*
* DRAM size information
* Specifies the value for EMC_ADR_CFG
*/
u32 emc_adr_cfg;
/*
* Specifies the time to wait after asserting pin
* CKE (in microseconds)
*/
u32 emc_pin_program_wait;
/* Specifies the extra delay before/after pin RESET/CKE command */
u32 emc_pin_extra_wait;
u32 emc_pin_gpio_enable;
u32 emc_pin_gpio;
/*
* Specifies the extra delay after the first writing
* of EMC_TIMING_CONTROL
*/
u32 emc_timing_control_wait;
/* Timing parameters required for the SDRAM */
/* Specifies the value for EMC_RC */
u32 emc_rc;
/* Specifies the value for EMC_RFC */
u32 emc_rfc;
u32 emc_rfc_pb;
u32 emc_ref_ctrl2;
/* Specifies the value for EMC_RFC_SLR */
u32 emc_rfc_slr;
/* Specifies the value for EMC_RAS */
u32 emc_ras;
/* Specifies the value for EMC_RP */
u32 emc_rp;
/* Specifies the value for EMC_R2R */
u32 emc_r2r;
/* Specifies the value for EMC_W2W */
u32 emc_w2w;
/* Specifies the value for EMC_R2W */
u32 emc_r2w;
/* Specifies the value for EMC_W2R */
u32 emc_w2r;
/* Specifies the value for EMC_R2P */
u32 emc_r2p;
/* Specifies the value for EMC_W2P */
u32 emc_w2p;
/* Specifies the value for EMC_RD_RCD */
u32 emc_tppd;
u32 emc_ccdmw;
u32 emc_rd_rcd;
/* Specifies the value for EMC_WR_RCD */
u32 emc_wr_rcd;
/* Specifies the value for EMC_RRD */
u32 emc_rrd;
/* Specifies the value for EMC_REXT */
u32 emc_rext;
/* Specifies the value for EMC_WEXT */
u32 emc_wext;
/* Specifies the value for EMC_WDV */
u32 emc_wdv;
u32 emc_wdv_chk;
u32 emc_wsv;
u32 emc_wev;
/* Specifies the value for EMC_WDV_MASK */
u32 emc_wdv_mask;
u32 emc_ws_duration;
u32 emc_we_duration;
/* Specifies the value for EMC_QUSE */
u32 emc_quse;
/* Specifies the value for EMC_QUSE_WIDTH */
u32 emc_quse_width;
/* Specifies the value for EMC_IBDLY */
u32 emc_ibdly;
u32 emc_obdly;
/* Specifies the value for EMC_EINPUT */
u32 emc_einput;
/* Specifies the value for EMC_EINPUT_DURATION */
u32 emc_einput_duration;
/* Specifies the value for EMC_PUTERM_EXTRA */
u32 emc_puterm_extra;
/* Specifies the value for EMC_PUTERM_WIDTH */
u32 emc_puterm_width;
u32 emc_qrst;
u32 emc_qsafe;
u32 emc_rdv;
u32 emc_rdv_mask;
u32 emc_rdv_early;
u32 emc_rdv_early_mask;
/* Specifies the value for EMC_QPOP */
u32 emc_qpop;
/* Specifies the value for EMC_REFRESH */
u32 emc_refresh;
/* Specifies the value for EMC_BURST_REFRESH_NUM */
u32 emc_burst_refresh_num;
/* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */
u32 emc_prerefresh_req_cnt;
/* Specifies the value for EMC_PDEX2WR */
u32 emc_pdex2wr;
/* Specifies the value for EMC_PDEX2RD */
u32 emc_pdex2rd;
/* Specifies the value for EMC_PCHG2PDEN */
u32 emc_pchg2pden;
/* Specifies the value for EMC_ACT2PDEN */
u32 emc_act2pden;
/* Specifies the value for EMC_AR2PDEN */
u32 emc_ar2pden;
/* Specifies the value for EMC_RW2PDEN */
u32 emc_rw2pden;
u32 emc_cke2pden;
u32 emc_pdex2che;
u32 emc_pdex2mrr;
/* Specifies the value for EMC_TXSR */
u32 emc_txsr;
/* Specifies the value for EMC_TXSRDLL */
u32 emc_txsr_dll;
/* Specifies the value for EMC_TCKE */
u32 emc_tcke;
/* Specifies the value for EMC_TCKESR */
u32 emc_tckesr;
/* Specifies the value for EMC_TPD */
u32 emc_tpd;
/* Specifies the value for EMC_TFAW */
u32 emc_tfaw;
/* Specifies the value for EMC_TRPAB */
u32 emc_trpab;
/* Specifies the value for EMC_TCLKSTABLE */
u32 emc_tclkstable;
/* Specifies the value for EMC_TCLKSTOP */
u32 emc_tclkstop;
/* Specifies the value for EMC_TREFBW */
u32 emc_trefbw;
/* FBIO configuration values */
/* Specifies the value for EMC_FBIO_CFG5 */
u32 emc_fbio_cfg5;
/* Specifies the value for EMC_FBIO_CFG7 */
u32 emc_fbio_cfg7;
u32 emc_fbio_cfg8;
/* Command mapping for CMD brick 0 */
u32 emc_cmd_mapping_cmd0_0;
u32 emc_cmd_mapping_cmd0_1;
u32 emc_cmd_mapping_cmd0_2;
u32 emc_cmd_mapping_cmd1_0;
u32 emc_cmd_mapping_cmd1_1;
u32 emc_cmd_mapping_cmd1_2;
u32 emc_cmd_mapping_cmd2_0;
u32 emc_cmd_mapping_cmd2_1;
u32 emc_cmd_mapping_cmd2_2;
u32 emc_cmd_mapping_cmd3_0;
u32 emc_cmd_mapping_cmd3_1;
u32 emc_cmd_mapping_cmd3_2;
u32 emc_cmd_mapping_byte;
/* Specifies the value for EMC_FBIO_SPARE */
u32 emc_fbio_spare;
/* Specifies the value for EMC_CFG_RSV */
u32 emc_cfg_rsv;
/* MRS command values */
/* Specifies the value for EMC_MRS */
u32 emc_mrs;
/* Specifies the MP0 command to initialize mode registers */
u32 emc_emrs;
/* Specifies the MP2 command to initialize mode registers */
u32 emc_emrs2;
/* Specifies the MP3 command to initialize mode registers */
u32 emc_emrs3;
/* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */
u32 emc_mrw1;
/* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */
u32 emc_mrw2;
/* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */
u32 emc_mrw3;
/* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */
u32 emc_mrw4;
/* Specifies the programming to LPDDR4 Mode Register 3 at cold boot */
u32 emc_mrw6;
/* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */
u32 emc_mrw8;
/* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */
u32 emc_mrw9;
/* Specifies the programming to LPDDR4 Mode Register 12 at cold boot */
u32 emc_mrw10;
/* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */
u32 emc_mrw12;
/* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */
u32 emc_mrw13;
/* Specifies the programming to LPDDR4 Mode Register 22 at cold boot */
u32 emc_mrw14;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at cold boot
*/
u32 emc_mrw_extra;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at warm boot
*/
u32 emc_warm_boot_mrw_extra;
/*
* Specify the enable of extra Mode Register programming at
* warm boot
*/
u32 emc_warm_boot_extramode_reg_write_enable;
/*
* Specify the enable of extra Mode Register programming at
* cold boot
*/
u32 emc_extramode_reg_write_enable;
/* Specifies the EMC_MRW reset command value */
u32 emc_mrw_reset_command;
/* Specifies the EMC Reset wait time (in microseconds) */
u32 emc_mrw_reset_ninit_wait;
/* Specifies the value for EMC_MRS_WAIT_CNT */
u32 emc_mrs_wait_cnt;
/* Specifies the value for EMC_MRS_WAIT_CNT2 */
u32 emc_mrs_wait_cnt2;
/* EMC miscellaneous configurations */
/* Specifies the value for EMC_CFG */
u32 emc_cfg;
/* Specifies the value for EMC_CFG_2 */
u32 emc_cfg2;
/* Specifies the pipe bypass controls */
u32 emc_cfg_pipe;
u32 emc_cfg_pipe_clk;
u32 emc_fdpd_ctrl_cmd_no_ramp;
u32 emc_cfg_update;
/* Specifies the value for EMC_DBG */
u32 emc_dbg;
u32 emc_dbg_write_mux;
/* Specifies the value for EMC_CMDQ */
u32 emc_cmd_q;
/* Specifies the value for EMC_MC2EMCQ */
u32 emc_mc2emc_q;
/* Specifies the value for EMC_DYN_SELF_REF_CONTROL */
u32 emc_dyn_self_ref_control;
/* Specifies the value for MEM_INIT_DONE */
u32 ahb_arbitration_xbar_ctrl_meminit_done;
/* Specifies the value for EMC_CFG_DIG_DLL */
u32 emc_cfg_dig_dll;
u32 emc_cfg_dig_dll_1;
/* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */
u32 emc_cfg_dig_dll_period;
/* Specifies the value of *DEV_SELECTN of various EMC registers */
u32 emc_dev_select;
/* Specifies the value for EMC_SEL_DPD_CTRL */
u32 emc_sel_dpd_ctrl;
/* Pads trimmer delays */
u32 emc_fdpd_ctrl_dq;
u32 emc_fdpd_ctrl_cmd;
u32 emc_pmacro_ib_vref_dq_0;
u32 emc_pmacro_ib_vref_dq_1;
u32 emc_pmacro_ib_vref_dqs_0;
u32 emc_pmacro_ib_vref_dqs_1;
u32 emc_pmacro_ib_rxrt;
u32 emc_cfg_pipe1;
u32 emc_cfg_pipe2;
/* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */
u32 emc_pmacro_quse_ddll_rank0_0;
u32 emc_pmacro_quse_ddll_rank0_1;
u32 emc_pmacro_quse_ddll_rank0_2;
u32 emc_pmacro_quse_ddll_rank0_3;
u32 emc_pmacro_quse_ddll_rank0_4;
u32 emc_pmacro_quse_ddll_rank0_5;
u32 emc_pmacro_quse_ddll_rank1_0;
u32 emc_pmacro_quse_ddll_rank1_1;
u32 emc_pmacro_quse_ddll_rank1_2;
u32 emc_pmacro_quse_ddll_rank1_3;
u32 emc_pmacro_quse_ddll_rank1_4;
u32 emc_pmacro_quse_ddll_rank1_5;
u32 emc_pmacro_ob_ddll_long_dq_rank0_0;
u32 emc_pmacro_ob_ddll_long_dq_rank0_1;
u32 emc_pmacro_ob_ddll_long_dq_rank0_2;
u32 emc_pmacro_ob_ddll_long_dq_rank0_3;
u32 emc_pmacro_ob_ddll_long_dq_rank0_4;
u32 emc_pmacro_ob_ddll_long_dq_rank0_5;
u32 emc_pmacro_ob_ddll_long_dq_rank1_0;
u32 emc_pmacro_ob_ddll_long_dq_rank1_1;
u32 emc_pmacro_ob_ddll_long_dq_rank1_2;
u32 emc_pmacro_ob_ddll_long_dq_rank1_3;
u32 emc_pmacro_ob_ddll_long_dq_rank1_4;
u32 emc_pmacro_ob_ddll_long_dq_rank1_5;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_0;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_1;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_2;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_3;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_4;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_5;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_0;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_1;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_2;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_3;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_4;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_5;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_0;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_1;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_2;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_3;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_0;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_1;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_2;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_3;
u32 emc_pmacro_ddll_long_cmd_0;
u32 emc_pmacro_ddll_long_cmd_1;
u32 emc_pmacro_ddll_long_cmd_2;
u32 emc_pmacro_ddll_long_cmd_3;
u32 emc_pmacro_ddll_long_cmd_4;
u32 emc_pmacro_ddll_short_cmd_0;
u32 emc_pmacro_ddll_short_cmd_1;
u32 emc_pmacro_ddll_short_cmd_2;
/*
* Specifies the delay after asserting CKE pin during a WarmBoot0
* sequence (in microseconds)
*/
u32 warm_boot_wait;
/* Specifies the value for EMC_ODT_WRITE */
u32 emc_odt_write;
/* Periodic ZQ calibration */
/*
* Specifies the value for EMC_ZCAL_INTERVAL
* Value 0 disables ZQ calibration
*/
u32 emc_zcal_interval;
/* Specifies the value for EMC_ZCAL_WAIT_CNT */
u32 emc_zcal_wait_cnt;
/* Specifies the value for EMC_ZCAL_MRW_CMD */
u32 emc_zcal_mrw_cmd;
/* DRAM initialization sequence flow control */
/* Specifies the MRS command value for resetting DLL */
u32 emc_mrs_reset_dll;
/* Specifies the command for ZQ initialization of device 0 */
u32 emc_zcal_init_dev0;
/* Specifies the command for ZQ initialization of device 1 */
u32 emc_zcal_init_dev1;
/*
* Specifies the wait time after programming a ZQ initialization
* command (in microseconds)
*/
u32 emc_zcal_init_wait;
/*
* Specifies the enable for ZQ calibration at cold boot [bit 0]
* and warm boot [bit 1]
*/
u32 emc_zcal_warm_cold_boot_enables;
/*
* Specifies the MRW command to LPDDR2 for ZQ calibration
* on warmboot
*/
/* Is issued to both devices separately */
u32 emc_mrw_lpddr2zcal_warm_boot;
/*
* Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
* Is issued to both devices separately
*/
u32 emc_zqcal_ddr3_warm_boot;
u32 emc_zqcal_lpddr4_warm_boot;
/*
* Specifies the wait time for ZQ calibration on warmboot
* (in microseconds)
*/
u32 emc_zcal_warm_boot_wait;
/*
* Specifies the enable for DRAM Mode Register programming
* at warm boot
*/
u32 emc_mrs_warm_boot_enable;
/*
* Specifies the wait time after sending an MRS DLL reset command
* in microseconds)
*/
u32 emc_mrs_reset_dll_wait;
/* Specifies the extra MRS command to initialize mode registers */
u32 emc_mrs_extra;
/* Specifies the extra MRS command at warm boot */
u32 emc_warm_boot_mrs_extra;
/* Specifies the EMRS command to enable the DDR2 DLL */
u32 emc_emrs_ddr2_dll_enable;
/* Specifies the MRS command to reset the DDR2 DLL */
u32 emc_mrs_ddr2_dll_reset;
/* Specifies the EMRS command to set OCD calibration */
u32 emc_emrs_ddr2_ocd_calib;
/*
* Specifies the wait between initializing DDR and setting OCD
* calibration (in microseconds)
*/
u32 emc_ddr2_wait;
/* Specifies the value for EMC_CLKEN_OVERRIDE */
u32 emc_clken_override;
/*
* Specifies LOG2 of the extra refresh numbers after booting
* Program 0 to disable
*/
u32 emc_extra_refresh_num;
/* Specifies the master override for all EMC clocks */
u32 emc_clken_override_allwarm_boot;
/* Specifies the master override for all MC clocks */
u32 mc_clken_override_allwarm_boot;
/* Specifies digital dll period, choosing between 4 to 64 ms */
u32 emc_cfg_dig_dll_period_warm_boot;
/* Pad controls */
/* Specifies the value for PMC_VDDP_SEL */
u32 pmc_vddp_sel;
/* Specifies the wait time after programming PMC_VDDP_SEL */
u32 pmc_vddp_sel_wait;
/* Specifies the value for PMC_DDR_PWR */
u32 pmc_ddr_pwr;
/* Specifies the value for PMC_DDR_CFG */
u32 pmc_ddr_cfg;
/* Specifies the value for PMC_IO_DPD3_REQ */
u32 pmc_io_dpd3_req;
/* Specifies the wait time after programming PMC_IO_DPD3_REQ */
u32 pmc_io_dpd3_req_wait;
u32 pmc_io_dpd4_req_wait;
/* Specifies the value for PMC_REG_SHORT */
u32 pmc_reg_short;
/* Specifies the value for PMC_NO_IOPOWER */
u32 pmc_no_io_power;
u32 pmc_ddr_ctrl_wait;
u32 pmc_ddr_ctrl;
/* Specifies the value for EMC_ACPD_CONTROL */
u32 emc_acpd_control;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */
u32 emc_swizzle_rank0_byte0;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */
u32 emc_swizzle_rank0_byte1;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */
u32 emc_swizzle_rank0_byte2;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */
u32 emc_swizzle_rank0_byte3;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */
u32 emc_swizzle_rank1_byte0;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */
u32 emc_swizzle_rank1_byte1;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */
u32 emc_swizzle_rank1_byte2;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */
u32 emc_swizzle_rank1_byte3;
/* Specifies the value for EMC_TXDSRVTTGEN */
u32 emc_txdsrvttgen;
/* Specifies the value for EMC_DATA_BRLSHFT_0 */
u32 emc_data_brlshft0;
u32 emc_data_brlshft1;
u32 emc_dqs_brlshft0;
u32 emc_dqs_brlshft1;
u32 emc_cmd_brlshft0;
u32 emc_cmd_brlshft1;
u32 emc_cmd_brlshft2;
u32 emc_cmd_brlshft3;
u32 emc_quse_brlshft0;
u32 emc_quse_brlshft1;
u32 emc_quse_brlshft2;
u32 emc_quse_brlshft3;
u32 emc_dll_cfg0;
u32 emc_dll_cfg1;
u32 emc_pmc_scratch1;
u32 emc_pmc_scratch2;
u32 emc_pmc_scratch3;
u32 emc_pmacro_pad_cfg_ctrl;
u32 emc_pmacro_vttgen_ctrl0;
u32 emc_pmacro_vttgen_ctrl1;
u32 emc_pmacro_vttgen_ctrl2;
u32 emc_pmacro_brick_ctrl_rfu1;
u32 emc_pmacro_cmd_brick_ctrl_fdpd;
u32 emc_pmacro_brick_ctrl_rfu2;
u32 emc_pmacro_data_brick_ctrl_fdpd;
u32 emc_pmacro_bg_bias_ctrl0;
u32 emc_pmacro_data_pad_rx_ctrl;
u32 emc_pmacro_cmd_pad_rx_ctrl;
u32 emc_pmacro_data_rx_term_mode;
u32 emc_pmacro_cmd_rx_term_mode;
u32 emc_pmacro_data_pad_tx_ctrl;
u32 emc_pmacro_common_pad_tx_ctrl;
u32 emc_pmacro_cmd_pad_tx_ctrl;
u32 emc_cfg3;
u32 emc_pmacro_tx_pwrd0;
u32 emc_pmacro_tx_pwrd1;
u32 emc_pmacro_tx_pwrd2;
u32 emc_pmacro_tx_pwrd3;
u32 emc_pmacro_tx_pwrd4;
u32 emc_pmacro_tx_pwrd5;
u32 emc_config_sample_delay;
u32 emc_pmacro_brick_mapping0;
u32 emc_pmacro_brick_mapping1;
u32 emc_pmacro_brick_mapping2;
u32 emc_pmacro_tx_sel_clk_src0;
u32 emc_pmacro_tx_sel_clk_src1;
u32 emc_pmacro_tx_sel_clk_src2;
u32 emc_pmacro_tx_sel_clk_src3;
u32 emc_pmacro_tx_sel_clk_src4;
u32 emc_pmacro_tx_sel_clk_src5;
u32 emc_pmacro_ddll_bypass;
u32 emc_pmacro_ddll_pwrd0;
u32 emc_pmacro_ddll_pwrd1;
u32 emc_pmacro_ddll_pwrd2;
u32 emc_pmacro_cmd_ctrl0;
u32 emc_pmacro_cmd_ctrl1;
u32 emc_pmacro_cmd_ctrl2;
/* DRAM size information */
/* Specifies the value for MC_EMEM_ADR_CFG */
u32 mc_emem_adr_cfg;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */
u32 mc_emem_adr_cfg_dev0;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */
u32 mc_emem_adr_cfg_dev1;
u32 mc_emem_adr_cfg_channel_mask;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */
u32 mc_emem_adr_cfg_bank_mask0;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */
u32 mc_emem_adr_cfg_bank_mask1;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */
u32 mc_emem_adr_cfg_bank_mask2;
/*
* Specifies the value for MC_EMEM_CFG which holds the external memory
* size (in KBytes)
*/
u32 mc_emem_cfg;
/* MC arbitration configuration */
/* Specifies the value for MC_EMEM_ARB_CFG */
u32 mc_emem_arb_cfg;
/* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */
u32 mc_emem_arb_outstanding_req;
u32 emc_emem_arb_refpb_hp_ctrl;
u32 emc_emem_arb_refpb_bank_ctrl;
/* Specifies the value for MC_EMEM_ARB_TIMING_RCD */
u32 mc_emem_arb_timing_rcd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RP */
u32 mc_emem_arb_timing_rp;
/* Specifies the value for MC_EMEM_ARB_TIMING_RC */
u32 mc_emem_arb_timing_rc;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAS */
u32 mc_emem_arb_timing_ras;
/* Specifies the value for MC_EMEM_ARB_TIMING_FAW */
u32 mc_emem_arb_timing_faw;
/* Specifies the value for MC_EMEM_ARB_TIMING_RRD */
u32 mc_emem_arb_timing_rrd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */
u32 mc_emem_arb_timing_rap2pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */
u32 mc_emem_arb_timing_wap2pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2R */
u32 mc_emem_arb_timing_r2r;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2W */
u32 mc_emem_arb_timing_w2w;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2W */
u32 mc_emem_arb_timing_r2w;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2R */
u32 mc_emem_arb_timing_w2r;
u32 mc_emem_arb_timing_rfcpb;
/* Specifies the value for MC_EMEM_ARB_DA_TURNS */
u32 mc_emem_arb_da_turns;
/* Specifies the value for MC_EMEM_ARB_DA_COVERS */
u32 mc_emem_arb_da_covers;
/* Specifies the value for MC_EMEM_ARB_MISC0 */
u32 mc_emem_arb_misc0;
/* Specifies the value for MC_EMEM_ARB_MISC1 */
u32 mc_emem_arb_misc1;
u32 mc_emem_arb_misc2;
/* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */
u32 mc_emem_arb_ring1_throttle;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE */
u32 mc_emem_arb_override;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */
u32 mc_emem_arb_override1;
/* Specifies the value for MC_EMEM_ARB_RSV */
u32 mc_emem_arb_rsv;
u32 mc_da_cfg0;
u32 mc_emem_arb_timing_ccdmw;
/* Specifies the value for MC_CLKEN_OVERRIDE */
u32 mc_clken_override;
/* Specifies the value for MC_STAT_CONTROL */
u32 mc_stat_control;
/* Specifies the value for MC_VIDEO_PROTECT_BOM */
u32 mc_video_protect_bom;
/* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */
u32 mc_video_protect_bom_adr_hi;
/* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */
u32 mc_video_protect_size_mb;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */
u32 mc_video_protect_vpr_override;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */
u32 mc_video_protect_vpr_override1;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */
u32 mc_video_protect_gpu_override0;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */
u32 mc_video_protect_gpu_override1;
/* Specifies the value for MC_SEC_CARVEOUT_BOM */
u32 mc_sec_carveout_bom;
/* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */
u32 mc_sec_carveout_adr_hi;
/* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */
u32 mc_sec_carveout_size_mb;
/* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */
u32 mc_video_protect_write_access;
/* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */
u32 mc_sec_carveout_protect_write_access;
u32 mc_generalized_carveout1_bom;
u32 mc_generalized_carveout1_bom_hi;
u32 mc_generalized_carveout1_size_128kb;
u32 mc_generalized_carveout1_access0;
u32 mc_generalized_carveout1_access1;
u32 mc_generalized_carveout1_access2;
u32 mc_generalized_carveout1_access3;
u32 mc_generalized_carveout1_access4;
u32 mc_generalized_carveout1_force_internal_access0;
u32 mc_generalized_carveout1_force_internal_access1;
u32 mc_generalized_carveout1_force_internal_access2;
u32 mc_generalized_carveout1_force_internal_access3;
u32 mc_generalized_carveout1_force_internal_access4;
u32 mc_generalized_carveout1_cfg0;
u32 mc_generalized_carveout2_bom;
u32 mc_generalized_carveout2_bom_hi;
u32 mc_generalized_carveout2_size_128kb;
u32 mc_generalized_carveout2_access0;
u32 mc_generalized_carveout2_access1;
u32 mc_generalized_carveout2_access2;
u32 mc_generalized_carveout2_access3;
u32 mc_generalized_carveout2_access4;
u32 mc_generalized_carveout2_force_internal_access0;
u32 mc_generalized_carveout2_force_internal_access1;
u32 mc_generalized_carveout2_force_internal_access2;
u32 mc_generalized_carveout2_force_internal_access3;
u32 mc_generalized_carveout2_force_internal_access4;
u32 mc_generalized_carveout2_cfg0;
u32 mc_generalized_carveout3_bom;
u32 mc_generalized_carveout3_bom_hi;
u32 mc_generalized_carveout3_size_128kb;
u32 mc_generalized_carveout3_access0;
u32 mc_generalized_carveout3_access1;
u32 mc_generalized_carveout3_access2;
u32 mc_generalized_carveout3_access3;
u32 mc_generalized_carveout3_access4;
u32 mc_generalized_carveout3_force_internal_access0;
u32 mc_generalized_carveout3_force_internal_access1;
u32 mc_generalized_carveout3_force_internal_access2;
u32 mc_generalized_carveout3_force_internal_access3;
u32 mc_generalized_carveout3_force_internal_access4;
u32 mc_generalized_carveout3_cfg0;
u32 mc_generalized_carveout4_bom;
u32 mc_generalized_carveout4_bom_hi;
u32 mc_generalized_carveout4_size_128kb;
u32 mc_generalized_carveout4_access0;
u32 mc_generalized_carveout4_access1;
u32 mc_generalized_carveout4_access2;
u32 mc_generalized_carveout4_access3;
u32 mc_generalized_carveout4_access4;
u32 mc_generalized_carveout4_force_internal_access0;
u32 mc_generalized_carveout4_force_internal_access1;
u32 mc_generalized_carveout4_force_internal_access2;
u32 mc_generalized_carveout4_force_internal_access3;
u32 mc_generalized_carveout4_force_internal_access4;
u32 mc_generalized_carveout4_cfg0;
u32 mc_generalized_carveout5_bom;
u32 mc_generalized_carveout5_bom_hi;
u32 mc_generalized_carveout5_size_128kb;
u32 mc_generalized_carveout5_access0;
u32 mc_generalized_carveout5_access1;
u32 mc_generalized_carveout5_access2;
u32 mc_generalized_carveout5_access3;
u32 mc_generalized_carveout5_access4;
u32 mc_generalized_carveout5_force_internal_access0;
u32 mc_generalized_carveout5_force_internal_access1;
u32 mc_generalized_carveout5_force_internal_access2;
u32 mc_generalized_carveout5_force_internal_access3;
u32 mc_generalized_carveout5_force_internal_access4;
u32 mc_generalized_carveout5_cfg0;
/* Specifies enable for CA training */
u32 emc_ca_training_enable;
/* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */
u32 swizzle_rank_byte_encode;
/* Specifies enable and offset for patched boot rom write */
u32 boot_rom_patch_control;
/* Specifies data for patched boot rom write */
u32 boot_rom_patch_data;
/* Specifies the value for MC_MTS_CARVEOUT_BOM */
u32 mc_mts_carveout_bom;
/* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */
u32 mc_mts_carveout_adr_hi;
/* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */
u32 mc_mts_carveout_size_mb;
/* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */
u32 mc_mts_carveout_reg_ctrl;
} sdram_params_t210_t;
#endif

View File

@@ -0,0 +1,989 @@
/*
* Copyright (c) 2020 CTCaer
*
* 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.
*/
#ifndef _SDRAM_PARAM_T210B01_H_
#define _SDRAM_PARAM_T210B01_H_
typedef struct _sdram_params_t210b01_t
{
/* Specifies the type of memory device */
u32 memory_type;
/* MC/EMC clock source configuration */
/* Specifies the M value for PllM */
u32 pllm_input_divider;
/* Specifies the N value for PllM */
u32 pllm_feedback_divider;
/* Specifies the time to wait for PLLM to lock (in microseconds) */
u32 pllm_stable_time;
/* Specifies misc. control bits */
u32 pllm_setup_control;
/* Specifies the P value for PLLM */
u32 pllm_post_divider;
/* Specifies value for Charge Pump Gain Control */
u32 pllm_kcp;
/* Specifies VCO gain */
u32 pllm_kvco;
/* Spare BCT param */
u32 emc_bct_spare0;
/* Spare BCT param */
u32 emc_bct_spare1;
/* Spare BCT param */
u32 emc_bct_spare2;
/* Spare BCT param */
u32 emc_bct_spare3;
/* Spare BCT param */
u32 emc_bct_spare4;
/* Spare BCT param */
u32 emc_bct_spare5;
/* Spare BCT param */
u32 emc_bct_spare6;
/* Spare BCT param */
u32 emc_bct_spare7;
/* Spare BCT param */
u32 emc_bct_spare8;
/* Spare BCT param */
u32 emc_bct_spare9;
/* Spare BCT param */
u32 emc_bct_spare10;
/* Spare BCT param */
u32 emc_bct_spare11;
/* Spare BCT param */
u32 emc_bct_spare12;
/* Spare BCT param */
u32 emc_bct_spare13;
/* Spare BCT param */
u32 emc_bct_spare_secure0;
/* Spare BCT param */
u32 emc_bct_spare_secure1;
/* Spare BCT param */
u32 emc_bct_spare_secure2;
/* Spare BCT param */
u32 emc_bct_spare_secure3;
/* Spare BCT param */
u32 emc_bct_spare_secure4;
/* Spare BCT param */
u32 emc_bct_spare_secure5;
/* Spare BCT param */
u32 emc_bct_spare_secure6;
/* Spare BCT param */
u32 emc_bct_spare_secure7;
/* Spare BCT param */
u32 emc_bct_spare_secure8;
/* Spare BCT param */
u32 emc_bct_spare_secure9;
/* Spare BCT param */
u32 emc_bct_spare_secure10;
/* Spare BCT param */
u32 emc_bct_spare_secure11;
/* Spare BCT param */
u32 emc_bct_spare_secure12;
/* Spare BCT param */
u32 emc_bct_spare_secure13;
/* Spare BCT param */
u32 emc_bct_spare_secure14;
/* Spare BCT param */
u32 emc_bct_spare_secure15;
/* Spare BCT param */
u32 emc_bct_spare_secure16;
/* Spare BCT param */
u32 emc_bct_spare_secure17;
/* Spare BCT param */
u32 emc_bct_spare_secure18;
/* Spare BCT param */
u32 emc_bct_spare_secure19;
/* Spare BCT param */
u32 emc_bct_spare_secure20;
/* Spare BCT param */
u32 emc_bct_spare_secure21;
/* Spare BCT param */
u32 emc_bct_spare_secure22;
/* Spare BCT param */
u32 emc_bct_spare_secure23;
/* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */
u32 emc_clock_source;
u32 emc_clock_source_dll;
/* Defines possible override for PLLLM_MISC2 */
u32 clk_rst_pllm_misc20_override;
/* enables override for PLLLM_MISC2 */
u32 clk_rst_pllm_misc20_override_enable;
/* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */
u32 clear_clock2_mc1;
/* Auto-calibration of EMC pads */
/* Specifies the value for EMC_AUTO_CAL_INTERVAL */
u32 emc_auto_cal_interval;
/*
* Specifies the value for EMC_AUTO_CAL_CONFIG
* Note: Trigger bits are set by the SDRAM code.
*/
u32 emc_auto_cal_config;
/* Specifies the value for EMC_AUTO_CAL_CONFIG2 */
u32 emc_auto_cal_config2;
/* Specifies the value for EMC_AUTO_CAL_CONFIG3 */
u32 emc_auto_cal_config3;
u32 emc_auto_cal_config4;
u32 emc_auto_cal_config5;
u32 emc_auto_cal_config6;
u32 emc_auto_cal_config7;
u32 emc_auto_cal_config8;
u32 emc_auto_cal_config9;
/* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */
u32 emc_auto_cal_vref_sel0;
u32 emc_auto_cal_vref_sel1;
/* Specifies the value for EMC_AUTO_CAL_CHANNEL */
u32 emc_auto_cal_channel;
/* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */
u32 emc_pmacro_auto_cal_cfg0;
u32 emc_pmacro_auto_cal_cfg1;
u32 emc_pmacro_auto_cal_cfg2;
u32 emc_pmacro_rx_term;
u32 emc_pmacro_dq_tx_drive;
u32 emc_pmacro_ca_tx_drive;
u32 emc_pmacro_cmd_tx_drive;
u32 emc_pmacro_auto_cal_common;
u32 emc_pmacro_zcrtl;
/*
* Specifies the time for the calibration
* to stabilize (in microseconds)
*/
u32 emc_auto_cal_wait;
u32 emc_xm2_comp_pad_ctrl;
u32 emc_xm2_comp_pad_ctrl2;
u32 emc_xm2_comp_pad_ctrl3;
/*
* DRAM size information
* Specifies the value for EMC_ADR_CFG
*/
u32 emc_adr_cfg;
/*
* Specifies the time to wait after asserting pin
* CKE (in microseconds)
*/
u32 emc_pin_program_wait;
/* Specifies the extra delay before/after pin RESET/CKE command */
u32 emc_pin_extra_wait;
u32 emc_pin_gpio_enable;
u32 emc_pin_gpio;
/*
* Specifies the extra delay after the first writing
* of EMC_TIMING_CONTROL
*/
u32 emc_timing_control_wait;
/* Timing parameters required for the SDRAM */
/* Specifies the value for EMC_RC */
u32 emc_rc;
/* Specifies the value for EMC_RFC */
u32 emc_rfc;
u32 emc_rfc_pb;
u32 emc_ref_ctrl2;
/* Specifies the value for EMC_RFC_SLR */
u32 emc_rfc_slr;
/* Specifies the value for EMC_RAS */
u32 emc_ras;
/* Specifies the value for EMC_RP */
u32 emc_rp;
/* Specifies the value for EMC_R2R */
u32 emc_r2r;
/* Specifies the value for EMC_W2W */
u32 emc_w2w;
/* Specifies the value for EMC_R2W */
u32 emc_r2w;
/* Specifies the value for EMC_W2R */
u32 emc_w2r;
/* Specifies the value for EMC_R2P */
u32 emc_r2p;
/* Specifies the value for EMC_W2P */
u32 emc_w2p;
/* Specifies the value for EMC_RD_RCD */
u32 emc_tppd;
u32 emc_trtm;
u32 emc_twtm;
u32 emc_tratm;
u32 emc_twatm;
u32 emc_tr2ref;
u32 emc_ccdmw;
u32 emc_rd_rcd;
/* Specifies the value for EMC_WR_RCD */
u32 emc_wr_rcd;
/* Specifies the value for EMC_RRD */
u32 emc_rrd;
/* Specifies the value for EMC_REXT */
u32 emc_rext;
/* Specifies the value for EMC_WEXT */
u32 emc_wext;
/* Specifies the value for EMC_WDV */
u32 emc_wdv;
u32 emc_wdv_chk;
u32 emc_wsv;
u32 emc_wev;
/* Specifies the value for EMC_WDV_MASK */
u32 emc_wdv_mask;
u32 emc_ws_duration;
u32 emc_we_duration;
/* Specifies the value for EMC_QUSE */
u32 emc_quse;
/* Specifies the value for EMC_QUSE_WIDTH */
u32 emc_quse_width;
/* Specifies the value for EMC_IBDLY */
u32 emc_ibdly;
u32 emc_obdly;
/* Specifies the value for EMC_EINPUT */
u32 emc_einput;
/* Specifies the value for EMC_EINPUT_DURATION */
u32 emc_einput_duration;
/* Specifies the value for EMC_PUTERM_EXTRA */
u32 emc_puterm_extra;
/* Specifies the value for EMC_PUTERM_WIDTH */
u32 emc_puterm_width;
u32 emc_qrst;
u32 emc_qsafe;
u32 emc_rdv;
u32 emc_rdv_mask;
u32 emc_rdv_early;
u32 emc_rdv_early_mask;
/* Specifies the value for EMC_QPOP */
u32 emc_qpop;
/* Specifies the value for EMC_REFRESH */
u32 emc_refresh;
/* Specifies the value for EMC_BURST_REFRESH_NUM */
u32 emc_burst_refresh_num;
/* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */
u32 emc_prerefresh_req_cnt;
/* Specifies the value for EMC_PDEX2WR */
u32 emc_pdex2wr;
/* Specifies the value for EMC_PDEX2RD */
u32 emc_pdex2rd;
/* Specifies the value for EMC_PCHG2PDEN */
u32 emc_pchg2pden;
/* Specifies the value for EMC_ACT2PDEN */
u32 emc_act2pden;
/* Specifies the value for EMC_AR2PDEN */
u32 emc_ar2pden;
/* Specifies the value for EMC_RW2PDEN */
u32 emc_rw2pden;
u32 emc_cke2pden;
u32 emc_pdex2che;
u32 emc_pdex2mrr;
/* Specifies the value for EMC_TXSR */
u32 emc_txsr;
/* Specifies the value for EMC_TXSRDLL */
u32 emc_txsr_dll;
/* Specifies the value for EMC_TCKE */
u32 emc_tcke;
/* Specifies the value for EMC_TCKESR */
u32 emc_tckesr;
/* Specifies the value for EMC_TPD */
u32 emc_tpd;
/* Specifies the value for EMC_TFAW */
u32 emc_tfaw;
/* Specifies the value for EMC_TRPAB */
u32 emc_trpab;
/* Specifies the value for EMC_TCLKSTABLE */
u32 emc_tclkstable;
/* Specifies the value for EMC_TCLKSTOP */
u32 emc_tclkstop;
/* Specifies the value for EMC_TREFBW */
u32 emc_trefbw;
/* FBIO configuration values */
/* Specifies the value for EMC_FBIO_CFG5 */
u32 emc_fbio_cfg5;
/* Specifies the value for EMC_FBIO_CFG7 */
u32 emc_fbio_cfg7;
u32 emc_fbio_cfg8;
/* Command mapping for CMD brick 0 */
u32 emc_cmd_mapping_cmd0_0;
u32 emc_cmd_mapping_cmd0_1;
u32 emc_cmd_mapping_cmd0_2;
u32 emc_cmd_mapping_cmd1_0;
u32 emc_cmd_mapping_cmd1_1;
u32 emc_cmd_mapping_cmd1_2;
u32 emc_cmd_mapping_cmd2_0;
u32 emc_cmd_mapping_cmd2_1;
u32 emc_cmd_mapping_cmd2_2;
u32 emc_cmd_mapping_cmd3_0;
u32 emc_cmd_mapping_cmd3_1;
u32 emc_cmd_mapping_cmd3_2;
u32 emc_cmd_mapping_byte;
/* Specifies the value for EMC_FBIO_SPARE */
u32 emc_fbio_spare;
/* Specifies the value for EMC_CFG_RSV */
u32 emc_cfg_rsv;
/* MRS command values */
/* Specifies the value for EMC_MRS */
u32 emc_mrs;
/* Specifies the MP0 command to initialize mode registers */
u32 emc_emrs;
/* Specifies the MP2 command to initialize mode registers */
u32 emc_emrs2;
/* Specifies the MP3 command to initialize mode registers */
u32 emc_emrs3;
/* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */
u32 emc_mrw1;
/* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */
u32 emc_mrw2;
/* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */
u32 emc_mrw3;
/* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */
u32 emc_mrw4;
/* Specifies the programming to LPDDR4 Mode Register 3 at cold boot */
u32 emc_mrw6;
/* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */
u32 emc_mrw8;
/* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */
u32 emc_mrw9;
/* Specifies the programming to LPDDR4 Mode Register 12 at cold boot */
u32 emc_mrw10;
/* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */
u32 emc_mrw12;
/* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */
u32 emc_mrw13;
/* Specifies the programming to LPDDR4 Mode Register 22 at cold boot */
u32 emc_mrw14;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at cold boot
*/
u32 emc_mrw_extra;
/*
* Specifies the programming to extra LPDDR2 Mode Register
* at warm boot
*/
u32 emc_warm_boot_mrw_extra;
/*
* Specify the enable of extra Mode Register programming at
* warm boot
*/
u32 emc_warm_boot_extramode_reg_write_enable;
/*
* Specify the enable of extra Mode Register programming at
* cold boot
*/
u32 emc_extramode_reg_write_enable;
/* Specifies the EMC_MRW reset command value */
u32 emc_mrw_reset_command;
/* Specifies the EMC Reset wait time (in microseconds) */
u32 emc_mrw_reset_ninit_wait;
/* Specifies the value for EMC_MRS_WAIT_CNT */
u32 emc_mrs_wait_cnt;
/* Specifies the value for EMC_MRS_WAIT_CNT2 */
u32 emc_mrs_wait_cnt2;
/* EMC miscellaneous configurations */
/* Specifies the value for EMC_CFG */
u32 emc_cfg;
/* Specifies the value for EMC_CFG_2 */
u32 emc_cfg2;
/* Specifies the pipe bypass controls */
u32 emc_cfg_pipe;
u32 emc_cfg_pipe_clk;
u32 emc_fdpd_ctrl_cmd_no_ramp;
u32 emc_cfg_update;
/* Specifies the value for EMC_DBG */
u32 emc_dbg;
u32 emc_dbg_write_mux;
/* Specifies the value for EMC_CMDQ */
u32 emc_cmd_q;
/* Specifies the value for EMC_MC2EMCQ */
u32 emc_mc2emc_q;
/* Specifies the value for EMC_DYN_SELF_REF_CONTROL */
u32 emc_dyn_self_ref_control;
/* Specifies the value for MEM_INIT_DONE */
u32 ahb_arbitration_xbar_ctrl_meminit_done;
/* Specifies the value for EMC_CFG_DIG_DLL */
u32 emc_cfg_dig_dll;
u32 emc_cfg_dig_dll_1;
/* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */
u32 emc_cfg_dig_dll_period;
/* Specifies the value of *DEV_SELECTN of various EMC registers */
u32 emc_dev_select;
/* Specifies the value for EMC_SEL_DPD_CTRL */
u32 emc_sel_dpd_ctrl;
/* Pads trimmer delays */
u32 emc_fdpd_ctrl_dq;
u32 emc_fdpd_ctrl_cmd;
u32 emc_pmacro_ib_vref_dq_0;
u32 emc_pmacro_ib_vref_dq_1;
u32 emc_pmacro_ib_vref_dqs_0;
u32 emc_pmacro_ib_vref_dqs_1;
u32 emc_pmacro_ib_rxrt;
u32 emc_cfg_pipe1;
u32 emc_cfg_pipe2;
/* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */
u32 emc_pmacro_quse_ddll_rank0_0;
u32 emc_pmacro_quse_ddll_rank0_1;
u32 emc_pmacro_quse_ddll_rank0_2;
u32 emc_pmacro_quse_ddll_rank0_3;
u32 emc_pmacro_quse_ddll_rank0_4;
u32 emc_pmacro_quse_ddll_rank0_5;
u32 emc_pmacro_quse_ddll_rank1_0;
u32 emc_pmacro_quse_ddll_rank1_1;
u32 emc_pmacro_quse_ddll_rank1_2;
u32 emc_pmacro_quse_ddll_rank1_3;
u32 emc_pmacro_quse_ddll_rank1_4;
u32 emc_pmacro_quse_ddll_rank1_5;
u32 emc_pmacro_ob_ddll_long_dq_rank0_0;
u32 emc_pmacro_ob_ddll_long_dq_rank0_1;
u32 emc_pmacro_ob_ddll_long_dq_rank0_2;
u32 emc_pmacro_ob_ddll_long_dq_rank0_3;
u32 emc_pmacro_ob_ddll_long_dq_rank0_4;
u32 emc_pmacro_ob_ddll_long_dq_rank0_5;
u32 emc_pmacro_ob_ddll_long_dq_rank1_0;
u32 emc_pmacro_ob_ddll_long_dq_rank1_1;
u32 emc_pmacro_ob_ddll_long_dq_rank1_2;
u32 emc_pmacro_ob_ddll_long_dq_rank1_3;
u32 emc_pmacro_ob_ddll_long_dq_rank1_4;
u32 emc_pmacro_ob_ddll_long_dq_rank1_5;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_0;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_1;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_2;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_3;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_4;
u32 emc_pmacro_ob_ddll_long_dqs_rank0_5;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_0;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_1;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_2;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_3;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_4;
u32 emc_pmacro_ob_ddll_long_dqs_rank1_5;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_0;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_1;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_2;
u32 emc_pmacro_ib_ddll_long_dqs_rank0_3;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_0;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_1;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_2;
u32 emc_pmacro_ib_ddll_long_dqs_rank1_3;
u32 emc_pmacro_ddll_long_cmd_0;
u32 emc_pmacro_ddll_long_cmd_1;
u32 emc_pmacro_ddll_long_cmd_2;
u32 emc_pmacro_ddll_long_cmd_3;
u32 emc_pmacro_ddll_long_cmd_4;
u32 emc_pmacro_ddll_short_cmd_0;
u32 emc_pmacro_ddll_short_cmd_1;
u32 emc_pmacro_ddll_short_cmd_2;
u32 emc_pmacro_ddll_periodic_offset;
/*
* Specifies the delay after asserting CKE pin during a WarmBoot0
* sequence (in microseconds)
*/
u32 warm_boot_wait;
/* Specifies the value for EMC_ODT_WRITE */
u32 emc_odt_write;
/* Periodic ZQ calibration */
/*
* Specifies the value for EMC_ZCAL_INTERVAL
* Value 0 disables ZQ calibration
*/
u32 emc_zcal_interval;
/* Specifies the value for EMC_ZCAL_WAIT_CNT */
u32 emc_zcal_wait_cnt;
/* Specifies the value for EMC_ZCAL_MRW_CMD */
u32 emc_zcal_mrw_cmd;
/* DRAM initialization sequence flow control */
/* Specifies the MRS command value for resetting DLL */
u32 emc_mrs_reset_dll;
/* Specifies the command for ZQ initialization of device 0 */
u32 emc_zcal_init_dev0;
/* Specifies the command for ZQ initialization of device 1 */
u32 emc_zcal_init_dev1;
/*
* Specifies the wait time after programming a ZQ initialization
* command (in microseconds)
*/
u32 emc_zcal_init_wait;
/*
* Specifies the enable for ZQ calibration at cold boot [bit 0]
* and warm boot [bit 1]
*/
u32 emc_zcal_warm_cold_boot_enables;
/*
* Specifies the MRW command to LPDDR2 for ZQ calibration
* on warmboot
*/
/* Is issued to both devices separately */
u32 emc_mrw_lpddr2zcal_warm_boot;
/*
* Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
* Is issued to both devices separately
*/
u32 emc_zqcal_ddr3_warm_boot;
u32 emc_zqcal_lpddr4_warm_boot;
/*
* Specifies the wait time for ZQ calibration on warmboot
* (in microseconds)
*/
u32 emc_zcal_warm_boot_wait;
/*
* Specifies the enable for DRAM Mode Register programming
* at warm boot
*/
u32 emc_mrs_warm_boot_enable;
/*
* Specifies the wait time after sending an MRS DLL reset command
* in microseconds)
*/
u32 emc_mrs_reset_dll_wait;
/* Specifies the extra MRS command to initialize mode registers */
u32 emc_mrs_extra;
/* Specifies the extra MRS command at warm boot */
u32 emc_warm_boot_mrs_extra;
/* Specifies the EMRS command to enable the DDR2 DLL */
u32 emc_emrs_ddr2_dll_enable;
/* Specifies the MRS command to reset the DDR2 DLL */
u32 emc_mrs_ddr2_dll_reset;
/* Specifies the EMRS command to set OCD calibration */
u32 emc_emrs_ddr2_ocd_calib;
/*
* Specifies the wait between initializing DDR and setting OCD
* calibration (in microseconds)
*/
u32 emc_ddr2_wait;
/* Specifies the value for EMC_CLKEN_OVERRIDE */
u32 emc_clken_override;
/*
* Specifies LOG2 of the extra refresh numbers after booting
* Program 0 to disable
*/
u32 emc_extra_refresh_num;
/* Specifies the master override for all EMC clocks */
u32 emc_clken_override_allwarm_boot;
/* Specifies the master override for all MC clocks */
u32 mc_clken_override_allwarm_boot;
/* Specifies digital dll period, choosing between 4 to 64 ms */
u32 emc_cfg_dig_dll_period_warm_boot;
/* Pad controls */
/* Specifies the value for PMC_VDDP_SEL */
u32 pmc_vddp_sel;
/* Specifies the wait time after programming PMC_VDDP_SEL */
u32 pmc_vddp_sel_wait;
/* Specifies the value for PMC_DDR_CFG */
u32 pmc_ddr_cfg;
/* Specifies the value for PMC_IO_DPD3_REQ */
u32 pmc_io_dpd3_req;
/* Specifies the wait time after programming PMC_IO_DPD3_REQ */
u32 pmc_io_dpd3_req_wait;
u32 pmc_io_dpd4_req_wait;
/* Specifies the value for PMC_REG_SHORT */
u32 pmc_reg_short;
/* Specifies the value for PMC_NO_IOPOWER */
u32 pmc_no_io_power;
u32 pmc_ddr_ctrl_wait;
u32 pmc_ddr_ctrl;
/* Specifies the value for EMC_ACPD_CONTROL */
u32 emc_acpd_control;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */
u32 emc_swizzle_rank0_byte0;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */
u32 emc_swizzle_rank0_byte1;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */
u32 emc_swizzle_rank0_byte2;
/* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */
u32 emc_swizzle_rank0_byte3;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */
u32 emc_swizzle_rank1_byte0;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */
u32 emc_swizzle_rank1_byte1;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */
u32 emc_swizzle_rank1_byte2;
/* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */
u32 emc_swizzle_rank1_byte3;
/* Specifies the value for EMC_TXDSRVTTGEN */
u32 emc_txdsrvttgen;
/* Specifies the value for EMC_DATA_BRLSHFT_0 */
u32 emc_data_brlshft0;
u32 emc_data_brlshft1;
u32 emc_dqs_brlshft0;
u32 emc_dqs_brlshft1;
u32 emc_cmd_brlshft0;
u32 emc_cmd_brlshft1;
u32 emc_cmd_brlshft2;
u32 emc_cmd_brlshft3;
u32 emc_quse_brlshft0;
u32 emc_quse_brlshft1;
u32 emc_quse_brlshft2;
u32 emc_quse_brlshft3;
u32 emc_dll_cfg0;
u32 emc_dll_cfg1;
u32 emc_pmc_scratch1;
u32 emc_pmc_scratch2;
u32 emc_pmc_scratch3;
u32 emc_pmacro_pad_cfg_ctrl;
u32 emc_pmacro_vttgen_ctrl0;
u32 emc_pmacro_vttgen_ctrl1;
u32 emc_pmacro_vttgen_ctrl2;
u32 emc_pmacro_dsr_vttgen_ctrl0;
u32 emc_pmacro_brick_ctrl_rfu1;
u32 emc_pmacro_cmd_brick_ctrl_fdpd;
u32 emc_pmacro_brick_ctrl_rfu2;
u32 emc_pmacro_data_brick_ctrl_fdpd;
u32 emc_pmacro_bg_bias_ctrl0;
u32 emc_pmacro_data_pad_rx_ctrl;
u32 emc_pmacro_cmd_pad_rx_ctrl;
u32 emc_pmacro_data_rx_term_mode;
u32 emc_pmacro_cmd_rx_term_mode;
u32 emc_pmacro_data_pad_tx_ctrl;
u32 emc_pmacro_cmd_pad_tx_ctrl;
u32 emc_cfg3;
u32 emc_pmacro_tx_pwrd0;
u32 emc_pmacro_tx_pwrd1;
u32 emc_pmacro_tx_pwrd2;
u32 emc_pmacro_tx_pwrd3;
u32 emc_pmacro_tx_pwrd4;
u32 emc_pmacro_tx_pwrd5;
u32 emc_config_sample_delay;
u32 emc_pmacro_brick_mapping0;
u32 emc_pmacro_brick_mapping1;
u32 emc_pmacro_brick_mapping2;
u32 emc_pmacro_tx_sel_clk_src0;
u32 emc_pmacro_tx_sel_clk_src1;
u32 emc_pmacro_tx_sel_clk_src2;
u32 emc_pmacro_tx_sel_clk_src3;
u32 emc_pmacro_tx_sel_clk_src4;
u32 emc_pmacro_tx_sel_clk_src5;
u32 emc_pmacro_perbit_fgcg_ctrl0;
u32 emc_pmacro_perbit_fgcg_ctrl1;
u32 emc_pmacro_perbit_fgcg_ctrl2;
u32 emc_pmacro_perbit_fgcg_ctrl3;
u32 emc_pmacro_perbit_fgcg_ctrl4;
u32 emc_pmacro_perbit_fgcg_ctrl5;
u32 emc_pmacro_perbit_rfu_ctrl0;
u32 emc_pmacro_perbit_rfu_ctrl1;
u32 emc_pmacro_perbit_rfu_ctrl2;
u32 emc_pmacro_perbit_rfu_ctrl3;
u32 emc_pmacro_perbit_rfu_ctrl4;
u32 emc_pmacro_perbit_rfu_ctrl5;
u32 emc_pmacro_perbit_rfu1_ctrl0;
u32 emc_pmacro_perbit_rfu1_ctrl1;
u32 emc_pmacro_perbit_rfu1_ctrl2;
u32 emc_pmacro_perbit_rfu1_ctrl3;
u32 emc_pmacro_perbit_rfu1_ctrl4;
u32 emc_pmacro_perbit_rfu1_ctrl5;
u32 emc_pmacro_data_pi_ctrl;
u32 emc_pmacro_cmd_pi_ctrl;
u32 emc_pmacro_ddll_bypass;
u32 emc_pmacro_ddll_pwrd0;
u32 emc_pmacro_ddll_pwrd1;
u32 emc_pmacro_ddll_pwrd2;
u32 emc_pmacro_cmd_ctrl0;
u32 emc_pmacro_cmd_ctrl1;
u32 emc_pmacro_cmd_ctrl2;
/* DRAM size information */
/* Specifies the value for MC_EMEM_ADR_CFG */
u32 mc_emem_adr_cfg;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */
u32 mc_emem_adr_cfg_dev0;
/* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */
u32 mc_emem_adr_cfg_dev1;
u32 mc_emem_adr_cfg_channel_mask;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */
u32 mc_emem_adr_cfg_bank_mask0;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */
u32 mc_emem_adr_cfg_bank_mask1;
/* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */
u32 mc_emem_adr_cfg_bank_mask2;
/*
* Specifies the value for MC_EMEM_CFG which holds the external memory
* size (in KBytes)
*/
u32 mc_emem_cfg;
/* MC arbitration configuration */
/* Specifies the value for MC_EMEM_ARB_CFG */
u32 mc_emem_arb_cfg;
/* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */
u32 mc_emem_arb_outstanding_req;
u32 emc_emem_arb_refpb_hp_ctrl;
u32 emc_emem_arb_refpb_bank_ctrl;
/* Specifies the value for MC_EMEM_ARB_TIMING_RCD */
u32 mc_emem_arb_timing_rcd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RP */
u32 mc_emem_arb_timing_rp;
/* Specifies the value for MC_EMEM_ARB_TIMING_RC */
u32 mc_emem_arb_timing_rc;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAS */
u32 mc_emem_arb_timing_ras;
/* Specifies the value for MC_EMEM_ARB_TIMING_FAW */
u32 mc_emem_arb_timing_faw;
/* Specifies the value for MC_EMEM_ARB_TIMING_RRD */
u32 mc_emem_arb_timing_rrd;
/* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */
u32 mc_emem_arb_timing_rap2pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */
u32 mc_emem_arb_timing_wap2pre;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2R */
u32 mc_emem_arb_timing_r2r;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2W */
u32 mc_emem_arb_timing_w2w;
/* Specifies the value for MC_EMEM_ARB_TIMING_R2W */
u32 mc_emem_arb_timing_r2w;
/* Specifies the value for MC_EMEM_ARB_TIMING_W2R */
u32 mc_emem_arb_timing_w2r;
u32 mc_emem_arb_timing_rfcpb;
/* Specifies the value for MC_EMEM_ARB_DA_TURNS */
u32 mc_emem_arb_da_turns;
/* Specifies the value for MC_EMEM_ARB_DA_COVERS */
u32 mc_emem_arb_da_covers;
/* Specifies the value for MC_EMEM_ARB_MISC0 */
u32 mc_emem_arb_misc0;
/* Specifies the value for MC_EMEM_ARB_MISC1 */
u32 mc_emem_arb_misc1;
u32 mc_emem_arb_misc2;
/* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */
u32 mc_emem_arb_ring1_throttle;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE */
u32 mc_emem_arb_override;
/* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */
u32 mc_emem_arb_override1;
/* Specifies the value for MC_EMEM_ARB_RSV */
u32 mc_emem_arb_rsv;
u32 mc_da_cfg0;
u32 mc_emem_arb_timing_ccdmw;
/* Specifies the value for MC_CLKEN_OVERRIDE */
u32 mc_clken_override;
/* Specifies the value for MC_STAT_CONTROL */
u32 mc_stat_control;
/* Specifies the value for MC_VIDEO_PROTECT_BOM */
u32 mc_video_protect_bom;
/* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */
u32 mc_video_protect_bom_adr_hi;
/* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */
u32 mc_video_protect_size_mb;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */
u32 mc_video_protect_vpr_override;
/* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */
u32 mc_video_protect_vpr_override1;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */
u32 mc_video_protect_gpu_override0;
/* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */
u32 mc_video_protect_gpu_override1;
/* Specifies the value for MC_SEC_CARVEOUT_BOM */
u32 mc_sec_carveout_bom;
/* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */
u32 mc_sec_carveout_adr_hi;
/* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */
u32 mc_sec_carveout_size_mb;
/* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */
u32 mc_video_protect_write_access;
/* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */
u32 mc_sec_carveout_protect_write_access;
u32 mc_generalized_carveout1_bom;
u32 mc_generalized_carveout1_bom_hi;
u32 mc_generalized_carveout1_size_128kb;
u32 mc_generalized_carveout1_access0;
u32 mc_generalized_carveout1_access1;
u32 mc_generalized_carveout1_access2;
u32 mc_generalized_carveout1_access3;
u32 mc_generalized_carveout1_access4;
u32 mc_generalized_carveout1_force_internal_access0;
u32 mc_generalized_carveout1_force_internal_access1;
u32 mc_generalized_carveout1_force_internal_access2;
u32 mc_generalized_carveout1_force_internal_access3;
u32 mc_generalized_carveout1_force_internal_access4;
u32 mc_generalized_carveout1_cfg0;
u32 mc_generalized_carveout2_bom;
u32 mc_generalized_carveout2_bom_hi;
u32 mc_generalized_carveout2_size_128kb;
u32 mc_generalized_carveout2_access0;
u32 mc_generalized_carveout2_access1;
u32 mc_generalized_carveout2_access2;
u32 mc_generalized_carveout2_access3;
u32 mc_generalized_carveout2_access4;
u32 mc_generalized_carveout2_force_internal_access0;
u32 mc_generalized_carveout2_force_internal_access1;
u32 mc_generalized_carveout2_force_internal_access2;
u32 mc_generalized_carveout2_force_internal_access3;
u32 mc_generalized_carveout2_force_internal_access4;
u32 mc_generalized_carveout2_cfg0;
u32 mc_generalized_carveout3_bom;
u32 mc_generalized_carveout3_bom_hi;
u32 mc_generalized_carveout3_size_128kb;
u32 mc_generalized_carveout3_access0;
u32 mc_generalized_carveout3_access1;
u32 mc_generalized_carveout3_access2;
u32 mc_generalized_carveout3_access3;
u32 mc_generalized_carveout3_access4;
u32 mc_generalized_carveout3_force_internal_access0;
u32 mc_generalized_carveout3_force_internal_access1;
u32 mc_generalized_carveout3_force_internal_access2;
u32 mc_generalized_carveout3_force_internal_access3;
u32 mc_generalized_carveout3_force_internal_access4;
u32 mc_generalized_carveout3_cfg0;
u32 mc_generalized_carveout4_bom;
u32 mc_generalized_carveout4_bom_hi;
u32 mc_generalized_carveout4_size_128kb;
u32 mc_generalized_carveout4_access0;
u32 mc_generalized_carveout4_access1;
u32 mc_generalized_carveout4_access2;
u32 mc_generalized_carveout4_access3;
u32 mc_generalized_carveout4_access4;
u32 mc_generalized_carveout4_force_internal_access0;
u32 mc_generalized_carveout4_force_internal_access1;
u32 mc_generalized_carveout4_force_internal_access2;
u32 mc_generalized_carveout4_force_internal_access3;
u32 mc_generalized_carveout4_force_internal_access4;
u32 mc_generalized_carveout4_cfg0;
u32 mc_generalized_carveout5_bom;
u32 mc_generalized_carveout5_bom_hi;
u32 mc_generalized_carveout5_size_128kb;
u32 mc_generalized_carveout5_access0;
u32 mc_generalized_carveout5_access1;
u32 mc_generalized_carveout5_access2;
u32 mc_generalized_carveout5_access3;
u32 mc_generalized_carveout5_access4;
u32 mc_generalized_carveout5_force_internal_access0;
u32 mc_generalized_carveout5_force_internal_access1;
u32 mc_generalized_carveout5_force_internal_access2;
u32 mc_generalized_carveout5_force_internal_access3;
u32 mc_generalized_carveout5_force_internal_access4;
u32 mc_generalized_carveout5_cfg0;
/* Specifies enable for CA training */
u32 emc_ca_training_enable;
/* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */
u32 swizzle_rank_byte_encode;
/* Specifies enable and offset for patched boot rom write */
u32 boot_rom_patch_control;
/* Specifies data for patched boot rom write */
u32 boot_rom_patch_data;
/* Specifies the value for MC_MTS_CARVEOUT_BOM */
u32 mc_mts_carveout_bom;
/* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */
u32 mc_mts_carveout_adr_hi;
/* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */
u32 mc_mts_carveout_size_mb;
/* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */
u32 mc_mts_carveout_reg_ctrl;
/* Specifies the clients that are allowed to access untranslated memory */
u32 mc_untranslated_region_check;
/* Just a place holder for special usage when there is no BCT for certain registers */
u32 bct_na;
} sdram_params_t210b01_t;
#endif

171
bdk/mem/smmu.c Normal file
View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <soc/ccplex.h>
#include <soc/t210.h>
#include <mem/mc_t210.h>
#include <mem/smmu.h>
#include <utils/util.h>
#include <utils/aarch64_util.h>
bool smmu_used = false;
u8 *_pageheap = (u8 *)SMMU_HEAP_ADDR;
//Enabling SMMU requires a TZ secure write: MC(MC_SMMU_CONFIG) = 1;
u8 smmu_payload[] __attribute__((aligned(16))) = {
0x41, 0x01, 0x00, 0x58, // 0x00: LDR X1, =0x70019010
0x20, 0x00, 0x80, 0xD2, // 0x04: MOV X0, #0x1
0x20, 0x00, 0x00, 0xB9, // 0x08: STR W0, [X1]
0x1F, 0x71, 0x08, 0xD5, // 0x0C: IC IALLUIS
0x9F, 0x3B, 0x03, 0xD5, // 0x10: DSB ISH
0xFE, 0xFF, 0xFF, 0x17, // 0x14: B loop
0x00, 0x00, 0x80, 0xD2, // 0x18: MOV X0, #0x0
0x20, 0x00, 0x00, 0xB9, // 0x1C: STR W0, [X1]
0x80, 0x00, 0x00, 0x58, // 0x20: LDR X0, =0x4002B000
0x00, 0x00, 0x1F, 0xD6, // 0x28: BR X0
0x10, 0x90, 0x01, 0x70, // 0x28: MC_SMMU_CONFIG
0x00, 0x00, 0x00, 0x00, // 0x2C:
0x00, 0x00, 0x00, 0x00, // 0x30: secmon address
0x00, 0x00, 0x00, 0x00 // 0x34:
};
void *page_alloc(u32 num)
{
u8 *res = _pageheap;
_pageheap += SZ_PAGE * num;
memset(res, 0, SZ_PAGE * num);
return res;
}
u32 *smmu_alloc_pdir()
{
u32 *pdir = (u32 *)page_alloc(1);
for (int pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++)
pdir[pdn] = _PDE_VACANT(pdn);
return pdir;
}
void smmu_flush_regs()
{
(void)MC(MC_SMMU_PTB_DATA);
}
void smmu_flush_all()
{
MC(MC_SMMU_PTC_FLUSH) = 0;
smmu_flush_regs();
MC(MC_SMMU_TLB_FLUSH) = 0;
smmu_flush_regs();
}
void smmu_init(u32 secmon_base)
{
MC(MC_SMMU_PTB_ASID) = 0;
MC(MC_SMMU_PTB_DATA) = 0;
MC(MC_SMMU_TLB_CONFIG) = 0x30000030;
MC(MC_SMMU_PTC_CONFIG) = 0x28000F3F;
MC(MC_SMMU_PTC_FLUSH) = 0;
MC(MC_SMMU_TLB_FLUSH) = 0;
// Set the secmon address
*(u32 *)(smmu_payload + 0x30) = secmon_base;
}
void smmu_enable()
{
if (smmu_used)
return;
ccplex_boot_cpu0((u32)smmu_payload);
smmu_used = true;
msleep(150);
smmu_flush_all();
}
bool smmu_is_used()
{
return smmu_used;
}
void smmu_exit()
{
*(u32 *)(smmu_payload + 0x14) = _NOP();
}
u32 *smmu_init_domain4(u32 dev_base, u32 asid)
{
u32 *pdir = smmu_alloc_pdir();
MC(MC_SMMU_PTB_ASID) = asid;
MC(MC_SMMU_PTB_DATA) = SMMU_MK_PDIR((u32)pdir, _PDIR_ATTR);
smmu_flush_regs();
MC(dev_base) = 0x80000000 | (asid << 24) | (asid << 16) | (asid << 8) | (asid);
smmu_flush_regs();
return pdir;
}
u32 *smmu_get_pte(u32 *pdir, u32 iova)
{
u32 ptn = SMMU_ADDR_TO_PFN(iova);
u32 pdn = SMMU_ADDR_TO_PDN(iova);
u32 *ptbl;
if (pdir[pdn] != _PDE_VACANT(pdn))
ptbl = (u32 *)((pdir[pdn] & SMMU_PFN_MASK) << SMMU_PDIR_SHIFT);
else
{
ptbl = (u32 *)page_alloc(1);
u32 addr = SMMU_PDN_TO_ADDR(pdn);
for (int pn = 0; pn < SMMU_PTBL_COUNT; pn++, addr += SMMU_PAGE_SIZE)
ptbl[pn] = _PTE_VACANT(addr);
pdir[pdn] = SMMU_MK_PDE((u32)ptbl, _PDE_ATTR | _PDE_NEXT);
smmu_flush_all();
}
return &ptbl[ptn % SMMU_PTBL_COUNT];
}
void smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr)
{
for (int i = 0; i < cnt; i++)
{
u32 *pte = smmu_get_pte(pdir, addr);
*pte = SMMU_ADDR_TO_PFN(page) | attr;
addr += SZ_PAGE;
page += SZ_PAGE;
}
smmu_flush_all();
}
u32 *smmu_init_for_tsec()
{
return smmu_init_domain4(MC_SMMU_TSEC_ASID, 1);
}
void smmu_deinit_for_tsec()
{
MC(MC_SMMU_PTB_ASID) = 1;
MC(MC_SMMU_PTB_DATA) = 0;
MC(MC_SMMU_TSEC_ASID) = 0;
smmu_flush_regs();
}

82
bdk/mem/smmu.h Normal file
View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <utils/types.h>
#define SMMU_HEAP_ADDR 0xA0000000
#define MC_INTSTATUS 0x0
#define MC_INTMASK 0x4
#define MC_ERR_STATUS 0x8
#define MC_ERR_ADR 0xc
#define MC_SMMU_CONFIG 0x10
#define MC_SMMU_TLB_CONFIG 0x14
#define MC_SMMU_PTC_CONFIG 0x18
#define MC_SMMU_PTB_ASID 0x1c
#define MC_SMMU_PTB_DATA 0x20
#define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_TSEC_ASID 0x294
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
#define SMMU_PDE_NEXT_SHIFT 28
#define MC_SMMU_PTB_DATA_0_ASID_NONSECURE_SHIFT 29
#define MC_SMMU_PTB_DATA_0_ASID_WRITABLE_SHIFT 30
#define MC_SMMU_PTB_DATA_0_ASID_READABLE_SHIFT 31
#define SMMU_PAGE_SHIFT 12
#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT)
#define SMMU_PDIR_COUNT 1024
#define SMMU_PDIR_SIZE (sizeof(u32) * SMMU_PDIR_COUNT)
#define SMMU_PTBL_COUNT 1024
#define SMMU_PTBL_SIZE (sizeof(u32) * SMMU_PTBL_COUNT)
#define SMMU_PDIR_SHIFT 12
#define SMMU_PDE_SHIFT 12
#define SMMU_PTE_SHIFT 12
#define SMMU_PFN_MASK 0x000FFFFF
#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
#define _READABLE (1 << MC_SMMU_PTB_DATA_0_ASID_READABLE_SHIFT)
#define _WRITABLE (1 << MC_SMMU_PTB_DATA_0_ASID_WRITABLE_SHIFT)
#define _NONSECURE (1 << MC_SMMU_PTB_DATA_0_ASID_NONSECURE_SHIFT)
#define _PDE_NEXT (1 << SMMU_PDE_NEXT_SHIFT)
#define _MASK_ATTR (_READABLE | _WRITABLE | _NONSECURE)
#define _PDIR_ATTR (_READABLE | _WRITABLE | _NONSECURE)
#define _PDE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
#define _PDE_VACANT(pdn) (((pdn) << 10) | _PDE_ATTR)
#define _PTE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
#define _PTE_VACANT(addr) (((addr) >> SMMU_PAGE_SHIFT) | _PTE_ATTR)
#define SMMU_MK_PDIR(page, attr) (((page) >> SMMU_PDIR_SHIFT) | (attr))
#define SMMU_MK_PDE(page, attr) (((page) >> SMMU_PDE_SHIFT) | (attr))
void *page_alloc(u32 num);
u32 *smmu_alloc_pdir();
void smmu_flush_regs();
void smmu_flush_all();
void smmu_init(u32 secmon_base);
void smmu_enable();
bool smmu_is_used();
void smmu_exit();
u32 *smmu_init_domain4(u32 dev_base, u32 asid);
u32 *smmu_get_pte(u32 *pdir, u32 iova);
void smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr);
u32 *smmu_init_for_tsec();
void smmu_deinit_for_tsec();

122
bdk/memory_map.h Normal file
View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2019-2021 CTCaer
*
* 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 _MEMORY_MAP_H_
#define _MEMORY_MAP_H_
/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */
/* --- IPL: 0x40008000 - 0x40028000 --- */
#define LDR_LOAD_ADDR 0x40007000
#define IPL_LOAD_ADDR 0x40008000
#define IPL_SZ_MAX SZ_128K
#define XUSB_RING_ADDR 0x40020000 // XUSB EP context and TRB ring buffers.
#define SECMON_MIN_START 0x4002B000 // Minimum reserved address for secmon.
#define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init.
/* start.S / exception_handlers.S */
#define SYS_STACK_TOP_INIT 0x4003FF00
#define FIQ_STACK_TOP 0x40040000
#define IRQ_STACK_TOP 0x40040000
#define IPL_RELOC_ADDR 0x4003FF00
#define IPL_RELOC_SZ 0x10
#define EXCP_STORAGE_ADDR 0x4003FFF0
#define EXCP_STORAGE_SZ 0x10
/* --- DRAM START --- */
#define DRAM_START 0x80000000
#define HOS_RSVD SZ_16M // Do not write anything in this area.
#define NYX_LOAD_ADDR 0x81000000
#define NYX_SZ_MAX SZ_16M
/* --- Gap: 0x82000000 - 0x82FFFFFF --- */
/* Stack theoretical max: 33MB */
#define IPL_STACK_TOP 0x83100000
#define IPL_HEAP_START 0x84000000
#define IPL_HEAP_SZ SZ_512M
/* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */
// Virtual disk / Chainloader buffers.
#define RAM_DISK_ADDR 0xA4000000
#define RAM_DISK_SZ 0x41000000 // 1040MB.
#define RAM_DISK2_SZ 0x21000000 // 528MB.
// L4T Kernel Panic Storage (PSTORE).
#define PSTORE_ADDR 0xB0000000
#define PSTORE_SZ SZ_2M
//#define DRAM_LIB_ADDR 0xE0000000
/* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading.
// SDMMC DMA buffers 1
#define SDMMC_UPPER_BUFFER 0xE5000000
#define SDMMC_UP_BUF_SZ SZ_128M
// Nyx buffers.
#define NYX_STORAGE_ADDR 0xED000000
#define NYX_RES_ADDR 0xEE000000
#define NYX_RES_SZ SZ_16M
// SDMMC DMA buffers 2
#define SDXC_BUF_ALIGNED 0xEF000000
#define MIXD_BUF_ALIGNED 0xF0000000
#define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED
#define SDMMC_DMA_BUF_SZ SZ_16M // 4MB currently used.
// Nyx LvGL buffers.
#define NYX_LV_VDB_ADR 0xF1000000
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
#define NYX_LV_MEM_ADR 0xF1400000
#define NYX_LV_MEM_SZ 0x6600000 // 70MB.
// Framebuffer addresses.
#define IPL_FB_ADDRESS 0xF5A00000
#define IPL_FB_SZ 0x384000 // 720 x 1280 x 4.
#define LOG_FB_ADDRESS 0xF5E00000
#define LOG_FB_SZ 0x334000 // 1280 x 656 x 4.
#define NYX_FB_ADDRESS 0xF6200000
#define NYX_FB2_ADDRESS 0xF6600000
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
/* OBSOLETE: Very old hwinit based payloads were setting a carveout here. */
#define DRAM_MEM_HOLE_ADR 0xF6A00000
#define DRAM_MEM_HOLE_SZ 0x8140000
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
#define DRAM_START2 0xFEB40000
// USB buffers.
#define USBD_ADDR 0xFEF00000
#define USB_DESCRIPTOR_ADDR 0xFEF40000
#define USB_EP_CONTROL_BUF_ADDR 0xFEF80000
#define USB_EP_BULK_IN_BUF_ADDR 0xFF000000
#define USB_EP_BULK_OUT_BUF_ADDR 0xFF800000
#define USB_EP_BULK_OUT_MAX_XFER SZ_8M
// #define EXT_PAYLOAD_ADDR 0xC0000000
// #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
// #define COREBOOT_ADDR (0xD0000000 - rom_size)
// NX BIS driver sector cache.
#define NX_BIS_CACHE_ADDR 0xC5000000
#define NX_BIS_CACHE_SZ 0x10020000 // 256MB.
#define NX_BIS_LOOKUP_ADDR DRAM_MEM_HOLE_ADR
#define NX_BIS_LOOKUP_SZ DRAM_MEM_HOLE_SZ
#endif

46
bdk/module.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* Common Module Header
* Copyright (c) 2018 M4xw
*
* 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 _MODULE_H_
#define _MODULE_H_
#include <stddef.h>
#include <mem/heap.h>
#define IANOS_EXT0 0x304E4149
// Module Callback
typedef void (*cbMainModule_t)(const char *s);
typedef void (*memcpy_t)(void *, void *, size_t);
typedef void (*memset_t)(void *, int, size_t);
typedef int (*reg_voltage_set_t)(u32, u32);
typedef struct _bdkParams_t
{
void *gfxCon;
void *gfxCtx;
heap_t *sharedHeap;
memcpy_t memcpy;
memset_t memset;
u32 extension_magic;
reg_voltage_set_t reg_voltage_set;
} *bdkParams_t;
// Module Entrypoint
typedef void (*moduleEntrypoint_t)(void *, bdkParams_t);
#endif

99
bdk/power/bm92t36.c Normal file
View File

@@ -0,0 +1,99 @@
/*
* USB-PD driver for Nintendo Switch's TI BM92T36
*
* Copyright (c) 2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "bm92t36.h"
#include <soc/i2c.h>
#include <utils/util.h>
#define ALERT_STATUS_REG 0x2
#define STATUS1_REG 0x3
#define STATUS2_REG 0x4
#define COMMAND_REG 0x5
#define CONFIG1_REG 0x6
#define DEV_CAPS_REG 0x7
#define READ_PDOS_SRC_REG 0x8
#define CONFIG2_REG 0x17
#define DP_STATUS_REG 0x18
#define DP_ALERT_EN_REG 0x19
#define VENDOR_CONFIG_REG 0x1A
#define AUTO_NGT_FIXED_REG 0x20
#define AUTO_NGT_BATT_REG 0x23
#define SYS_CONFIG1_REG 0x26
#define SYS_CONFIG2_REG 0x27
#define CURRENT_PDO_REG 0x28
#define CURRENT_RDO_REG 0x2B
#define ALERT_ENABLE_REG 0x2E
#define SYS_CONFIG3_REG 0x2F
#define SET_RDO_REG 0x30
#define PDOS_SNK_REG 0x33
#define PDOS_SRC_PROV_REG 0x3C
#define FW_TYPE_REG 0x4B
#define FW_REVISION_REG 0x4C
#define MAN_ID_REG 0x4D
#define DEV_ID_REG 0x4E
#define REV_ID_REG 0x4F
#define INCOMING_VDM_REG 0x50
#define OUTGOING_VDM_REG 0x60
#define STATUS1_INSERT BIT(7) // Cable inserted.
typedef struct _pd_object_t {
unsigned int amp:10;
unsigned int volt:10;
unsigned int info:10;
unsigned int type:2;
} __attribute__((packed)) pd_object_t;
static int _bm92t36_read_reg(u8 *buf, u32 size, u32 reg)
{
return i2c_recv_buf_big(buf, size, I2C_1, BM92T36_I2C_ADDR, reg);
}
void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd)
{
u8 buf[32];
pd_object_t pdos[7];
if (inserted)
{
_bm92t36_read_reg(buf, 2, STATUS1_REG);
*inserted = buf[0] & STATUS1_INSERT ? true : false;
}
if (usb_pd)
{
_bm92t36_read_reg(buf, 29, READ_PDOS_SRC_REG);
memcpy(pdos, &buf[1], 28);
memset(usb_pd, 0, sizeof(usb_pd_objects_t));
usb_pd->pdo_no = buf[0] / sizeof(pd_object_t);
for (u32 i = 0; i < usb_pd->pdo_no; i++)
{
usb_pd->pdos[i].amperage = pdos[i].amp * 10;
usb_pd->pdos[i].voltage = (pdos[i].volt * 50) / 1000;
}
_bm92t36_read_reg(buf, 5, CURRENT_PDO_REG);
memcpy(pdos, &buf[1], 4);
usb_pd->selected_pdo.amperage = pdos[0].amp * 10;
usb_pd->selected_pdo.voltage = (pdos[0].volt * 50) / 1000;
}
}

41
bdk/power/bm92t36.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* USB-PD driver for Nintendo Switch's TI BM92T36
*
* Copyright (c) 2020 CTCaer
*
* 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 __BM92T36_H_
#define __BM92T36_H_
#include <utils/types.h>
#define BM92T36_I2C_ADDR 0x18
typedef struct _usb_pd_object_t
{
u32 amperage;
u32 voltage;
} usb_pd_object_t;
typedef struct _usb_pd_objects_t
{
u32 pdo_no;
usb_pd_object_t pdos[7];
usb_pd_object_t selected_pdo;
} usb_pd_objects_t;
void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd);
#endif

178
bdk/power/bq24193.c Normal file
View File

@@ -0,0 +1,178 @@
/*
* Battery charger driver for Nintendo Switch's TI BQ24193
*
* Copyright (c) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "bq24193.h"
#include <soc/i2c.h>
#include <utils/util.h>
static u8 bq24193_get_reg(u8 reg)
{
return i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, reg);
}
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
{
u8 data;
switch (prop) {
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
data = bq24193_get_reg(BQ24193_InputSource);
data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;
*value = 0;
*value += ((data >> 0) & 1) ? 80 : 0;
*value += ((data >> 1) & 1) ? 160 : 0;
*value += ((data >> 2) & 1) ? 320 : 0;
*value += ((data >> 3) & 1) ? 640 : 0;
*value += 3880;
break;
case BQ24193_InputCurrentLimit: // Input current limit (mA).
data = bq24193_get_reg(BQ24193_InputSource);
data &= BQ24193_INCONFIG_INLIMIT_MASK;
switch (data)
{
case 0:
*value = 100;
break;
case 1:
*value = 150;
break;
case 2:
*value = 500;
break;
case 3:
*value = 900;
break;
case 4:
*value = 1200;
break;
case 5:
*value = 1500;
break;
case 6:
*value = 2000;
break;
case 7:
*value = 3000;
break;
}
break;
case BQ24193_SystemMinimumVoltage: // Minimum system voltage limit (mV).
data = bq24193_get_reg(BQ24193_PORConfig);
*value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1;
*value *= 100;
*value += 3000;
break;
case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
data = bq24193_get_reg(BQ24193_ChrgCurr);
data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2;
*value = 0;
*value += ((data >> 0) & 1) ? 64 : 0;
*value += ((data >> 1) & 1) ? 128 : 0;
*value += ((data >> 2) & 1) ? 256 : 0;
*value += ((data >> 3) & 1) ? 512 : 0;
*value += ((data >> 4) & 1) ? 1024 : 0;
*value += ((data >> 5) & 1) ? 2048 : 0;
*value += 512;
data = bq24193_get_reg(BQ24193_ChrgCurr);
data &= BQ24193_CHRGCURR_20PCT_MASK;
if (data)
*value = *value * 20 / 100; // Fast charge current limit is 20%.
break;
case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV).
data = bq24193_get_reg(BQ24193_ChrgVolt);
data = (data & BQ24193_CHRGVOLT_VREG) >> 2;
*value = 0;
*value += ((data >> 0) & 1) ? 16 : 0;
*value += ((data >> 1) & 1) ? 32 : 0;
*value += ((data >> 2) & 1) ? 64 : 0;
*value += ((data >> 3) & 1) ? 128 : 0;
*value += ((data >> 4) & 1) ? 256 : 0;
*value += ((data >> 5) & 1) ? 512 : 0;
*value += 3504;
break;
case BQ24193_RechargeThreshold: // Recharge voltage threshold less than voltage limit (mV).
data = bq24193_get_reg(BQ24193_ChrgVolt);
data &= BQ24193_IRTHERMAL_THERM_MASK;
if (data)
*value = 300;
else
*value = 100;
break;
case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC).
data = bq24193_get_reg(BQ24193_IRCompThermal);
data &= BQ24193_IRTHERMAL_THERM_MASK;
switch (data)
{
case 0:
*value = 60;
break;
case 1:
*value = 80;
break;
case 2:
*value = 100;
break;
case 3:
*value = 120;
break;
}
break;
case BQ24193_ChargeStatus: // 0: Not charging, 1: Pre-charge, 2: Fast charging, 3: Charge termination done
data = bq24193_get_reg(BQ24193_Status);
*value = (data & BQ24193_STATUS_CHRG_MASK) >> 4;
break;
case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
data = bq24193_get_reg(BQ24193_FaultReg);
*value = data & BQ24193_FAULT_THERM_MASK;
break;
case BQ24193_DevID: // Dev ID.
data = bq24193_get_reg(BQ24193_VendorPart);
*value = data & BQ24193_VENDORPART_DEV_MASK;
break;
case BQ24193_ProductNumber: // Product number.
data = bq24193_get_reg(BQ24193_VendorPart);
*value = (data & BQ24193_VENDORPART_PN_MASK) >> 3;
break;
default:
return -1;
}
return 0;
}
void bq24193_enable_charger()
{
u8 reg = bq24193_get_reg(BQ24193_PORConfig);
reg &= ~BQ24193_PORCONFIG_CHGCONFIG_MASK;
reg |= BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN;
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_PORConfig, reg);
}
void bq24193_fake_battery_removal()
{
// Disable watchdog to keep BATFET disabled.
u8 value = bq24193_get_reg(BQ24193_ChrgTermTimer);
value &= ~BQ24193_CHRGTERM_WATCHDOG_MASK;
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_ChrgTermTimer, value);
// Force BATFET to disabled state. This disconnects the battery from the system.
value = bq24193_get_reg(BQ24193_Misc);
value |= BQ24193_MISC_BATFET_DI_MASK;
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value);
}

121
bdk/power/bq24193.h Normal file
View File

@@ -0,0 +1,121 @@
/*
* Battery charger driver for Nintendo Switch's TI BQ24193
*
* Copyright (c) 2018 CTCaer
*
* 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 __BQ24193_H_
#define __BQ24193_H_
#define BQ24193_I2C_ADDR 0x6B
// REG 0 masks.
#define BQ24193_INCONFIG_INLIMIT_MASK (7<<0)
#define BQ24193_INCONFIG_VINDPM_MASK 0x78
#define BQ24193_INCONFIG_HIZ_EN_MASK (1<<7)
// REG 1 masks.
#define BQ24193_PORCONFIG_BOOST_MASK (1<<0)
#define BQ24193_PORCONFIG_SYSMIN_MASK (7<<1)
#define BQ24193_PORCONFIG_CHGCONFIG_MASK (3<<4)
#define BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN (1<<4)
#define BQ24193_PORCONFIG_I2CWATCHDOG_MASK (1<<6)
#define BQ24193_PORCONFIG_RESET_MASK (1<<7)
// REG 2 masks.
#define BQ24193_CHRGCURR_20PCT_MASK (1<<0)
#define BQ24193_CHRGCURR_ICHG_MASK 0xFC
// REG 3 masks.
#define BQ24193_PRECHRG_ITERM 0x0F
#define BQ24193_PRECHRG_IPRECHG 0xF0
// REG 4 masks.
#define BQ24193_CHRGVOLT_VTHRES (1<<0)
#define BQ24193_CHRGVOLT_BATTLOW (1<<1)
#define BQ24193_CHRGVOLT_VREG 0xFC
// REG 5 masks.
#define BQ24193_CHRGTERM_ISET_MASK (1<<0)
#define BQ24193_CHRGTERM_CHGTIMER_MASK (3<<1)
#define BQ24193_CHRGTERM_ENTIMER_MASK (1<<3)
#define BQ24193_CHRGTERM_WATCHDOG_MASK (3<<4)
#define BQ24193_CHRGTERM_TERM_ST_MASK (1<<6)
#define BQ24193_CHRGTERM_TERM_EN_MASK (1<<7)
// REG 6 masks.
#define BQ24193_IRTHERMAL_THERM_MASK (3<<0)
#define BQ24193_IRTHERMAL_VCLAMP_MASK (7<<2)
#define BQ24193_IRTHERMAL_BATTCOMP_MASK (7<<5)
// REG 7 masks.
#define BQ24193_MISC_INT_MASK (3<<0)
#define BQ24193_MISC_VSET_MASK (1<<4)
#define BQ24193_MISC_BATFET_DI_MASK (1<<5)
#define BQ24193_MISC_TMR2X_EN_MASK (1<<6)
#define BQ24193_MISC_DPDM_EN_MASK (1<<7)
// REG 8 masks.
#define BQ24193_STATUS_VSYS_MASK (1<<0)
#define BQ24193_STATUS_THERM_MASK (1<<1)
#define BQ24193_STATUS_PG_MASK (1<<2)
#define BQ24193_STATUS_DPM_MASK (1<<3)
#define BQ24193_STATUS_CHRG_MASK (3<<4)
#define BQ24193_STATUS_VBUS_MASK (3<<6)
// REG 9 masks.
#define BQ24193_FAULT_THERM_MASK (7<<0)
#define BQ24193_FAULT_BATT_OVP_MASK (1<<3)
#define BQ24193_FAULT_CHARGE_MASK (3<<4)
#define BQ24193_FAULT_BOOST_MASK (1<<6)
#define BQ24193_FAULT_WATCHDOG_MASK (1<<7)
// REG A masks.
#define BQ24193_VENDORPART_DEV_MASK (3<<0)
#define BQ24193_VENDORPART_PN_MASK (7<<3)
enum BQ24193_reg {
BQ24193_InputSource = 0x00,
BQ24193_PORConfig = 0x01,
BQ24193_ChrgCurr = 0x02,
BQ24193_PreChrgTerm = 0x03,
BQ24193_ChrgVolt = 0x04,
BQ24193_ChrgTermTimer = 0x05,
BQ24193_IRCompThermal = 0x06,
BQ24193_Misc = 0x07,
BQ24193_Status = 0x08,
BQ24193_FaultReg = 0x09,
BQ24193_VendorPart = 0x0A,
};
enum BQ24193_reg_prop {
BQ24193_InputVoltageLimit, // REG 0.
BQ24193_InputCurrentLimit, // REG 0.
BQ24193_SystemMinimumVoltage, // REG 1.
BQ24193_FastChargeCurrentLimit, // REG 2.
BQ24193_ChargeVoltageLimit, // REG 4.
BQ24193_RechargeThreshold, // REG 4.
BQ24193_ThermalRegulation, // REG 6.
BQ24193_ChargeStatus, // REG 8.
BQ24193_TempStatus, // REG 9.
BQ24193_DevID, // REG A.
BQ24193_ProductNumber, // REG A.
};
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value);
void bq24193_enable_charger();
void bq24193_fake_battery_removal();
#endif /* __BQ24193_H_ */

281
bdk/power/max17050.c Normal file
View File

@@ -0,0 +1,281 @@
/*
* Fuel gauge driver for Nintendo Switch's Maxim 17050
*
* Copyright (c) 2011 Samsung Electronics
* MyungJoo Ham <myungjoo.ham@samsung.com>
* Copyright (c) 2018 CTCaer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This driver is based on max17040_battery.c
*/
#include "max17050.h"
#include <soc/i2c.h>
#include <utils/util.h>
#define BASE_SNS_UOHM 5000
/* Status register bits */
#define STATUS_POR_BIT BIT(1)
#define STATUS_BST_BIT BIT(3)
#define STATUS_VMN_BIT BIT(8)
#define STATUS_TMN_BIT BIT(9)
#define STATUS_SMN_BIT BIT(10)
#define STATUS_BI_BIT BIT(11)
#define STATUS_VMX_BIT BIT(12)
#define STATUS_TMX_BIT BIT(13)
#define STATUS_SMX_BIT BIT(14)
#define STATUS_BR_BIT BIT(15)
#define VFSOC0_LOCK 0x0000
#define VFSOC0_UNLOCK 0x0080
#define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */
static u32 battery_voltage = 0;
u32 max17050_get_cached_batt_volt()
{
return battery_voltage;
}
static u16 max17050_get_reg(u8 reg)
{
u16 data = 0;
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, reg);
return data;
}
int max17050_get_property(enum MAX17050_reg reg, int *value)
{
u16 data;
switch (reg)
{
case MAX17050_Age: // Age (percent). Based on 100% x (FullCAP Register/DesignCap).
data = max17050_get_reg(MAX17050_Age);
*value = data >> 8; /* Show MSB. 1% increments */
break;
case MAX17050_Cycles: // Cycle count.
*value = max17050_get_reg(MAX17050_Cycles);
break;
case MAX17050_MinVolt: // Voltage max/min
data = max17050_get_reg(MAX17050_MinMaxVolt);
*value = (data & 0xff) * 20; /* Voltage MIN. Units of 20mV */
break;
case MAX17050_MaxVolt: // Voltage max/min
data = max17050_get_reg(MAX17050_MinMaxVolt);
*value = (data >> 8) * 20; /* Voltage MAX. Units of LSB = 20mV */
break;
case MAX17050_V_empty: // Voltage min design.
data = max17050_get_reg(MAX17050_V_empty);
*value = (data >> 7) * 10; /* Units of LSB = 10mV */
break;
case MAX17050_VCELL: // Voltage now.
data = max17050_get_reg(MAX17050_VCELL);
*value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */
battery_voltage = *value;
break;
case MAX17050_AvgVCELL: // Voltage avg.
data = max17050_get_reg(MAX17050_AvgVCELL);
*value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */
break;
case MAX17050_OCVInternal: // Voltage ocv.
data = max17050_get_reg(MAX17050_OCVInternal);
*value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */
break;
case MAX17050_RepSOC: // Capacity %.
*value = max17050_get_reg(MAX17050_RepSOC);
break;
case MAX17050_DesignCap: // Charge full design.
data = max17050_get_reg(MAX17050_DesignCap);
*value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN;
break;
case MAX17050_FullCAP: // Charge full.
data = max17050_get_reg(MAX17050_FullCAP);
*value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN;
break;
case MAX17050_RepCap: // Charge now.
data = max17050_get_reg(MAX17050_RepCap);
*value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN;
break;
case MAX17050_TEMP: // Temp.
data = max17050_get_reg(MAX17050_TEMP);
*value = (s16)data;
*value = *value * 10 / 256;
break;
case MAX17050_Current: // Current now.
data = max17050_get_reg(MAX17050_Current);
*value = (s16)data;
*value *= 1562500 / (MAX17050_BOARD_SNS_RESISTOR_UOHM * MAX17050_BOARD_CGAIN);
break;
case MAX17050_AvgCurrent: // Current avg.
data = max17050_get_reg(MAX17050_AvgCurrent);
*value = (s16)data;
*value *= 1562500 / (MAX17050_BOARD_SNS_RESISTOR_UOHM * MAX17050_BOARD_CGAIN);
break;
default:
return -1;
}
return 0;
}
static int _max17050_write_verify_reg(u8 reg, u16 value)
{
int retries = 8;
int ret;
u16 read_value;
do
{
ret = i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, reg, (u8 *)&value, 2);
read_value = max17050_get_reg(reg);
if (read_value != value)
{
ret = -1;
retries--;
}
} while (retries && read_value != value);
return ret;
}
static void _max17050_override_por(u8 reg, u16 value)
{
if (value)
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, reg, (u8 *)&value, 2);
}
static void _max17050_load_new_capacity_params()
{
u16 fullcap, repSoc, dq_acc, dp_acc;
fullcap = 0x2476; // 4667mAh design capacity.
dq_acc = 0x10bc; // From a healthy fuel gauge.
dp_acc = 0x5e09; // =||=
repSoc = 0x6400; // 100%.
_max17050_write_verify_reg(MAX17050_RemCap, fullcap);
_max17050_write_verify_reg(MAX17050_RepCap, fullcap);
_max17050_write_verify_reg(MAX17050_dQacc, dq_acc);
_max17050_write_verify_reg(MAX17050_dPacc, dp_acc);
_max17050_write_verify_reg(MAX17050_FullCAP, fullcap);
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_DesignCap, (u8 *)&fullcap, 2);
_max17050_write_verify_reg(MAX17050_FullCAPNom, fullcap);
/* Update SOC register with new SOC */
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepSOC, (u8 *)&repSoc, 2);
}
static void _max17050_reset_vfsoc0_reg()
{
u16 lockVal = 0;
u16 vfSoc = 0x6440; // >100% for fully charged battery
lockVal = VFSOC0_UNLOCK;
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_VFSOC0Enable, (u8 *)&lockVal, 2);
_max17050_write_verify_reg(MAX17050_VFSOC0, vfSoc);
lockVal = VFSOC0_LOCK;
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_VFSOC0Enable, (u8 *)&lockVal, 2);
}
static void _max17050_update_capacity_regs()
{
u16 value = 0x2476; // Set to 4667mAh design capacity.
_max17050_write_verify_reg(MAX17050_FullCAP, value);
_max17050_write_verify_reg(MAX17050_FullCAPNom, value);
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_DesignCap, config->design_cap, 2);
}
static void _max17050_write_config_regs()
{
u16 value = 0;
value = 0x7254;
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_CONFIG, (u8 *)&value, 2);
value = 0x2473;
i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_LearnCFG, (u8 *)&value, 2);
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_FilterCFG, (u8 *)&value, 2)
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RelaxCFG, (u8 *)&value, 2)
//i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_FullSOCThr, (u8 *)&value, 2)
}
/*
* Block write all the override values coming from platform data.
* This function MUST be called before the POR initialization proceedure
* specified by maxim.
*/
static void _max17050_override_por_values()
{
u16 dq_acc = 0x10bc; // From a healthy fuel gauge.
u16 dp_acc = 0x5e09; // =||=
_max17050_override_por(MAX17050_dQacc, dq_acc);
_max17050_override_por(MAX17050_dPacc, dp_acc);
//_max17050_override_por(MAX17050_RCOMP0, config->rcomp0); //0x58
//_max17050_override_por(MAX17050_TempCo, config->tcompc0); //0x1b22
//u16 k_empty0 = 0x439;
//_max17050_override_por(map, MAX17050_K_empty0, k_empty0); // Unknown cell data
}
static void _max17050_set_por_bit(u16 value)
{
_max17050_write_verify_reg(MAX17050_STATUS, value);
}
int max17050_fix_configuration()
{
/* Init phase, set the POR bit */
_max17050_set_por_bit(STATUS_POR_BIT);
/* Override POR values */
_max17050_override_por_values();
/* After Power up, the MAX17050 requires 500ms in order
* to perform signal debouncing and initial SOC reporting
*/
msleep(500);
/* Initialize configaration */
_max17050_write_config_regs();
/* update capacity params */
_max17050_update_capacity_regs();
/* delay must be atleast 350mS to allow VFSOC
* to be calculated from the new configuration
*/
msleep(350);
/* reset vfsoc0 reg */
_max17050_reset_vfsoc0_reg();
/* load new capacity params */
_max17050_load_new_capacity_params();
/* Init complete, Clear the POR bit */
//_max17050_set_por_bit(0); // Should we? Or let the switch to reconfigure POR?
// Sets POR, BI, BR.
_max17050_set_por_bit(0x8801);
return 0;
}

137
bdk/power/max17050.h Normal file
View File

@@ -0,0 +1,137 @@
/*
* Fuel gauge driver for Nintendo Switch's Maxim 17050
*
* Copyright (c) 2011 Samsung Electronics
* MyungJoo Ham <myungjoo.ham@samsung.com>
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __MAX17050_H_
#define __MAX17050_H_
#include <utils/types.h>
/* Board default values */
#define MAX17050_BOARD_CGAIN 2 /* Actual: 1.99993 */
#define MAX17050_BOARD_SNS_RESISTOR_UOHM 5000 /* 0.005 Ohm */
#define MAX17050_STATUS_BattAbsent BIT(3)
/* Consider RepCap which is less then 10 units below FullCAP full */
#define MAX17050_FULL_THRESHOLD 10
#define MAX17050_CHARACTERIZATION_DATA_SIZE 48
#define MAXIM17050_I2C_ADDR 0x36
enum MAX17050_reg {
MAX17050_STATUS = 0x00,
MAX17050_VALRT_Th = 0x01,
MAX17050_TALRT_Th = 0x02,
MAX17050_SALRT_Th = 0x03,
MAX17050_AtRate = 0x04,
MAX17050_RepCap = 0x05,
MAX17050_RepSOC = 0x06,
MAX17050_Age = 0x07,
MAX17050_TEMP = 0x08,
MAX17050_VCELL = 0x09,
MAX17050_Current = 0x0A,
MAX17050_AvgCurrent = 0x0B,
MAX17050_SOC = 0x0D,
MAX17050_AvSOC = 0x0E,
MAX17050_RemCap = 0x0F,
MAX17050_FullCAP = 0x10,
MAX17050_TTE = 0x11,
MAX17050_QRTbl00 = 0x12,
MAX17050_FullSOCThr = 0x13,
MAX17050_RSLOW = 0x14,
MAX17050_AvgTA = 0x16,
MAX17050_Cycles = 0x17,
MAX17050_DesignCap = 0x18,
MAX17050_AvgVCELL = 0x19,
MAX17050_MinMaxTemp = 0x1A,
MAX17050_MinMaxVolt = 0x1B,
MAX17050_MinMaxCurr = 0x1C,
MAX17050_CONFIG = 0x1D,
MAX17050_ICHGTerm = 0x1E,
MAX17050_AvCap = 0x1F,
MAX17050_ManName = 0x20,
MAX17050_DevName = 0x21,
MAX17050_QRTbl10 = 0x22,
MAX17050_FullCAPNom = 0x23,
MAX17050_TempNom = 0x24,
MAX17050_TempLim = 0x25,
MAX17050_TempHot = 0x26,
MAX17050_AIN = 0x27,
MAX17050_LearnCFG = 0x28,
MAX17050_FilterCFG = 0x29,
MAX17050_RelaxCFG = 0x2A,
MAX17050_MiscCFG = 0x2B,
MAX17050_TGAIN = 0x2C,
MAX17050_TOFF = 0x2D,
MAX17050_CGAIN = 0x2E,
MAX17050_COFF = 0x2F,
MAX17050_QRTbl20 = 0x32,
MAX17050_SOC_empty = 0x33,
MAX17050_T_empty = 0x34,
MAX17050_FullCAP0 = 0x35,
MAX17050_LAvg_empty = 0x36,
MAX17050_FCTC = 0x37,
MAX17050_RCOMP0 = 0x38,
MAX17050_TempCo = 0x39,
MAX17050_V_empty = 0x3A,
MAX17050_K_empty0 = 0x3B,
MAX17050_TaskPeriod = 0x3C,
MAX17050_FSTAT = 0x3D,
MAX17050_TIMER = 0x3E,
MAX17050_SHDNTIMER = 0x3F,
MAX17050_QRTbl30 = 0x42,
MAX17050_dQacc = 0x45,
MAX17050_dPacc = 0x46,
MAX17050_VFSOC0 = 0x48,
Max17050_QH0 = 0x4C,
MAX17050_QH = 0x4D,
MAX17050_QL = 0x4E,
MAX17050_MinVolt = 0x50, // Custom ID. Not to be sent to i2c.
MAX17050_MaxVolt = 0x51, // Custom ID. Not to be sent to i2c.
MAX17050_VFSOC0Enable = 0x60,
MAX17050_MODELEnable1 = 0x62,
MAX17050_MODELEnable2 = 0x63,
MAX17050_MODELChrTbl = 0x80,
MAX17050_OCV = 0xEE,
MAX17050_OCVInternal = 0xFB,
MAX17050_VFSOC = 0xFF,
};
int max17050_get_property(enum MAX17050_reg reg, int *value);
int max17050_fix_configuration();
u32 max17050_get_cached_batt_volt();
#endif /* __MAX17050_H_ */

380
bdk/power/max77620.h Normal file
View File

@@ -0,0 +1,380 @@
/*
* Defining registers address and its bit definitions of MAX77620 and MAX20024
*
* Copyright (c) 2019-2020 CTCaer
*
* 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.
*/
#ifndef _MFD_MAX77620_H_
#define _MFD_MAX77620_H_
#define MAX77620_I2C_ADDR 0x3C
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
#define MAX77620_REG_CNFGGLBL1 0x00
#define MAX77620_CNFGGLBL1_LBRSTEN BIT(0)
#define MAX77620_CNFGGLBL1_LBDAC_MASK 0x0E
#define MAX77620_CNFGGLBL1_LBDAC_2700 (0 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_2800 (1 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_2900 (2 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3000 (3 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3100 (4 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3200 (5 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3300 (6 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_3400 (7 << 1)
#define MAX77620_CNFGGLBL1_LBHYST_100 (0 << 4)
#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4)
#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4)
#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4)
#define MAX77620_CNFGGLBL1_MPPLD BIT(6)
#define MAX77620_CNFGGLBL1_LBDAC_EN BIT(7)
#define MAX77620_REG_CNFGGLBL2 0x01
#define MAX77620_TWD_MASK 0x3
#define MAX77620_TWD_2s 0x0
#define MAX77620_TWD_16s 0x1
#define MAX77620_TWD_64s 0x2
#define MAX77620_TWD_128s 0x3
#define MAX77620_WDTEN BIT(2)
#define MAX77620_WDTSLPC BIT(3)
#define MAX77620_WDTOFFC BIT(4)
#define MAX77620_GLBL_LPM BIT(5)
#define MAX77620_I2CTWD_MASK 0xC0
#define MAX77620_I2CTWD_DISABLED 0x00
#define MAX77620_I2CTWD_1_33ms 0x40
#define MAX77620_I2CTWD_35_7ms 0x80
#define MAX77620_I2CTWD_41_7ms 0xC0
#define MAX77620_REG_CNFGGLBL3 0x02
#define MAX77620_WDTC_MASK 0x3
#define MAX77620_REG_CNFG1_32K 0x03
#define MAX77620_CNFG1_PWR_MD_32K_MASK 0x3
#define MAX77620_CNFG1_32K_OUT0_EN BIT(2)
#define MAX77620_CNFG1_32KLOAD_MASK 0x30
#define MAX77620_CNFG1_32K_OK BIT(7)
#define MAX77620_REG_CNFGBBC 0x04
#define MAX77620_CNFGBBC_ENABLE BIT(0)
#define MAX77620_CNFGBBC_CURRENT_MASK 0x06
#define MAX77620_CNFGBBC_CURRENT_SHIFT 1
#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18
#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3
#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE BIT(5)
#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0
#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6
#define MAX77620_CNFGBBC_RESISTOR_100 (0 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_CNFGBBC_RESISTOR_1K (1 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_CNFGBBC_RESISTOR_3K (2 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_REG_IRQTOP 0x05
#define MAX77620_REG_IRQTOPM 0x0D
#define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1)
#define MAX77620_IRQ_TOP_32K_MASK BIT(2)
#define MAX77620_IRQ_TOP_RTC_MASK BIT(3)
#define MAX77620_IRQ_TOP_GPIO_MASK BIT(4)
#define MAX77620_IRQ_TOP_LDO_MASK BIT(5)
#define MAX77620_IRQ_TOP_SD_MASK BIT(6)
#define MAX77620_IRQ_TOP_GLBL_MASK BIT(7)
#define MAX77620_REG_INTLBT 0x06
#define MAX77620_REG_INTENLBT 0x0E
#define MAX77620_IRQ_GLBLM_MASK BIT(0)
#define MAX77620_IRQ_TJALRM2_MASK BIT(1)
#define MAX77620_IRQ_TJALRM1_MASK BIT(2)
#define MAX77620_IRQ_LBM_MASK BIT(3)
#define MAX77620_REG_IRQSD 0x07
#define MAX77620_REG_IRQMASKSD 0x0F
#define MAX77620_IRQSD_PFI_SD3 BIT(4)
#define MAX77620_IRQSD_PFI_SD2 BIT(5)
#define MAX77620_IRQSD_PFI_SD1 BIT(6)
#define MAX77620_IRQSD_PFI_SD0 BIT(7)
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 // LDO number that irq occured.
#define MAX77620_REG_IRQ_MSK_L0_7 0x10
#define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occured. Only bit0: LDO8 is valid.
#define MAX77620_REG_IRQ_MSK_L8 0x11
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt.
#define MAX77620_REG_ONOFFIRQ 0x0B
#define MAX77620_REG_ONOFFIRQM 0x12
#define MAX77620_ONOFFIRQ_MRWRN BIT(0)
#define MAX77620_ONOFFIRQ_EN0_1SEC BIT(1)
#define MAX77620_ONOFFIRQ_EN0_F BIT(2)
#define MAX77620_ONOFFIRQ_EN0_R BIT(3)
#define MAX77620_ONOFFIRQ_LID_F BIT(4)
#define MAX77620_ONOFFIRQ_LID_R BIT(5)
#define MAX77620_ONOFFIRQ_ACOK_F BIT(6)
#define MAX77620_ONOFFIRQ_ACOK_R BIT(7)
#define MAX77620_REG_NVERC 0x0C // Shutdown reason (non-volatile).
#define MAX77620_NVERC_SHDN BIT(0)
#define MAX77620_NVERC_WTCHDG BIT(1)
#define MAX77620_NVERC_HDRST BIT(2)
#define MAX77620_NVERC_TOVLD BIT(3)
#define MAX77620_NVERC_MBLSD BIT(4)
#define MAX77620_NVERC_MBO BIT(5)
#define MAX77620_NVERC_MBU BIT(6)
#define MAX77620_NVERC_RSTIN BIT(7)
#define MAX77620_REG_STATLBT 0x13
#define MAX77620_REG_STATSD 0x14
#define MAX77620_REG_ONOFFSTAT 0x15
#define MAX77620_ONOFFSTAT_LID BIT(0)
#define MAX77620_ONOFFSTAT_ACOK BIT(1)
#define MAX77620_ONOFFSTAT_EN0 BIT(2)
/* SD and LDO Registers */
#define MAX77620_REG_SD0 0x16
#define MAX77620_REG_SD1 0x17
#define MAX77620_REG_SD2 0x18
#define MAX77620_REG_SD3 0x19
#define MAX77620_REG_SD4 0x1A
#define MAX77620_REG_DVSSD0 0x1B
#define MAX77620_REG_DVSSD1 0x1C
#define MAX77620_SDX_VOLT_MASK 0xFF
#define MAX77620_SD0_VOLT_MASK 0x3F
#define MAX77620_SD1_VOLT_MASK 0x7F
#define MAX77620_LDO_VOLT_MASK 0x3F
#define MAX77620_REG_SD0_CFG 0x1D
#define MAX77620_REG_SD1_CFG 0x1E
#define MAX77620_REG_SD2_CFG 0x1F
#define MAX77620_REG_SD3_CFG 0x20
#define MAX77620_REG_SD4_CFG 0x21
#define MAX77620_SD_SR_MASK 0xC0
#define MAX77620_SD_SR_SHIFT 6
#define MAX77620_SD_POWER_MODE_MASK 0x30
#define MAX77620_SD_POWER_MODE_SHIFT 4
#define MAX77620_SD_CFG1_ADE_MASK BIT(3)
#define MAX77620_SD_CFG1_ADE_DISABLE 0
#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3)
#define MAX77620_SD_FPWM_MASK 0x04
#define MAX77620_SD_FPWM_SHIFT 2
#define MAX77620_SD_FSRADE_MASK 0x01
#define MAX77620_SD_FSRADE_SHIFT 0
#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2)
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2)
#define MAX77620_SD_CFG1_MPOK_MASK BIT(1)
#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0)
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0)
#define MAX77620_REG_SD_CFG2 0x22
#define MAX77620_SD_CNF2_RSVD BIT(0)
#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1)
#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2)
#define MAX77620_REG_LDO0_CFG 0x23
#define MAX77620_REG_LDO0_CFG2 0x24
#define MAX77620_REG_LDO1_CFG 0x25
#define MAX77620_REG_LDO1_CFG2 0x26
#define MAX77620_REG_LDO2_CFG 0x27
#define MAX77620_REG_LDO2_CFG2 0x28
#define MAX77620_REG_LDO3_CFG 0x29
#define MAX77620_REG_LDO3_CFG2 0x2A
#define MAX77620_REG_LDO4_CFG 0x2B
#define MAX77620_REG_LDO4_CFG2 0x2C
#define MAX77620_REG_LDO5_CFG 0x2D
#define MAX77620_REG_LDO5_CFG2 0x2E
#define MAX77620_REG_LDO6_CFG 0x2F
#define MAX77620_REG_LDO6_CFG2 0x30
#define MAX77620_REG_LDO7_CFG 0x31
#define MAX77620_REG_LDO7_CFG2 0x32
#define MAX77620_REG_LDO8_CFG 0x33
#define MAX77620_REG_LDO8_CFG2 0x34
/*! LDO CFG */
#define MAX77620_LDO_POWER_MODE_SHIFT 6
#define MAX77620_LDO_POWER_MODE_MASK (3 << MAX77620_LDO_POWER_MODE_SHIFT)
#define MAX77620_POWER_MODE_NORMAL 3
#define MAX77620_POWER_MODE_LPM 2
#define MAX77620_POWER_MODE_GLPM 1
#define MAX77620_POWER_MODE_DISABLE 0
/*! LDO CFG2 */
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
#define MAX77620_LDO_CFG2_SS_FAST (0 << 0)
#define MAX77620_LDO_CFG2_SS_SLOW (1 << 0)
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
#define MAX77620_LDO_CFG2_MPOK_MASK BIT(2)
#define MAX77620_LDO_CFG2_POK_MASK BIT(3)
#define MAX77620_LDO_CFG2_COMP_SHIFT 4
#define MAX77620_LDO_CFG2_COMP_MASK (3 << MAX77620_LDO_COMP_SHIFT)
#define MAX77620_LDO_CFG2_COMP_SLOW 3
#define MAX77620_LDO_CFG2_COMP_MID_SLOW 2
#define MAX77620_LDO_CFG2_COMP_MID_FAST 1
#define MAX77620_LDO_CFG2_COMP_FAST 0
#define MAX77620_LDO_CFG2_ALPM_EN_MASK BIT(6)
#define MAX77620_LDO_CFG2_OVCLMP_MASK BIT(7)
#define MAX77620_REG_LDO_CFG3 0x35
#define MAX77620_LDO_BIAS_EN BIT(0)
#define MAX77620_TRACK4_SHIFT 5
#define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT)
#define MAX77620_REG_GPIO0 0x36
#define MAX77620_REG_GPIO1 0x37
#define MAX77620_REG_GPIO2 0x38
#define MAX77620_REG_GPIO3 0x39
#define MAX77620_REG_GPIO4 0x3A
#define MAX77620_REG_GPIO5 0x3B
#define MAX77620_REG_GPIO6 0x3C
#define MAX77620_REG_GPIO7 0x3D
#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN (0 << 0)
#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1)
#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1)
#define MAX77620_CNFG_GPIO_DIR_OUTPUT (0 << 1)
#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3)
#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW (0 << 3)
#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4)
#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4)
#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5)
#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6)
#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6)
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
#define MAX77620_GPIO_OUTPUT_DISABLE 0
#define MAX77620_GPIO_OUTPUT_ENABLE 1
#define MAX77620_REG_PUE_GPIO 0x3E // Gpio Pullup resistor enable.
#define MAX77620_REG_PDE_GPIO 0x3F // Gpio Pulldown resistor enable.
#define MAX77620_REG_AME_GPIO 0x40 // Gpio pinmuxing. Clear bits are Standard GPIO.
#define MAX77620_REG_ONOFFCNFG1 0x41
#define MAX20024_ONOFFCNFG1_CLRSE 0x18
#define MAX77620_ONOFFCNFG1_PWR_OFF BIT(1)
#define MAX77620_ONOFFCNFG1_SLPEN BIT(2)
#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
#define MAX77620_ONOFFCNFG1_RSVD BIT(6)
#define MAX77620_ONOFFCNFG1_SFT_RST BIT(7)
#define MAX77620_REG_ONOFFCNFG2 0x42
#define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0)
#define MAX77620_ONOFFCNFG2_WK_ALARM2 BIT(1)
#define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2)
#define MAX77620_ONOFFCNFG2_WK_MBATT BIT(3) // MBATT event generates a wakeup signal. use it in android/l4t?
#define MAX77620_ONOFFCNFG2_WK_ACOK BIT(4)
#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5)
#define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6)
#define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7)
/* FPS Registers */
#define MAX77620_REG_FPS_CFG0 0x43 // FPS0.
#define MAX77620_REG_FPS_CFG1 0x44 // FPS1.
#define MAX77620_REG_FPS_CFG2 0x45 // FPS2.
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
#define MAX77620_FPS_ENFPS_SW 0x01
#define MAX77620_FPS_EN_SRC_SHIFT 1
#define MAX77620_FPS_EN_SRC_MASK 0x06
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
#define MAX77620_REG_FPS_LDO0 0x46
#define MAX77620_REG_FPS_LDO1 0x47
#define MAX77620_REG_FPS_LDO2 0x48
#define MAX77620_REG_FPS_LDO3 0x49
#define MAX77620_REG_FPS_LDO4 0x4A
#define MAX77620_REG_FPS_LDO5 0x4B
#define MAX77620_REG_FPS_LDO6 0x4C
#define MAX77620_REG_FPS_LDO7 0x4D
#define MAX77620_REG_FPS_LDO8 0x4E
#define MAX77620_REG_FPS_SD0 0x4F
#define MAX77620_REG_FPS_SD1 0x50
#define MAX77620_REG_FPS_SD2 0x51
#define MAX77620_REG_FPS_SD3 0x52
#define MAX77620_REG_FPS_SD4 0x53
#define MAX77620_REG_FPS_GPIO1 0x54
#define MAX77620_REG_FPS_GPIO2 0x55
#define MAX77620_REG_FPS_GPIO3 0x56
#define MAX77620_REG_FPS_RSO 0x57
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
#define MAX77620_FPS_SRC_SHIFT 6
#define MAX77620_FPS_SRC_MASK 0xC0
#define MAX77620_FPS_COUNT 3
#define MAX77620_FPS_PERIOD_MIN_US 40
#define MAX77620_FPS_PERIOD_MAX_US 2560
#define MAX77620_REG_CID0 0x58
#define MAX77620_REG_CID1 0x59
#define MAX77620_REG_CID2 0x5A
#define MAX77620_REG_CID3 0x5B
#define MAX77620_REG_CID4 0x5C // OTP version.
#define MAX77620_REG_CID5 0x5D
#define MAX77620_CID_DIDO_MASK 0xF
#define MAX77620_CID_DIDO_SHIFT 0
#define MAX77620_CID_DIDM_MASK 0xF0
#define MAX77620_CID_DIDM_SHIFT 4
/* Device Identification Metal */
#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF)
/* Device Indentification OTP */
#define MAX77620_CID5_DIDO(n) ((n) & 0xF)
#define MAX77620_REG_DVSSD4 0x5E
#define MAX20024_REG_MAX_ADD 0x70
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0)
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1)
#define MAX77620_IRQ_LVL2_GPIO_EDGE2 BIT(2)
#define MAX77620_IRQ_LVL2_GPIO_EDGE3 BIT(3)
#define MAX77620_IRQ_LVL2_GPIO_EDGE4 BIT(4)
#define MAX77620_IRQ_LVL2_GPIO_EDGE5 BIT(5)
#define MAX77620_IRQ_LVL2_GPIO_EDGE6 BIT(6)
#define MAX77620_IRQ_LVL2_GPIO_EDGE7 BIT(7)
/* Interrupts */
enum {
MAX77620_IRQ_TOP_GLBL, /* Low-Battery */
MAX77620_IRQ_TOP_SD, /* SD power fail */
MAX77620_IRQ_TOP_LDO, /* LDO power fail */
MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */
MAX77620_IRQ_TOP_RTC, /* RTC */
MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */
MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */
MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */
MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */
MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */
};
/* GPIOs */
enum {
MAX77620_GPIO0,
MAX77620_GPIO1,
MAX77620_GPIO2,
MAX77620_GPIO3,
MAX77620_GPIO4,
MAX77620_GPIO5,
MAX77620_GPIO6,
MAX77620_GPIO7,
MAX77620_GPIO_NR,
};
/* FPS Source */
enum max77620_fps_src {
MAX77620_FPS_SRC_0,
MAX77620_FPS_SRC_1,
MAX77620_FPS_SRC_2,
MAX77620_FPS_SRC_NONE,
MAX77620_FPS_SRC_DEF,
};
#endif /* _MFD_MAX77620_H_ */

339
bdk/power/max7762x.c Normal file
View File

@@ -0,0 +1,339 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <power/max7762x.h>
#include <power/max77620.h>
#include <power/max77812.h>
#include <soc/fuse.h>
#include <soc/i2c.h>
#include <soc/t210.h>
#include <utils/util.h>
#define REGULATOR_SD 0
#define REGULATOR_LDO 1
#define REGULATOR_BC0 2
#define REGULATOR_BC1 3
typedef struct _max77620_fps_t
{
u8 fps_addr;
u8 fps_src;
u8 pd_period;
u8 pu_period;
} max77620_fps_t;
typedef struct _max77621_ctrl_t
{
u8 ctrl1_por;
u8 ctrl1_hos;
u8 ctrl2_por;
u8 ctrl2_hos;
} max77621_ctrl_t;
typedef struct _max77812_ctrl_t
{
u8 mask;
u8 shift;
u8 rsvd0;
u8 rsvd1;
} max77812_en_t;
typedef struct _max77620_regulator_t
{
const char *name;
u32 uv_step;
u32 uv_min;
u32 uv_default;
u32 uv_max;
u8 type;
u8 volt_addr;
u8 cfg_addr;
u8 volt_mask;
union {
max77620_fps_t fps;
max77621_ctrl_t ctrl;
max77812_en_t enable;
};
} max77620_regulator_t;
static const max77620_regulator_t _pmic_regulators[] = {
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
{ "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
{ "ldo1", 25000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO1, 3, 7, 0 }} },
{ "ldo2", 50000, 800000, 1800000, 3300000, REGULATOR_LDO, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO2, 3, 7, 0 }} },
{ "ldo3", 50000, 800000, 3100000, 3100000, REGULATOR_LDO, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO3, 3, 7, 0 }} },
{ "ldo4", 12500, 800000, 850000, 1000000, REGULATOR_LDO, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO4, 0, 7, 1 }} },
{ "ldo5", 50000, 800000, 1800000, 1800000, REGULATOR_LDO, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO5, 3, 7, 0 }} },
{ "ldo6", 50000, 800000, 2900000, 2900000, REGULATOR_LDO, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO6, 3, 7, 0 }} },
{ "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} },
{ "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} },
{ "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
{ "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
{ "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} },
//{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} },
//{ "max77812_RAM", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration.
};
static u8 _max77812_get_address()
{
static u8 max77812_i2c_addr = 0;
if (max77812_i2c_addr)
return max77812_i2c_addr;
max77812_i2c_addr =
!(FUSE(FUSE_RESERVED_ODM28_T210B01) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
return max77812_i2c_addr;
}
static u8 _max7762x_get_i2c_address(u32 id)
{
const max77620_regulator_t *reg = &_pmic_regulators[id];
// Choose the correct i2c address.
switch (reg->type)
{
case REGULATOR_SD:
case REGULATOR_LDO:
return MAX77620_I2C_ADDR;
case REGULATOR_BC0:
return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR);
case REGULATOR_BC1:
return _max77812_get_address();
default:
return 0;
}
}
static void _max7762x_set_reg(u8 addr, u8 reg, u8 val)
{
u32 retries = 100;
while (retries)
{
if (i2c_send_byte(I2C_5, addr, reg, val))
break;
usleep(50);
retries--;
}
}
int max77620_regulator_get_status(u32 id)
{
if (id > REGULATOR_LDO8)
return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id];
// SD power OK status.
if (reg->type == REGULATOR_SD)
{
u8 mask = 1u << (7 - id);
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & mask) ? 0 : 1;
}
// LDO power OK status.
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & MAX77620_LDO_CFG2_POK_MASK) ? 1 : 0;
}
int max77620_regulator_config_fps(u32 id)
{
if (id > REGULATOR_LDO8)
return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id];
// Set FPS configuration.
_max7762x_set_reg(MAX77620_I2C_ADDR,
reg->fps.fps_addr,
(reg->fps.fps_src << MAX77620_FPS_SRC_SHIFT) |
(reg->fps.pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) |
(reg->fps.pd_period << MAX77620_FPS_PD_PERIOD_SHIFT));
return 1;
}
int max7762x_regulator_set_voltage(u32 id, u32 mv)
{
if (id > REGULATOR_MAX)
return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id];
if (mv < reg->uv_min || mv > reg->uv_max)
return 0;
u8 addr = _max7762x_get_i2c_address(id);
// Calculate voltage multiplier.
u32 mult = (mv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step;
u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr);
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
// Set voltage.
_max7762x_set_reg(addr, reg->volt_addr, val);
// If max77621 set DVS voltage also.
if (reg->type == REGULATOR_BC0)
_max7762x_set_reg(addr, reg->cfg_addr, MAX77621_VOUT_ENABLE_MASK | val);
// Wait for ramp up/down delay.
usleep(1000);
return 1;
}
int max7762x_regulator_enable(u32 id, bool enable)
{
u8 reg_addr;
u8 enable_val;
u8 enable_mask;
u8 enable_shift;
if (id > REGULATOR_MAX)
return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id];
// Choose the correct i2c and register addresses and mask/shift for each type.
switch (reg->type)
{
case REGULATOR_SD:
reg_addr = reg->cfg_addr;
enable_val = MAX77620_POWER_MODE_NORMAL;
enable_mask = MAX77620_SD_POWER_MODE_MASK;
enable_shift = MAX77620_SD_POWER_MODE_SHIFT;
break;
case REGULATOR_LDO:
reg_addr = reg->volt_addr;
enable_val = MAX77620_POWER_MODE_NORMAL;
enable_mask = MAX77620_LDO_POWER_MODE_MASK;
enable_shift = MAX77620_LDO_POWER_MODE_SHIFT;
break;
case REGULATOR_BC0:
reg_addr = reg->volt_addr;
enable_val = MAX77621_VOUT_ENABLE;
enable_mask = MAX77621_DVC_DVS_ENABLE_MASK;
enable_shift = MAX77621_DVC_DVS_ENABLE_SHIFT;
break;
case REGULATOR_BC1:
reg_addr = reg->cfg_addr;
enable_val = MAX77812_EN_CTRL_ENABLE;
enable_mask = reg->enable.mask;
enable_shift = reg->enable.shift;
break;
default:
return 0;
}
u8 addr = _max7762x_get_i2c_address(id);
// Read and enable/disable.
u8 val = i2c_recv_byte(I2C_5, addr, reg_addr);
val &= ~enable_mask;
if (enable)
val |= (enable_val << enable_shift);
// Set enable.
_max7762x_set_reg(addr, reg_addr, val);
// Wait for enable/disable ramp delay.
usleep(1000);
return 1;
}
void max77620_config_gpio(u32 gpio_id, bool enable)
{
if (gpio_id > 7)
return;
// Configure as standard GPIO.
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, val & ~BIT(gpio_id));
// Set GPIO configuration.
if (enable)
val = MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DIR_OUTPUT | MAX77620_CNFG_GPIO_DRV_PUSHPULL;
else
val = MAX77620_CNFG_GPIO_DIR_INPUT | MAX77620_CNFG_GPIO_DRV_OPENDRAIN;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO0 + gpio_id, val);
}
void max77621_config_default(u32 id, bool por)
{
const max77620_regulator_t *reg = &_pmic_regulators[id];
if (reg->type != REGULATOR_BC0)
return;
u8 addr = _max7762x_get_i2c_address(id);
if (por)
{
// Set voltage and disable power before changing the inductor.
max7762x_regulator_set_voltage(id, 1000000);
max7762x_regulator_enable(id, false);
// Configure to default.
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_por);
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_por);
}
else
{
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_hos);
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_hos);
}
}
void max77620_config_default()
{
// Check if Erista OTP.
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4) != 0x35)
return;
// Set default voltages and enable regulators.
for (u32 i = 1; i <= REGULATOR_LDO8; i++)
{
max77620_regulator_config_fps(i);
max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);
if (_pmic_regulators[i].fps.fps_src != MAX77620_FPS_SRC_NONE)
max7762x_regulator_enable(i, true);
}
// Enable SD0 output voltage sense and disable for SD1. Additionally disable the reserved bit.
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
}
// Stock HOS: disabled.
void max77620_low_battery_monitor_config(bool enable)
{
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
MAX77620_CNFGGLBL1_LBDAC_EN |
(enable ? MAX77620_CNFGGLBL1_MPPLD : 0) |
MAX77620_CNFGGLBL1_LBHYST_200 |
MAX77620_CNFGGLBL1_LBDAC_2800);
}

148
bdk/power/max7762x.h Normal file
View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2020 CTCaer
*
* 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 _MAX7762X_H_
#define _MAX7762X_H_
#include <utils/types.h>
/*
* Switch Power domains (max77620):
* Name | Usage | uV step | uV min | uV default | uV max | Init
*-------+---------------+---------+--------+------------+---------+------------------
* sd0 | SoC | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1)
* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv)
* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 |
* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1)
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv)
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv)
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv)
*/
/*
* MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode
* MAX77620_REG_GPIOx: 0x9 sets output and enable
*/
/*! MAX77620 partitions. */
#define REGULATOR_SD0 0
#define REGULATOR_SD1 1
#define REGULATOR_SD2 2
#define REGULATOR_SD3 3
#define REGULATOR_LDO0 4
#define REGULATOR_LDO1 5
#define REGULATOR_LDO2 6
#define REGULATOR_LDO3 7
#define REGULATOR_LDO4 8
#define REGULATOR_LDO5 9
#define REGULATOR_LDO6 10
#define REGULATOR_LDO7 11
#define REGULATOR_LDO8 12
#define REGULATOR_CPU0 13
#define REGULATOR_GPU0 14
#define REGULATOR_CPU1 15
//#define REGULATOR_GPU1 16
//#define REGULATOR_GPU1 17
#define REGULATOR_MAX 15
#define MAX77621_CPU_I2C_ADDR 0x1B
#define MAX77621_GPU_I2C_ADDR 0x1C
#define MAX77621_VOUT_REG 0x00
#define MAX77621_VOUT_DVS_REG 0x01
#define MAX77621_CONTROL1_REG 0x02
#define MAX77621_CONTROL2_REG 0x03
#define MAX77621_CHIPID1_REG 0x04
#define MAX77621_CHIPID2_REG 0x05
/* MAX77621_VOUT_DVC_DVS */
#define MAX77621_DVC_DVS_VOLT_MASK 0x7F
#define MAX77621_DVC_DVS_ENABLE_SHIFT 7
#define MAX77621_DVC_DVS_ENABLE_MASK (1 << MAX77621_DVC_DVS_ENABLE_SHIFT)
/* MAX77621_VOUT */
#define MAX77621_VOUT_DISABLE 0
#define MAX77621_VOUT_ENABLE 1
#define MAX77621_VOUT_ENABLE_MASK (MAX77621_VOUT_ENABLE << MAX77621_DVC_DVS_ENABLE_SHIFT)
/* MAX77621_CONTROL1 */
#define MAX77621_RAMP_12mV_PER_US 0x0
#define MAX77621_RAMP_25mV_PER_US 0x1
#define MAX77621_RAMP_50mV_PER_US 0x2
#define MAX77621_RAMP_200mV_PER_US 0x3
#define MAX77621_RAMP_MASK 0x3
#define MAX77621_FREQSHIFT_9PER BIT(2)
#define MAX77621_BIAS_ENABLE BIT(3)
#define MAX77621_AD_ENABLE BIT(4)
#define MAX77621_NFSR_ENABLE BIT(5)
#define MAX77621_FPWM_EN_M BIT(6)
#define MAX77621_SNS_ENABLE BIT(7)
/* MAX77621_CONTROL2 */
#define MAX77621_INDUCTOR_MIN_30_PER 0
#define MAX77621_INDUCTOR_NOMINAL 1
#define MAX77621_INDUCTOR_PLUS_30_PER 2
#define MAX77621_INDUCTOR_PLUS_60_PER 3
#define MAX77621_INDUCTOR_MASK 3
#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0
#define MAX77621_CKKADV_TRIP_150mV_PER_US BIT(2)
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS BIT(3)
#define MAX77621_CKKADV_TRIP_DISABLE (BIT(2) | BIT(3))
#define MAX77621_CKKADV_TRIP_MASK (BIT(2) | BIT(3))
#define MAX77621_FT_ENABLE BIT(4)
#define MAX77621_DISCH_ENABLE BIT(5)
#define MAX77621_WDTMR_ENABLE BIT(6)
#define MAX77621_T_JUNCTION_120 BIT(7)
#define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US)
#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \
MAX77621_NFSR_ENABLE | \
MAX77621_SNS_ENABLE | \
MAX77621_RAMP_12mV_PER_US)
#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \
MAX77621_FT_ENABLE | \
MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | \
MAX77621_CKKADV_TRIP_150mV_PER_US | \
MAX77621_INDUCTOR_NOMINAL)
#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \
MAX77621_WDTMR_ENABLE | \
MAX77621_CKKADV_TRIP_75mV_PER_US | \
MAX77621_INDUCTOR_NOMINAL)
#define MAX77621_CTRL_HOS_CFG 0
#define MAX77621_CTRL_POR_CFG 1
int max77620_regulator_get_status(u32 id);
int max77620_regulator_config_fps(u32 id);
int max7762x_regulator_set_voltage(u32 id, u32 mv);
int max7762x_regulator_enable(u32 id, bool enable);
void max77620_config_gpio(u32 id, bool enable);
void max77620_config_default();
void max77620_low_battery_monitor_config(bool enable);
void max77621_config_default(u32 id, bool por);
#endif

105
bdk/power/max77812.h Normal file
View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 2020 CTCaer
*
* 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 _MAX77812_H_
#define _MAX77812_H_
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // 2 Outputs: 3-phase M1 + 1-phase M4.
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4.
#define MAX77812_REG_RSET 0x00
#define MAX77812_REG_INT_SRC 0x01
#define MAX77812_REG_INT_SRC_M 0x02
#define MAX77812_REG_TOPSYS_INT 0x03
#define MAX77812_REG_TOPSYS_INT_M 0x04
#define MAX77812_REG_TOPSYS_STAT 0x05
#define MAX77812_REG_EN_CTRL 0x06
#define MAX77812_EN_CTRL_ENABLE 1
#define MAX77812_EN_CTRL_EN_M1_SHIFT 0
#define MAX77812_EN_CTRL_EN_M1_MASK (1 << MAX77812_EN_CTRL_EN_M1_SHIFT)
#define MAX77812_EN_CTRL_EN_M2_SHIFT 2
#define MAX77812_EN_CTRL_EN_M2_MASK (1 << MAX77812_EN_CTRL_EN_M2_SHIFT)
#define MAX77812_EN_CTRL_EN_M3_SHIFT 4
#define MAX77812_EN_CTRL_EN_M3_MASK (1 << MAX77812_EN_CTRL_EN_M3_SHIFT)
#define MAX77812_EN_CTRL_EN_M4_SHIFT 6
#define MAX77812_EN_CTRL_EN_M4_MASK (1 << MAX77812_EN_CTRL_EN_M4_SHIFT)
#define MAX77812_REG_STUP_DLY2 0x07
#define MAX77812_REG_STUP_DLY3 0x08
#define MAX77812_REG_STUP_DLY4 0x09
#define MAX77812_REG_SHDN_DLY1 0x0A
#define MAX77812_REG_SHDN_DLY2 0x0B
#define MAX77812_REG_SHDN_DLY3 0x0C
#define MAX77812_REG_SHDN_DLY4 0x0D
#define MAX77812_REG_WDTRSTB_DEB 0x0E
#define MAX77812_REG_GPI_FUNC 0x0F
#define MAX77812_REG_GPI_DEB1 0x10
#define MAX77812_REG_GPI_DEB2 0x11
#define MAX77812_REG_GPI_PD_CTRL 0x12
#define MAX77812_REG_PROT_CFG 0x13
#define MAX77812_REG_VERSION 0x14
#define MAX77812_REG_I2C_CFG 0x15
#define MAX77812_REG_BUCK_INT 0x20
#define MAX77812_REG_BUCK_INT_M 0x21
#define MAX77812_REG_BUCK_STAT 0x22
#define MAX77812_REG_M1_VOUT 0x23 // GPU.
#define MAX77812_REG_M2_VOUT 0x24
#define MAX77812_REG_M3_VOUT 0x25 // DRAM on PHASE211.
#define MAX77812_REG_M4_VOUT 0x26 // CPU.
#define MAX77812_REG_M1_VOUT_D 0x27
#define MAX77812_REG_M2_VOUT_D 0x28
#define MAX77812_REG_M3_VOUT_D 0x29
#define MAX77812_REG_M4_VOUT_D 0x2A
#define MAX77812_REG_M1_VOUT_S 0x2B
#define MAX77812_REG_M2_VOUT_S 0x2C
#define MAX77812_REG_M3_VOUT_S 0x2D
#define MAX77812_REG_M4_VOUT_S 0x2E
#define MAX77812_REG_M1_CFG 0x2F
#define MAX77812_REG_M2_CFG 0x30
#define MAX77812_REG_M3_CFG 0x31
#define MAX77812_REG_M4_CFG 0x32
#define MAX77812_REG_GLB_CFG1 0x33
#define MAX77812_REG_GLB_CFG2 0x34
#define MAX77812_REG_GLB_CFG3 0x35
/*! Protected area and settings only for MAX77812_REG_VERSION 4 */
#define MAX77812_REG_GLB_CFG4 0x36
#define MAX77812_REG_GLB_CFG5 0x37
#define MAX77812_REG_GLB_CFG6 0x38
#define MAX77812_REG_GLB_CFG7 0x39
#define MAX77812_REG_GLB_CFG8 0x3A
#define MAX77812_REG_PROT_ACCESS 0xFD
#define MAX77812_REG_MAX 0xFE
#define MAX77812_REG_EN_CTRL_MASK(n) BIT(n)
#define MAX77812_START_SLEW_RATE_MASK 0x07
#define MAX77812_SHDN_SLEW_RATE_MASK 0x70
#define MAX77812_RAMPUP_SLEW_RATE_MASK 0x07
#define MAX77812_RAMPDOWN_SLEW_RATE_MASK 0x70
#define MAX77812_SLEW_RATE_SHIFT 4
#define MAX77812_OP_ACTIVE_DISCHARGE_MASK BIT(7)
#define MAX77812_PEAK_CURRENT_LMT_MASK 0x70
#define MAX77812_SWITCH_FREQ_MASK 0x0C
#define MAX77812_FORCED_PWM_MASK BIT(1)
#define MAX77812_SLEW_RATE_CNTRL_MASK BIT(0)
#define MAX77812_START_SHD_DELAY_MASK 0x1F
#define MAX77812_VERSION_MASK 0x07
#define MAX77812_ES2_VERSION 0x04
#define MAX77812_QS_VERSION 0x05
#define MAX77812_BUCK_VOLT_MASK 0xFF
#endif

125
bdk/power/regulator_5v.c Normal file
View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/fuse.h>
#include <soc/gpio.h>
#include <soc/hw_init.h>
#include <soc/pinmux.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <utils/types.h>
static u8 reg_5v_dev = 0;
static bool usb_src = false;
void regulator_5v_enable(u8 dev)
{
// The power supply selection from battery or USB is automatic.
if (!reg_5v_dev)
{
// Fan and Rail power from battery 5V regulator.
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1;
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
// Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula.
u32 hw_type = fuse_read_hw_type();
if (hw_type == FUSE_NX_HW_TYPE_ICOSA ||
hw_type == FUSE_NX_HW_TYPE_IOWA)
{
// Fan and Rail power from USB 5V VBUS.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
}
// Enable GPIO AO IO rail for T210.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
// Make sure GPIO power is enabled.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
// Override power detect for GPIO AO IO rails.
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
usb_src = false;
}
reg_5v_dev |= dev;
}
void regulator_5v_disable(u8 dev)
{
reg_5v_dev &= ~dev;
if (!reg_5v_dev)
{
// Rail power from battery 5V regulator.
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE;
// Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula.
u32 hw_type = fuse_read_hw_type();
if (hw_type == FUSE_NX_HW_TYPE_ICOSA ||
hw_type == FUSE_NX_HW_TYPE_IOWA)
{
// Rail power from USB 5V VBUS.
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE;
usb_src = false;
}
// GPIO AO IO rails.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
}
}
bool regulator_5v_get_dev_enabled(u8 dev)
{
return (reg_5v_dev & dev);
}
void regulator_5v_usb_src_enable(bool enable)
{
// Only for Icosa/Iowa. Skip on Hoag/Aula.
u32 hw_type = fuse_read_hw_type();
if (hw_type != FUSE_NX_HW_TYPE_ICOSA &&
hw_type != FUSE_NX_HW_TYPE_IOWA)
return;
if (enable && !usb_src)
{
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_HIGH);
usb_src = true;
}
else if (!enable && usb_src)
{
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
usb_src = false;
}
}

35
bdk/power/regulator_5v.h Normal file
View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2019 CTCaer
*
* 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 _REGULATOR_5V_H_
#define _REGULATOR_5V_H_
#include <utils/types.h>
enum
{
REGULATOR_5V_FAN = BIT(0),
REGULATOR_5V_JC_R = BIT(1),
REGULATOR_5V_JC_L = BIT(2),
REGULATOR_5V_ALL = 0xFF
};
void regulator_5v_enable(u8 dev);
void regulator_5v_disable(u8 dev);
bool regulator_5v_get_dev_enabled(u8 dev);
void regulator_5v_usb_src_enable(bool enable);
#endif

147
bdk/rtc/max77620-rtc.c Normal file
View File

@@ -0,0 +1,147 @@
/*
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
*
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2019 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <rtc/max77620-rtc.h>
#include <soc/i2c.h>
#include <utils/util.h>
void max77620_rtc_get_time(rtc_time_t *time)
{
u8 val = 0;
// Update RTC regs from RTC clock.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
// Get control reg config.
val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_CONTROL_REG);
// TODO: Check for binary format also?
// Get time.
time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F;
time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F;
u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG);
time->hour = hour & 0x1F;
if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK))
time->hour = (time->hour & 0xF) + 12;
// Get day of week. 1: Monday to 7: Sunday.
time->weekday = 0;
val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_WEEKDAY_REG);
for (int i = 0; i < 8; i++)
{
time->weekday++;
if (val & 1)
break;
val >>= 1;
}
// Get date.
time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f;
time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1;
time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000;
}
void max77620_rtc_stop_alarm()
{
u8 val = 0;
// Update RTC regs from RTC clock.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
// Stop alarm for both ALARM1 and ALARM2. Horizon uses ALARM2.
for (int i = 0; i < (MAX77620_RTC_NR_TIME_REGS * 2); i++)
{
val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_SEC_REG + i);
val &= ~MAX77620_RTC_ALARM_EN_MASK;
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_SEC_REG + i, val);
}
// Update RTC clock from RTC regs.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_WRITE_UPDATE);
}
void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
{
u32 tmp, edays, year, month, day;
// Set time.
time->sec = epoch % 60;
epoch /= 60;
time->min = epoch % 60;
epoch /= 60;
time->hour = epoch % 24;
epoch /= 24;
// Calculate base date values.
tmp = (u32)(((u64)4 * epoch + 102032) / 146097 + 15);
tmp = (u32)((u64)epoch + 2442113 + tmp - (tmp >> 2));
year = (20 * tmp - 2442) / 7305;
edays = tmp - 365 * year - (year >> 2);
month = edays * 1000 / 30601;
day = edays - month * 30 - month * 601 / 1000;
// Month/Year offset.
if(month < 14)
{
year -= 4716;
month--;
}
else
{
year -= 4715;
month -= 13;
}
// Set date.
time->year = year;
time->month = month;
time->day = day;
// Set weekday.
time->weekday = 0; //! TODO.
}
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time)
{
u32 year, month, epoch;
//Year
year = time->year;
//Month of year
month = time->month;
// Month/Year offset.
if(month < 3)
{
month += 12;
year--;
}
epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days.
epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days.
epoch -= 719561; // Epoch time is 1/1/1970.
epoch *= 86400; // Days to seconds.
epoch += (3600 * time->hour) + (60 * time->min) + time->sec; // Add hours, minutes and seconds.
return epoch;
}

77
bdk/rtc/max77620-rtc.h Normal file
View File

@@ -0,0 +1,77 @@
/*
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
*
* Copyright (c) 2018 CTCaer
*
* 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 _MFD_MAX77620_RTC_H_
#define _MFD_MAX77620_RTC_H_
#include <utils/types.h>
#define MAX77620_RTC_I2C_ADDR 0x68
#define MAX77620_RTC_NR_TIME_REGS 7
#define MAX77620_RTC_CONTROLM_REG 0x02
#define MAX77620_RTC_CONTROL_REG 0x03
#define MAX77620_RTC_BIN_FORMAT BIT(0)
#define MAX77620_RTC_24H BIT(1)
#define MAX77620_RTC_UPDATE0_REG 0x04
#define MAX77620_RTC_WRITE_UPDATE BIT(0)
#define MAX77620_RTC_READ_UPDATE BIT(4)
#define MAX77620_RTC_SEC_REG 0x07
#define MAX77620_RTC_MIN_REG 0x08
#define MAX77620_RTC_HOUR_REG 0x09
#define MAX77620_RTC_HOUR_PM_MASK BIT(6)
#define MAX77620_RTC_WEEKDAY_REG 0x0A
#define MAX77620_RTC_MONTH_REG 0x0B
#define MAX77620_RTC_YEAR_REG 0x0C
#define MAX77620_RTC_DATE_REG 0x0D
#define MAX77620_ALARM1_SEC_REG 0x0E
#define MAX77620_ALARM1_MIN_REG 0x0F
#define MAX77620_ALARM1_HOUR_REG 0x10
#define MAX77620_ALARM1_WEEKDAY_REG 0x11
#define MAX77620_ALARM1_MONTH_REG 0x12
#define MAX77620_ALARM1_YEAR_REG 0x13
#define MAX77620_ALARM1_DATE_REG 0x14
#define MAX77620_ALARM2_SEC_REG 0x15
#define MAX77620_ALARM2_MIN_REG 0x16
#define MAX77620_ALARM2_HOUR_REG 0x17
#define MAX77620_ALARM2_WEEKDAY_REG 0x18
#define MAX77620_ALARM2_MONTH_REG 0x19
#define MAX77620_ALARM2_YEAR_REG 0x1A
#define MAX77620_ALARM2_DATE_REG 0x1B
#define MAX77620_RTC_ALARM_EN_MASK BIT(7)
typedef struct _rtc_time_t {
u8 weekday;
u8 sec;
u8 min;
u8 hour;
u8 day;
u8 month;
u16 year;
} rtc_time_t;
void max77620_rtc_get_time(rtc_time_t *time);
void max77620_rtc_stop_alarm();
void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time);
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time);
#endif /* _MFD_MAX77620_RTC_H_ */

776
bdk/sec/se.c Normal file
View File

@@ -0,0 +1,776 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 Atmosphère-NX
* Copyright (c) 2019-2021 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "se.h"
#include "se_t210.h"
#include <memory_map.h>
#include <mem/heap.h>
#include <soc/bpmp.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <utils/util.h>
typedef struct _se_ll_t
{
vu32 num;
vu32 addr;
vu32 size;
} se_ll_t;
static u32 _se_rsa_mod_sizes[SE_RSA_KEYSLOT_COUNT];
static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT];
static void _gf256_mul_x(void *block)
{
u8 *pdata = (u8 *)block;
u32 carry = 0;
for (int i = 0xF; i >= 0; i--)
{
u8 b = pdata[i];
pdata[i] = (b << 1) | carry;
carry = b >> 7;
}
if (carry)
pdata[0xF] ^= 0x87;
}
static void _gf256_mul_x_le(void *block)
{
u32 *pdata = (u32 *)block;
u32 carry = 0;
for (u32 i = 0; i < 4; i++)
{
u32 b = pdata[i];
pdata[i] = (b << 1) | carry;
carry = b >> 31;
}
if (carry)
pdata[0x0] ^= 0x87;
}
static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size)
{
ll->num = 0;
ll->addr = addr;
ll->size = size;
}
static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
{
SE(SE_IN_LL_ADDR_REG) = (u32)src;
SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
}
static int _se_wait()
{
while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE))
;
if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
(SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
SE(SE_ERR_STATUS_REG) != 0)
return 0;
return 1;
}
se_ll_t *ll_dst, *ll_src;
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot)
{
ll_dst = NULL;
ll_src = NULL;
if (dst)
{
ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t));
_se_ll_init(ll_dst, (u32)dst, dst_size);
}
if (src)
{
ll_src = (se_ll_t *)malloc(sizeof(se_ll_t));
_se_ll_init(ll_src, (u32)src, src_size);
}
_se_ll_set(ll_dst, ll_src);
SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
SE(SE_OPERATION_REG) = op;
if (is_oneshot)
{
int res = _se_wait();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
if (src)
free(ll_src);
if (dst)
free(ll_dst);
return res;
}
return 1;
}
static int _se_execute_finalize()
{
int res = _se_wait();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
if (ll_src)
{
free(ll_src);
ll_src = NULL;
}
if (ll_dst)
{
free(ll_dst);
ll_dst = NULL;
}
return res;
}
static int _se_execute_oneshot(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
{
return _se_execute(op, dst, dst_size, src, src_size, true);
}
static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (!src || !dst)
return 0;
u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
memset(block, 0, SE_AES_BLOCK_SIZE);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
memcpy(block, src, src_size);
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
memcpy(dst, block, dst_size);
free(block);
return res;
}
static void _se_aes_ctr_set(const void *ctr)
{
u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, ctr, SE_AES_IV_SIZE);
for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
}
void se_rsa_acc_ctrl(u32 rs, u32 flags)
{
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
(((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
if (flags & SE_RSA_KEY_LOCK_FLAG)
SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
}
// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot
void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size)
{
u32 *data = (u32 *)mod;
for (u32 i = 0; i < mod_size / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[mod_size / 4 - i - 1]);
}
data = (u32 *)exp;
for (u32 i = 0; i < exp_size / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[exp_size / 4 - i - 1]);
}
_se_rsa_mod_sizes[ks] = mod_size;
_se_rsa_exp_sizes[ks] = exp_size;
}
// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot
void se_rsa_key_clear(u32 ks)
{
for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
}
for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
}
}
// se_rsa_exp_mod() was derived from Atmosphère's se_synchronous_exp_mod and se_get_exp_mod_output
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
{
int res;
u8 stack_buf[SE_RSA2048_DIGEST_SIZE];
for (u32 i = 0; i < src_size; i++)
stack_buf[i] = *((u8 *)src + src_size - i - 1);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG);
SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks);
SE(SE_RSA_KEY_SIZE_REG) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
SE(SE_RSA_EXP_SIZE_REG) = _se_rsa_exp_sizes[ks] >> 2;
res = _se_execute_oneshot(SE_OP_START, NULL, 0, stack_buf, src_size);
// Copy output hash.
u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < dst_size / 4; i++)
dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i * 4)));
return res;
}
void se_key_acc_ctrl(u32 ks, u32 flags)
{
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
if (flags & SE_KEY_LOCK_FLAG)
SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks);
}
u32 se_key_acc_ctrl_get(u32 ks)
{
return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
}
void se_aes_key_set(u32 ks, const void *key, u32 size)
{
u32 data[SE_AES_MAX_KEY_SIZE / 4];
memcpy(data, key, size);
for (u32 i = 0; i < (size / 4); i++)
{
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
}
}
void se_aes_key_partial_set(u32 ks, u32 index, u32 data)
{
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | index;
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data;
}
void se_aes_iv_set(u32 ks, const void *iv)
{
u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, iv, SE_AES_IV_SIZE);
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
{
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
}
}
void se_aes_key_get(u32 ks, void *key, u32 size)
{
u32 data[SE_AES_MAX_KEY_SIZE / 4];
for (u32 i = 0; i < (size / 4); i++)
{
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
}
memcpy(key, data, size);
}
void se_aes_key_clear(u32 ks)
{
for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / 4); i++)
{
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
}
}
void se_aes_iv_clear(u32 ks)
{
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
{
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
}
}
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
{
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
return _se_execute_oneshot(SE_OP_START, NULL, 0, input, SE_KEY_128_SIZE);
}
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (enc)
{
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
}
else
{
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
}
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
}
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (enc)
{
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
}
else
{
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
}
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
}
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
{
return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
}
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, const void *ctr)
{
SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
_se_aes_ctr_set(ctr);
u32 src_size_aligned = ALIGN_DOWN(src_size, 0x10);
u32 src_size_delta = src_size & 0xF;
if (src_size_aligned)
{
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
return 0;
}
if (src_size - src_size_aligned && src_size_aligned < dst_size)
return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
MIN(src_size_delta, dst_size - src_size_aligned),
src + src_size_aligned, src_size_delta);
return 1;
}
// random calls were derived from Atmosphère's
int se_initialize_rng()
{
static bool initialized = false;
if (initialized)
return 1;
u8 *output_buf = (u8 *)malloc(0x10);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_RNG_RESEED_INTERVAL_REG) = 70001;
SE(SE_RNG_SRC_CONFIG_REG) = SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) |
SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
int res =_se_execute_oneshot(SE_OP_START, output_buf, 0x10, NULL, 0);
free(output_buf);
if (res)
initialized = true;
return res;
}
int se_generate_random(void *dst, u32 size)
{
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
u32 num_blocks = size >> 4;
u32 aligned_size = num_blocks << 4;
if (num_blocks)
{
SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 1;
if (!_se_execute_oneshot(SE_OP_START, dst, aligned_size, NULL, 0))
return 0;
}
if (size > aligned_size)
return _se_execute_one_block(SE_OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
return 1;
}
int se_generate_random_key(u32 ks_dst, u32 ks_src)
{
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst);
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0;
return 1;
}
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size)
{
u8 tweak[0x10];
u8 orig_tweak[0x10];
u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
//Generate tweak.
for (int i = 0xF; i >= 0; i--)
{
tweak[i] = sec & 0xFF;
sec >>= 8;
}
if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak))
return 0;
memcpy(orig_tweak, tweak, 0x10);
// We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < sec_size / 0x10; i++)
{
for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
psrc += 4;
pdst += 4;
}
if (!se_aes_crypt_ecb(crypt_ks, enc, dst, sec_size, dst, sec_size))
return 0;
pdst = (u32 *)dst;
ptweak = (u32 *)orig_tweak;
for (u32 i = 0; i < sec_size / 0x10; i++)
{
for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(orig_tweak);
pdst += 4;
}
return 1;
}
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs)
{
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
for (u32 i = 0; i < num_secs; i++)
if (!se_aes_xts_crypt_sec(tweak_ks, crypt_ks, enc, sec + i, pdst + sec_size * i, psrc + sec_size * i, sec_size))
return 0;
return 1;
}
// se_aes_cmac() was derived from Atmosphère's se_compute_aes_cmac
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
{
int res = 0;
u8 *key = (u8 *)calloc(0x10, 1);
u8 *last_block = (u8 *)calloc(0x10, 1);
// generate derived key
if (!se_aes_crypt_block_ecb(ks, ENCRYPT, key, key))
goto out;
_gf256_mul_x(key);
if (src_size & 0xF)
_gf256_mul_x(key);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
se_aes_iv_clear(ks);
u32 num_blocks = (src_size + 0xf) >> 4;
if (num_blocks > 1)
{
SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 2;
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, src_size))
goto out;
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
}
if (src_size & 0xf)
{
memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf);
last_block[src_size & 0xf] = 0x80;
}
else if (src_size >= 0x10)
{
memcpy(last_block, src + src_size - 0x10, 0x10);
}
for (u32 i = 0; i < 0x10; i++)
last_block[i] ^= key[i];
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, 0x10);
u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < (dst_size >> 2); i++)
dst32[i] = SE(SE_HASH_RESULT_REG + (i << 2));
out:;
free(key);
free(last_block);
return res;
}
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
{
int res;
u32 hash32[SE_SHA_256_SIZE / 4];
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0;
// Setup config for SHA256.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_SHA_CONFIG_REG) = sha_cfg;
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
// Set total size to current buffer size if empty.
if (!total_size)
total_size = src_size;
// Set total size: BITS(src_size), up to 2 EB.
SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
// Set size left to hash.
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
// If we hash in chunks, copy over the intermediate.
if (sha_cfg == SHA_CONTINUE && msg_left)
{
// Restore message left to process.
SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
// Restore hash reg.
memcpy(hash32, hash, SE_SHA_256_SIZE);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
}
// Trigger the operation.
res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
if (is_oneshot)
{
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
}
// Copy output hash.
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, SE_SHA_256_SIZE);
}
return res;
}
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
{
return se_calc_sha256(hash, NULL, src, src_size, 0, SHA_INIT_HASH, true);
}
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
{
u32 hash32[SE_SHA_256_SIZE / 4];
int res = _se_execute_finalize();
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
}
// Copy output hash.
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, SE_SHA_256_SIZE);
return res;
}
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size)
{
int res = 0;
u8 *secret = (u8 *)malloc(0x40);
u8 *ipad = (u8 *)malloc(0x40 + src_size);
u8 *opad = (u8 *)malloc(0x60);
if (key_size > 0x40)
{
if (!se_calc_sha256_oneshot(secret, key, key_size))
goto out;
memset(secret + 0x20, 0, 0x20);
}
else
{
memcpy(secret, key, key_size);
memset(secret + key_size, 0, 0x40 - key_size);
}
u32 *secret32 = (u32 *)secret;
u32 *ipad32 = (u32 *)ipad;
u32 *opad32 = (u32 *)opad;
for (u32 i = 0; i < 0x10; i++)
{
ipad32[i] = secret32[i] ^ 0x36363636;
opad32[i] = secret32[i] ^ 0x5C5C5C5C;
}
memcpy(ipad + 0x40, src, src_size);
if (!se_calc_sha256_oneshot(dst, ipad, 0x40 + src_size))
goto out;
memcpy(opad + 0x40, dst, 0x20);
if (!se_calc_sha256_oneshot(dst, opad, 0x60))
goto out;
res = 1;
out:;
free(secret);
free(ipad);
free(opad);
return res;
}
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
{
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
// Set Secure Random Key.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
// Save AES keys.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++)
{
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
if (keysize > SE_KEY_128_SIZE)
{
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
}
}
// Save SRK to PMC secure scratches.
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// End context save.
SE(SE_CONFIG_REG) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// Get SRK.
u32 srk[4];
srk[0] = PMC(APBDEV_PMC_SECURE_SCRATCH4);
srk[1] = PMC(APBDEV_PMC_SECURE_SCRATCH5);
srk[2] = PMC(APBDEV_PMC_SECURE_SCRATCH6);
srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7);
// Decrypt context.
se_aes_key_clear(3);
se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, DECRYPT, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3);
}

53
bdk/sec/se.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2021 CTCaer
* Copyright (c) 2019-2021 shchmue
*
* 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 _SE_H_
#define _SE_H_
#include <utils/types.h>
void se_rsa_acc_ctrl(u32 rs, u32 flags);
void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size);
void se_rsa_key_clear(u32 ks);
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
void se_key_acc_ctrl(u32 ks, u32 flags);
u32 se_key_acc_ctrl_get(u32 ks);
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
void se_aes_key_set(u32 ks, const void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv);
void se_aes_key_partial_set(u32 ks, u32 index, u32 data);
void se_aes_key_get(u32 ks, void *key, u32 size);
void se_aes_key_clear(u32 ks);
void se_aes_iv_clear(u32 ks);
int se_initialize_rng();
int se_generate_random(void *dst, u32 size);
int se_generate_random_key(u32 ks_dst, u32 ks_src);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, const void *ctr);
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size);
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs);
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
#endif

326
bdk/sec/se_t210.h Normal file
View File

@@ -0,0 +1,326 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* 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 _SE_T210_H
#define _SE_T210_H
#include <utils/types.h>
#define SE_CRYPTO_QUEUE_LENGTH 50
#define SE_MAX_SRC_SG_COUNT 50
#define SE_MAX_DST_SG_COUNT 50
#define SE_AES_KEYSLOT_COUNT 16
#define SE_RSA_KEYSLOT_COUNT 2
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
#define SE_AES_BLOCK_SIZE 16
#define SE_AES_IV_SIZE 16
#define SE_AES_MIN_KEY_SIZE 16
#define SE_AES_MAX_KEY_SIZE 32
#define SE_KEY_128_SIZE 16
#define SE_KEY_192_SIZE 24
#define SE_KEY_256_SIZE 32
#define SE_SHA_192_SIZE 24
#define SE_SHA_256_SIZE 32
#define SE_SHA_384_SIZE 48
#define SE_SHA_512_SIZE 64
#define SE_RNG_IV_SIZE 16
#define SE_RNG_DT_SIZE 16
#define SE_RNG_KEY_SIZE 16
#define SE_RNG_SEED_SIZE (SE_RNG_IV_SIZE + SE_RNG_KEY_SIZE + SE_RNG_DT_SIZE)
#define SE_AES_CMAC_DIGEST_SIZE 16
#define SE_RSA512_DIGEST_SIZE 64
#define SE_RSA1024_DIGEST_SIZE 128
#define SE_RSA1536_DIGEST_SIZE 192
#define SE_RSA2048_DIGEST_SIZE 256
#define DECRYPT 0
#define ENCRYPT 1
/* SE register definitions */
#define SE_SE_SECURITY_REG 0x000
#define SE_HARD_SETTING BIT(0)
#define SE_ENG_DIS BIT(1)
#define SE_PERKEY_SETTING BIT(2)
#define SE_SOFT_SETTING BIT(16)
#define SE_TZRAM_SECURITY_REG 0x004
#define SE_TZRAM_HARD_SETTING BIT(0)
#define SE_TZRAM_ENG_DIS BIT(1)
#define SE_OPERATION_REG 0x008
#define SE_OP_ABORT 0
#define SE_OP_START 1
#define SE_OP_RESTART_OUT 2
#define SE_OP_CTX_SAVE 3
#define SE_OP_RESTART_IN 4
#define SE_INT_ENABLE_REG 0x00C
#define SE_INT_STATUS_REG 0x010
#define SE_INT_IN_LL_BUF_RD BIT(0)
#define SE_INT_IN_DONE BIT(1)
#define SE_INT_OUT_LL_BUF_WR BIT(2)
#define SE_INT_OUT_DONE BIT(3)
#define SE_INT_OP_DONE BIT(4)
#define SE_INT_RESEED_NEEDED BIT(5)
#define SE_INT_ERR_STAT BIT(16)
#define SE_CONFIG_REG 0x014
#define DST_MEMORY 0
#define DST_HASHREG 1
#define DST_KEYTABLE 2
#define DST_SRK 3
#define DST_RSAREG 4
#define SE_CONFIG_DST(x) ((x) << 2)
#define ALG_NOP 0
#define ALG_AES_DEC 1
#define SE_CONFIG_DEC_ALG(x) ((x) << 8)
#define ALG_NOP 0
#define ALG_AES_ENC 1
#define ALG_RNG 2
#define ALG_SHA 3
#define ALG_RSA 4
#define SE_CONFIG_ENC_ALG(x) ((x) << 12)
#define MODE_KEY128 0
#define MODE_KEY192 1
#define MODE_KEY256 2
#define MODE_SHA1 0
#define MODE_SHA224 4
#define MODE_SHA256 5
#define MODE_SHA384 6
#define MODE_SHA512 7
#define SE_CONFIG_DEC_MODE(x) ((x) << 16)
#define SE_CONFIG_ENC_MODE(x) ((x) << 24)
#define SE_IN_LL_ADDR_REG 0x018
#define SE_IN_CUR_BYTE_ADDR_REG 0x01C
#define SE_IN_CUR_LL_ID_REG 0x020
#define SE_OUT_LL_ADDR_REG 0x024
#define SE_OUT_CUR_BYTE_ADDR_REG 0x028
#define SE_OUT_CUR_LL_ID_REG 0x02C
#define SE_HASH_RESULT_REG 0x030
#define SE_HASH_RESULT_REG_COUNT 16
#define SE_CONTEXT_SAVE_CONFIG_REG 0x070
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_CONTEXT_AES_WORD_QUAD(x) ((x) << 0)
#define SE_CONTEXT_AES_KEY_INDEX(x) ((x) << 8)
#define KEYS_0_3 0
#define KEYS_4_7 1
#define KEYS_8_11 2
#define KEYS_12_15 3
#define SE_CONTEXT_RSA_WORD_QUAD(x) ((x) << 12)
#define SLOT0_EXPONENT 0
#define SLOT0_MODULUS 1
#define SLOT1_EXPONENT 2
#define SLOT1_MODULUS 3
#define SE_CONTEXT_RSA_KEY_INDEX(x) ((x) << 16)
#define STICKY_0_3 0
#define STICKY_4_7 1
#define SE_CONTEXT_STICKY_WORD_QUAD(x) ((x) << 24)
#define STICKY_BITS 0
#define RSA_KEYTABLE 1
#define AES_KEYTABLE 2
#define MEM 4
#define SRK 6
#define SE_CONTEXT_SRC(x) ((x) << 29)
#define SE_CTX_SAVE_AUTO_T210B01_REG 0x074
#define SE_CTX_SAVE_AUTO_ENABLE BIT(0)
#define SE_CTX_SAVE_AUTO_LOCK BIT(8)
#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
#define SE_CRYPTO_LAST_BLOCK 0x080
#define SE_SHA_CONFIG_REG 0x200
#define SHA_CONTINUE 0
#define SHA_INIT_HASH 1
#define SE_SHA_MSG_LENGTH_0_REG 0x204
#define SE_SHA_MSG_LENGTH_1_REG 0x208
#define SE_SHA_MSG_LENGTH_2_REG 0x20C
#define SE_SHA_MSG_LENGTH_3_REG 0x210
#define SE_SHA_MSG_LEFT_0_REG 0x214
#define SE_SHA_MSG_LEFT_1_REG 0x218
#define SE_SHA_MSG_LEFT_2_REG 0x21C
#define SE_SHA_MSG_LEFT_3_REG 0x220
#define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
#define SE_KEY_LOCK_FLAG 0x80
#define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
#define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_CRYPTO_CONFIG_REG 0x304
#define HASH_DISABLE 0
#define HASH_ENABLE 1
#define SE_CRYPTO_HASH(x) ((x) << 0)
#define XOR_BYPASS 0
#define XOR_TOP 2
#define XOR_BOTTOM 3
#define SE_CRYPTO_XOR_POS(x) ((x) << 1)
#define INPUT_MEMORY 0
#define INPUT_RANDOM 1
#define INPUT_AESOUT 2
#define INPUT_LNR_CTR 3
#define SE_CRYPTO_INPUT_SEL(x) ((x) << 3)
#define VCTRAM_MEM 0
#define VCTRAM_AESOUT 2
#define VCTRAM_PREVMEM 3
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << 5)
#define IV_ORIGINAL 0
#define IV_UPDATED 1
#define SE_CRYPTO_IV_SEL(x) ((x) << 7)
#define CORE_DECRYPT 0
#define CORE_ENCRYPT 1
#define SE_CRYPTO_CORE_SEL(x) ((x) << 8)
#define SE_CRYPTO_KEYSCH_BYPASS BIT(10)
#define SE_CRYPTO_CTR_CNTN(x) ((x) << 11)
#define SE_CRYPTO_KEY_INDEX(x) ((x) << 24)
#define MEMIF_AHB 0
#define MEMIF_MCCIF 1
#define SE_CRYPTO_MEMIF(x) ((x) << 31)
#define SE_CRYPTO_LINEAR_CTR_REG 0x308
#define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
#define SE_CRYPTO_BLOCK_COUNT_REG 0x318
#define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
#define SE_KEYTABLE_PKT(x) ((x) << 0)
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_KEYTABLE_QUAD(x) ((x) << 2)
#define SE_KEYTABLE_SLOT(x) ((x) << 4)
#define SE_CRYPTO_KEYTABLE_DATA_REG 0x320
#define SE_CRYPTO_KEYTABLE_DST_REG 0x330
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_KEYTABLE_DST_WORD_QUAD(x) ((x) << 0)
#define SE_KEYTABLE_DST_KEY_INDEX(x) ((x) << 8)
#define SE_RNG_CONFIG_REG 0x340
#define MODE_NORMAL 0
#define MODE_FORCE_INSTANTION 1
#define MODE_FORCE_RESEED 2
#define SE_RNG_CONFIG_MODE(x) ((x) << 0)
#define SRC_NONE 0
#define SRC_ENTROPY 1
#define SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << 2)
#define SE_RNG_SRC_CONFIG_REG 0x344
#define RO_ENTR_LOCK_DISABLE 0
#define RO_ENTR_LOCK_ENABLE 1
#define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
#define RO_ENTR_DISABLE 0
#define RO_ENTR_ENABLE 1
#define SE_RNG_SRC_CONFIG_ENTR_SRC(x) ((x) << 1)
#define RO_HW_DIS_CYA_DISABLE 0
#define RO_HW_DIS_CYA_ENABLE 1
#define SE_RNG_SRC_CONFIG_HW_DIS_CYA(x) ((x) << 2)
#define SE_RNG_SRC_CONFIG_ENTR_SUBSMPL(x) ((x) << 4)
#define SE_RNG_SRC_CONFIG_ENTR_DATA_FLUSH BIT(8)
#define SE_RNG_RESEED_INTERVAL_REG 0x348
#define SE_RSA_CONFIG 0x400
#define RSA_KEY_SLOT_ONE 0
#define RSA_KEY_SLOT_TW0 1
#define RSA_KEY_SLOT(x) ((x) << 24)
#define SE_RSA_KEY_SIZE_REG 0x404
#define RSA_KEY_WIDTH_512 0
#define RSA_KEY_WIDTH_1024 1
#define RSA_KEY_WIDTH_1536 2
#define RSA_KEY_WIDTH_2048 3
#define SE_RSA_EXP_SIZE_REG 0x408
#define SE_RSA_SECURITY_PERKEY_REG 0x40C
#define SE_RSA_KEY_LOCK_FLAG 0x80
#define SE_RSA_KEYTABLE_ACCESS_REG 0x410
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG | SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG)
#define SE_RSA_KEYTABLE_ADDR_REG 0x420
#define SE_RSA_KEYTABLE_PKT(x) ((x) << 0)
#define RSA_KEY_TYPE_EXP 0
#define RSA_KEY_TYPE_MOD 1
#define SE_RSA_KEYTABLE_TYPE(x) ((x) << 6)
#define RSA_KEY_NUM(x) ((x) << 7)
#define RSA_KEY_INPUT_MODE_REG 0
#define RSA_KEY_INPUT_MODE_DMA 1
#define SE_RSA_KEYTABLE_INPUT_MODE(x) ((x) << 8)
#define RSA_KEY_READ 0
#define RSA_KEY_WRITE 1
#define SE_RSA_KEY_OP(x) ((x) << 10)
#define SE_RSA_KEYTABLE_DATA_REG 0x424
#define SE_RSA_OUTPUT_REG 0x428
#define SE_RSA_OUTPUT_REG_COUNT 64
#define SE_STATUS_REG 0x800
#define SE_STATUS_STATE_IDLE 0
#define SE_STATUS_STATE_BUSY 1
#define SE_STATUS_STATE_WAIT_OUT 2
#define SE_STATUS_STATE_WAIT_IN 3
#define SE_STATUS_STATE_MASK 3
#define SE_ERR_STATUS_REG 0x804
#define SE_ERR_STATUS_SE_NS_ACCESS BIT(0)
#define SE_ERR_STATUS_BUSY_REG_WR BIT(1)
#define SE_ERR_STATUS_DST BIT(2)
#define SE_ERR_STATUS_SRK_USAGE_LIMIT BIT(3)
#define SE_ERR_STATUS_TZRAM_NS_ACCESS BIT(24)
#define SE_ERR_STATUS_TZRAM_ADDRESS BIT(25)
#define SE_MISC_REG 0x808
#define SE_ENTROPY_NEXT_192BIT BIT(0)
#define SE_ENTROPY_VN_BYPASS BIT(1)
#define SE_CLK_OVR_ON BIT(2)
#define SE_SPARE_REG 0x80C
#define SE_ERRATA_FIX_DISABLE 0
#define SE_ERRATA_FIX_ENABLE 1
#define SE_ECO(x) ((x) << 0)
#endif

309
bdk/sec/tsec.c Normal file
View File

@@ -0,0 +1,309 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "tsec.h"
#include "tsec_t210.h"
#include <sec/se_t210.h>
#include <soc/bpmp.h>
#include <soc/clock.h>
#include <soc/kfuse.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <mem/heap.h>
#include <mem/mc.h>
#include <mem/smmu.h>
#include <utils/util.h>
// #include <gfx_utils.h>
#define PKG11_MAGIC 0x31314B50
#define TSEC_HOS_KB_620 6
static int _tsec_dma_wait_idle()
{
u32 timeout = get_tmr_ms() + 10000;
while (!(TSEC(TSEC_DMATRFCMD) & TSEC_DMATRFCMD_IDLE))
if (get_tmr_ms() > timeout)
return 0;
return 1;
}
static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offset)
{
u32 cmd;
if (not_imem)
cmd = TSEC_DMATRFCMD_SIZE_256B; // DMA 256 bytes
else
cmd = TSEC_DMATRFCMD_IMEM; // DMA IMEM (Instruction memmory)
TSEC(TSEC_DMATRFMOFFS) = i_offset;
TSEC(TSEC_DMATRFFBOFFS) = pa_offset;
TSEC(TSEC_DMATRFCMD) = cmd;
return _tsec_dma_wait_idle();
}
int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
{
int res = 0;
u8 *fwbuf = NULL;
u32 type = tsec_ctxt->type;
u32 *pdir, *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
u32 *pkg11_magic_off;
bpmp_mmu_disable();
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
// Enable clocks.
clock_enable_host1x();
usleep(2);
clock_enable_tsec();
clock_enable_sor_safe();
clock_enable_sor0();
clock_enable_sor1();
clock_enable_kfuse();
kfuse_wait_ready();
if (type == TSEC_FW_TYPE_NEW)
{
// Disable all CCPLEX core rails.
pmc_enable_partition(POWER_RAIL_CE0, DISABLE);
pmc_enable_partition(POWER_RAIL_CE1, DISABLE);
pmc_enable_partition(POWER_RAIL_CE2, DISABLE);
pmc_enable_partition(POWER_RAIL_CE3, DISABLE);
// Enable AHB aperture and set it to full mmio.
mc_enable_ahb_redirect(true);
}
// Configure Falcon.
TSEC(TSEC_DMACTL) = 0;
TSEC(TSEC_IRQMSET) =
TSEC_IRQMSET_EXT(0xFF) |
TSEC_IRQMSET_WDTMR |
TSEC_IRQMSET_HALT |
TSEC_IRQMSET_EXTERR |
TSEC_IRQMSET_SWGEN0 |
TSEC_IRQMSET_SWGEN1;
TSEC(TSEC_IRQDEST) =
TSEC_IRQDEST_EXT(0xFF) |
TSEC_IRQDEST_HALT |
TSEC_IRQDEST_EXTERR |
TSEC_IRQDEST_SWGEN0 |
TSEC_IRQDEST_SWGEN1;
TSEC(TSEC_ITFEN) = TSEC_ITFEN_CTXEN | TSEC_ITFEN_MTHDEN;
if (!_tsec_dma_wait_idle())
{
res = -1;
goto out;
}
// Load firmware or emulate memio environment for newer TSEC fw.
if (type == TSEC_FW_TYPE_EMU)
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
else
{
fwbuf = (u8 *)malloc(SZ_16K);
u8 *fwbuf_aligned = (u8 *)ALIGN((u32)fwbuf, 0x100);
memcpy(fwbuf_aligned, tsec_ctxt->fw, tsec_ctxt->size);
TSEC(TSEC_DMATRFBASE) = (u32)fwbuf_aligned >> 8;
}
for (u32 addr = 0; addr < tsec_ctxt->size; addr += 0x100)
{
if (!_tsec_dma_pa_to_internal_100(false, addr, addr))
{
res = -2;
goto out_free;
}
}
if (type == TSEC_FW_TYPE_EMU)
{
// Init SMMU translation for TSEC.
pdir = smmu_init_for_tsec();
smmu_init(tsec_ctxt->secmon_base);
// Enable SMMU
if (!smmu_is_used())
smmu_enable();
// Clock reset controller.
car = page_alloc(1);
memcpy(car, (void *)CLOCK_BASE, SZ_PAGE);
car[CLK_RST_CONTROLLER_CLK_SOURCE_TSEC / 4] = 2;
smmu_map(pdir, CLOCK_BASE, (u32)car, 1, _WRITABLE | _READABLE | _NONSECURE);
// Fuse driver.
fuse = page_alloc(1);
memcpy((void *)&fuse[0x800/4], (void *)FUSE_BASE, SZ_1K);
fuse[0x82C / 4] = 0;
fuse[0x9E0 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
fuse[0x9E4 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
smmu_map(pdir, (FUSE_BASE - 0x800), (u32)fuse, 1, _READABLE | _NONSECURE);
// Power management controller.
pmc = page_alloc(1);
smmu_map(pdir, RTC_BASE, (u32)pmc, 1, _READABLE | _NONSECURE);
// Flow control.
flowctrl = page_alloc(1);
smmu_map(pdir, FLOW_CTLR_BASE, (u32)flowctrl, 1, _WRITABLE | _NONSECURE);
// Security engine.
se = page_alloc(1);
memcpy(se, (void *)SE_BASE, SZ_PAGE);
smmu_map(pdir, SE_BASE, (u32)se, 1, _READABLE | _WRITABLE | _NONSECURE);
// Memory controller.
mc = page_alloc(1);
memcpy(mc, (void *)MC_BASE, SZ_PAGE);
mc[MC_IRAM_BOM / 4] = 0;
mc[MC_IRAM_TOM / 4] = 0x80000000;
smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE);
// IRAM
iram = page_alloc(0x30);
memcpy(iram, tsec_ctxt->pkg1, 0x30000);
// PKG1.1 magic offset.
pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4));
smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
// Exception vectors
evec = page_alloc(1);
smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE);
}
// Execute firmware.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
TSEC(TSEC_STATUS) = 0;
TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1.
TSEC(TSEC_BOOTVEC) = 0;
TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU;
if (type == TSEC_FW_TYPE_EMU)
{
u32 start = get_tmr_us();
u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
u32 key[16] = {0};
u32 kidx = 0;
while (*pkg11_magic_off != PKG11_MAGIC)
{
smmu_flush_all();
if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
{
k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
key[kidx++] = k;
}
// Failsafe.
if ((u32)get_tmr_us() - start > 125000)
break;
}
if (kidx != 8)
{
res = -6;
smmu_deinit_for_tsec();
goto out_free;
}
// Give some extra time to make sure PKG1.1 is decrypted.
msleep(50);
memcpy(tsec_keys, &key, 0x20);
memcpy(tsec_ctxt->pkg1, iram, 0x30000);
smmu_deinit_for_tsec();
// for (int i = 0; i < kidx; i++)
// gfx_printf("key %08X\n", key[i]);
// gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_STATUS));
// u32 errst = MC(MC_ERR_STATUS);
// gfx_printf(" MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR));
// gfx_printf(" type: %02X\n", errst >> 28);
// gfx_printf(" smmu: %02X\n", (errst >> 25) & 3);
// gfx_printf(" dir: %s\n", (errst >> 16) & 1 ? "W" : "R");
// gfx_printf(" cid: %02x\n", errst & 0xFF);
}
else
{
if (!_tsec_dma_wait_idle())
{
res = -3;
goto out_free;
}
u32 timeout = get_tmr_ms() + 2000;
while (!TSEC(TSEC_STATUS))
if (get_tmr_ms() > timeout)
{
res = -4;
goto out_free;
}
if (TSEC(TSEC_STATUS) != 0xB0B0B0B0)
{
res = -5;
goto out_free;
}
// Fetch result.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
u32 buf[4];
buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB);
buf[1] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB);
buf[2] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB);
buf[3] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB);
SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
}
out_free:;
free(fwbuf);
out:;
// Disable clocks.
clock_disable_kfuse();
clock_disable_sor1();
clock_disable_sor0();
clock_disable_sor_safe();
clock_disable_tsec();
bpmp_mmu_enable();
bpmp_clk_rate_set(prev_fid);
// Disable AHB aperture.
if (type == TSEC_FW_TYPE_NEW)
mc_disable_ahb_redirect();
return res;
}

43
bdk/sec/tsec.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* 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 _TSEC_H_
#define _TSEC_H_
#include <utils/types.h>
enum tsec_fw_type
{
// Retail Hovi Keygen.
TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0.
TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated enviroment.
TSEC_FW_TYPE_NEW = 2, // 7.0.0+.
};
typedef struct _tsec_ctxt_t
{
const void *fw;
u32 size;
u32 type;
void *pkg1;
u32 pkg11_off;
u32 secmon_base;
} tsec_ctxt_t;
int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt);
#endif

50
bdk/sec/tsec_t210.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2018 CTCaer
*
* 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 _TSEC_T210_H_
#define _TSEC_T210_H_
#define TSEC_BOOTKEYVER 0x1040
#define TSEC_STATUS 0x1044
#define TSEC_ITFEN 0x1048
#define TSEC_ITFEN_CTXEN BIT(0)
#define TSEC_ITFEN_MTHDEN BIT(1)
#define TSEC_IRQMSET 0x1010
#define TSEC_IRQMSET_WDTMR BIT(1)
#define TSEC_IRQMSET_HALT BIT(4)
#define TSEC_IRQMSET_EXTERR BIT(5)
#define TSEC_IRQMSET_SWGEN0 BIT(6)
#define TSEC_IRQMSET_SWGEN1 BIT(7)
#define TSEC_IRQMSET_EXT(val) (((val) & 0xFF) << 8)
#define TSEC_IRQDEST 0x101C
#define TSEC_IRQDEST_HALT BIT(4)
#define TSEC_IRQDEST_EXTERR BIT(5)
#define TSEC_IRQDEST_SWGEN0 BIT(6)
#define TSEC_IRQDEST_SWGEN1 BIT(7)
#define TSEC_IRQDEST_EXT(val) (((val) & 0xFF) << 8)
#define TSEC_CPUCTL 0x1100
#define TSEC_CPUCTL_STARTCPU BIT(1)
#define TSEC_BOOTVEC 0x1104
#define TSEC_DMACTL 0x110C
#define TSEC_DMATRFBASE 0x1110
#define TSEC_DMATRFMOFFS 0x1114
#define TSEC_DMATRFCMD 0x1118
#define TSEC_DMATRFCMD_IDLE BIT(1)
#define TSEC_DMATRFCMD_IMEM BIT(4)
#define TSEC_DMATRFCMD_SIZE_256B (6 << 8)
#define TSEC_DMATRFFBOFFS 0x111C
#endif

313
bdk/soc/bpmp.c Normal file
View File

@@ -0,0 +1,313 @@
/*
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
*
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/bpmp.h>
#include <soc/clock.h>
#include <soc/t210.h>
#include <memory_map.h>
#include <utils/util.h>
#define BPMP_MMU_CACHE_LINE_SIZE 0x20
#define BPMP_CACHE_CONFIG 0x0
#define CFG_ENABLE_CACHE BIT(0)
#define CFG_ENABLE_SKEW_ASSOC BIT(1)
#define CFG_DISABLE_RANDOM_ALLOC BIT(2)
#define CFG_FORCE_WRITE_THROUGH BIT(3)
#define CFG_NEVER_ALLOCATE BIT(6)
#define CFG_ENABLE_INTERRUPT BIT(7)
#define CFG_MMU_TAG_MODE(x) ((x) << 8)
#define TAG_MODE_PARALLEL 0
#define TAG_MODE_TAG_FIRST 1
#define TAG_MODE_MMU_FIRST 2
#define CFG_DISABLE_WRITE_BUFFER BIT(10)
#define CFG_DISABLE_READ_BUFFER BIT(11)
#define CFG_ENABLE_HANG_DETECT BIT(12)
#define CFG_FULL_LINE_DIRTY BIT(13)
#define CFG_TAG_CHK_ABRT_ON_ERR BIT(14)
#define CFG_TAG_CHK_CLR_ERR BIT(15)
#define CFG_DISABLE_SAMELINE BIT(16)
#define CFG_OBS_BUS_EN BIT(31)
#define BPMP_CACHE_LOCK 0x4
#define LOCK_LINE(x) BIT((x))
#define BPMP_CACHE_SIZE 0xC
#define BPMP_CACHE_LFSR 0x10
#define BPMP_CACHE_TAG_STATUS 0x14
#define TAG_STATUS_TAG_CHECK_ERROR BIT(0)
#define TAG_STATUS_CONFLICT_ADDR_MASK 0xFFFFFFE0
#define BPMP_CACHE_CLKEN_OVERRIDE 0x18
#define CLKEN_OVERRIDE_WR_MCCIF_CLKEN BIT(0)
#define CLKEN_OVERRIDE_RD_MCCIF_CLKEN BIT(1)
#define BPMP_CACHE_MAINT_ADDR 0x20
#define BPMP_CACHE_MAINT_DATA 0x24
#define BPMP_CACHE_MAINT_REQ 0x28
#define MAINT_REQ_WAY_BITMAP(x) ((x) << 8)
#define BPMP_CACHE_INT_MASK 0x40
#define BPMP_CACHE_INT_CLEAR 0x44
#define BPMP_CACHE_INT_RAW_EVENT 0x48
#define BPMP_CACHE_INT_STATUS 0x4C
#define INT_MAINT_DONE BIT(0)
#define INT_MAINT_ERROR BIT(1)
#define BPMP_CACHE_RB_CFG 0x80
#define BPMP_CACHE_WB_CFG 0x84
#define BPMP_CACHE_MMU_FALLBACK_ENTRY 0xA0
#define BPMP_CACHE_MMU_SHADOW_COPY_MASK 0xA4
#define BPMP_CACHE_MMU_CFG 0xAC
#define MMU_CFG_BLOCK_MAIN_ENTRY_WR BIT(0)
#define MMU_CFG_SEQ_EN BIT(1)
#define MMU_CFG_TLB_EN BIT(2)
#define MMU_CFG_SEG_CHECK_ALL_ENTRIES BIT(3)
#define MMU_CFG_ABORT_STORE_LAST BIT(4)
#define MMU_CFG_CLR_ABORT BIT(5)
#define BPMP_CACHE_MMU_CMD 0xB0
#define MMU_CMD_NOP 0
#define MMU_CMD_INIT 1
#define MMU_CMD_COPY_SHADOW 2
#define BPMP_CACHE_MMU_ABORT_STAT 0xB4
#define ABORT_STAT_UNIT_MASK 0x7
#define ABORT_STAT_UNIT_NONE 0
#define ABORT_STAT_UNIT_CACHE 1
#define ABORT_STAT_UNIT_SEQ 2
#define ABORT_STAT_UNIT_TLB 3
#define ABORT_STAT_UNIT_SEG 4
#define ABORT_STAT_UNIT_FALLBACK 5
#define ABORT_STAT_OVERLAP BIT(3)
#define ABORT_STAT_ENTRY (0x1F << 4)
#define ABORT_STAT_TYPE_MASK (3 << 16)
#define ABORT_STAT_TYPE_EXE (0 << 16)
#define ABORT_STAT_TYPE_RD (1 << 16)
#define ABORT_STAT_TYPE_WR (2 << 16)
#define ABORT_STAT_SIZE (3 << 18)
#define ABORT_STAT_SEQ BIT(20)
#define ABORT_STAT_PROT BIT(21)
#define BPMP_CACHE_MMU_ABORT_ADDR 0xB8
#define BPMP_CACHE_MMU_ACTIVE_ENTRIES 0xBC
#define BPMP_MMU_SHADOW_ENTRY_BASE (BPMP_CACHE_BASE + 0x400)
#define BPMP_MMU_MAIN_ENTRY_BASE (BPMP_CACHE_BASE + 0x800)
#define MMU_EN_CACHED BIT(0)
#define MMU_EN_EXEC BIT(1)
#define MMU_EN_READ BIT(2)
#define MMU_EN_WRITE BIT(3)
bpmp_mmu_entry_t mmu_entries[] =
{
{ DRAM_START, 0xFFFFFFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true },
{ IRAM_BASE, 0x4003FFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true }
};
void bpmp_mmu_maintenance(u32 op, bool force)
{
if (!force && !(BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE_CACHE))
return;
BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = INT_MAINT_DONE;
// This is a blocking operation.
BPMP_CACHE_CTRL(BPMP_CACHE_MAINT_REQ) = MAINT_REQ_WAY_BITMAP(0xF) | op;
while(!(BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT) & INT_MAINT_DONE))
;
BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT);
}
void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply)
{
if (idx > 31)
return;
volatile bpmp_mmu_entry_t *mmu_entry = (bpmp_mmu_entry_t *)(BPMP_MMU_SHADOW_ENTRY_BASE + sizeof(bpmp_mmu_entry_t) * idx);
if (entry->enable)
{
mmu_entry->start_addr = ALIGN(entry->start_addr, BPMP_MMU_CACHE_LINE_SIZE);
mmu_entry->end_addr = ALIGN_DOWN(entry->end_addr, BPMP_MMU_CACHE_LINE_SIZE);
mmu_entry->attr = entry->attr;
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) |= BIT(idx);
if (apply)
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW;
}
}
void bpmp_mmu_enable()
{
if (BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE_CACHE)
return;
// Init BPMP MMU.
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_INIT;
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_FALLBACK_ENTRY) = MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC; // RWX for non-defined regions.
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CFG) = MMU_CFG_SEQ_EN | MMU_CFG_TLB_EN | MMU_CFG_ABORT_STORE_LAST;
// Init BPMP MMU entries.
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) = 0;
for (u32 idx = 0; idx < ARRAY_SIZE(mmu_entries); idx++)
bpmp_mmu_set_entry(idx, &mmu_entries[idx], false);
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW;
// Invalidate cache.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, true);
// Enable cache.
BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = CFG_ENABLE_CACHE | CFG_FORCE_WRITE_THROUGH |
CFG_MMU_TAG_MODE(TAG_MODE_PARALLEL) | CFG_TAG_CHK_ABRT_ON_ERR;
// HW bug. Invalidate cache again.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
}
void bpmp_mmu_disable()
{
if (!(BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) & CFG_ENABLE_CACHE))
return;
// Clean and invalidate cache.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
// Disable cache.
BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0;
}
// APB clock affects RTC, PWM, MEMFETCH, APE, USB, SOR PWM,
// I2C host, DC/DSI/DISP. UART gives extra stress.
// 92: 100% success ratio. 93-94: 595-602MHz has 99% success ratio. 95: 608MHz less.
const u8 pll_divn[] = {
0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB.
85, // BPMP_CLK_HIGH_BOOST: 544MHz 33% - 136MHz APB.
90, // BPMP_CLK_SUPER_BOOST: 576MHz 41% - 144MHz APB.
92 // BPMP_CLK_HYPER_BOOST: 589MHz 44% - 147MHz APB.
// Do not use for public releases!
//95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB.
};
bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
void bpmp_clk_rate_get()
{
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
if (clk_src_is_pllp)
bpmp_fid_current = BPMP_CLK_NORMAL;
else
{
bpmp_fid_current = BPMP_CLK_HIGH_BOOST;
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
for (u32 i = 1; i < sizeof(pll_divn); i++)
{
if (pll_divn[i] == pll_divn_curr)
{
bpmp_fid_current = i;
break;
}
}
}
}
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid)
{
bpmp_freq_t prev_fid = bpmp_fid_current;
if (fid > (BPMP_CLK_MAX - 1))
fid = BPMP_CLK_MAX - 1;
if (prev_fid == fid)
return prev_fid;
if (fid)
{
if (prev_fid)
{
// Restore to PLLP source during PLLC configuration.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
msleep(1); // Wait a bit for clock source change.
}
// Configure and enable PLLC.
clock_enable_pllc(pll_divn[fid]);
// Set SCLK / HCLK / PCLK.
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / (3 + 1). HCLK == SCLK.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003310; // PLLC_OUT1 for active and CLKM for idle.
}
else
{
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003330; // PLLP_OUT for active and CLKM for idle.
msleep(1); // Wait a bit for clock source change.
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / (2 + 1). HCLK == SCLK.
// Disable PLLC to save power.
clock_disable_pllc();
}
bpmp_fid_current = fid;
// Return old fid in case of temporary swap.
return prev_fid;
}
// The following functions halt BPMP to reduce power while sleeping.
// They are not as accurate as RTC at big values but they guarantee time+ delay.
void bpmp_usleep(u32 us)
{
u32 delay;
// Each iteration takes 1us.
while (us)
{
delay = (us > HALT_COP_MAX_CNT) ? HALT_COP_MAX_CNT : us;
us -= delay;
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_USEC | delay;
}
}
void bpmp_msleep(u32 ms)
{
u32 delay;
// Iteration time is variable. ~200 - 1000us.
while (ms)
{
delay = (ms > HALT_COP_MAX_CNT) ? HALT_COP_MAX_CNT : ms;
ms -= delay;
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_MSEC | delay;
}
}
void bpmp_halt()
{
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_JTAG;
}

69
bdk/soc/bpmp.h Normal file
View File

@@ -0,0 +1,69 @@
/*
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
*
* Copyright (c) 2019-2021 CTCaer
*
* 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 _BPMP_H_
#define _BPMP_H_
#include <utils/types.h>
typedef enum
{
BPMP_MMU_MAINT_NOP = 0,
BPMP_MMU_MAINT_CLEAN_PHY = 1,
BPMP_MMU_MAINT_INVALID_PHY = 2,
BPMP_MMU_MAINT_CLEAN_INVALID_PHY = 3,
BPMP_MMU_MAINT_CLEAN_LINE = 9,
BPMP_MMU_MAINT_INVALID_LINE = 10,
BPMP_MMU_MAINT_CLEAN_INVALID_LINE = 11,
BPMP_MMU_MAINT_CLEAN_WAY = 17,
BPMP_MMU_MAINT_INVALID_WAY = 18,
BPMP_MMU_MAINT_CLN_INV_WAY = 19
} bpmp_maintenance_t;
typedef struct _bpmp_mmu_entry_t
{
u32 start_addr;
u32 end_addr;
u32 attr;
u32 enable;
} bpmp_mmu_entry_t;
typedef enum
{
BPMP_CLK_NORMAL, // 408MHz 0% - 136MHz APB.
BPMP_CLK_HIGH_BOOST, // 544MHz 33% - 136MHz APB.
BPMP_CLK_SUPER_BOOST, // 576MHz 41% - 144MHz APB.
BPMP_CLK_HYPER_BOOST, // 589MHz 44% - 147MHz APB.
//BPMP_CLK_DEV_BOOST, // 608MHz 49% - 152MHz APB.
BPMP_CLK_MAX
} bpmp_freq_t;
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
void bpmp_mmu_maintenance(u32 op, bool force);
void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply);
void bpmp_mmu_enable();
void bpmp_mmu_disable();
void bpmp_clk_rate_get();
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid);
void bpmp_usleep(u32 us);
void bpmp_msleep(u32 ms);
void bpmp_halt();
#endif

108
bdk/soc/ccplex.c Normal file
View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/ccplex.h>
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/clock.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <power/max77620.h>
#include <power/max7762x.h>
#include <power/max77812.h>
#include <utils/util.h>
void _ccplex_enable_power_t210()
{
// Configure GPIO5 and enable output in order to power CPU pmic.
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_ENABLE);
// Configure CPU pmic.
// 1-3.x: MAX77621_NFSR_ENABLE.
// 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL.
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_HOS_CFG);
// Set voltage and enable cores power.
max7762x_regulator_set_voltage(REGULATOR_CPU0, 950000);
max7762x_regulator_enable(REGULATOR_CPU0, true);
}
void _ccplex_enable_power_t210b01()
{
// Set voltage and enable cores power.
max7762x_regulator_set_voltage(REGULATOR_CPU1, 800000);
max7762x_regulator_enable(REGULATOR_CPU1, true);
}
void ccplex_boot_cpu0(u32 entry)
{
// Set ACTIVE_CLUSER to FAST.
FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE;
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
_ccplex_enable_power_t210();
else
_ccplex_enable_power_t210b01();
clock_enable_pllx();
// Configure MSELECT source and enable clock to 102MHz.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT);
// Configure initial CPU clock frequency and enable clock.
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ.
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG);
clock_enable_coresight();
// CAR2PMC_CPU_ACK_WIDTH should be set to 0.
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
// Enable CPU main rail.
pmc_enable_partition(POWER_RAIL_CRAIL, ENABLE);
// Enable cluster 0 non-CPU rail.
pmc_enable_partition(POWER_RAIL_C0NC, ENABLE);
// Enable CPU0 rail.
pmc_enable_partition(POWER_RAIL_CE0, ENABLE);
// Request and wait for RAM repair.
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1;
while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & 2))
;
EXCP_VEC(EVP_CPU_RESET_VECTOR) = 0;
// Set reset vector.
SB(SB_AA64_RESET_LOW) = entry | SB_AA64_RST_AARCH64_MODE_EN;
SB(SB_AA64_RESET_HIGH) = 0;
// Non-secure reset vector write disable.
SB(SB_CSR) = SB_CSR_NS_RST_VEC_WR_DIS;
(void)SB(SB_CSR);
// Tighten up the security aperture.
// MC(MC_TZ_SECURITY_CTRL) = 1;
// Clear MSELECT reset.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT);
// Clear NONCPU reset.
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
// Clear CPU0 reset.
// < 5.x: 0x411F000F, Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x41010001;
}

24
bdk/soc/ccplex.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _CCPLEX_H_
#define _CCPLEX_H_
#include <utils/types.h>
void ccplex_boot_cpu0(u32 entry);
#endif

819
bdk/soc/clock.c Normal file
View File

@@ -0,0 +1,819 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/clock.h>
#include <soc/hw_init.h>
#include <soc/t210.h>
#include <storage/sdmmc.h>
#include <utils/util.h>
typedef struct _clock_osc_t
{
u32 freq;
u16 min;
u16 max;
} clock_osc_t;
static const clock_osc_t _clock_osc_cnt[] = {
{ 12000, 706, 757 },
{ 13000, 766, 820 },
{ 16800, 991, 1059 },
{ 19200, 1133, 1210 },
{ 26000, 1535, 1638 },
{ 38400, 2268, 2418 },
{ 48000, 2836, 3023 }
};
/* clock_t: reset, enable, source, index, clk_src, clk_div */
static const clock_t _clock_uart[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, CLK_U_UARTD, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, CLK_Y_UARTAPE, 0, 2 }
};
//I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26.
static const clock_t _clock_i2c[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, 19 }, //20.4MHz -> 100KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, 4 }, //81.6MHz -> 400KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_V_I2C4, 0, 19 }, //20.4MHz -> 100KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_H_I2C5, 0, 4 }, //81.6MHz -> 400KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, 19 } //20.4MHz -> 100KHz
};
static clock_t _clock_se = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz.
};
static clock_t _clock_tzram = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0
};
static clock_t _clock_host1x = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz.
};
static clock_t _clock_tsec = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz.
};
static clock_t _clock_sor_safe = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0
};
static clock_t _clock_sor0 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0
};
static clock_t _clock_sor1 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 //204MHz.
};
static clock_t _clock_kfuse = {
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
};
static clock_t _clock_cl_dvfs = {
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
};
static clock_t _clock_coresight = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz.
};
static clock_t _clock_pwm = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
};
static clock_t _clock_sdmmc_legacy_tm = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66
};
void clock_enable(const clock_t *clk)
{
// Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
// Disable.
CLOCK(clk->enable) &= ~BIT(clk->index);
// Configure clock source if required.
if (clk->source)
CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29);
// Enable.
CLOCK(clk->enable) = (CLOCK(clk->enable) & ~BIT(clk->index)) | BIT(clk->index);
usleep(2);
// Take clock off reset.
CLOCK(clk->reset) &= ~BIT(clk->index);
}
void clock_disable(const clock_t *clk)
{
// Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
// Disable.
CLOCK(clk->enable) &= ~BIT(clk->index);
}
void clock_enable_fuse(bool enable)
{
// Enable Fuse registers visibility.
CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = (CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF) | ((enable & 1) << 28);
}
void clock_enable_uart(u32 idx)
{
clock_enable(&_clock_uart[idx]);
}
void clock_disable_uart(u32 idx)
{
clock_disable(&_clock_uart[idx]);
}
#define UART_SRC_CLK_DIV_EN BIT(24)
int clock_uart_use_src_div(u32 idx, u32 baud)
{
u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000;
if (baud == 1000000)
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 49;
else
{
CLOCK(_clock_uart[idx].source) = clk_src_div | 2;
return 1;
}
return 0;
}
void clock_enable_i2c(u32 idx)
{
clock_enable(&_clock_i2c[idx]);
}
void clock_disable_i2c(u32 idx)
{
clock_disable(&_clock_i2c[idx]);
}
void clock_enable_se()
{
clock_enable(&_clock_se);
// Lock clock to always enabled if T210B01.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SE) |= 0x100;
}
void clock_enable_tzram()
{
clock_enable(&_clock_tzram);
}
void clock_enable_host1x()
{
clock_enable(&_clock_host1x);
}
void clock_disable_host1x()
{
clock_disable(&_clock_host1x);
}
void clock_enable_tsec()
{
clock_enable(&_clock_tsec);
}
void clock_disable_tsec()
{
clock_disable(&_clock_tsec);
}
void clock_enable_sor_safe()
{
clock_enable(&_clock_sor_safe);
}
void clock_disable_sor_safe()
{
clock_disable(&_clock_sor_safe);
}
void clock_enable_sor0()
{
clock_enable(&_clock_sor0);
}
void clock_disable_sor0()
{
clock_disable(&_clock_sor0);
}
void clock_enable_sor1()
{
clock_enable(&_clock_sor1);
}
void clock_disable_sor1()
{
clock_disable(&_clock_sor1);
}
void clock_enable_kfuse()
{
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_KFUSE);
usleep(10); // Wait 10s to prevent glitching.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_KFUSE);
usleep(20); // Wait 20s fo kfuse hw to init.
}
void clock_disable_kfuse()
{
clock_disable(&_clock_kfuse);
}
void clock_enable_cl_dvfs()
{
clock_enable(&_clock_cl_dvfs);
}
void clock_disable_cl_dvfs()
{
clock_disable(&_clock_cl_dvfs);
}
void clock_enable_coresight()
{
clock_enable(&_clock_coresight);
}
void clock_disable_coresight()
{
clock_disable(&_clock_coresight);
}
void clock_enable_pwm()
{
clock_enable(&_clock_pwm);
}
void clock_disable_pwm()
{
clock_disable(&_clock_pwm);
}
void clock_enable_pllx()
{
// Configure and enable PLLX if disabled.
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE.
{
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= ~PLLX_MISC3_IDDQ; // Disable IDDQ.
usleep(2);
// Set div configuration.
const u32 pllx_div_cfg = (2 << 20) | (156 << 8) | 2; // P div: 2 (3), N div: 156, M div: 2. 998.4 MHz.
// Bypass dividers.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | pllx_div_cfg;
// Disable bypass
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = pllx_div_cfg;
// Set PLLX_LOCK_ENABLE.
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) |= PLLX_MISC_LOCK_EN;
// Enable PLLX.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | pllx_div_cfg;
}
// Wait for PLL to stabilize.
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK))
;
}
void clock_enable_pllc(u32 divn)
{
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
// Check if already enabled and configured.
if ((CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_ENABLE) && (pll_divn_curr == divn))
return;
// Take PLLC out of reset and set basic misc parameters.
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) =
((CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) & 0xFFF0000F) & ~PLLC_MISC_RESET) | (0x80000 << 4); // PLLC_EXT_FRU.
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM.
// Disable PLL and IDDQ in case they are on.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE;
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ;
usleep(10);
// Set PLLC dividers.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = (divn << 10) | 4; // DIVM: 4, DIVP: 1.
// Enable PLLC and wait for Phase and Frequency lock.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_ENABLE;
while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_LOCK))
;
// Disable PLLC_OUT1, enable reset and set div to 1.5.
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = BIT(8);
// Enable PLLC_OUT1 and bring it out of reset.
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= (PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR);
msleep(1); // Wait a bit for PLL to stabilize.
}
void clock_disable_pllc()
{
// Disable PLLC and PLLC_OUT1.
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~(PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR);
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE;
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_REF_DIS;
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ;
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) |= PLLC_MISC_RESET;
usleep(10);
}
#define PLLC4_ENABLED BIT(31)
#define PLLC4_IN_USE (~PLLC4_ENABLED)
u32 pllc4_enabled = 0;
static void _clock_enable_pllc4(u32 mask)
{
pllc4_enabled |= mask;
if (pllc4_enabled & PLLC4_ENABLED)
return;
// Enable Phase and Frequency lock detection.
//CLOCK(CLK_RST_CONTROLLER_PLLC4_MISC) = PLLC4_MISC_EN_LCKDET;
// Disable PLL and IDDQ in case they are on.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLCX_BASE_ENABLE;
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLC4_BASE_IDDQ;
usleep(10);
// Set PLLC4 dividers.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (104 << 8) | 4; // DIVM: 4, DIVP: 1.
// Enable PLLC4 and wait for Phase and Frequency lock.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE;
while (!(CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) & PLLCX_BASE_LOCK))
;
msleep(1); // Wait a bit for PLL to stabilize.
pllc4_enabled |= PLLC4_ENABLED;
}
static void _clock_disable_pllc4(u32 mask)
{
pllc4_enabled &= ~mask;
// Check if currently in use or disabled.
if ((pllc4_enabled & PLLC4_IN_USE) || !(pllc4_enabled & PLLC4_ENABLED))
return;
// Disable PLLC4.
msleep(1); // Wait at least 1ms to prevent glitching.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLCX_BASE_ENABLE;
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLC4_BASE_IDDQ;
usleep(10);
pllc4_enabled = 0;
}
void clock_enable_pllu()
{
// Configure PLLU.
CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) |= BIT(29); // Disable reference clock.
u32 pllu_cfg = (CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & 0xFFE00000) | BIT(24) | (1 << 16) | (0x19 << 8) | 2;
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg;
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | PLLCX_BASE_ENABLE; // Enable.
// Wait for PLL to stabilize.
u32 timeout = (u32)TMR(TIMERUS_CNTR_1US) + 1300;
while (!(CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & PLLCX_BASE_LOCK)) // PLL_LOCK.
if ((u32)TMR(TIMERUS_CNTR_1US) > timeout)
break;
usleep(10);
// Enable PLLU USB/HSIC/ICUSB/48M.
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) |= 0x2E00000;
}
void clock_disable_pllu()
{
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x2E00000; // Disable PLLU USB/HSIC/ICUSB/48M.
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x40000000; // Disable PLLU.
CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) &= ~0x20000000; // Enable reference clock.
}
void clock_enable_utmipll()
{
// Set UTMIPLL dividers and config based on OSC and enable it to 960 MHz.
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG0) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG0) & 0xFF0000FF) | (25 << 16) | (1 << 8); // 38.4Mhz * (25 / 1) = 960 MHz.
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) & 0xFF00003F) | (24 << 18); // Set delay count for 38.4Mhz osc crystal.
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) & 0x7FFA000) | (1 << 15) | 375;
// Wait for UTMIPLL to stabilize.
u32 retries = 10; // Wait 20us
while (!(CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) & UTMIPLL_LOCK) && retries)
{
usleep(1);
retries--;
}
}
static int _clock_sdmmc_is_reset(u32 id)
{
switch (id)
{
case SDMMC_1:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC1);
case SDMMC_2:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC2);
case SDMMC_3:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & BIT(CLK_U_SDMMC3);
case SDMMC_4:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC4);
}
return 0;
}
static void _clock_sdmmc_set_reset(u32 id)
{
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC4);
break;
}
}
static void _clock_sdmmc_clear_reset(u32 id)
{
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC4);
break;
}
}
static int _clock_sdmmc_is_enabled(u32 id)
{
switch (id)
{
case SDMMC_1:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC1);
case SDMMC_2:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC2);
case SDMMC_3:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & BIT(CLK_U_SDMMC3);
case SDMMC_4:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC4);
}
return 0;
}
static void _clock_sdmmc_set_enable(u32 id)
{
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC4);
break;
}
}
static void _clock_sdmmc_clear_enable(u32 id)
{
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC4);
break;
}
}
static void _clock_sdmmc_config_legacy_tm()
{
clock_t *clk = &_clock_sdmmc_legacy_tm;
if (!(CLOCK(clk->enable) & BIT(clk->index)))
clock_enable(clk);
}
typedef struct _clock_sdmmc_t
{
u32 clock;
u32 real_clock;
} clock_sdmmc_t;
static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 };
#define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0
#define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3
#define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1
static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
{
u32 divisor = 0;
u32 source = SDMMC_CLOCK_SRC_PLLP_OUT0;
if (id > SDMMC_4)
return 0;
// Get IO clock divisor.
switch (val)
{
case 25000:
*pclock = 24728;
divisor = 31; // 16.5 div.
break;
case 26000:
*pclock = 25500;
divisor = 30; // 16 div.
break;
case 40800:
*pclock = 40800;
divisor = 18; // 10 div.
break;
case 50000:
*pclock = 48000;
divisor = 15; // 8.5 div.
break;
case 52000:
*pclock = 51000;
divisor = 14; // 8 div.
break;
case 100000:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
*pclock = 99840;
divisor = 2; // 2 div.
break;
case 164000:
*pclock = 163200;
divisor = 3; // 2.5 div.
break;
case 200000: // 240MHz evo+.
switch (id)
{
case SDMMC_1:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
break;
case SDMMC_2:
source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ;
break;
case SDMMC_3:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
break;
case SDMMC_4:
source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ;
break;
}
*pclock = 199680;
divisor = 0; // 1 div.
break;
default:
*pclock = 24728;
divisor = 31; // 16.5 div.
}
_clock_sdmmc_table[id].clock = val;
_clock_sdmmc_table[id].real_clock = *pclock;
// Enable PLLC4 if in use by any SDMMC.
if (source)
_clock_enable_pllc4(BIT(id));
// Set SDMMC legacy timeout clock.
_clock_sdmmc_config_legacy_tm();
// Set SDMMC clock.
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = (source << 29) | divisor;
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = (source << 29) | divisor;
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = (source << 29) | divisor;
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = (source << 29) | divisor;
break;
}
return 1;
}
void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val)
{
if (_clock_sdmmc_table[id].clock == val)
{
*pclock = _clock_sdmmc_table[id].real_clock;
}
else
{
int is_enabled = _clock_sdmmc_is_enabled(id);
if (is_enabled)
_clock_sdmmc_clear_enable(id);
_clock_sdmmc_config_clock_host(pclock, id, val);
if (is_enabled)
_clock_sdmmc_set_enable(id);
_clock_sdmmc_is_reset(id);
}
}
void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type)
{
// Get Card clock divisor.
switch (type)
{
case SDHCI_TIMING_MMC_ID: // Actual IO Freq: 380.59 KHz.
*pclock = 26000;
*pdivisor = 66;
break;
case SDHCI_TIMING_MMC_LS26:
*pclock = 26000;
*pdivisor = 1;
break;
case SDHCI_TIMING_MMC_HS52:
*pclock = 52000;
*pdivisor = 1;
break;
case SDHCI_TIMING_MMC_HS200:
case SDHCI_TIMING_MMC_HS400:
case SDHCI_TIMING_UHS_SDR104:
*pclock = 200000;
*pdivisor = 1;
break;
case SDHCI_TIMING_SD_ID: // Actual IO Freq: 380.43 KHz.
*pclock = 25000;
*pdivisor = 64;
break;
case SDHCI_TIMING_SD_DS12:
case SDHCI_TIMING_UHS_SDR12:
*pclock = 25000;
*pdivisor = 1;
break;
case SDHCI_TIMING_SD_HS25:
case SDHCI_TIMING_UHS_SDR25:
*pclock = 50000;
*pdivisor = 1;
break;
case SDHCI_TIMING_UHS_SDR50:
*pclock = 100000;
*pdivisor = 1;
break;
case SDHCI_TIMING_UHS_SDR82:
*pclock = 164000;
*pdivisor = 1;
break;
case SDHCI_TIMING_UHS_DDR50:
*pclock = 40800;
*pdivisor = 1;
break;
case SDHCI_TIMING_MMC_HS102: // Actual IO Freq: 99.84 MHz.
*pclock = 200000;
*pdivisor = 2;
break;
}
}
int clock_sdmmc_is_not_reset_and_enabled(u32 id)
{
return !_clock_sdmmc_is_reset(id) && _clock_sdmmc_is_enabled(id);
}
void clock_sdmmc_enable(u32 id, u32 val)
{
u32 clock = 0;
if (_clock_sdmmc_is_enabled(id))
_clock_sdmmc_clear_enable(id);
_clock_sdmmc_set_reset(id);
_clock_sdmmc_config_clock_host(&clock, id, val);
_clock_sdmmc_set_enable(id);
_clock_sdmmc_is_reset(id);
usleep((100000 + clock - 1) / clock);
_clock_sdmmc_clear_reset(id);
_clock_sdmmc_is_reset(id);
}
void clock_sdmmc_disable(u32 id)
{
_clock_sdmmc_set_reset(id);
_clock_sdmmc_clear_enable(id);
_clock_sdmmc_is_reset(id);
_clock_disable_pllc4(BIT(id));
}
u32 clock_get_osc_freq()
{
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = OSC_FREQ_DET_TRIG | (2 - 1); // 2 periods of 32.76KHz window.
while (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY)
;
u32 cnt = (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_CNT);
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = 0;
// Return frequency in KHz.
for (u32 i = 0; i < ARRAY_SIZE(_clock_osc_cnt); i++)
if (cnt >= _clock_osc_cnt[i].min && cnt <= _clock_osc_cnt[i].max)
return _clock_osc_cnt[i].freq;
return 0;
}
u32 clock_get_dev_freq(clock_pto_id_t id)
{
const u32 pto_win = 16;
const u32 pto_osc = 32768;
u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (pto_win - 1);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep((1000000 * pto_win / pto_osc) + 12 + 2);
while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY)
;
u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT;
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep(2);
u32 freq_khz = (u64)cnt * pto_osc / pto_win / 1000;
return freq_khz;
}

677
bdk/soc/clock.h Normal file
View File

@@ -0,0 +1,677 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* 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 _CLOCK_H_
#define _CLOCK_H_
#include <utils/types.h>
/*! Clock registers. */
#define CLK_RST_CONTROLLER_RST_SOURCE 0x0
#define CLK_RST_CONTROLLER_RST_DEVICES_L 0x4
#define CLK_RST_CONTROLLER_RST_DEVICES_H 0x8
#define CLK_RST_CONTROLLER_RST_DEVICES_U 0xC
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_L 0x10
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_H 0x14
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_U 0x18
#define CLK_RST_CONTROLLER_CCLK_BURST_POLICY 0x20
#define CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER 0x24
#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY 0x28
#define CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2C
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30
#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48
#define CLK_RST_CONTROLLER_OSC_CTRL 0x50
#define CLK_RST_CONTROLLER_OSC_FREQ_DET 0x58
#define CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS 0x5C
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL 0x60
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS 0x64
#define CLK_RST_CONTROLLER_PLLC_BASE 0x80
#define CLK_RST_CONTROLLER_PLLC_OUT 0x84
#define CLK_RST_CONTROLLER_PLLC_MISC 0x88
#define CLK_RST_CONTROLLER_PLLC_MISC_1 0x8C
#define CLK_RST_CONTROLLER_PLLM_BASE 0x90
#define CLK_RST_CONTROLLER_PLLM_MISC1 0x98
#define CLK_RST_CONTROLLER_PLLM_MISC2 0x9C
#define CLK_RST_CONTROLLER_PLLP_BASE 0xA0
#define CLK_RST_CONTROLLER_PLLA_BASE 0xB0
#define CLK_RST_CONTROLLER_PLLA_OUT 0xB4
#define CLK_RST_CONTROLLER_PLLA_MISC1 0xB8
#define CLK_RST_CONTROLLER_PLLA_MISC 0xBC
#define CLK_RST_CONTROLLER_PLLU_BASE 0xC0
#define CLK_RST_CONTROLLER_PLLU_OUTA 0xC4
#define CLK_RST_CONTROLLER_PLLU_MISC 0xCC
#define CLK_RST_CONTROLLER_PLLD_BASE 0xD0
#define CLK_RST_CONTROLLER_PLLD_MISC1 0xD8
#define CLK_RST_CONTROLLER_PLLD_MISC 0xDC
#define CLK_RST_CONTROLLER_PLLX_BASE 0xE0
#define CLK_RST_CONTROLLER_PLLX_MISC 0xE4
#define CLK_RST_CONTROLLER_PLLE_BASE 0xE8
#define CLK_RST_CONTROLLER_PLLE_MISC 0xEC
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA 0xF8
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB 0xFC
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2S2 0x100
#define CLK_RST_CONTROLLER_CLK_SOURCE_PWM 0x110
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 0x124
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 0x128
#define CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 0x138
#define CLK_RST_CONTROLLER_CLK_SOURCE_VI 0x148
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 0x150
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 0x154
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 0x164
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA 0x178
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB 0x17C
#define CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X 0x180
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C2 0x198
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19C
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC 0x1A0
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 0x1B8
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 0x1BC
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTD 0x1C0
#define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE 0x1D4
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2S1 0x1D8
#define CLK_RST_CONTROLLER_CLK_SOURCE_TSEC 0x1F4
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X 0x280
#define CLK_RST_CONTROLLER_CLK_ENB_X_SET 0x284
#define CLK_RST_CONTROLLER_CLK_ENB_X_CLR 0x288
#define CLK_RST_CONTROLLER_RST_DEVICES_X 0x28C
#define CLK_RST_CONTROLLER_RST_DEV_X_SET 0x290
#define CLK_RST_CONTROLLER_RST_DEV_X_CLR 0x294
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_Y 0x298
#define CLK_RST_CONTROLLER_CLK_ENB_Y_SET 0x29C
#define CLK_RST_CONTROLLER_CLK_ENB_Y_CLR 0x2A0
#define CLK_RST_CONTROLLER_RST_DEVICES_Y 0x2A4
#define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2A8
#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2AC
#define CLK_RST_CONTROLLER_RST_DEV_L_SET 0x300
#define CLK_RST_CONTROLLER_RST_DEV_L_CLR 0x304
#define CLK_RST_CONTROLLER_RST_DEV_H_SET 0x308
#define CLK_RST_CONTROLLER_RST_DEV_H_CLR 0x30C
#define CLK_RST_CONTROLLER_RST_DEV_U_SET 0x310
#define CLK_RST_CONTROLLER_RST_DEV_U_CLR 0x314
#define CLK_RST_CONTROLLER_CLK_ENB_L_SET 0x320
#define CLK_RST_CONTROLLER_CLK_ENB_L_CLR 0x324
#define CLK_RST_CONTROLLER_CLK_ENB_H_SET 0x328
#define CLK_RST_CONTROLLER_CLK_ENB_H_CLR 0x32C
#define CLK_RST_CONTROLLER_CLK_ENB_U_SET 0x330
#define CLK_RST_CONTROLLER_CLK_ENB_U_CLR 0x334
#define CLK_RST_CONTROLLER_RST_DEVICES_V 0x358
#define CLK_RST_CONTROLLER_RST_DEVICES_W 0x35C
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_V 0x360
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_W 0x364
#define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2 0x388
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC 0x3A0
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 0x3C4
#define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 0x3EC
#define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400
#define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410
#define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C
#define CLK_RST_CONTROLLER_RST_DEV_V_SET 0x430
#define CLK_RST_CONTROLLER_RST_DEV_V_CLR 0x434
#define CLK_RST_CONTROLLER_RST_DEV_W_SET 0x438
#define CLK_RST_CONTROLLER_RST_DEV_W_CLR 0x43C
#define CLK_RST_CONTROLLER_CLK_ENB_V_SET 0x440
#define CLK_RST_CONTROLLER_CLK_ENB_V_CLR 0x444
#define CLK_RST_CONTROLLER_CLK_ENB_W_SET 0x448
#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR 0x44C
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET 0x450
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR 0x454
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG0 0x480
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG1 0x484
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG2 0x488
#define CLK_RST_CONTROLLER_PLLE_AUX 0x48C
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S0 0x4A0
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG3 0x4C0
#define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518
#define CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0 0x52C
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE 0x554
#define CLK_RST_CONTROLLER_SPARE_REG0 0x55C
#define CLK_RST_CONTROLLER_PLLC4_BASE 0x5A4
#define CLK_RST_CONTROLLER_PLLC4_MISC 0x5A8
#define CLK_RST_CONTROLLER_PLLC_MISC_2 0x5D0
#define CLK_RST_CONTROLLER_PLLC4_OUT 0x5E4
#define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_FS 0x608
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_CORE_DEV 0x60C
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_SS 0x610
#define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP 0x620
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664
#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694
#define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0
#define CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK 0x6CC
#define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710
#define CLK_NO_SOURCE 0x0
#define CLK_NOT_USED 0x0
/*! PLL control and status bits */
#define PLLX_BASE_LOCK BIT(27)
#define PLLX_BASE_REF_DIS BIT(29)
#define PLLX_BASE_ENABLE BIT(30)
#define PLLX_BASE_BYPASS BIT(31)
#define PLLX_MISC_LOCK_EN BIT(18)
#define PLLX_MISC3_IDDQ BIT(3)
#define PLLCX_BASE_LOCK BIT(27)
#define PLLCX_BASE_REF_DIS BIT(29)
#define PLLCX_BASE_ENABLE BIT(30)
#define PLLCX_BASE_BYPASS BIT(31)
#define PLLA_OUT0_RSTN_CLR BIT(0)
#define PLLA_OUT0_CLKEN BIT(1)
#define PLLA_BASE_IDDQ BIT(25)
#define PLLC_OUT1_RSTN_CLR BIT(0)
#define PLLC_OUT1_CLKEN BIT(1)
#define PLLC_MISC1_IDDQ BIT(27)
#define PLLC_MISC_RESET BIT(30)
#define PLLC4_OUT3_RSTN_CLR BIT(0)
#define PLLC4_OUT3_CLKEN BIT(1)
#define PLLC4_BASE_IDDQ BIT(18)
#define PLLC4_MISC_EN_LCKDET BIT(30)
#define UTMIPLL_LOCK BIT(31)
/*! PTO_CLK_CNT */
#define PTO_REF_CLK_WIN_CFG_MASK 0xF
#define PTO_REF_CLK_WIN_CFG_16P 0xF
#define PTO_CNT_EN BIT(9)
#define PTO_CNT_RST BIT(10)
#define PTO_CLK_ENABLE BIT(13)
#define PTO_SRC_SEL_SHIFT 14
#define PTO_SRC_SEL_MASK 0x1FF
#define PTO_DIV_SEL_MASK (3 << 23)
#define PTO_DIV_SEL_GATED (0 << 23)
#define PTO_DIV_SEL_DIV1 (1 << 23)
#define PTO_DIV_SEL_DIV2_RISING (2 << 23)
#define PTO_DIV_SEL_DIV2_FALLING (3 << 23)
#define PTO_DIV_SEL_CPU_EARLY (0 << 23)
#define PTO_DIV_SEL_CPU_LATE (1 << 23)
#define PTO_CLK_CNT_BUSY BIT(31)
#define PTO_CLK_CNT 0xFFFFFF
/*! OSC_FREQ_DET */
#define OSC_REF_CLK_WIN_CFG_MASK 0xF
#define OSC_FREQ_DET_TRIG BIT(31)
#define OSC_FREQ_DET_BUSY BIT(31)
#define OSC_FREQ_DET_CNT 0xFFFF
/*! PTO IDs. */
typedef enum _clock_pto_id_t
{
CLK_PTO_PCLK_SYS = 0x06,
CLK_PTO_HCLK_SYS = 0x07,
CLK_PTO_UTMIP_240 = 0x0C,
CLK_PTO_CCLK_G = 0x12,
CLK_PTO_CCLK_G_DIV2 = 0x13,
CLK_PTO_SPI1 = 0x17,
CLK_PTO_SPI2 = 0x18,
CLK_PTO_SPI3 = 0x19,
CLK_PTO_SPI4 = 0x1A,
CLK_PTO_MAUD = 0x1B,
CLK_PTO_SCLK = 0x1C,
CLK_PTO_SDMMC1 = 0x20,
CLK_PTO_SDMMC2 = 0x21,
CLK_PTO_SDMMC3 = 0x22,
CLK_PTO_SDMMC4 = 0x23,
CLK_PTO_EMC = 0x24,
CLK_PTO_CCLK_LP = 0x2B,
CLK_PTO_CCLK_LP_DIV2 = 0x2C,
CLK_PTO_MSELECT = 0x2F,
CLK_PTO_VIC = 0x36,
CLK_PTO_NVDEC = 0x39,
CLK_PTO_NVENC = 0x3A,
CLK_PTO_NVJPG = 0x3B,
CLK_PTO_TSEC = 0x3C,
CLK_PTO_TSECB = 0x3D,
CLK_PTO_SE = 0x3E,
CLK_PTO_DSIA_LP = 0x62,
CLK_PTO_ISP = 0x64,
CLK_PTO_MC = 0x6A,
CLK_PTO_ACTMON = 0x6B,
CLK_PTO_CSITE = 0x6C,
CLK_PTO_HOST1X = 0x6F,
CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE.
CLK_PTO_SOC_THERM = 0x75,
CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC.
CLK_PTO_ACLK = 0x7C,
CLK_PTO_QSPI = 0x7D,
CLK_PTO_I2S1 = 0x80,
CLK_PTO_I2S2 = 0x81,
CLK_PTO_I2S3 = 0x82,
CLK_PTO_I2S4 = 0x83,
CLK_PTO_I2S5 = 0x84,
CLK_PTO_AHUB = 0x85,
CLK_PTO_APE = 0x86,
CLK_PTO_DVFS_SOC = 0x88,
CLK_PTO_DVFS_REF = 0x89,
CLK_PTO_SPDIF = 0x8F,
CLK_PTO_SPDIF_IN = 0x90,
CLK_PTO_UART_FST_MIPI_CAL = 0x91,
CLK_PTO_PWM = 0x93,
CLK_PTO_I2C1 = 0x94,
CLK_PTO_I2C2 = 0x95,
CLK_PTO_I2C3 = 0x96,
CLK_PTO_I2C4 = 0x97,
CLK_PTO_I2C5 = 0x98,
CLK_PTO_I2C6 = 0x99,
CLK_PTO_I2C_SLOW = 0x9A,
CLK_PTO_UARTAPE = 0x9B,
CLK_PTO_EXTPERIPH1 = 0x9D,
CLK_PTO_EXTPERIPH2 = 0x9E,
CLK_PTO_ENTROPY = 0xA0,
CLK_PTO_UARTA = 0xA1,
CLK_PTO_UARTB = 0xA2,
CLK_PTO_UARTC = 0xA3,
CLK_PTO_UARTD = 0xA4,
CLK_PTO_OWR = 0xA5,
CLK_PTO_HDA2CODEC_2X = 0xA7,
CLK_PTO_HDA = 0xA8,
CLK_PTO_SDMMC_LEGACY_TM = 0xAB,
CLK_PTO_SOR0 = 0xC0,
CLK_PTO_SOR1 = 0xC1,
CLK_PTO_DISP2 = 0xC4,
CLK_PTO_DISP1 = 0xC5,
CLK_PTO_XUSB_FALCON = 0x110,
CLK_PTO_XUSB_FS = 0x136,
CLK_PTO_XUSB_SS_HOST_DEV = 0x137,
CLK_PTO_XUSB_CORE_HOST = 0x138,
CLK_PTO_XUSB_CORE_DEV = 0x139,
/*
* PLL need PTO enabled in MISC registers.
* Normal div is 2 so result is multiplied with it.
*/
CLK_PTO_PLLC_DIV2 = 0x01,
CLK_PTO_PLLM_DIV2 = 0x02,
CLK_PTO_PLLP_DIV2 = 0x03,
CLK_PTO_PLLA_DIV2 = 0x04,
CLK_PTO_PLLX_DIV2 = 0x05,
CLK_PTO_PLLMB_DIV2 = 0x25,
CLK_PTO_PLLC4_DIV2 = 0x51,
CLK_PTO_PLLA1_DIV2 = 0x55,
CLK_PTO_PLLC2_DIV2 = 0x58,
CLK_PTO_PLLC3_DIV2 = 0x5A,
CLK_PTO_PLLD_DIV2 = 0xCB,
CLK_PTO_PLLD2_DIV2 = 0xCD,
CLK_PTO_PLLDP_DIV2 = 0xCF,
CLK_PTO_PLLU_DIV2 = 0x10D,
CLK_PTO_PLLREFE_DIV2 = 0x10F,
} clock_pto_id_t;
/*
* CLOCK Peripherals:
* L 0 - 31
* H 32 - 63
* U 64 - 95
* V 96 - 127
* W 128 - 159
* X 160 - 191
* Y 192 - 223
*/
enum CLK_L_DEV
{
CLK_L_CPU = 0, // Only reset. Deprecated.
CLK_L_BPMP = 1, // Only reset.
CLK_L_SYS = 2, // Only reset.
CLK_L_ISPB = 3,
CLK_L_RTC = 4,
CLK_L_TMR = 5,
CLK_L_UARTA = 6,
CLK_L_UARTB = 7,
CLK_L_GPIO = 8,
CLK_L_SDMMC2 = 9,
CLK_L_SPDIF = 10,
CLK_L_I2S2 = 11, // I2S1
CLK_L_I2C1 = 12,
CLK_L_NDFLASH = 13, // HIDDEN.
CLK_L_SDMMC1 = 14,
CLK_L_SDMMC4 = 15,
CLK_L_TWC = 16, // HIDDEN.
CLK_L_PWM = 17,
CLK_L_I2S3 = 18,
CLK_L_EPP = 19, // HIDDEN.
CLK_L_VI = 20,
CLK_L_2D = 21, // HIDDEN.
CLK_L_USBD = 22,
CLK_L_ISP = 23,
CLK_L_3D = 24, // HIDDEN.
CLK_L_IDE = 25, // RESERVED.
CLK_L_DISP2 = 26,
CLK_L_DISP1 = 27,
CLK_L_HOST1X = 28,
CLK_L_VCP = 29, // HIDDEN.
CLK_L_I2S1 = 30, // I2S0
CLK_L_BPMP_CACHE_CTRL = 31, // CONTROLLER
};
enum CLK_H_DEV
{
CLK_H_MEM = 0, // MC.
CLK_H_AHBDMA = 1,
CLK_H_APBDMA = 2,
//CLK_H_ = 3,
CLK_H_KBC = 4, // HIDDEN.
CLK_H_STAT_MON = 5,
CLK_H_PMC = 6,
CLK_H_FUSE = 7,
CLK_H_KFUSE = 8,
CLK_H_SPI1 = 9,
CLK_H_SNOR = 10, // HIDDEN.
CLK_H_JTAG2TBC = 11,
CLK_H_SPI2 = 12,
CLK_H_XIO = 13, // HIDDEN.
CLK_H_SPI3 = 14,
CLK_H_I2C5 = 15,
CLK_H_DSI = 16,
CLK_H_TVO = 17, // RESERVED.
CLK_H_HSI = 18, // HIDDEN.
CLK_H_HDMI = 19, // HIDDEN.
CLK_H_CSI = 20,
CLK_H_TVDAC = 21, // RESERVED.
CLK_H_I2C2 = 22,
CLK_H_UARTC = 23,
CLK_H_MIPI_CAL = 24,
CLK_H_EMC = 25,
CLK_H_USB2 = 26,
CLK_H_USB3 = 27, // HIDDEN.
CLK_H_MPE = 28, // HIDDEN.
CLK_H_VDE = 29, // HIDDEN.
CLK_H_BSEA = 30, // HIDDEN.
CLK_H_BSEV = 31,
};
enum CLK_U_DEV
{
CLK_U_SPEEDO = 0, // RESERVED.
CLK_U_UARTD = 1,
CLK_U_UARTE = 2, // HIDDEN.
CLK_U_I2C3 = 3,
CLK_U_SPI4 = 4,
CLK_U_SDMMC3 = 5,
CLK_U_PCIE = 6,
CLK_U_OWR = 7, // RESERVED.
CLK_U_AFI = 8,
CLK_U_CSITE = 9,
CLK_U_PCIEXCLK = 10, // Only reset.
CLK_U_BPMPUCQ = 11, // HIDDEN.
CLK_U_LA = 12,
CLK_U_TRACECLKIN = 13, // HIDDEN.
CLK_U_SOC_THERM = 14,
CLK_U_DTV = 15,
CLK_U_NAND_SPEED = 16, // HIDDEN.
CLK_U_I2C_SLOW = 17,
CLK_U_DSIB = 18,
CLK_U_TSEC = 19,
CLK_U_IRAMA = 20,
CLK_U_IRAMB = 21,
CLK_U_IRAMC = 22,
CLK_U_IRAMD = 23, // EMUCIF ON RESET
CLK_U_BPMP_CACHE_RAM = 24,
CLK_U_XUSB_HOST = 25,
CLK_U_CLK_M_DOUBLER = 26,
CLK_U_MSENC = 27, // HIDDEN.
CLK_U_SUS_OUT = 28,
CLK_U_DEV2_OUT = 29,
CLK_U_DEV1_OUT = 30,
CLK_U_XUSB_DEV = 31,
};
enum CLK_V_DEV
{
CLK_V_CPUG = 0,
CLK_V_CPULP = 1, // Reserved.
CLK_V_3D2 = 2, // HIDDEN.
CLK_V_MSELECT = 3,
CLK_V_TSENSOR = 4,
CLK_V_I2S4 = 5,
CLK_V_I2S5 = 6,
CLK_V_I2C4 = 7,
CLK_V_SPI5 = 8, // HIDDEN.
CLK_V_SPI6 = 9, // HIDDEN.
CLK_V_AHUB = 10, // AUDIO.
CLK_V_APB2APE = 11, // APBIF.
CLK_V_DAM0 = 12, // HIDDEN.
CLK_V_DAM1 = 13, // HIDDEN.
CLK_V_DAM2 = 14, // HIDDEN.
CLK_V_HDA2CODEC_2X = 15,
CLK_V_ATOMICS = 16,
//CLK_V_ = 17,
//CLK_V_ = 18,
//CLK_V_ = 19,
//CLK_V_ = 20,
//CLK_V_ = 21,
CLK_V_SPDIF_DOUBLER = 22,
CLK_V_ACTMON = 23,
CLK_V_EXTPERIPH1 = 24,
CLK_V_EXTPERIPH2 = 25,
CLK_V_EXTPERIPH3 = 26,
CLK_V_SATA_OOB = 27,
CLK_V_SATA = 28,
CLK_V_HDA = 29,
CLK_V_TZRAM = 30, // HIDDEN.
CLK_V_SE = 31, // HIDDEN.
};
enum CLK_W_DEV
{
CLK_W_HDA2HDMICODEC = 0,
CLK_W_RESERVED0 = 1, //satacoldrstn
CLK_W_PCIERX0 = 2,
CLK_W_PCIERX1 = 3,
CLK_W_PCIERX2 = 4,
CLK_W_PCIERX3 = 5,
CLK_W_PCIERX4 = 6,
CLK_W_PCIERX5 = 7,
CLK_W_CEC = 8,
CLK_W_PCIE2_IOBIST = 9,
CLK_W_EMC_IOBIST = 10,
CLK_W_HDMI_IOBIST = 11, // HIDDEN.
CLK_W_SATA_IOBIST = 12,
CLK_W_MIPI_IOBIST = 13,
CLK_W_XUSB_PADCTL = 14, // Only reset.
CLK_W_XUSB = 15,
CLK_W_CILAB = 16,
CLK_W_CILCD = 17,
CLK_W_CILEF = 18,
CLK_W_DSIA_LP = 19,
CLK_W_DSIB_LP = 20,
CLK_W_ENTROPY = 21,
CLK_W_DDS = 22, // HIDDEN.
//CLK_W_ = 23,
CLK_W_DP2 = 24, // HIDDEN.
CLK_W_AMX0 = 25, // HIDDEN.
CLK_W_ADX0 = 26, // HIDDEN.
CLK_W_DVFS = 27,
CLK_W_XUSB_SS = 28,
CLK_W_EMC_LATENCY = 29,
CLK_W_MC1 = 30,
//CLK_W_ = 31,
};
enum CLK_X_DEV
{
CLK_X_SPARE = 0,
CLK_X_DMIC1 = 1,
CLK_X_DMIC2 = 2,
CLK_X_ETR = 3,
CLK_X_CAM_MCLK = 4,
CLK_X_CAM_MCLK2 = 5,
CLK_X_I2C6 = 6,
CLK_X_MC_CAPA = 7, // MC DAISY CHAIN1
CLK_X_MC_CBPA = 8, // MC DAISY CHAIN2
CLK_X_MC_CPU = 9,
CLK_X_MC_BBC = 10,
CLK_X_VIM2_CLK = 11,
//CLK_X_ = 12,
CLK_X_MIPIBIF = 13, //RESERVED
CLK_X_EMC_DLL = 14,
//CLK_X_ = 15,
CLK_X_HDMI_AUDIO = 16, // HIDDEN.
CLK_X_UART_FST_MIPI_CAL = 17,
CLK_X_VIC = 18,
//CLK_X_ = 19,
CLK_X_ADX1 = 20, // HIDDEN.
CLK_X_DPAUX = 21,
CLK_X_SOR0 = 22,
CLK_X_SOR1 = 23,
CLK_X_GPU = 24,
CLK_X_DBGAPB = 25,
CLK_X_HPLL_ADSP = 26,
CLK_X_PLLP_ADSP = 27,
CLK_X_PLLA_ADSP = 28,
CLK_X_PLLG_REF = 29,
//CLK_X_ = 30,
//CLK_X_ = 31,
};
enum CLK_Y_DEV
{
CLK_Y_SPARE1 = 0,
CLK_Y_SDMMC_LEGACY_TM = 1,
CLK_Y_NVDEC = 2,
CLK_Y_NVJPG = 3,
CLK_Y_AXIAP = 4,
CLK_Y_DMIC3 = 5,
CLK_Y_APE = 6,
CLK_Y_ADSP = 7,
CLK_Y_MC_CDPA = 8, // MC DAISY CHAIN4
CLK_Y_MC_CCPA = 9, // MC DAISY CHAIN3
CLK_Y_MAUD = 10,
//CLK_Y_ = 11,
CLK_Y_SATA_USB_UPHY = 12, // Only reset.
CLK_Y_PEX_USB_UPHY = 13, // Only reset.
CLK_Y_TSECB = 14,
CLK_Y_DPAUX1 = 15,
CLK_Y_VI_I2C = 16,
CLK_Y_HSIC_TRK = 17,
CLK_Y_USB2_TRK = 18,
CLK_Y_QSPI = 19,
CLK_Y_UARTAPE = 20,
CLK_Y_ADSPINTF = 21, // Only reset.
CLK_Y_ADSPPERIPH = 22, // Only reset.
CLK_Y_ADSPDBG = 23, // Only reset.
CLK_Y_ADSPWDT = 24, // Only reset.
CLK_Y_ADSPSCU = 25, // Only reset.
CLK_Y_ADSPNEON = 26,
CLK_Y_NVENC = 27,
CLK_Y_IQC2 = 28,
CLK_Y_IQC1 = 29,
CLK_Y_SOR_SAFE = 30,
CLK_Y_PLLP_OUT_CPU = 31,
};
/*! Generic clock descriptor. */
typedef struct _clock_t
{
u16 reset;
u16 enable;
u16 source;
u8 index;
u8 clk_src;
u8 clk_div;
} clock_t;
/*! Generic clock enable/disable. */
void clock_enable(const clock_t *clk);
void clock_disable(const clock_t *clk);
/*! Clock control for specific hardware portions. */
void clock_enable_fuse(bool enable);
void clock_enable_uart(u32 idx);
void clock_disable_uart(u32 idx);
int clock_uart_use_src_div(u32 idx, u32 baud);
void clock_enable_i2c(u32 idx);
void clock_disable_i2c(u32 idx);
void clock_enable_se();
void clock_enable_tzram();
void clock_enable_host1x();
void clock_disable_host1x();
void clock_enable_tsec();
void clock_disable_tsec();
void clock_enable_sor_safe();
void clock_disable_sor_safe();
void clock_enable_sor0();
void clock_disable_sor0();
void clock_enable_sor1();
void clock_disable_sor1();
void clock_enable_kfuse();
void clock_disable_kfuse();
void clock_enable_cl_dvfs();
void clock_disable_cl_dvfs();
void clock_enable_coresight();
void clock_disable_coresight();
void clock_enable_pwm();
void clock_disable_pwm();
void clock_enable_pllx();
void clock_enable_pllc(u32 divn);
void clock_disable_pllc();
void clock_enable_pllu();
void clock_disable_pllu();
void clock_enable_utmipll();
void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val);
void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type);
int clock_sdmmc_is_not_reset_and_enabled(u32 id);
void clock_sdmmc_enable(u32 id, u32 val);
void clock_sdmmc_disable(u32 id);
u32 clock_get_osc_freq();
u32 clock_get_dev_freq(clock_pto_id_t id);
#endif

452
bdk/soc/fuse.c Normal file
View File

@@ -0,0 +1,452 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011
* Copyright (c) 2019-2021 CTCaer
* Copyright (c) 2021 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <sec/se.h>
#include <sec/se_t210.h>
#include <soc/fuse.h>
#include <soc/hw_init.h>
#include <soc/t210.h>
#include <utils/types.h>
static const u32 evp_thunk_template[] = {
0xe92d0007, // STMFD SP!, {R0-R2}
0xe1a0200e, // MOV R2, LR
0xe2422002, // SUB R2, R2, #2
0xe5922000, // LDR R2, [R2]
0xe20220ff, // AND R2, R2, #0xFF
0xe1a02082, // MOV R2, R2,LSL#1
0xe59f001c, // LDR R0, =evp_thunk_template
0xe59f101c, // LDR R1, =thunk_end
0xe0411000, // SUB R1, R1, R0
0xe59f0018, // LDR R0, =iram_evp_thunks
0xe0800001, // ADD R0, R0, R1
0xe0822000, // ADD R2, R2, R0
0xe3822001, // ORR R2, R2, #1
0xe8bd0003, // LDMFD SP!, {R0,R1}
0xe12fff12, // BX R2
0x001007b0, // off_1007EC DCD evp_thunk_template
0x001007f8, // off_1007F0 DCD thunk_end
0x40004c30, // off_1007F4 DCD iram_evp_thunks
// thunk_end is here
};
static const u32 evp_thunk_template_len = sizeof(evp_thunk_template);
// treated as 12bit values
static const u32 hash_vals[] = {1, 2, 4, 8, 0, 3, 5, 6, 7, 9, 10, 11};
void fuse_disable_program()
{
FUSE(FUSE_DISABLEREGPROGRAM) = 1;
}
u32 fuse_read_odm(u32 idx)
{
return FUSE(FUSE_RESERVED_ODMX(idx));
}
u32 fuse_read_odm_keygen_rev()
{
bool has_new_keygen;
// Check if it has new keygen.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
has_new_keygen = true;
else
has_new_keygen = (fuse_read_odm(4) & 0x800) && fuse_read_odm(0) == 0x8E61ECAE && fuse_read_odm(1) == 0xF2BA3BB2;
if (has_new_keygen)
return (fuse_read_odm(2) & 0x1F);
return 0;
}
u32 fuse_read_bootrom_rev()
{
u32 rev = FUSE(FUSE_SOC_SPEEDO_1_CALIB);
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
return rev;
else
return rev | (1 << 12);
}
u32 fuse_read_dramid(bool raw_id)
{
u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3;
if (raw_id)
return dramid;
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
if (dramid > 6)
dramid = 0;
}
else
{
if (dramid > 28)
dramid = 8;
}
return dramid;
}
u32 fuse_read_hw_state()
{
if ((fuse_read_odm(4) & 3) != 3)
return FUSE_NX_HW_STATE_PROD;
else
return FUSE_NX_HW_STATE_DEV;
}
u32 fuse_read_hw_type()
{
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
{
switch ((fuse_read_odm(4) & 0xF0000) >> 16)
{
case 2:
return FUSE_NX_HW_TYPE_HOAG;
case 4:
return FUSE_NX_HW_TYPE_AULA;
case 1:
default:
return FUSE_NX_HW_TYPE_IOWA;
}
}
return FUSE_NX_HW_TYPE_ICOSA;
}
int fuse_set_sbk()
{
if (FUSE(FUSE_PRIVATE_KEY0) != 0xFFFFFFFF)
{
// Read SBK from fuses.
u32 sbk[4] = {
FUSE(FUSE_PRIVATE_KEY0),
FUSE(FUSE_PRIVATE_KEY1),
FUSE(FUSE_PRIVATE_KEY2),
FUSE(FUSE_PRIVATE_KEY3)
};
// Set SBK to slot 14.
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
// Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
return 1;
}
return 0;
}
void fuse_wait_idle()
{
u32 ctrl;
do
{
ctrl = FUSE(FUSE_CTRL);
} while (((ctrl >> 16) & 0x1f) != 4);
}
u32 fuse_read(u32 addr)
{
FUSE(FUSE_ADDR) = addr;
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
fuse_wait_idle();
return FUSE(FUSE_RDATA);
}
void fuse_read_array(u32 *words)
{
u32 array_size = (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) ? 256 : 192;
for (u32 i = 0; i < array_size; i++)
words[i] = fuse_read(i);
}
static u32 _parity32_even(u32 *words, u32 count)
{
u32 acc = words[0];
for (u32 i = 1; i < count; i++)
{
acc ^= words[i];
}
u32 lo = ((acc & 0xffff) ^ (acc >> 16)) & 0xff;
u32 hi = ((acc & 0xffff) ^ (acc >> 16)) >> 8;
u32 x = hi ^ lo;
lo = ((x & 0xf) ^ (x >> 4)) & 3;
hi = ((x & 0xf) ^ (x >> 4)) >> 2;
x = hi ^ lo;
return (x & 1) ^ (x >> 1);
}
static int _patch_hash_one(u32 *word)
{
u32 bits20_31 = *word & 0xfff00000;
u32 parity_bit = _parity32_even(&bits20_31, 1);
u32 hash = 0;
for (u32 i = 0; i < 12; i++)
{
if (*word & (1 << (20 + i)))
{
hash ^= hash_vals[i];
}
}
if (hash == 0)
{
if (parity_bit == 0)
{
return 0;
}
*word ^= 1 << 24;
return 1;
}
if (parity_bit == 0)
{
return 3;
}
for (u32 i = 0; i < ARRAY_SIZE(hash_vals); i++)
{
if (hash_vals[i] == hash)
{
*word ^= 1 << (20 + i);
return 1;
}
}
return 2;
}
static int _patch_hash_multi(u32 *words, u32 count)
{
u32 parity_bit = _parity32_even(words, count);
u32 bits0_14 = words[0] & 0x7fff;
u32 bit15 = words[0] & 0x8000;
u32 bits16_19 = words[0] & 0xf0000;
u32 hash = 0;
words[0] = bits16_19;
for (u32 i = 0; i < count; i++)
{
u32 w = words[i];
if (w)
{
for (u32 bitpos = 0; bitpos < 32; bitpos++)
{
if ((w >> bitpos) & 1)
{
hash ^= 0x4000 + i * 32 + bitpos;
}
}
}
}
hash ^= bits0_14;
// stupid but this is what original code does.
// equivalent to original words[0] &= 0xfff00000
words[0] = bits16_19 ^ bit15 ^ bits0_14;
if (hash == 0)
{
if (parity_bit == 0)
{
return 0;
}
words[0] ^= 0x8000;
return 1;
}
if (parity_bit == 0)
{
return 3;
}
u32 bitcount = hash - 0x4000;
if (bitcount < 16 || bitcount >= count * 32)
{
u32 num_set = 0;
for (u32 bitpos = 0; bitpos < 15; bitpos++)
{
if ((hash >> bitpos) & 1)
{
num_set++;
}
}
if (num_set != 1)
{
return 2;
}
words[0] ^= hash;
return 1;
}
words[bitcount / 32] ^= 1 << (hash & 0x1f);
return 1;
}
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
{
u32 words[80];
u32 word_count;
u32 word_addr;
u32 word0 = 0;
u32 total_read = 0;
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
word_count &= 0x7F;
word_addr = 191;
while (word_count)
{
total_read += word_count;
if (total_read >= ARRAY_SIZE(words))
{
break;
}
for (u32 i = 0; i < word_count; i++)
words[i] = fuse_read(word_addr--);
word0 = words[0];
if (_patch_hash_multi(words, word_count) >= 2)
{
return 1;
}
u32 ipatch_count = (words[0] >> 16) & 0xF;
if (ipatch_count)
{
for (u32 i = 0; i < ipatch_count; i++)
{
u32 word = words[i + 1];
u32 addr = (word >> 16) * 2;
u32 data = word & 0xFFFF;
ipatch(addr, data);
}
}
words[0] = word0;
if ((word0 >> 25) == 0)
break;
if (_patch_hash_one(&word0) >= 2)
{
return 3;
}
word_count = word0 >> 25;
}
return 0;
}
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
{
u32 words[80];
u32 word_count;
u32 word_addr;
u32 word0 = 0;
u32 total_read = 0;
int evp_thunk_written = 0;
void *evp_thunk_dst_addr = 0;
memset(iram_evp_thunks, 0, *iram_evp_thunks_len);
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
word_count &= 0x7F;
word_addr = 191;
while (word_count)
{
total_read += word_count;
if (total_read >= ARRAY_SIZE(words))
{
break;
}
for (u32 i = 0; i < word_count; i++)
words[i] = fuse_read(word_addr--);
word0 = words[0];
if (_patch_hash_multi(words, word_count) >= 2)
{
return 1;
}
u32 ipatch_count = (words[0] >> 16) & 0xF;
u32 insn_count = word_count - ipatch_count - 1;
if (insn_count)
{
if (!evp_thunk_written)
{
evp_thunk_dst_addr = (void *)iram_evp_thunks;
memcpy(evp_thunk_dst_addr, (void *)evp_thunk_template, evp_thunk_template_len);
evp_thunk_dst_addr += evp_thunk_template_len;
evp_thunk_written = 1;
*iram_evp_thunks_len = evp_thunk_template_len;
//write32(TEGRA_EXCEPTION_VECTORS_BASE + 0x208, iram_evp_thunks);
}
u32 thunk_patch_len = insn_count * sizeof(u32);
memcpy(evp_thunk_dst_addr, &words[ipatch_count + 1], thunk_patch_len);
evp_thunk_dst_addr += thunk_patch_len;
*iram_evp_thunks_len += thunk_patch_len;
}
words[0] = word0;
if ((word0 >> 25) == 0)
break;
if (_patch_hash_one(&word0) >= 2)
{
return 3;
}
word_count = word0 >> 25;
}
return 0;
}
bool fuse_check_patched_rcm()
{
// Check if XUSB in use or Tegra X1+.
if (FUSE(FUSE_RESERVED_SW) & (1<<7) || hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
return true;
// Check if RCM is ipatched.
u32 word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE) & 0x7F;
u32 word_addr = 191;
while (word_count)
{
u32 word0 = fuse_read(word_addr);
u32 ipatch_count = (word0 >> 16) & 0xF;
for (u32 i = 0; i < ipatch_count; i++)
{
u32 word = fuse_read(word_addr - (i + 1));
u32 addr = (word >> 16) * 2;
if (addr == 0x769A)
return true;
}
word_addr -= word_count;
word_count = word0 >> 25;
}
return false;
}

110
bdk/soc/fuse.h Normal file
View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011
* Copyright (c) 2019-2021 CTCaer
* Copyright (c) 2021 shchmue
*
* 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 _FUSE_H_
#define _FUSE_H_
#include <utils/types.h>
/*! Fuse registers. */
#define FUSE_CTRL 0x0
#define FUSE_ADDR 0x4
#define FUSE_RDATA 0x8
#define FUSE_WDATA 0xC
#define FUSE_TIME_RD1 0x10
#define FUSE_TIME_RD2 0x14
#define FUSE_TIME_PGM1 0x18
#define FUSE_TIME_PGM2 0x1C
#define FUSE_PRIV2INTFC 0x20
#define FUSE_FUSEBYPASS 0x24
#define FUSE_PRIVATEKEYDISABLE 0x28
#define FUSE_DISABLEREGPROGRAM 0x2C
#define FUSE_WRITE_ACCESS_SW 0x30
#define FUSE_PWR_GOOD_SW 0x34
#define FUSE_SKU_INFO 0x110
#define FUSE_CPU_SPEEDO_0_CALIB 0x114
#define FUSE_CPU_IDDQ_CALIB 0x118
#define FUSE_OPT_FT_REV 0x128
#define FUSE_CPU_SPEEDO_1_CALIB 0x12C
#define FUSE_CPU_SPEEDO_2_CALIB 0x130
#define FUSE_SOC_SPEEDO_0_CALIB 0x134
#define FUSE_SOC_SPEEDO_1_CALIB 0x138
#define FUSE_SOC_SPEEDO_2_CALIB 0x13C
#define FUSE_SOC_IDDQ_CALIB 0x140
#define FUSE_OPT_CP_REV 0x190
#define FUSE_FIRST_BOOTROM_PATCH_SIZE 0x19c
#define FUSE_PRIVATE_KEY0 0x1A4
#define FUSE_PRIVATE_KEY1 0x1A8
#define FUSE_PRIVATE_KEY2 0x1AC
#define FUSE_PRIVATE_KEY3 0x1B0
#define FUSE_PRIVATE_KEY4 0x1B4
#define FUSE_RESERVED_SW 0x1C0
#define FUSE_USB_CALIB 0x1F0
#define FUSE_SKU_DIRECT_CONFIG 0x1F4
#define FUSE_OPT_VENDOR_CODE 0x200
#define FUSE_OPT_FAB_CODE 0x204
#define FUSE_OPT_LOT_CODE_0 0x208
#define FUSE_OPT_LOT_CODE_1 0x20C
#define FUSE_OPT_WAFER_ID 0x210
#define FUSE_OPT_X_COORDINATE 0x214
#define FUSE_OPT_Y_COORDINATE 0x218
#define FUSE_GPU_IDDQ_CALIB 0x228
#define FUSE_USB_CALIB_EXT 0x350
#define FUSE_RESERVED_ODM28_T210B01 0x240
/*! Fuse commands. */
#define FUSE_READ 0x1
#define FUSE_WRITE 0x2
#define FUSE_SENSE 0x3
#define FUSE_CMD_MASK 0x3
/*! Fuse cache registers. */
#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x))
enum
{
FUSE_NX_HW_TYPE_ICOSA,
FUSE_NX_HW_TYPE_IOWA,
FUSE_NX_HW_TYPE_HOAG,
FUSE_NX_HW_TYPE_AULA
};
enum
{
FUSE_NX_HW_STATE_PROD,
FUSE_NX_HW_STATE_DEV
};
void fuse_disable_program();
u32 fuse_read_odm(u32 idx);
u32 fuse_read_odm_keygen_rev();
u32 fuse_read_bootrom_rev();
u32 fuse_read_dramid(bool raw_id);
u32 fuse_read_hw_state();
u32 fuse_read_hw_type();
int fuse_set_sbk();
void fuse_wait_idle();
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
void fuse_read_array(u32 *words);
bool fuse_check_patched_rcm();
#endif

168
bdk/soc/gpio.c Normal file
View File

@@ -0,0 +1,168 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/gpio.h>
#include <soc/t210.h>
#define GPIO_BANK_IDX(port) ((port) >> 2)
#define GPIO_CNF_OFFSET(port) (0x00 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_OE_OFFSET(port) (0x10 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_OUT_OFFSET(port) (0x20 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_IN_OFFSET(port) (0x30 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_INT_STA_OFFSET(port) (0x40 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_INT_ENB_OFFSET(port) (0x50 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_INT_LVL_OFFSET(port) (0x60 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_INT_CLR_OFFSET(port) (0x70 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_OE_MASKED_OFFSET(port) (0x90 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + (((port) >> 2) << 8) + (((port) % 4) << 2))
#define GPIO_IRQ_BANK1 32
#define GPIO_IRQ_BANK2 33
#define GPIO_IRQ_BANK3 34
#define GPIO_IRQ_BANK4 35
#define GPIO_IRQ_BANK5 55
#define GPIO_IRQ_BANK6 87
#define GPIO_IRQ_BANK7 89
#define GPIO_IRQ_BANK8 125
static u8 gpio_bank_irq_ids[8] = {
GPIO_IRQ_BANK1, GPIO_IRQ_BANK2, GPIO_IRQ_BANK3, GPIO_IRQ_BANK4,
GPIO_IRQ_BANK5, GPIO_IRQ_BANK6, GPIO_IRQ_BANK7, GPIO_IRQ_BANK8
};
void gpio_config(u32 port, u32 pins, int mode)
{
u32 offset = GPIO_CNF_OFFSET(port);
if (mode)
GPIO(offset) |= pins;
else
GPIO(offset) &= ~pins;
(void)GPIO(offset); // Commit the write.
}
void gpio_output_enable(u32 port, u32 pins, int enable)
{
u32 port_offset = GPIO_OE_OFFSET(port);
if (enable)
GPIO(port_offset) |= pins;
else
GPIO(port_offset) &= ~pins;
(void)GPIO(port_offset); // Commit the write.
}
void gpio_write(u32 port, u32 pins, int high)
{
u32 port_offset = GPIO_OUT_OFFSET(port);
if (high)
GPIO(port_offset) |= pins;
else
GPIO(port_offset) &= ~pins;
(void)GPIO(port_offset); // Commit the write.
}
int gpio_read(u32 port, u32 pins)
{
u32 port_offset = GPIO_IN_OFFSET(port);
return (GPIO(port_offset) & pins) ? 1 : 0;
}
static void _gpio_interrupt_clear(u32 port, u32 pins)
{
u32 port_offset = GPIO_INT_CLR_OFFSET(port);
GPIO(port_offset) |= pins;
(void)GPIO(port_offset); // Commit the write.
}
int gpio_interrupt_status(u32 port, u32 pins)
{
u32 port_offset = GPIO_INT_STA_OFFSET(port);
u32 enabled = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins;
int status = ((GPIO(port_offset) & pins) && enabled) ? 1 : 0;
// Clear the interrupt status.
if (status)
_gpio_interrupt_clear(port, pins);
return status;
}
void gpio_interrupt_enable(u32 port, u32 pins, int enable)
{
u32 port_offset = GPIO_INT_ENB_OFFSET(port);
// Clear any possible stray interrupt.
_gpio_interrupt_clear(port, pins);
if (enable)
GPIO(port_offset) |= pins;
else
GPIO(port_offset) &= ~pins;
(void)GPIO(port_offset); // Commit the write.
}
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta)
{
u32 port_offset = GPIO_INT_LVL_OFFSET(port);
u32 val = GPIO(port_offset);
if (high)
val |= pins;
else
val &= ~pins;
if (edge)
val |= pins << 8;
else
val &= ~(pins << 8);
if (delta)
val |= pins << 16;
else
val &= ~(pins << 16);
GPIO(port_offset) = val;
(void)GPIO(port_offset); // Commit the write.
// Clear any possible stray interrupt.
_gpio_interrupt_clear(port, pins);
}
u32 gpio_get_bank_irq_id(u32 port)
{
u32 bank_idx = GPIO_BANK_IDX(port);
return gpio_bank_irq_ids[bank_idx];
}

95
bdk/soc/gpio.h Normal file
View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer
*
* 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 _GPIO_H_
#define _GPIO_H_
#include <utils/types.h>
#define GPIO_MODE_SPIO 0
#define GPIO_MODE_GPIO 1
#define GPIO_OUTPUT_DISABLE 0
#define GPIO_OUTPUT_ENABLE 1
#define GPIO_IRQ_DISABLE 0
#define GPIO_IRQ_ENABLE 1
#define GPIO_LOW 0
#define GPIO_HIGH 1
#define GPIO_FALLING 0
#define GPIO_RISING 1
#define GPIO_LEVEL 0
#define GPIO_EDGE 1
#define GPIO_CONFIGURED_EDGE 0
#define GPIO_ANY_EDGE_CHANGE 1
/*! GPIO pins (0-7 for each port). */
#define GPIO_PIN_0 BIT(0)
#define GPIO_PIN_1 BIT(1)
#define GPIO_PIN_2 BIT(2)
#define GPIO_PIN_3 BIT(3)
#define GPIO_PIN_4 BIT(4)
#define GPIO_PIN_5 BIT(5)
#define GPIO_PIN_6 BIT(6)
#define GPIO_PIN_7 BIT(7)
/*! GPIO ports (A-EE). */
#define GPIO_PORT_A 0
#define GPIO_PORT_B 1
#define GPIO_PORT_C 2
#define GPIO_PORT_D 3
#define GPIO_PORT_E 4
#define GPIO_PORT_F 5
#define GPIO_PORT_G 6
#define GPIO_PORT_H 7
#define GPIO_PORT_I 8
#define GPIO_PORT_J 9
#define GPIO_PORT_K 10
#define GPIO_PORT_L 11
#define GPIO_PORT_M 12
#define GPIO_PORT_N 13
#define GPIO_PORT_O 14
#define GPIO_PORT_P 15
#define GPIO_PORT_Q 16
#define GPIO_PORT_R 17
#define GPIO_PORT_S 18
#define GPIO_PORT_T 19
#define GPIO_PORT_U 20
#define GPIO_PORT_V 21
#define GPIO_PORT_W 22
#define GPIO_PORT_X 23
#define GPIO_PORT_Y 24
#define GPIO_PORT_Z 25
#define GPIO_PORT_AA 26
#define GPIO_PORT_BB 27
#define GPIO_PORT_CC 28
#define GPIO_PORT_DD 29
#define GPIO_PORT_EE 30
void gpio_config(u32 port, u32 pins, int mode);
void gpio_output_enable(u32 port, u32 pins, int enable);
void gpio_write(u32 port, u32 pins, int high);
int gpio_read(u32 port, u32 pins);
int gpio_interrupt_status(u32 port, u32 pins);
void gpio_interrupt_enable(u32 port, u32 pins, int enable);
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta);
u32 gpio_get_bank_irq_id(u32 port);
#endif

479
bdk/soc/hw_init.c Normal file
View File

@@ -0,0 +1,479 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <soc/hw_init.h>
#include <display/di.h>
#include <input/joycon.h>
#include <input/touch.h>
#include <sec/se.h>
#include <sec/se_t210.h>
#include <soc/bpmp.h>
#include <soc/clock.h>
#include <soc/fuse.h>
#include <soc/gpio.h>
#include <soc/i2c.h>
#include <soc/pinmux.h>
#include <soc/pmc.h>
#include <soc/uart.h>
#include <soc/t210.h>
#include <mem/mc.h>
#include <mem/minerva.h>
#include <mem/sdram.h>
#include <power/bq24193.h>
#include <power/max77620.h>
#include <power/max7762x.h>
#include <power/regulator_5v.h>
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <thermal/fan.h>
#include <thermal/tmp451.h>
#include <utils/util.h>
extern boot_cfg_t b_cfg;
extern volatile nyx_storage_t *nyx_str;
u32 hw_rst_status;
u32 hw_rst_reason;
u32 hw_get_chip_id()
{
if (((APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01)
return GP_HIDREV_MAJOR_T210B01;
else
return GP_HIDREV_MAJOR_T210;
}
/*
* CLK_OSC - 38.4 MHz crystal.
* CLK_M - 19.2 MHz (osc/2).
* CLK_S - 32.768 KHz (from PMIC).
* SCLK - 204MHz init (-> 408MHz -> OC).
* HCLK - 204MHz init (-> 408MHz -> OC).
* PCLK - 68MHz init (-> 136MHz -> OC/4).
*/
static void _config_oscillators()
{
CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2.
SYSCTR0(SYSCTR0_CNTFID0) = 19200000; // Set counter frequency.
TMR(TIMERUS_USEC_CFG) = 0x45F; // For 19.2MHz clk_m.
CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; // Set OSC to 38.4MHz and drive strength.
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81) | 0xE; // Set LP0 OSC drive strength.
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF) | PMC_OSC_EDPD_OVER_OSC_CTRL_OVER;
PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | PMC_CNTRL2_HOLD_CKE_LOW_EN;
PMC(APBDEV_PMC_SCRATCH188) = (PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF) | (4 << 23); // LP0 EMC2TMC_CFG_XM2COMP_PU_VREF_SEL_RANGE.
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; // Set HCLK div to 2 and PCLK div to 1.
CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; // PLLMB disable.
PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz)
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set BPMP/SCLK div to 1.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set BPMP/SCLK source to Run and PLLP_OUT2 (204MHz).
CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; // Enable SUPER_SDIV to 1.
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
}
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
static void _config_gpios(bool nx_hoag)
{
// Clamp inputs when tristated.
APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0;
if (!nx_hoag)
{
PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0;
PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0;
// Set pin mode for UARTB/C TX pins.
#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_B
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
#endif
#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_C
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
#endif
// Enable input logic for UARTB/C TX pins.
gpio_output_enable(GPIO_PORT_G, GPIO_PIN_0, GPIO_OUTPUT_DISABLE);
gpio_output_enable(GPIO_PORT_D, GPIO_PIN_1, GPIO_OUTPUT_DISABLE);
}
// Set Joy-Con IsAttached direction.
PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
// Set Joy-Con IsAttached mode.
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO);
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO);
// Enable input logic for Joy-Con IsAttached pins.
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_6, GPIO_OUTPUT_DISABLE);
gpio_output_enable(GPIO_PORT_H, GPIO_PIN_6, GPIO_OUTPUT_DISABLE);
pinmux_config_i2c(I2C_1);
pinmux_config_i2c(I2C_5);
pinmux_config_uart(UART_A);
// Configure volume up/down as inputs.
gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO);
gpio_config(GPIO_PORT_X, GPIO_PIN_7, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_X, GPIO_PIN_6, GPIO_OUTPUT_DISABLE);
gpio_output_enable(GPIO_PORT_X, GPIO_PIN_7, GPIO_OUTPUT_DISABLE);
// Configure HOME as inputs.
// PINMUX_AUX(PINMUX_AUX_BUTTON_HOME) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
// gpio_config(GPIO_PORT_Y, GPIO_PIN_1, GPIO_MODE_GPIO);
}
static void _config_pmc_scratch()
{
PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option.
PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; // Unset DATA_DQ_E_IVREF EMC_PMACRO_DATA_PAD_TX_CTRL
PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT;
}
static void _mbist_workaround()
{
// Make sure Audio clocks are enabled before accessing I2S.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
// Set mux output to SOR1 clock switch.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) | 0x8000) & 0xFFFFBFFF;
// Enabled PLLD and set csi to PLLD for test pattern generation.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) |= 0x40800000;
// Clear per-clock resets for APE/VIC/HOST1X/DISP1.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = BIT(CLK_Y_APE);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = BIT(CLK_X_VIC);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
usleep(2);
// I2S channels to master and disable SLCG.
I2S(I2S1_CTRL) |= I2S_CTRL_MASTER_EN;
I2S(I2S1_CG) &= ~I2S_CG_SLCG_ENABLE;
I2S(I2S2_CTRL) |= I2S_CTRL_MASTER_EN;
I2S(I2S2_CG) &= ~I2S_CG_SLCG_ENABLE;
I2S(I2S3_CTRL) |= I2S_CTRL_MASTER_EN;
I2S(I2S3_CG) &= ~I2S_CG_SLCG_ENABLE;
I2S(I2S4_CTRL) |= I2S_CTRL_MASTER_EN;
I2S(I2S4_CG) &= ~I2S_CG_SLCG_ENABLE;
I2S(I2S5_CTRL) |= I2S_CTRL_MASTER_EN;
I2S(I2S5_CG) &= ~I2S_CG_SLCG_ENABLE;
DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= 4; // DSC_SLCG_OVERRIDE.
VIC(0x8C) = 0xFFFFFFFF;
usleep(2);
// Set per-clock reset for APE/VIC/HOST1X/DISP1.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = BIT(CLK_Y_APE);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = BIT(CLK_X_VIC);
// Enable specific clocks and disable all others.
// CLK L Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) =
BIT(CLK_H_PMC) |
BIT(CLK_H_FUSE);
// CLK H Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) =
BIT(CLK_L_RTC) |
BIT(CLK_L_TMR) |
BIT(CLK_L_GPIO) |
BIT(CLK_L_BPMP_CACHE_CTRL);
// CLK U Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) =
BIT(CLK_U_CSITE) |
BIT(CLK_U_IRAMA) |
BIT(CLK_U_IRAMB) |
BIT(CLK_U_IRAMC) |
BIT(CLK_U_IRAMD) |
BIT(CLK_U_BPMP_CACHE_RAM);
// CLK V Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) =
BIT(CLK_V_MSELECT) |
BIT(CLK_V_APB2APE) |
BIT(CLK_V_SPDIF_DOUBLER) |
BIT(CLK_V_SE);
// CLK W Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) =
BIT(CLK_W_PCIERX0) |
BIT(CLK_W_PCIERX1) |
BIT(CLK_W_PCIERX2) |
BIT(CLK_W_PCIERX3) |
BIT(CLK_W_PCIERX4) |
BIT(CLK_W_PCIERX5) |
BIT(CLK_W_ENTROPY) |
BIT(CLK_W_MC1);
// CLK X Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) =
BIT(CLK_X_MC_CAPA) |
BIT(CLK_X_MC_CBPA) |
BIT(CLK_X_MC_CPU) |
BIT(CLK_X_MC_BBC) |
BIT(CLK_X_GPU) |
BIT(CLK_X_DBGAPB) |
BIT(CLK_X_PLLG_REF);
// CLK Y Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) =
BIT(CLK_Y_MC_CDPA) |
BIT(CLK_Y_MC_CCPA);
// Disable clock gate overrides.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA) = 0;
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB) = 0;
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC) = 0;
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = 0;
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE) = 0;
// Set child clock sources.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF; // Disable PLLD and set reference clock and csi clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF; // Set SOR1 to automatic muxing of safe clock (24MHz) or SOR1 clk switch.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
}
static void _config_se_brom()
{
// Enable Fuse visibility.
clock_enable_fuse(true);
// Try to set SBK from fuses. If patched, skip.
fuse_set_sbk();
// Lock SSK (although it's not set and unused anyways).
// se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG);
// This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, SZ_64K);
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
// Save reset reason.
hw_rst_status = PMC(APBDEV_PMC_SCRATCH200);
hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK;
// Clear the boot reason to avoid problems later.
PMC(APBDEV_PMC_SCRATCH200) = 0x0;
PMC(APBDEV_PMC_RST_STATUS) = 0x0;
APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10);
}
static void _config_regulators(bool tegra_t210)
{
// Set RTC/AO domain to POR voltage.
if (tegra_t210)
max7762x_regulator_set_voltage(REGULATOR_LDO4, 1000000);
// Disable low battery shutdown monitor.
max77620_low_battery_monitor_config(false);
// Disable SDMMC1 IO power.
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
max7762x_regulator_enable(REGULATOR_LDO2, false);
sd_power_cycle_time_start = get_tmr_ms();
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1,
MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
if (tegra_t210)
{
// Configure all Flexible Power Sequencers for MAX77620.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT));
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (1 << MAX77620_FPS_EN_SRC_SHIFT));
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG2, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT));
max77620_regulator_config_fps(REGULATOR_LDO4);
max77620_regulator_config_fps(REGULATOR_LDO8);
max77620_regulator_config_fps(REGULATOR_SD0);
max77620_regulator_config_fps(REGULATOR_SD1);
max77620_regulator_config_fps(REGULATOR_SD3);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3,
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
// Set vdd_core voltage to 1.125V.
max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000);
// Fix CPU/GPU after L4T warmboot.
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE);
max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE);
// Set POR configuration.
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG);
max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG);
}
else // Tegra X1+ set vdd_core voltage to 1.05V.
max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000);
}
void hw_init()
{
// Get Chip ID.
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
bool nx_hoag = fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG;
// Bootrom stuff we skipped by going through rcm.
_config_se_brom();
//FUSE(FUSE_PRIVATEKEYDISABLE) = 0x11;
SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F; // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN.
PMC(APBDEV_PMC_SCRATCH49) = PMC(APBDEV_PMC_SCRATCH49) & 0xFFFFFFFC;
// Perform Memory Built-In Self Test WAR if T210.
if (tegra_t210)
_mbist_workaround();
// Enable Security Engine clock.
clock_enable_se();
// Enable Fuse visibility.
clock_enable_fuse(true);
// Disable Fuse programming.
fuse_disable_program();
// Enable clocks to Memory controllers and disable AHB redirect.
mc_enable();
// Initialize counters, CLKM, BPMP and other clocks based on 38.4MHz oscillator.
_config_oscillators();
// Initialize pin configuration.
_config_gpios(nx_hoag);
#ifdef DEBUG_UART_PORT
clock_enable_uart(DEBUG_UART_PORT);
uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE);
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
#endif
// Enable Dynamic Voltage and Frequency Scaling device clock.
clock_enable_cl_dvfs();
// Enable clocks to I2C1 and I2CPWR.
clock_enable_i2c(I2C_1);
clock_enable_i2c(I2C_5);
// Enable clock to TZRAM.
clock_enable_tzram();
// Initialize I2C5, mandatory for PMIC.
i2c_init(I2C_5);
//! TODO: Why? Device is NFC MCU on Lite.
if (nx_hoag)
{
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
max7762x_regulator_enable(REGULATOR_LDO8, true);
}
// Initialize I2C1 for various power related devices.
i2c_init(I2C_1);
// Initialize various regulators based on Erista/Mariko platform.
_config_regulators(tegra_t210);
// Enable charger in case it's disabled.
bq24193_enable_charger();
_config_pmc_scratch(); // Missing from 4.x+
// Set BPMP/SCLK to PLLP_OUT (408MHz).
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333;
// Disable TZRAM shutdown control and lock the regs.
if (!tegra_t210)
{
PMC(APBDEV_PMC_TZRAM_PWR_CNTRL) &= 0xFFFFFFFE;
PMC(APBDEV_PMC_TZRAM_NON_SEC_DISABLE) = 3;
PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = 3;
}
// Initialize External memory controller and configure DRAM parameters.
sdram_init();
bpmp_mmu_enable();
}
void hw_reinit_workaround(bool coreboot, u32 bl_magic)
{
// Disable BPMP max clock.
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
#ifdef NYX
// Disable temperature sensor, touchscreen, 5V regulators and Joy-Con.
tmp451_end();
set_fan_duty(0);
touch_power_off();
jc_deinit();
regulator_5v_disable(REGULATOR_5V_ALL);
#endif
// Flush/disable MMU cache and set DRAM clock to 204MHz.
bpmp_mmu_disable();
minerva_change_freq(FREQ_204);
nyx_str->mtc_cfg.init_done = 0;
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
// Do coreboot mitigations.
if (coreboot)
{
msleep(10);
clock_disable_cl_dvfs();
// Disable Joy-con GPIOs.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO);
// Reinstate SD controller power.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
}
// Seamless display or display power off.
switch (bl_magic)
{
case BL_MAGIC_CRBOOT_SLD:;
// Set pwm to 0%, switch to gpio mode and restore pwm duty.
u32 brightness = display_get_backlight_brightness();
display_backlight_brightness(0, 1000);
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO);
display_backlight_brightness(brightness, 0);
break;
default:
display_end();
}
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
if (bl_magic == BL_MAGIC_BROKEN_HWI)
{
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
clock_disable_cl_dvfs();
msleep(200);
}
}

33
bdk/soc/hw_init.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* 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 _HW_INIT_H_
#define _HW_INIT_H_
#include <utils/types.h>
#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0.
#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit.
extern u32 hw_rst_status;
extern u32 hw_rst_reason;
void hw_init();
void hw_reinit_workaround(bool coreboot, u32 magic);
u32 hw_get_chip_id();
#endif

424
bdk/soc/i2c.c Normal file
View File

@@ -0,0 +1,424 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <soc/i2c.h>
#include <utils/util.h>
#define I2C_PACKET_PROT_I2C BIT(4)
#define I2C_HEADER_CONT_XFER BIT(15)
#define I2C_HEADER_REP_START BIT(16)
#define I2C_HEADER_IE_ENABLE BIT(17)
#define I2C_HEADER_READ BIT(19)
#define I2C_CNFG (0x00 / 4)
#define CMD1_WRITE (0 << 6)
#define CMD1_READ BIT(6)
#define NORMAL_MODE_GO BIT(9)
#define PACKET_MODE_GO BIT(10)
#define NEW_MASTER_FSM BIT(11)
#define DEBOUNCE_CNT_4T (2 << 12)
#define I2C_CMD_ADDR0 (0x04 / 4)
#define ADDR0_WRITE 0
#define ADDR0_READ 1
#define I2C_CMD_DATA1 (0x0C / 4)
#define I2C_CMD_DATA2 (0x10 / 4)
#define I2C_STATUS (0x1C / 4)
#define I2C_STATUS_NOACK (0xF << 0)
#define I2C_STATUS_BUSY BIT(8)
#define I2C_TX_FIFO (0x50 / 4)
#define I2C_RX_FIFO (0x54 / 4)
#define I2C_FIFO_CONTROL (0x5C / 4)
#define RX_FIFO_FLUSH BIT(0)
#define TX_FIFO_FLUSH BIT(1)
#define I2C_FIFO_STATUS (0x60 / 4)
#define RX_FIFO_FULL_CNT (0xF << 0)
#define TX_FIFO_EMPTY_CNT (0xF << 4)
#define I2C_INT_EN (0x64 / 4)
#define I2C_INT_STATUS (0x68 / 4)
#define I2C_INT_SOURCE (0x70 / 4)
#define RX_FIFO_DATA_REQ BIT(0)
#define TX_FIFO_DATA_REQ BIT(1)
#define ARB_LOST BIT(2)
#define NO_ACK BIT(3)
#define RX_FIFO_UNDER BIT(4)
#define TX_FIFO_OVER BIT(5)
#define ALL_PACKETS_COMPLETE BIT(6)
#define PACKET_COMPLETE BIT(7)
#define BUS_CLEAR_DONE BIT(11)
#define I2C_CLK_DIVISOR (0x6C / 4)
#define I2C_BUS_CLEAR_CONFIG (0x84 / 4)
#define BC_ENABLE BIT(0)
#define BC_TERMINATE BIT(1)
#define I2C_BUS_CLEAR_STATUS (0x88 / 4)
#define I2C_CONFIG_LOAD (0x8C / 4)
#define MSTR_CONFIG_LOAD BIT(0)
#define TIMEOUT_CONFIG_LOAD BIT(2)
static const u32 i2c_addrs[] = {
0x7000C000, // I2C_1.
0x7000C400, // I2C_2.
0x7000C500, // I2C_3.
0x7000C700, // I2C_4.
0x7000D000, // I2C_5.
0x7000D100 // I2C_6.
};
static void _i2c_load_cfg_wait(vu32 *base)
{
base[I2C_CONFIG_LOAD] = BIT(5) | TIMEOUT_CONFIG_LOAD | MSTR_CONFIG_LOAD;
for (u32 i = 0; i < 20; i++)
{
usleep(1);
if (!(base[I2C_CONFIG_LOAD] & MSTR_CONFIG_LOAD))
break;
}
}
static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
{
if (size > 8)
return 0;
u32 tmp = 0;
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
// Set device address and send mode.
base[I2C_CMD_ADDR0] = dev_addr << 1 | ADDR0_WRITE;
if (size > 4)
{
memcpy(&tmp, buf, 4);
base[I2C_CMD_DATA1] = tmp; //Set value.
tmp = 0;
memcpy(&tmp, buf + 4, size - 4);
base[I2C_CMD_DATA2] = tmp;
}
else
{
memcpy(&tmp, buf, size);
base[I2C_CMD_DATA1] = tmp; //Set value.
}
// Set size and send mode.
base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE;
// Load configuration.
_i2c_load_cfg_wait(base);
// Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{
if (get_tmr_us() > timeout)
return 0;
}
if (base[I2C_STATUS] & I2C_STATUS_NOACK)
return 0;
return 1;
}
static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
{
if (size > 8)
return 0;
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
// Set device address and recv mode.
base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ;
// Set size and recv mode.
base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_READ;
// Load configuration.
_i2c_load_cfg_wait(base);
// Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{
if (get_tmr_us() > timeout)
return 0;
}
if (base[I2C_STATUS] & I2C_STATUS_NOACK)
return 0;
u32 tmp = base[I2C_CMD_DATA1]; // Get LS value.
if (size > 4)
{
memcpy(buf, &tmp, 4);
tmp = base[I2C_CMD_DATA2]; // Get MS value.
memcpy(buf + 4, &tmp, size - 4);
}
else
memcpy(buf, &tmp, size);
return 1;
}
static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
{
if (size > 32)
return 0;
int res = 0;
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
// Enable interrupts.
base[I2C_INT_EN] = ALL_PACKETS_COMPLETE | PACKET_COMPLETE | NO_ACK |
ARB_LOST | TX_FIFO_OVER | RX_FIFO_UNDER | TX_FIFO_DATA_REQ;
base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
// Set device address and recv mode.
base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ;
// Set recv mode.
base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE;
// Set and flush FIFO.
base[I2C_FIFO_CONTROL] = RX_FIFO_FLUSH | TX_FIFO_FLUSH;
// Load configuration.
_i2c_load_cfg_wait(base);
// Initiate transaction on packet mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | PACKET_MODE_GO;
u32 hdr[3];
hdr[0] = I2C_PACKET_PROT_I2C;
hdr[1] = size - 1;
hdr[2] = I2C_HEADER_IE_ENABLE | I2C_HEADER_CONT_XFER | (dev_addr << 1);
// Send header with request.
base[I2C_TX_FIFO] = hdr[0];
base[I2C_TX_FIFO] = hdr[1];
base[I2C_TX_FIFO] = hdr[2];
u32 timeout = get_tmr_ms() + 400;
while (size)
{
if (base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT)
{
u32 tmp = 0;
u32 snd_size = MIN(size, 4);
memcpy(&tmp, buf, snd_size);
base[I2C_TX_FIFO] = tmp;
buf += snd_size;
size -= snd_size;
}
if (get_tmr_ms() > timeout)
{
res = 1;
break;
}
}
if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK)
res = 1;
// Disable packet mode.
usleep(20);
base[I2C_CNFG] &= 0xFFFFF9FF;
// Disable interrupts.
base[I2C_INT_EN] = 0;
return res;
}
static int _i2c_recv_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg)
{
if (size > 32)
return 0;
int res = 0;
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
// Enable interrupts.
base[I2C_INT_EN] = ALL_PACKETS_COMPLETE | PACKET_COMPLETE | NO_ACK |
ARB_LOST | TX_FIFO_OVER | RX_FIFO_UNDER | RX_FIFO_DATA_REQ;
base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
// Set device address and recv mode.
base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ;
// Set recv mode.
base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_READ;
// Set and flush FIFO.
base[I2C_FIFO_CONTROL] = RX_FIFO_FLUSH | TX_FIFO_FLUSH;
// Load configuration.
_i2c_load_cfg_wait(base);
// Initiate transaction on packet mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | PACKET_MODE_GO;
// Send reg request.
u32 hdr[3];
hdr[0] = I2C_PACKET_PROT_I2C;
hdr[1] = 1 - 1;
hdr[2] = I2C_HEADER_REP_START | (dev_addr << 1);
// Send header with reg request.
base[I2C_TX_FIFO] = hdr[0];
base[I2C_TX_FIFO] = hdr[1];
base[I2C_TX_FIFO] = hdr[2];
base[I2C_TX_FIFO] = reg;
u32 timeout = get_tmr_ms() + 400;
while (!(base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT))
if (get_tmr_ms() > timeout)
break;
// Send read request.
hdr[1] = size - 1;
hdr[2] = I2C_HEADER_READ | (dev_addr << 1);
// Send header with read request.
base[I2C_TX_FIFO] = hdr[0];
base[I2C_TX_FIFO] = hdr[1];
base[I2C_TX_FIFO] = hdr[2];
timeout = get_tmr_ms() + 400;
while (size)
{
if (base[I2C_FIFO_STATUS] & RX_FIFO_FULL_CNT)
{
u32 rcv_size = MIN(size, 4);
u32 tmp = base[I2C_RX_FIFO];
memcpy(buf, &tmp, rcv_size);
buf += rcv_size;
size -= rcv_size;
}
if (get_tmr_ms() > timeout)
{
res = 1;
break;
}
}
if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK)
res = 1;
// Disable packet mode.
usleep(20);
base[I2C_CNFG] &= 0xFFFFF9FF;
// Disable interrupts.
base[I2C_INT_EN] = 0;
return res;
}
void i2c_init(u32 i2c_idx)
{
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
base[I2C_CLK_DIVISOR] = (5 << 16) | 1; // SF mode Div: 6, HS mode div: 2.
base[I2C_BUS_CLEAR_CONFIG] = (9 << 16) | BC_TERMINATE | BC_ENABLE;
// Load configuration.
_i2c_load_cfg_wait(base);
for (u32 i = 0; i < 10; i++)
{
usleep(20000);
if (base[I2C_INT_STATUS] & BUS_CLEAR_DONE)
break;
}
(vu32)base[I2C_BUS_CLEAR_STATUS];
base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
}
int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr)
{
return _i2c_recv_single(i2c_idx, buf, size, dev_addr);
}
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
{
if (size > 32)
return 0;
return _i2c_send_pkt(i2c_idx, buf, size, dev_addr);
}
int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
{
return _i2c_recv_pkt(i2c_idx, buf, size, dev_addr, reg);
}
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size)
{
u8 tmp[4];
if (size > 7)
return 0;
tmp[0] = reg;
memcpy(tmp + 1, buf, size);
return _i2c_send_single(i2c_idx, dev_addr, tmp, size + 1);
}
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
{
int res = _i2c_send_single(i2c_idx, dev_addr, (u8 *)&reg, 1);
if (res)
res = _i2c_recv_single(i2c_idx, buf, size, dev_addr);
return res;
}
int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val)
{
return i2c_send_buf_small(i2c_idx, dev_addr, reg, &val, 1);
}
u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg)
{
u8 tmp = 0;
i2c_recv_buf_small(&tmp, 1, i2c_idx, dev_addr, reg);
return tmp;
}

39
bdk/soc/i2c.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2020 CTCaer
*
* 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 _I2C_H_
#define _I2C_H_
#include <utils/types.h>
#define I2C_1 0
#define I2C_2 1
#define I2C_3 2
#define I2C_4 3
#define I2C_5 4
#define I2C_6 5
void i2c_init(u32 i2c_idx);
int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr);
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size);
int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size);
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val);
u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg);
#endif

273
bdk/soc/irq.c Normal file
View File

@@ -0,0 +1,273 @@
/*
* BPMP-Lite IRQ driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "irq.h"
#include <soc/t210.h>
#include <gfx_utils.h>
#include <mem/heap.h>
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
extern void irq_disable();
extern void irq_enable_cpu_irq_exceptions();
extern void irq_disable_cpu_irq_exceptions();
typedef struct _irq_ctxt_t
{
u32 irq;
int (*handler)(u32 irq, void *data);
void *data;
u32 flags;
} irq_ctxt_t;
bool irq_init_done = false;
irq_ctxt_t irqs[IRQ_MAX_HANDLERS];
static void _irq_enable_source(u32 irq)
{
u32 ctrl_idx = irq >> 5;
u32 bit = irq % 32;
// Set as normal IRQ.
ICTLR(ctrl_idx, PRI_ICTLR_COP_IEP_CLASS) &= ~BIT(bit);
// Enable IRQ source.
ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_SET) = BIT(bit);
}
static void _irq_disable_source(u32 irq)
{
u32 ctrl_idx = irq >> 5;
u32 bit = irq % 32;
// Disable IRQ source.
ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = BIT(bit);
}
static void _irq_disable_and_ack_all()
{
// Disable and ack all IRQ sources.
for (u32 ctrl_idx = 0; ctrl_idx < 6; ctrl_idx++)
{
u32 enabled_irqs = ICTLR(ctrl_idx, PRI_ICTLR_COP_IER);
ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = enabled_irqs;
ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs;
}
}
static void _irq_ack_source(u32 irq)
{
u32 ctrl_idx = irq >> 5;
u32 bit = irq % 32;
// Force stop the interrupt as it's serviced here.
ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = BIT(bit);
}
void irq_free(u32 irq)
{
for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
{
if (irqs[idx].irq == irq && irqs[idx].handler)
{
irqs[idx].irq = 0;
irqs[idx].handler = NULL;
irqs[idx].data = NULL;
irqs[idx].flags = 0;
_irq_disable_source(irq);
}
}
}
static void _irq_free_all()
{
for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
{
if (irqs[idx].handler)
{
_irq_disable_source(irqs[idx].irq);
irqs[idx].irq = 0;
irqs[idx].handler = NULL;
irqs[idx].data = NULL;
irqs[idx].flags = 0;
}
}
}
static irq_status_t _irq_handle_source(u32 irq)
{
int status = IRQ_NONE;
_irq_disable_source(irq);
_irq_ack_source(irq);
u32 idx;
for (idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
{
if (irqs[idx].irq == irq)
{
status = irqs[idx].handler(irqs[idx].irq, irqs[idx].data);
if (status == IRQ_HANDLED)
break;
}
}
// Do not re-enable if not handled.
if (status == IRQ_NONE)
return status;
if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
irq_free(irq);
else
_irq_enable_source(irq);
return status;
}
void irq_handler()
{
// Get IRQ source.
u32 irq = EXCP_VEC(EVP_COP_IRQ_STS) & 0xFF;
if (!irq_init_done)
{
_irq_disable_source(irq);
_irq_ack_source(irq);
return;
}
DPRINTF("IRQ: %d\n", irq);
int err = _irq_handle_source(irq);
if (err == IRQ_NONE)
{
DPRINTF("Unhandled IRQ got disabled: %d!\n", irq);
}
}
static void _irq_init()
{
_irq_disable_and_ack_all();
memset(irqs, 0, sizeof(irq_ctxt_t) * IRQ_MAX_HANDLERS);
irq_init_done = true;
}
void irq_end()
{
if (!irq_init_done)
return;
_irq_free_all();
irq_disable_cpu_irq_exceptions();
irq_init_done = false;
}
void irq_wait_event(u32 irq)
{
irq_disable_cpu_irq_exceptions();
_irq_enable_source(irq);
// Halt BPMP and wait for the IRQ. No need to use WAIT_EVENT + LIC_IRQ when BPMP serves the IRQ.
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_STOP_UNTIL_IRQ;
_irq_disable_source(irq);
_irq_ack_source(irq);
irq_enable_cpu_irq_exceptions();
}
void irq_disable_wait_event()
{
irq_enable_cpu_irq_exceptions();
}
irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t flags)
{
if (!irq_init_done)
_irq_init();
for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
{
if (irqs[idx].handler == NULL ||
(irqs[idx].irq == irq && irqs[idx].flags & IRQ_FLAG_REPLACEABLE))
{
DPRINTF("Registered handler, IRQ: %d, Slot: %d\n", irq, idx);
DPRINTF("Handler: %08p, Flags: %x\n", (u32)handler, flags);
irqs[idx].irq = irq;
irqs[idx].handler = handler;
irqs[idx].data = data;
irqs[idx].flags = flags;
_irq_enable_source(irq);
return IRQ_ENABLED;
}
else if (irqs[idx].irq == irq)
return IRQ_ALREADY_REGISTERED;
}
return IRQ_NO_SLOTS_AVAILABLE;
}
void __attribute__ ((target("arm"))) fiq_setup()
{
/*
asm volatile("mrs r12, cpsr\n\t"
"bic r12, r12, #0x1F\n\t"
"orr r12, r12, #0x11\n\t"
"msr cpsr_c, r12\n\t");
register volatile char *text asm ("r8");
register volatile char *uart_tx asm ("r9");
register int len asm ("r10");
len = 5;
uart_tx = (char *)0x70006040;
memcpy((char *)text, "FIQ\r\n", len);
*uart_tx = 0;
asm volatile("mrs r12, cpsr\n"
"orr r12, r12, #0x1F\n"
"msr cpsr_c, r12");
*/
}
void __attribute__ ((target("arm"), interrupt ("FIQ"))) fiq_handler()
{
/*
register volatile char *text asm ("r8");
register volatile char *uart_tx asm ("r9");
register int len asm ("r10");
while (len)
{
*uart_tx = *text++;
len--;
}
*/
}

222
bdk/soc/irq.h Normal file
View File

@@ -0,0 +1,222 @@
/*
* BPMP-Lite IRQ driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
*
* 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 IRQ_H
#define IRQ_H
#include <utils/types.h>
#define IRQ_MAX_HANDLERS 16
/* Primary interrupt controller ids */
#define IRQ_TMR1 0
#define IRQ_TMR2 1
#define IRQ_RTC 2
#define IRQ_CEC 3
#define IRQ_SHR_SEM_INBOX_FULL 4
#define IRQ_SHR_SEM_INBOX_EMPTY 5
#define IRQ_SHR_SEM_OUTBOX_FULL 6
#define IRQ_SHR_SEM_OUTBOX_EMPTY 7
#define IRQ_NVJPEG 8
#define IRQ_NVDEC 9
#define IRQ_QUAD_SPI 10
#define IRQ_DPAUX_INT1 11
#define IRQ_SATA_RX_STAT 13
#define IRQ_SDMMC1 14
#define IRQ_SDMMC2 15
#define IRQ_VGPIO_INT 16
#define IRQ_VII2C_INT 17
#define IRQ_SDMMC3 19
#define IRQ_USB 20
#define IRQ_USB2 21
#define IRQ_SATA_CTL 23
#define IRQ_PMC_INT 24
#define IRQ_FC_INT 25
#define IRQ_APB_DMA_CPU 26
#define IRQ_ARB_SEM_GNT_COP 28
#define IRQ_ARB_SEM_GNT_CPU 29
#define IRQ_SDMMC4 31
/* Secondary interrupt controller ids */
#define IRQ_GPIO1 32
#define IRQ_GPIO2 33
#define IRQ_GPIO3 34
#define IRQ_GPIO4 35
#define IRQ_UARTA 36
#define IRQ_UARTB 37
#define IRQ_I2C 38
#define IRQ_USB3_HOST_INT 39
#define IRQ_USB3_HOST_SMI 40
#define IRQ_TMR3 41
#define IRQ_TMR4 42
#define IRQ_USB3_HOST_PME 43
#define IRQ_USB3_DEV_HOST 44
#define IRQ_ACTMON 45
#define IRQ_UARTC 46
#define IRQ_THERMAL 48
#define IRQ_XUSB_PADCTL 49
#define IRQ_TSEC 50
#define IRQ_EDP 51
#define IRQ_I2C5 53
#define IRQ_GPIO5 55
#define IRQ_USB3_DEV_SMI 56
#define IRQ_USB3_DEV_PME 57
#define IRQ_SE 58
#define IRQ_SPI1 59
#define IRQ_APB_DMA_COP 60
#define IRQ_CLDVFS 62
#define IRQ_I2C6 63
/* Tertiary interrupt controller ids */
#define IRQ_HOST1X_SYNCPT_COP 64
#define IRQ_HOST1X_SYNCPT_CPU 65
#define IRQ_HOST1X_GEN_COP 66
#define IRQ_HOST1X_GEN_CPU 67
#define IRQ_NVENC 68
#define IRQ_VI 69
#define IRQ_ISPB 70
#define IRQ_ISP 71
#define IRQ_VIC 72
#define IRQ_DISPLAY 73
#define IRQ_DISPLAYB 74
#define IRQ_SOR1 75
#define IRQ_SOR 76
#define IRQ_MC 77
#define IRQ_EMC 78
#define IRQ_TSECB 80
#define IRQ_HDA 81
#define IRQ_SPI2 82
#define IRQ_SPI3 83
#define IRQ_I2C2 84
#define IRQ_PMU_EXT 86
#define IRQ_GPIO6 87
#define IRQ_GPIO7 89
#define IRQ_UARTD 90
#define IRQ_I2C3 92
#define IRQ_SPI4 93
/* Quaternary interrupt controller ids */
#define IRQ_DTV 96
#define IRQ_PCIE_INT 98
#define IRQ_PCIE_MSI 99
#define IRQ_AVP_CACHE 101
#define IRQ_APE_INT1 102
#define IRQ_APE_INT0 103
#define IRQ_APB_DMA_CH0 104
#define IRQ_APB_DMA_CH1 105
#define IRQ_APB_DMA_CH2 106
#define IRQ_APB_DMA_CH3 107
#define IRQ_APB_DMA_CH4 108
#define IRQ_APB_DMA_CH5 109
#define IRQ_APB_DMA_CH6 110
#define IRQ_APB_DMA_CH7 111
#define IRQ_APB_DMA_CH8 112
#define IRQ_APB_DMA_CH9 113
#define IRQ_APB_DMA_CH10 114
#define IRQ_APB_DMA_CH11 115
#define IRQ_APB_DMA_CH12 116
#define IRQ_APB_DMA_CH13 117
#define IRQ_APB_DMA_CH14 118
#define IRQ_APB_DMA_CH15 119
#define IRQ_I2C4 120
#define IRQ_TMR5 121
#define IRQ_WDT_CPU 123
#define IRQ_WDT_AVP 124
#define IRQ_GPIO8 125
#define IRQ_CAR 126
/* Quinary interrupt controller ids */
#define IRQ_APB_DMA_CH16 128
#define IRQ_APB_DMA_CH17 129
#define IRQ_APB_DMA_CH18 130
#define IRQ_APB_DMA_CH19 131
#define IRQ_APB_DMA_CH20 132
#define IRQ_APB_DMA_CH21 133
#define IRQ_APB_DMA_CH22 134
#define IRQ_APB_DMA_CH23 135
#define IRQ_APB_DMA_CH24 136
#define IRQ_APB_DMA_CH25 137
#define IRQ_APB_DMA_CH26 138
#define IRQ_APB_DMA_CH27 139
#define IRQ_APB_DMA_CH28 140
#define IRQ_APB_DMA_CH29 141
#define IRQ_APB_DMA_CH30 142
#define IRQ_APB_DMA_CH31 143
#define IRQ_CPU0_PMU_INTR 144
#define IRQ_CPU1_PMU_INTR 145
#define IRQ_CPU2_PMU_INTR 146
#define IRQ_CPU3_PMU_INTR 147
#define IRQ_SDMMC1_SYS 148
#define IRQ_SDMMC2_SYS 149
#define IRQ_SDMMC3_SYS 150
#define IRQ_SDMMC4_SYS 151
#define IRQ_TMR6 152
#define IRQ_TMR7 153
#define IRQ_TMR8 154
#define IRQ_TMR9 155
#define IRQ_TMR0 156
#define IRQ_GPU_STALL 157
#define IRQ_GPU_NONSTALL 158
#define IRQ_DPAUX 159
/* Senary interrupt controller ids */
#define IRQ_MPCORE_AXIERRIRQ 160
#define IRQ_MPCORE_INTERRIRQ 161
#define IRQ_EVENT_GPIO_A 162
#define IRQ_EVENT_GPIO_B 163
#define IRQ_EVENT_GPIO_C 164
#define IRQ_FLOW_RSM_CPU 168
#define IRQ_FLOW_RSM_COP 169
#define IRQ_TMR_SHARED 170
#define IRQ_MPCORE_CTIIRQ0 171
#define IRQ_MPCORE_CTIIRQ1 172
#define IRQ_MPCORE_CTIIRQ2 173
#define IRQ_MPCORE_CTIIRQ3 174
#define IRQ_MSELECT_ERROR 175
#define IRQ_TMR10 176
#define IRQ_TMR11 177
#define IRQ_TMR12 178
#define IRQ_TMR13 179
typedef int (*irq_handler_t)(u32 irq, void *data);
typedef enum _irq_status_t
{
IRQ_NONE = 0,
IRQ_HANDLED = 1,
IRQ_ERROR = 2,
IRQ_ENABLED = 0,
IRQ_NO_SLOTS_AVAILABLE = 1,
IRQ_ALREADY_REGISTERED = 2
} irq_status_t;
typedef enum _irq_flags_t
{
IRQ_FLAG_NONE = 0,
IRQ_FLAG_ONE_OFF = BIT(0),
IRQ_FLAG_REPLACEABLE = BIT(1)
} irq_flags_t;
void irq_end();
void irq_free(u32 irq);
void irq_wait_event();
void irq_disable_wait_event();
irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t flags);
#endif

51
bdk/soc/kfuse.c Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/kfuse.h>
#include <soc/clock.h>
#include <soc/t210.h>
int kfuse_wait_ready()
{
// Wait for KFUSE to finish init and verification of data.
while (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_DONE))
;
if (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_CRCPASS))
return 0;
return 1;
}
int kfuse_read(u32 *buf)
{
int res = 0;
clock_enable_kfuse();
if (!kfuse_wait_ready())
goto out;
KFUSE(KFUSE_KEYADDR) = KFUSE_KEYADDR_AUTOINC;
for (int i = 0; i < KFUSE_NUM_WORDS; i++)
buf[i] = KFUSE(KFUSE_KEYS);
res = 1;
out:
clock_disable_kfuse();
return res;
}

42
bdk/soc/kfuse.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _KFUSE_H_
#define _KFUSE_H_
#include <utils/types.h>
#define KFUSE_STATE_CURBLOCK_MASK 0x3F
#define KFUSE_STATE_ERRBLOCK_SHIFT 8
#define KFUSE_STATE_ERRBLOCK_MASK 0x3F00
#define KFUSE_STATE_DONE BIT(16)
#define KFUSE_STATE_CRCPASS BIT(17)
#define KFUSE_STATE_RESTART BIT(24)
#define KFUSE_STATE_STOP BIT(25)
#define KFUSE_STATE_SOFTRESET BIT(31)
#define KFUSE_KEYADDR_AUTOINC BIT(16)
#define KFUSE_STATE 0x80
#define KFUSE_KEYADDR 0x88
#define KFUSE_KEYS 0x8C
#define KFUSE_NUM_WORDS 144
int kfuse_wait_ready();
int kfuse_read(u32 *buf);
#endif

32
bdk/soc/pinmux.c Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/pinmux.h>
#include <soc/t210.h>
void pinmux_config_uart(u32 idx)
{
PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0;
PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0;
PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN;
}
void pinmux_config_i2c(u32 idx)
{
PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = PINMUX_INPUT_ENABLE;
PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = PINMUX_INPUT_ENABLE;
}

122
bdk/soc/pinmux.h Normal file
View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _PINMUX_H_
#define _PINMUX_H_
#include <utils/types.h>
/*! APB MISC registers. */
#define APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL 0x8D4
#define APB_MISC_GP_SDMMC3_CLK_LPBK_CONTROL 0x8D8
#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98
#define APB_MISC_GP_VGPIO_GPIO_MUX_SEL 0xB74
/*! Pinmux registers. */
#define PINMUX_AUX_SDMMC1_CLK 0x00
#define PINMUX_AUX_SDMMC1_CMD 0x04
#define PINMUX_AUX_SDMMC1_DAT3 0x08
#define PINMUX_AUX_SDMMC1_DAT2 0x0C
#define PINMUX_AUX_SDMMC1_DAT1 0x10
#define PINMUX_AUX_SDMMC1_DAT0 0x14
#define PINMUX_AUX_SDMMC3_CLK 0x1C
#define PINMUX_AUX_SDMMC3_CMD 0x20
#define PINMUX_AUX_SDMMC3_DAT0 0x24
#define PINMUX_AUX_SDMMC3_DAT1 0x28
#define PINMUX_AUX_SDMMC3_DAT2 0x2C
#define PINMUX_AUX_SDMMC3_DAT3 0x30
#define PINMUX_AUX_SATA_LED_ACTIVE 0x4C
#define PINMUX_AUX_DMIC3_CLK 0xB4
#define PINMUX_AUX_DMIC3_DAT 0xB8
#define PINMUX_AUX_CAM_I2C_SCL 0xD4
#define PINMUX_AUX_CAM_I2C_SDA 0xD8
#define PINMUX_AUX_UART2_TX 0xF4
#define PINMUX_AUX_UART3_TX 0x104
#define PINMUX_AUX_DAP4_DIN 0x148
#define PINMUX_AUX_DAP4_SCLK 0x150
#define PINMUX_AUX_GPIO_X1_AUD 0x18C
#define PINMUX_AUX_GPIO_X3_AUD 0x190
#define PINMUX_AUX_SPDIF_IN 0x1A4
#define PINMUX_AUX_USB_VBUS_EN0 0x1A8
#define PINMUX_AUX_USB_VBUS_EN1 0x1AC
#define PINMUX_AUX_WIFI_EN 0x1B4
#define PINMUX_AUX_WIFI_RST 0x1B8
#define PINMUX_AUX_AP_WAKE_NFC 0x1CC
#define PINMUX_AUX_NFC_EN 0x1D0
#define PINMUX_AUX_NFC_INT 0x1D4
#define PINMUX_AUX_CAM1_PWDN 0x1EC
#define PINMUX_AUX_CAM2_PWDN 0x1F0
#define PINMUX_AUX_LCD_BL_PWM 0x1FC
#define PINMUX_AUX_LCD_BL_EN 0x200
#define PINMUX_AUX_LCD_RST 0x204
#define PINMUX_AUX_LCD_GPIO1 0x208
#define PINMUX_AUX_LCD_GPIO2 0x20C
#define PINMUX_AUX_TOUCH_INT 0x220
#define PINMUX_AUX_MOTION_INT 0x224
#define PINMUX_AUX_BUTTON_HOME 0x240
#define PINMUX_AUX_GPIO_PE6 0x248
#define PINMUX_AUX_GPIO_PH6 0x250
#define PINMUX_AUX_GPIO_PK3 0x260
#define PINMUX_AUX_GPIO_PZ1 0x280
/* Only in T210B01 */
#define PINMUX_AUX_SDMMC2_DAT0 0x294
#define PINMUX_AUX_SDMMC2_DAT1 0x298
#define PINMUX_AUX_SDMMC2_DAT2 0x29C
#define PINMUX_AUX_SDMMC2_DAT3 0x2A0
#define PINMUX_AUX_SDMMC2_DAT4 0x2A4
#define PINMUX_AUX_SDMMC2_DAT5 0x2A8
#define PINMUX_AUX_SDMMC2_DAT6 0x2AC
#define PINMUX_AUX_SDMMC2_DAT7 0x2B0
#define PINMUX_AUX_SDMMC2_CLK 0x2B4
#define PINMUX_AUX_SDMMC2_CMD 0x2BC
/*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */
#define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x))
#define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x))
#define PINMUX_AUX_UARTX_RTS(x) (0xEC + 0x10 * (x))
#define PINMUX_AUX_UARTX_CTS(x) (0xF0 + 0x10 * (x))
/*! 0:GEN1, 1:GEN2, 2:GEN3, 3:CAM, 4:PWR */
#define PINMUX_AUX_X_I2C_SCL(x) (0xBC + 8 * (x))
#define PINMUX_AUX_X_I2C_SDA(x) (0xC0 + 8 * (x))
#define PINMUX_FUNC_MASK (3 << 0)
#define PINMUX_PULL_MASK (3 << 2)
#define PINMUX_PULL_NONE (0 << 2)
#define PINMUX_PULL_DOWN (1 << 2)
#define PINMUX_PULL_UP (2 << 2)
#define PINMUX_TRISTATE BIT(4)
#define PINMUX_PARKED BIT(5)
#define PINMUX_INPUT_ENABLE BIT(6)
#define PINMUX_LOCK BIT(7)
#define PINMUX_LPDR BIT(8)
#define PINMUX_HSM BIT(9)
#define PINMUX_IO_HV BIT(10)
#define PINMUX_OPEN_DRAIN BIT(11)
#define PINMUX_SCHMT BIT(12)
#define PINMUX_DRIVE_MASK (3 << 13)
#define PINMUX_DRIVE_1X (0 << 13)
#define PINMUX_DRIVE_2X (1 << 13)
#define PINMUX_DRIVE_3X (2 << 13)
#define PINMUX_DRIVE_4X (3 << 13)
void pinmux_config_uart(u32 idx);
void pinmux_config_i2c(u32 idx);
#endif

110
bdk/soc/pmc.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/hw_init.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <utils/util.h>
void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
{
// Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address.
if (lock_mask & PMC_SEC_LOCK_MISC)
{
PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3.
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23.
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85.
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119.
// SE2 context.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
{
PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38)
PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150.
}
}
if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS)
{
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20.
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54.
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87.
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF; // RW lock: 88-98.
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF; // RW lock: 104-107.
}
if (lock_mask & PMC_SEC_LOCK_RST_VECTOR)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xF00000; // RW lock: 34-35.
if (lock_mask & PMC_SEC_LOCK_CARVEOUTS)
{
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x30000; // RW lock: 16.
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xC0000000; // RW lock: 39.
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0xC0C00000; // RW lock: 51, 55.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0x3FF0; // RW lock: 74-78.
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103.
}
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W)
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115.
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_R)
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xAA0000; // R lock: 112-115.
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_W)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x55; // W lock: 24-27.
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27.
if (lock_mask & PMC_SEC_LOCK_SE_SRK)
PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7
}
int pmc_enable_partition(pmc_power_rail_t part, u32 enable)
{
u32 part_mask = BIT(part);
u32 desired_state = enable << part;
// Check if the partition has the state we want.
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
return 1;
u32 i = 5001;
while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100)
{
usleep(1);
i--;
if (i < 1)
return 0;
}
// Toggle power gating.
PMC(APBDEV_PMC_PWRGATE_TOGGLE) = part | 0x100;
i = 5001;
while (i > 0)
{
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
break;
usleep(1);
i--;
}
return 1;
}

160
bdk/soc/pmc.h Normal file
View File

@@ -0,0 +1,160 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018-2020 CTCaer
*
* 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 _PMC_H_
#define _PMC_H_
#include <utils/types.h>
/*! PMC registers. */
#define APBDEV_PMC_CNTRL 0x0
#define PMC_CNTRL_MAIN_RST BIT(4)
#define APBDEV_PMC_SEC_DISABLE 0x4
#define APBDEV_PMC_PWRGATE_TOGGLE 0x30
#define APBDEV_PMC_PWRGATE_STATUS 0x38
#define APBDEV_PMC_NO_IOPOWER 0x44
#define PMC_NO_IOPOWER_SDMMC1_IO_EN BIT(12)
#define PMC_NO_IOPOWER_AUDIO_HV BIT(18)
#define PMC_NO_IOPOWER_GPIO_IO_EN BIT(21)
#define APBDEV_PMC_SCRATCH0 0x50
#define PMC_SCRATCH0_MODE_WARMBOOT BIT(0)
#define PMC_SCRATCH0_MODE_RCM BIT(1)
#define PMC_SCRATCH0_MODE_PAYLOAD BIT(29)
#define PMC_SCRATCH0_MODE_FASTBOOT BIT(30)
#define PMC_SCRATCH0_MODE_RECOVERY BIT(31)
#define PMC_SCRATCH0_MODE_CUSTOM_ALL (PMC_SCRATCH0_MODE_RECOVERY | PMC_SCRATCH0_MODE_FASTBOOT | PMC_SCRATCH0_MODE_PAYLOAD)
#define APBDEV_PMC_SCRATCH1 0x54
#define APBDEV_PMC_SCRATCH20 0xA0
#define APBDEV_PMC_SECURE_SCRATCH4 0xC0
#define APBDEV_PMC_SECURE_SCRATCH5 0xC4
#define APBDEV_PMC_PWR_DET_VAL 0xE4
#define PMC_PWR_DET_SDMMC1_IO_EN BIT(12)
#define PMC_PWR_DET_AUDIO_HV BIT(18)
#define PMC_PWR_DET_GPIO_IO_EN BIT(21)
#define APBDEV_PMC_DDR_PWR 0xE8
#define APBDEV_PMC_USB_AO 0xF0
#define APBDEV_PMC_CRYPTO_OP 0xF4
#define PMC_CRYPTO_OP_SE_ENABLE 0
#define PMC_CRYPTO_OP_SE_DISABLE 1
#define APBDEV_PMC_SCRATCH33 0x120
#define APBDEV_PMC_SCRATCH37 0x130
#define PMC_SCRATCH37_KERNEL_PANIC_FLAG BIT(24)
#define APBDEV_PMC_SCRATCH40 0x13C
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
#define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER 0x400000
#define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8
#define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2)
#define APBDEV_PMC_RST_STATUS 0x1B4
#define PMC_RST_STATUS_MASK 0x7
#define PMC_RST_STATUS_POR 0
#define PMC_RST_STATUS_WATCHDOG 1
#define PMC_RST_STATUS_SENSOR 2
#define PMC_RST_STATUS_SW_MAIN 3
#define PMC_RST_STATUS_LP0 4
#define PMC_RST_STATUS_AOTAG 5
#define APBDEV_PMC_IO_DPD_REQ 0x1B8
#define PMC_IO_DPD_REQ_DPD_OFF BIT(30)
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
#define APBDEV_PMC_VDDP_SEL 0x1CC
#define APBDEV_PMC_DDR_CFG 0x1D0
#define APBDEV_PMC_SECURE_SCRATCH6 0x224
#define APBDEV_PMC_SECURE_SCRATCH7 0x228
#define APBDEV_PMC_SCRATCH45 0x234
#define APBDEV_PMC_SCRATCH46 0x238
#define APBDEV_PMC_SCRATCH49 0x244
#define APBDEV_PMC_TSC_MULT 0x2B4
#define APBDEV_PMC_SEC_DISABLE2 0x2C4
#define APBDEV_PMC_WEAK_BIAS 0x2C8
#define APBDEV_PMC_REG_SHORT 0x2CC
#define APBDEV_PMC_SEC_DISABLE3 0x2D8
#define APBDEV_PMC_SECURE_SCRATCH21 0x334
#define PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT 0x10
#define APBDEV_PMC_SECURE_SCRATCH32 0x360
#define APBDEV_PMC_SECURE_SCRATCH49 0x3A4
#define APBDEV_PMC_CNTRL2 0x440
#define PMC_CNTRL2_HOLD_CKE_LOW_EN 0x1000
#define APBDEV_PMC_IO_DPD3_REQ 0x45C
#define APBDEV_PMC_IO_DPD4_REQ 0x464
#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4
#define APBDEV_PMC_UTMIP_PAD_CFG3 0x4CC
#define APBDEV_PMC_DDR_CNTRL 0x4E4
#define APBDEV_PMC_SEC_DISABLE4 0x5B0
#define APBDEV_PMC_SEC_DISABLE5 0x5B4
#define APBDEV_PMC_SEC_DISABLE6 0x5B8
#define APBDEV_PMC_SEC_DISABLE7 0x5BC
#define APBDEV_PMC_SEC_DISABLE8 0x5C0
#define APBDEV_PMC_SEC_DISABLE9 0x5C4
#define APBDEV_PMC_SEC_DISABLE10 0x5C8
#define APBDEV_PMC_SCRATCH188 0x810
#define APBDEV_PMC_SCRATCH190 0x818
#define APBDEV_PMC_SCRATCH200 0x840
#define APBDEV_PMC_TZRAM_PWR_CNTRL 0xBE8
#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC
#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0
typedef enum _pmc_sec_lock_t
{
PMC_SEC_LOCK_MISC = BIT(0),
PMC_SEC_LOCK_LP0_PARAMS = BIT(1),
PMC_SEC_LOCK_RST_VECTOR = BIT(2),
PMC_SEC_LOCK_CARVEOUTS = BIT(3),
PMC_SEC_LOCK_TZ_CMAC_W = BIT(4),
PMC_SEC_LOCK_TZ_CMAC_R = BIT(5),
PMC_SEC_LOCK_TZ_KEK_W = BIT(6),
PMC_SEC_LOCK_TZ_KEK_R = BIT(7),
PMC_SEC_LOCK_SE_SRK = BIT(8),
} pmc_sec_lock_t;
typedef enum _pmc_power_rail_t
{
POWER_RAIL_CRAIL = 0,
POWER_RAIL_3D0 = 1,
POWER_RAIL_VENC = 2,
POWER_RAIL_PCIE = 3,
POWER_RAIL_VDEC = 4,
POWER_RAIL_L2C = 5,
POWER_RAIL_MPE = 6,
POWER_RAIL_HEG = 7,
POWER_RAIL_SATA = 8,
POWER_RAIL_CE1 = 9,
POWER_RAIL_CE2 = 10,
POWER_RAIL_CE3 = 11,
POWER_RAIL_CELP = 12,
POWER_RAIL_3D1 = 13,
POWER_RAIL_CE0 = 14,
POWER_RAIL_C0NC = 15,
POWER_RAIL_C1NC = 16,
POWER_RAIL_SOR = 17,
POWER_RAIL_DIS = 18,
POWER_RAIL_DISB = 19,
POWER_RAIL_XUSBA = 20,
POWER_RAIL_XUSBB = 21,
POWER_RAIL_XUSBC = 22,
POWER_RAIL_VIC = 23,
POWER_RAIL_IRAM = 24,
POWER_RAIL_NVDEC = 25,
POWER_RAIL_NVJPG = 26,
POWER_RAIL_AUD = 27,
POWER_RAIL_DFD = 28,
POWER_RAIL_VE2 = 29
} pmc_power_rail_t;
void pmc_scratch_lock(pmc_sec_lock_t lock_mask);
int pmc_enable_partition(pmc_power_rail_t part, u32 enable);
#endif

564
bdk/soc/pmc_lp0_t210.h Normal file
View File

@@ -0,0 +1,564 @@
/*
* Copyright (c) 2010-2015, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef _TEGRA210_PMC_H_
#define _TEGRA210_PMC_H_
#include <utils/types.h>
struct tegra_pmc_regs
{
u32 cntrl;
u32 sec_disable;
u32 pmc_swrst;
u32 wake_mask;
u32 wake_lvl;
u32 wake_status;
u32 sw_wake_status;
u32 dpd_pads_oride;
u32 dpd_sample;
u32 dpd_enable;
u32 pwrgate_timer_off;
u32 clamp_status;
u32 pwrgate_toggle;
u32 remove_clamping_cmd;
u32 pwrgate_status;
u32 pwrgood_timer;
u32 blink_timer;
u32 no_iopower;
u32 pwr_det;
u32 pwr_det_latch;
u32 scratch0;
u32 scratch1;
u32 scratch2;
u32 scratch3;
u32 scratch4;
u32 scratch5;
u32 scratch6;
u32 scratch7;
u32 scratch8;
u32 scratch9;
u32 scratch10;
u32 scratch11;
u32 scratch12;
u32 scratch13;
u32 scratch14;
u32 scratch15;
u32 scratch16;
u32 scratch17;
u32 scratch18;
u32 scratch19;
u32 odmdata;
u32 scratch21;
u32 scratch22;
u32 scratch23;
u32 secure_scratch0;
u32 secure_scratch1;
u32 secure_scratch2;
u32 secure_scratch3;
u32 secure_scratch4;
u32 secure_scratch5;
u32 cpupwrgood_timer;
u32 cpupwroff_timer;
u32 pg_mask;
u32 pg_mask_1;
u32 auto_wake_lvl;
u32 auto_wake_lvl_mask;
u32 wake_delay;
u32 pwr_det_val;
u32 ddr_pwr;
u32 usb_debounce_del;
u32 usb_a0;
u32 crypto_op;
u32 pllp_wb0_override;
u32 scratch24;
u32 scratch25;
u32 scratch26;
u32 scratch27;
u32 scratch28;
u32 scratch29;
u32 scratch30;
u32 scratch31;
u32 scratch32;
u32 scratch33;
u32 scratch34;
u32 scratch35;
u32 scratch36;
u32 scratch37;
u32 scratch38;
u32 scratch39;
u32 scratch40;
u32 scratch41;
u32 scratch42;
u32 bondout_mirror[3];
u32 sys_33v_en;
u32 bondout_mirror_access;
u32 gate;
u32 wake2_mask;
u32 wake2_lvl;
u32 wake2_status;
u32 sw_wake2_status;
u32 auto_wake2_lvl_mask;
u32 pg_mask_2;
u32 pg_mask_ce1;
u32 pg_mask_ce2;
u32 pg_mask_ce3;
u32 pwrgate_timer_ce[7];
u32 pcx_edpd_cntrl;
u32 osc_edpd_over;
u32 clk_out_cntrl;
u32 sata_pwrgt;
u32 sensor_ctrl;
u32 rst_status;
u32 io_dpd_req;
u32 io_dpd_status;
u32 io_dpd2_req;
u32 io_dpd2_status;
u32 sel_dpd_tim;
u32 vddp_sel;
u32 ddr_cfg;
u32 e_no_vttgen;
u8 _rsv0[4];
u32 pllm_wb0_override_freq;
u32 test_pwrgate;
u32 pwrgate_timer_mult;
u32 dis_sel_dpd;
u32 utmip_uhsic_triggers;
u32 utmip_uhsic_saved_state;
u32 utmip_pad_cfg;
u32 utmip_term_pad_cfg;
u32 utmip_uhsic_sleep_cfg;
u32 utmip_uhsic_sleepwalk_cfg;
u32 utmip_sleepwalk_p[3];
u32 uhsic_sleepwalk_p0;
u32 utmip_uhsic_status;
u32 utmip_uhsic_fake;
u32 bondout_mirror3[5 - 3];
u32 secure_scratch6;
u32 secure_scratch7;
u32 scratch43;
u32 scratch44;
u32 scratch45;
u32 scratch46;
u32 scratch47;
u32 scratch48;
u32 scratch49;
u32 scratch50;
u32 scratch51;
u32 scratch52;
u32 scratch53;
u32 scratch54;
u32 scratch55;
u32 scratch0_eco;
u32 por_dpd_ctrl;
u32 scratch2_eco;
u32 utmip_uhsic_line_wakeup;
u32 utmip_bias_master_cntrl;
u32 utmip_master_config;
u32 td_pwrgate_inter_part_timer;
u32 utmip_uhsic2_triggers;
u32 utmip_uhsic2_saved_state;
u32 utmip_uhsic2_sleep_cfg;
u32 utmip_uhsic2_sleepwalk_cfg;
u32 uhsic2_sleepwalk_p1;
u32 utmip_uhsic2_status;
u32 utmip_uhsic2_fake;
u32 utmip_uhsic2_line_wakeup;
u32 utmip_master2_config;
u32 utmip_uhsic_rpd_cfg;
u32 pg_mask_ce0;
u32 pg_mask3[5 - 3];
u32 pllm_wb0_override2;
u32 tsc_mult;
u32 cpu_vsense_override;
u32 glb_amap_cfg;
u32 sticky_bits;
u32 sec_disable2;
u32 weak_bias;
u32 reg_short;
u32 pg_mask_andor;
u8 _rsv1[0x2c];
u32 secure_scratch8; /* offset 0x300 */
u32 secure_scratch9;
u32 secure_scratch10;
u32 secure_scratch11;
u32 secure_scratch12;
u32 secure_scratch13;
u32 secure_scratch14;
u32 secure_scratch15;
u32 secure_scratch16;
u32 secure_scratch17;
u32 secure_scratch18;
u32 secure_scratch19;
u32 secure_scratch20;
u32 secure_scratch21;
u32 secure_scratch22;
u32 secure_scratch23;
u32 secure_scratch24;
u32 secure_scratch25;
u32 secure_scratch26;
u32 secure_scratch27;
u32 secure_scratch28;
u32 secure_scratch29;
u32 secure_scratch30;
u32 secure_scratch31;
u32 secure_scratch32;
u32 secure_scratch33;
u32 secure_scratch34;
u32 secure_scratch35;
u32 secure_scratch36;
u32 secure_scratch37;
u32 secure_scratch38;
u32 secure_scratch39;
u32 secure_scratch40;
u32 secure_scratch41;
u32 secure_scratch42;
u32 secure_scratch43;
u32 secure_scratch44;
u32 secure_scratch45;
u32 secure_scratch46;
u32 secure_scratch47;
u32 secure_scratch48;
u32 secure_scratch49;
u32 secure_scratch50;
u32 secure_scratch51;
u32 secure_scratch52;
u32 secure_scratch53;
u32 secure_scratch54;
u32 secure_scratch55;
u32 secure_scratch56;
u32 secure_scratch57;
u32 secure_scratch58;
u32 secure_scratch59;
u32 secure_scratch60;
u32 secure_scratch61;
u32 secure_scratch62;
u32 secure_scratch63;
u32 secure_scratch64;
u32 secure_scratch65;
u32 secure_scratch66;
u32 secure_scratch67;
u32 secure_scratch68;
u32 secure_scratch69;
u32 secure_scratch70;
u32 secure_scratch71;
u32 secure_scratch72;
u32 secure_scratch73;
u32 secure_scratch74;
u32 secure_scratch75;
u32 secure_scratch76;
u32 secure_scratch77;
u32 secure_scratch78;
u32 secure_scratch79;
u32 _rsv0x420[8];
u32 cntrl2; /* 0x440 */
u32 _rsv0x444[2];
u32 event_counter; /* 0x44C */
u32 fuse_control;
u32 scratch1_eco;
u32 _rsv0x458[1];
u32 io_dpd3_req; /* 0x45C */
u32 io_dpd3_status;
u32 io_dpd4_req;
u32 io_dpd4_status;
u32 _rsv0x46C[30];
u32 ddr_cntrl; /* 0x4E4 */
u32 _rsv0x4E8[70];
u32 scratch56; /* 0x600 */
u32 scratch57;
u32 scratch58;
u32 scratch59;
u32 scratch60;
u32 scratch61;
u32 scratch62;
u32 scratch63;
u32 scratch64;
u32 scratch65;
u32 scratch66;
u32 scratch67;
u32 scratch68;
u32 scratch69;
u32 scratch70;
u32 scratch71;
u32 scratch72;
u32 scratch73;
u32 scratch74;
u32 scratch75;
u32 scratch76;
u32 scratch77;
u32 scratch78;
u32 scratch79;
u32 scratch80;
u32 scratch81;
u32 scratch82;
u32 scratch83;
u32 scratch84;
u32 scratch85;
u32 scratch86;
u32 scratch87;
u32 scratch88;
u32 scratch89;
u32 scratch90;
u32 scratch91;
u32 scratch92;
u32 scratch93;
u32 scratch94;
u32 scratch95;
u32 scratch96;
u32 scratch97;
u32 scratch98;
u32 scratch99;
u32 scratch100;
u32 scratch101;
u32 scratch102;
u32 scratch103;
u32 scratch104;
u32 scratch105;
u32 scratch106;
u32 scratch107;
u32 scratch108;
u32 scratch109;
u32 scratch110;
u32 scratch111;
u32 scratch112;
u32 scratch113;
u32 scratch114;
u32 scratch115;
u32 scratch116;
u32 scratch117;
u32 scratch118;
u32 scratch119;
u32 scratch120; /* 0x700 */
u32 scratch121;
u32 scratch122;
u32 scratch123;
u32 scratch124;
u32 scratch125;
u32 scratch126;
u32 scratch127;
u32 scratch128;
u32 scratch129;
u32 scratch130;
u32 scratch131;
u32 scratch132;
u32 scratch133;
u32 scratch134;
u32 scratch135;
u32 scratch136;
u32 scratch137;
u32 scratch138;
u32 scratch139;
u32 scratch140;
u32 scratch141;
u32 scratch142;
u32 scratch143;
u32 scratch144;
u32 scratch145;
u32 scratch146;
u32 scratch147;
u32 scratch148;
u32 scratch149;
u32 scratch150;
u32 scratch151;
u32 scratch152;
u32 scratch153;
u32 scratch154;
u32 scratch155;
u32 scratch156;
u32 scratch157;
u32 scratch158;
u32 scratch159;
u32 scratch160;
u32 scratch161;
u32 scratch162;
u32 scratch163;
u32 scratch164;
u32 scratch165;
u32 scratch166;
u32 scratch167;
u32 scratch168;
u32 scratch169;
u32 scratch170;
u32 scratch171;
u32 scratch172;
u32 scratch173;
u32 scratch174;
u32 scratch175;
u32 scratch176;
u32 scratch177;
u32 scratch178;
u32 scratch179;
u32 scratch180;
u32 scratch181;
u32 scratch182;
u32 scratch183;
u32 scratch184;
u32 scratch185;
u32 scratch186;
u32 scratch187;
u32 scratch188;
u32 scratch189;
u32 scratch190;
u32 scratch191;
u32 scratch192;
u32 scratch193;
u32 scratch194;
u32 scratch195;
u32 scratch196;
u32 scratch197;
u32 scratch198;
u32 scratch199;
u32 scratch200;
u32 scratch201;
u32 scratch202;
u32 scratch203;
u32 scratch204;
u32 scratch205;
u32 scratch206;
u32 scratch207;
u32 scratch208;
u32 scratch209;
u32 scratch210;
u32 scratch211;
u32 scratch212;
u32 scratch213;
u32 scratch214;
u32 scratch215;
u32 scratch216;
u32 scratch217;
u32 scratch218;
u32 scratch219;
u32 scratch220;
u32 scratch221;
u32 scratch222;
u32 scratch223;
u32 scratch224;
u32 scratch225;
u32 scratch226;
u32 scratch227;
u32 scratch228;
u32 scratch229;
u32 scratch230;
u32 scratch231;
u32 scratch232;
u32 scratch233;
u32 scratch234;
u32 scratch235;
u32 scratch236;
u32 scratch237;
u32 scratch238;
u32 scratch239;
u32 scratch240;
u32 scratch241;
u32 scratch242;
u32 scratch243;
u32 scratch244;
u32 scratch245;
u32 scratch246;
u32 scratch247;
u32 scratch248;
u32 scratch249;
u32 scratch250;
u32 scratch251;
u32 scratch252;
u32 scratch253;
u32 scratch254;
u32 scratch255;
u32 scratch256;
u32 scratch257;
u32 scratch258;
u32 scratch259;
u32 scratch260;
u32 scratch261;
u32 scratch262;
u32 scratch263;
u32 scratch264;
u32 scratch265;
u32 scratch266;
u32 scratch267;
u32 scratch268;
u32 scratch269;
u32 scratch270;
u32 scratch271;
u32 scratch272;
u32 scratch273;
u32 scratch274;
u32 scratch275;
u32 scratch276;
u32 scratch277;
u32 scratch278;
u32 scratch279;
u32 scratch280;
u32 scratch281;
u32 scratch282;
u32 scratch283;
u32 scratch284;
u32 scratch285;
u32 scratch286;
u32 scratch287;
u32 scratch288;
u32 scratch289;
u32 scratch290;
u32 scratch291;
u32 scratch292;
u32 scratch293;
u32 scratch294;
u32 scratch295;
u32 scratch296;
u32 scratch297;
u32 scratch298;
u32 scratch299; /* 0x9CC */
u32 _rsv0x9D0[50];
u32 secure_scratch80; /* 0xa98 */
u32 secure_scratch81;
u32 secure_scratch82;
u32 secure_scratch83;
u32 secure_scratch84;
u32 secure_scratch85;
u32 secure_scratch86;
u32 secure_scratch87;
u32 secure_scratch88;
u32 secure_scratch89;
u32 secure_scratch90;
u32 secure_scratch91;
u32 secure_scratch92;
u32 secure_scratch93;
u32 secure_scratch94;
u32 secure_scratch95;
u32 secure_scratch96;
u32 secure_scratch97;
u32 secure_scratch98;
u32 secure_scratch99;
u32 secure_scratch100;
u32 secure_scratch101;
u32 secure_scratch102;
u32 secure_scratch103;
u32 secure_scratch104;
u32 secure_scratch105;
u32 secure_scratch106;
u32 secure_scratch107;
u32 secure_scratch108;
u32 secure_scratch109;
u32 secure_scratch110;
u32 secure_scratch111;
u32 secure_scratch112;
u32 secure_scratch113;
u32 secure_scratch114;
u32 secure_scratch115;
u32 secure_scratch116;
u32 secure_scratch117;
u32 secure_scratch118;
u32 secure_scratch119;
};
#endif /* _TEGRA210_PMC_H_ */

307
bdk/soc/t210.h Normal file
View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 _T210_H_
#define _T210_H_
#include <utils/types.h>
#define BOOTROM_BASE 0x100000
#define IRAM_BASE 0x40000000
#define HOST1X_BASE 0x50000000
#define BPMP_CACHE_BASE 0x50040000
#define DISPLAY_A_BASE 0x54200000
#define DSI_BASE 0x54300000
#define VIC_BASE 0x54340000
#define TSEC_BASE 0x54500000
#define SOR1_BASE 0x54580000
#define ICTLR_BASE 0x60004000
#define TMR_BASE 0x60005000
#define CLOCK_BASE 0x60006000
#define FLOW_CTLR_BASE 0x60007000
#define AHBDMA_BASE 0x60008000
#define SYSREG_BASE 0x6000C000
#define SB_BASE (SYSREG_BASE + 0x200)
#define GPIO_BASE 0x6000D000
#define GPIO_1_BASE (GPIO_BASE)
#define GPIO_2_BASE (GPIO_BASE + 0x100)
#define GPIO_3_BASE (GPIO_BASE + 0x200)
#define GPIO_4_BASE (GPIO_BASE + 0x300)
#define GPIO_5_BASE (GPIO_BASE + 0x400)
#define GPIO_6_BASE (GPIO_BASE + 0x500)
#define GPIO_7_BASE (GPIO_BASE + 0x600)
#define GPIO_8_BASE (GPIO_BASE + 0x700)
#define EXCP_VEC_BASE 0x6000F000
#define IPATCH_BASE 0x6001DC00
#define APBDMA_BASE 0x60020000
#define APB_MISC_BASE 0x70000000
#define PINMUX_AUX_BASE 0x70003000
#define UART_BASE 0x70006000
#define PWM_BASE 0x7000A000
#define RTC_BASE 0x7000E000
#define PMC_BASE 0x7000E400
#define SYSCTR0_BASE 0x700F0000
#define FUSE_BASE 0x7000F800
#define KFUSE_BASE 0x7000FC00
#define SE_BASE 0x70012000
#define MC_BASE 0x70019000
#define EMC_BASE 0x7001B000
#define EMC0_BASE 0x7001E000
#define EMC1_BASE 0x7001F000
#define XUSB_HOST_BASE 0x70090000
#define XUSB_PADCTL_BASE 0x7009F000
#define XUSB_DEV_BASE 0x700D0000
#define MIPI_CAL_BASE 0x700E3000
#define CL_DVFS_BASE 0x70110000
#define I2S_BASE 0x702D1000
#define ADMA_BASE 0x702E2000
#define TZRAM_BASE 0x7C010000
#define USB_BASE 0x7D000000
#define USB_OTG_BASE USB_BASE
#define USB1_BASE 0x7D004000
#define _REG(base, off) *(vu32 *)((base) + (off))
#define HOST1X(off) _REG(HOST1X_BASE, off)
#define BPMP_CACHE_CTRL(off) _REG(BPMP_CACHE_BASE, off)
#define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off)
#define DSI(off) _REG(DSI_BASE, off)
#define VIC(off) _REG(VIC_BASE, off)
#define TSEC(off) _REG(TSEC_BASE, off)
#define SOR1(off) _REG(SOR1_BASE, off)
#define ICTLR(cidx, off) _REG(ICTLR_BASE + (0x100 * (cidx)), off)
#define TMR(off) _REG(TMR_BASE, off)
#define CLOCK(off) _REG(CLOCK_BASE, off)
#define FLOW_CTLR(off) _REG(FLOW_CTLR_BASE, off)
#define SYSREG(off) _REG(SYSREG_BASE, off)
#define AHB_GIZMO(off) _REG(SYSREG_BASE, off)
#define SB(off) _REG(SB_BASE, off)
#define GPIO(off) _REG(GPIO_BASE, off)
#define GPIO_1(off) _REG(GPIO_1_BASE, off)
#define GPIO_2(off) _REG(GPIO_2_BASE, off)
#define GPIO_3(off) _REG(GPIO_3_BASE, off)
#define GPIO_4(off) _REG(GPIO_4_BASE, off)
#define GPIO_5(off) _REG(GPIO_5_BASE, off)
#define GPIO_6(off) _REG(GPIO_6_BASE, off)
#define GPIO_7(off) _REG(GPIO_7_BASE, off)
#define GPIO_8(off) _REG(GPIO_8_BASE, off)
#define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off)
#define APB_MISC(off) _REG(APB_MISC_BASE, off)
#define PINMUX_AUX(off) _REG(PINMUX_AUX_BASE, off)
#define PWM(off) _REG(PWM_BASE, off)
#define RTC(off) _REG(RTC_BASE, off)
#define PMC(off) _REG(PMC_BASE, off)
#define SYSCTR0(off) _REG(SYSCTR0_BASE, off)
#define FUSE(off) _REG(FUSE_BASE, off)
#define KFUSE(off) _REG(KFUSE_BASE, off)
#define SE(off) _REG(SE_BASE, off)
#define MC(off) _REG(MC_BASE, off)
#define EMC(off) _REG(EMC_BASE, off)
#define EMC_CH0(off) _REG(EMC0_BASE, off)
#define EMC_CH1(off) _REG(EMC1_BASE, off)
#define XUSB_HOST(off) _REG(XUSB_HOST_BASE, off)
#define XUSB_PADCTL(off) _REG(XUSB_PADCTL_BASE, off)
#define XUSB_DEV(off) _REG(XUSB_DEV_BASE, off)
#define XUSB_DEV_XHCI(off) _REG(XUSB_DEV_BASE, off)
#define XUSB_DEV_PCI(off) _REG(XUSB_DEV_BASE + 0x8000, off)
#define XUSB_DEV_DEV(off) _REG(XUSB_DEV_BASE + 0x9000, off)
#define MIPI_CAL(off) _REG(MIPI_CAL_BASE, off)
#define CL_DVFS(off) _REG(CL_DVFS_BASE, off)
#define I2S(off) _REG(I2S_BASE, off)
#define ADMA(off) _REG(ADMA_BASE, off)
#define USB(off) _REG(USB_BASE, off)
#define USB1(off) _REG(USB1_BASE, off)
#define TEST_REG(off) _REG(0x0, off)
/* HOST1X registers. */
#define HOST1X_CH0_SYNC_BASE 0x2100
#define HOST1X_CH0_SYNC_SYNCPT_9 (HOST1X_CH0_SYNC_BASE + 0xFA4)
#define HOST1X_CH0_SYNC_SYNCPT_160 (HOST1X_CH0_SYNC_BASE + 0x1200)
/*! EVP registers. */
#define EVP_CPU_RESET_VECTOR 0x100
#define EVP_COP_RESET_VECTOR 0x200
#define EVP_COP_UNDEF_VECTOR 0x204
#define EVP_COP_SWI_VECTOR 0x208
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
#define EVP_COP_DATA_ABORT_VECTOR 0x210
#define EVP_COP_RSVD_VECTOR 0x214
#define EVP_COP_IRQ_VECTOR 0x218
#define EVP_COP_FIQ_VECTOR 0x21C
#define EVP_COP_IRQ_STS 0x220
/*! Primary Interrupt Controller registers. */
#define PRI_ICTLR_FIR 0x14
#define PRI_ICTLR_FIR_SET 0x18
#define PRI_ICTLR_FIR_CLR 0x1C
#define PRI_ICTLR_CPU_IER 0x20
#define PRI_ICTLR_CPU_IER_SET 0x24
#define PRI_ICTLR_CPU_IER_CLR 0x28
#define PRI_ICTLR_CPU_IEP_CLASS 0x2C
#define PRI_ICTLR_COP_IER 0x30
#define PRI_ICTLR_COP_IER_SET 0x34
#define PRI_ICTLR_COP_IER_CLR 0x38
#define PRI_ICTLR_COP_IEP_CLASS 0x3C
/*! AHB Gizmo registers. */
#define AHB_ARBITRATION_PRIORITY_CTRL 0x8
#define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29)
#define PRIORITY_SELECT_USB BIT(6) // USB-OTG.
#define PRIORITY_SELECT_USB2 BIT(18) // USB-HSIC.
#define PRIORITY_SELECT_USB3 BIT(17) // XUSB.
#define AHB_GIZMO_AHB_MEM 0x10
#define AHB_MEM_ENB_FAST_REARBITRATE BIT(2)
#define AHB_MEM_DONT_SPLIT_AHB_WR BIT(7)
#define AHB_MEM_IMMEDIATE BIT(18)
#define AHB_GIZMO_APB_DMA 0x14
#define AHB_GIZMO_USB 0x20
#define AHB_GIZMO_SDMMC4 0x48
#define AHB_GIZMO_USB2 0x7C
#define AHB_GIZMO_USB3 0x80
#define AHB_GIZMO_IMMEDIATE BIT(18)
#define AHB_ARBITRATION_XBAR_CTRL 0xE0
#define AHB_AHB_MEM_PREFETCH_CFG3 0xE4
#define AHB_AHB_MEM_PREFETCH_CFG4 0xE8
#define AHB_AHB_MEM_PREFETCH_CFG1 0xF0
#define AHB_AHB_MEM_PREFETCH_CFG2 0xF4
#define MST_ID(x) (((x) & 0x1F) << 26)
#define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5)
#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG.
#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC.
#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB.
#define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21)
#define MEM_PREFETCH_ENABLE BIT(31)
#define AHB_AHB_SPARE_REG 0x110
/*! Misc registers. */
#define APB_MISC_PP_STRAPPING_OPT_A 0x08
#define APB_MISC_PP_PINMUX_GLOBAL 0x40
#define APB_MISC_GP_HIDREV 0x804
#define GP_HIDREV_MAJOR_T210 0x1
#define GP_HIDREV_MAJOR_T210B01 0x2
#define APB_MISC_GP_AUD_MCLK_CFGPADCTRL 0x8F4
#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34
#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98
#define APB_MISC_GP_EMMC2_PAD_CFGPADCTRL 0xA9C
#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4
#define APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL 0xABC
#define APB_MISC_GP_DSI_PAD_CONTROL 0xAC0
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68
/*! Secure boot registers. */
#define SB_CSR 0x0
#define SB_CSR_NS_RST_VEC_WR_DIS BIT(1)
#define SB_CSR_PIROM_DISABLE BIT(4)
#define SB_AA64_RESET_LOW 0x30
#define SB_AA64_RST_AARCH64_MODE_EN BIT(0)
#define SB_AA64_RESET_HIGH 0x34
/*! SOR registers. */
#define SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB 0x1E8
#define SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB 0x21C
#define SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB 0x208
#define SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB 0x20C
/*! RTC registers. */
#define APBDEV_RTC_SECONDS 0x8
#define APBDEV_RTC_SHADOW_SECONDS 0xC
#define APBDEV_RTC_MILLI_SECONDS 0x10
/*! SYSCTR0 registers. */
#define SYSCTR0_CNTFID0 0x20
#define SYSCTR0_CNTCR 0x00
#define SYSCTR0_COUNTERID0 0xFE0
#define SYSCTR0_COUNTERID1 0xFE4
#define SYSCTR0_COUNTERID2 0xFE8
#define SYSCTR0_COUNTERID3 0xFEC
#define SYSCTR0_COUNTERID4 0xFD0
#define SYSCTR0_COUNTERID5 0xFD4
#define SYSCTR0_COUNTERID6 0xFD8
#define SYSCTR0_COUNTERID7 0xFDC
#define SYSCTR0_COUNTERID8 0xFF0
#define SYSCTR0_COUNTERID9 0xFF4
#define SYSCTR0_COUNTERID10 0xFF8
#define SYSCTR0_COUNTERID11 0xFFC
/*! TMR registers. */
#define TIMERUS_CNTR_1US (0x10 + 0x0)
#define TIMERUS_USEC_CFG (0x10 + 0x4)
#define TIMER_TMR8_TMR_PTV 0x78
#define TIMER_TMR9_TMR_PTV 0x80
#define TIMER_PER_EN BIT(30)
#define TIMER_EN BIT(31)
#define TIMER_TMR8_TMR_PCR 0x7C
#define TIMER_TMR9_TMR_PCR 0x8C
#define TIMER_INTR_CLR BIT(30)
#define TIMER_WDT4_CONFIG (0x100 + 0x80)
#define TIMER_SRC(TMR) ((TMR) & 0xF)
#define TIMER_PER(PER) (((PER) & 0xFF) << 4)
#define TIMER_SYSRESET_EN BIT(14)
#define TIMER_PMCRESET_EN BIT(15)
#define TIMER_WDT4_COMMAND (0x108 + 0x80)
#define TIMER_START_CNT BIT(0)
#define TIMER_CNT_DISABLE BIT(1)
#define TIMER_WDT4_UNLOCK_PATTERN (0x10C + 0x80)
#define TIMER_MAGIC_PTRN 0xC45A
/*! I2S registers. */
#define I2S1_CG 0x88
#define I2S1_CTRL 0xA0
#define I2S2_CG 0x188
#define I2S2_CTRL 0x1A0
#define I2S3_CG 0x288
#define I2S3_CTRL 0x2A0
#define I2S4_CG 0x388
#define I2S4_CTRL 0x3A0
#define I2S5_CG 0x488
#define I2S5_CTRL 0x4A0
#define I2S_CG_SLCG_ENABLE BIT(0)
#define I2S_CTRL_MASTER_EN BIT(10)
/*! PWM registers. */
#define PWM_CONTROLLER_PWM_CSR_0 0x00
#define PWM_CONTROLLER_PWM_CSR_1 0x10
#define PWM_CSR_EN BIT(31)
/*! Special registers. */
#define EMC_SCRATCH0 0x324
#define EMC_HEKA_UPD BIT(30)
/*! Flow controller registers. */
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
#define HALT_COP_GIC_IRQ BIT(9)
#define HALT_COP_LIC_IRQ BIT(11)
#define HALT_COP_SEC BIT(23)
#define HALT_COP_MSEC BIT(24)
#define HALT_COP_USEC BIT(25)
#define HALT_COP_JTAG BIT(28)
#define HALT_COP_WAIT_EVENT BIT(30)
#define HALT_COP_STOP_UNTIL_IRQ BIT(31)
#define HALT_COP_MAX_CNT 0xFF
#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0
#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14
#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C
#define FLOW_CTLR_HALT_CPU3_EVENTS 0x24
#define FLOW_CTLR_CPU0_CSR 0x8
#define FLOW_CTLR_CPU1_CSR 0x18
#define FLOW_CTLR_CPU2_CSR 0x20
#define FLOW_CTLR_CPU3_CSR 0x28
#define FLOW_CTLR_RAM_REPAIR 0x40
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
#endif

174
bdk/soc/uart.c Normal file
View File

@@ -0,0 +1,174 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/uart.h>
#include <soc/clock.h>
#include <soc/t210.h>
#include <utils/util.h>
/* UART A, B, C, D and E. */
static const u32 uart_baseoff[5] = { 0, 0x40, 0x200, 0x300, 0x400 };
void uart_init(u32 idx, u32 baud)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
// Make sure no data is being sent.
uart_wait_idle(idx, UART_TX_IDLE);
// Set clock.
bool clk_type = clock_uart_use_src_div(idx, baud);
// Misc settings.
u32 div = clk_type ? ((8 * baud + 408000000) / (16 * baud)) : 1; // DIV_ROUND_CLOSEST.
uart->UART_IER_DLAB = 0; // Disable interrupts.
uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode.
uart->UART_THR_DLAB = (u8)div; // Divisor latch LSB.
uart->UART_IER_DLAB = (u8)(div >> 8); // Divisor latch MSB.
uart->UART_LCR = UART_LCR_WORD_LENGTH_8; // Disable DLAB.
(void)uart->UART_SPR;
// Setup and flush fifo.
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO;
(void)uart->UART_SPR;
usleep(20);
uart->UART_MCR = 0; // Disable hardware flow control.
usleep(96);
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | UART_IIR_FCR_TX_CLR | UART_IIR_FCR_RX_CLR;
// Wait 3 symbols for baudrate change.
usleep(3 * ((baud + 999999) / baud));
uart_wait_idle(idx, UART_TX_IDLE | UART_RX_IDLE);
}
void uart_wait_idle(u32 idx, u32 which)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
if (UART_TX_IDLE & which)
{
while (!(uart->UART_LSR & UART_LSR_TMTY))
;
}
if (UART_RX_IDLE & which)
{
while (uart->UART_LSR & UART_LSR_RDR)
;
}
}
void uart_send(u32 idx, const u8 *buf, u32 len)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
for (u32 i = 0; i != len; i++)
{
while (!(uart->UART_LSR & UART_LSR_THRE))
;
uart->UART_THR_DLAB = buf[i];
}
}
u32 uart_recv(u32 idx, u8 *buf, u32 len)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
u32 timeout = get_tmr_us() + 250;
u32 i;
for (i = 0; ; i++)
{
while (!(uart->UART_LSR & UART_LSR_RDR))
{
if (timeout < get_tmr_us())
break;
if (len && len < i)
break;
}
if (timeout < get_tmr_us())
break;
buf[i] = uart->UART_THR_DLAB;
timeout = get_tmr_us() + 250;
}
return i ? (len ? (i - 1) : i) : 0;
}
void uart_invert(u32 idx, bool enable, u32 invert_mask)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
if (enable)
uart->UART_IRDA_CSR |= invert_mask;
else
uart->UART_IRDA_CSR &= ~invert_mask;
(void)uart->UART_SPR;
}
u32 uart_get_IIR(u32 idx)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
u32 iir = uart->UART_IIR_FCR & UART_IIR_INT_MASK;
if (iir & UART_IIR_NO_INT)
return 0;
else
return ((iir >> 1) + 1); // Return encoded interrupt.
}
void uart_set_IIR(u32 idx)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
uart->UART_IER_DLAB &= ~UART_IER_DLAB_IE_EORD;
(void)uart->UART_SPR;
uart->UART_IER_DLAB |= UART_IER_DLAB_IE_EORD;
(void)uart->UART_SPR;
}
void uart_empty_fifo(u32 idx, u32 which)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
uart->UART_MCR = 0;
(void)uart->UART_SPR;
usleep(96);
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | UART_IIR_FCR_TX_CLR | UART_IIR_FCR_RX_CLR;
(void)uart->UART_SPR;
usleep(18);
u32 tries = 0;
if (UART_IIR_FCR_TX_CLR & which)
{
while (tries < 10 && uart->UART_LSR & UART_LSR_TMTY)
{
tries++;
usleep(100);
}
tries = 0;
}
if (UART_IIR_FCR_RX_CLR & which)
{
while (tries < 10 && !uart->UART_LSR & UART_LSR_RDR)
{
tries++;
usleep(100);
}
}
}

98
bdk/soc/uart.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2020 CTCaer
*
* 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 _UART_H_
#define _UART_H_
#include <utils/types.h>
#define UART_A 0
#define UART_B 1
#define UART_C 2
#define UART_D 3
#define UART_E 4
#define BAUD_115200 115200
#define UART_TX_IDLE 0x1
#define UART_RX_IDLE 0x2
#define UART_TX_FIFO_FULL 0x100
#define UART_RX_FIFO_EMPTY 0x200
#define UART_INVERT_RXD 0x01
#define UART_INVERT_TXD 0x02
#define UART_INVERT_CTS 0x04
#define UART_INVERT_RTS 0x08
#define UART_IER_DLAB_IE_EORD 0x20
#define UART_LCR_DLAB 0x80
#define UART_LCR_STOP 0x4
#define UART_LCR_WORD_LENGTH_8 0x3
#define UART_LSR_RDR 0x1
#define UART_LSR_THRE 0x20
#define UART_LSR_TMTY 0x40
#define UART_LSR_FIFOE 0x80
#define UART_IIR_FCR_TX_CLR 0x4
#define UART_IIR_FCR_RX_CLR 0x2
#define UART_IIR_FCR_EN_FIFO 0x1
#define UART_IIR_NO_INT BIT(0)
#define UART_IIR_INT_MASK 0xF
/* Custom returned interrupt results. Actual interrupts are -1 */
#define UART_IIR_NOI 0 // No interrupt.
#define UART_IIR_MSI 1 // Modem status interrupt.
#define UART_IIR_THRI 2 // Transmitter holding register empty.
#define UART_IIR_RDI 3 // Receiver data interrupt.
#define UART_IIR_ERROR 4 // Overrun Error, Parity Error, Framing Error, Break.
#define UART_IIR_REDI 5 // Receiver end of data interrupt.
#define UART_IIR_RDTI 7 // Receiver data timeout interrupt.
#define UART_MCR_RTS 0x2
#define UART_MCR_DTR 0x1
typedef struct _uart_t
{
/* 0x00 */ vu32 UART_THR_DLAB;
/* 0x04 */ vu32 UART_IER_DLAB;
/* 0x08 */ vu32 UART_IIR_FCR;
/* 0x0C */ vu32 UART_LCR;
/* 0x10 */ vu32 UART_MCR;
/* 0x14 */ vu32 UART_LSR;
/* 0x18 */ vu32 UART_MSR;
/* 0x1C */ vu32 UART_SPR;
/* 0x20 */ vu32 UART_IRDA_CSR;
/* 0x24 */ vu32 UART_RX_FIFO_CFG;
/* 0x28 */ vu32 UART_MIE;
/* 0x2C */ vu32 UART_VENDOR_STATUS;
/* 0x30 */ u8 _pad_30[0xC];
/* 0x3C */ vu32 UART_ASR;
} uart_t;
void uart_init(u32 idx, u32 baud);
void uart_wait_idle(u32 idx, u32 which);
void uart_send(u32 idx, const u8 *buf, u32 len);
u32 uart_recv(u32 idx, u8 *buf, u32 len);
void uart_invert(u32 idx, bool enable, u32 invert_mask);
u32 uart_get_IIR(u32 idx);
void uart_set_IIR(u32 idx);
void uart_empty_fifo(u32 idx, u32 which);
#endif

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