Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b77f185269 | ||
|
|
f776c1f79f | ||
|
|
c0bad45cde |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
.vs
|
||||
.vscode
|
||||
build/*
|
||||
output/*
|
||||
build_ipl/*
|
||||
|
||||
147
Makefile
147
Makefile
@@ -2,115 +2,68 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/base_rules
|
||||
CC = $(DEVKITARM)/bin/arm-none-eabi-gcc
|
||||
LD = $(DEVKITARM)/bin/arm-none-eabi-ld
|
||||
OBJCOPY = $(DEVKITARM)/bin/arm-none-eabi-objcopy
|
||||
|
||||
################################################################################
|
||||
|
||||
IPL_LOAD_ADDR := 0x40008000
|
||||
IPL_MAGIC := 0x43544349 #"ICTC"
|
||||
include ./Versions.inc
|
||||
|
||||
################################################################################
|
||||
|
||||
TARGET := hekate
|
||||
BUILDDIR := build
|
||||
OUTPUTDIR := output
|
||||
SOURCEDIR = bootloader
|
||||
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
|
||||
|
||||
# Main and graphics.
|
||||
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
start.o exception_handlers.o \
|
||||
main.o heap.o \
|
||||
gfx.o tui.o \
|
||||
fe_emmc_tools.o fe_info.o fe_tools.o \
|
||||
TARGET := ipl
|
||||
BUILD := build_ipl
|
||||
SOURCEDIR := ipl
|
||||
OBJS = $(addprefix $(BUILD)/, \
|
||||
start.o \
|
||||
main.o \
|
||||
btn.o \
|
||||
clock.o \
|
||||
cluster.o \
|
||||
fuse.o \
|
||||
gpio.o \
|
||||
heap.o \
|
||||
hos.o \
|
||||
i2c.o \
|
||||
kfuse.o \
|
||||
lz.o \
|
||||
max7762x.o \
|
||||
mc.o \
|
||||
nx_emmc.o \
|
||||
sdmmc.o \
|
||||
sdmmc_driver.o \
|
||||
sdram.o \
|
||||
sdram_lp0.o \
|
||||
tui.o \
|
||||
util.o \
|
||||
di.o \
|
||||
gfx.o \
|
||||
pinmux.o \
|
||||
pkg1.o \
|
||||
pkg2.o \
|
||||
se.o \
|
||||
tsec.o \
|
||||
uart.o \
|
||||
ini.o \
|
||||
)
|
||||
|
||||
# Hardware.
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
bpmp.o clock.o cluster.o di.o gpio.o i2c.o irq.o mc.o sdram.o \
|
||||
pinmux.o se.o smmu.o tsec.o uart.o \
|
||||
fuse.o kfuse.o minerva.o \
|
||||
sdmmc.o sdmmc_driver.o emummc.o nx_emmc.o nx_sd.o \
|
||||
bq24193.o max17050.o max7762x.o max77620-rtc.o \
|
||||
hw_init.o \
|
||||
)
|
||||
|
||||
# Utilities.
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
btn.o dirlist.o ianos.o util.o \
|
||||
config.o ini.o \
|
||||
)
|
||||
|
||||
# Horizon.
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
hos.o hos_config.o pkg1.o pkg2.o pkg2_ini_kippatch.o fss.o secmon_exo.o sept.o \
|
||||
)
|
||||
|
||||
# Libraries.
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
lz.o blz.o \
|
||||
diskio.o ff.o ffunicode.o ffsystem.o \
|
||||
elfload.o elfreloc_arm.o \
|
||||
)
|
||||
|
||||
################################################################################
|
||||
|
||||
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) -DBL_MAGIC=$(IPL_MAGIC)
|
||||
CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_RESERVED=$(BLVERSION_RSVD)
|
||||
CUSTOMDEFINES += -DNYX_VER_MJ=$(NYXVERSION_MAJOR) -DNYX_VER_MN=$(NYXVERSION_MINOR) -DNYX_VER_HF=$(NYXVERSION_HOTFX) -DNYX_RESERVED=$(NYXVERSION_RSVD)
|
||||
#CUSTOMDEFINES += -DMENU_LOGO_ENABLE
|
||||
|
||||
# 0: UART_A, 1: UART_B.
|
||||
#CUSTOMDEFINES += -DDEBUG_UART_PORT=0
|
||||
|
||||
#CUSTOMDEFINES += -DDEBUG
|
||||
OBJS += $(addprefix $(BUILD)/, diskio.o ff.o ffunicode.o)
|
||||
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES)
|
||||
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
|
||||
CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11# -Wall
|
||||
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections
|
||||
|
||||
MODULEDIRS := $(wildcard modules/*)
|
||||
NYXDIR := $(wildcard nyx)
|
||||
.PHONY: all clean
|
||||
|
||||
################################################################################
|
||||
|
||||
.PHONY: all clean $(MODULEDIRS) $(NYXDIR)
|
||||
|
||||
all: $(TARGET).bin
|
||||
@echo -n "Payload size is "
|
||||
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
||||
@echo $(BIN_SIZE)
|
||||
@echo "Max size is 126296 Bytes."
|
||||
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
||||
all: $(BUILD)/$(TARGET)
|
||||
|
||||
clean:
|
||||
@rm -rf $(OBJS)
|
||||
@rm -rf $(BUILDDIR)
|
||||
@rm -rf $(OUTPUTDIR)
|
||||
@rm -rf $(BUILD)/$(TARGET).elf
|
||||
@rm -rf $(BUILD)/$(TARGET)
|
||||
|
||||
$(MODULEDIRS):
|
||||
$(MAKE) -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
|
||||
$(BUILD)/$(TARGET): $(BUILD)/$(TARGET).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(NYXDIR):
|
||||
$(MAKE) -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
|
||||
$(BUILD)/$(TARGET).elf: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -T ipl/link.ld $^ -o $@
|
||||
|
||||
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR)
|
||||
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
|
||||
@printf ICTC49 >> $(OUTPUTDIR)/$@
|
||||
|
||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
||||
|
||||
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
||||
$(BUILD)/%.o: $(SOURCEDIR)/%.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILDDIR)/$(TARGET)/%.o: %.S
|
||||
$(BUILD)/%.o: $(SOURCEDIR)/%.S
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJS): $(BUILDDIR)/$(TARGET)
|
||||
|
||||
$(BUILDDIR)/$(TARGET):
|
||||
@mkdir -p "$(BUILDDIR)"
|
||||
@mkdir -p "$(BUILDDIR)/$(TARGET)"
|
||||
@mkdir -p "$(OUTPUTDIR)"
|
||||
|
||||
172
README.md
172
README.md
@@ -1,168 +1,16 @@
|
||||
# hekate - CTCaer mod
|
||||
# hekate
|
||||
|
||||

|
||||

|
||||
|
||||
Nintendo Switch bootloader, firmware patcher, and more.
|
||||
|
||||
Custom Nintendo Switch bootloader, firmware patcher, and more.
|
||||
## ipl config
|
||||
|
||||
The ipl can be configured via 'hekate_ipl.ini' (if it is present on the SD card). Each ini section represents a boot entry, except for the special section 'config' that controls the global configuration.
|
||||
|
||||
## Bootloader folders and files
|
||||
Possible key/value combinations:
|
||||
|
||||
| Folder/File | Description |
|
||||
| ------------------------ | --------------------------------------------------------------------- |
|
||||
| bootloader | Main folder. |
|
||||
| \|__ bootlogo.bmp | It is used when custom is on and no logopath found. Can be skipped. |
|
||||
| \|__ hekate_ipl.ini | Main bootloader configuration and boot entries. |
|
||||
| \|__ patches.ini | Add external patches. Can be skipped. A template can be found [here](./res/patches_template.ini) |
|
||||
| \|__ update.bin | If newer, it is loaded at boot. For modchips. Auto updated. Can be skipped. |
|
||||
| bootloader/ini/ | For individual inis. 'More configs...' menu. Autoboot is supported. |
|
||||
| bootloader/res/ | Nyx user resources. Icons and more. |
|
||||
| \|__ background.bmp | Nyx - custom background. |
|
||||
| \|__ icon_switch.bmp | Nyx - Default icon for CFWs. |
|
||||
| \|__ icon_payload.bmp | Nyx - Default icon for Payloads. |
|
||||
| \|__ icon_lakka.bmp | Nyx - Default icon for Lakka. |
|
||||
| bootloader/sys/ | For system modules. |
|
||||
| \|__ emummc.kipm | emuMMC KIP1 module. Important! |
|
||||
| \|__ libsys_lp0.bso | LP0 (sleep mode) module. Important! |
|
||||
| \|__ libsys_minerva.bso | Minerva Training Cell. Used for DRAM Frequency training. Important! |
|
||||
| \|__ nyx.bin | Nyx - Our GUI. Important! |
|
||||
| \|__ res.pak | Nyx resources package. Important! |
|
||||
| bootloader/screenshots/ | Folder where Nyx screenshots are saved |
|
||||
| bootloader/payloads/ | For payloads. 'Payloads...' menu. Autoboot only supported by including them into an ini. All CFW bootloaders, tools, Linux payloads are supported. |
|
||||
| bootloader/libtools/ | Future reserved |
|
||||
| sept | Sept folder. This must be always get updated via the Atmosphère release zip. Needed for tools and booting HOS on 7.0.0 and up. Unused for booting HOS if `fss0=` key is defined. |
|
||||
|
||||
**Note**: Sept files for booting 7.0.0 and up are expected at /sept folder at root of sd card.
|
||||
|
||||
|
||||
## Bootloader configuration
|
||||
|
||||
The bootloader can be configured via 'bootloader/hekate_ipl.ini' (if it is present on the SD card). Each ini section represents a boot entry, except for the special section 'config' that controls the global configuration.
|
||||
|
||||
|
||||
There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Caption, "**#**": Comment, "*newline*": .ini cosmetic newline.
|
||||
|
||||
|
||||
You can find a template [Here](./res/hekate_ipl_template.ini)
|
||||
|
||||
|
||||
### Global Configuration keys/values when boot entry is **config**:
|
||||
|
||||
| Config option | Description |
|
||||
| ------------------ | ---------------------------------------------------------- |
|
||||
| autoboot=0 | 0: Disable, #: Boot entry number to auto boot. |
|
||||
| autoboot_list=0 | 0: Read `autoboot` boot entry from hekate_ipl.ini, 1: Read from ini folder (ini files are ASCII ordered). |
|
||||
| bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. |
|
||||
| autohosoff=1 | 0: Disable, 1: If woke up from HOS via an RTC alarm, shows logo, then powers off completely, 2: No logo, immediately powers off.|
|
||||
| autonogc=1 | 0: Disable, 1: Automatically applies nogc patch if unburnt fuses found and a >= 4.0.0 HOS is booted. |
|
||||
| updater2p=0 | 0: Disable, 1: Force updates (if needed) the reboot2payload binary to be hekate. |
|
||||
| backlight=100 | Screen backlight level. 0-255. |
|
||||
|
||||
|
||||
### Nyx Global Configuration keys/values for (nyx.ini):
|
||||
|
||||
| Config option | Description |
|
||||
| ------------------ | ---------------------------------------------------------- |
|
||||
| themecolor=167 | Sets Nyx color of text highlights. |
|
||||
| timeoff=100 | Sets time offset in HEX. Must be in HOS epoch format |
|
||||
| homescreen=0 | Sets home screen. 0: Home menu, 1: All configs (merges Launch and More configs), 2: Launch, 3: More Configs. |
|
||||
| verification=1 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and mostly reliable), 2: Full (sha256 based, slow and 100% reliable). |
|
||||
|
||||
|
||||
### Boot entry key/value combinations:
|
||||
|
||||
| Config option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
| warmboot={SD path} | Replaces the warmboot binary |
|
||||
| secmon={SD path} | Replaces the security monitor binary |
|
||||
| kernel={SD path} | Replaces the kernel binary |
|
||||
| kip1={SD path} | Replaces/Adds kernel initial process. Multiple can be set. |
|
||||
| kip1={SD folder}/* | Loads every .kip/.kip1 inside a folder. Compatible with single kip1 keys. |
|
||||
| fss0={SD path} | Takes a fusee-secondary binary and `extracts` all needed parts from it. kips, exosphere, warmboot and sept. |
|
||||
| fss0experimental=1 | Enables loading of experimental content from a FSS0 storage |
|
||||
| kip1patch=patchname | Enables a kip1 patch. Specify with multiple lines and/or as CSV. If not found, an error will show up |
|
||||
| fullsvcperm=1 | Disables SVC verification (full services permission) |
|
||||
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
|
||||
| atmosphere=1 | Enables Atmosphère patching. |
|
||||
| emupath={SD folder} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
|
||||
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
|
||||
| emummc_force_disable=1 | Disables emuMMC if it's enabled. |
|
||||
| stock=1 | Disables unneeded kernel patching when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disabled=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
||||
| id=idname | Identifies boot entry for forced boot via id. Max 7 chars. |
|
||||
| payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. |
|
||||
| logopath={SD path} | If no logopath, `bootloader/bootlogo.bmp` will be used if exists. If logopath exists, it will load the specified bitmap. |
|
||||
| icon={SD path} | Force Nyx to use the icon defined here. If this is not found, it will check for a bmp named as the boot entry ([Test 2] -> `bootloader/res/Test 2.bmp`). Otherwise default will be used. |
|
||||
|
||||
|
||||
### Boot entry key/value Exosphère combinations:
|
||||
|
||||
| Config option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
| nouserexceptions=1 | Disables usermode exception handlers when paired with Exosphère. |
|
||||
| userpmu=1 | Enables user access to PMU when paired with Exosphère. |
|
||||
| cal0blank=1 | Overrides Exosphère config `blank_prodinfo_{sys/emu}mmc`. If that key doesn't exist, `exosphere.ini` will be used. |
|
||||
| cal0writesys=1 | Overrides Exosphère config `allow_writing_to_cal_sysmmc`. If that key doesn't exist, `exosphere.ini` will be used. |
|
||||
|
||||
|
||||
**Note1**: When using the wildcard (`/*`) with `kip1` you can still use the normal `kip1` after that to load extra single kips.
|
||||
|
||||
**Note2**: When using FSS0 it parses exosphere, warmboot and all core kips. You can override the first 2 by using `secmon`/`warmboot` after defining `fss0`.
|
||||
You can define `kip1` to load an extra kip or many via the wildcard (`/*`) usage.
|
||||
|
||||
**Warning**: Never define *fss0 core* kips when using `fss0` and make sure that the folder (when using `/*`), does not include them.
|
||||
This is in case the kips are incompatible between them. If compatible, you can override `fss0` kips with no issues (useful for testing with intermediate kip changes).
|
||||
|
||||
|
||||
### Payload storage:
|
||||
|
||||
hekate has a boot storage in the binary that helps it configure it outside of BPMP enviroment:
|
||||
|
||||
| Offset / Name | Description |
|
||||
| ----------------------- | ----------------------------------------------------------------- |
|
||||
| '0x94' boot_cfg | bit0: `Force AutoBoot`, bit1: `Show launch log`, bit2: Boot from ID, bit3: `Boot to emuMMC`, bit7: `sept run`. |
|
||||
| '0x95' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. |
|
||||
| '0x96' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. |
|
||||
| '0x97' extra_cfg | bit7: Force Nyx to run `Dump pkg1/2`. |
|
||||
| '0x98' xt_str[128] | Depends on the set cfg bits. |
|
||||
| '0x98' id[8] | When `Boot from ID` is set, it will search all inis automatically and find the boot entry with that id and boot it. Must be NULL terminated. |
|
||||
| '0xA0' emummc_path[120] | When `Boot to emuMMC` is set, it will override the current emuMMC (boot entry or emummc.ini). Must be NULL terminated. |
|
||||
|
||||
|
||||
If the main .ini is not found, it is created on the first hekate boot.
|
||||
|
||||
|
||||
```
|
||||
hekate (c) 2018, naehrwert, st4rk.
|
||||
(c) 2018-2020, CTCaer.
|
||||
|
||||
Nyx GUI (c) 2019-2020, CTCaer.
|
||||
|
||||
Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8.
|
||||
Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
|
||||
|
||||
Open source and free packages used:
|
||||
- FatFs R0.13a, Copyright (c) 2017, ChaN
|
||||
- bcl-1.2.0, Copyright (c) 2003-2006, Marcus Geelnard
|
||||
- Atmosphère (Exosphere types/panic, prc id kernel patches),
|
||||
Copyright (c) 2018-2019, Atmosphère-NX
|
||||
- elfload, Copyright (c) 2014 Owen Shepherd, Copyright (c) 2018 M4xw
|
||||
- Littlev Graphics Library, Copyright (c) 2016 Gabor Kiss-Vamosi
|
||||
|
||||
___
|
||||
.-' `'.
|
||||
/ \
|
||||
| ;
|
||||
| | ___.--,
|
||||
_.._ |0) = (0) | _.---'`__.-( (_.
|
||||
__.--'`_.. '.__.\ '--. \_.-' ,.--'` `""`
|
||||
( ,.--'` ',__ /./; ;, '.__.'` __
|
||||
_`) ) .---.__.' / | |\ \__..--"" """--.,_
|
||||
`---' .'.''-._.-'`_./ /\ '. \ _.--''````'''--._`-.__.'
|
||||
| | .' _.-' | | \ \ '. `----`
|
||||
\ \/ .' \ \ '. '-._)
|
||||
\/ / \ \ `=.__`'-.
|
||||
/ /\ `) ) / / `"".`\
|
||||
, _.-'.'\ \ / / ( ( / /
|
||||
`--'` ) ) .-'.' '.'. | (
|
||||
(/` ( (` ) ) '-; [switchbrew]
|
||||
```
|
||||
- warmboot={SD path}
|
||||
- secmon={SD path}
|
||||
- kernel={SD path}
|
||||
- kip1={SD path}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# hekate - Bootlogo
|
||||
|
||||
The bootlogo can be any size with a maximum of 720 x 1280.
|
||||
|
||||
When it's smaller than 720 x 1280, it is automatically centered and the background takes the color of the first pixel.
|
||||
|
||||
When saving a landscape bootlogo, it should be rotated 90 degrees counterclockwise.
|
||||
|
||||
Lastly, the supported format is 32-bit (ARGB) BMP. Classic 24-bit (RGB) BMPs are not supported for performance reasons.
|
||||
|
||||
|
||||
## How to configure
|
||||
|
||||
If the custom logo option is enabled, it will try to load /bootlogo.bmp. If this is not found, the default hekate's logo will be used.
|
||||
|
||||
If a boot entry specifies a custom logo path, this is one will be loaded. Again if this is not found, bootlogo.bmp will be loaded and if that fails, hekate's built-in will be used.
|
||||
11
Versions.inc
11
Versions.inc
@@ -1,11 +0,0 @@
|
||||
# IPL Version.
|
||||
BLVERSION_MAJOR := 5
|
||||
BLVERSION_MINOR := 2
|
||||
BLVERSION_HOTFX := 0
|
||||
BLVERSION_RSVD := 0
|
||||
|
||||
# Nyx Version.
|
||||
NYXVERSION_MAJOR := 0
|
||||
NYXVERSION_MINOR := 9
|
||||
NYXVERSION_HOTFX := 0
|
||||
NYXVERSION_RSVD := 0
|
||||
@@ -1,616 +0,0 @@
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "ini.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../gfx/tui.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/list.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
void set_default_configuration()
|
||||
{
|
||||
h_cfg.autoboot = 0;
|
||||
h_cfg.autoboot_list = 0;
|
||||
h_cfg.bootwait = 3;
|
||||
h_cfg.se_keygen_done = 0;
|
||||
h_cfg.sbar_time_keeping = 0;
|
||||
h_cfg.backlight = 100;
|
||||
h_cfg.autohosoff = 0;
|
||||
h_cfg.autonogc = 1;
|
||||
h_cfg.updater2p = 0;
|
||||
h_cfg.brand = NULL;
|
||||
h_cfg.tagline = NULL;
|
||||
h_cfg.errors = 0;
|
||||
h_cfg.eks = NULL;
|
||||
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
|
||||
h_cfg.rcm_patched = true;
|
||||
h_cfg.emummc_force_disable = false;
|
||||
|
||||
sd_power_cycle_time_start = 0;
|
||||
}
|
||||
|
||||
int create_config_entry()
|
||||
{
|
||||
if (!sd_mount())
|
||||
return 1;
|
||||
|
||||
char lbuf[32];
|
||||
FIL fp;
|
||||
bool mainIniFound = false;
|
||||
|
||||
LIST_INIT(ini_sections);
|
||||
|
||||
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
||||
mainIniFound = true;
|
||||
else
|
||||
{
|
||||
u8 res = f_open(&fp, "bootloader/hekate_ipl.ini", FA_READ);
|
||||
if (res == FR_NO_FILE || res == FR_NO_PATH)
|
||||
{
|
||||
f_mkdir("bootloader");
|
||||
f_mkdir("bootloader/ini");
|
||||
f_mkdir("bootloader/payloads");
|
||||
f_mkdir("bootloader/sys");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!res)
|
||||
f_close(&fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (f_open(&fp, "bootloader/hekate_ipl.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
|
||||
return 1;
|
||||
// Add config entry.
|
||||
f_puts("[config]\nautoboot=", &fp);
|
||||
itoa(h_cfg.autoboot, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nautoboot_list=", &fp);
|
||||
itoa(h_cfg.autoboot_list, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nbootwait=", &fp);
|
||||
itoa(h_cfg.bootwait, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nbacklight=", &fp);
|
||||
itoa(h_cfg.backlight, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nautohosoff=", &fp);
|
||||
itoa(h_cfg.autohosoff, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nautonogc=", &fp);
|
||||
itoa(h_cfg.autonogc, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nupdater2p=", &fp);
|
||||
itoa(h_cfg.updater2p, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
if (h_cfg.brand)
|
||||
{
|
||||
f_puts("\nbrand=", &fp);
|
||||
f_puts(h_cfg.brand, &fp);
|
||||
}
|
||||
if (h_cfg.tagline)
|
||||
{
|
||||
f_puts("\ntagline=", &fp);
|
||||
f_puts(h_cfg.tagline, &fp);
|
||||
}
|
||||
f_puts("\n", &fp);
|
||||
|
||||
if (mainIniFound)
|
||||
{
|
||||
// Re-construct existing entries.
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
if (!strcmp(ini_sec->name, "config"))
|
||||
continue;
|
||||
|
||||
switch (ini_sec->type)
|
||||
{
|
||||
case INI_CHOICE: // Re-construct Boot entry [ ].
|
||||
f_puts("[", &fp);
|
||||
f_puts(ini_sec->name, &fp);
|
||||
f_puts("]\n", &fp);
|
||||
// Re-construct boot entry's config.
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
{
|
||||
f_puts(kv->key, &fp);
|
||||
f_puts("=", &fp);
|
||||
f_puts(kv->val, &fp);
|
||||
f_puts("\n", &fp);
|
||||
}
|
||||
break;
|
||||
case INI_CAPTION: // Re-construct caption entry { }.
|
||||
f_puts("{", &fp);
|
||||
f_puts(ini_sec->name, &fp);
|
||||
f_puts("}\n", &fp);
|
||||
break;
|
||||
case INI_NEWLINE: // Re-construct cosmetic newline \n.
|
||||
f_puts("\n", &fp);
|
||||
break;
|
||||
case INI_COMMENT: // Re-construct comment entry #.
|
||||
f_puts("#", &fp);
|
||||
f_puts(ini_sec->name, &fp);
|
||||
f_puts("\n", &fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f_close(&fp);
|
||||
sd_unmount();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
static void _save_config()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!create_config_entry())
|
||||
gfx_puts("\nConfiguration was saved!\n");
|
||||
else
|
||||
EPRINTF("\nConfiguration saving failed!");
|
||||
gfx_puts("\nPress any key...");
|
||||
}
|
||||
|
||||
static void _config_autoboot_list(void *ent)
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 *temp_autoboot = NULL;
|
||||
|
||||
LIST_INIT(ini_sections);
|
||||
|
||||
u8 max_entries = 30;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
||||
u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries);
|
||||
char *boot_text = (char *)malloc(512 * max_entries);
|
||||
|
||||
for (u32 j = 0; j < max_entries; j++)
|
||||
boot_values[j] = j;
|
||||
|
||||
if (sd_mount())
|
||||
{
|
||||
if (ini_parse(&ini_sections, "bootloader/ini", true))
|
||||
{
|
||||
// Build configuration menu.
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
u32 i = 2;
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
// Skip other ini entries for autoboot.
|
||||
if (ini_sec->type == INI_CHOICE)
|
||||
{
|
||||
if (!strcmp(ini_sec->name, "config"))
|
||||
continue;
|
||||
|
||||
if (strlen(ini_sec->name) > 510)
|
||||
ments[i].caption = ini_sec->name;
|
||||
else
|
||||
{
|
||||
if (h_cfg.autoboot != (i - 1) || !h_cfg.autoboot_list)
|
||||
boot_text[(i - 1) * 512] = ' ';
|
||||
|
||||
else
|
||||
boot_text[(i - 1) * 512] = '*';
|
||||
strcpy(boot_text + (i - 1) * 512 + 1, ini_sec->name);
|
||||
ments[i].caption = &boot_text[(i - 1) * 512];
|
||||
}
|
||||
ments[i].type = ini_sec->type;
|
||||
ments[i].data = &boot_values[i - 1];
|
||||
i++;
|
||||
|
||||
if ((i - 1) > max_entries)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ments[i], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Select an entry to auto boot", 0, 0};
|
||||
temp_autoboot = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_autoboot != NULL)
|
||||
{
|
||||
h_cfg.autoboot = *(u32 *)temp_autoboot;
|
||||
h_cfg.autoboot_list = 1;
|
||||
_save_config();
|
||||
|
||||
ment_t *tmp = (ment_t *)ent;
|
||||
tmp->data = NULL;
|
||||
}
|
||||
else
|
||||
goto out2;
|
||||
}
|
||||
else
|
||||
{
|
||||
EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!.");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:;
|
||||
btn_wait();
|
||||
out2:;
|
||||
free(ments);
|
||||
free(boot_values);
|
||||
free(boot_text);
|
||||
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
void config_autoboot()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 *temp_autoboot = NULL;
|
||||
|
||||
LIST_INIT(ini_sections);
|
||||
|
||||
u8 max_entries = 30;
|
||||
u32 boot_text_size = 512;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 5));
|
||||
u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries);
|
||||
char *boot_text = (char *)malloc(boot_text_size * max_entries);
|
||||
|
||||
for (u32 j = 0; j < max_entries; j++)
|
||||
boot_values[j] = j;
|
||||
|
||||
if (sd_mount())
|
||||
{
|
||||
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
||||
{
|
||||
// Build configuration menu.
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
ments[2].type = MENT_DATA;
|
||||
if (!h_cfg.autoboot)
|
||||
ments[2].caption = "*Disable";
|
||||
else
|
||||
ments[2].caption = " Disable";
|
||||
ments[2].data = &boot_values[0];
|
||||
|
||||
ments[3].type = MENT_HDLR_RE;
|
||||
if (h_cfg.autoboot_list)
|
||||
ments[3].caption = "*More configs...";
|
||||
else
|
||||
ments[3].caption = " More configs...";
|
||||
ments[3].handler = _config_autoboot_list;
|
||||
ments[3].data = (void *)0xCAFE;
|
||||
|
||||
ments[4].type = MENT_CHGLINE;
|
||||
|
||||
u32 i = 5;
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
// Skip other ini entries for autoboot.
|
||||
if (ini_sec->type == INI_CHOICE)
|
||||
{
|
||||
if (!strcmp(ini_sec->name, "config"))
|
||||
continue;
|
||||
|
||||
if (strlen(ini_sec->name) > 510)
|
||||
ments[i].caption = ini_sec->name;
|
||||
else
|
||||
{
|
||||
if (h_cfg.autoboot != (i - 4) || h_cfg.autoboot_list)
|
||||
boot_text[(i - 4) * boot_text_size] = ' ';
|
||||
|
||||
else
|
||||
boot_text[(i - 4) * boot_text_size] = '*';
|
||||
strcpy(boot_text + (i - 4) * boot_text_size + 1, ini_sec->name);
|
||||
ments[i].caption = &boot_text[(i - 4) * boot_text_size];
|
||||
}
|
||||
ments[i].type = ini_sec->type;
|
||||
ments[i].data = &boot_values[i - 4];
|
||||
i++;
|
||||
|
||||
if ((i - 4) > max_entries)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 6 && !h_cfg.autoboot_list)
|
||||
{
|
||||
ments[i].type = MENT_CAPTION;
|
||||
ments[i].caption = "No main configurations found...";
|
||||
ments[i].color = 0xFFFFDD00;
|
||||
i++;
|
||||
}
|
||||
|
||||
memset(&ments[i], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Disable or select entry to auto boot", 0, 0};
|
||||
temp_autoboot = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_autoboot != NULL)
|
||||
{
|
||||
h_cfg.autoboot = *(u32 *)temp_autoboot;
|
||||
h_cfg.autoboot_list = 0;
|
||||
_save_config();
|
||||
}
|
||||
else
|
||||
goto out2;
|
||||
}
|
||||
else
|
||||
{
|
||||
EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!.");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:;
|
||||
btn_wait();
|
||||
out2:;
|
||||
free(ments);
|
||||
free(boot_values);
|
||||
free(boot_text);
|
||||
|
||||
sd_unmount();
|
||||
|
||||
if (temp_autoboot == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
void config_bootdelay()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 delay_entries = 6;
|
||||
u32 delay_text_size = 32;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (delay_entries + 3));
|
||||
u32 *delay_values = (u32 *)malloc(sizeof(u32) * delay_entries);
|
||||
char *delay_text = (char *)malloc(delay_text_size * delay_entries);
|
||||
|
||||
for (u32 j = 0; j < delay_entries; j++)
|
||||
delay_values[j] = j;
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
ments[2].type = MENT_DATA;
|
||||
if (h_cfg.bootwait)
|
||||
ments[2].caption = " 0 seconds (Bootlogo disabled)";
|
||||
else
|
||||
ments[2].caption = "*0 seconds (Bootlogo disabled)";
|
||||
ments[2].data = &delay_values[0];
|
||||
|
||||
u32 i = 0;
|
||||
for (i = 1; i < delay_entries; i++)
|
||||
{
|
||||
if (h_cfg.bootwait != i)
|
||||
delay_text[i * delay_text_size] = ' ';
|
||||
else
|
||||
delay_text[i * delay_text_size] = '*';
|
||||
delay_text[i * delay_text_size + 1] = i + '0';
|
||||
strcpy(delay_text + i * delay_text_size + 2, " seconds");
|
||||
|
||||
ments[i + 2].type = MENT_DATA;
|
||||
ments[i + 2].caption = delay_text + (i * delay_text_size);
|
||||
ments[i + 2].data = &delay_values[i];
|
||||
}
|
||||
|
||||
memset(&ments[i + 2], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Time delay for entering bootloader menu", 0, 0};
|
||||
|
||||
u32 *temp_bootwait = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_bootwait != NULL)
|
||||
{
|
||||
h_cfg.bootwait = *(u32 *)temp_bootwait;
|
||||
_save_config();
|
||||
}
|
||||
|
||||
free(ments);
|
||||
free(delay_values);
|
||||
free(delay_text);
|
||||
|
||||
if (temp_bootwait == NULL)
|
||||
return;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void config_backlight()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 bri_text_size = 8;
|
||||
u32 bri_entries = 11;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (bri_entries + 3));
|
||||
u32 *bri_values = (u32 *)malloc(sizeof(u32) * bri_entries);
|
||||
char *bri_text = (char *)malloc(bri_text_size * bri_entries);
|
||||
|
||||
for (u32 j = 1; j < bri_entries; j++)
|
||||
bri_values[j] = j * 10;
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
u32 i = 0;
|
||||
for (i = 1; i < bri_entries; i++)
|
||||
{
|
||||
if ((h_cfg.backlight / 20) != i)
|
||||
bri_text[i * bri_text_size] = ' ';
|
||||
else
|
||||
bri_text[i * bri_text_size] = '*';
|
||||
|
||||
if (i < 10)
|
||||
{
|
||||
bri_text[i * bri_text_size + 1] = i + '0';
|
||||
strcpy(bri_text + i * bri_text_size + 2, "0%");
|
||||
}
|
||||
else
|
||||
strcpy(bri_text + i * bri_text_size + 1, "100%");
|
||||
|
||||
ments[i + 1].type = MENT_DATA;
|
||||
ments[i + 1].caption = bri_text + (i * bri_text_size);
|
||||
ments[i + 1].data = &bri_values[i];
|
||||
}
|
||||
|
||||
memset(&ments[i + 1], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Backlight brightness", 0, 0};
|
||||
|
||||
u32 *temp_backlight = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_backlight != NULL)
|
||||
{
|
||||
h_cfg.backlight = (*(u32 *)temp_backlight) * 2;
|
||||
_save_config();
|
||||
}
|
||||
|
||||
free(ments);
|
||||
free(bri_values);
|
||||
free(bri_text);
|
||||
|
||||
if (temp_backlight == NULL)
|
||||
return;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void config_auto_hos_poweroff()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6);
|
||||
u32 *hp_values = (u32 *)malloc(sizeof(u32) * 3);
|
||||
|
||||
for (u32 j = 0; j < 3; j++)
|
||||
{
|
||||
hp_values[j] = j;
|
||||
ments[j + 2].type = MENT_DATA;
|
||||
ments[j + 2].data = &hp_values[j];
|
||||
}
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
if (h_cfg.autohosoff == 1)
|
||||
{
|
||||
ments[2].caption = " Disable";
|
||||
ments[3].caption = "*Enable";
|
||||
ments[4].caption = " Enable (No logo)";
|
||||
}
|
||||
else if (h_cfg.autohosoff >= 2)
|
||||
{
|
||||
ments[2].caption = " Disable";
|
||||
ments[3].caption = " Enable";
|
||||
ments[4].caption = "*Enable (No logo)";
|
||||
}
|
||||
else
|
||||
{
|
||||
ments[2].caption = "*Disable";
|
||||
ments[3].caption = " Enable";
|
||||
ments[4].caption = " Enable (No logo)";
|
||||
}
|
||||
|
||||
memset(&ments[5], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Power off if woke up from HOS", 0, 0};
|
||||
|
||||
u32 *temp_autohosoff = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_autohosoff != NULL)
|
||||
{
|
||||
h_cfg.autohosoff = *(u32 *)temp_autohosoff;
|
||||
_save_config();
|
||||
}
|
||||
|
||||
free(ments);
|
||||
free(hp_values);
|
||||
|
||||
if (temp_autohosoff == NULL)
|
||||
return;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void config_nogc()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 5);
|
||||
u32 *cb_values = (u32 *)malloc(sizeof(u32) * 2);
|
||||
|
||||
for (u32 j = 0; j < 2; j++)
|
||||
{
|
||||
cb_values[j] = j;
|
||||
ments[j + 2].type = MENT_DATA;
|
||||
ments[j + 2].data = &cb_values[j];
|
||||
}
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
if (h_cfg.autonogc)
|
||||
{
|
||||
ments[2].caption = " Disable";
|
||||
ments[3].caption = "*Auto";
|
||||
}
|
||||
else
|
||||
{
|
||||
ments[2].caption = "*Disable";
|
||||
ments[3].caption = " Auto";
|
||||
}
|
||||
|
||||
memset(&ments[4], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "No Gamecard", 0, 0};
|
||||
|
||||
u32 *temp_nogc = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_nogc != NULL)
|
||||
{
|
||||
h_cfg.autonogc = *(u32 *)temp_nogc;
|
||||
_save_config();
|
||||
}
|
||||
|
||||
free(ments);
|
||||
free(cb_values);
|
||||
|
||||
if (temp_nogc == NULL)
|
||||
return;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#include "../hos/hos.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
typedef struct _hekate_config
|
||||
{
|
||||
// Non-volatile config.
|
||||
u32 autoboot;
|
||||
u32 autoboot_list;
|
||||
u32 bootwait;
|
||||
u32 backlight;
|
||||
u32 autohosoff;
|
||||
u32 autonogc;
|
||||
u32 updater2p;
|
||||
char *brand;
|
||||
char *tagline;
|
||||
// Global temporary config.
|
||||
bool se_keygen_done;
|
||||
bool sept_run;
|
||||
bool emummc_force_disable;
|
||||
bool rcm_patched;
|
||||
u32 sbar_time_keeping;
|
||||
u32 errors;
|
||||
hos_eks_mbr_t *eks;
|
||||
} hekate_config;
|
||||
|
||||
void set_default_configuration();
|
||||
int create_config_entry();
|
||||
void config_autoboot();
|
||||
void config_bootdelay();
|
||||
void config_backlight();
|
||||
void config_auto_hos_poweroff();
|
||||
void config_nogc();
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* 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 "ini.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../utils/dirlist.h"
|
||||
|
||||
static char *_strdup(char *str)
|
||||
{
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
// Remove starting space.
|
||||
if (str[0] == ' ' && strlen(str))
|
||||
str++;
|
||||
|
||||
char *res = (char *)malloc(strlen(str) + 1);
|
||||
strcpy(res, str);
|
||||
|
||||
// Remove trailing space.
|
||||
if (strlen(res) && res[strlen(res) - 1] == ' ')
|
||||
res[strlen(res) - 1] = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 _find_section_name(char *lbuf, u32 lblen, char schar)
|
||||
{
|
||||
u32 i;
|
||||
// Depends on 'FF_USE_STRFUNC 2' that removes \r.
|
||||
for (i = 0; i < lblen && lbuf[i] != schar && lbuf[i] != '\n'; i++)
|
||||
;
|
||||
lbuf[i] = 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type)
|
||||
{
|
||||
if (csec)
|
||||
list_append(dst, &csec->link);
|
||||
|
||||
csec = (ini_sec_t *)calloc(sizeof(ini_sec_t), 1);
|
||||
csec->name = _strdup(name);
|
||||
csec->type = type;
|
||||
|
||||
return csec;
|
||||
}
|
||||
|
||||
int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
{
|
||||
u32 lblen;
|
||||
u32 pathlen = strlen(ini_path);
|
||||
u32 k = 0;
|
||||
char lbuf[512];
|
||||
char *filelist = NULL;
|
||||
FIL fp;
|
||||
ini_sec_t *csec = NULL;
|
||||
|
||||
char *filename = (char *)malloc(256);
|
||||
|
||||
strcpy(filename, ini_path);
|
||||
|
||||
// Get all ini filenames.
|
||||
if (is_dir)
|
||||
{
|
||||
filelist = dirlist(filename, "*.ini", false);
|
||||
if (!filelist)
|
||||
{
|
||||
free(filename);
|
||||
return 0;
|
||||
}
|
||||
strcpy(filename + pathlen, "/");
|
||||
pathlen++;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Copy ini filename in path string.
|
||||
if (is_dir)
|
||||
{
|
||||
if (filelist[k * 256])
|
||||
{
|
||||
strcpy(filename + pathlen, &filelist[k * 256]);
|
||||
k++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Open ini.
|
||||
if (f_open(&fp, filename, FA_READ) != FR_OK)
|
||||
{
|
||||
free(filelist);
|
||||
free(filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Fetch one line.
|
||||
lbuf[0] = 0;
|
||||
f_gets(lbuf, 512, &fp);
|
||||
lblen = strlen(lbuf);
|
||||
|
||||
// Remove trailing newline. Depends on 'FF_USE_STRFUNC 2' that removes \r.
|
||||
if (lblen && lbuf[lblen - 1] == '\n')
|
||||
lbuf[lblen - 1] = 0;
|
||||
|
||||
if (lblen > 2 && lbuf[0] == '[') // Create new section.
|
||||
{
|
||||
_find_section_name(lbuf, lblen, ']');
|
||||
|
||||
csec = _ini_create_section(dst, csec, &lbuf[1], INI_CHOICE);
|
||||
list_init(&csec->kvs);
|
||||
}
|
||||
else if (lblen > 1 && lbuf[0] == '{') // Create new caption. Support empty caption '{}'.
|
||||
{
|
||||
_find_section_name(lbuf, lblen, '}');
|
||||
|
||||
csec = _ini_create_section(dst, csec, &lbuf[1], INI_CAPTION);
|
||||
csec->color = 0xFF0AB9E6;
|
||||
}
|
||||
else if (lblen > 2 && lbuf[0] == '#') // Create comment.
|
||||
{
|
||||
csec = _ini_create_section(dst, csec, &lbuf[1], INI_COMMENT);
|
||||
}
|
||||
else if (lblen < 2) // Create empty line.
|
||||
{
|
||||
csec = _ini_create_section(dst, csec, NULL, INI_NEWLINE);
|
||||
}
|
||||
else if (csec && csec->type == INI_CHOICE) // Extract key/value.
|
||||
{
|
||||
u32 i = _find_section_name(lbuf, lblen, '=');
|
||||
|
||||
ini_kv_t *kv = (ini_kv_t *)calloc(sizeof(ini_kv_t), 1);
|
||||
kv->key = _strdup(&lbuf[0]);
|
||||
kv->val = _strdup(&lbuf[i + 1]);
|
||||
list_append(&csec->kvs, &kv->link);
|
||||
}
|
||||
} while (!f_eof(&fp));
|
||||
|
||||
f_close(&fp);
|
||||
|
||||
if (csec)
|
||||
{
|
||||
list_append(dst, &csec->link);
|
||||
if (is_dir)
|
||||
csec = NULL;
|
||||
}
|
||||
} while (is_dir);
|
||||
|
||||
free(filename);
|
||||
free(filelist);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *ini_check_payload_section(ini_sec_t *cfg)
|
||||
{
|
||||
if (cfg == NULL)
|
||||
return NULL;
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link)
|
||||
{
|
||||
if (!strcmp("payload", kv->key))
|
||||
return kv->val;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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 _INI_H_
|
||||
#define _INI_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
#include "../utils/list.h"
|
||||
|
||||
#define INI_CHOICE 3
|
||||
#define INI_CAPTION 5
|
||||
#define INI_CHGLINE 6
|
||||
#define INI_NEWLINE 0xFE
|
||||
#define INI_COMMENT 0xFF
|
||||
|
||||
typedef struct _ini_kv_t
|
||||
{
|
||||
char *key;
|
||||
char *val;
|
||||
link_t link;
|
||||
} ini_kv_t;
|
||||
|
||||
typedef struct _ini_sec_t
|
||||
{
|
||||
char *name;
|
||||
link_t kvs;
|
||||
link_t link;
|
||||
u32 type;
|
||||
u32 color;
|
||||
} ini_sec_t;
|
||||
|
||||
int ini_parse(link_t *dst, char *ini_path, bool is_dir);
|
||||
char *ini_check_payload_section(ini_sec_t *cfg);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
* 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 | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||
* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq
|
||||
* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
|
||||
* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
|
||||
* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
|
||||
* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und
|
||||
* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, 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
|
||||
@@ -1,922 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 Rajko Stojadinovic
|
||||
* 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 <stdlib.h>
|
||||
|
||||
#include "fe_emmc_tools.h"
|
||||
#include "../../common/memory_map.h"
|
||||
#include "../config/config.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../gfx/tui.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#define NUM_SECTORS_PER_ITER 8192 // 4MB Cache.
|
||||
#define OUT_FILENAME_SZ 128
|
||||
#define SHA256_SZ 0x20
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFilename, emmc_part_t *part)
|
||||
{
|
||||
FIL fp;
|
||||
u8 sparseShouldVerify = 4;
|
||||
u32 btn = 0;
|
||||
u32 prevPct = 200;
|
||||
u32 sdFileSector = 0;
|
||||
int res = 0;
|
||||
|
||||
u8 hashEm[SHA256_SZ];
|
||||
u8 hashSd[SHA256_SZ];
|
||||
|
||||
if (f_open(&fp, outFilename, FA_READ) == FR_OK)
|
||||
{
|
||||
u32 totalSectorsVer = (u32)((u64)f_size(&fp) >> (u64)9);
|
||||
|
||||
u8 *bufEm = (u8 *)EMMC_BUF_ALIGNED;
|
||||
u8 *bufSd = (u8 *)SDXC_BUF_ALIGNED;
|
||||
|
||||
u32 pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start);
|
||||
tui_pbar(0, gfx_con.y, pct, 0xFF96FF00, 0xFF155500);
|
||||
|
||||
u32 num = 0;
|
||||
while (totalSectorsVer > 0)
|
||||
{
|
||||
num = MIN(totalSectorsVer, NUM_SECTORS_PER_ITER);
|
||||
|
||||
// Check every time or every 4.
|
||||
// Every 4 protects from fake sd, sector corruption and frequent I/O corruption.
|
||||
// Full provides all that, plus protection from extremely rare I/O corruption.
|
||||
if (!(sparseShouldVerify % 4))
|
||||
{
|
||||
if (!sdmmc_storage_read(storage, lba_curr, num, bufEm))
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nFailed to read %d blocks (@LBA %08X),\nfrom eMMC!\n\nVerification failed..\n",
|
||||
num, lba_curr);
|
||||
|
||||
f_close(&fp);
|
||||
return 1;
|
||||
}
|
||||
f_lseek(&fp, (u64)sdFileSector << (u64)9);
|
||||
if (f_read(&fp, bufSd, num << 9, NULL))
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nFailed to read %d blocks (@LBA %08X),\nfrom sd card!\n\nVerification failed..\n", num, lba_curr);
|
||||
|
||||
f_close(&fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
se_calc_sha256(hashEm, bufEm, num << 9);
|
||||
se_calc_sha256(hashSd, bufSd, num << 9);
|
||||
res = memcmp(hashEm, hashSd, 0x10);
|
||||
|
||||
if (res)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nSD and eMMC data (@LBA %08X),\ndo not match!\n\nVerification failed..\n", lba_curr);
|
||||
|
||||
f_close(&fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start);
|
||||
if (pct != prevPct)
|
||||
{
|
||||
tui_pbar(0, gfx_con.y, pct, 0xFF96FF00, 0xFF155500);
|
||||
prevPct = pct;
|
||||
}
|
||||
|
||||
lba_curr += num;
|
||||
totalSectorsVer -= num;
|
||||
sdFileSector += num;
|
||||
sparseShouldVerify++;
|
||||
|
||||
btn = btn_wait_timeout(0, BTN_VOL_DOWN | BTN_VOL_UP);
|
||||
if ((btn & BTN_VOL_DOWN) && (btn & BTN_VOL_UP))
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
WPRINTF("\n\nVerification was cancelled!");
|
||||
gfx_con.fntsz = 8;
|
||||
msleep(1000);
|
||||
|
||||
f_close(&fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
f_close(&fp);
|
||||
|
||||
tui_pbar(0, gfx_con.y, pct, 0xFFCCCCCC, 0xFF555555);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTF("\nFile not found or could not be loaded.\n\nVerification failed..\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void _update_filename(char *outFilename, u32 sdPathLen, u32 numSplitParts, u32 currPartIdx)
|
||||
{
|
||||
if (numSplitParts >= 10 && currPartIdx < 10)
|
||||
{
|
||||
outFilename[sdPathLen] = '0';
|
||||
itoa(currPartIdx, &outFilename[sdPathLen + 1], 10);
|
||||
}
|
||||
else
|
||||
itoa(currPartIdx, &outFilename[sdPathLen], 10);
|
||||
}
|
||||
|
||||
static int _dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
{
|
||||
static const u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF;
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
u32 multipartSplitSize = (1u << 31);
|
||||
u32 totalSectors = part->lba_end - part->lba_start + 1;
|
||||
u32 currPartIdx = 0;
|
||||
u32 numSplitParts = 0;
|
||||
u32 maxSplitParts = 0;
|
||||
u32 btn = 0;
|
||||
bool isSmallSdCard = false;
|
||||
bool partialDumpInProgress = false;
|
||||
int res = 0;
|
||||
char *outFilename = sd_path;
|
||||
u32 sdPathLen = strlen(sd_path);
|
||||
|
||||
FIL partialIdxFp;
|
||||
char partialIdxFilename[12];
|
||||
strcpy(partialIdxFilename, "partial.idx");
|
||||
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_printf("\nSD Card free space: %d MiB, Total backup size %d MiB\n\n",
|
||||
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF,
|
||||
totalSectors >> SECTORS_TO_MIB_COEFF);
|
||||
|
||||
// 1GB parts for sd cards 8GB and less.
|
||||
if ((sd_storage.csd.capacity >> (20 - sd_storage.csd.read_blkbits)) <= 8192)
|
||||
multipartSplitSize = (1u << 30);
|
||||
// Maximum parts fitting the free space available.
|
||||
maxSplitParts = (sd_fs.free_clst * sd_fs.csize) / (multipartSplitSize / NX_EMMC_BLOCKSIZE);
|
||||
|
||||
// Check if the USER partition or the RAW eMMC fits the sd card free space.
|
||||
if (totalSectors > (sd_fs.free_clst * sd_fs.csize))
|
||||
{
|
||||
isSmallSdCard = true;
|
||||
|
||||
gfx_printf("%k\nSD card free space is smaller than backup size.%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
|
||||
if (!maxSplitParts)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTF("Not enough free space for Partial Backup.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Check if we are continuing a previous raw eMMC or USER partition backup in progress.
|
||||
if (f_open(&partialIdxFp, partialIdxFilename, FA_READ) == FR_OK && totalSectors > (FAT32_FILESIZE_LIMIT / NX_EMMC_BLOCKSIZE))
|
||||
{
|
||||
gfx_printf("%kFound Partial Backup in progress. Continuing...%k\n\n", 0xFFAEFD14, 0xFFCCCCCC);
|
||||
|
||||
partialDumpInProgress = true;
|
||||
// Force partial dumping, even if the card is larger.
|
||||
isSmallSdCard = true;
|
||||
|
||||
f_read(&partialIdxFp, &currPartIdx, 4, NULL);
|
||||
f_close(&partialIdxFp);
|
||||
|
||||
if (!maxSplitParts)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTF("Not enough free space for Partial Backup.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Increase maxSplitParts to accommodate previously backed up parts.
|
||||
maxSplitParts += currPartIdx;
|
||||
}
|
||||
else if (isSmallSdCard)
|
||||
gfx_printf("%kPartial Backup enabled (with %d MiB parts)...%k\n\n", 0xFFFFBA00, multipartSplitSize >> 20, 0xFFCCCCCC);
|
||||
|
||||
// Check if filesystem is FAT32 or the free space is smaller and backup in parts.
|
||||
if (((sd_fs.fs_type != FS_EXFAT) && totalSectors > (FAT32_FILESIZE_LIMIT / NX_EMMC_BLOCKSIZE)) || isSmallSdCard)
|
||||
{
|
||||
u32 multipartSplitSectors = multipartSplitSize / NX_EMMC_BLOCKSIZE;
|
||||
numSplitParts = (totalSectors + multipartSplitSectors - 1) / multipartSplitSectors;
|
||||
|
||||
outFilename[sdPathLen++] = '.';
|
||||
|
||||
// Continue from where we left, if Partial Backup in progress.
|
||||
_update_filename(outFilename, sdPathLen, numSplitParts, partialDumpInProgress ? currPartIdx : 0);
|
||||
}
|
||||
|
||||
FIL fp;
|
||||
gfx_con_getpos(&gfx_con.savedx, &gfx_con.savedy);
|
||||
if (!f_open(&fp, outFilename, FA_READ))
|
||||
{
|
||||
f_close(&fp);
|
||||
gfx_con.fntsz = 16;
|
||||
|
||||
WPRINTF("An existing backup has been detected!");
|
||||
WPRINTF("Press POWER to Continue.\nPress VOL to go to the menu.\n");
|
||||
msleep(500);
|
||||
|
||||
if (!(btn_wait() & BTN_POWER))
|
||||
return 0;
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_clear_partial_grey(0x1B, gfx_con.savedy, 48);
|
||||
}
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("Filename: %s\n\n", outFilename);
|
||||
res = f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (res)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("Error (%d) creating file %s.\n", res, outFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 *buf = (u8 *)MIXD_BUF_ALIGNED;
|
||||
|
||||
u32 lba_curr = part->lba_start;
|
||||
u32 lbaStartPart = part->lba_start;
|
||||
u32 bytesWritten = 0;
|
||||
u32 prevPct = 200;
|
||||
int retryCount = 0;
|
||||
|
||||
// Continue from where we left, if Partial Backup in progress.
|
||||
if (partialDumpInProgress)
|
||||
{
|
||||
lba_curr += currPartIdx * (multipartSplitSize / NX_EMMC_BLOCKSIZE);
|
||||
totalSectors -= currPartIdx * (multipartSplitSize / NX_EMMC_BLOCKSIZE);
|
||||
lbaStartPart = lba_curr; // Update the start LBA for verification.
|
||||
}
|
||||
u64 totalSize = (u64)((u64)totalSectors << 9);
|
||||
if (!isSmallSdCard && (sd_fs.fs_type == FS_EXFAT || totalSize <= FAT32_FILESIZE_LIMIT))
|
||||
f_lseek(&fp, totalSize);
|
||||
else
|
||||
f_lseek(&fp, MIN(totalSize, multipartSplitSize));
|
||||
f_lseek(&fp, 0);
|
||||
|
||||
u32 num = 0;
|
||||
u32 pct = 0;
|
||||
while (totalSectors > 0)
|
||||
{
|
||||
if (numSplitParts != 0 && bytesWritten >= multipartSplitSize)
|
||||
{
|
||||
f_close(&fp);
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
currPartIdx++;
|
||||
|
||||
// Verify part.
|
||||
if (_dump_emmc_verify(storage, lbaStartPart, outFilename, part))
|
||||
{
|
||||
EPRINTF("\nPress any key and try again...\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_update_filename(outFilename, sdPathLen, numSplitParts, currPartIdx);
|
||||
|
||||
// Always create partial.idx before next part, in case a fatal error occurs.
|
||||
if (isSmallSdCard)
|
||||
{
|
||||
// Create partial backup index file.
|
||||
if (f_open(&partialIdxFp, partialIdxFilename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
|
||||
{
|
||||
f_write(&partialIdxFp, &currPartIdx, 4, NULL);
|
||||
f_close(&partialIdxFp);
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTF("\nError creating partial.idx file.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// More parts to backup that do not currently fit the sd card free space or fatal error.
|
||||
if (currPartIdx >= maxSplitParts)
|
||||
{
|
||||
gfx_puts("\n\n1. Press any key to unmount SD Card.\n\
|
||||
2. Remove SD Card and move files to free space.\n\
|
||||
Don\'t move the partial.idx file!\n\
|
||||
3. Re-insert SD Card.\n\
|
||||
4. Select the SAME option again to continue.\n");
|
||||
gfx_con.fntsz = 16;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Create next part.
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("Filename: %s\n\n", outFilename);
|
||||
lbaStartPart = lba_curr;
|
||||
res = f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (res)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("Error (%d) creating file %s.\n", res, outFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytesWritten = 0;
|
||||
|
||||
totalSize = (u64)((u64)totalSectors << 9);
|
||||
f_lseek(&fp, MIN(totalSize, multipartSplitSize));
|
||||
f_lseek(&fp, 0);
|
||||
}
|
||||
|
||||
retryCount = 0;
|
||||
num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
|
||||
while (!sdmmc_storage_read(storage, lba_curr, num, buf))
|
||||
{
|
||||
EPRINTFARGS("Error reading %d blocks @ LBA %08X,\nfrom eMMC (try %d), retrying...",
|
||||
num, lba_curr, ++retryCount);
|
||||
|
||||
msleep(150);
|
||||
if (retryCount >= 3)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X\nfrom eMMC. Aborting..\n",
|
||||
num, lba_curr);
|
||||
EPRINTF("\nPress any key and try again...\n");
|
||||
|
||||
f_close(&fp);
|
||||
f_unlink(outFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
res = f_write(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL);
|
||||
if (res)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nFatal error (%d) when writing to SD Card", res);
|
||||
EPRINTF("\nPress any key and try again...\n");
|
||||
|
||||
f_close(&fp);
|
||||
f_unlink(outFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start);
|
||||
if (pct != prevPct)
|
||||
{
|
||||
tui_pbar(0, gfx_con.y, pct, 0xFFCCCCCC, 0xFF555555);
|
||||
prevPct = pct;
|
||||
}
|
||||
|
||||
lba_curr += num;
|
||||
totalSectors -= num;
|
||||
bytesWritten += num * NX_EMMC_BLOCKSIZE;
|
||||
|
||||
// Force a flush after a lot of data if not splitting.
|
||||
if (numSplitParts == 0 && bytesWritten >= multipartSplitSize)
|
||||
{
|
||||
f_sync(&fp);
|
||||
bytesWritten = 0;
|
||||
}
|
||||
|
||||
btn = btn_wait_timeout(0, BTN_VOL_DOWN | BTN_VOL_UP);
|
||||
if ((btn & BTN_VOL_DOWN) && (btn & BTN_VOL_UP))
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
WPRINTF("\n\nThe backup was cancelled!");
|
||||
EPRINTF("\nPress any key...\n");
|
||||
msleep(1500);
|
||||
|
||||
f_close(&fp);
|
||||
f_unlink(outFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
tui_pbar(0, gfx_con.y, 100, 0xFFCCCCCC, 0xFF555555);
|
||||
|
||||
// Backup operation ended successfully.
|
||||
f_close(&fp);
|
||||
|
||||
// Verify last part or single file backup.
|
||||
if (_dump_emmc_verify(storage, lbaStartPart, outFilename, part))
|
||||
{
|
||||
EPRINTF("\nPress any key and try again...\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
tui_pbar(0, gfx_con.y, 100, 0xFF96FF00, 0xFF155500);
|
||||
|
||||
gfx_con.fntsz = 16;
|
||||
// Remove partial backup index file if no fatal errors occurred.
|
||||
if (isSmallSdCard)
|
||||
{
|
||||
f_unlink(partialIdxFilename);
|
||||
gfx_printf("%k\n\nYou can now join the files\nand get the complete eMMC RAW GPP backup.", 0xFFCCCCCC);
|
||||
}
|
||||
gfx_puts("\n\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PART_BOOT = (1 << 0),
|
||||
PART_SYSTEM = (1 << 1),
|
||||
PART_USER = (1 << 2),
|
||||
PART_RAW = (1 << 3),
|
||||
PART_GP_ALL = (1 << 7)
|
||||
} emmcPartType_t;
|
||||
|
||||
static void _dump_emmc_selected(emmcPartType_t dumpType)
|
||||
{
|
||||
int res = 0;
|
||||
u32 timer = 0;
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
tui_sbar(true);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
goto out;
|
||||
|
||||
gfx_puts("Checking for available free space...\n\n");
|
||||
// Get SD Card free space for Partial Backup.
|
||||
f_getfree("", &sd_fs.free_clst, NULL);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
char sdPath[OUT_FILENAME_SZ];
|
||||
// Create Restore folders, if they do not exist.
|
||||
emmcsn_path_impl(sdPath, "/restore", "", &storage);
|
||||
emmcsn_path_impl(sdPath, "/restore/partitions", "", &storage);
|
||||
|
||||
timer = get_tmr_s();
|
||||
if (dumpType & PART_BOOT)
|
||||
{
|
||||
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
|
||||
|
||||
emmc_part_t bootPart;
|
||||
memset(&bootPart, 0, sizeof(bootPart));
|
||||
bootPart.lba_start = 0;
|
||||
bootPart.lba_end = (BOOT_PART_SIZE / NX_EMMC_BLOCKSIZE) - 1;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
strcpy(bootPart.name, "BOOT");
|
||||
bootPart.name[4] = (u8)('0' + i);
|
||||
bootPart.name[5] = 0;
|
||||
|
||||
gfx_printf("%k%02d: %s (%07X-%07X)%k\n", 0xFF00DDFF, i,
|
||||
bootPart.name, bootPart.lba_start, bootPart.lba_end, 0xFFCCCCCC);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, i + 1);
|
||||
|
||||
emmcsn_path_impl(sdPath, "", bootPart.name, &storage);
|
||||
res = _dump_emmc_part(sdPath, &storage, &bootPart);
|
||||
}
|
||||
}
|
||||
|
||||
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER) || (dumpType & PART_RAW))
|
||||
{
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER))
|
||||
{
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
if ((dumpType & PART_USER) == 0 && !strcmp(part->name, "USER"))
|
||||
continue;
|
||||
if ((dumpType & PART_SYSTEM) == 0 && strcmp(part->name, "USER"))
|
||||
continue;
|
||||
|
||||
gfx_printf("%k%02d: %s (%07X-%07X)%k\n", 0xFF00DDFF, i++,
|
||||
part->name, part->lba_start, part->lba_end, 0xFFCCCCCC);
|
||||
|
||||
emmcsn_path_impl(sdPath, "/partitions", part->name, &storage);
|
||||
res = _dump_emmc_part(sdPath, &storage, part);
|
||||
// If a part failed, don't continue.
|
||||
if (!res)
|
||||
break;
|
||||
}
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
}
|
||||
|
||||
if (dumpType & PART_RAW)
|
||||
{
|
||||
// Get GP partition size dynamically.
|
||||
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
|
||||
|
||||
emmc_part_t rawPart;
|
||||
memset(&rawPart, 0, sizeof(rawPart));
|
||||
rawPart.lba_start = 0;
|
||||
rawPart.lba_end = RAW_AREA_NUM_SECTORS - 1;
|
||||
strcpy(rawPart.name, "rawnand.bin");
|
||||
{
|
||||
gfx_printf("%k%02d: %s (%07X-%07X)%k\n", 0xFF00DDFF, i++,
|
||||
rawPart.name, rawPart.lba_start, rawPart.lba_end, 0xFFCCCCCC);
|
||||
|
||||
emmcsn_path_impl(sdPath, "", rawPart.name, &storage);
|
||||
res = _dump_emmc_part(sdPath, &storage, &rawPart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfx_putc('\n');
|
||||
timer = get_tmr_s() - timer;
|
||||
gfx_printf("Time taken: %dm %ds.\n", timer / 60, timer % 60);
|
||||
sdmmc_storage_end(&storage);
|
||||
if (res)
|
||||
gfx_printf("\n%kFinished and verified!%k\nPress any key...\n", 0xFF96FF00, 0xFFCCCCCC);
|
||||
|
||||
out:
|
||||
sd_unmount();
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void dump_emmc_system() { _dump_emmc_selected(PART_SYSTEM); }
|
||||
void dump_emmc_user() { _dump_emmc_selected(PART_USER); }
|
||||
void dump_emmc_boot() { _dump_emmc_selected(PART_BOOT); }
|
||||
void dump_emmc_rawnand() { _dump_emmc_selected(PART_RAW); }
|
||||
|
||||
static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part, bool allow_multi_part)
|
||||
{
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
u32 totalSectors = part->lba_end - part->lba_start + 1;
|
||||
u32 currPartIdx = 0;
|
||||
u32 numSplitParts = 0;
|
||||
u32 lbaStartPart = part->lba_start;
|
||||
int res = 0;
|
||||
char *outFilename = sd_path;
|
||||
u32 sdPathLen = strlen(sd_path);
|
||||
u64 fileSize = 0;
|
||||
u64 totalCheckFileSize = 0;
|
||||
gfx_con.fntsz = 8;
|
||||
|
||||
FIL fp;
|
||||
FILINFO fno;
|
||||
|
||||
gfx_con_getpos(&gfx_con.savedx, &gfx_con.savedy);
|
||||
|
||||
bool use_multipart = false;
|
||||
|
||||
if (allow_multi_part)
|
||||
{
|
||||
// Check to see if there is a combined file and if so then use that.
|
||||
if (f_stat(outFilename, &fno))
|
||||
{
|
||||
// If not, check if there are partial files and the total size matches.
|
||||
gfx_printf("No single file, checking for part files...\n");
|
||||
|
||||
outFilename[sdPathLen++] = '.';
|
||||
|
||||
// Stat total size of the part files.
|
||||
while ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
|
||||
{
|
||||
_update_filename(outFilename, sdPathLen, 99, numSplitParts);
|
||||
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("\nFilename: %s\n", outFilename);
|
||||
|
||||
if (f_stat(outFilename, &fno))
|
||||
{
|
||||
WPRINTFARGS("Error (%d) file not found '%s'. Aborting...\n", res, outFilename);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
totalCheckFileSize += (u64)fno.fsize;
|
||||
|
||||
numSplitParts++;
|
||||
}
|
||||
|
||||
gfx_printf("\n%X sectors total.\n", (u32)((u64)totalCheckFileSize >> (u64)9));
|
||||
|
||||
if ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTF("Size of SD Card split backups does not match,\neMMC's selected part size.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
use_multipart = true;
|
||||
_update_filename(outFilename, sdPathLen, numSplitParts, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res = f_open(&fp, outFilename, FA_READ);
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("\nFilename: %s\n", outFilename);
|
||||
if (res)
|
||||
{
|
||||
if (res != FR_NO_FILE)
|
||||
EPRINTFARGS("Error (%d) while opening backup. Continuing...\n", res);
|
||||
else
|
||||
WPRINTFARGS("Error (%d) file not found. Continuing...\n", res);
|
||||
gfx_con.fntsz = 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (!use_multipart && (((u32)((u64)f_size(&fp) >> (u64)9)) != totalSectors)) // Check total restore size vs emmc size.
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTF("Size of the SD Card backup does not match,\neMMC's selected part size.\n");
|
||||
f_close(&fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileSize = (u64)f_size(&fp);
|
||||
gfx_printf("\nTotal restore size: %d MiB.\n\n",
|
||||
(u32)((use_multipart ? (u64)totalCheckFileSize : fileSize) >> (u64)9) >> SECTORS_TO_MIB_COEFF);
|
||||
}
|
||||
|
||||
u8 *buf = (u8 *)MIXD_BUF_ALIGNED;
|
||||
|
||||
u32 lba_curr = part->lba_start;
|
||||
u32 bytesWritten = 0;
|
||||
u32 prevPct = 200;
|
||||
int retryCount = 0;
|
||||
|
||||
u32 num = 0;
|
||||
u32 pct = 0;
|
||||
|
||||
gfx_con_getpos(&gfx_con.savedx, &gfx_con.savedy);
|
||||
|
||||
while (totalSectors > 0)
|
||||
{
|
||||
// If we have more than one part, check the size for the split parts and make sure that the bytes written is not more than that.
|
||||
if (numSplitParts != 0 && bytesWritten >= fileSize)
|
||||
{
|
||||
// If we have more bytes written then close the file pointer and increase the part index we are using
|
||||
f_close(&fp);
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
currPartIdx++;
|
||||
|
||||
// Verify part.
|
||||
if (_dump_emmc_verify(storage, lbaStartPart, outFilename, part))
|
||||
{
|
||||
EPRINTF("\nPress any key and try again...\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_update_filename(outFilename, sdPathLen, numSplitParts, currPartIdx);
|
||||
|
||||
// Read from next part.
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("Filename: %s\n\n", outFilename);
|
||||
|
||||
lbaStartPart = lba_curr;
|
||||
|
||||
// Try to open the next file part
|
||||
res = f_open(&fp, outFilename, FA_READ);
|
||||
if (res)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("Error (%d) opening file %s.\n", res, outFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
fileSize = (u64)f_size(&fp);
|
||||
bytesWritten = 0;
|
||||
}
|
||||
|
||||
retryCount = 0;
|
||||
num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
|
||||
|
||||
res = f_read(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL);
|
||||
if (res)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nFatal error (%d) when reading from SD Card", res);
|
||||
EPRINTF("\nYour device may be in an inoperative state!\n\nPress any key and try again now...\n");
|
||||
|
||||
f_close(&fp);
|
||||
return 0;
|
||||
}
|
||||
while (!sdmmc_storage_write(storage, lba_curr, num, buf))
|
||||
{
|
||||
EPRINTFARGS("Error writing %d blocks @ LBA %08X\nto eMMC (try %d), retrying...",
|
||||
num, lba_curr, ++retryCount);
|
||||
|
||||
msleep(150);
|
||||
if (retryCount >= 3)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nFailed to write %d blocks @ LBA %08X\nfrom eMMC. Aborting..\n",
|
||||
num, lba_curr);
|
||||
EPRINTF("\nYour device may be in an inoperative state!\n\nPress any key and try again...\n");
|
||||
|
||||
f_close(&fp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start);
|
||||
if (pct != prevPct)
|
||||
{
|
||||
tui_pbar(0, gfx_con.y, pct, 0xFFCCCCCC, 0xFF555555);
|
||||
prevPct = pct;
|
||||
}
|
||||
|
||||
lba_curr += num;
|
||||
totalSectors -= num;
|
||||
bytesWritten += num * NX_EMMC_BLOCKSIZE;
|
||||
}
|
||||
tui_pbar(0, gfx_con.y, 100, 0xFFCCCCCC, 0xFF555555);
|
||||
|
||||
// Restore operation ended successfully.
|
||||
f_close(&fp);
|
||||
|
||||
// Verify restored data.
|
||||
if (_dump_emmc_verify(storage, lbaStartPart, outFilename, part))
|
||||
{
|
||||
EPRINTF("\nPress any key and try again...\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
tui_pbar(0, gfx_con.y, 100, 0xFF96FF00, 0xFF155500);
|
||||
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_puts("\n\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _restore_emmc_selected(emmcPartType_t restoreType)
|
||||
{
|
||||
int res = 0;
|
||||
u32 timer = 0;
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
tui_sbar(true);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
gfx_printf("%kThis may render your device inoperative!\n\n", 0xFFFFDD00);
|
||||
gfx_printf("Are you really sure?\n\n%k", 0xFFCCCCCC);
|
||||
if ((restoreType & PART_BOOT) || (restoreType & PART_GP_ALL))
|
||||
{
|
||||
gfx_puts("The mode you selected will only restore\nthe ");
|
||||
if (restoreType & PART_BOOT)
|
||||
gfx_puts("boot ");
|
||||
gfx_puts("partitions that it can find.\n");
|
||||
gfx_puts("If it is not found, it will be skipped\nand continue with the next.\n\n");
|
||||
}
|
||||
gfx_con_getpos(&gfx_con.savedx, &gfx_con.savedy);
|
||||
|
||||
u8 failsafe_wait = 10;
|
||||
while (failsafe_wait > 0)
|
||||
{
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("%kWait... (%ds) %k", 0xFF888888, failsafe_wait, 0xFFCCCCCC);
|
||||
msleep(1000);
|
||||
failsafe_wait--;
|
||||
}
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
|
||||
gfx_puts("Press POWER to Continue.\nPress VOL to go to the menu.\n\n\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (!(btn & BTN_POWER))
|
||||
goto out;
|
||||
|
||||
if (!sd_mount())
|
||||
goto out;
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
char sdPath[OUT_FILENAME_SZ];
|
||||
|
||||
timer = get_tmr_s();
|
||||
if (restoreType & PART_BOOT)
|
||||
{
|
||||
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
|
||||
|
||||
emmc_part_t bootPart;
|
||||
memset(&bootPart, 0, sizeof(bootPart));
|
||||
bootPart.lba_start = 0;
|
||||
bootPart.lba_end = (BOOT_PART_SIZE / NX_EMMC_BLOCKSIZE) - 1;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
strcpy(bootPart.name, "BOOT");
|
||||
bootPart.name[4] = (u8)('0' + i);
|
||||
bootPart.name[5] = 0;
|
||||
|
||||
gfx_printf("%k%02d: %s (%07X-%07X)%k\n", 0xFF00DDFF, i,
|
||||
bootPart.name, bootPart.lba_start, bootPart.lba_end, 0xFFCCCCCC);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, i + 1);
|
||||
|
||||
emmcsn_path_impl(sdPath, "/restore", bootPart.name, &storage);
|
||||
res = _restore_emmc_part(sdPath, &storage, &bootPart, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (restoreType & PART_GP_ALL)
|
||||
{
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
gfx_printf("%k%02d: %s (%07X-%07X)%k\n", 0xFF00DDFF, i++,
|
||||
part->name, part->lba_start, part->lba_end, 0xFFCCCCCC);
|
||||
|
||||
emmcsn_path_impl(sdPath, "/restore/partitions/", part->name, &storage);
|
||||
res = _restore_emmc_part(sdPath, &storage, part, false);
|
||||
}
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
}
|
||||
|
||||
if (restoreType & PART_RAW)
|
||||
{
|
||||
// Get GP partition size dynamically.
|
||||
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
|
||||
|
||||
emmc_part_t rawPart;
|
||||
memset(&rawPart, 0, sizeof(rawPart));
|
||||
rawPart.lba_start = 0;
|
||||
rawPart.lba_end = RAW_AREA_NUM_SECTORS - 1;
|
||||
strcpy(rawPart.name, "rawnand.bin");
|
||||
{
|
||||
gfx_printf("%k%02d: %s (%07X-%07X)%k\n", 0xFF00DDFF, i++,
|
||||
rawPart.name, rawPart.lba_start, rawPart.lba_end, 0xFFCCCCCC);
|
||||
|
||||
emmcsn_path_impl(sdPath, "/restore", rawPart.name, &storage);
|
||||
res = _restore_emmc_part(sdPath, &storage, &rawPart, true);
|
||||
}
|
||||
}
|
||||
|
||||
gfx_putc('\n');
|
||||
timer = get_tmr_s() - timer;
|
||||
gfx_printf("Time taken: %dm %ds.\n", timer / 60, timer % 60);
|
||||
sdmmc_storage_end(&storage);
|
||||
if (res)
|
||||
gfx_printf("\n%kFinished and verified!%k\nPress any key...\n", 0xFF96FF00, 0xFFCCCCCC);
|
||||
|
||||
out:
|
||||
sd_unmount();
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void restore_emmc_boot() { _restore_emmc_selected(PART_BOOT); }
|
||||
void restore_emmc_rawnand() { _restore_emmc_selected(PART_RAW); }
|
||||
void restore_emmc_gpp_parts() { _restore_emmc_selected(PART_GP_ALL); }
|
||||
|
||||
#pragma GCC pop_options
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Rajko Stojadinovic
|
||||
* 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 _FE_EMMC_TOOLS_H_
|
||||
#define _FE_EMMC_TOOLS_H_
|
||||
|
||||
void dump_emmc_system();
|
||||
void dump_emmc_user();
|
||||
void dump_emmc_boot();
|
||||
void dump_emmc_rawnand();
|
||||
|
||||
void restore_emmc_boot();
|
||||
void restore_emmc_rawnand();
|
||||
void restore_emmc_gpp_parts();
|
||||
|
||||
#endif
|
||||
@@ -1,655 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 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 "fe_info.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../hos/hos.h"
|
||||
#include "../hos/pkg1.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../power/bq24193.h"
|
||||
#include "../power/max17050.h"
|
||||
#include "../sec/tsec.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../soc/kfuse.h"
|
||||
#include "../soc/smmu.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/mmc.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
void print_fuseinfo()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 burntFuses = 0;
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
{
|
||||
if ((fuse_read_odm(7) >> i) & 1)
|
||||
burntFuses++;
|
||||
}
|
||||
|
||||
gfx_printf("\nSKU: %X - ", FUSE(FUSE_SKU_INFO));
|
||||
switch (fuse_read_odm(4) & 3)
|
||||
{
|
||||
case 0:
|
||||
gfx_printf("Retail\n");
|
||||
break;
|
||||
case 3:
|
||||
gfx_printf("Dev\n");
|
||||
break;
|
||||
}
|
||||
gfx_printf("Sdram ID: %d\n", (fuse_read_odm(4) >> 3) & 0x1F);
|
||||
gfx_printf("Burnt fuses: %d / 64\n", burntFuses);
|
||||
gfx_printf("Secure key: %08X%08X%08X%08X\n\n\n",
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY0)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY1)),
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY2)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY3)));
|
||||
|
||||
gfx_printf("%k(Unlocked) fuse cache:\n\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_hexdump(0x7000F900, (u8 *)0x7000F900, 0x300);
|
||||
|
||||
gfx_puts("\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (sd_mount())
|
||||
{
|
||||
char path[64];
|
||||
emmcsn_path_impl(path, "/dumps", "fuse_cached.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)0x7000F900, 0x300, path))
|
||||
gfx_puts("\nfuse_cached.bin saved!\n");
|
||||
|
||||
u32 words[192];
|
||||
fuse_read_array(words);
|
||||
emmcsn_path_impl(path, "/dumps", "fuse_array_raw.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)words, sizeof(words), path))
|
||||
gfx_puts("\nfuse_array_raw.bin saved!\n");
|
||||
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
}
|
||||
|
||||
void print_kfuseinfo()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
gfx_printf("%kKFuse contents:\n\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
u32 buf[KFUSE_NUM_WORDS];
|
||||
if (!kfuse_read(buf))
|
||||
EPRINTF("CRC fail.");
|
||||
else
|
||||
gfx_hexdump(0, (u8 *)buf, KFUSE_NUM_WORDS * 4);
|
||||
|
||||
gfx_puts("\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (sd_mount())
|
||||
{
|
||||
char path[64];
|
||||
emmcsn_path_impl(path, "/dumps", "kfuses.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)buf, KFUSE_NUM_WORDS * 4, path))
|
||||
gfx_puts("\nDone!\n");
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
}
|
||||
|
||||
void print_mmc_info()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 card_type;
|
||||
u32 speed = 0;
|
||||
|
||||
gfx_printf("%kCID:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
switch (storage.csd.mmca_vsn)
|
||||
{
|
||||
case 2: /* MMC v2.0 - v2.2 */
|
||||
case 3: /* MMC v3.1 - v3.3 */
|
||||
case 4: /* MMC v4 */
|
||||
gfx_printf(
|
||||
" Vendor ID: %X\n"
|
||||
" Card/BGA: %X\n"
|
||||
" OEM ID: %02X\n"
|
||||
" Model: %c%c%c%c%c%c\n"
|
||||
" Prd Rev: %X\n"
|
||||
" S/N: %04X\n"
|
||||
" Month/Year: %02d/%04d\n\n",
|
||||
storage.cid.manfid, storage.cid.card_bga, storage.cid.oemid,
|
||||
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2],
|
||||
storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5],
|
||||
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (storage.csd.structure == 0)
|
||||
EPRINTF("Unknown CSD structure.");
|
||||
else
|
||||
{
|
||||
gfx_printf("%kExtended CSD V1.%d:%k\n",
|
||||
0xFF00DDFF, storage.ext_csd.ext_struct, 0xFFCCCCCC);
|
||||
card_type = storage.ext_csd.card_type;
|
||||
char card_type_support[96];
|
||||
card_type_support[0] = 0;
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
|
||||
{
|
||||
strcat(card_type_support, "HS26");
|
||||
speed = (26 << 16) | 26;
|
||||
}
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_52)
|
||||
{
|
||||
strcat(card_type_support, ", HS52");
|
||||
speed = (52 << 16) | 52;
|
||||
}
|
||||
if (card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
|
||||
{
|
||||
strcat(card_type_support, ", DDR52_1.8V");
|
||||
speed = (52 << 16) | 104;
|
||||
}
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
|
||||
{
|
||||
strcat(card_type_support, ", HS200_1.8V");
|
||||
speed = (200 << 16) | 200;
|
||||
}
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)
|
||||
{
|
||||
strcat(card_type_support, ", HS400_1.8V");
|
||||
speed = (200 << 16) | 400;
|
||||
}
|
||||
|
||||
gfx_printf(
|
||||
" Spec Version: %02X\n"
|
||||
" Extended Rev: 1.%d\n"
|
||||
" Dev Version: %d\n"
|
||||
" Cmd Classes: %02X\n"
|
||||
" Capacity: %s\n"
|
||||
" Max Rate: %d MB/s (%d MHz)\n"
|
||||
" Current Rate: %d MB/s\n"
|
||||
" Type Support: ",
|
||||
storage.csd.mmca_vsn, storage.ext_csd.rev, storage.ext_csd.dev_version, storage.csd.cmdclass,
|
||||
storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
storage.csd.busspeed);
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_printf("%s", card_type_support);
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_printf("\n\n", card_type_support);
|
||||
|
||||
u32 boot_size = storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
|
||||
gfx_printf("%keMMC Partitions:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_printf(" 1: %kBOOT0 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF96FF00, 0xFFCCCCCC,
|
||||
boot_size / 1024, boot_size / 512);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf(" 2: %kBOOT1 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF96FF00, 0xFFCCCCCC,
|
||||
boot_size / 1024, boot_size / 512);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf(" 3: %kRPMB %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF96FF00, 0xFFCCCCCC,
|
||||
rpmb_size / 1024, rpmb_size / 512);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf(" 0: %kGPP (USER) %k\n Size: %5d MiB (LBA Sectors: 0x%07X)\n\n", 0xFF96FF00, 0xFFCCCCCC,
|
||||
storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf("%kGPP (eMMC USER) partition table:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
int gpp_idx = 0;
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
gfx_printf(" %02d: %k%s%k\n Size: % 5d MiB (LBA Sectors 0x%07X)\n LBA Range: %08X-%08X\n",
|
||||
gpp_idx++, 0xFFAEFD14, part->name, 0xFFCCCCCC, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
||||
part->lba_end - part->lba_start + 1, part->lba_start, part->lba_end);
|
||||
gfx_put_small_sep();
|
||||
}
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void print_sdcard_info()
|
||||
{
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (sd_mount())
|
||||
{
|
||||
gfx_printf("%kCard IDentification:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_printf(
|
||||
" Vendor ID: %02x\n"
|
||||
" OEM ID: %c%c\n"
|
||||
" Model: %c%c%c%c%c\n"
|
||||
" HW rev: %X\n"
|
||||
" FW rev: %X\n"
|
||||
" S/N: %08x\n"
|
||||
" Month/Year: %02d/%04d\n\n",
|
||||
sd_storage.cid.manfid, (sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF,
|
||||
sd_storage.cid.prod_name[0], sd_storage.cid.prod_name[1], sd_storage.cid.prod_name[2],
|
||||
sd_storage.cid.prod_name[3], sd_storage.cid.prod_name[4],
|
||||
sd_storage.cid.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
|
||||
sd_storage.cid.month, sd_storage.cid.year);
|
||||
|
||||
gfx_printf("%kCard-Specific Data V%d.0:%k\n", 0xFF00DDFF, sd_storage.csd.structure + 1, 0xFFCCCCCC);
|
||||
gfx_printf(
|
||||
" Cmd Classes: %02X\n"
|
||||
" Capacity: %d MiB\n"
|
||||
" Bus Width: %d\n"
|
||||
" Current Rate: %d MB/s (%d MHz)\n"
|
||||
" Speed Class: %d\n"
|
||||
" UHS Grade: U%d\n"
|
||||
" Video Class: V%d\n"
|
||||
" App perf class: A%d\n"
|
||||
" Write Protect: %d\n\n",
|
||||
sd_storage.csd.cmdclass, sd_storage.sec_cnt >> 11,
|
||||
sd_storage.ssr.bus_width, sd_storage.csd.busspeed, sd_storage.csd.busspeed * 2,
|
||||
sd_storage.ssr.speed_class, sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class,
|
||||
sd_storage.ssr.app_class, sd_storage.csd.write_protect);
|
||||
|
||||
gfx_puts("Acquiring FAT volume info...\n\n");
|
||||
f_getfree("", &sd_fs.free_clst, NULL);
|
||||
gfx_printf("%kFound %s volume:%k\n Free: %d MiB\n Cluster: %d KiB\n",
|
||||
0xFF00DDFF, sd_fs.fs_type == FS_EXFAT ? "exFAT" : "FAT32", 0xFFCCCCCC,
|
||||
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF, (sd_fs.csize > 1) ? (sd_fs.csize >> 1) : 512);
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void print_tsec_key()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 retries = 0;
|
||||
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
// Read package1.
|
||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTF("Unknown pkg1 version.");
|
||||
goto out_wait;
|
||||
}
|
||||
|
||||
u8 keys[0x10 * 2];
|
||||
memset(keys, 0x00, 0x20);
|
||||
|
||||
tsec_ctxt.fw = (u8 *)pkg1 + pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = pkg1;
|
||||
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = pkg1_id->secmon_base;
|
||||
|
||||
if (pkg1_id->kb <= KB_FIRMWARE_VERSION_600)
|
||||
tsec_ctxt.size = 0xF00;
|
||||
else if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
tsec_ctxt.size = 0x2900;
|
||||
else if (pkg1_id->kb == KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
tsec_ctxt.size = 0x3000;
|
||||
// Exit after TSEC key generation.
|
||||
*((vu16 *)((u32)tsec_ctxt.fw + 0x2DB5)) = 0x02F8;
|
||||
}
|
||||
else
|
||||
tsec_ctxt.size = 0x3300;
|
||||
|
||||
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
u8 *tsec_paged = (u8 *)page_alloc(3);
|
||||
memcpy(tsec_paged, (void *)tsec_ctxt.fw, tsec_ctxt.size);
|
||||
tsec_ctxt.fw = tsec_paged;
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
|
||||
while (tsec_query(keys, pkg1_id->kb, &tsec_ctxt) < 0)
|
||||
{
|
||||
memset(keys, 0x00, 0x20);
|
||||
|
||||
retries++;
|
||||
|
||||
if (retries > 3)
|
||||
{
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gfx_printf("%kTSEC key: %k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
if (res >= 0)
|
||||
{
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
gfx_printf("%02X", keys[j]);
|
||||
|
||||
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
gfx_printf("\n%kTSEC root: %k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
gfx_printf("%02X", keys[0x10 + j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
EPRINTFARGS("ERROR %X\n", res);
|
||||
|
||||
gfx_puts("\n\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (sd_mount())
|
||||
{
|
||||
char path[64];
|
||||
emmcsn_path_impl(path, "/dumps", "tsec_keys.bin", NULL);
|
||||
if (!sd_save_to_file(keys, 0x10 * 2, path))
|
||||
gfx_puts("\nDone!\n");
|
||||
sd_unmount();
|
||||
}
|
||||
}
|
||||
else
|
||||
goto out;
|
||||
|
||||
out_wait:
|
||||
btn_wait();
|
||||
|
||||
out:
|
||||
free(pkg1);
|
||||
}
|
||||
|
||||
void print_fuel_gauge_info()
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
gfx_printf("%kFuel Gauge Info:\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
max17050_get_property(MAX17050_RepSOC, &value);
|
||||
gfx_printf("Capacity now: %3d%\n", value >> 8);
|
||||
|
||||
max17050_get_property(MAX17050_RepCap, &value);
|
||||
gfx_printf("Capacity now: %4d mAh\n", value);
|
||||
|
||||
max17050_get_property(MAX17050_FullCAP, &value);
|
||||
gfx_printf("Capacity full: %4d mAh\n", value);
|
||||
|
||||
max17050_get_property(MAX17050_DesignCap, &value);
|
||||
gfx_printf("Capacity (design): %4d mAh\n", value);
|
||||
|
||||
max17050_get_property(MAX17050_Current, &value);
|
||||
if (value >= 0)
|
||||
gfx_printf("Current now: %d mA\n", value / 1000);
|
||||
else
|
||||
gfx_printf("Current now: -%d mA\n", ~value / 1000);
|
||||
|
||||
max17050_get_property(MAX17050_AvgCurrent, &value);
|
||||
if (value >= 0)
|
||||
gfx_printf("Current average: %d mA\n", value / 1000);
|
||||
else
|
||||
gfx_printf("Current average: -%d mA\n", ~value / 1000);
|
||||
|
||||
max17050_get_property(MAX17050_VCELL, &value);
|
||||
gfx_printf("Voltage now: %4d mV\n", value);
|
||||
|
||||
max17050_get_property(MAX17050_OCVInternal, &value);
|
||||
gfx_printf("Voltage open-circuit: %4d mV\n", value);
|
||||
|
||||
max17050_get_property(MAX17050_MinVolt, &value);
|
||||
gfx_printf("Min voltage reached: %4d mV\n", value);
|
||||
|
||||
max17050_get_property(MAX17050_MaxVolt, &value);
|
||||
gfx_printf("Max voltage reached: %4d mV\n", value);
|
||||
|
||||
max17050_get_property(MAX17050_V_empty, &value);
|
||||
gfx_printf("Empty voltage (design): %4d mV\n", value);
|
||||
|
||||
max17050_get_property(MAX17050_TEMP, &value);
|
||||
if (value >= 0)
|
||||
gfx_printf("Battery temperature: %d.%d oC\n", value / 10, value % 10);
|
||||
else
|
||||
gfx_printf("Battery temperature: -%d.%d oC\n", ~value / 10, (~value) % 10);
|
||||
}
|
||||
|
||||
void print_battery_charger_info()
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
gfx_printf("%k\n\nBattery Charger Info:\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
bq24193_get_property(BQ24193_InputVoltageLimit, &value);
|
||||
gfx_printf("Input voltage limit: %4d mV\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_InputCurrentLimit, &value);
|
||||
gfx_printf("Input current limit: %4d mA\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_SystemMinimumVoltage, &value);
|
||||
gfx_printf("Min voltage limit: %4d mV\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_FastChargeCurrentLimit, &value);
|
||||
gfx_printf("Fast charge current limit: %4d mA\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_ChargeVoltageLimit, &value);
|
||||
gfx_printf("Charge voltage limit: %4d mV\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_ChargeStatus, &value);
|
||||
gfx_printf("Charge status: ");
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
gfx_printf("Not charging\n");
|
||||
break;
|
||||
case 1:
|
||||
gfx_printf("Pre-charging\n");
|
||||
break;
|
||||
case 2:
|
||||
gfx_printf("Fast charging\n");
|
||||
break;
|
||||
case 3:
|
||||
gfx_printf("Charge terminated\n");
|
||||
break;
|
||||
default:
|
||||
gfx_printf("Unknown (%d)\n", value);
|
||||
break;
|
||||
}
|
||||
bq24193_get_property(BQ24193_TempStatus, &value);
|
||||
gfx_printf("Temperature status: ");
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
gfx_printf("Normal\n");
|
||||
break;
|
||||
case 2:
|
||||
gfx_printf("Warm\n");
|
||||
break;
|
||||
case 3:
|
||||
gfx_printf("Cool\n");
|
||||
break;
|
||||
case 5:
|
||||
gfx_printf("Cold\n");
|
||||
break;
|
||||
case 6:
|
||||
gfx_printf("Hot\n");
|
||||
break;
|
||||
default:
|
||||
gfx_printf("Unknown (%d)\n", value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_battery_info()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
print_fuel_gauge_info();
|
||||
|
||||
print_battery_charger_info();
|
||||
|
||||
u8 *buf = (u8 *)malloc(0x100 * 2);
|
||||
|
||||
gfx_printf("%k\n\nBattery Fuel Gauge Registers:\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
for (int i = 0; i < 0x200; i += 2)
|
||||
{
|
||||
i2c_recv_buf_small(buf + i, 2, I2C_1, MAXIM17050_I2C_ADDR, i >> 1);
|
||||
usleep(2500);
|
||||
}
|
||||
|
||||
gfx_hexdump(0, (u8 *)buf, 0x200);
|
||||
|
||||
gfx_puts("\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (sd_mount())
|
||||
{
|
||||
char path[64];
|
||||
emmcsn_path_impl(path, "/dumps", "fuel_gauge.bin", NULL);
|
||||
if (sd_save_to_file((u8 *)buf, 0x200, path))
|
||||
EPRINTF("\nError creating fuel.bin file.");
|
||||
else
|
||||
gfx_puts("\nDone!\n");
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void _ipatch_process(u32 offset, u32 value)
|
||||
{
|
||||
gfx_printf("%8x %8x", BOOTROM_BASE + offset, value);
|
||||
u8 lo = value & 0xff;
|
||||
switch (value >> 8)
|
||||
{
|
||||
case 0x20:
|
||||
gfx_printf(" MOVS R0, #0x%02X", lo);
|
||||
break;
|
||||
case 0xDF:
|
||||
gfx_printf(" SVC #0x%02X", lo);
|
||||
break;
|
||||
}
|
||||
gfx_puts("\n");
|
||||
}
|
||||
|
||||
void bootrom_ipatches_info()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
static const u32 BOOTROM_SIZE = 0x18000;
|
||||
|
||||
u32 res = fuse_read_ipatch(_ipatch_process);
|
||||
if (res != 0)
|
||||
EPRINTFARGS("Failed to read ipatches. Error: %d", res);
|
||||
|
||||
gfx_puts("\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (sd_mount())
|
||||
{
|
||||
char path[64];
|
||||
u32 iram_evp_thunks[0x200];
|
||||
u32 iram_evp_thunks_len = sizeof(iram_evp_thunks);
|
||||
res = fuse_read_evp_thunk(iram_evp_thunks, &iram_evp_thunks_len);
|
||||
if (res == 0)
|
||||
{
|
||||
emmcsn_path_impl(path, "/dumps", "evp_thunks.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)iram_evp_thunks, iram_evp_thunks_len, path))
|
||||
gfx_puts("\nevp_thunks.bin saved!\n");
|
||||
}
|
||||
else
|
||||
EPRINTFARGS("Failed to read evp_thunks. Error: %d", res);
|
||||
|
||||
emmcsn_path_impl(path, "/dumps", "bootrom_patched.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)BOOTROM_BASE, BOOTROM_SIZE, path))
|
||||
gfx_puts("\nbootrom_patched.bin saved!\n");
|
||||
|
||||
u32 ipatch_backup[14];
|
||||
memcpy(ipatch_backup, (void *)IPATCH_BASE, sizeof(ipatch_backup));
|
||||
memset((void*)IPATCH_BASE, 0, sizeof(ipatch_backup));
|
||||
|
||||
emmcsn_path_impl(path, "/dumps", "bootrom_unpatched.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)BOOTROM_BASE, BOOTROM_SIZE, path))
|
||||
gfx_puts("\nbootrom_unpatched.bin saved!\n");
|
||||
|
||||
memcpy((void*)IPATCH_BASE, ipatch_backup, sizeof(ipatch_backup));
|
||||
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _FE_INFO_H_
|
||||
#define _FE_INFO_H_
|
||||
|
||||
void print_fuseinfo();
|
||||
void print_kfuseinfo();
|
||||
void print_mmc_info();
|
||||
void print_sdcard_info();
|
||||
void print_tsec_key();
|
||||
void print_fuel_gauge_info();
|
||||
void print_battery_charger_info();
|
||||
void print_battery_info();
|
||||
void bootrom_ipatches_info();
|
||||
|
||||
#endif
|
||||
@@ -1,609 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018 Reisyukaku
|
||||
*
|
||||
* 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 "fe_tools.h"
|
||||
#include "../config/config.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../gfx/tui.h"
|
||||
#include "../hos/hos.h"
|
||||
#include "../hos/pkg1.h"
|
||||
#include "../hos/pkg2.h"
|
||||
#include "../hos/sept.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../power/max7762x.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
extern boot_cfg_t b_cfg;
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
void dump_packages12()
|
||||
{
|
||||
if (!sd_mount())
|
||||
return;
|
||||
|
||||
char path[64];
|
||||
|
||||
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
|
||||
u8 *warmboot = (u8 *)calloc(1, 0x40000);
|
||||
u8 *secmon = (u8 *)calloc(1, 0x40000);
|
||||
u8 *loader = (u8 *)calloc(1, 0x40000);
|
||||
u8 *pkg2 = NULL;
|
||||
u8 kb = 0;
|
||||
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out_free;
|
||||
}
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTF("Unknown pkg1 version for reading\nTSEC firmware.");
|
||||
// Dump package1.
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &storage);
|
||||
if (sd_save_to_file(pkg1, 0x40000, path))
|
||||
goto out_free;
|
||||
gfx_puts("\nEnc pkg1 dumped to pkg1_enc.bin\n");
|
||||
|
||||
goto out_free;
|
||||
}
|
||||
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
|
||||
|
||||
kb = pkg1_id->kb;
|
||||
|
||||
if (!h_cfg.se_keygen_done)
|
||||
{
|
||||
tsec_ctxt.fw = (void *)pkg1 + pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = (void *)pkg1;
|
||||
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = pkg1_id->secmon_base;
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
|
||||
{
|
||||
b_cfg.autoboot = 0;
|
||||
b_cfg.autoboot_list = 0;
|
||||
|
||||
gfx_printf("sept will run to get the keys.\nThen rerun this option.");
|
||||
btn_wait();
|
||||
|
||||
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, kb, NULL))
|
||||
{
|
||||
gfx_printf("Failed to run sept\n");
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
// Read keyblob.
|
||||
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
|
||||
// Decrypt.
|
||||
hos_keygen(keyblob, kb, &tsec_ctxt, NULL);
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
h_cfg.se_keygen_done = 1;
|
||||
free(keyblob);
|
||||
}
|
||||
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
pkg1_decrypt(pkg1_id, pkg1);
|
||||
|
||||
if (kb <= KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1);
|
||||
|
||||
// Display info.
|
||||
gfx_printf("%kNX Bootloader size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->ldr_size);
|
||||
|
||||
gfx_printf("%kSecure monitor addr: %k0x%05X\n", 0xFFC7EA46, 0xFFCCCCCC, pkg1_id->secmon_base);
|
||||
gfx_printf("%kSecure monitor size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->sm_size);
|
||||
|
||||
gfx_printf("%kWarmboot addr: %k0x%05X\n", 0xFFC7EA46, 0xFFCCCCCC, pkg1_id->warmboot_base);
|
||||
gfx_printf("%kWarmboot size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->wb_size);
|
||||
|
||||
// Dump package1.1.
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &storage);
|
||||
if (sd_save_to_file(pkg1, 0x40000, path))
|
||||
goto out_free;
|
||||
gfx_puts("\npkg1 dumped to pkg1_decr.bin\n");
|
||||
|
||||
// Dump nxbootloader.
|
||||
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &storage);
|
||||
if (sd_save_to_file(loader, hdr->ldr_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("NX Bootloader dumped to nxloader.bin\n");
|
||||
|
||||
// Dump secmon.
|
||||
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &storage);
|
||||
if (sd_save_to_file(secmon, hdr->sm_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("Secure Monitor dumped to secmon.bin\n");
|
||||
|
||||
// Dump warmboot.
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &storage);
|
||||
if (sd_save_to_file(warmboot, hdr->wb_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("Warmboot dumped to warmboot.bin\n\n\n");
|
||||
}
|
||||
|
||||
// Dump package2.1.
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
// Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
// Find package2 partition.
|
||||
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
|
||||
if (!pkg2_part)
|
||||
goto out;
|
||||
|
||||
// Read in package2 header and get package2 real size.
|
||||
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
||||
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
|
||||
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
|
||||
free(tmp);
|
||||
// Read in package2.
|
||||
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
|
||||
pkg2 = malloc(pkg2_size_aligned);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
|
||||
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
|
||||
// Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb);
|
||||
if (!pkg2_hdr)
|
||||
{
|
||||
gfx_printf("Pkg2 decryption failed!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Display info.
|
||||
gfx_printf("%kKernel size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, pkg2_hdr->sec_size[PKG2_SEC_KERNEL]);
|
||||
gfx_printf("%kINI1 size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, pkg2_hdr->sec_size[PKG2_SEC_INI1]);
|
||||
|
||||
// Dump pkg2.1.
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &storage);
|
||||
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
|
||||
goto out;
|
||||
gfx_puts("\npkg2 dumped to pkg2_decr.bin\n");
|
||||
|
||||
// Dump kernel.
|
||||
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &storage);
|
||||
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
|
||||
goto out;
|
||||
gfx_puts("Kernel dumped to kernel.bin\n");
|
||||
|
||||
// Dump INI1.
|
||||
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &storage);
|
||||
u32 ini1_off = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||
u32 ini1_size = pkg2_hdr->sec_size[PKG2_SEC_INI1];
|
||||
if (!ini1_size)
|
||||
{
|
||||
pkg2_get_newkern_info(pkg2_hdr->data);
|
||||
ini1_off = pkg2_newkern_ini1_start;
|
||||
ini1_size = pkg2_newkern_ini1_end - pkg2_newkern_ini1_start;
|
||||
}
|
||||
if (ini1_off)
|
||||
{
|
||||
if (sd_save_to_file(pkg2_hdr->data + ini1_off, ini1_size, path))
|
||||
goto out;
|
||||
gfx_puts("INI1 dumped to ini1.bin\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx_puts("Failed to dump INI1!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
gfx_puts("\nDone. Press any key...\n");
|
||||
|
||||
out:
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
out_free:
|
||||
free(pkg1);
|
||||
free(secmon);
|
||||
free(warmboot);
|
||||
free(loader);
|
||||
free(pkg2);
|
||||
sdmmc_storage_end(&storage);
|
||||
sd_unmount();
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
se_aes_key_clear(8);
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void _toggle_autorcm(bool enable)
|
||||
{
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
u8 randomXor = 0;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
int i, sect = 0;
|
||||
u8 corr_mod_byte0;
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
corr_mod_byte0 = 0xF7;
|
||||
else
|
||||
corr_mod_byte0 = 0x37;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
||||
sdmmc_storage_read(&storage, sect, 1, tempbuf);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
do
|
||||
{
|
||||
randomXor = get_tmr_us() & 0xFF; // Bricmii style of bricking.
|
||||
} while (!randomXor); // Avoid the lottery.
|
||||
|
||||
tempbuf[0x10] ^= randomXor;
|
||||
}
|
||||
else
|
||||
tempbuf[0x10] = corr_mod_byte0;
|
||||
sdmmc_storage_write(&storage, sect, 1, tempbuf);
|
||||
}
|
||||
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
if (enable)
|
||||
gfx_printf("%kAutoRCM mode enabled!%k", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
else
|
||||
gfx_printf("%kAutoRCM mode disabled!%k", 0xFF96FF00, 0xFFCCCCCC);
|
||||
gfx_printf("\n\nPress any key...\n");
|
||||
|
||||
out:
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void _enable_autorcm() { _toggle_autorcm(true); }
|
||||
void _disable_autorcm() { _toggle_autorcm(false); }
|
||||
|
||||
void menu_autorcm()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (h_cfg.rcm_patched)
|
||||
{
|
||||
gfx_printf("%kThis device is RCM patched and\nAutoRCM function is disabled.\n\n"
|
||||
"In case %kAutoRCM%k is enabled\nthis will %kBRICK%k your device PERMANENTLY!!%k",
|
||||
0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFCCCCCC);
|
||||
btn_wait();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Do a simple check on the main BCT.
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
bool disabled = true;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
btn_wait();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
{
|
||||
if (tempbuf[0x10] != 0xF7)
|
||||
disabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tempbuf[0x10] != 0x37)
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
// Create AutoRCM menu.
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6);
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
ments[2].type = MENT_CAPTION;
|
||||
ments[3].type = MENT_CHGLINE;
|
||||
if (disabled)
|
||||
{
|
||||
ments[2].caption = "Status: Disabled!";
|
||||
ments[2].color = 0xFF96FF00;
|
||||
ments[4].caption = "Enable AutoRCM";
|
||||
ments[4].handler = _enable_autorcm;
|
||||
}
|
||||
else
|
||||
{
|
||||
ments[2].caption = "Status: Enabled!";
|
||||
ments[2].color = 0xFFFFBA00;
|
||||
ments[4].caption = "Disable AutoRCM";
|
||||
ments[4].handler = _disable_autorcm;
|
||||
}
|
||||
ments[4].type = MENT_HDLR_RE;
|
||||
ments[4].data = NULL;
|
||||
|
||||
memset(&ments[5], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "This corrupts your BOOT0!", 0, 0};
|
||||
|
||||
tui_do_menu(&menu);
|
||||
}
|
||||
|
||||
int _fix_attributes(char *path, u32 *total, u32 hos_folder, u32 check_first_run)
|
||||
{
|
||||
FRESULT res;
|
||||
DIR dir;
|
||||
u32 dirLength = 0;
|
||||
static FILINFO fno;
|
||||
|
||||
if (check_first_run)
|
||||
{
|
||||
// Read file attributes.
|
||||
res = f_stat(path, &fno);
|
||||
if (res != FR_OK)
|
||||
return res;
|
||||
|
||||
// Check if archive bit is set.
|
||||
if (fno.fattrib & AM_ARC)
|
||||
{
|
||||
*(u32 *)total = *(u32 *)total + 1;
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
}
|
||||
}
|
||||
|
||||
// Open directory.
|
||||
res = f_opendir(&dir, path);
|
||||
if (res != FR_OK)
|
||||
return res;
|
||||
|
||||
dirLength = strlen(path);
|
||||
for (;;)
|
||||
{
|
||||
// Clear file or folder path.
|
||||
path[dirLength] = 0;
|
||||
|
||||
// Read a directory item.
|
||||
res = f_readdir(&dir, &fno);
|
||||
|
||||
// Break on error or end of dir.
|
||||
if (res != FR_OK || fno.fname[0] == 0)
|
||||
break;
|
||||
|
||||
// Skip official Nintendo dir if started from root.
|
||||
if (!hos_folder && !strcmp(fno.fname, "Nintendo"))
|
||||
continue;
|
||||
|
||||
// Set new directory or file.
|
||||
memcpy(&path[dirLength], "/", 1);
|
||||
memcpy(&path[dirLength + 1], fno.fname, strlen(fno.fname) + 1);
|
||||
|
||||
// Check if archive bit is set.
|
||||
if (fno.fattrib & AM_ARC)
|
||||
{
|
||||
*total = *total + 1;
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
}
|
||||
|
||||
// Is it a directory?
|
||||
if (fno.fattrib & AM_DIR)
|
||||
{
|
||||
// Set archive bit to NCA folders.
|
||||
if (hos_folder && !strcmp(fno.fname + strlen(fno.fname) - 4, ".nca"))
|
||||
{
|
||||
*total = *total + 1;
|
||||
f_chmod(path, AM_ARC, AM_ARC);
|
||||
}
|
||||
|
||||
// Update status bar.
|
||||
tui_sbar(false);
|
||||
|
||||
// Enter the directory.
|
||||
res = _fix_attributes(path, total, hos_folder, 0);
|
||||
if (res != FR_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f_closedir(&dir);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void _fix_sd_attr(u32 type)
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
char path[256];
|
||||
char label[16];
|
||||
|
||||
u32 total = 0;
|
||||
if (sd_mount())
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
strcpy(path, "/");
|
||||
strcpy(label, "SD Card");
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
strcpy(path, "/Nintendo");
|
||||
strcpy(label, "Nintendo folder");
|
||||
break;
|
||||
}
|
||||
|
||||
gfx_printf("Traversing all %s files!\nThis may take some time...\n\n", label);
|
||||
_fix_attributes(path, &total, type, type);
|
||||
gfx_printf("%kTotal archive bits cleared: %d!%k\n\nDone! Press any key...", 0xFF96FF00, total, 0xFFCCCCCC);
|
||||
sd_unmount();
|
||||
}
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void fix_sd_all_attr() { _fix_sd_attr(0); }
|
||||
void fix_sd_nin_attr() { _fix_sd_attr(1); }
|
||||
|
||||
/* void fix_fuel_gauge_configuration()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
int battVoltage, avgCurrent;
|
||||
|
||||
max17050_get_property(MAX17050_VCELL, &battVoltage);
|
||||
max17050_get_property(MAX17050_AvgCurrent, &avgCurrent);
|
||||
|
||||
// Check if still charging. If not, check if battery is >= 95% (4.1V).
|
||||
if (avgCurrent < 0 && battVoltage > 4100)
|
||||
{
|
||||
if ((avgCurrent / 1000) < -10)
|
||||
EPRINTF("You need to be connected to a wall adapter,\nto apply this fix!");
|
||||
else
|
||||
{
|
||||
gfx_printf("%kAre you really sure?\nThis will reset your fuel gauge completely!\n", 0xFFFFDD00);
|
||||
gfx_printf("Additionally this will power off your console.\n%k", 0xFFCCCCCC);
|
||||
|
||||
gfx_puts("\nPress POWER to Continue.\nPress VOL to go to the menu.\n\n\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
max17050_fix_configuration();
|
||||
msleep(1000);
|
||||
gfx_con_getpos(&gfx_con.savedx, &gfx_con.savedy);
|
||||
u16 value = 0;
|
||||
gfx_printf("%kThe console will power off in 45 seconds.\n%k", 0xFFFFDD00, 0xFFCCCCCC);
|
||||
while (value < 46)
|
||||
{
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("%2ds elapsed", value);
|
||||
msleep(1000);
|
||||
value++;
|
||||
}
|
||||
msleep(2000);
|
||||
|
||||
power_off();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
EPRINTF("You need a fully charged battery\nand connected to a wall adapter,\nto apply this fix!");
|
||||
|
||||
msleep(500);
|
||||
btn_wait();
|
||||
} */
|
||||
|
||||
/*void reset_pmic_fuel_gauge_charger_config()
|
||||
{
|
||||
int avgCurrent;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
gfx_printf("%k\nThis will wipe your battery stats completely!\n"
|
||||
"%kAnd it may not power on without physically\nremoving and re-inserting the battery.\n%k"
|
||||
"\nAre you really sure?%k\n", 0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFCCCCCC);
|
||||
|
||||
gfx_puts("\nPress POWER to Continue.\nPress VOL to go to the menu.\n\n\n");
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
gfx_printf("%kKeep the USB cable connected!%k\n\n", 0xFFFFDD00, 0xFFCCCCCC);
|
||||
gfx_con_getpos(&gfx_con.savedx, &gfx_con.savedy);
|
||||
|
||||
u8 value = 30;
|
||||
while (value > 0)
|
||||
{
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("%kWait... (%ds) %k", 0xFF888888, value, 0xFFCCCCCC);
|
||||
msleep(1000);
|
||||
value--;
|
||||
}
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
|
||||
//Check if still connected.
|
||||
max17050_get_property(MAX17050_AvgCurrent, &avgCurrent);
|
||||
if ((avgCurrent / 1000) < -10)
|
||||
EPRINTF("You need to be connected to a wall adapter\nor PC to apply this fix!");
|
||||
else
|
||||
{
|
||||
// Apply fix.
|
||||
bq24193_fake_battery_removal();
|
||||
gfx_printf("Done! \n"
|
||||
"%k1. Remove the USB cable\n"
|
||||
"2. Press POWER for 15s.\n"
|
||||
"3. Reconnect the USB to power-on!%k\n", 0xFFFFDD00, 0xFFCCCCCC);
|
||||
}
|
||||
msleep(500);
|
||||
btn_wait();
|
||||
}
|
||||
}*/
|
||||
|
||||
#pragma GCC pop_options
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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 _FE_TOOLS_H_
|
||||
#define _FE_TOOLS_H_
|
||||
|
||||
void dump_packages12();
|
||||
void fix_sd_all_attr();
|
||||
void fix_sd_nin_attr();
|
||||
void fix_battery_desync();
|
||||
void menu_autorcm();
|
||||
|
||||
#endif
|
||||
@@ -1,351 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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 "di.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../power/max77620.h"
|
||||
#include "../power/max7762x.h"
|
||||
#include "../soc/clock.h"
|
||||
#include "../soc/gpio.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;
|
||||
|
||||
void display_end();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void display_init()
|
||||
{
|
||||
// Check if display is already initialized.
|
||||
if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & 0x18000000)
|
||||
display_end();
|
||||
|
||||
// Power on.
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL);
|
||||
|
||||
// Enable Display Interface specific clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000; // Clear reset DSI, MIPI_CAL.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000; // Set enable clock DSI, MIPI_CAL.
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000; // Set enable clock DISP1, HOST1X.
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x20000; // Set enable clock 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) = 0x80000; // Set enable clock DSIA_LP.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
|
||||
|
||||
// Disable deep power down.
|
||||
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
|
||||
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
|
||||
|
||||
// Config LCD and Backlight 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_BL_PWM) &= ~PINMUX_TRISTATE; // PULL_DOWN | 1
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
|
||||
// Set Backlight +-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 Backlight power.
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // Backlight +5V enable.
|
||||
usleep(10000);
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // Backlight -5V enable.
|
||||
usleep(10000);
|
||||
|
||||
// Configure Backlight pins (PWM, EN, 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);
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Enable Backlight EN.
|
||||
|
||||
// Power up supply regulator for display interface.
|
||||
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 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): 96 MHz.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2D0AAA; // PLLD_ENABLE_CLK.
|
||||
|
||||
// Setup display communication interfaces.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_dc_setup_win_config, 94);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config, 61);
|
||||
usleep(10000);
|
||||
|
||||
// Enable Backlight Reset.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH);
|
||||
usleep(60000);
|
||||
|
||||
// Setups DSI packet configuration and request display id.
|
||||
DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204;
|
||||
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0);
|
||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_READ, MIPI_DCS_GET_DISPLAY_ID, 0);
|
||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||
|
||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
|
||||
_display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA);
|
||||
|
||||
usleep(5000);
|
||||
|
||||
// MIPI_DCS_GET_DISPLAY_ID reply is a long read, size 3 u32.
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
_display_id = DSI(_DSIREG(DSI_RD_DATA)); // Skip ack and msg type info and get the payload (display id).
|
||||
|
||||
// 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_LPM062M)
|
||||
_display_id = PANEL_JDI_LPM062M;
|
||||
|
||||
// Initialize display panel.
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
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);
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
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; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
|
||||
else
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // 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_P062CCA_AZ2:
|
||||
case PANEL_AUO_A062TAN02:
|
||||
default: // Allow spare part displays to work.
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 120000);
|
||||
break;
|
||||
}
|
||||
|
||||
_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): 460.8 MHz.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN.
|
||||
|
||||
// Finalize DSI configuration.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 21);
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; // PCD1 | div3.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10);
|
||||
usleep(10000);
|
||||
|
||||
// Calibrate display communication pads.
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_pad_cal_config, 6);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_pad_cal_config, 4);
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_apply_dsi_cal_config, 16);
|
||||
usleep(10000);
|
||||
|
||||
// Enable video display controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_enable_config, 113);
|
||||
}
|
||||
|
||||
void display_backlight_pwm_init()
|
||||
{
|
||||
clock_enable_pwm();
|
||||
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM.
|
||||
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFFC) | 1; // PWM clock source.
|
||||
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_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
{
|
||||
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF;
|
||||
if (brightness == old_value)
|
||||
return;
|
||||
|
||||
if (brightness > 255)
|
||||
brightness = 255;
|
||||
|
||||
if (old_value < brightness)
|
||||
{
|
||||
for (u32 i = old_value; i < brightness + 1; i++)
|
||||
{
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
|
||||
usleep(step_delay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = old_value; i > brightness; i--)
|
||||
{
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
|
||||
usleep(step_delay);
|
||||
}
|
||||
}
|
||||
if (!brightness)
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
|
||||
}
|
||||
|
||||
void display_end()
|
||||
{
|
||||
display_backlight_brightness(0, 1000);
|
||||
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE;
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF
|
||||
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // Disable host cmd packet.
|
||||
|
||||
// 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);
|
||||
usleep(10000);
|
||||
|
||||
// De-initialize display panel.
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
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_P062CCA_AZ2:
|
||||
case PANEL_AUO_A062TAN02:
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
// Set Power.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0xB39; // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
|
||||
if (_display_id == PANEL_INL_P062CCA_AZ2)
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
|
||||
else
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
|
||||
// Set Power control. (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; // Set Power control. (Unknown).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE, 50000);
|
||||
|
||||
// Disable display and backlight pins.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
|
||||
usleep(10000);
|
||||
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable.
|
||||
usleep(10000);
|
||||
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable.
|
||||
usleep(10000);
|
||||
|
||||
// Disable Display Interface specific clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000; // Set reset clock DSI, MIPI_CAL.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000; // Clear enable clock DSI, MIPI_CAL.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1X.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000; // Clear enable DISP1, HOST1X.
|
||||
|
||||
// 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 to automatic function mode.
|
||||
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) & 0xFFFFFFFC)| 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
display_backlight(true);
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer()
|
||||
{
|
||||
// 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, 32);
|
||||
usleep(35000);
|
||||
|
||||
return (u32 *)IPL_FB_ADDRESS;
|
||||
}
|
||||
|
||||
@@ -1,533 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _DI_H_
|
||||
#define _DI_H_
|
||||
|
||||
#include "../../common/memory_map.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
/*! 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_NO_STALL (1 << 8)
|
||||
#define SYNCPT_CNTRL_SOFT_RESET (1 << 0)
|
||||
|
||||
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
|
||||
#define SYNCPT_VSYNC_ENABLE (1 << 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 (1 << 0)
|
||||
#define PW1_ENABLE (1 << 2)
|
||||
#define PW2_ENABLE (1 << 4)
|
||||
#define PW3_ENABLE (1 << 6)
|
||||
#define PW4_ENABLE (1 << 8)
|
||||
#define PM0_ENABLE (1 << 16)
|
||||
#define PM1_ENABLE (1 << 18)
|
||||
|
||||
#define DC_CMD_INT_STATUS 0x37
|
||||
#define DC_CMD_INT_MASK 0x38
|
||||
#define DC_CMD_INT_ENABLE 0x39
|
||||
|
||||
#define DC_CMD_STATE_ACCESS 0x40
|
||||
#define READ_MUX (1 << 0)
|
||||
#define WRITE_MUX (1 << 2)
|
||||
|
||||
#define DC_CMD_STATE_CONTROL 0x41
|
||||
#define GENERAL_ACT_REQ (1 << 0)
|
||||
#define WIN_A_ACT_REQ (1 << 1)
|
||||
#define WIN_B_ACT_REQ (1 << 2)
|
||||
#define WIN_C_ACT_REQ (1 << 3)
|
||||
#define WIN_D_ACT_REQ (1 << 4)
|
||||
#define CURSOR_ACT_REQ (1 << 7)
|
||||
#define GENERAL_UPDATE (1 << 8)
|
||||
#define WIN_A_UPDATE (1 << 9)
|
||||
#define WIN_B_UPDATE (1 << 10)
|
||||
#define WIN_C_UPDATE (1 << 11)
|
||||
#define WIN_D_UPDATE (1 << 12)
|
||||
#define CURSOR_UPDATE (1 << 15)
|
||||
#define NC_HOST_TRIG (1 << 24)
|
||||
|
||||
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
|
||||
#define WINDOW_A_SELECT (1 << 4)
|
||||
#define WINDOW_B_SELECT (1 << 5)
|
||||
#define WINDOW_C_SELECT (1 << 6)
|
||||
#define WINDOW_D_SELECT (1 << 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 HDMI_ENABLE (1 << 30)
|
||||
#define DSI_ENABLE (1 << 29)
|
||||
#define SOR1_TIMING_CYA (1 << 27)
|
||||
#define SOR1_ENABLE (1 << 26)
|
||||
#define SOR_ENABLE (1 << 25)
|
||||
#define CURSOR_ENABLE (1 << 16)
|
||||
|
||||
#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 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 SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
|
||||
|
||||
#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 SC1_H_QUALIFIER_NONE (1 << 16)
|
||||
#define SC0_H_QUALIFIER_NONE (1 << 0)
|
||||
|
||||
#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_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 (1 << 0)
|
||||
#define V_DIRECTION (1 << 2)
|
||||
#define SCAN_COLUMN (1 << 4)
|
||||
#define COLOR_EXPAND (1 << 6)
|
||||
#define CSC_ENABLE (1 << 18)
|
||||
#define WIN_ENABLE (1 << 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_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_FIFO_RESET (1 << 21)
|
||||
#define DSI_HOST_CONTROL_CRC_RESET (1 << 20)
|
||||
#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_RAW (1 << 6)
|
||||
#define DSI_HOST_CONTROL_HS (1 << 5)
|
||||
#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4)
|
||||
#define DSI_HOST_CONTROL_IMM_BTA (1 << 3)
|
||||
#define DSI_HOST_CONTROL_PKT_BTA (1 << 2)
|
||||
#define DSI_HOST_CONTROL_CS (1 << 1)
|
||||
#define DSI_HOST_CONTROL_ECC (1 << 0)
|
||||
|
||||
#define DSI_CONTROL 0x10
|
||||
#define DSI_CONTROL_HS_CLK_CTRL (1 << 20)
|
||||
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
|
||||
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
|
||||
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
|
||||
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
|
||||
#define DSI_CONTROL_DCS_ENABLE (1 << 3)
|
||||
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
|
||||
#define DSI_CONTROL_VIDEO_ENABLE (1 << 1)
|
||||
#define DSI_CONTROL_HOST_ENABLE (1 << 0)
|
||||
|
||||
#define DSI_SOL_DELAY 0x11
|
||||
#define DSI_MAX_THRESHOLD 0x12
|
||||
|
||||
#define DSI_TRIGGER 0x13
|
||||
#define DSI_TRIGGER_HOST (1 << 1)
|
||||
#define DSI_TRIGGER_VIDEO (1 << 0)
|
||||
|
||||
#define DSI_TX_CRC 0x14
|
||||
#define DSI_STATUS 0x15
|
||||
#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_LRX(x) (((x) & 0xffff) << 16)
|
||||
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
|
||||
|
||||
#define DSI_TIMEOUT_1 0x45
|
||||
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
|
||||
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
|
||||
|
||||
#define DSI_TO_TALLY 0x46
|
||||
|
||||
#define DSI_PAD_CONTROL_0 0x4B
|
||||
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
|
||||
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
|
||||
|
||||
#define DSI_PAD_CONTROL_CD 0x4C
|
||||
#define DSI_VIDEO_MODE_CONTROL 0x4E
|
||||
#define DSI_CMD_PKT_VID_ENABLE 1
|
||||
|
||||
#define DSI_PAD_CONTROL_1 0x4F
|
||||
#define DSI_PAD_CONTROL_2 0x50
|
||||
|
||||
#define DSI_PAD_CONTROL_3 0x51
|
||||
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
|
||||
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
|
||||
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
|
||||
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
|
||||
|
||||
#define DSI_PAD_CONTROL_4 0x52
|
||||
#define DSI_INIT_SEQ_DATA_15 0x5F
|
||||
|
||||
/*! 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_DCS_SHORT_WRITE 0x05
|
||||
#define MIPI_DSI_DCS_READ 0x06
|
||||
#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15
|
||||
#define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37
|
||||
#define MIPI_DSI_DCS_LONG_WRITE 0x39
|
||||
|
||||
/*! MIPI DCS CMDs. */
|
||||
#define MIPI_DCS_GET_DISPLAY_ID 0x04
|
||||
#define MIPI_DCS_ENTER_SLEEP_MODE 0x10
|
||||
#define MIPI_DCS_EXIT_SLEEP_MODE 0x11
|
||||
#define MIPI_DCS_SET_DISPLAY_ON 0x29
|
||||
|
||||
/* Switch Panels:
|
||||
* [10] 81 [26]: JDI LPM062M326A
|
||||
* [10] 96 [09]: JDI LAM062M109A
|
||||
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
|
||||
* [20] XX [10]: InnoLux P062CCA-AZ2 [UNCONFIRMED ID]
|
||||
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
|
||||
* [30] XX [10]: AUO A062TAN02 (59.06A33.002) [UNCONFIRMED ID]
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PANEL_JDI_LPM062M = 0x10,
|
||||
PANEL_INL_P062CCA_AZ1 = 0x0F20,
|
||||
PANEL_AUO_A062TAN01 = 0x0F30,
|
||||
PANEL_INL_P062CCA_AZ2 = 0x1020,
|
||||
PANEL_AUO_A062TAN02 = 0x1030
|
||||
};
|
||||
|
||||
void display_init();
|
||||
void display_backlight_pwm_init();
|
||||
void display_end();
|
||||
|
||||
/*! 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);
|
||||
|
||||
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
|
||||
u32 *display_init_framebuffer();
|
||||
void display_init_cursor(void *crs_fb, u32 size);
|
||||
void display_set_pos_cursor(u32 x, u32 y);
|
||||
void display_deinit_cursor();
|
||||
|
||||
#endif
|
||||
@@ -1,596 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
//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},
|
||||
{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},
|
||||
{0x4E4, 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},
|
||||
{0x716, 0x10000FF},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{0x716, 0x10000FF},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{0x716, 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[61] = {
|
||||
{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},
|
||||
{DSI_INIT_SEQ_DATA_15, 0},
|
||||
{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},
|
||||
{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},
|
||||
{DSI_PHY_TIMING_0, 0x6070601},
|
||||
{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},
|
||||
{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_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, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x0BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x1939}, // MIPI_DSI_DCS_LONG_WRITE: 25 bytes.
|
||||
{DSI_WR_DATA, 0xAAAAAAD8},
|
||||
{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: 0x1BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2739}, // MIPI_DSI_DCS_LONG_WRITE: 39 bytes.
|
||||
{DSI_WR_DATA, 0xFFFFFFD8},
|
||||
{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: 0x2BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xF39}, // MIPI_DSI_DCS_LONG_WRITE: 15 bytes.
|
||||
{DSI_WR_DATA, 0xFFFFFFD8},
|
||||
{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: 0x0BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x06D915}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x6D9.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x000000B9}, // Disable extension cmd.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST}
|
||||
};
|
||||
|
||||
//DSI packet config.
|
||||
static const cfg_op_t _display_dsi_packet_config[21] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PHY_TIMING_0, 0x6070601},
|
||||
{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[6] = {
|
||||
{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},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0x300}
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_dsi_pad_cal_config[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}
|
||||
};
|
||||
|
||||
//MIPI CAL config.
|
||||
static const cfg_op_t _display_mipi_apply_dsi_cal_config[16] = {
|
||||
{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},
|
||||
{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},
|
||||
{0x4E4, 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},
|
||||
{0x716, 0x10000FF},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{0x716, 0x10000FF},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{0x716, 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_DISP_TIMING_OPTIONS, 0},
|
||||
{DC_DISP_REF_TO_SYNC, (1 << 16)}, // h_ref_to_sync = 0, v_ref_to_sync = 1.
|
||||
{DC_DISP_SYNC_WIDTH, 0x10048},
|
||||
{DC_DISP_BACK_PORCH, 0x90048},
|
||||
{DC_DISP_ACTIVE, 0x50002D0},
|
||||
{DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the 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}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2139}, // MIPI_DSI_DCS_LONG_WRITE: 33 bytes.
|
||||
{DSI_WR_DATA, 0x191919D5},
|
||||
{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}, // 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}, // Disable extension cmd.
|
||||
{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}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
|
||||
{DSI_WR_DATA, 0x191919D5},
|
||||
{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},
|
||||
{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}, // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
|
||||
// Set Power control. (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}, // Set Power control. (Unknown).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x000000B9}, // Disable extension cmd.
|
||||
{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.
|
||||
static const cfg_op_t cfg_display_framebuffer[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(2880)},
|
||||
{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}
|
||||
};
|
||||
@@ -1,524 +0,0 @@
|
||||
/*
|
||||
* 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 <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "gfx.h"
|
||||
|
||||
static const u8 _gfx_font[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( )
|
||||
0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, // Char 033 (!)
|
||||
0x00, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, // Char 034 (")
|
||||
0x00, 0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, // Char 035 (#)
|
||||
0x00, 0x18, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x18, // Char 036 ($)
|
||||
0x00, 0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, // Char 037 (%)
|
||||
0x00, 0x3C, 0x66, 0x3C, 0x1C, 0xE6, 0x66, 0xFC, // Char 038 (&)
|
||||
0x00, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, // Char 039 (')
|
||||
0x00, 0x30, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, // Char 040 (()
|
||||
0x00, 0x0C, 0x18, 0x30, 0x30, 0x18, 0x0C, 0x00, // Char 041 ())
|
||||
0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, // Char 042 (*)
|
||||
0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, // Char 043 (+)
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0C, 0x00, // Char 044 (,)
|
||||
0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, // Char 045 (-)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, // Char 046 (.)
|
||||
0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, // Char 047 (/)
|
||||
0x00, 0x3C, 0x66, 0x76, 0x6E, 0x66, 0x3C, 0x00, // Char 048 (0)
|
||||
0x00, 0x18, 0x1C, 0x18, 0x18, 0x18, 0x7E, 0x00, // Char 049 (1)
|
||||
0x00, 0x3C, 0x62, 0x30, 0x0C, 0x06, 0x7E, 0x00, // Char 050 (2)
|
||||
0x00, 0x3C, 0x62, 0x38, 0x60, 0x66, 0x3C, 0x00, // Char 051 (3)
|
||||
0x00, 0x6C, 0x6C, 0x66, 0xFE, 0x60, 0x60, 0x00, // Char 052 (4)
|
||||
0x00, 0x7E, 0x06, 0x7E, 0x60, 0x66, 0x3C, 0x00, // Char 053 (5)
|
||||
0x00, 0x3C, 0x06, 0x3E, 0x66, 0x66, 0x3C, 0x00, // Char 054 (6)
|
||||
0x00, 0x7E, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, // Char 055 (7)
|
||||
0x00, 0x3C, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, // Char 056 (8)
|
||||
0x00, 0x3C, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x00, // Char 057 (9)
|
||||
0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, // Char 058 (:)
|
||||
0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x0C, 0x00, // Char 059 (;)
|
||||
0x00, 0x70, 0x1C, 0x06, 0x06, 0x1C, 0x70, 0x00, // Char 060 (<)
|
||||
0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, // Char 061 (=)
|
||||
0x00, 0x0E, 0x38, 0x60, 0x60, 0x38, 0x0E, 0x00, // Char 062 (>)
|
||||
0x00, 0x3C, 0x66, 0x30, 0x18, 0x00, 0x18, 0x00, // Char 063 (?)
|
||||
0x00, 0x3C, 0x66, 0x76, 0x76, 0x06, 0x46, 0x3C, // Char 064 (@)
|
||||
0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // Char 065 (A)
|
||||
0x00, 0x3E, 0x66, 0x3E, 0x66, 0x66, 0x3E, 0x00, // Char 066 (B)
|
||||
0x00, 0x3C, 0x66, 0x06, 0x06, 0x66, 0x3C, 0x00, // Char 067 (C)
|
||||
0x00, 0x1E, 0x36, 0x66, 0x66, 0x36, 0x1E, 0x00, // Char 068 (D)
|
||||
0x00, 0x7E, 0x06, 0x1E, 0x06, 0x06, 0x7E, 0x00, // Char 069 (E)
|
||||
0x00, 0x3E, 0x06, 0x1E, 0x06, 0x06, 0x06, 0x00, // Char 070 (F)
|
||||
0x00, 0x3C, 0x66, 0x06, 0x76, 0x66, 0x3C, 0x00, // Char 071 (G)
|
||||
0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // Char 072 (H)
|
||||
0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // Char 073 (I)
|
||||
0x00, 0x78, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, // Char 074 (J)
|
||||
0x00, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x00, // Char 075 (K)
|
||||
0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x00, // Char 076 (L)
|
||||
0x00, 0x46, 0x6E, 0x7E, 0x56, 0x46, 0x46, 0x00, // Char 077 (M)
|
||||
0x00, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00, // Char 078 (N)
|
||||
0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 079 (O)
|
||||
0x00, 0x3E, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00, // Char 080 (P)
|
||||
0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x70, 0x00, // Char 081 (Q)
|
||||
0x00, 0x3E, 0x66, 0x3E, 0x1E, 0x36, 0x66, 0x00, // Char 082 (R)
|
||||
0x00, 0x3C, 0x66, 0x0C, 0x30, 0x66, 0x3C, 0x00, // Char 083 (S)
|
||||
0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, // Char 084 (T)
|
||||
0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 085 (U)
|
||||
0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // Char 086 (V)
|
||||
0x00, 0x46, 0x46, 0x56, 0x7E, 0x6E, 0x46, 0x00, // Char 087 (W)
|
||||
0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, // Char 088 (X)
|
||||
0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, // Char 089 (Y)
|
||||
0x00, 0x7E, 0x30, 0x18, 0x0C, 0x06, 0x7E, 0x00, // Char 090 (Z)
|
||||
0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, // Char 091 ([)
|
||||
0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, // Char 092 (\)
|
||||
0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, // Char 093 (])
|
||||
0x00, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, // Char 094 (^)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, // Char 095 (_)
|
||||
0x00, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // Char 096 (`)
|
||||
0x00, 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x7C, 0x00, // Char 097 (a)
|
||||
0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, // Char 098 (b)
|
||||
0x00, 0x00, 0x3C, 0x06, 0x06, 0x06, 0x3C, 0x00, // Char 099 (c)
|
||||
0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, // Char 100 (d)
|
||||
0x00, 0x00, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00, // Char 101 (e)
|
||||
0x00, 0x38, 0x0C, 0x3E, 0x0C, 0x0C, 0x0C, 0x00, // Char 102 (f)
|
||||
0x00, 0x00, 0x7C, 0x66, 0x7C, 0x40, 0x3C, 0x00, // Char 103 (g)
|
||||
0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x00, // Char 104 (h)
|
||||
0x00, 0x18, 0x00, 0x1C, 0x18, 0x18, 0x3C, 0x00, // Char 105 (i)
|
||||
0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x1E, 0x00, // Char 106 (j)
|
||||
0x00, 0x06, 0x06, 0x36, 0x1E, 0x36, 0x66, 0x00, // Char 107 (k)
|
||||
0x00, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // Char 108 (l)
|
||||
0x00, 0x00, 0x66, 0xFE, 0xFE, 0xD6, 0xC6, 0x00, // Char 109 (m)
|
||||
0x00, 0x00, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x00, // Char 110 (n)
|
||||
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 111 (o)
|
||||
0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x00, // Char 112 (p)
|
||||
0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x00, // Char 113 (q)
|
||||
0x00, 0x00, 0x3E, 0x66, 0x06, 0x06, 0x06, 0x00, // Char 114 (r)
|
||||
0x00, 0x00, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x00, // Char 115 (s)
|
||||
0x00, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x70, 0x00, // Char 116 (t)
|
||||
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, // Char 117 (u)
|
||||
0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // Char 118 (v)
|
||||
0x00, 0x00, 0xC6, 0xD6, 0xFE, 0x7C, 0x6C, 0x00, // Char 119 (w)
|
||||
0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, // Char 120 (x)
|
||||
0x00, 0x00, 0x66, 0x66, 0x7C, 0x60, 0x3C, 0x00, // Char 121 (y)
|
||||
0x00, 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x7E, 0x00, // Char 122 (z)
|
||||
0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 0x18, // Char 123 ({)
|
||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, // Char 124 (|)
|
||||
0x00, 0x0C, 0x08, 0x08, 0x10, 0x08, 0x08, 0x0C, // Char 125 (})
|
||||
0x00, 0x00, 0x00, 0x4C, 0x32, 0x00, 0x00, 0x00 // Char 126 (~)
|
||||
};
|
||||
|
||||
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride)
|
||||
{
|
||||
gfx_ctxt.fb = fb;
|
||||
gfx_ctxt.width = width;
|
||||
gfx_ctxt.height = height;
|
||||
gfx_ctxt.stride = stride;
|
||||
}
|
||||
|
||||
void gfx_clear_grey(u8 color)
|
||||
{
|
||||
memset(gfx_ctxt.fb, color, gfx_ctxt.width * gfx_ctxt.height * 4);
|
||||
}
|
||||
|
||||
void gfx_clear_color(u32 color)
|
||||
{
|
||||
for (u32 i = 0; i < gfx_ctxt.width * gfx_ctxt.height; i++)
|
||||
gfx_ctxt.fb[i] = color;
|
||||
}
|
||||
|
||||
void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height)
|
||||
{
|
||||
memset(gfx_ctxt.fb + pos_x * gfx_ctxt.stride, color, height * 4 * gfx_ctxt.stride);
|
||||
}
|
||||
|
||||
void gfx_con_init()
|
||||
{
|
||||
gfx_con.gfx_ctxt = &gfx_ctxt;
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_con.x = 0;
|
||||
gfx_con.y = 0;
|
||||
gfx_con.savedx = 0;
|
||||
gfx_con.savedy = 0;
|
||||
gfx_con.fgcol = 0xFFCCCCCC;
|
||||
gfx_con.fillbg = 1;
|
||||
gfx_con.bgcol = 0xFF1B1B1B;
|
||||
gfx_con.mute = 0;
|
||||
}
|
||||
|
||||
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol)
|
||||
{
|
||||
gfx_con.fgcol = fgcol;
|
||||
gfx_con.fillbg = fillbg;
|
||||
gfx_con.bgcol = bgcol;
|
||||
}
|
||||
|
||||
void gfx_con_getpos(u32 *x, u32 *y)
|
||||
{
|
||||
*x = gfx_con.x;
|
||||
*y = gfx_con.y;
|
||||
}
|
||||
|
||||
void gfx_con_setpos(u32 x, u32 y)
|
||||
{
|
||||
gfx_con.x = x;
|
||||
gfx_con.y = y;
|
||||
}
|
||||
|
||||
void gfx_putc(char c)
|
||||
{
|
||||
// Duplicate code for performance reasons.
|
||||
switch (gfx_con.fntsz)
|
||||
{
|
||||
case 16:
|
||||
if (c >= 32 && c <= 126)
|
||||
{
|
||||
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
||||
u32 *fb = gfx_ctxt.fb + gfx_con.x + gfx_con.y * gfx_ctxt.stride;
|
||||
|
||||
for (u32 i = 0; i < 16; i += 2)
|
||||
{
|
||||
u8 v = *cbuf;
|
||||
for (u32 k = 0; k < 2; k++)
|
||||
{
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
{
|
||||
if (v & 1)
|
||||
{
|
||||
*fb = gfx_con.fgcol;
|
||||
fb++;
|
||||
*fb = gfx_con.fgcol;
|
||||
}
|
||||
else if (gfx_con.fillbg)
|
||||
{
|
||||
*fb = gfx_con.bgcol;
|
||||
fb++;
|
||||
*fb = gfx_con.bgcol;
|
||||
}
|
||||
else
|
||||
fb++;
|
||||
v >>= 1;
|
||||
fb++;
|
||||
}
|
||||
fb += gfx_ctxt.stride - 16;
|
||||
v = *cbuf;
|
||||
}
|
||||
cbuf++;
|
||||
}
|
||||
gfx_con.x += 16;
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
gfx_con.x = 0;
|
||||
gfx_con.y += 16;
|
||||
if (gfx_con.y > gfx_ctxt.height - 16)
|
||||
gfx_con.y = 0;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
if (c >= 32 && c <= 126)
|
||||
{
|
||||
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
||||
u32 *fb = gfx_ctxt.fb + gfx_con.x + gfx_con.y * gfx_ctxt.stride;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
u8 v = *cbuf++;
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
{
|
||||
if (v & 1)
|
||||
*fb = gfx_con.fgcol;
|
||||
else if (gfx_con.fillbg)
|
||||
*fb = gfx_con.bgcol;
|
||||
v >>= 1;
|
||||
fb++;
|
||||
}
|
||||
fb += gfx_ctxt.stride - 8;
|
||||
}
|
||||
gfx_con.x += 8;
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
gfx_con.x = 0;
|
||||
gfx_con.y += 8;
|
||||
if (gfx_con.y > gfx_ctxt.height - 8)
|
||||
gfx_con.y = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_puts(char *s)
|
||||
{
|
||||
if (!s || gfx_con.mute)
|
||||
return;
|
||||
|
||||
for (; *s; s++)
|
||||
gfx_putc(*s);
|
||||
}
|
||||
|
||||
static void _gfx_putn(u32 v, int base, char fill, int fcnt)
|
||||
{
|
||||
char buf[65];
|
||||
static const char digits[] = "0123456789ABCDEFghijklmnopqrstuvwxyz";
|
||||
char *p;
|
||||
int c = fcnt;
|
||||
|
||||
if (base > 36)
|
||||
return;
|
||||
|
||||
p = buf + 64;
|
||||
*p = 0;
|
||||
do
|
||||
{
|
||||
c--;
|
||||
*--p = digits[v % base];
|
||||
v /= base;
|
||||
} while (v);
|
||||
|
||||
if (fill != 0)
|
||||
{
|
||||
while (c > 0)
|
||||
{
|
||||
*--p = fill;
|
||||
c--;
|
||||
}
|
||||
}
|
||||
|
||||
gfx_puts(p);
|
||||
}
|
||||
|
||||
void gfx_put_small_sep()
|
||||
{
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_putc('\n');
|
||||
gfx_con.fntsz = prevFontSize;
|
||||
}
|
||||
|
||||
void gfx_put_big_sep()
|
||||
{
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_putc('\n');
|
||||
gfx_con.fntsz = prevFontSize;
|
||||
}
|
||||
|
||||
void gfx_printf(const char *fmt, ...)
|
||||
{
|
||||
if (gfx_con.mute)
|
||||
return;
|
||||
|
||||
va_list ap;
|
||||
int fill, fcnt;
|
||||
|
||||
va_start(ap, fmt);
|
||||
while(*fmt)
|
||||
{
|
||||
if(*fmt == '%')
|
||||
{
|
||||
fmt++;
|
||||
fill = 0;
|
||||
fcnt = 0;
|
||||
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ')
|
||||
{
|
||||
fcnt = *fmt;
|
||||
fmt++;
|
||||
if (*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
fill = fcnt;
|
||||
fcnt = *fmt - '0';
|
||||
fmt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fill = ' ';
|
||||
fcnt -= '0';
|
||||
}
|
||||
}
|
||||
switch(*fmt)
|
||||
{
|
||||
case 'c':
|
||||
gfx_putc(va_arg(ap, u32));
|
||||
break;
|
||||
case 's':
|
||||
gfx_puts(va_arg(ap, char *));
|
||||
break;
|
||||
case 'd':
|
||||
_gfx_putn(va_arg(ap, u32), 10, fill, fcnt);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
case 'x':
|
||||
case 'X':
|
||||
_gfx_putn(va_arg(ap, u32), 16, fill, fcnt);
|
||||
break;
|
||||
case 'k':
|
||||
gfx_con.fgcol = va_arg(ap, u32);
|
||||
break;
|
||||
case 'K':
|
||||
gfx_con.bgcol = va_arg(ap, u32);
|
||||
gfx_con.fillbg = 1;
|
||||
break;
|
||||
case '%':
|
||||
gfx_putc('%');
|
||||
break;
|
||||
case '\0':
|
||||
goto out;
|
||||
default:
|
||||
gfx_putc('%');
|
||||
gfx_putc(*fmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
gfx_putc(*fmt);
|
||||
fmt++;
|
||||
}
|
||||
|
||||
out:
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
{
|
||||
if (gfx_con.mute)
|
||||
return;
|
||||
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 8;
|
||||
for(u32 i = 0; i < len; i++)
|
||||
{
|
||||
if(i % 0x10 == 0)
|
||||
{
|
||||
if(i != 0)
|
||||
{
|
||||
gfx_puts("| ");
|
||||
for(u32 j = 0; j < 0x10; j++)
|
||||
{
|
||||
u8 c = buf[i - 0x10 + j];
|
||||
if(c >= 32 && c <= 126)
|
||||
gfx_putc(c);
|
||||
else
|
||||
gfx_putc('.');
|
||||
}
|
||||
gfx_putc('\n');
|
||||
}
|
||||
gfx_printf("%08x: ", base + i);
|
||||
}
|
||||
gfx_printf("%02x ", buf[i]);
|
||||
if (i == len - 1)
|
||||
{
|
||||
int ln = len % 0x10 != 0;
|
||||
u32 k = 0x10 - 1;
|
||||
if (ln)
|
||||
{
|
||||
k = (len & 0xF) - 1;
|
||||
for (u32 j = 0; j < 0x10 - k; j++)
|
||||
gfx_puts(" ");
|
||||
}
|
||||
gfx_puts("| ");
|
||||
for(u32 j = 0; j < (ln ? k : k + 1); j++)
|
||||
{
|
||||
u8 c = buf[i - k + j];
|
||||
if(c >= 32 && c <= 126)
|
||||
gfx_putc(c);
|
||||
else
|
||||
gfx_putc('.');
|
||||
}
|
||||
gfx_putc('\n');
|
||||
}
|
||||
}
|
||||
gfx_putc('\n');
|
||||
gfx_con.fntsz = prevFontSize;
|
||||
}
|
||||
|
||||
static int abs(int x)
|
||||
{
|
||||
if (x < 0)
|
||||
return -x;
|
||||
return x;
|
||||
}
|
||||
|
||||
void gfx_set_pixel(u32 x, u32 y, u32 color)
|
||||
{
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = color;
|
||||
}
|
||||
|
||||
void gfx_line(int x0, int y0, int x1, int y1, u32 color)
|
||||
{
|
||||
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||
int err = (dx > dy ? dx : -dy) / 2, e2;
|
||||
|
||||
while (1)
|
||||
{
|
||||
gfx_set_pixel(x0, y0, color);
|
||||
if (x0 == x1 && y0 == y1)
|
||||
break;
|
||||
e2 = err;
|
||||
if (e2 >-dx)
|
||||
{
|
||||
err -= dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 < dy)
|
||||
{
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_set_rect_grey(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
u32 pos = 0;
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
{
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
{
|
||||
memset(&gfx_ctxt.fb[x + y*gfx_ctxt.stride], buf[pos], 4);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gfx_set_rect_rgb(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
u32 pos = 0;
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
{
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
{
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = buf[pos + 2] | (buf[pos + 1] << 8) | (buf[pos] << 16);
|
||||
pos+=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
u32 *ptr = (u32 *)buf;
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = *ptr++;
|
||||
}
|
||||
|
||||
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
{
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = buf[(size_y + pos_y - 1 - y ) * size_x + x - pos_x];
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* 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 _GFX_H_
|
||||
#define _GFX_H_
|
||||
|
||||
#include "../../common/common_gfx.h"
|
||||
|
||||
#define EPRINTF(text) gfx_printf("%k"text"%k\n", 0xFFFF0000, 0xFFCCCCCC)
|
||||
#define EPRINTFARGS(text, args...) gfx_printf("%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC)
|
||||
#define WPRINTF(text) gfx_printf("%k"text"%k\n", 0xFFFFDD00, 0xFFCCCCCC)
|
||||
#define WPRINTFARGS(text, args...) gfx_printf("%k"text"%k\n", 0xFFFFDD00, args, 0xFFCCCCCC)
|
||||
|
||||
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride);
|
||||
void gfx_clear_grey(u8 color);
|
||||
void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height);
|
||||
void gfx_clear_color(u32 color);
|
||||
void gfx_con_init();
|
||||
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol);
|
||||
void gfx_con_getpos(u32 *x, u32 *y);
|
||||
void gfx_con_setpos(u32 x, u32 y);
|
||||
void gfx_putc(char c);
|
||||
void gfx_puts(char *s);
|
||||
void gfx_printf(const char *fmt, ...);
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
|
||||
|
||||
void gfx_set_pixel(u32 x, u32 y, u32 color);
|
||||
void gfx_line(int x0, int y0, int x1, int y1, u32 color);
|
||||
void gfx_put_small_sep();
|
||||
void gfx_put_big_sep();
|
||||
void gfx_set_rect_grey(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
void gfx_set_rect_rgb(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
|
||||
// Global gfx console and context.
|
||||
gfx_ctxt_t gfx_ctxt;
|
||||
gfx_con_t gfx_con;
|
||||
|
||||
#endif
|
||||
@@ -1,537 +0,0 @@
|
||||
/*
|
||||
* 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 _HEKATE_LOGOS_H_
|
||||
#define _HEKATE_LOGOS_H_
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
// 119 x 57 @24bpp RGB RAW positioned at 577 x 1199
|
||||
#define SZ_MENU_LOGO 20349
|
||||
#define SZ_MENU_LOGO_BLZ 3084
|
||||
static unsigned char Kc_MENU_LOGO_blz[SZ_MENU_LOGO_BLZ] = {
|
||||
0x03, 0x30, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x36, 0xF0, 0xFF, 0x81, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x62, 0xF1,
|
||||
0x0F, 0xF0, 0x14, 0xF1, 0x62, 0xF1, 0x2A, 0xF0, 0xFF, 0x93, 0x10, 0x1D, 0x99, 0x03, 0x4F, 0xB2,
|
||||
0xBF, 0x17, 0x5A, 0x96, 0x0F, 0xF0, 0xF8, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0xBD, 0xF0, 0x81, 0xF0, 0x24, 0xF0, 0x81, 0xF0,
|
||||
0x62, 0xF1, 0x0F, 0xF0, 0x30, 0xF0, 0x62, 0xF1, 0xFF, 0xC0, 0x93, 0x90, 0x96, 0xCF, 0xF0, 0xA2,
|
||||
0x03, 0xCD, 0xF2, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0xC6, 0xF0, 0x81, 0xF0, 0x2A, 0xF0, 0xFF, 0x81, 0xF0, 0x62, 0xF1, 0x0F,
|
||||
0xF0, 0x30, 0xF0, 0x62, 0xF1, 0x96, 0xF6, 0xD8, 0xF0, 0xE1, 0xF0, 0xFF, 0xAE, 0xF3, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0xC6,
|
||||
0xF0, 0x81, 0xF0, 0x27, 0xF0, 0x81, 0xF0, 0x26, 0xF1, 0x0F, 0xF0, 0x2A, 0xF0, 0xFF, 0x4A, 0xC1,
|
||||
0x07, 0x95, 0x0F, 0xF0, 0xC9, 0xC0, 0xE6, 0x84, 0x0E, 0x41, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x4B, 0xF0, 0x51, 0xF0, 0xFF,
|
||||
0x81, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x21, 0xF0, 0x62, 0xF1, 0x51, 0xF0, 0x32, 0xF1, 0x1E, 0x90,
|
||||
0xFF, 0xC0, 0x03, 0xFF, 0x90, 0xBF, 0x07, 0xD3, 0x05, 0xBA, 0xA0, 0xE3, 0xF4, 0x0F, 0xF0, 0xE7,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x2D, 0xF0, 0x81, 0xF0,
|
||||
0xFF, 0x81, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x27, 0xF0, 0x0B, 0xF1, 0x62, 0xF1, 0x21, 0xF0, 0xEA,
|
||||
0x7F, 0x02, 0x1F, 0xD1, 0xF7, 0x21, 0xF0, 0x8A, 0x03, 0xB4, 0x90, 0x62, 0x16, 0x3C, 0x0B, 0xF1,
|
||||
0x1B, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFD, 0x0F, 0xF0,
|
||||
0x24, 0xF0, 0x54, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x21, 0xF0, 0x62, 0xF1, 0xFF, 0x2A,
|
||||
0xF0, 0x35, 0xF1, 0xA5, 0xF3, 0x7B, 0xF3, 0xF5, 0x01, 0x0B, 0x71, 0xAE, 0x4F, 0x0C, 0x16, 0x72,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFE, 0x0F, 0xF0, 0x2C,
|
||||
0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x21, 0xF0, 0x81, 0xF0, 0x2A, 0xF0, 0x62, 0xF1, 0xFF, 0x62, 0xF1,
|
||||
0x20, 0xF0, 0xAE, 0x0C, 0xD0, 0xFE, 0x1B, 0x24, 0xF0, 0xD0, 0xFE, 0xD3, 0xDF, 0x04, 0xD0, 0xDE,
|
||||
0xEA, 0xC9, 0x00, 0x00, 0x33, 0xC0, 0x33, 0xF0, 0x76, 0xF8, 0xFC, 0xEF, 0x9A, 0x17, 0x01, 0x03,
|
||||
0xCF, 0x62, 0xF1, 0xED, 0x30, 0x09, 0x00, 0xB9, 0x3A, 0x0F, 0x3C, 0xFF, 0x81, 0xF0, 0x81, 0xF0,
|
||||
0x23, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x62, 0xF1, 0x62, 0xF1, 0x1E, 0xF0, 0xFF, 0xDF, 0x04, 0x06,
|
||||
0x4C, 0x06, 0xFC, 0x54, 0xF0, 0x06, 0xFC, 0x66, 0xF0, 0x4B, 0x30, 0xFC, 0x5C, 0x01, 0xEE, 0x02,
|
||||
0x68, 0x91, 0x06, 0x03, 0xA6, 0x95, 0x5F, 0xF1, 0x15, 0x00, 0x0F, 0x00, 0xFF, 0x09, 0x00, 0x11,
|
||||
0x94, 0x7B, 0x09, 0xA9, 0x02, 0x0E, 0x67, 0x5B, 0xF8, 0x06, 0x00, 0x15, 0x3C, 0xFF, 0x4C, 0xF5,
|
||||
0x81, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x24, 0xF0, 0x62, 0xF1, 0x62, 0xF1, 0xFF, 0x3C,
|
||||
0xF9, 0x3C, 0xF9, 0x0F, 0xF0, 0x27, 0xF0, 0x21, 0xF3, 0x1E, 0x00, 0x83, 0x91, 0x32, 0xF7, 0xFF,
|
||||
0x33, 0x30, 0x8A, 0xF9, 0x5F, 0x94, 0x0B, 0xF1, 0x7A, 0x01, 0x0C, 0x00, 0x62, 0xF1, 0x58, 0x02,
|
||||
0xFF, 0x5C, 0x01, 0x15, 0x3F, 0x24, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x24,
|
||||
0xF0, 0xFF, 0x08, 0xF1, 0x62, 0xF1, 0x72, 0xF6, 0x72, 0xF6, 0x0F, 0xF0, 0x24, 0xF0, 0x21, 0xF0,
|
||||
0xC4, 0x35, 0xFF, 0x33, 0xF0, 0x6A, 0xC8, 0xEC, 0xFA, 0x36, 0xC0, 0xCA, 0xF2, 0x3E, 0x01, 0x50,
|
||||
0xF1, 0xF0, 0x00, 0xFF, 0xC4, 0x92, 0x21, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x21, 0xF0, 0x62, 0xF1, 0xFF, 0x27, 0xF0, 0xDE, 0xF0, 0xDE, 0xF0, 0x0F, 0xF0, 0x21, 0xF0, 0x98,
|
||||
0xC1, 0x1E, 0x00, 0x33, 0xF0, 0xFF, 0xFE, 0xFA, 0xEE, 0xF2, 0x36, 0xF0, 0x2C, 0xF1, 0x3B, 0x01,
|
||||
0x1A, 0x91, 0x7F, 0xC5, 0x24, 0xF0, 0xFF, 0x57, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x24,
|
||||
0xF0, 0x27, 0xF0, 0x62, 0xF1, 0xDE, 0xF0, 0xFF, 0xDE, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x36, 0xF0, 0x62, 0xF1, 0x25, 0xFB, 0xFC, 0x03, 0xFF, 0x36, 0xF0, 0x51, 0xFC, 0xFF, 0x03, 0x1A,
|
||||
0xC1, 0x2E, 0xF5, 0x57, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x30, 0xF0, 0x27, 0xF0,
|
||||
0x62, 0xF1, 0x24, 0xF0, 0xDE, 0xF0, 0xDE, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x2D,
|
||||
0xF0, 0x62, 0xF1, 0x25, 0xF8, 0x33, 0xF0, 0x60, 0xF9, 0x1A, 0x91, 0xFF, 0x0C, 0x9F, 0x27, 0xF0,
|
||||
0x57, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x27, 0xF0, 0x27, 0xF0, 0xFF, 0x62, 0xF1, 0x38,
|
||||
0xF1, 0xDD, 0xF7, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x24, 0xF0, 0xFF, 0x91, 0xF5,
|
||||
0xFC, 0x33, 0x36, 0xF0, 0x39, 0xFF, 0x62, 0x01, 0x62, 0xF1, 0x2D, 0xF0, 0x81, 0xF0, 0xFF, 0x81,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x2D, 0xF0, 0x62, 0xF1, 0x62, 0xF1, 0x21, 0xF0, 0x4F, 0x7F, 0x18,
|
||||
0x38, 0xA1, 0x01, 0x05, 0x0F, 0xF0, 0x0F, 0xF0, 0x8A, 0xF0, 0xB4, 0xF9, 0x62, 0x01, 0xFE, 0xE9,
|
||||
0x6D, 0x1B, 0xF0, 0xAB, 0x9C, 0x0F, 0xF0, 0x09, 0x90, 0xA7, 0x9D, 0x34, 0x38, 0x62, 0xF1, 0xFF,
|
||||
0x2A, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x2A, 0xF0, 0x62, 0xF1, 0x62, 0xF1,
|
||||
0xFF, 0xD5, 0xF3, 0xE1, 0x60, 0xAB, 0xF3, 0x0F, 0xF0, 0x2D, 0xF0, 0xB2, 0xF5, 0x22, 0x0B, 0x96,
|
||||
0x3C, 0xFF, 0x1F, 0x5B, 0x45, 0xF0, 0x62, 0xF1, 0x0F, 0xF0, 0x25, 0xF0, 0x1A, 0xF1, 0x62, 0xF1,
|
||||
0x1F, 0xF0, 0xFF, 0x81, 0xF0, 0x2A, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x62, 0xF1, 0x62, 0xF1, 0x25,
|
||||
0xF0, 0xAB, 0xF3, 0xFF, 0x37, 0xF5, 0x86, 0xFA, 0x16, 0x92, 0xB1, 0x00, 0x50, 0xD4, 0x73, 0x3B,
|
||||
0x2D, 0xC0, 0x45, 0xF0, 0xFF, 0x82, 0x98, 0xFC, 0xC6, 0x0F, 0xF0, 0x1B, 0xF0, 0x62, 0xF1, 0x29,
|
||||
0xF0, 0x81, 0xF0, 0x81, 0xF0, 0xFF, 0x1E, 0xF0, 0x81, 0xF0, 0x27, 0xF0, 0x62, 0xF1, 0x62, 0xF1,
|
||||
0x6D, 0xF2, 0x34, 0x95, 0x38, 0x7F, 0x19, 0x01, 0x10, 0x39, 0xF0, 0xE6, 0xF4, 0x0D, 0x02, 0xCA,
|
||||
0xF5, 0xAC, 0x08, 0x02, 0x20, 0xFE, 0x2B, 0xF0, 0x62, 0xF1, 0x91, 0xF2, 0x0F, 0xF0, 0x1F, 0xF0,
|
||||
0x62, 0xF1, 0x2E, 0xF0, 0x81, 0xF0, 0xFF, 0x81, 0xF0, 0x22, 0xF0, 0x81, 0xF0, 0xC4, 0xD2, 0x62,
|
||||
0xF1, 0x62, 0xF1, 0x24, 0xF0, 0x46, 0xF2, 0xFF, 0xDA, 0x07, 0x03, 0x30, 0x33, 0xF0, 0x38, 0x19,
|
||||
0x1B, 0xF5, 0x01, 0x07, 0x1F, 0x92, 0x40, 0x12, 0x33, 0xF0, 0x30, 0xF0, 0x45, 0xF0, 0x56, 0x94,
|
||||
0x62, 0x01, 0x09, 0x90, 0xFF, 0x0F, 0xF0, 0x1B, 0xF0, 0x62, 0xF1, 0x2D, 0xF0, 0x81, 0xF0, 0x24,
|
||||
0xF0, 0x81, 0xF0, 0x5A, 0xF0, 0xFF, 0x27, 0xF0, 0x62, 0xF1, 0x62, 0xF1, 0x21, 0xF0, 0xEA, 0x02,
|
||||
0x1F, 0x24, 0xC0, 0x8F, 0x36, 0xF0, 0x87, 0xF3, 0x74, 0x14, 0xBD, 0x10, 0x62, 0xF1, 0x33, 0xF0,
|
||||
0x41, 0xC4, 0xF3, 0x62, 0x31, 0xE7, 0x96, 0x14, 0x97, 0x0F, 0xF0, 0x1B, 0xF0, 0x62, 0xF1, 0x51,
|
||||
0xF0, 0x81, 0xF0, 0xFF, 0x81, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x27, 0xF0, 0x62, 0xF1, 0x62, 0xF1,
|
||||
0x5A, 0xF0, 0x84, 0x7F, 0x12, 0xB1, 0xD3, 0xAE, 0x0C, 0xC0, 0x13, 0x90, 0x93, 0x0A, 0x05, 0x9F,
|
||||
0xC3, 0xF2, 0x86, 0xF1, 0xCA, 0xF2, 0x27, 0xF0, 0xB2, 0x35, 0x4D, 0xC1, 0x62, 0x01, 0x09, 0x90,
|
||||
0x0F, 0xF0, 0xFF, 0x18, 0xF0, 0x62, 0xF1, 0x4E, 0xF0, 0x81, 0xF0, 0x0F, 0xF0, 0x6C, 0xF0, 0x81,
|
||||
0xF0, 0x24, 0xF0, 0xFF, 0x62, 0xF1, 0x51, 0xF0, 0x5A, 0xF0, 0xBB, 0x0A, 0xE1, 0x70, 0xD8, 0xF0,
|
||||
0xDB, 0xF0, 0xE7, 0x0E, 0xF1, 0x4A, 0x04, 0x6C, 0xF0, 0x11, 0xF4, 0x5F, 0x01, 0x45, 0x00, 0x12,
|
||||
0x90, 0xB5, 0x02, 0xFF, 0x86, 0x01, 0x80, 0x01, 0x09, 0x90, 0x27, 0xF0, 0x29, 0x01, 0x5B, 0xC2,
|
||||
0x1A, 0xF1, 0x48, 0xF0, 0xFF, 0x81, 0xF0, 0x7E, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0x21, 0xF0, 0x62,
|
||||
0xF1, 0x0F, 0xF0, 0x3C, 0xF0, 0xFF, 0x02, 0x01, 0x0F, 0xF0, 0xCF, 0xF0, 0xF5, 0x01, 0x20, 0x3A,
|
||||
0x32, 0x15, 0xF0, 0xC7, 0x00, 0x00, 0x39, 0x60, 0x33, 0xF0, 0xEE, 0x02, 0x18, 0x00, 0x7F, 0x7F,
|
||||
0x7F, 0x1F, 0x45, 0x60, 0x3E, 0x91, 0x41, 0x01, 0xCB, 0xCB, 0xCB, 0x03, 0x30, 0x2A, 0xF0, 0xC7,
|
||||
0x20, 0x01, 0x0B, 0x01, 0x09, 0x00, 0x62, 0xC1, 0x62, 0xF1, 0x42, 0xF0, 0x81, 0xF0, 0x7E, 0xF0,
|
||||
0xFF, 0x81, 0xF0, 0x30, 0xF0, 0x62, 0xF1, 0x62, 0xF1, 0x0F, 0xF0, 0x36, 0xF0, 0x93, 0x10, 0x3F,
|
||||
0x1D, 0x03, 0x30, 0x09, 0x90, 0xD5, 0x90, 0xC6, 0x00, 0x14, 0xC1, 0x39, 0xF0, 0xE1, 0x7E, 0xE1,
|
||||
0xE1, 0x83, 0x91, 0x12, 0x00, 0x2A, 0x00, 0x24, 0x00, 0x39, 0x30, 0x21, 0x00, 0xFC, 0x45, 0x00,
|
||||
0x5F, 0x5F, 0x5F, 0x92, 0xF1, 0x15, 0x00, 0x47, 0x01, 0x35, 0x01, 0xF1, 0x37, 0x37, 0x37, 0x12,
|
||||
0x60, 0xA8, 0xA8, 0xA8, 0x00, 0x00, 0x88, 0x11, 0x01, 0x0C, 0x00, 0x62, 0xC1, 0x62, 0xF1, 0x0F,
|
||||
0xF0, 0x2D, 0xF0, 0x81, 0xF0, 0x81, 0xF0, 0xFF, 0x0F, 0xF0, 0x21, 0xF0, 0x74, 0x14, 0x1C, 0x3F,
|
||||
0x90, 0x4F, 0x18, 0x23, 0x45, 0x70, 0x0F, 0xF0, 0x2A, 0xF0, 0x12, 0x00, 0xC7, 0x07, 0x1E, 0x03,
|
||||
0x30, 0x8F, 0x00, 0x00, 0xFF, 0x00, 0x20, 0xDF, 0x04, 0x1F, 0xA1, 0x01, 0x0E, 0x1D, 0x62, 0x16,
|
||||
0x1C, 0x0F, 0xF0, 0x36, 0xF0, 0x21, 0x00, 0xE0, 0xD6, 0xD6, 0xD6, 0x39, 0x90, 0xB4, 0xB4, 0xB4,
|
||||
0x6F, 0x08, 0x6F, 0x6F, 0x0C, 0x60, 0xEB, 0xEB, 0xEB, 0x9B, 0x9B, 0x04, 0x9B, 0x00, 0x00, 0x27,
|
||||
0xF0, 0x12, 0x00, 0x0C, 0x00, 0x03, 0x30, 0x00, 0x00, 0x1B, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0x8D,
|
||||
0x8D, 0x8D, 0x18, 0xF0, 0x03, 0x00, 0xC0, 0xF5, 0xF5, 0xF5, 0x4C, 0x4C, 0x4C, 0x06, 0x60, 0x0F,
|
||||
0xF0, 0xC0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x68, 0xF1, 0x0C, 0xC0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00,
|
||||
0xAD, 0xAD, 0xAD, 0x09, 0x90, 0x8F, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x3F, 0xF0, 0x48, 0xF0, 0x15, 0x30, 0xFF, 0x6F, 0x60, 0x1E, 0x66, 0xD2, 0x00, 0x5B, 0x05,
|
||||
0x03, 0x30, 0x33, 0xF0, 0x17, 0xF1, 0x62, 0xF1, 0xFF, 0x0F, 0xF0, 0x15, 0xF0, 0x62, 0xF1, 0x1B,
|
||||
0xF0, 0x62, 0xF1, 0x0F, 0xF0, 0x0F, 0xF0, 0x15, 0xF0, 0xFF, 0x2B, 0xC5, 0x62, 0xF1, 0x25, 0xFB,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x33, 0xF0, 0x48, 0xF0, 0x0B, 0xC1, 0xFF, 0xE1, 0x63, 0x0F, 0xF0, 0x2D,
|
||||
0xF0, 0x9D, 0x92, 0x62, 0xF1, 0x0C, 0xC0, 0x18, 0xF0, 0x62, 0x91, 0xFF, 0x24, 0xF0, 0xA4, 0xF1,
|
||||
0xA6, 0x92, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x38, 0xF1, 0xB7, 0x93, 0xFF, 0x62, 0xF1, 0x9F,
|
||||
0x60, 0x26, 0x31, 0x27, 0x60, 0x93, 0x90, 0x5B, 0x68, 0x48, 0xC0, 0x5B, 0xF8, 0xFF, 0x99, 0xF0,
|
||||
0x5B, 0xF8, 0x7E, 0x90, 0x69, 0xC0, 0x62, 0xF1, 0x95, 0x34, 0x39, 0x90, 0x5B, 0x98, 0xFF, 0x81,
|
||||
0x00, 0x03, 0x00, 0x91, 0x65, 0x77, 0x31, 0x35, 0x34, 0x21, 0x30, 0xCA, 0x62, 0x4B, 0x30, 0xFF,
|
||||
0x25, 0x68, 0x5B, 0xF8, 0x8E, 0x92, 0x5C, 0xF1, 0x62, 0xF1, 0xF2, 0x67, 0x2A, 0x00, 0x5B, 0xC8,
|
||||
0xFF, 0x62, 0xF1, 0x33, 0x30, 0x60, 0x30, 0xC3, 0x36, 0xCF, 0x30, 0x56, 0x01, 0x91, 0x65, 0x91,
|
||||
0xF5, 0xFF, 0x48, 0xF0, 0x62, 0xF1, 0x91, 0xF5, 0x3C, 0x00, 0x36, 0x00, 0x63, 0x96, 0x46, 0xF5,
|
||||
0x62, 0xF1, 0xFF, 0xB8, 0x65, 0x6B, 0x31, 0x91, 0x65, 0x35, 0x34, 0x24, 0x00, 0x91, 0x95, 0xEC,
|
||||
0x34, 0x36, 0xC0, 0xFF, 0x14, 0x34, 0x3F, 0x90, 0x91, 0xC5, 0x39, 0x00, 0xF6, 0xF6, 0x56, 0xF1,
|
||||
0x62, 0xF1, 0x12, 0x00, 0xFF, 0x91, 0x65, 0x2D, 0x00, 0x62, 0xF1, 0x62, 0xF1, 0x1B, 0x00, 0x7B,
|
||||
0x66, 0xC7, 0x92, 0xC7, 0xF2, 0xFF, 0x48, 0xF0, 0x62, 0xF1, 0xC7, 0xF2, 0xCF, 0xF0, 0x7C, 0xF2,
|
||||
0x62, 0xF1, 0x40, 0x02, 0xC7, 0xF2, 0xFF, 0x85, 0xC2, 0xC7, 0x32, 0xA7, 0x34, 0xB1, 0x90, 0xD4,
|
||||
0x64, 0x2C, 0x64, 0xC7, 0xF2, 0x6F, 0x60, 0xFF, 0xB0, 0x64, 0xB5, 0xF2, 0x62, 0xF1, 0xC7, 0xF2,
|
||||
0xC7, 0xF2, 0x54, 0xF0, 0x62, 0xF1, 0x29, 0x61, 0xFF, 0x1A, 0x61, 0x03, 0x00, 0x1E, 0xF0, 0x62,
|
||||
0xF1, 0x27, 0xF0, 0x84, 0x30, 0x45, 0x60, 0x51, 0x30, 0xFF, 0x38, 0xF1, 0x62, 0xF1, 0x62, 0xF1,
|
||||
0x36, 0x00, 0x00, 0x00, 0x45, 0x90, 0x2D, 0x00, 0x5A, 0x00, 0xFF, 0xD5, 0x33, 0xFF, 0x90, 0xD1,
|
||||
0x01, 0x5D, 0x30, 0x62, 0xF1, 0x1B, 0xC0, 0x15, 0x30, 0x99, 0x30, 0xFF, 0xF3, 0x90, 0x33, 0x33,
|
||||
0x14, 0xC4, 0x62, 0xF1, 0x06, 0x60, 0x62, 0xC1, 0x54, 0xF0, 0x62, 0xF1, 0xFF, 0x03, 0x00, 0x93,
|
||||
0x00, 0xA8, 0x00, 0x12, 0x30, 0x09, 0x00, 0x03, 0x00, 0x48, 0xF0, 0x62, 0xF1, 0xFF, 0x62, 0xF1,
|
||||
0xCF, 0x30, 0xFE, 0xF4, 0x09, 0x03, 0xBF, 0x01, 0x38, 0x61, 0x62, 0xF1, 0x62, 0xF1, 0xFF, 0x24,
|
||||
0x30, 0x48, 0xC0, 0x62, 0x31, 0xCF, 0x00, 0xFF, 0x30, 0x62, 0x61, 0x26, 0xC1, 0x3F, 0x60, 0xFF,
|
||||
0x63, 0x60, 0x45, 0x00, 0x0F, 0xF0, 0x5C, 0xF1, 0x62, 0xF1, 0x2C, 0x94, 0x90, 0x30, 0x42, 0x00,
|
||||
0xFF, 0x62, 0xC1, 0x54, 0xF0, 0x62, 0xF1, 0x93, 0x30, 0x30, 0x00, 0x3F, 0x30, 0x09, 0x00, 0x03,
|
||||
0x00, 0xFF, 0x48, 0xF0, 0x62, 0xF1, 0x62, 0xF1, 0xE4, 0x30, 0xDD, 0x31, 0x57, 0x30, 0x03, 0x00,
|
||||
0x7B, 0x90, 0xFF, 0xF9, 0x30, 0x62, 0xF1, 0x62, 0xF1, 0x2D, 0x30, 0x2A, 0x00, 0xB7, 0x60, 0x3C,
|
||||
0x00, 0x62, 0x61, 0xFF, 0x39, 0x00, 0x7E, 0x60, 0xF6, 0x00, 0x62, 0x62, 0x62, 0xB4, 0x60, 0x54,
|
||||
0x00, 0xC7, 0x71, 0x31, 0x45, 0x00, 0xC6, 0x60, 0xAA, 0x31, 0xA2, 0x30, 0x41, 0x01, 0x0C, 0xC0,
|
||||
0x53, 0xF1, 0xFF, 0x62, 0xF1, 0x0C, 0x00, 0x18, 0x30, 0x2D, 0x00, 0x62, 0xC1, 0x54, 0x90, 0x2A,
|
||||
0x60, 0x48, 0x00, 0xFF, 0xBA, 0x60, 0x2D, 0x00, 0x93, 0x30, 0x1A, 0x61, 0xD2, 0x00, 0x1E, 0x30,
|
||||
0x48, 0xF0, 0x15, 0xC0, 0xFF, 0x33, 0x00, 0x6C, 0x00, 0x09, 0x60, 0x27, 0x60, 0x09, 0x00, 0xB3,
|
||||
0xB3, 0xB3, 0x1F, 0x0F, 0x00, 0x33, 0x00, 0xBA, 0x00, 0xAE, 0x60, 0x00, 0x00, 0x69, 0x30, 0xA2,
|
||||
0x00, 0x7B, 0xC0, 0xFF, 0x18, 0x00, 0x69, 0x60, 0x39, 0x00, 0x12, 0x00, 0x18, 0x00, 0x93, 0x00,
|
||||
0x0F, 0x00, 0x21, 0x30, 0xFF, 0x93, 0x93, 0x93, 0x8A, 0x00, 0x12, 0x00, 0x09, 0x00, 0xCB, 0x61,
|
||||
0x1E, 0x00, 0xF8, 0x12, 0x30, 0x21, 0x60, 0x69, 0x00, 0x4A, 0x4A, 0x4A, 0x09, 0x00, 0x18, 0x00,
|
||||
0xC7, 0x0C, 0x00, 0x9B, 0x9B, 0x9B, 0x12, 0x30, 0x81, 0x81, 0x81, 0x11, 0x3C, 0x60, 0x57, 0x57,
|
||||
0x57, 0x0F, 0xF0, 0x33, 0xF0, 0x8A, 0x8A, 0x31, 0x8A, 0x6D, 0x6D, 0x6D, 0x62, 0x31, 0x06, 0x00,
|
||||
0x00, 0x00, 0xBB, 0x70, 0xBB, 0xBB, 0xA4, 0xA4, 0xA4, 0x2D, 0x2D, 0x2D, 0x00, 0x06, 0x00, 0x3D,
|
||||
0x3D, 0x3D, 0xAC, 0xAC, 0xAC, 0x00, 0x00, 0x81, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x18, 0xF0, 0x62, 0xF1,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x15, 0xF0, 0x00, 0x00, 0x77, 0x7F, 0x77, 0x77, 0x0C, 0xC0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFC, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0,
|
||||
0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F,
|
||||
0xF0, 0x0F, 0xF0, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00, 0x1B, 0x1B, 0x1B, 0x1F, 0xFF, 0xFF, 0xFF,
|
||||
0x0C, 0x0C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x71, 0x43, 0x00, 0x00
|
||||
};
|
||||
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
|
||||
// 68 x 192 @8bpp Grayscale RAW.
|
||||
#define X_BOOTLOGO 68
|
||||
#define Y_BOOTLOGO 192
|
||||
#define SZ_BOOTLOGO 13056
|
||||
#define SZ_BOOTLOGO_BLZ 3988
|
||||
static u8 BOOTLOGO_BLZ[SZ_BOOTLOGO_BLZ] = {
|
||||
0x0F, 0xF0, 0x80, 0x1B, 0x1B, 0x40, 0xF0, 0x1E, 0x1F, 0x48, 0x5A, 0x0F, 0xF0, 0x0F, 0xF0, 0xE4,
|
||||
0x17, 0xF0, 0x91, 0x13, 0x26, 0x28, 0x23, 0x1E, 0x0A, 0xA0, 0x0F, 0xF0, 0xC3, 0x22, 0xF0, 0xC3,
|
||||
0xA4, 0x1E, 0x29, 0x33, 0xDB, 0x2C, 0xEA, 0x53, 0x83, 0x0F, 0xF0, 0x38, 0xF0, 0xBC, 0x39, 0x21,
|
||||
0x22, 0xB0, 0x87, 0x20, 0x2F, 0x27, 0x3E, 0xDB, 0x35, 0x01, 0xA6, 0x69, 0xF2, 0x3C, 0xFD, 0x25,
|
||||
0x2D, 0x38, 0x77, 0x28, 0x15, 0x8A, 0x33, 0x45, 0xDB, 0x09, 0xEF, 0xBB, 0x44, 0xD0, 0xC0, 0x18,
|
||||
0xEF, 0x2E, 0x3B, 0xF5, 0x32, 0x25, 0x41, 0xC0, 0x83, 0x52, 0xE1, 0x07, 0xCD, 0x08, 0xF4, 0xF5,
|
||||
0x3B, 0x61, 0xB2, 0x95, 0xF1, 0x01, 0x10, 0xE7, 0xA3, 0x02, 0x95, 0x91, 0x3C, 0xFD, 0x41, 0x90,
|
||||
0x41, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x7F, 0x3D, 0x9B, 0xFA, 0x41, 0xF0, 0x41, 0xF0, 0x0F,
|
||||
0xF0, 0x26, 0xF0, 0x41, 0xF0, 0x41, 0xF0, 0xFE, 0x4C, 0xF0, 0x41, 0xF0, 0x41, 0xF0, 0x4D, 0xF5,
|
||||
0x95, 0x01, 0x9B, 0x02, 0xCD, 0x5D, 0x41, 0xF0, 0xFF, 0x41, 0xF0, 0x4D, 0xF5, 0x77, 0xC5, 0x18,
|
||||
0x93, 0xCD, 0x8D, 0x41, 0xF0, 0x41, 0xF0, 0xEB, 0x4D, 0xF5, 0x69, 0xFB, 0x6C, 0xF4, 0x41, 0xF0,
|
||||
0x4D, 0xF5, 0x65, 0x3F, 0x28, 0x01, 0x10, 0xBF, 0x03, 0x30, 0x00, 0x00, 0x2A, 0x2A, 0x2A, 0x30,
|
||||
0x45, 0x57, 0x03, 0xE4, 0x03, 0x41, 0xB0, 0xCD, 0xFD, 0x5D, 0x02, 0xCD, 0x1D, 0xC9, 0x1C, 0x2C,
|
||||
0x38, 0x3F, 0x3F, 0x01, 0x10, 0x03, 0x30, 0x00, 0x00, 0x41, 0x41, 0x41, 0x48, 0x0E, 0x56, 0x61,
|
||||
0xF5, 0x41, 0xED, 0xDF, 0xCD, 0xFD, 0x3D, 0xBB, 0x30, 0x2D, 0x6D, 0xB3, 0x6D, 0x4D, 0x15, 0x38,
|
||||
0x01, 0x10, 0xE1, 0xF6, 0xD0, 0x3C, 0x27, 0x41, 0xB0, 0xCD, 0xFD, 0xA4, 0xCD, 0x2D, 0xF0, 0x4E,
|
||||
0x6F, 0x6C, 0x01, 0x10, 0x03, 0x30, 0x00, 0x00, 0x73, 0x73, 0x73, 0x74, 0x75, 0x07, 0x72, 0x68,
|
||||
0x31, 0x22, 0x41, 0xD0, 0xA4, 0xF2, 0xCD, 0x3D, 0xE6, 0x1E, 0xF0, 0x36, 0x3D, 0x02, 0x20, 0x03,
|
||||
0x30, 0x00, 0x00, 0x40, 0x40, 0x40, 0x1C, 0x3F, 0x3A, 0x31, 0x84, 0x89, 0x21, 0x41, 0xF0, 0xB8,
|
||||
0xCB, 0x20, 0x68, 0x23, 0x26, 0x28, 0x2A, 0x2C, 0x2F, 0x2F, 0x2E, 0x00, 0x2B, 0x28, 0x28, 0x01,
|
||||
0x10, 0x27, 0x27, 0x27, 0x27, 0x08, 0x26, 0x24, 0x21, 0x08, 0x85, 0x41, 0xF0, 0xCB, 0xF8, 0x21,
|
||||
0x28, 0x38, 0x2F, 0x35, 0x38, 0x39, 0x36, 0x31, 0x2B, 0x24, 0x00, 0x1F, 0x1D, 0x01, 0x10, 0x1C,
|
||||
0x1C, 0x1C, 0xC3, 0x50, 0x41, 0xF0, 0xC4, 0x39, 0xF8, 0x40, 0x20, 0x2D, 0x3A, 0x56, 0xA8, 0xBE,
|
||||
0xBE, 0x03, 0xBE, 0xA7, 0x63, 0x34, 0x42, 0x40, 0x41, 0xF0, 0xB1, 0xF7, 0xA8, 0x02, 0xF0, 0xE5,
|
||||
0x06, 0x77, 0xB3, 0x8A, 0x08, 0x25, 0x30, 0x41, 0xAA, 0x11, 0xED, 0xD3, 0xAC, 0xA1, 0xAD, 0xCA,
|
||||
0xF5, 0xB2, 0x00, 0x39, 0x37, 0x33, 0x41, 0xF0, 0x41, 0xF0, 0x50, 0x49, 0x6D, 0x71, 0x03, 0x1B,
|
||||
0x5E, 0x20, 0x2D, 0x41, 0xAB, 0xE4, 0x80, 0x4E, 0x48, 0x00, 0x46, 0x4A, 0x53, 0x77, 0xE4, 0xBD,
|
||||
0x35, 0x24, 0x00, 0x44, 0x94, 0x41, 0xF0, 0x4D, 0xF5, 0x09, 0x15, 0x26, 0x3A, 0x7C, 0xF5, 0x0F,
|
||||
0x7F, 0x45, 0x37, 0x30, 0x2F, 0x32, 0x3F, 0x51, 0x00, 0x78, 0xF5, 0x74, 0x2D, 0xAE, 0x32, 0x41,
|
||||
0xF0, 0x4D, 0xF5, 0x9D, 0x6A, 0xF0, 0x1F, 0x2D, 0x45, 0xC1, 0xC1, 0x47, 0x30, 0x23, 0x00, 0x1F,
|
||||
0x1F, 0x21, 0x2A, 0x3D, 0x54, 0xC1, 0xBE, 0x00, 0x35, 0x22, 0x01, 0x10, 0x41, 0xF0, 0xA5, 0xF2,
|
||||
0x3D, 0x44, 0x15, 0x0A, 0x20, 0x7C, 0x33, 0x4C, 0xED, 0x88, 0x39, 0x24, 0x84, 0x10, 0x1F, 0x40,
|
||||
0x2F, 0x49, 0x8D, 0xED, 0x3B, 0x44, 0x0D, 0x41, 0xF0, 0x41, 0xF0, 0xE0, 0x64, 0x02, 0x27, 0x0B,
|
||||
0xBB, 0xB3, 0xB5, 0x13, 0x21, 0x37, 0x4F, 0x13, 0xF5, 0x49, 0x30, 0xED, 0x21, 0x1D, 0x28, 0x40,
|
||||
0x55, 0x08, 0xF5, 0x3F, 0x15, 0x40, 0x41, 0xF0, 0x2D, 0xF3, 0xAF, 0x07, 0x2D, 0x41, 0x50, 0xBC,
|
||||
0x42, 0x2C, 0xB8, 0x32, 0x24, 0x3B, 0x52, 0xF5, 0x40, 0x04, 0xB1, 0xF7, 0x1B, 0x41, 0xF0, 0x41,
|
||||
0xF0, 0x41, 0x41, 0xD0, 0x41, 0xF0, 0x41, 0xF0, 0xED, 0x79, 0xF7, 0x41, 0xF0, 0x41, 0xF0, 0xD0,
|
||||
0xD9, 0x8A, 0x8A, 0x8A, 0x8A, 0x0F, 0x8A, 0x93, 0xAC, 0x09, 0x50, 0x29, 0xB7, 0xF9, 0xF3, 0x41,
|
||||
0xF0, 0x8C, 0x0D, 0xF8, 0x81, 0x1F, 0x0F, 0x81, 0xBB, 0x81, 0x41, 0x10, 0x50, 0xF5, 0x22, 0x45,
|
||||
0x30, 0x70, 0x33, 0x29, 0x3F, 0x54, 0xF5, 0x46, 0x04, 0x30, 0x72, 0x23, 0x20, 0x71, 0xE3, 0xA5,
|
||||
0xF2, 0x3D, 0x20, 0x77, 0x9B, 0x3A, 0xAD, 0x16, 0x52, 0xF5, 0x52, 0x09, 0x00, 0x07, 0x10, 0x3B,
|
||||
0x4E, 0x31, 0x61, 0xF5, 0x54, 0x41, 0x35, 0x35, 0x35, 0x35, 0x00, 0x34, 0x30, 0x29, 0x21, 0x0D,
|
||||
0xF1, 0x41, 0xF0, 0x11, 0x4E, 0x36, 0x70, 0x50, 0xF5, 0xAF, 0x09, 0x00, 0x07, 0x10, 0xAA, 0xAF,
|
||||
0xB4, 0x18, 0xF5, 0xB1, 0xAC, 0xA9, 0xA9, 0xA9, 0xA9, 0xA8, 0x00, 0xA5, 0xA2, 0x99, 0xCE, 0x1D,
|
||||
0xF2, 0xA1, 0x22, 0x11, 0x3E, 0x30, 0x46, 0x3C, 0xC1, 0xC2, 0x09, 0x10, 0x06, 0x10, 0xC2, 0xC4,
|
||||
0xC5, 0xC3, 0x0C, 0xC1, 0xC0, 0xC0, 0xC0, 0xC0, 0xBF, 0xBD, 0xBA, 0x00, 0x2A, 0x41, 0xB0, 0x6D,
|
||||
0xF7, 0x41, 0x00, 0x8A, 0xA4, 0x3D, 0x8A, 0x0E, 0xA4, 0x95, 0x01, 0x27, 0x35, 0x43, 0x49, 0x09,
|
||||
0x00, 0x07, 0x10, 0xC2, 0x49, 0x4B, 0x4E, 0x4F, 0x4C, 0x49, 0x48, 0x48, 0x00, 0x48, 0x48, 0x46,
|
||||
0x40, 0x34, 0x51, 0x91, 0x41, 0xF0, 0x01, 0x10, 0xE0, 0xC7, 0x00, 0x9B, 0xBB, 0xB3, 0x4A, 0xC9,
|
||||
0x10, 0x25, 0x2C, 0x21, 0x01, 0x10, 0x06, 0x30, 0x31, 0x31, 0x31, 0x00, 0x00, 0x30, 0x30, 0x23,
|
||||
0x30, 0x2C, 0x27, 0xC9, 0x00, 0x41, 0xF0, 0xA1, 0xF2, 0x42, 0x40, 0x06, 0x60, 0xF8, 0x03, 0x30,
|
||||
0x00, 0x00, 0x1F, 0xDD, 0xA6, 0x41, 0xF0, 0xBF, 0xF3, 0x02, 0x20, 0xCD, 0xFD, 0xFB, 0x95, 0xF1,
|
||||
0x17, 0xD6, 0x62, 0x6D, 0x62, 0x2D, 0x90, 0x48, 0x29, 0x43, 0x2E, 0x03, 0x30, 0x03, 0x30, 0x00,
|
||||
0x00, 0x2F, 0x2F, 0x2F, 0x2B, 0x0E, 0x7D, 0xF8, 0x95, 0xF1, 0xB3, 0x9B, 0xAC, 0x95, 0x21, 0x1D,
|
||||
0x23, 0x23, 0x2F, 0x60, 0x66, 0x02, 0x20, 0x03, 0x30, 0x00, 0x00, 0x68, 0x68, 0x38, 0x68, 0x67,
|
||||
0x63, 0x5B, 0x27, 0x85, 0x10, 0x41, 0xF0, 0x0D, 0xF1, 0xE0, 0x39, 0x03, 0x28, 0x39, 0x07, 0x70,
|
||||
0x03, 0x30, 0x00, 0x00, 0xF5, 0xF5, 0x39, 0xF5, 0x2C, 0x20, 0x41, 0x90, 0x41, 0xF0, 0x27, 0x1B,
|
||||
0x25, 0x2B, 0xF5, 0x17, 0xF8, 0x34, 0x44, 0x4F, 0x02, 0x20, 0x03, 0x30, 0x00, 0x00, 0x52, 0x52,
|
||||
0x38, 0x52, 0x51, 0x49, 0x3A, 0x29, 0xE0, 0x12, 0x41, 0xF0, 0x2D, 0xF3, 0xE0, 0x42, 0x00, 0x20,
|
||||
0x28, 0x31, 0x38, 0x03, 0x30, 0x03, 0x30, 0x00, 0x00, 0xE1, 0x39, 0x39, 0x39, 0x34, 0x2C, 0x23,
|
||||
0xA9, 0xBF, 0xE9, 0xF2, 0xC0, 0xAC, 0x32, 0x4A, 0xBB, 0x3B, 0x27, 0x20, 0x21, 0xAC, 0xCF, 0x22,
|
||||
0x49, 0x22, 0xA9, 0xFF, 0xB5, 0xF3, 0xEA, 0x2F, 0x57, 0xAC, 0xAD, 0x63, 0x38, 0xF0, 0xCE, 0x41,
|
||||
0xF0, 0xDD, 0xFE, 0xA4, 0x9B, 0xA4, 0xBB, 0x81, 0x06, 0x60, 0x83, 0x37, 0xF0, 0x41, 0xF0, 0xD6,
|
||||
0xF5, 0xC3, 0x00, 0xD4, 0xC5, 0x1D, 0xF0, 0x41, 0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0x19, 0xF0,
|
||||
0x41, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x2D, 0xF0, 0x41, 0xF0, 0x03, 0x30, 0xFF, 0x00, 0x00, 0x6D,
|
||||
0x6D, 0xD9, 0xC1, 0x33, 0xF0, 0x41, 0xF0, 0x15, 0xFA, 0x03, 0x30, 0xF9, 0x23, 0xF0, 0x41, 0xF0,
|
||||
0x41, 0xF0, 0x19, 0xF0, 0xE2, 0x3F, 0x20, 0x91, 0xAD, 0x1B, 0x5F, 0x41, 0xF0, 0x24, 0xF0, 0xA6,
|
||||
0xD2, 0x24, 0x2A, 0x56, 0x26, 0x61, 0xD2, 0x87, 0x41, 0xF0, 0xF8, 0xCC, 0xD9, 0xC1, 0x2C, 0x39,
|
||||
0xF5, 0x31, 0x24, 0x07, 0x15, 0x90, 0x41, 0xF0, 0xA5, 0xF2, 0x15, 0xD0, 0x46, 0xF5, 0x15, 0x10,
|
||||
0x41, 0xF0, 0xCF, 0xE5, 0xF6, 0x57, 0xBB, 0x00, 0x00, 0x57, 0x57, 0x57, 0x77, 0x09, 0x7D, 0xC0,
|
||||
0x22, 0x38, 0x4D, 0xF5, 0x3F, 0xC9, 0x50, 0x41, 0xF0, 0xC1, 0xBC, 0xBC, 0xBB, 0x00, 0x00, 0xAC,
|
||||
0xAC, 0xAC, 0xA4, 0xA5, 0x92, 0x85, 0x41, 0xF0, 0x41, 0xF0, 0xD9, 0xF1, 0x41, 0xF0, 0x39, 0x4F,
|
||||
0xF5, 0x40, 0x0F, 0xCE, 0x14, 0x41, 0xF0, 0x41, 0xF0, 0xD5, 0x3D, 0x85, 0xF5, 0x37, 0x4B, 0xF5,
|
||||
0x1F, 0x3E, 0x46, 0x74, 0x41, 0xF0, 0x26, 0xF0, 0x15, 0xF0, 0x32, 0x44, 0xF5, 0x1E, 0x39, 0xEE,
|
||||
0x76, 0x1B, 0x41, 0xF0, 0xA5, 0xF2, 0x6D, 0xFC, 0x36, 0x7C, 0x3A, 0x2F, 0x23, 0x15, 0xB0, 0x41,
|
||||
0xF0, 0xA5, 0xF2, 0x71, 0xAB, 0x22, 0x28, 0x3C, 0x2A, 0x25, 0x1F, 0x15, 0x90, 0x41, 0xF0, 0xA5,
|
||||
0xF2, 0x11, 0xC0, 0x6E, 0x0C, 0xF8, 0xE3, 0xAE, 0x41, 0xF0, 0xA5, 0xF2, 0x41, 0xC0, 0x33, 0xF0,
|
||||
0x41, 0xF0, 0xA5, 0xF2, 0x0B, 0xB0, 0xFF, 0x33, 0xF0, 0x41, 0xF0, 0xA5, 0xF2, 0x0B, 0xB0, 0x33,
|
||||
0xF0, 0x41, 0xF0, 0xA5, 0xF2, 0x0A, 0xA0, 0xFF, 0x33, 0xF0, 0x41, 0xF0, 0xA5, 0xF2, 0x09, 0x90,
|
||||
0x1E, 0xF0, 0x41, 0xF0, 0xA5, 0xF2, 0x04, 0x40, 0xFF, 0x25, 0xF0, 0xD5, 0xF5, 0x41, 0xF0, 0x53,
|
||||
0xF2, 0x85, 0xFE, 0x4D, 0xF5, 0xE3, 0xFA, 0x81, 0x7F, 0x8A, 0x81, 0xA9, 0x3B, 0x1E, 0x21, 0x26,
|
||||
0x26, 0x23, 0x04, 0x1F, 0x1C, 0x33, 0xAD, 0x24, 0x28, 0x29, 0x26, 0x05, 0x89, 0x84, 0x41, 0xF0,
|
||||
0x47, 0x20, 0xB3, 0x93, 0x77, 0x8A, 0xB3, 0xA4, 0x03, 0x2D, 0x81, 0x24, 0x40, 0x41, 0x39, 0x28,
|
||||
0x1F, 0xCB, 0x18, 0x82, 0x21, 0x21, 0x20, 0x1E, 0x1B, 0x2A, 0x24, 0x68, 0x6A, 0x20, 0x62, 0x2B,
|
||||
0x3D, 0xA4, 0x41, 0xF0, 0x93, 0xA4, 0x58, 0x16, 0x2D, 0x4C, 0xA4, 0x93, 0x10, 0x10, 0x4C, 0x10,
|
||||
0x10, 0x23, 0x84, 0x09, 0x2B, 0x54, 0x35, 0x37, 0xBB, 0x07, 0x96, 0x1F, 0x4F, 0x2E, 0x00, 0x39,
|
||||
0x24, 0x2C, 0x41, 0xA0, 0x41, 0xF0, 0x55, 0x31, 0x3D, 0x2D, 0x23, 0x63, 0x18, 0x29, 0x34, 0x04,
|
||||
0xD7, 0x41, 0xC7, 0xC8, 0xC4, 0x31, 0x21, 0x0E, 0x5F, 0x46, 0x40, 0xA1, 0xB6, 0x55, 0xFE, 0x9A,
|
||||
0x52, 0x10, 0x70, 0x34, 0x64, 0xB2, 0x14, 0x6E, 0x2E, 0x00, 0xBF, 0x4D, 0xA5, 0xB2, 0x65, 0xFF,
|
||||
0xA5, 0x36, 0x6D, 0xAC, 0x10, 0x70, 0x34, 0x64, 0xCE, 0x2E, 0x40, 0x41, 0xF0, 0xD2, 0xD9, 0xBB,
|
||||
0x77, 0x2D, 0x1B, 0x2D, 0x07, 0x77, 0xBB, 0x6D, 0x10, 0x70, 0x34, 0x64, 0x2E, 0x40, 0x41, 0xF0,
|
||||
0x08, 0xE9, 0xF8, 0x98, 0x1E, 0xAC, 0x62, 0x41, 0xC0, 0x41, 0xF0, 0x41, 0xF0, 0x77, 0xC8, 0x41,
|
||||
0x60, 0xF9, 0x41, 0xF0, 0x41, 0xF0, 0x41, 0xF0, 0xB5, 0xF3, 0x07, 0x60, 0xA2, 0xF3, 0x41, 0xF0,
|
||||
0x71, 0xF3, 0xFF, 0x06, 0x20, 0x07, 0x40, 0x55, 0x32, 0x24, 0x24, 0x2B, 0x47, 0x03, 0x44, 0x09,
|
||||
0x41, 0xF0, 0x47, 0xBD, 0x8A, 0x81, 0x4A, 0x1B, 0x77, 0x07, 0xB3, 0xBB, 0xD5, 0x55, 0x06, 0x20,
|
||||
0x07, 0x40, 0x6B, 0x44, 0x05, 0x46, 0x5C, 0x5E, 0xBC, 0x08, 0x41, 0xF0, 0xC8, 0xB4, 0x93, 0x73,
|
||||
0x07, 0xAC, 0x62, 0x2E, 0x3D, 0x6D, 0xAC, 0x3D, 0x34, 0x06, 0x20, 0x07, 0x40, 0xD1, 0xCF, 0x38,
|
||||
0xCD, 0xCD, 0xCF, 0xD1, 0xD2, 0x41, 0xC0, 0x91, 0xF5, 0x77, 0x60, 0x80, 0x14, 0x8D, 0x15, 0x57,
|
||||
0xBB, 0xA5, 0x32, 0x40, 0xF0, 0x92, 0x52, 0x41, 0xF0, 0xF3, 0x41, 0xF0, 0x1D, 0x02, 0x3E, 0x6D,
|
||||
0x01, 0x10, 0x3D, 0xF0, 0x4C, 0x0A, 0x12, 0xB3, 0x41, 0xF0, 0x41, 0xF0, 0xF1, 0x1B, 0x61, 0x01,
|
||||
0x10, 0x29, 0xF3, 0x44, 0x21, 0x8F, 0xB7, 0x41, 0xF0, 0x03, 0x20, 0x61, 0x5B, 0x1F, 0x21, 0xFF,
|
||||
0x21, 0xFF, 0xD5, 0xF5, 0x03, 0x20, 0xF7, 0xAE, 0x27, 0xBB, 0x1B, 0xF6, 0x1F, 0x47, 0x51, 0x52,
|
||||
0x50, 0x09, 0x21, 0xAF, 0x4E, 0x4E, 0x4B, 0x44, 0x38, 0x65, 0x2F, 0x41, 0xF0, 0xC1, 0xB1, 0xF7,
|
||||
0x51, 0x04, 0x25, 0x32, 0x41, 0x45, 0x3F, 0x34, 0x03, 0x21, 0x0F, 0x03, 0x30, 0x00, 0x00, 0x1E,
|
||||
0x0F, 0x29, 0x28, 0x24, 0x02, 0x6A, 0x8F, 0x41, 0xF0, 0x45, 0xFD, 0x42, 0x34, 0x0F, 0x34, 0x24,
|
||||
0x01, 0x10, 0x03, 0x30, 0xCB, 0x00, 0x00, 0x1D, 0x35, 0x59, 0x41, 0xF0, 0x19, 0xF0, 0x34, 0xBF,
|
||||
0x1B, 0xF0, 0x41, 0xF0, 0xFD, 0x19, 0xF0, 0xB5, 0x83, 0x1E, 0xF0, 0x41, 0xF0, 0x1C, 0xF0, 0x21,
|
||||
0x9F, 0x2D, 0x83, 0x15, 0xF0, 0xFF, 0x41, 0xF0, 0x41, 0xF0, 0xA5, 0xF2, 0x91, 0xD5, 0x41, 0xF0,
|
||||
0x41, 0xF0, 0x57, 0x34, 0x3F, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x26, 0x26, 0x26, 0x24, 0x21,
|
||||
0x07, 0x1E, 0x1C, 0x41, 0x80, 0x51, 0xF1, 0x99, 0xFE, 0x6D, 0x51, 0x04, 0x40, 0x9C, 0x45, 0x00,
|
||||
0x00, 0x45, 0x45, 0x45, 0x43, 0x3D, 0x32, 0x02, 0x26, 0x01, 0xDD, 0x38, 0xAC, 0xAA, 0x83, 0x41,
|
||||
0x50, 0xE1, 0xE1, 0x04, 0x40, 0x9E, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xDF, 0xDE, 0xDA, 0x02,
|
||||
0x34, 0x22, 0x41, 0xC0, 0xC4, 0xA8, 0x4A, 0xB2, 0x73, 0x41, 0x50, 0x3E, 0xF0, 0xEC, 0x85, 0xF0,
|
||||
0xCD, 0xB0, 0x81, 0xDB, 0x31, 0x8A, 0xBB, 0x77, 0x41, 0x50, 0x8B, 0x3E, 0xF0, 0x69, 0xFB, 0xCA,
|
||||
0xD0, 0x57, 0xB2, 0x13, 0x9B, 0x3D, 0x65, 0x7F, 0x97, 0xDD, 0xFA, 0x41, 0xE1, 0xFA, 0xC7, 0xC0,
|
||||
0x8A, 0x9B, 0xB3, 0x6D, 0x0D, 0x41, 0x80, 0x7E, 0x76, 0x04, 0x40, 0x70, 0x00, 0x00, 0x70, 0x70,
|
||||
0x29, 0x70, 0x6E, 0x63, 0x4C, 0x35, 0xCC, 0x51, 0xF1, 0x81, 0xBB, 0x30, 0xBB, 0x6D, 0x01, 0x9D,
|
||||
0x6A, 0x4C, 0x04, 0x40, 0x40, 0x00, 0x00, 0xA4, 0x40, 0xD1, 0xD9, 0x41, 0xF0, 0xF5, 0x0F, 0xA4,
|
||||
0xAC, 0x62, 0x77, 0x0E, 0xE7, 0x02, 0xBD, 0x7C, 0x54, 0x30, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00,
|
||||
0x22, 0x73, 0x22, 0x22, 0x21, 0x1F, 0xA5, 0xD2, 0x2D, 0xF3, 0x5F, 0x32, 0x79, 0x8C, 0xF0, 0x3A,
|
||||
0xD1, 0x1C, 0xF7, 0x83, 0x21, 0x2D, 0xF3, 0xAC, 0x57, 0xD7, 0x41, 0x95, 0xB3, 0x9B, 0x35, 0x1C,
|
||||
0xF1, 0x1B, 0x4F, 0x70, 0x46, 0x85, 0x61, 0x27, 0x6C, 0x25, 0x20, 0x6D, 0xD7, 0xD8, 0xA5, 0xCA,
|
||||
0x79, 0x9B, 0x7C, 0x7B, 0xB8, 0x70, 0xDC, 0xBD, 0x04, 0x34, 0x3E, 0x41, 0x80, 0x2B, 0xE5, 0x56,
|
||||
0x41, 0xF0, 0xC1, 0x05, 0xF9, 0x59, 0xF0, 0xF0, 0xEF, 0xDC, 0x60, 0x1D, 0x20, 0x21, 0x09, 0x05,
|
||||
0x4A, 0x6B, 0xB9, 0xE6, 0xFF, 0x39, 0xC9, 0x10, 0x81, 0x41, 0xF0, 0x3B, 0xF0, 0x59, 0x2A, 0x54,
|
||||
0x58, 0x49, 0x30, 0x21, 0x07, 0xC1, 0x50, 0x81, 0x04, 0xA4, 0x17, 0x26, 0xC5, 0x24, 0x41, 0xF0,
|
||||
0xC3, 0xF0, 0xF5, 0x17, 0xFB, 0x29, 0x32, 0x33, 0x2E, 0x24, 0x1E, 0xC1, 0x50, 0x7C, 0x40, 0xBC,
|
||||
0x80, 0x30, 0x09, 0xF5, 0xAC, 0xCF, 0xA9, 0x6F, 0x85, 0x20, 0x1F, 0x1F, 0x3E, 0x1F, 0xD3, 0x19,
|
||||
0x2F, 0x39, 0x49, 0xC1, 0x00, 0x2C, 0x63, 0x71, 0xE3, 0xE2, 0x5F, 0xBA, 0x00, 0x00, 0x5A, 0x0A,
|
||||
0x4A, 0x93, 0xBB, 0x77, 0x76, 0x53, 0x87, 0x24, 0x2B, 0x35, 0x42, 0x52, 0x98, 0xC1, 0x60, 0xF1,
|
||||
0x40, 0xC0, 0x90, 0x4D, 0xE9, 0xF2, 0x1B, 0x1B, 0xCE, 0xF9, 0x9B, 0x48, 0x3D, 0xEE, 0x32, 0x22,
|
||||
0x28, 0x31, 0x3E, 0x4D, 0x7B, 0x02, 0xBC, 0xF0, 0x1C, 0x62, 0xA6, 0x6C, 0x55, 0x42, 0x61, 0xF2,
|
||||
0x84, 0xD2, 0xF9, 0x93, 0xB3, 0x54, 0x1A, 0x45, 0x2D, 0x37, 0x47, 0x69, 0x19, 0xB0, 0xE0, 0x94,
|
||||
0x51, 0xDA, 0x36, 0x00, 0x6A, 0x45, 0x30, 0x14, 0x27, 0x21, 0x91, 0xA5, 0x41, 0xF0, 0xBF, 0x1C,
|
||||
0x93, 0x3D, 0x51, 0x61, 0x9C, 0x92, 0xCF, 0xF8, 0x3E, 0x60, 0x88, 0x7F, 0x51, 0x11, 0x30, 0x48,
|
||||
0x1F, 0x1D, 0x41, 0xF0, 0x4D, 0xC9, 0x9B, 0xAC, 0x62, 0xA1, 0x66, 0x8C, 0x32, 0x56, 0x11, 0x41,
|
||||
0xDA, 0xB7, 0x7C, 0x5F, 0x55, 0x04, 0x62, 0xC9, 0x10, 0x50, 0x41, 0x00, 0x41, 0xF0, 0x93, 0xB5,
|
||||
0xBB, 0x81, 0x3A, 0xC6, 0x54, 0x41, 0x60, 0xF8, 0xC1, 0x8A, 0x77, 0x5F, 0x4A, 0x03, 0x39, 0x35,
|
||||
0x41, 0x60, 0x41, 0xF0, 0x84, 0xA4, 0xBB, 0x9B, 0xD5, 0x65, 0x9C, 0x2D, 0x13, 0x89, 0x4D, 0xDA,
|
||||
0xAC, 0x6E, 0x49, 0x39, 0x34, 0x03, 0x49, 0x74, 0x41, 0x40, 0x41, 0xF0, 0xE0, 0xFE, 0x4D, 0x55,
|
||||
0x1F, 0x32, 0x3C, 0x57, 0xD1, 0xD1, 0x40, 0xF8, 0xD6, 0x9E, 0x52, 0x61, 0x04, 0x7C, 0xC6, 0xA8,
|
||||
0x41, 0xF0, 0x3B, 0xF0, 0x1D, 0x12, 0x3E, 0x5B, 0x80, 0x1E, 0xD1, 0x60, 0xF8, 0xD1, 0xB0, 0x3A,
|
||||
0x00, 0x55, 0x2F, 0x14, 0x8E, 0x91, 0x1B, 0x41, 0xF0, 0x95, 0xF1, 0x29, 0x38, 0xD1, 0x00, 0x8F,
|
||||
0xC1, 0x26, 0xF1, 0x8A, 0x75, 0x69, 0x43, 0x2F, 0x27, 0x21, 0x42, 0x30, 0x82, 0x41, 0xF0, 0x3A,
|
||||
0xF0, 0x68, 0x2B, 0xD1, 0x90, 0x98, 0x22, 0xB9, 0x72, 0x41, 0x1F, 0xF5, 0x23, 0x41, 0xF0, 0x3C,
|
||||
0xF0, 0xD1, 0xA0, 0x54, 0x67, 0x82, 0xB8, 0x0F, 0xE1, 0xAF, 0x53, 0xE6, 0xAF, 0xC5, 0x24, 0x41,
|
||||
0xF0, 0x3B, 0xF0, 0xD1, 0x90, 0xF2, 0x2F, 0x3B, 0x49, 0x5B, 0x6C, 0x90, 0xC1, 0xF1, 0x00, 0xC5,
|
||||
0x54, 0x1D, 0x32, 0x41, 0xF0, 0x39, 0xF0, 0xD1, 0x80, 0x23, 0x29, 0x33, 0x1F, 0x3F, 0x4F, 0x61,
|
||||
0x72, 0xA5, 0xD2, 0x95, 0xB1, 0x41, 0xF0, 0xC0, 0x40, 0xF0, 0xE1, 0x0D, 0xC4, 0x5D, 0x1F, 0x25,
|
||||
0x2C, 0x36, 0x44, 0x07, 0x55, 0x68, 0x83, 0xC1, 0xE9, 0x51, 0x41, 0x41, 0xF0, 0xAF, 0xF3, 0xE0,
|
||||
0xD1, 0x19, 0x25, 0x27, 0x23, 0x1E, 0x25, 0xE0, 0x3F, 0x21, 0x27, 0x31, 0x30, 0x3B, 0x4D, 0x65,
|
||||
0x79, 0x9C, 0xDE, 0x99, 0xDE, 0x80, 0x15, 0xFA, 0x00, 0x00, 0x8A, 0x8A, 0x8A, 0x8A, 0x49, 0x19,
|
||||
0x35, 0x43, 0xA9, 0x36, 0x2A, 0x2E, 0x52, 0xD9, 0x22, 0x27, 0x35, 0x4F, 0x18, 0x6B, 0x99, 0xEF,
|
||||
0x44, 0x41, 0xB0, 0x7D, 0xF8, 0xB3, 0x81, 0x30, 0xE9, 0x52, 0x20, 0x31, 0x4B, 0xFF, 0xB2, 0x43,
|
||||
0x2C, 0x01, 0x21, 0xE9, 0x61, 0x1D, 0x21, 0x2B, 0x40, 0x5E, 0xBF, 0x02, 0x9D, 0xEA, 0x41, 0xF0,
|
||||
0x69, 0x3F, 0x71, 0x33, 0x60, 0x98, 0x00, 0x49, 0x30, 0x2F, 0x16, 0x59, 0x1E, 0x24, 0x31, 0x48,
|
||||
0x80, 0x42, 0x11, 0x4A, 0x41, 0x91, 0xB5, 0x51, 0xF1, 0x31, 0x81, 0x3D, 0x1C, 0x15, 0xE7, 0x6F,
|
||||
0x34, 0x17, 0x25, 0x1E, 0x44, 0x41, 0x52, 0xA8, 0xF8, 0xF5, 0x37, 0x41, 0xF0, 0xC4, 0x0E, 0xAE,
|
||||
0x70, 0x5B, 0x45, 0x1D, 0x89, 0x2D, 0xF0, 0x81, 0x39, 0x27, 0x0F, 0x1F, 0x1C, 0x1D, 0x22, 0x2E,
|
||||
0x42, 0x6E, 0xD8, 0x00, 0x82, 0x20, 0xD5, 0x3F, 0xF5, 0xB7, 0x41, 0xF0, 0xB3, 0x6D, 0x8A, 0x39,
|
||||
0x99, 0xBD, 0x1C, 0x54, 0xAE, 0xD2, 0x10, 0xF8, 0x9D, 0x3D, 0x29, 0x09, 0x22, 0x27, 0x35, 0x4D,
|
||||
0x90, 0xF0, 0x18, 0x22, 0xA9, 0x40, 0x4F, 0x30, 0xF5, 0x27, 0x41, 0xF0, 0xC4, 0x7C, 0x8D, 0x69,
|
||||
0x1D, 0x27, 0x3C, 0x3C, 0x60, 0x9B, 0x57, 0x11, 0xFF, 0xB6, 0x46, 0x39, 0x08, 0x41, 0x5A, 0xC7,
|
||||
0x40, 0x20, 0xE1, 0x84, 0x4D, 0x34, 0x08, 0x24, 0xF5, 0xB7, 0x71, 0xF3, 0x8A, 0x2D, 0x42, 0x70,
|
||||
0x29, 0x3E, 0x26, 0x5B, 0x85, 0x05, 0x20, 0xCE, 0x65, 0x86, 0xE9, 0x7F, 0x20, 0x84, 0xBF, 0x60,
|
||||
0x43, 0x2F, 0x23, 0xC5, 0x10, 0x41, 0xF0, 0xE9, 0xF2, 0xE0, 0x68, 0x3B, 0x28, 0x39, 0x55, 0x75,
|
||||
0x56, 0x21, 0xE9, 0x82, 0x20, 0xA1, 0xE9, 0x94, 0x52, 0xEC, 0x02, 0x25, 0xDB, 0x61, 0xF2, 0x42,
|
||||
0xA0, 0x1E, 0x78, 0x25, 0x34, 0x4F, 0x70, 0xC1, 0x4B, 0x51, 0xC9, 0x64, 0x20, 0x47, 0x31, 0x25,
|
||||
0x1E, 0x41, 0xE0, 0x85, 0xF0, 0x9B, 0x2D, 0x30, 0x1B, 0x90, 0x1D, 0x22, 0x30, 0x49, 0x6A, 0xAF,
|
||||
0xF8, 0x01, 0xCB, 0x10, 0xF1, 0xA5, 0x5F, 0x3E, 0x2B, 0x21, 0x1D, 0x01, 0xD1, 0xE9, 0x41, 0xF0,
|
||||
0xBC, 0x0C, 0x3B, 0x34, 0x28, 0x17, 0x1F, 0x21, 0x23, 0x1F, 0x25, 0x2A, 0x36, 0x4C, 0x6C, 0x9D,
|
||||
0xF1, 0x42, 0x10, 0x80, 0x99, 0x51, 0x34, 0x28, 0x25, 0x24, 0x24, 0x22, 0x00, 0x20, 0x1E, 0x49,
|
||||
0xC9, 0x8D, 0xF9, 0x8B, 0x39, 0xA1, 0x16, 0x21, 0x2B, 0x3C, 0x37, 0x3D, 0x41, 0x41, 0x45, 0x4F,
|
||||
0x63, 0x7C, 0x00, 0x8A, 0xE9, 0x42, 0x10, 0x8C, 0x4C, 0x42, 0x40, 0x40, 0x04, 0x3F, 0x39, 0x30,
|
||||
0x25, 0x1E, 0x0C, 0x30, 0x41, 0xF0, 0xE5, 0xF6, 0xE0, 0x2B, 0x41, 0xC8, 0xCC, 0xCD, 0xCD, 0xCE,
|
||||
0xCF, 0x00, 0xD0, 0xD2, 0xD2, 0xD2, 0x37, 0x10, 0xF8, 0xD0, 0xCE, 0x10, 0xCD, 0xCD, 0xCD, 0xCA,
|
||||
0xC4, 0x31, 0xD9, 0x11, 0x41, 0xF0, 0xC0, 0x5B, 0xF2, 0xEC, 0x51, 0xFF, 0x3D, 0xF0, 0xD9, 0xF1,
|
||||
0xD8, 0xE1, 0x81, 0x8A, 0x3B, 0x81, 0xDA, 0x01, 0x9D, 0x1A, 0x66, 0x00, 0x00, 0x3E, 0xF0, 0x9D,
|
||||
0xFA, 0x2F, 0xE7, 0xF6, 0xB3, 0x93, 0x77, 0x8A, 0xB3, 0x3B, 0x10, 0x20, 0x38, 0x20, 0x5F, 0x01,
|
||||
0x10, 0xF5, 0xF3, 0x43, 0xE5, 0x36, 0x41, 0xF0, 0x25, 0x52, 0xA4, 0x76, 0x09, 0x19, 0x2D, 0x3D,
|
||||
0x14, 0x1F, 0x2F, 0x49, 0x99, 0xA1, 0x05, 0x02, 0x20, 0x03, 0x30, 0x00, 0x00, 0xA4, 0xA4, 0xA4,
|
||||
0xA3, 0x9D, 0x07, 0x8E, 0x36, 0x23, 0x41, 0x70, 0x41, 0xF0, 0x41, 0x14, 0xE5, 0x76, 0x26, 0x78,
|
||||
0x35, 0x45, 0x4F, 0x52, 0x4F, 0x03, 0x30, 0x4E, 0x00, 0x00, 0xA0, 0x4E, 0x4E, 0x4E, 0x4F, 0x52,
|
||||
0x52, 0x4B, 0x3C, 0x00, 0x2A, 0x41, 0x00, 0x41, 0xF0, 0xA5, 0xF2, 0xA1, 0x16, 0x24, 0x30, 0x3D,
|
||||
0x1E, 0x41, 0x3C, 0x32, 0x2D, 0x2A, 0xC0, 0x44, 0x2A, 0x2A, 0x20, 0x2A, 0x2B, 0x31, 0x3A, 0x44,
|
||||
0x42, 0x39, 0x28, 0x00, 0x09, 0xA5, 0x41, 0xF0, 0xAC, 0x30, 0x37, 0x6D, 0x05, 0x09, 0x1F, 0x2A,
|
||||
0x2B, 0x3F, 0xB1, 0xB2, 0xAD, 0x31, 0x23, 0x1D, 0x1E, 0x00, 0x20, 0x26, 0x8A, 0x04, 0x22, 0x1F,
|
||||
0x1D, 0x1D, 0x20, 0x04, 0x2D, 0x44, 0xC8, 0xC8, 0xC5, 0x32, 0x21, 0x41, 0xC0, 0x80, 0xA8, 0xE6,
|
||||
0x77, 0x2D, 0x1B, 0x2D, 0x77, 0xE5, 0x16, 0x20, 0x41, 0x34, 0x57, 0x10, 0x00, 0x3E, 0x25, 0x30,
|
||||
0x18, 0x68, 0x6A, 0x24, 0x43, 0x28, 0x20, 0x35, 0x5A, 0x2E, 0x00, 0x40, 0x09, 0x75, 0x41, 0xF0,
|
||||
0xD1, 0xB5, 0x27, 0xAC, 0x4A, 0x05, 0xAC, 0x62, 0x1B, 0xE9, 0x22, 0x10, 0x20, 0xC5, 0x30, 0x18,
|
||||
0x43, 0x48, 0x21, 0x3C, 0x6B, 0x2E, 0x00, 0xE9, 0xF2, 0x95, 0xF5, 0xE3, 0x3D, 0xA3, 0x16, 0x10,
|
||||
0x70, 0x30, 0x08, 0x74, 0x18, 0x46, 0x28, 0x4E, 0x22, 0x9E, 0x61, 0xF2, 0x95, 0xF1, 0x22, 0xF6,
|
||||
0x14, 0x02, 0x6E, 0x07, 0x00, 0x4D, 0x29, 0x2F, 0x2E, 0x20, 0x41, 0xF0, 0x2D, 0xF3, 0x22, 0x40,
|
||||
0x93, 0x10, 0x30, 0x41, 0xF0, 0x41, 0xF0, 0xEF, 0xC9, 0xF0, 0x80, 0x44, 0xBB, 0x10, 0x50, 0x41,
|
||||
0xF0, 0x41, 0xF0, 0x4F, 0xC5, 0xBB, 0x7B, 0x4C, 0x35, 0xB3, 0xA4, 0x10, 0x70, 0x07, 0x60, 0x2E,
|
||||
0x40, 0x41, 0xF0, 0xA8, 0xB2, 0xF9, 0x6D, 0xBB, 0x00, 0x00, 0x6D, 0x7A, 0x08, 0x2D, 0x41, 0x20,
|
||||
0x06, 0x20, 0xD4, 0xD5, 0x65, 0xCB, 0x25, 0x41, 0xF0, 0x51, 0xF1, 0x41, 0xA0, 0x06, 0x20, 0xD5,
|
||||
0x65, 0xCB, 0x25, 0xFF, 0x41, 0xA0, 0x41, 0xF0, 0x41, 0xF0, 0x06, 0x20, 0xD5, 0x65, 0xCB, 0x25,
|
||||
0x41, 0xB0, 0x41, 0xF0, 0xFF, 0xCE, 0xF4, 0x40, 0xF0, 0x33, 0x24, 0x41, 0x80, 0x41, 0xF0, 0x9A,
|
||||
0x21, 0x2D, 0x8A, 0x3F, 0xAC, 0x98, 0x16, 0x22, 0x3F, 0x6F, 0x01, 0x10, 0x3D, 0xF0, 0x4E, 0x62,
|
||||
0x29, 0x41, 0x90, 0x41, 0xF0, 0x8A, 0xAC, 0x4A, 0x1B, 0x9B, 0x06, 0xA4, 0x6D, 0xA4, 0x93, 0x1D,
|
||||
0x12, 0x69, 0x01, 0x10, 0xD5, 0xF1, 0xD0, 0x49, 0x1D, 0xC2, 0x85, 0xF0, 0x3D, 0x00, 0x3D, 0x1B,
|
||||
0x3D, 0xD5, 0x45, 0x8E, 0xD5, 0xF5, 0xD5, 0xF5, 0x41, 0xF0, 0xC7, 0x00, 0x7D, 0x14, 0xBB, 0xD5,
|
||||
0x25, 0xD5, 0xF5, 0xDF, 0xD5, 0xF5, 0x41, 0xF0, 0x44, 0x00, 0x8A, 0x8A, 0xCB, 0x15, 0xD5, 0x85,
|
||||
0xD5, 0xF5, 0xE7, 0x41, 0xF0, 0x3A, 0xB4, 0x93, 0xBB, 0x4A, 0x1B, 0x4A, 0xA4, 0x03, 0x77, 0xB5,
|
||||
0x13, 0x22, 0x28, 0x2A, 0x03, 0x30, 0x03, 0x30, 0x00, 0x00, 0xE2, 0x2B, 0x2B, 0x2B, 0x28, 0x24,
|
||||
0x1F, 0x1D, 0xD2, 0x23, 0xE2, 0xC0, 0x77, 0x4A, 0x9F, 0x12, 0xDA, 0x11, 0x23, 0x2E, 0x3A, 0x41,
|
||||
0x0C, 0x02, 0x20, 0x03, 0x30, 0x00, 0x00, 0x45, 0x45, 0x45, 0x43, 0x3D, 0x07, 0x32, 0x26, 0x95,
|
||||
0x11, 0x41, 0xF0, 0x3B, 0xF0, 0x0D, 0x11, 0x45, 0xDC, 0x3C, 0xDF, 0x02, 0x20, 0x03, 0x30, 0x00,
|
||||
0x00, 0xE0, 0xE0, 0xE0, 0xDF, 0x0E, 0xDE, 0xDA, 0x0D, 0x21, 0x41, 0xF0, 0xC3, 0xF0, 0x85, 0x10,
|
||||
0x5D, 0x01, 0x10, 0xBC, 0x3D, 0xF0, 0x41, 0x26, 0x41, 0x90, 0x41, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x57, 0x79, 0x57, 0x24, 0x03, 0x21, 0x3B, 0x67, 0x01, 0x10, 0x3D, 0xF0, 0x48, 0x62, 0x71, 0xA3,
|
||||
0x41, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0x85, 0x00, 0x20, 0x4F, 0x37, 0x5E, 0x01, 0x10,
|
||||
0xE5, 0xF2, 0x42, 0x27, 0x01, 0x10, 0x41, 0xF0, 0xCC, 0x16, 0xC2, 0xA4, 0x81, 0xA5, 0x02, 0x2D,
|
||||
0x46, 0x7E, 0x8A, 0x09, 0x09, 0x10, 0x8E, 0x92, 0x61, 0x12, 0x94, 0x90, 0x8C, 0x8C, 0x09, 0x8C,
|
||||
0x8C, 0x8C, 0x8B, 0x83, 0x71, 0x34, 0x22, 0x00, 0x41, 0xF0, 0x1B, 0x3D, 0xF0, 0x3D, 0x41, 0x00,
|
||||
0x1D, 0x23, 0x2F, 0x15, 0x3B, 0x43, 0x09, 0x10, 0x4C, 0x63, 0x7C, 0x41, 0x00, 0x6F, 0x44, 0x52,
|
||||
0x47, 0x47, 0x47, 0x47, 0x47, 0x45, 0x3F, 0x00, 0x33, 0x27, 0x1D, 0x62, 0x41, 0xF0, 0x9A, 0xD2,
|
||||
0x1D, 0x20, 0x23, 0x1C, 0x25, 0x09, 0x10, 0x2D, 0x49, 0x74, 0x41, 0x00, 0x57, 0x34, 0x22, 0x27,
|
||||
0x27, 0x27, 0x27, 0x27, 0x26, 0x24, 0x21, 0x00, 0x1E, 0x1C, 0x41, 0xF0, 0x1B, 0x68, 0xF0, 0x6D,
|
||||
0x56, 0x32, 0x0B, 0x30, 0xD4, 0x23, 0x0D, 0x21, 0x50, 0x2B, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x12,
|
||||
0x1C, 0x41, 0xC0, 0x41, 0xF0, 0x00, 0x00, 0x9B, 0x9B, 0x9B, 0xA4, 0x0E, 0xBB, 0xCF, 0x31, 0x41,
|
||||
0xF0, 0x41, 0xF0, 0x41, 0xF0, 0x00, 0x00, 0x77, 0x77, 0x3E, 0x77, 0x6D, 0x3D, 0x11, 0x50, 0x41,
|
||||
0xF0, 0x41, 0xF0, 0x41, 0xF0, 0x17, 0xF0, 0xF8, 0x22, 0x40, 0x70, 0x41, 0x00, 0x4F, 0x2A, 0x16,
|
||||
0xF0, 0x41, 0xF0, 0xC8, 0x4F, 0xF3, 0x0B, 0x30, 0x24, 0x41, 0x71, 0x41, 0x00, 0x51, 0x2B, 0x23,
|
||||
0x00, 0x00, 0x1D, 0x1D, 0x81, 0x93, 0x41, 0xF0, 0xDF, 0x21, 0x62, 0x03, 0x10, 0xB9, 0x62, 0x2D,
|
||||
0x1E, 0x22, 0x1F, 0x24, 0x29, 0x2E, 0x09, 0x10, 0x84, 0x35, 0x50, 0x78, 0x41, 0x00, 0x5D, 0x3C,
|
||||
0x00, 0x00, 0x2F, 0x48, 0x2F, 0x2F, 0x2B, 0x26, 0x20, 0xD9, 0xE1, 0x40, 0xA0, 0xBB, 0x60, 0xB3,
|
||||
0x7D, 0x20, 0xB3, 0x77, 0x85, 0x22, 0x35, 0x6A, 0x72, 0x12, 0x09, 0x10, 0x78, 0x88, 0x94, 0x38,
|
||||
0x00, 0x8E, 0x7D, 0x75, 0x11, 0x75, 0x75, 0x75, 0x75, 0x74, 0x6D, 0x62, 0x2B, 0x00, 0x1F, 0x0C,
|
||||
0x60, 0x41, 0xF0, 0x77, 0xAC, 0x57, 0x42, 0x50, 0x77, 0x46, 0xC9, 0x00, 0x30, 0x4F, 0x01, 0x10,
|
||||
0x3D, 0xF0, 0x39, 0xE8, 0x71, 0x41, 0xF0, 0xD9, 0xB3, 0x6D, 0x24, 0x50, 0x57, 0xAC, 0x21, 0x00,
|
||||
0x39, 0x63, 0x24, 0x01, 0x10, 0x3D, 0xF0, 0x45, 0x0C, 0x10, 0x41, 0xF0, 0x41, 0xF0, 0x21, 0x00,
|
||||
0x3A, 0x7B, 0x65, 0x07, 0x70, 0x03, 0x30, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x47, 0x0E, 0x28, 0x41,
|
||||
0xE0, 0x08, 0x80, 0x34, 0x70, 0xBB, 0x1B, 0x1B, 0x1F, 0x0E, 0x33, 0x55, 0xE0, 0x05, 0x50, 0x03,
|
||||
0x30, 0x00, 0x00, 0xE1, 0xE1, 0x38, 0xE1, 0xDD, 0x3D, 0x25, 0x0C, 0x60, 0x41, 0xF0, 0xA4, 0x8A,
|
||||
0x30, 0x24, 0x50, 0x81, 0xA4, 0x31, 0x01, 0x28, 0x3C, 0x52, 0x60, 0x09, 0x02, 0x20, 0x03, 0x30,
|
||||
0x00, 0x00, 0x65, 0x65, 0x65, 0x63, 0x58, 0x07, 0x45, 0x2F, 0x20, 0x41, 0xC0, 0x42, 0xA0, 0xBB,
|
||||
0x81, 0x3D, 0x18, 0x22, 0x10, 0x2D, 0x81, 0xBB, 0x57, 0x31, 0x11, 0x28, 0x30, 0x21, 0x36, 0x02,
|
||||
0x20, 0x03, 0x30, 0x00, 0x00, 0x39, 0x39, 0x39, 0x37, 0x0E, 0x32, 0x2B, 0x22, 0x40, 0x70, 0x21,
|
||||
0x34, 0x47, 0xDB, 0x08, 0x3A, 0x28, 0x43, 0xB0, 0x9B, 0xBB, 0xB3, 0xAC, 0xAC, 0x04, 0xB3, 0xBB,
|
||||
0xA4, 0x3F, 0x20, 0x1C, 0x1E, 0x1F, 0x04, 0x40, 0x88, 0x03, 0x30, 0x00, 0x00, 0x20, 0x20, 0x20,
|
||||
0x1F, 0x1F, 0xD9, 0x80, 0x83, 0x20, 0x32, 0x44, 0xDB, 0x38, 0x26, 0x12, 0xC0, 0x4A, 0x40, 0x62,
|
||||
0x6D, 0x6D, 0x62, 0x4A, 0x02, 0x20, 0x0F, 0xF0, 0x15, 0xF0, 0xE0, 0x20, 0x2E, 0x3B, 0xDB, 0x32,
|
||||
0x24, 0x05, 0x50, 0x0F, 0xF0, 0xC0, 0x0F, 0xF0, 0x15, 0xF0, 0x1E, 0x26, 0x2E, 0x31, 0x29, 0x20,
|
||||
0x03, 0x06, 0x60, 0x0F, 0xF0, 0x26, 0xF0, 0x42, 0xF0, 0x20, 0x23, 0x24, 0x20, 0x0F, 0x1D, 0x06,
|
||||
0x60, 0x0F, 0xF0, 0x0F, 0xF0, 0x13, 0xF0, 0x1C, 0x1D, 0x1D, 0x1E, 0x1C, 0x00, 0x00, 0x09, 0x90,
|
||||
0x03, 0x30, 0x00, 0x00, 0x1B, 0x1B, 0x1B, 0x1E, 0x94, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||
0x6C, 0x23, 0x00, 0x00
|
||||
};
|
||||
|
||||
// 21 x 50 @8bpp RGB.
|
||||
#define X_BATTERY_EMPTY 21
|
||||
#define Y_BATTERY_EMPTY_BATT 38
|
||||
#define Y_BATTERY_EMPTY_CHRG 12
|
||||
#define SZ_BATTERY_EMPTY 3150
|
||||
#define SZ_BATTERY_EMPTY_BLZ 740
|
||||
static u8 BATTERY_EMPTY_BLZ[SZ_BATTERY_EMPTY_BLZ] =
|
||||
{
|
||||
0x17, 0xC0, 0x5D, 0x51, 0x79, 0x12, 0x79, 0x48, 0x69, 0x00, 0x0D, 0x46, 0xE3, 0x0F, 0xF0, 0x20,
|
||||
0xF0, 0x35, 0x2E, 0x38, 0x3F, 0x40, 0xEF, 0xCF, 0x00, 0x89, 0x77, 0x00, 0x17, 0x01, 0x14, 0x09,
|
||||
0x90, 0x36, 0xF0, 0xA4, 0xF1, 0x62, 0x01, 0x38, 0xA1, 0x99, 0x84, 0x3E, 0x00, 0x23, 0x1F, 0x04,
|
||||
0x40, 0x3B, 0xF0, 0x5B, 0x4F, 0x00, 0x18, 0x25, 0x20, 0x24, 0x90, 0x57, 0x00, 0x3C, 0xC0, 0x7B,
|
||||
0x00, 0x63, 0x10, 0x31, 0x7C, 0x2B, 0x03, 0x30, 0x3C, 0xF0, 0xA2, 0x00, 0xCE, 0x11, 0x0F, 0x0D,
|
||||
0x21, 0x00, 0x9E, 0xDE, 0x00, 0x06, 0x40, 0x60, 0xF0, 0xB9, 0xA0, 0xEA, 0x70, 0x3C, 0xF0, 0xF5,
|
||||
0x67, 0xD4, 0x3E, 0x01, 0x54, 0x00, 0x00, 0x00, 0x57, 0x70, 0xCD, 0xB1, 0x00, 0x1E, 0xFB, 0xD9,
|
||||
0x15, 0xA0, 0xC9, 0xAE, 0x69, 0x30, 0x3C, 0xD0, 0x30, 0xF0, 0xE4, 0xC1, 0xA7, 0x18, 0x10, 0x0D,
|
||||
0x0C, 0x00, 0x49, 0x3F, 0x04, 0x00, 0x87, 0x75, 0x00, 0xC5, 0xAA, 0x2A, 0x00, 0x09, 0x40, 0xC0,
|
||||
0xD7, 0xBA, 0x24, 0x00, 0x0C, 0xA0, 0x33, 0xF0, 0xF7, 0xD6, 0x0C, 0x00, 0x9C, 0x3C, 0xA0, 0x07,
|
||||
0x06, 0x2A, 0x10, 0x7D, 0x6C, 0x00, 0xBB, 0x09, 0xA2, 0x00, 0xF3, 0xD2, 0x00, 0xE3, 0xC4, 0x0C,
|
||||
0xA0, 0x80, 0x3C, 0xF0, 0x41, 0x38, 0x05, 0x50, 0x3E, 0xF1, 0x03, 0x00, 0x01, 0x19, 0x01, 0x00,
|
||||
0x33, 0x2C, 0x00, 0x71, 0x62, 0x00, 0x00, 0xAF, 0x97, 0x00, 0xEB, 0xCB, 0x03, 0x30, 0x03, 0x30,
|
||||
0x3C, 0x40, 0xE0, 0x81, 0x70, 0x04, 0x40, 0x0F, 0xF0, 0x23, 0xF0, 0x2D, 0x27, 0x00, 0x1C, 0x6B,
|
||||
0x5D, 0x00, 0xA9, 0x92, 0x00, 0xE7, 0xC8, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC, 0x00, 0xBF, 0xA5,
|
||||
0x0E, 0xE0, 0x81, 0x0F, 0xF0, 0x19, 0xF0, 0xA5, 0x00, 0x22, 0x00, 0x65, 0x58, 0x00, 0x07, 0x67,
|
||||
0x59, 0x07, 0x70, 0x0F, 0xF0, 0x2A, 0xF0, 0x06, 0x09, 0x45, 0x10, 0x3C, 0x0A, 0x00, 0x00, 0x03,
|
||||
0x30, 0x00, 0x00, 0x49, 0x11, 0x0B, 0x47, 0x0E, 0x10, 0x0B, 0x1B, 0x06, 0x04, 0x3F, 0xF0, 0xD2,
|
||||
0xF0, 0xCD, 0x38, 0xE0, 0x85, 0xF8, 0xF7, 0x3A, 0x26, 0x75, 0x00, 0xD2, 0xF0, 0x33, 0x00, 0x27,
|
||||
0x71, 0x09, 0x06, 0x24, 0x30, 0xBD, 0x2C, 0x1D, 0x15, 0x00, 0xDB, 0x44, 0x33, 0x22, 0x00, 0x00,
|
||||
0x03, 0x30, 0x00, 0x00, 0x57, 0x00, 0x5D, 0x00, 0x18, 0x00, 0xFC, 0xC7, 0x2E, 0x1F, 0x00, 0x00,
|
||||
0x45, 0x00, 0x29, 0x09, 0x06, 0x18, 0x89, 0x30, 0x2F, 0x0B, 0x07, 0xDF, 0x34, 0x23, 0x21, 0xC0,
|
||||
0x81, 0x59, 0x15, 0x0E, 0x3C, 0xC0, 0x2A, 0x00, 0xF5, 0xC7, 0xE1, 0x34, 0x38, 0x23, 0x31, 0x0B,
|
||||
0x07, 0xC9, 0x2F, 0x1F, 0x33, 0x00, 0x80, 0x2D, 0x00, 0x1E, 0x90, 0x4D, 0x12, 0x0C, 0x2D, 0xC0,
|
||||
0x41, 0x0F, 0x23, 0x0A, 0x03, 0x30, 0x00, 0x00, 0xD9, 0x33, 0x22, 0xE7, 0x36, 0x06, 0x24, 0x06,
|
||||
0x00, 0xCB, 0x2F, 0x1F, 0x39, 0x30, 0x15, 0x05, 0x22, 0x03, 0x06, 0x60, 0x0F, 0xF0, 0x21, 0xF0,
|
||||
0x0F, 0x03, 0x02, 0x03, 0x00, 0x8E, 0xF9, 0x3A, 0x3C, 0xA0, 0x0F, 0xF0, 0x27, 0xF0, 0x3C, 0xF0,
|
||||
0x3C, 0xF0, 0x30, 0xF0, 0xFC, 0x3C, 0xF0, 0x3C, 0xF0, 0x0F, 0xF0, 0x27, 0xF0, 0x3C, 0xF0, 0x3C,
|
||||
0xF0, 0x30, 0xF0, 0x3C, 0xF0, 0xFF, 0x3C, 0xF0, 0x0F, 0xF0, 0x27, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0,
|
||||
0x30, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0xFF, 0x0F, 0xF0, 0x27, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x30,
|
||||
0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x0F, 0xF0, 0xFF, 0x27, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x30, 0xF0,
|
||||
0x3C, 0xF0, 0x3C, 0xF0, 0x0F, 0xF0, 0x27, 0xF0, 0xFF, 0x3C, 0xF0, 0x3C, 0xF0, 0x30, 0xF0, 0x3C,
|
||||
0xF0, 0x3C, 0xF0, 0x0F, 0xF0, 0x27, 0xF0, 0x3C, 0xF0, 0xFF, 0x3C, 0xF0, 0x30, 0xF0, 0x3C, 0xF0,
|
||||
0x3C, 0xF0, 0x0F, 0xF0, 0x27, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0xFF, 0x30, 0xF0, 0x3C, 0xF0, 0x3C,
|
||||
0xF0, 0x0F, 0xF0, 0x27, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x30, 0xF0, 0xFF, 0x3C, 0xF0, 0x3C, 0xF0,
|
||||
0x0F, 0xF0, 0x27, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x30, 0xF0, 0x3C, 0xF0, 0xFF, 0x3C, 0xF0, 0x0F,
|
||||
0xF0, 0x27, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x30, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0xFF, 0x0F, 0xF0,
|
||||
0x27, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x30, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x0F, 0xF0, 0xFF, 0x27,
|
||||
0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x30, 0xF0, 0x3C, 0xF0, 0x3C, 0xF0, 0x0F, 0xF0, 0x27, 0xF0, 0xFF,
|
||||
0x3C, 0xF0, 0x3C, 0xF0, 0x30, 0xF0, 0x3C, 0xF0, 0x84, 0x90, 0x3F, 0x00, 0x00, 0x00, 0x0F, 0xF0,
|
||||
0xFF, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x07, 0x01, 0xB1, 0x40,
|
||||
0x81, 0x20, 0x33, 0x0C, 0x08, 0x00, 0x00, 0x0F, 0xF0, 0xC6, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00,
|
||||
0x0D, 0x03, 0x02, 0x2D, 0x0A, 0x07, 0x07, 0x75, 0x30, 0x39, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x0F,
|
||||
0xF0, 0x1B, 0xF0, 0x03, 0x00, 0xFE, 0x39, 0x00, 0xB1, 0x29, 0x1B, 0xF3, 0x39, 0x26, 0x00, 0x00,
|
||||
0x81, 0x0F, 0xF0, 0x09, 0x90, 0x03, 0x30, 0x00, 0x00, 0xFE, 0x3B, 0x27, 0xF5, 0x0F, 0x39, 0x26,
|
||||
0xB3, 0x2A, 0x1C, 0x17, 0x05, 0x03, 0x00, 0xFF, 0xE4, 0x02, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||
0x6A, 0x09, 0x00, 0x00
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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 "di.h"
|
||||
#include "tui.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../config/config.h"
|
||||
#include "../power/max17050.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
extern u8 *Kc_MENU_LOGO;
|
||||
#define X_MENU_LOGO 119
|
||||
#define Y_MENU_LOGO 57
|
||||
#define X_POS_MENU_LOGO 577
|
||||
#define Y_POS_MENU_LOGO 1179
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
void tui_sbar(bool force_update)
|
||||
{
|
||||
u32 cx, cy;
|
||||
|
||||
u32 timePassed = get_tmr_s() - h_cfg.sbar_time_keeping;
|
||||
if (!force_update)
|
||||
if (timePassed < 5)
|
||||
return;
|
||||
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 16;
|
||||
h_cfg.sbar_time_keeping = get_tmr_s();
|
||||
|
||||
u32 battPercent = 0;
|
||||
int battVoltCurr = 0;
|
||||
|
||||
gfx_con_getpos(&cx, &cy);
|
||||
gfx_con_setpos(0, 1260);
|
||||
|
||||
max17050_get_property(MAX17050_RepSOC, (int *)&battPercent);
|
||||
max17050_get_property(MAX17050_VCELL, &battVoltCurr);
|
||||
|
||||
gfx_clear_partial_grey(0x30, 1256, 24);
|
||||
gfx_printf("%K%k Battery: %d.%d%% (%d mV) - Charge:", 0xFF303030, 0xFF888888,
|
||||
(battPercent >> 8) & 0xFF, (battPercent & 0xFF) / 26, battVoltCurr);
|
||||
|
||||
max17050_get_property(MAX17050_Current, &battVoltCurr);
|
||||
|
||||
if (battVoltCurr >= 0)
|
||||
gfx_printf(" %k+%d mA%k%K\n",
|
||||
0xFF008800, battVoltCurr / 1000, 0xFFCCCCCC, 0xFF1B1B1B);
|
||||
else
|
||||
gfx_printf(" %k-%d mA%k%K\n",
|
||||
0xFF880000, (~battVoltCurr) / 1000, 0xFFCCCCCC, 0xFF1B1B1B);
|
||||
gfx_con.fntsz = prevFontSize;
|
||||
gfx_con_setpos(cx, cy);
|
||||
}
|
||||
|
||||
void tui_pbar(int x, int y, u32 val, u32 fgcol, u32 bgcol)
|
||||
{
|
||||
u32 cx, cy;
|
||||
if (val > 200)
|
||||
val = 200;
|
||||
|
||||
gfx_con_getpos(&cx, &cy);
|
||||
|
||||
gfx_con_setpos(x, y);
|
||||
|
||||
gfx_printf("%k[%3d%%]%k", fgcol, val, 0xFFCCCCCC);
|
||||
|
||||
x += 7 * gfx_con.fntsz;
|
||||
|
||||
for (int i = 0; i < (gfx_con.fntsz >> 3) * 6; i++)
|
||||
{
|
||||
gfx_line(x, y + i + 1, x + 3 * val, y + i + 1, fgcol);
|
||||
gfx_line(x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, bgcol);
|
||||
}
|
||||
|
||||
gfx_con_setpos(cx, cy);
|
||||
|
||||
// Update status bar.
|
||||
tui_sbar(false);
|
||||
}
|
||||
|
||||
void *tui_do_menu(menu_t *menu)
|
||||
{
|
||||
int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
tui_sbar(true);
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
gfx_set_rect_rgb(Kc_MENU_LOGO,
|
||||
X_MENU_LOGO, Y_MENU_LOGO, X_POS_MENU_LOGO, Y_POS_MENU_LOGO);
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
|
||||
while (true)
|
||||
{
|
||||
gfx_con_setcol(0xFFCCCCCC, 1, 0xFF1B1B1B);
|
||||
gfx_con_setpos(menu->x, menu->y);
|
||||
gfx_printf("[%s]\n\n", menu->caption);
|
||||
|
||||
// Skip caption or seperator lines selection.
|
||||
while (menu->ents[idx].type == MENT_CAPTION ||
|
||||
menu->ents[idx].type == MENT_CHGLINE)
|
||||
{
|
||||
if (prev_idx <= idx || (!idx && prev_idx == cnt - 1))
|
||||
{
|
||||
idx++;
|
||||
if (idx > (cnt - 1))
|
||||
{
|
||||
idx = 0;
|
||||
prev_idx = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
idx--;
|
||||
if (idx < 0)
|
||||
{
|
||||
idx = cnt - 1;
|
||||
prev_idx = cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_idx = idx;
|
||||
|
||||
// Draw the menu.
|
||||
for (cnt = 0; menu->ents[cnt].type != MENT_END; cnt++)
|
||||
{
|
||||
if (cnt == idx)
|
||||
gfx_con_setcol(0xFF1B1B1B, 1, 0xFFCCCCCC);
|
||||
else
|
||||
gfx_con_setcol(0xFFCCCCCC, 1, 0xFF1B1B1B);
|
||||
if (menu->ents[cnt].type == MENT_CAPTION)
|
||||
gfx_printf("%k %s", menu->ents[cnt].color, menu->ents[cnt].caption);
|
||||
else if (menu->ents[cnt].type != MENT_CHGLINE)
|
||||
gfx_printf(" %s", menu->ents[cnt].caption);
|
||||
if(menu->ents[cnt].type == MENT_MENU)
|
||||
gfx_printf("%k...", 0xFF0099EE);
|
||||
gfx_printf(" \n");
|
||||
}
|
||||
gfx_con_setcol(0xFFCCCCCC, 1, 0xFF1B1B1B);
|
||||
gfx_putc('\n');
|
||||
|
||||
// Print errors, help and battery status.
|
||||
gfx_con_setpos(0, 1127);
|
||||
gfx_printf("%k Warning: %k Nyx is missing!", 0xFF800000, 0xFF555555);
|
||||
gfx_con_setpos(0, 1191);
|
||||
gfx_printf("%k VOL: Move up/down\n PWR: Select option%k", 0xFF555555, 0xFFCCCCCC);
|
||||
|
||||
display_backlight_brightness(h_cfg.backlight, 1000);
|
||||
|
||||
// Wait for user command.
|
||||
u32 btn = btn_wait();
|
||||
|
||||
if (btn & BTN_VOL_DOWN && idx < (cnt - 1))
|
||||
idx++;
|
||||
else if (btn & BTN_VOL_DOWN && idx == (cnt - 1))
|
||||
{
|
||||
idx = 0;
|
||||
prev_idx = -1;
|
||||
}
|
||||
if (btn & BTN_VOL_UP && idx > 0)
|
||||
idx--;
|
||||
else if (btn & BTN_VOL_UP && idx == 0)
|
||||
{
|
||||
idx = cnt - 1;
|
||||
prev_idx = cnt;
|
||||
}
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
ment_t *ent = &menu->ents[idx];
|
||||
switch (ent->type)
|
||||
{
|
||||
case MENT_HANDLER:
|
||||
ent->handler(ent->data);
|
||||
break;
|
||||
case MENT_MENU:
|
||||
return tui_do_menu(ent->menu);
|
||||
break;
|
||||
case MENT_DATA:
|
||||
return ent->data;
|
||||
break;
|
||||
case MENT_BACK:
|
||||
return NULL;
|
||||
break;
|
||||
case MENT_HDLR_RE:
|
||||
ent->handler(ent);
|
||||
if (!ent->data)
|
||||
return NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
gfx_set_rect_rgb(Kc_MENU_LOGO,
|
||||
X_MENU_LOGO, Y_MENU_LOGO, X_POS_MENU_LOGO, Y_POS_MENU_LOGO);
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
}
|
||||
tui_sbar(false);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* Atmosphère Fusée Secondary Storage parser.
|
||||
*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "fss.h"
|
||||
#include "hos.h"
|
||||
#include "../config/config.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
|
||||
#include "../gfx/gfx.h"
|
||||
#define DPRINTF(...)
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool is_ipl_updated(void *buf, char *path, bool force);
|
||||
|
||||
// FSS0 Magic and Meta header offset.
|
||||
#define FSS0_MAGIC 0x30535346
|
||||
#define FSS0_META_OFFSET 0x4
|
||||
|
||||
// FSS0 Content Types.
|
||||
#define CNT_TYPE_FSP 0
|
||||
#define CNT_TYPE_EXO 1 // Exosphere (Secure Monitor).
|
||||
#define CNT_TYPE_WBT 2 // Warmboot (SC7Exit fw).
|
||||
#define CNT_TYPE_RBT 3 // Rebootstub (Warmboot based reboot fw).
|
||||
#define CNT_TYPE_SP1 4 // Sept Primary (TSEC and Sept Secondary loader).
|
||||
#define CNT_TYPE_SP2 5 // Sept Secondary (Acts as pkg11 and derives keys).
|
||||
#define CNT_TYPE_KIP 6 // KIP1 (Used for replacement or addition).
|
||||
#define CNT_TYPE_BMP 7
|
||||
#define CNT_TYPE_EMC 8
|
||||
#define CNT_TYPE_KLD 9 // Kernel Loader.
|
||||
#define CNT_TYPE_KRN 10 // Kernel.
|
||||
|
||||
// FSS0 Content Flags.
|
||||
#define CNT_FLAG0_EXPERIMENTAL (1 << 0)
|
||||
|
||||
// FSS0 Meta Header.
|
||||
typedef struct _fss_meta_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 size;
|
||||
u32 crt0_off;
|
||||
u32 cnt_off;
|
||||
u32 cnt_count;
|
||||
u32 hos_ver;
|
||||
u32 version;
|
||||
u32 git_rev;
|
||||
} fss_meta_t;
|
||||
|
||||
// FSS0 Content Header.
|
||||
typedef struct _fss_content_t
|
||||
{
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u8 type;
|
||||
u8 flags0;
|
||||
u8 flags1;
|
||||
u8 flags2;
|
||||
u32 rsvd1;
|
||||
char name[0x10];
|
||||
} fss_content_t;
|
||||
|
||||
static void _update_r2p(const char *path)
|
||||
{
|
||||
char *r2p_path = malloc(256);
|
||||
u32 path_len = strlen(path);
|
||||
strcpy(r2p_path, path);
|
||||
|
||||
while(path_len)
|
||||
{
|
||||
if ((r2p_path[path_len - 1] == '/') || (r2p_path[path_len - 1] == 0x5C))
|
||||
{
|
||||
r2p_path[path_len] = 0;
|
||||
strcat(r2p_path, "reboot_payload.bin");
|
||||
u8 *r2p_payload = sd_file_read(r2p_path, NULL);
|
||||
|
||||
is_ipl_updated(r2p_payload, r2p_path, h_cfg.updater2p ? true : false);
|
||||
|
||||
free(r2p_payload);
|
||||
break;
|
||||
}
|
||||
path_len--;
|
||||
}
|
||||
|
||||
free(r2p_path);
|
||||
}
|
||||
|
||||
int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
{
|
||||
FIL fp;
|
||||
|
||||
bool stock = false;
|
||||
int sept_used = 0;
|
||||
|
||||
if (!sept_ctxt)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||
{
|
||||
if (!strcmp("stock", kv->key))
|
||||
if (kv->val[0] == '1')
|
||||
stock = true;
|
||||
}
|
||||
|
||||
if (stock && ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && (!emu_cfg.enabled || h_cfg.emummc_force_disable))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (f_open(&fp, path, FA_READ) != FR_OK)
|
||||
return 0;
|
||||
|
||||
void *fss = malloc(f_size(&fp));
|
||||
|
||||
// Read first 1024 bytes of the fss file.
|
||||
f_read(&fp, fss, 1024, NULL);
|
||||
|
||||
// Get FSS0 Meta header offset.
|
||||
u32 fss_meta_addr = *(u32 *)(fss + FSS0_META_OFFSET);
|
||||
fss_meta_t *fss_meta = (fss_meta_t *)(fss + fss_meta_addr);
|
||||
|
||||
// Check if valid FSS0 and parse it.
|
||||
if (fss_meta->magic == FSS0_MAGIC)
|
||||
{
|
||||
gfx_printf("Found FSS0, Atmosphere %d.%d.%d-%08x\n"
|
||||
"Max HOS supported: %d.%d.%d\n"
|
||||
"Unpacking and loading components.. ",
|
||||
fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev,
|
||||
fss_meta->hos_ver >> 24, (fss_meta->hos_ver >> 16) & 0xFF, (fss_meta->hos_ver >> 8) & 0xFF);
|
||||
|
||||
if (!sept_ctxt)
|
||||
{
|
||||
ctxt->atmosphere = true;
|
||||
ctxt->fss0_hosver = fss_meta->hos_ver;
|
||||
}
|
||||
|
||||
// Parse FSS0 contents.
|
||||
fss_content_t *curr_fss_cnt = (fss_content_t *)(fss + fss_meta->cnt_off);
|
||||
void *content;
|
||||
for (u32 i = 0; i < fss_meta->cnt_count; i++)
|
||||
{
|
||||
content = (void *)(fss + curr_fss_cnt[i].offset);
|
||||
|
||||
// Check if offset is inside limits.
|
||||
if ((curr_fss_cnt[i].offset + curr_fss_cnt[i].size) > fss_meta->size)
|
||||
continue;
|
||||
|
||||
// If content is experimental and experimental flag is not enabled, skip it.
|
||||
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_enable_experimental)
|
||||
continue;
|
||||
|
||||
// Parse content.
|
||||
if (!sept_ctxt)
|
||||
{
|
||||
// Prepare content context.
|
||||
switch (curr_fss_cnt[i].type)
|
||||
{
|
||||
case CNT_TYPE_KIP:
|
||||
if (stock)
|
||||
continue;
|
||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||
mkip1->kip1 = content;
|
||||
list_append(&ctxt->kip1_list, &mkip1->link);
|
||||
DPRINTF("Loaded %s.kip1 from FSS0 (size %08X)\n", curr_fss_cnt[i].name, curr_fss_cnt[i].size);
|
||||
break;
|
||||
case CNT_TYPE_EXO:
|
||||
ctxt->secmon_size = curr_fss_cnt[i].size;
|
||||
ctxt->secmon = content;
|
||||
break;
|
||||
case CNT_TYPE_WBT:
|
||||
ctxt->warmboot_size = curr_fss_cnt[i].size;
|
||||
ctxt->warmboot = content;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load content to launch context.
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, content, curr_fss_cnt[i].size, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load sept content directly to launch context.
|
||||
switch (curr_fss_cnt[i].type)
|
||||
{
|
||||
case CNT_TYPE_SP1:
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, sept_ctxt->sept_primary, curr_fss_cnt[i].size, NULL);
|
||||
break;
|
||||
case CNT_TYPE_SP2:
|
||||
if (!memcmp(curr_fss_cnt[i].name, (sept_ctxt->kb < KB_FIRMWARE_VERSION_810) ? "septsecondary00" : "septsecondary01", 15))
|
||||
{
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, sept_ctxt->sept_secondary, curr_fss_cnt[i].size, NULL);
|
||||
sept_used = 1;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
gfx_printf("Done!\n");
|
||||
f_close(&fp);
|
||||
|
||||
_update_r2p(path);
|
||||
|
||||
return (!sept_ctxt ? 1 : sept_used);
|
||||
}
|
||||
|
||||
f_close(&fp);
|
||||
free(fss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_sept_from_ffs0(fss0_sept_t *sept_ctxt)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &sept_ctxt->cfg_sec->kvs, link)
|
||||
{
|
||||
if (!strcmp("fss0", kv->key))
|
||||
return parse_fss(NULL, kv->val, sept_ctxt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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 _FSS_H_
|
||||
#define _FSS_H_
|
||||
|
||||
#include "hos.h"
|
||||
|
||||
typedef struct _fss0_sept_t
|
||||
{
|
||||
u32 kb;
|
||||
ini_sec_t *cfg_sec;
|
||||
void *sept_primary;
|
||||
void *sept_secondary;
|
||||
|
||||
} fss0_sept_t;
|
||||
|
||||
int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt);
|
||||
int load_sept_from_ffs0(fss0_sept_t *sept_ctxt);
|
||||
|
||||
#endif
|
||||
@@ -1,953 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018 Ced2911
|
||||
* Copyright (c) 2018-2020 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 "hos.h"
|
||||
#include "hos_config.h"
|
||||
#include "sept.h"
|
||||
#include "secmon_exo.h"
|
||||
#include "../config/config.h"
|
||||
#include "../gfx/di.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../mem/mc.h"
|
||||
#include "../mem/minerva.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../sec/se_t210.h"
|
||||
#include "../sec/tsec.h"
|
||||
#include "../soc/bpmp.h"
|
||||
#include "../soc/cluster.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../soc/smmu.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../gfx/gfx.h"
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
#define EHPRINTFARGS(text, args...) \
|
||||
({ display_backlight_brightness(h_cfg.backlight, 1000); \
|
||||
gfx_con.mute = false; \
|
||||
gfx_printf("%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC); })
|
||||
|
||||
#define PKG2_LOAD_ADDR 0xA9800000
|
||||
|
||||
// Secmon mailbox.
|
||||
#define SECMON_MB_ADDR 0x40002EF8
|
||||
#define SECMON7_MB_ADDR 0x400000F8
|
||||
typedef struct _secmon_mailbox_t
|
||||
{
|
||||
// < 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot.
|
||||
// >= 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM ready, 4: pkg2 ready and continue boot.
|
||||
u32 in;
|
||||
// Non-zero: Secmon ready.
|
||||
u32 out;
|
||||
} secmon_mailbox_t;
|
||||
|
||||
static const u8 keyblob_keyseeds[][0x10] = {
|
||||
{ 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, //1.0.0
|
||||
{ 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, //3.0.0
|
||||
{ 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, //3.0.1
|
||||
{ 0x2D, 0x1F, 0x48, 0x80, 0xED, 0xEC, 0xED, 0x3E, 0x3C, 0xF2, 0x48, 0xB5, 0x65, 0x7D, 0xF7, 0xBE }, //4.0.0
|
||||
{ 0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80 }, //5.0.0
|
||||
{ 0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0 } //6.0.0
|
||||
};
|
||||
|
||||
static const u8 cmac_keyseed[0x10] =
|
||||
{ 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 };
|
||||
|
||||
static const u8 master_keyseed_retail[0x10] =
|
||||
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
|
||||
|
||||
static const u8 console_keyseed[0x10] =
|
||||
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
|
||||
|
||||
const u8 package2_keyseed[] =
|
||||
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
|
||||
|
||||
static const u8 master_keyseed_4xx_5xx_610[0x10] =
|
||||
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
|
||||
|
||||
static const u8 master_keyseed_620[0x10] =
|
||||
{ 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };
|
||||
|
||||
static const u8 console_keyseed_4xx_5xx[0x10] =
|
||||
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
|
||||
|
||||
static void _hos_crit_error(const char *text)
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
gfx_printf("%k%s%k\n", 0xFFFF0000, text, 0xFFCCCCCC);
|
||||
|
||||
display_backlight_brightness(h_cfg.backlight, 1000);
|
||||
}
|
||||
|
||||
static void _se_lock(bool lock_se)
|
||||
{
|
||||
if (lock_se)
|
||||
{
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
se_key_acc_ctrl(i, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
se_rsa_acc_ctrl(i, SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||
SE(SE_TZRAM_SECURITY_0) = 0; // Make SE TZRAM secure only.
|
||||
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = 0; // Make all key access regs secure only.
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all RSA access regs secure only.
|
||||
SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only.
|
||||
}
|
||||
|
||||
memset((void *)IPATCH_BASE, 0, 14 * sizeof(u32));
|
||||
SB(SB_CSR) = SB_CSR_PIROM_DISABLE;
|
||||
|
||||
// This is useful for documenting the bits in the SE config registers, so we can keep it around.
|
||||
/*gfx_printf("SE(SE_SECURITY_0) = %08X\n", SE(SE_SECURITY_0));
|
||||
gfx_printf("SE(0x4) = %08X\n", SE(0x4));
|
||||
gfx_printf("SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET));
|
||||
gfx_printf("SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET));
|
||||
for(u32 i = 0; i < 16; i++)
|
||||
gfx_printf("%02X ", SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + i * 4) & 0xFF);
|
||||
gfx_putc('\n');
|
||||
for(u32 i = 0; i < 2; i++)
|
||||
gfx_printf("%02X ", SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + i * 4) & 0xFF);
|
||||
gfx_putc('\n');
|
||||
gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/
|
||||
}
|
||||
|
||||
void _pmc_scratch_lock(u32 kb)
|
||||
{
|
||||
switch (kb)
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
case KB_FIRMWARE_VERSION_301:
|
||||
PMC(APBDEV_PMC_SEC_DISABLE) = 0x7FFFF3;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) = 0xFFAFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) = 0xFFAAFFFF;
|
||||
break;
|
||||
default:
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _sysctr0_reset()
|
||||
{
|
||||
SYSCTR0(SYSCTR0_CNTCR) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID0) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID1) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID2) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID3) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID4) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID5) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID6) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID7) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID8) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID9) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID10) = 0;
|
||||
SYSCTR0(SYSCTR0_COUNTERID11) = 0;
|
||||
}
|
||||
|
||||
void hos_eks_get()
|
||||
{
|
||||
// Check if EKS already found and parsed.
|
||||
if (!h_cfg.eks)
|
||||
{
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
|
||||
// Read EKS blob.
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
|
||||
// Decrypt EKS blob.
|
||||
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x10);
|
||||
se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Check if valid and for this unit.
|
||||
if (eks->enabled &&
|
||||
eks->magic == HOS_EKS_MAGIC &&
|
||||
eks->magic2 == HOS_EKS_MAGIC &&
|
||||
eks->sbk_low[0] == FUSE(FUSE_PRIVATE_KEY0) &&
|
||||
eks->sbk_low[1] == FUSE(FUSE_PRIVATE_KEY1))
|
||||
{
|
||||
h_cfg.eks = eks;
|
||||
return;
|
||||
}
|
||||
|
||||
free(mbr);
|
||||
}
|
||||
}
|
||||
|
||||
void hos_eks_save(u32 kb)
|
||||
{
|
||||
if (kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
// Only 6 Master keys for now.
|
||||
u8 key_idx = kb - KB_FIRMWARE_VERSION_700;
|
||||
if (key_idx > 5)
|
||||
return;
|
||||
|
||||
if (!h_cfg.eks)
|
||||
h_cfg.eks = calloc(512 , 1);
|
||||
|
||||
// If matching blob doesn't exist, create it.
|
||||
if (!(h_cfg.eks->enabled & (1 << key_idx)))
|
||||
{
|
||||
// Get keys.
|
||||
u8 *keys = (u8 *)calloc(0x1000, 1);
|
||||
se_get_aes_keys(keys + 0x800, keys, 0x10);
|
||||
|
||||
// Set magic and personalized info.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
h_cfg.eks->magic2 = HOS_EKS_MAGIC;
|
||||
h_cfg.eks->enabled |= 1 << key_idx;
|
||||
h_cfg.eks->sbk_low[0] = FUSE(FUSE_PRIVATE_KEY0);
|
||||
h_cfg.eks->sbk_low[1] = FUSE(FUSE_PRIVATE_KEY1);
|
||||
|
||||
// Copy new keys.
|
||||
memcpy(h_cfg.eks->keys[key_idx].dkg, keys + 10 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].dkk, keys + 15 * 0x10, 0x10);
|
||||
|
||||
// Encrypt EKS.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Write EKS to SD.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
|
||||
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
|
||||
|
||||
free(eks);
|
||||
free(mbr);
|
||||
free(keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hos_eks_clear(u32 kb)
|
||||
{
|
||||
if (h_cfg.eks && kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
// Check if Current Master key is enabled.
|
||||
u8 key_idx = kb - KB_FIRMWARE_VERSION_700;
|
||||
if (h_cfg.eks->enabled & (1 << key_idx))
|
||||
{
|
||||
// Disable current Master key version.
|
||||
h_cfg.eks->enabled &= ~(1 << key_idx);
|
||||
|
||||
// Encrypt EKS.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Write EKS to SD.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
|
||||
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
|
||||
|
||||
free(eks);
|
||||
free(mbr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
|
||||
{
|
||||
u8 tmp[0x20];
|
||||
u32 retries = 0;
|
||||
|
||||
if (kb > KB_FIRMWARE_VERSION_MAX)
|
||||
return 0;
|
||||
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
tsec_ctxt->size = 0xF00;
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
tsec_ctxt->size = 0x2900;
|
||||
else if (kb == KB_FIRMWARE_VERSION_700)
|
||||
tsec_ctxt->size = 0x3000;
|
||||
else
|
||||
tsec_ctxt->size = 0x3300;
|
||||
|
||||
// Prepare smmu tsec page for 6.2.0.
|
||||
if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
u8 *tsec_paged = (u8 *)page_alloc(3);
|
||||
memcpy(tsec_paged, (void *)tsec_ctxt->fw, tsec_ctxt->size);
|
||||
tsec_ctxt->fw = tsec_paged;
|
||||
}
|
||||
|
||||
// Get TSEC key.
|
||||
if (kb <= KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
while (tsec_query(tmp, kb, tsec_ctxt) < 0)
|
||||
{
|
||||
memset(tmp, 0x00, 0x20);
|
||||
retries++;
|
||||
|
||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||
if (retries > 15)
|
||||
{
|
||||
_hos_crit_error("\nFailed to get TSEC keys. Please try again.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
// Use HOS EKS if it exists.
|
||||
u8 key_idx = kb - KB_FIRMWARE_VERSION_700;
|
||||
if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx)))
|
||||
{
|
||||
// Set Device keygen key to slot 10.
|
||||
se_aes_key_set(10, h_cfg.eks->keys[key_idx].dkg, 0x10);
|
||||
// Set Master key to slot 12.
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10);
|
||||
// Set FW Device key key to slot 13.
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10);
|
||||
// Set Device key to slot 15.
|
||||
se_aes_key_set(15, h_cfg.eks->keys[key_idx].dkk, 0x10);
|
||||
|
||||
// Lock FDK.
|
||||
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
}
|
||||
|
||||
se_aes_key_clear(8);
|
||||
se_aes_unwrap_key(8, 12, package2_keyseed);
|
||||
}
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
// Set TSEC key.
|
||||
se_aes_key_set(12, tmp, 0x10);
|
||||
// Set TSEC root key.
|
||||
se_aes_key_set(13, tmp + 0x10, 0x10);
|
||||
|
||||
if (!(emu_cfg.enabled && !h_cfg.emummc_force_disable) && hos_ctxt->stock)
|
||||
{
|
||||
// Package2 key.
|
||||
se_aes_key_set(8, tmp + 0x10, 0x10);
|
||||
se_aes_unwrap_key(8, 8, master_keyseed_620);
|
||||
se_aes_unwrap_key(8, 8, master_keyseed_retail);
|
||||
se_aes_unwrap_key(8, 8, package2_keyseed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decrypt keyblob and set keyslots
|
||||
se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tmp + 0x20);
|
||||
se_aes_unwrap_key(14, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
|
||||
se_aes_unwrap_key(13, 13, master_keyseed_620);
|
||||
se_aes_unwrap_key(12, 13, master_keyseed_retail);
|
||||
se_aes_unwrap_key(10, 13, master_keyseed_4xx_5xx_610);
|
||||
|
||||
// Package2 key.
|
||||
se_aes_unwrap_key(8, 12, package2_keyseed);
|
||||
|
||||
h_cfg.se_keygen_done = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
|
||||
// Set TSEC key.
|
||||
se_aes_key_set(13, tmp, 0x10);
|
||||
|
||||
// Derive keyblob keys from TSEC+SBK.
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tmp);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
|
||||
// Clear SBK.
|
||||
se_aes_key_clear(14);
|
||||
|
||||
//TODO: verify keyblob CMAC.
|
||||
//se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
//se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0);
|
||||
//if (!memcmp(keyblob, tmp, 0x10))
|
||||
// return 0;
|
||||
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed);
|
||||
se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
|
||||
// Decrypt keyblob and set keyslots.
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); // Package1 key.
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
se_aes_key_set(13, keyblob + 0x20, 0x10);
|
||||
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail);
|
||||
|
||||
switch (kb)
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
case KB_FIRMWARE_VERSION_301:
|
||||
se_aes_unwrap_key(13, 15, console_keyseed);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
case KB_FIRMWARE_VERSION_600:
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
}
|
||||
|
||||
// Package2 key.
|
||||
se_key_acc_ctrl(8, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
se_aes_unwrap_key(8, 12, package2_keyseed);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
|
||||
{
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
int res = emummc_storage_init_mmc(&storage, &sdmmc);
|
||||
|
||||
if (res)
|
||||
{
|
||||
if (res == 2)
|
||||
_hos_crit_error("Failed to init eMMC");
|
||||
else
|
||||
_hos_crit_error("Failed to init emuMMC");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read package1.
|
||||
ctxt->pkg1 = (void *)malloc(0x40000);
|
||||
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
|
||||
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1);
|
||||
if (!ctxt->pkg1_id)
|
||||
{
|
||||
_hos_crit_error("Unknown pkg1 version.");
|
||||
EHPRINTFARGS("%sNot yet supported HOS version!",
|
||||
(emu_cfg.enabled && !h_cfg.emummc_force_disable) ? "Is emuMMC corrupt?\nOr " : "");
|
||||
goto out;
|
||||
}
|
||||
gfx_printf("Identified pkg1 and Keyblob %d\n\n", ctxt->pkg1_id->kb);
|
||||
|
||||
// Read the correct keyblob.
|
||||
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
emummc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
|
||||
|
||||
res = 1;
|
||||
|
||||
out:;
|
||||
sdmmc_storage_end(&storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
|
||||
{
|
||||
u8 *bctBuf = NULL;
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
int res = emummc_storage_init_mmc(&storage, &sdmmc);
|
||||
|
||||
if (res)
|
||||
{
|
||||
if (res == 2)
|
||||
_hos_crit_error("Failed to init eMMC");
|
||||
else
|
||||
_hos_crit_error("Failed to init emuMMC");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
emummc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
// Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
DPRINTF("Parsed GPT\n");
|
||||
// Find package2 partition.
|
||||
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
|
||||
if (!pkg2_part)
|
||||
goto out;
|
||||
|
||||
// Read in package2 header and get package2 real size.
|
||||
//TODO: implement memalign for DMA buffers.
|
||||
static const u32 BCT_SIZE = 0x4000;
|
||||
bctBuf = (u8 *)malloc(BCT_SIZE);
|
||||
nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE, 1, bctBuf);
|
||||
u32 *hdr = (u32 *)(bctBuf + 0x100);
|
||||
u32 pkg2_size = hdr[0] ^ hdr[2] ^ hdr[3];
|
||||
DPRINTF("pkg2 size on emmc is %08X\n", pkg2_size);
|
||||
|
||||
// Read in Boot Config.
|
||||
memset(bctBuf, 0, BCT_SIZE);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0, BCT_SIZE / NX_EMMC_BLOCKSIZE, bctBuf);
|
||||
|
||||
// Read in package2.
|
||||
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
|
||||
DPRINTF("pkg2 size aligned is %08X\n", pkg2_size_aligned);
|
||||
ctxt->pkg2 = malloc(pkg2_size_aligned);
|
||||
ctxt->pkg2_size = pkg2_size;
|
||||
nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE,
|
||||
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, ctxt->pkg2);
|
||||
out:;
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
return bctBuf;
|
||||
}
|
||||
|
||||
static void _free_launch_components(launch_ctxt_t *ctxt)
|
||||
{
|
||||
free(ctxt->keyblob);
|
||||
free(ctxt->pkg1);
|
||||
free(ctxt->pkg2);
|
||||
free(ctxt->warmboot);
|
||||
free(ctxt->secmon);
|
||||
free(ctxt->kernel);
|
||||
free(ctxt->kip1_patches);
|
||||
}
|
||||
|
||||
static bool _get_fs_exfat_compatible(link_t *info)
|
||||
{
|
||||
u32 fs_idx;
|
||||
u32 fs_ids_cnt;
|
||||
u32 sha_buf[32 / sizeof(u32)];
|
||||
kip1_id_t *kip_ids;
|
||||
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
||||
{
|
||||
if (strncmp((const char*)ki->kip1->name, "FS", 2))
|
||||
continue;
|
||||
|
||||
if (!se_calc_sha256(sha_buf, ki->kip1, ki->size))
|
||||
break;
|
||||
|
||||
pkg2_get_ids(&kip_ids, &fs_ids_cnt);
|
||||
|
||||
for (fs_idx = 0; fs_idx < fs_ids_cnt; fs_idx++)
|
||||
if (!memcmp(sha_buf, kip_ids[fs_idx].hash, 8))
|
||||
break;
|
||||
|
||||
// Return false if FAT32 only.
|
||||
if (fs_ids_cnt <= fs_idx && !(fs_idx & 1))
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int hos_launch(ini_sec_t *cfg)
|
||||
{
|
||||
minerva_change_freq(FREQ_1600);
|
||||
launch_ctxt_t ctxt;
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
volatile secmon_mailbox_t *secmon_mb;
|
||||
|
||||
memset(&ctxt, 0, sizeof(launch_ctxt_t));
|
||||
memset(&tsec_ctxt, 0, sizeof(tsec_ctxt_t));
|
||||
list_init(&ctxt.kip1_list);
|
||||
|
||||
ctxt.cfg = cfg;
|
||||
|
||||
if (!gfx_con.mute)
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
gfx_printf("Initializing...\n\n");
|
||||
|
||||
// Read package1 and the correct keyblob.
|
||||
if (!_read_emmc_pkg1(&ctxt))
|
||||
return 0;
|
||||
|
||||
// Try to parse config if present.
|
||||
if (ctxt.cfg && !parse_boot_config(&ctxt))
|
||||
{
|
||||
_hos_crit_error("Wrong ini cfg or missing files!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Enable emummc patching.
|
||||
if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
||||
{
|
||||
if (ctxt.stock)
|
||||
{
|
||||
_hos_crit_error("Stock emuMMC is not supported yet!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctxt.atmosphere = true; // Set atmosphere patching in case of Stock emuMMC and no fss0.
|
||||
config_kip1patch(&ctxt, "emummc");
|
||||
}
|
||||
else if (!emu_cfg.enabled && ctxt.emummc_forced)
|
||||
{
|
||||
_hos_crit_error("emuMMC is forced but not enabled!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if fuses lower than 4.0.0 or 9.0.0 and if yes apply NO Gamecard patch.
|
||||
// Additionally check if running emuMMC and disable GC if v3 fuses are burnt and HOS is <= 8.1.0.
|
||||
if (!ctxt.stock)
|
||||
{
|
||||
u32 fuses = fuse_read_odm(7);
|
||||
if ((h_cfg.autonogc &&
|
||||
((!(fuses & ~0xF) && (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_400)) || // LAFW v2.
|
||||
(!(fuses & ~0x3FF) && (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_900)))) // LAFW v3.
|
||||
|| ((emu_cfg.enabled && !h_cfg.emummc_force_disable) &&
|
||||
((fuses & 0x400) && (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_810))))
|
||||
config_kip1patch(&ctxt, "nogc");
|
||||
}
|
||||
|
||||
gfx_printf("Loaded config, pkg1 and keyblob\n");
|
||||
|
||||
// Generate keys.
|
||||
if (!h_cfg.se_keygen_done)
|
||||
{
|
||||
tsec_ctxt.fw = (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = ctxt.pkg1;
|
||||
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = ctxt.pkg1_id->secmon_base;
|
||||
|
||||
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
|
||||
{
|
||||
_hos_crit_error("Failed to run sept");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hos_keygen(ctxt.keyblob, ctxt.pkg1_id->kb, &tsec_ctxt, &ctxt))
|
||||
return 0;
|
||||
gfx_printf("Generated keys\n");
|
||||
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600)
|
||||
h_cfg.se_keygen_done = 1;
|
||||
}
|
||||
|
||||
// Decrypt and unpack package1 if we require parts of it.
|
||||
if (!ctxt.warmboot || !ctxt.secmon)
|
||||
{
|
||||
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600)
|
||||
pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1);
|
||||
|
||||
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && !(emu_cfg.enabled && !h_cfg.emummc_force_disable))
|
||||
{
|
||||
pkg1_unpack((void *)ctxt.pkg1_id->warmboot_base, (void *)ctxt.pkg1_id->secmon_base, NULL, ctxt.pkg1_id, ctxt.pkg1);
|
||||
gfx_printf("Decrypted & unpacked pkg1\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
_hos_crit_error("No mandatory secmon or warmboot provided!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace 'warmboot.bin' if requested.
|
||||
if (ctxt.warmboot)
|
||||
memcpy((void *)ctxt.pkg1_id->warmboot_base, ctxt.warmboot, ctxt.warmboot_size);
|
||||
else
|
||||
{
|
||||
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
_hos_crit_error("No warmboot provided!");
|
||||
return 0;
|
||||
}
|
||||
// Else we patch it to allow downgrading.
|
||||
patch_t *warmboot_patchset = ctxt.pkg1_id->warmboot_patchset;
|
||||
gfx_printf("%kPatching Warmboot%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
for (u32 i = 0; warmboot_patchset[i].off != 0xFFFFFFFF; i++)
|
||||
*(vu32 *)(ctxt.pkg1_id->warmboot_base + warmboot_patchset[i].off) = warmboot_patchset[i].val;
|
||||
}
|
||||
// Set warmboot address in PMC if required.
|
||||
if (ctxt.pkg1_id->set_warmboot)
|
||||
PMC(APBDEV_PMC_SCRATCH1) = ctxt.pkg1_id->warmboot_base;
|
||||
|
||||
// Replace 'SecureMonitor' if requested.
|
||||
if (ctxt.secmon)
|
||||
memcpy((void *)ctxt.pkg1_id->secmon_base, ctxt.secmon, ctxt.secmon_size);
|
||||
else if (ctxt.pkg1_id->secmon_patchset)
|
||||
{
|
||||
// Else we patch it to allow for an unsigned package2 and patched kernel.
|
||||
patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset;
|
||||
gfx_printf("%kPatching Secure Monitor%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++)
|
||||
*(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
|
||||
}
|
||||
|
||||
gfx_printf("Loaded warmboot and secmon\n");
|
||||
|
||||
// Read package2.
|
||||
u8 *bootConfigBuf = _read_emmc_pkg2(&ctxt);
|
||||
if (!bootConfigBuf)
|
||||
return 0;
|
||||
|
||||
gfx_printf("Read pkg2\n");
|
||||
|
||||
// Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2, ctxt.pkg1_id->kb);
|
||||
if (!pkg2_hdr)
|
||||
{
|
||||
_hos_crit_error("Pkg2 decryption failed!");
|
||||
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
EPRINTF("Is Sept updated?");
|
||||
|
||||
// Clear EKS slot, in case something went wrong with sept keygen.
|
||||
hos_eks_clear(ctxt.pkg1_id->kb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
|
||||
hos_eks_save(ctxt.pkg1_id->kb); // Save EKS slot if it doesn't exist.
|
||||
|
||||
LIST_INIT(kip1_info);
|
||||
if (!pkg2_parse_kips(&kip1_info, pkg2_hdr, &ctxt.new_pkg2))
|
||||
{
|
||||
_hos_crit_error("INI1 parsing failed!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gfx_printf("Parsed ini1\n");
|
||||
|
||||
// Use the kernel included in package2 in case we didn't load one already.
|
||||
if (!ctxt.kernel)
|
||||
{
|
||||
ctxt.kernel = pkg2_hdr->data;
|
||||
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||
|
||||
if (!ctxt.stock && (ctxt.svcperm || ctxt.debugmode || ctxt.atmosphere))
|
||||
{
|
||||
u8 kernel_hash[0x20];
|
||||
// Hash only Kernel when it embeds INI1.
|
||||
if (!ctxt.new_pkg2)
|
||||
se_calc_sha256(kernel_hash, ctxt.kernel, ctxt.kernel_size);
|
||||
else
|
||||
se_calc_sha256(kernel_hash, ctxt.kernel + PKG2_NEWKERN_START,
|
||||
pkg2_newkern_ini1_start - PKG2_NEWKERN_START);
|
||||
|
||||
ctxt.pkg2_kernel_id = pkg2_identify(kernel_hash);
|
||||
if (!ctxt.pkg2_kernel_id)
|
||||
{
|
||||
_hos_crit_error("Failed to identify kernel!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// In case a kernel patch option is set; allows to disable SVC verification or/and enable debug mode.
|
||||
kernel_patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset;
|
||||
if (kernel_patchset != NULL)
|
||||
{
|
||||
gfx_printf("%kPatching kernel%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
u32 *temp;
|
||||
for (u32 i = 0; kernel_patchset[i].id != 0xFFFFFFFF; i++)
|
||||
{
|
||||
if ((ctxt.svcperm && kernel_patchset[i].id == SVC_VERIFY_DS)
|
||||
|| (ctxt.debugmode && kernel_patchset[i].id == DEBUG_MODE_EN && !(ctxt.atmosphere && ctxt.secmon))
|
||||
|| (ctxt.atmosphere && kernel_patchset[i].id == ATM_GEN_PATCH))
|
||||
*(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val;
|
||||
else if (ctxt.atmosphere && kernel_patchset[i].id == ATM_ARR_PATCH)
|
||||
{
|
||||
temp = (u32 *)kernel_patchset[i].ptr;
|
||||
for (u32 j = 0; j < kernel_patchset[i].val; j++)
|
||||
*(vu32 *)(ctxt.kernel + kernel_patchset[i].off + (j << 2)) = temp[j];
|
||||
}
|
||||
else if (kernel_patchset[i].id < SVC_VERIFY_DS)
|
||||
*(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge extra KIP1s into loaded ones.
|
||||
gfx_printf("%kPatching kips%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
|
||||
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
|
||||
|
||||
// Check if FS is compatible with exFAT.
|
||||
if (!ctxt.stock && sd_fs.fs_type == FS_EXFAT && !_get_fs_exfat_compatible(&kip1_info))
|
||||
{
|
||||
_hos_crit_error("SD Card is exFAT and the installed\nFS only supports FAT32!");
|
||||
|
||||
_free_launch_components(&ctxt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Patch kip1s in memory if needed.
|
||||
const char* unappliedPatch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches);
|
||||
if (unappliedPatch != NULL)
|
||||
{
|
||||
EHPRINTFARGS("Failed to apply '%s'!", unappliedPatch);
|
||||
|
||||
_free_launch_components(&ctxt);
|
||||
return 0; // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated!
|
||||
}
|
||||
|
||||
// Rebuild and encrypt package2.
|
||||
pkg2_build_encrypt((void *)PKG2_LOAD_ADDR, ctxt.kernel, ctxt.kernel_size, &kip1_info, ctxt.new_pkg2);
|
||||
|
||||
gfx_printf("Rebuilt & loaded pkg2\n");
|
||||
|
||||
// Unmount SD card.
|
||||
sd_unmount();
|
||||
|
||||
gfx_printf("\n%kBooting...%k\n", 0xFF96FF00, 0xFFCCCCCC);
|
||||
|
||||
// Clear pkg1/pkg2 keys.
|
||||
se_aes_key_clear(8);
|
||||
se_aes_key_clear(11);
|
||||
|
||||
// Finalize per firmware keys.
|
||||
int bootStateDramPkg2 = 0;
|
||||
int bootStatePkg2Continue = 0;
|
||||
|
||||
switch (ctxt.pkg1_id->kb)
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
case KB_FIRMWARE_VERSION_301:
|
||||
if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_300)
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id.
|
||||
else if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_301)
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id.
|
||||
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
|
||||
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
|
||||
bootStateDramPkg2 = 2;
|
||||
bootStatePkg2Continue = 3;
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
case KB_FIRMWARE_VERSION_600:
|
||||
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
|
||||
se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
|
||||
default:
|
||||
bootStateDramPkg2 = 2;
|
||||
bootStatePkg2Continue = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear BCT area for retail units and copy it over if dev unit.
|
||||
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_500)
|
||||
{
|
||||
memset((void *)0x4003D000, 0, 0x3000);
|
||||
if ((fuse_read_odm(4) & 3) == 3)
|
||||
memcpy((void *)0x4003D000, bootConfigBuf, 0x1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset((void *)0x4003F000, 0, 0x1000);
|
||||
if ((fuse_read_odm(4) & 3) == 3)
|
||||
memcpy((void *)0x4003F800, bootConfigBuf, 0x800);
|
||||
}
|
||||
free(bootConfigBuf);
|
||||
|
||||
// Config Exosphère if booting full Atmosphère.
|
||||
if (ctxt.atmosphere && ctxt.secmon)
|
||||
config_exosphere(&ctxt);
|
||||
|
||||
// Finalize MC carveout.
|
||||
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_301)
|
||||
mc_config_carveout();
|
||||
|
||||
// Lock SE before starting 'SecureMonitor' if < 6.2.0, otherwise lock bootrom and ipatches.
|
||||
_se_lock(ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600);
|
||||
|
||||
// Reset sysctr0 counters.
|
||||
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_620)
|
||||
_sysctr0_reset();
|
||||
|
||||
// < 4.0.0 pkg1.1 locks PMC scratches.
|
||||
//_pmc_scratch_lock(ctxt.pkg1_id->kb);
|
||||
|
||||
// Set secmon mailbox address.
|
||||
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
|
||||
secmon_mb = (secmon_mailbox_t *)SECMON7_MB_ADDR;
|
||||
else
|
||||
secmon_mb = (secmon_mailbox_t *)SECMON_MB_ADDR;
|
||||
|
||||
// Start from DRAM ready signal and reset outgoing value.
|
||||
secmon_mb->in = bootStateDramPkg2;
|
||||
secmon_mb->out = 0;
|
||||
|
||||
// Disable display. This must be executed before secmon to provide support for all fw versions.
|
||||
display_end();
|
||||
|
||||
// Clear EMC_SCRATCH0.
|
||||
EMC(EMC_SCRATCH0) = 0;
|
||||
|
||||
// Flush cache and disable MMU.
|
||||
bpmp_mmu_disable();
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
minerva_change_freq(FREQ_1600);
|
||||
|
||||
// emuMMC: Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
||||
sdmmc_storage_init_wait_sd();
|
||||
|
||||
// Wait for secmon to get ready.
|
||||
if (smmu_is_used())
|
||||
smmu_exit();
|
||||
else
|
||||
cluster_boot_cpu0(ctxt.pkg1_id->secmon_base);
|
||||
while (!secmon_mb->out)
|
||||
; // A usleep(1) only works when in IRAM or with a trained DRAM.
|
||||
|
||||
// Signal pkg2 ready and continue boot.
|
||||
secmon_mb->in = bootStatePkg2Continue;
|
||||
|
||||
// Halt ourselves in waitevent state and resume if there's JTAG activity.
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* 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 _HOS_H_
|
||||
#define _HOS_H_
|
||||
|
||||
#include "pkg1.h"
|
||||
#include "pkg2.h"
|
||||
#include "../utils/types.h"
|
||||
#include "../config/ini.h"
|
||||
#include "../sec/tsec.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define KB_FIRMWARE_VERSION_100_200 0
|
||||
#define KB_FIRMWARE_VERSION_300 1
|
||||
#define KB_FIRMWARE_VERSION_301 2
|
||||
#define KB_FIRMWARE_VERSION_400 3
|
||||
#define KB_FIRMWARE_VERSION_500 4
|
||||
#define KB_FIRMWARE_VERSION_600 5
|
||||
#define KB_FIRMWARE_VERSION_620 6
|
||||
#define KB_FIRMWARE_VERSION_700 7
|
||||
#define KB_FIRMWARE_VERSION_810 8
|
||||
#define KB_FIRMWARE_VERSION_900 9
|
||||
#define KB_FIRMWARE_VERSION_910 10
|
||||
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_910
|
||||
|
||||
#define HOS_PKG11_MAGIC 0x31314B50
|
||||
#define HOS_EKS_MAGIC 0x30534B45
|
||||
|
||||
typedef struct _exo_ctxt_t
|
||||
{
|
||||
bool no_user_exceptions;
|
||||
bool user_pmu;
|
||||
bool *cal0_blank;
|
||||
bool *cal0_allow_writes_sys;
|
||||
} exo_ctxt_t;
|
||||
|
||||
typedef struct _hos_eks_keys_t
|
||||
{
|
||||
u8 dkg[0x10];
|
||||
u8 mkk[0x10];
|
||||
u8 fdk[0x10];
|
||||
u8 dkk[0x10];
|
||||
} hos_eks_keys_t;
|
||||
|
||||
typedef struct _hos_eks_mbr_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 enabled;
|
||||
u32 sbk_low[2];
|
||||
hos_eks_keys_t keys[6];
|
||||
u32 magic2;
|
||||
u32 rsvd2[3];
|
||||
} hos_eks_mbr_t;
|
||||
|
||||
static_assert(sizeof(hos_eks_mbr_t) < 424, "HOS EKS storage bigger than MBR!");
|
||||
|
||||
typedef struct _launch_ctxt_t
|
||||
{
|
||||
void *keyblob;
|
||||
|
||||
void *pkg1;
|
||||
const pkg1_id_t *pkg1_id;
|
||||
const pkg2_kernel_id_t *pkg2_kernel_id;
|
||||
|
||||
void *warmboot;
|
||||
u32 warmboot_size;
|
||||
void *secmon;
|
||||
u32 secmon_size;
|
||||
|
||||
void *pkg2;
|
||||
u32 pkg2_size;
|
||||
bool new_pkg2;
|
||||
|
||||
void *kernel;
|
||||
u32 kernel_size;
|
||||
link_t kip1_list;
|
||||
char* kip1_patches;
|
||||
|
||||
u32 fss0_hosver;
|
||||
bool svcperm;
|
||||
bool debugmode;
|
||||
bool stock;
|
||||
bool atmosphere;
|
||||
bool fss0_enable_experimental;
|
||||
bool emummc_forced;
|
||||
|
||||
exo_ctxt_t exo_cfg;
|
||||
|
||||
ini_sec_t *cfg;
|
||||
} launch_ctxt_t;
|
||||
|
||||
typedef struct _merge_kip_t
|
||||
{
|
||||
void *kip1;
|
||||
link_t link;
|
||||
} merge_kip_t;
|
||||
|
||||
void hos_eks_get();
|
||||
void hos_eks_save(u32 kb);
|
||||
void hos_eks_clear(u32 kb);
|
||||
int hos_launch(ini_sec_t *cfg);
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
|
||||
|
||||
#endif
|
||||
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* 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 "hos.h"
|
||||
#include "hos_config.h"
|
||||
#include "fss.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../utils/dirlist.h"
|
||||
|
||||
#include "../gfx/gfx.h"
|
||||
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
ctxt->warmboot = sd_file_read(value, &ctxt->warmboot_size);
|
||||
if (!ctxt->warmboot)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_secmon(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
ctxt->secmon = sd_file_read(value, &ctxt->secmon_size);
|
||||
if (!ctxt->secmon)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_kernel(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
ctxt->kernel = sd_file_read(value, &ctxt->kernel_size);
|
||||
if (!ctxt->kernel)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
if (!memcmp(value + strlen(value) - 1, "*", 1))
|
||||
{
|
||||
char *dir = (char *)malloc(256);
|
||||
strcpy(dir, value);
|
||||
|
||||
u32 dirlen = 0;
|
||||
dir[strlen(dir) - 2] = 0;
|
||||
char *filelist = dirlist(dir, "*.kip*", false);
|
||||
|
||||
strcat(dir, "/");
|
||||
dirlen = strlen(dir);
|
||||
|
||||
u32 i = 0;
|
||||
if (filelist)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!filelist[i * 256])
|
||||
break;
|
||||
|
||||
strcpy(dir + dirlen, &filelist[i * 256]);
|
||||
|
||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||
mkip1->kip1 = sd_file_read(dir, &size);
|
||||
if (!mkip1->kip1)
|
||||
{
|
||||
free(mkip1);
|
||||
free(dir);
|
||||
free(filelist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DPRINTF("Loaded kip1 from SD (size %08X)\n", size);
|
||||
list_append(&ctxt->kip1_list, &mkip1->link);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
free(dir);
|
||||
free(filelist);
|
||||
}
|
||||
else
|
||||
{
|
||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||
mkip1->kip1 = sd_file_read(value, &size);
|
||||
if (!mkip1->kip1)
|
||||
{
|
||||
free(mkip1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DPRINTF("Loaded kip1 from SD (size %08X)\n", size);
|
||||
list_append(&ctxt->kip1_list, &mkip1->link);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int config_kip1patch(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
|
||||
int valueLen = strlen(value);
|
||||
if (!valueLen)
|
||||
return 0;
|
||||
|
||||
if (ctxt->kip1_patches == NULL)
|
||||
{
|
||||
ctxt->kip1_patches = malloc(valueLen + 1);
|
||||
memcpy(ctxt->kip1_patches, value, valueLen);
|
||||
ctxt->kip1_patches[valueLen] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *oldAlloc = ctxt->kip1_patches;
|
||||
int oldSize = strlen(oldAlloc);
|
||||
ctxt->kip1_patches = malloc(oldSize + 1 + valueLen + 1);
|
||||
memcpy(ctxt->kip1_patches, oldAlloc, oldSize);
|
||||
free(oldAlloc);
|
||||
oldAlloc = NULL;
|
||||
ctxt->kip1_patches[oldSize++] = ',';
|
||||
memcpy(&ctxt->kip1_patches[oldSize], value, valueLen);
|
||||
ctxt->kip1_patches[oldSize + valueLen] = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_svcperm(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Disabled SVC verification\n");
|
||||
ctxt->svcperm = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_debugmode(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled Debug mode\n");
|
||||
ctxt->debugmode = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_stock(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Disabled all patching\n");
|
||||
ctxt->stock = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_emummc_forced(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Forced emuMMC\n");
|
||||
ctxt->emummc_forced = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_atmosphere(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled atmosphere patching\n");
|
||||
ctxt->atmosphere = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_dis_exo_user_exceptions(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Disabled exosphere user exception handlers\n");
|
||||
ctxt->exo_cfg.no_user_exceptions = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled user access to PMU\n");
|
||||
ctxt->exo_cfg.user_pmu = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_cfg.cal0_blank = calloc(1, 1);
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled prodinfo blanking\n");
|
||||
*ctxt->exo_cfg.cal0_blank = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_cfg.cal0_allow_writes_sys = calloc(1, 1);
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled prodinfo writes\n");
|
||||
*ctxt->exo_cfg.cal0_allow_writes_sys = true;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_fss(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||
{
|
||||
if (!strcmp("fss0experimental", kv->key))
|
||||
{
|
||||
ctxt->fss0_enable_experimental = *kv->val == '1';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return parse_fss(ctxt, value, NULL);
|
||||
}
|
||||
|
||||
typedef struct _cfg_handler_t
|
||||
{
|
||||
const char *key;
|
||||
int (*handler)(launch_ctxt_t *ctxt, const char *value);
|
||||
} cfg_handler_t;
|
||||
|
||||
static const cfg_handler_t _config_handlers[] = {
|
||||
{ "warmboot", _config_warmboot },
|
||||
{ "secmon", _config_secmon },
|
||||
{ "kernel", _config_kernel },
|
||||
{ "kip1", _config_kip1 },
|
||||
{ "kip1patch", config_kip1patch },
|
||||
{ "fullsvcperm", _config_svcperm },
|
||||
{ "debugmode", _config_debugmode },
|
||||
{ "stock", _config_stock },
|
||||
{ "atmosphere", _config_atmosphere },
|
||||
{ "fss0", _config_fss },
|
||||
{ "emummcforce", _config_emummc_forced },
|
||||
{ "nouserexceptions", _config_dis_exo_user_exceptions },
|
||||
{ "userpmu", _config_exo_user_pmu_access },
|
||||
{ "cal0blank", _config_exo_cal0_blanking },
|
||||
{ "cal0writesys", _config_exo_cal0_writes_enable },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
int parse_boot_config(launch_ctxt_t *ctxt)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||
{
|
||||
for(u32 i = 0; _config_handlers[i].key; i++)
|
||||
{
|
||||
if (!strcmp(_config_handlers[i].key, kv->key))
|
||||
{
|
||||
if (!_config_handlers[i].handler(ctxt, kv->val))
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
EPRINTFARGS("Error while loading %s:\n%s", kv->key, kv->val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* 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 _HOS_CONFIG_H_
|
||||
#define _HOS_CONFIG_H_
|
||||
|
||||
#include "hos.h"
|
||||
|
||||
int parse_boot_config(launch_ctxt_t *ctxt);
|
||||
int config_kip1patch(launch_ctxt_t *ctxt, const char *value);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018-2020 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 "pkg1.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../utils/aarch64_util.h"
|
||||
|
||||
#define _NOPv7() 0xE320F000
|
||||
|
||||
#define SM_100_ADR 0x4002B020
|
||||
PATCHSET_DEF(_secmon_1_patchset,
|
||||
// Patch the relocator to be able to run from SM_100_ADR.
|
||||
{ 0x1E0, _ADRP(0, 0x7C013000 - _PAGEOFF(SM_100_ADR)) },
|
||||
//Patch package2 decryption and signature/hash checks.
|
||||
{ 0x9F0 + 0xADC, _NOP() }, //Header signature.
|
||||
{ 0x9F0 + 0xB8C, _NOP() }, //Version.
|
||||
{ 0x9F0 + 0xBB0, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_2_patchset,
|
||||
// Patch package2 decryption and signature/hash checks.
|
||||
{ 0xAC8 + 0xAAC, _NOP() }, //Header signature.
|
||||
{ 0xAC8 + 0xB3C, _NOP() }, //Version.
|
||||
{ 0xAC8 + 0xB58, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_3_patchset,
|
||||
// Patch package2 decryption and signature/hash checks.
|
||||
{ 0xAC8 + 0xA30, _NOP() }, //Header signature.
|
||||
{ 0xAC8 + 0xAB4, _NOP() }, //package2 structure.
|
||||
{ 0xAC8 + 0xAC0, _NOP() }, //Version.
|
||||
{ 0xAC8 + 0xADC, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_4_patchset,
|
||||
// Patch package2 decryption and signature/hash checks.
|
||||
{ 0x2300 + 0x5D80, _NOP() }, //package2 structure.
|
||||
{ 0x2300 + 0x5D8C, _NOP() }, //Version.
|
||||
{ 0x2300 + 0x5EFC, _NOP() }, //Header signature.
|
||||
{ 0xAC8 + 0xA2C, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_5_patchset,
|
||||
// Patch package2 decryption and signature/hash checks.
|
||||
{ 0xDA8 + 0x9D8, _NOP() }, //package2 structure.
|
||||
{ 0xDA8 + 0x9E4, _NOP() }, //Version.
|
||||
{ 0xDA8 + 0xC9C, _NOP() }, //Header signature.
|
||||
{ 0xDA8 + 0x1038, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_6_patchset,
|
||||
// Patch package2 decryption and signature/hash checks.
|
||||
{ 0xDC8 + 0x820, _NOP() }, //package2 structure.
|
||||
{ 0xDC8 + 0x82C, _NOP() }, //Version.
|
||||
{ 0xDC8 + 0xE90, _NOP() }, //Header signature.
|
||||
{ 0xDC8 + 0x112C, _NOP() } //Sections SHA2.
|
||||
// Fix sleep mode for debug.
|
||||
// { 0x1A68 + 0x3854, 0x94000E45 }, //gpio_config_for_uart.
|
||||
// { 0x1A68 + 0x3858, 0x97FFFC0F }, //clkrst_reboot_uarta.
|
||||
// { 0x1A68 + 0x385C, 0x52A00021 }, //MOV W1, #0x10000 ; baudrate.
|
||||
// { 0x1A68 + 0x3860, 0x2A1F03E0 }, //MOV W0, WZR ; uart_port -> A.
|
||||
// { 0x1A68 + 0x3864, 0x72984001 }, //MOVK W1, #0xC200 ; baudrate.
|
||||
// { 0x1A68 + 0x3868, 0x94000C8C }, //uart_configure.
|
||||
// { 0x1A68 + 0x3A6C, _NOP() } // warmboot UARTA cfg.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_620_patchset,
|
||||
// Patch package2 decryption and signature/hash checks.
|
||||
{ 0xDC8 + 0x604, _NOP() }, //package2 structure.
|
||||
{ 0xDC8 + 0x610, _NOP() }, //Version.
|
||||
{ 0xDC8 + 0xC74, _NOP() }, //Header signature.
|
||||
{ 0xDC8 + 0xF10, _NOP() } //Sections SHA2.
|
||||
// Fix sleep mode for debug.
|
||||
// { 0x2AC8 + 0x3854, 0x94000F42 }, //gpio_config_for_uart.
|
||||
// { 0x2AC8 + 0x3858, 0x97FFFC0F }, //clkrst_reboot_uarta.
|
||||
// { 0x2AC8 + 0x385C, 0x52A00021 }, //MOV W1, #0x10000 ; baudrate.
|
||||
// { 0x2AC8 + 0x3860, 0x2A1F03E0 }, //MOV W0, WZR ; uart_port -> A.
|
||||
// { 0x2AC8 + 0x3864, 0x72984001 }, //MOVK W1, #0xC200 ; baudrate.
|
||||
// { 0x2AC8 + 0x3868, 0x94000D89 }, //uart_configure.
|
||||
// { 0x2AC8 + 0x3A6C, _NOP() } // warmboot UARTA cfg.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_1_patchset,
|
||||
{ 0x4DC, _NOPv7() } // Fuse check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_2_patchset,
|
||||
{ 0x4DC, _NOPv7() } // Fuse check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_3_patchset,
|
||||
{ 0x4DC, _NOPv7() }, // Fuse check.
|
||||
{ 0x4F0, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_4_patchset,
|
||||
{ 0x544, _NOPv7() }, // Fuse check.
|
||||
{ 0x558, _NOPv7() } // Segment id check.
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* package1.1 header: <wb, ldr, sm>
|
||||
* package1.1 layout:
|
||||
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
|
||||
* 2.0: {wb, ldr, sm} { 0, 1, 2 }
|
||||
* 3.0: {wb, ldr, sm} { 0, 1, 2 }
|
||||
* 3.1: {wb, ldr, sm} { 0, 1, 2 }
|
||||
* 4.0: {ldr, sm, wb} { 1, 2, 0 }
|
||||
* 5.0: {ldr, sm, wb} { 1, 2, 0 }
|
||||
* 6.0: {ldr, sm, wb} { 1, 2, 0 }
|
||||
* 6.2: {ldr, sm, wb} { 1, 2, 0 }
|
||||
* 7.0: {ldr, sm, wb} { 1, 2, 0 }
|
||||
*/
|
||||
|
||||
static const pkg1_id_t _pkg1_ids[] = {
|
||||
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, true, _secmon_1_patchset, _warmboot_1_patchset }, //1.0.0 (Patched relocator)
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_2_patchset, _warmboot_2_patchset }, //2.0.0 - 2.3.0
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.0
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.1 - 3.0.2
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_4_patchset, _warmboot_4_patchset }, //4.0.0 - 4.1.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_5_patchset, _warmboot_4_patchset }, //5.0.0 - 5.1.0
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_6_patchset, _warmboot_4_patchset }, //6.0.0 - 6.1.0
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_620_patchset, _warmboot_4_patchset }, //6.2.0
|
||||
{ "20181218175730", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.0
|
||||
{ "20190208150037", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.1
|
||||
{ "20190314172056", 7, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //8.0.0 - 8.0.1
|
||||
{ "20190531152432", 8, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //8.1.0
|
||||
{ "20190809135709", 9, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //9.0.0 - 9.0.1
|
||||
{ "20191021113848", 10, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //9.1.0
|
||||
{ "20200303104606", 10, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //10.0.0
|
||||
{ NULL } //End.
|
||||
};
|
||||
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1)
|
||||
{
|
||||
char build_date[15];
|
||||
memcpy(build_date, (char *)(pkg1 + 0x10), 14);
|
||||
build_date[14] = 0;
|
||||
gfx_printf("Found pkg1 ('%s').\n\n", build_date);
|
||||
|
||||
for (u32 i = 0; _pkg1_ids[i].id; i++)
|
||||
if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 12))
|
||||
return &_pkg1_ids[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
|
||||
{
|
||||
// Decrypt package1.
|
||||
u8 *pkg11 = pkg1 + id->pkg11_off;
|
||||
u32 pkg11_size = *(u32 *)pkg11;
|
||||
se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10);
|
||||
}
|
||||
|
||||
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1)
|
||||
{
|
||||
pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
|
||||
|
||||
u32 sec_size[3] = { hdr->wb_size, hdr->ldr_size, hdr->sm_size };
|
||||
//u32 sec_off[3] = { hdr->wb_off, hdr->ldr_off, hdr->sm_off };
|
||||
|
||||
u8 *pdata = (u8 *)hdr + sizeof(pk11_hdr_t);
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
{
|
||||
if (id->sec_map[i] == 0 && warmboot_dst)
|
||||
memcpy(warmboot_dst, pdata, sec_size[id->sec_map[i]]);
|
||||
else if (id->sec_map[i] == 1 && ldr_dst)
|
||||
memcpy(ldr_dst, pdata, sec_size[id->sec_map[i]]);
|
||||
else if (id->sec_map[i] == 2 && secmon_dst)
|
||||
memcpy(secmon_dst, pdata, sec_size[id->sec_map[i]]);
|
||||
pdata += sec_size[id->sec_map[i]];
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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 _PKG1_H_
|
||||
#define _PKG1_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
typedef struct _patch_t
|
||||
{
|
||||
u32 off;
|
||||
u32 val;
|
||||
} patch_t;
|
||||
|
||||
#define PATCHSET_DEF(name, ...) \
|
||||
patch_t name[] = { \
|
||||
__VA_ARGS__, \
|
||||
{ 0xFFFFFFFF, 0xFFFFFFFF } \
|
||||
}
|
||||
|
||||
typedef struct _pkg1_id_t
|
||||
{
|
||||
const char *id;
|
||||
u32 kb;
|
||||
u32 tsec_off;
|
||||
u32 pkg11_off;
|
||||
u32 sec_map[3];
|
||||
u32 secmon_base;
|
||||
u32 warmboot_base;
|
||||
bool set_warmboot;
|
||||
patch_t *secmon_patchset;
|
||||
patch_t *warmboot_patchset;
|
||||
} pkg1_id_t;
|
||||
|
||||
typedef struct _pk11_hdr_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 wb_size;
|
||||
u32 wb_off;
|
||||
u32 pad;
|
||||
u32 ldr_size;
|
||||
u32 ldr_off;
|
||||
u32 sm_size;
|
||||
u32 sm_off;
|
||||
} pk11_hdr_t;
|
||||
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
||||
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
|
||||
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* 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 _PKG2_H_
|
||||
#define _PKG2_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
#include "../utils/list.h"
|
||||
|
||||
#define PKG2_MAGIC 0x31324B50
|
||||
#define PKG2_SEC_BASE 0x80000000
|
||||
#define PKG2_SEC_KERNEL 0
|
||||
#define PKG2_SEC_INI1 1
|
||||
|
||||
#define INI1_MAGIC 0x31494E49
|
||||
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // Offset of OP + 12 is the INI1 offset.
|
||||
#define PKG2_NEWKERN_START 0x800
|
||||
|
||||
u32 pkg2_newkern_ini1_val;
|
||||
u32 pkg2_newkern_ini1_start;
|
||||
u32 pkg2_newkern_ini1_end;
|
||||
|
||||
typedef struct _kernel_patch_t
|
||||
{
|
||||
u32 id;
|
||||
u32 off;
|
||||
u32 val;
|
||||
u32 *ptr;
|
||||
} kernel_patch_t;
|
||||
|
||||
#define KERNEL_PATCHSET_DEF(name, ...) \
|
||||
kernel_patch_t name[] = { \
|
||||
__VA_ARGS__, \
|
||||
{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32 *)0xFFFFFFFF} \
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
// Always applied.
|
||||
SVC_GENERIC = 0,
|
||||
// Generic instruction patches.
|
||||
SVC_VERIFY_DS = 0x10,
|
||||
DEBUG_MODE_EN = 0x11,
|
||||
ATM_GEN_PATCH = 0x12,
|
||||
ATM_SYSM_INCR = ATM_GEN_PATCH,
|
||||
// >4 bytes patches. Value is a pointer of a u32 array.
|
||||
ATM_ARR_PATCH = 0x13,
|
||||
};
|
||||
|
||||
typedef struct _pkg2_hdr_t
|
||||
{
|
||||
u8 ctr[0x10];
|
||||
u8 sec_ctr[0x40];
|
||||
u32 magic;
|
||||
u32 base;
|
||||
u32 pad0;
|
||||
u16 version;
|
||||
u16 pad1;
|
||||
u32 sec_size[4];
|
||||
u32 sec_off[4];
|
||||
u8 sec_sha256[0x80];
|
||||
u8 data[];
|
||||
} pkg2_hdr_t;
|
||||
|
||||
typedef struct _pkg2_ini1_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 size;
|
||||
u32 num_procs;
|
||||
u32 pad;
|
||||
} pkg2_ini1_t;
|
||||
|
||||
typedef struct _pkg2_kip1_sec_t
|
||||
{
|
||||
u32 offset;
|
||||
u32 size_decomp;
|
||||
u32 size_comp;
|
||||
u32 attrib;
|
||||
} pkg2_kip1_sec_t;
|
||||
|
||||
#define KIP1_NUM_SECTIONS 6
|
||||
|
||||
typedef struct _pkg2_kip1_t
|
||||
{
|
||||
u32 magic;
|
||||
u8 name[12];
|
||||
u64 tid;
|
||||
u32 proc_cat;
|
||||
u8 main_thrd_prio;
|
||||
u8 def_cpu_core;
|
||||
u8 res;
|
||||
u8 flags;
|
||||
pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
|
||||
u32 caps[0x20];
|
||||
u8 data[];
|
||||
} pkg2_kip1_t;
|
||||
|
||||
typedef struct _pkg2_kip1_info_t
|
||||
{
|
||||
pkg2_kip1_t *kip1;
|
||||
u32 size;
|
||||
link_t link;
|
||||
} pkg2_kip1_info_t;
|
||||
|
||||
typedef struct _pkg2_kernel_id_t
|
||||
{
|
||||
u8 hash[8];
|
||||
kernel_patch_t *kernel_patchset;
|
||||
} pkg2_kernel_id_t;
|
||||
|
||||
typedef struct _kip1_patch_t
|
||||
{
|
||||
u32 offset; // section+offset of patch to apply.
|
||||
u32 length; // In bytes, 0 means last patch.
|
||||
char* srcData; // That must match.
|
||||
char* dstData; // That it gets replaced by.
|
||||
} kip1_patch_t;
|
||||
|
||||
typedef struct _kip1_patchset_t
|
||||
{
|
||||
char* name; // NULL means end.
|
||||
kip1_patch_t* patches; // NULL means not necessary.
|
||||
} kip1_patchset_t;
|
||||
|
||||
typedef struct _kip1_id_t
|
||||
{
|
||||
const char* name;
|
||||
u8 hash[8];
|
||||
kip1_patchset_t* patchset;
|
||||
} kip1_id_t;
|
||||
|
||||
void pkg2_get_newkern_info(u8 *kern_data);
|
||||
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
|
||||
int pkg2_has_kip(link_t *info, u64 tid);
|
||||
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
|
||||
void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1);
|
||||
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
|
||||
void pkg2_get_ids(kip1_id_t **ids, u32 *entries);
|
||||
const char* pkg2_patch_kips(link_t *info, char* patchNames);
|
||||
|
||||
const pkg2_kernel_id_t *pkg2_identify(u8 *hash);
|
||||
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb);
|
||||
void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info, bool new_pkg2);
|
||||
|
||||
#endif
|
||||
@@ -1,156 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pkg2_ini_kippatch.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
|
||||
#define KPS(x) ((u32)(x) << 29)
|
||||
|
||||
static u8 *_htoa(u8 *result, const char *ptr, u8 byte_len)
|
||||
{
|
||||
char ch = *ptr;
|
||||
u32 ascii_len = byte_len * 2;
|
||||
if (!result)
|
||||
result = malloc(byte_len);
|
||||
u8 *dst = result;
|
||||
|
||||
while (ch == ' ' || ch == '\t')
|
||||
ch = *(++ptr);
|
||||
|
||||
bool shift = true;
|
||||
while (ascii_len)
|
||||
{
|
||||
u8 tmp = 0;
|
||||
if (ch >= '0' && ch <= '9')
|
||||
tmp = (ch - '0');
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
tmp = (ch - 'A' + 10);
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
tmp = (ch - 'a' + 10);
|
||||
|
||||
if (shift)
|
||||
*dst = (tmp << 4) & 0xF0;
|
||||
else
|
||||
{
|
||||
*dst |= (tmp & 0x0F);
|
||||
dst++;
|
||||
}
|
||||
|
||||
ascii_len--;
|
||||
ch = *(++ptr);
|
||||
shift = !shift;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *_strdup(char *str)
|
||||
{
|
||||
if (!str)
|
||||
return NULL;
|
||||
if (str[0] == ' ' && (strlen(str) > 1))
|
||||
str++;
|
||||
char *res = (char *)malloc(strlen(str) + 1);
|
||||
strcpy(res, str);
|
||||
if (res[strlen(res) - 1] == ' ' && (strlen(res) > 1))
|
||||
res[strlen(res) - 1] = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static u32 _find_patch_section_name(char *lbuf, u32 lblen, char schar)
|
||||
{
|
||||
u32 i;
|
||||
for (i = 0; i < lblen && lbuf[i] != schar && lbuf[i] != '\n' && lbuf[i] != '\r'; i++)
|
||||
;
|
||||
lbuf[i] = 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec, char *name)
|
||||
{
|
||||
if (ksec)
|
||||
list_append(dst, &ksec->link);
|
||||
|
||||
ksec = (ini_kip_sec_t *)calloc(sizeof(ini_kip_sec_t), 1);
|
||||
u32 i = _find_patch_section_name(name, strlen(name), ':') + 1;
|
||||
ksec->name = _strdup(name);
|
||||
|
||||
// Get hash section.
|
||||
_htoa(ksec->hash, &name[i], 8);
|
||||
|
||||
return ksec;
|
||||
}
|
||||
|
||||
int ini_patch_parse(link_t *dst, char *ini_path)
|
||||
{
|
||||
u32 lblen;
|
||||
char lbuf[512];
|
||||
FIL fp;
|
||||
ini_kip_sec_t *ksec = NULL;
|
||||
|
||||
// Open ini.
|
||||
if (f_open(&fp, ini_path, FA_READ) != FR_OK)
|
||||
return 0;
|
||||
|
||||
do
|
||||
{
|
||||
// Fetch one line.
|
||||
lbuf[0] = 0;
|
||||
f_gets(lbuf, 512, &fp);
|
||||
lblen = strlen(lbuf);
|
||||
|
||||
// Remove trailing newline. Depends on 'FF_USE_STRFUNC 2' that removes \r.
|
||||
if (lblen && lbuf[lblen - 1] == '\n')
|
||||
lbuf[lblen - 1] = 0;
|
||||
|
||||
if (lblen > 2 && lbuf[0] == '[') // Create new section.
|
||||
{
|
||||
_find_patch_section_name(lbuf, lblen, ']');
|
||||
|
||||
ksec = _ini_create_kip_section(dst, ksec, &lbuf[1]);
|
||||
list_init(&ksec->pts);
|
||||
}
|
||||
else if (ksec && lbuf[0] == '.') //Extract key/value.
|
||||
{
|
||||
u32 tmp = 0;
|
||||
u32 i = _find_patch_section_name(lbuf, lblen, '=');
|
||||
|
||||
ini_patchset_t *pt = (ini_patchset_t *)calloc(sizeof(ini_patchset_t), 1);
|
||||
|
||||
pt->name = _strdup(&lbuf[1]);
|
||||
|
||||
u8 kip_sidx = lbuf[i + 1] - '0';
|
||||
|
||||
if (kip_sidx < 6)
|
||||
{
|
||||
pt->offset = KPS(kip_sidx);
|
||||
tmp = _find_patch_section_name(&lbuf[i + 3], lblen, ':');
|
||||
pt->offset |= strtol(&lbuf[i + 3], NULL, 16);
|
||||
|
||||
i += tmp + 4;
|
||||
|
||||
tmp = _find_patch_section_name(&lbuf[i], lblen, ':');
|
||||
pt->length = strtol(&lbuf[i], NULL, 16);
|
||||
|
||||
i += tmp + 1;
|
||||
|
||||
tmp = _find_patch_section_name(&lbuf[i], lblen, ',');
|
||||
pt->srcData = _htoa(NULL, &lbuf[i], pt->length);
|
||||
i += tmp + 1;
|
||||
pt->dstData = _htoa(NULL, &lbuf[i], pt->length);
|
||||
}
|
||||
|
||||
list_append(&ksec->pts, &pt->link);
|
||||
}
|
||||
} while (!f_eof(&fp));
|
||||
|
||||
f_close(&fp);
|
||||
|
||||
if (ksec)
|
||||
list_append(dst, &ksec->link);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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 _INIPATCH_H_
|
||||
#define _INIPATCH_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
#include "../utils/list.h"
|
||||
|
||||
typedef struct _ini_patchset_t
|
||||
{
|
||||
char *name;
|
||||
u32 offset; // section + offset of patch to apply.
|
||||
u32 length; // In bytes, 0 means last patch.
|
||||
u8 *srcData; // That must match.
|
||||
u8 *dstData; // Gets replaced with.
|
||||
link_t link;
|
||||
} ini_patchset_t;
|
||||
|
||||
typedef struct _ini_kip_sec_t
|
||||
{
|
||||
char *name;
|
||||
u8 hash[8];
|
||||
link_t pts;
|
||||
link_t link;
|
||||
} ini_kip_sec_t;
|
||||
|
||||
int ini_patch_parse(link_t *dst, char *ini_path);
|
||||
|
||||
#endif
|
||||
@@ -1,355 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2019 Atmosphère-NX
|
||||
*
|
||||
* 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 "hos.h"
|
||||
#include "../config/config.h"
|
||||
#include "../gfx/di.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
enum emuMMC_Type
|
||||
{
|
||||
emuMMC_None = 0,
|
||||
emuMMC_Partition,
|
||||
emuMMC_File,
|
||||
emuMMC_MAX
|
||||
};
|
||||
|
||||
/* "EFS0" */
|
||||
#define EMUMMC_MAGIC 0x30534645
|
||||
#define EMUMMC_FILE_PATH_MAX 0x80
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 magic;
|
||||
u32 type;
|
||||
u32 id;
|
||||
u32 fs_ver;
|
||||
} emummc_base_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64 start_sector;
|
||||
} emummc_partition_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char path[EMUMMC_FILE_PATH_MAX];
|
||||
} emummc_file_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
emummc_base_config_t base_cfg;
|
||||
union
|
||||
{
|
||||
emummc_partition_config_t partition_cfg;
|
||||
emummc_file_config_t file_cfg;
|
||||
};
|
||||
char nintendo_path[EMUMMC_FILE_PATH_MAX];
|
||||
} exo_emummc_config_t;
|
||||
|
||||
typedef struct _exo_cfg_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 fwno;
|
||||
u32 flags;
|
||||
u32 reserved[5];
|
||||
exo_emummc_config_t emummc_cfg;
|
||||
} exo_cfg_t;
|
||||
|
||||
typedef struct _atm_meta_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 fwno;
|
||||
} wb_cfg_t;
|
||||
|
||||
// Atmosphère reboot-to-fatal-error.
|
||||
typedef struct _atm_fatal_error_ctx
|
||||
{
|
||||
u32 magic;
|
||||
u32 error_desc;
|
||||
u64 title_id;
|
||||
union
|
||||
{
|
||||
u64 gprs[32];
|
||||
struct
|
||||
{
|
||||
u64 _gprs[29];
|
||||
u64 fp;
|
||||
u64 lr;
|
||||
u64 sp;
|
||||
};
|
||||
};
|
||||
u64 pc;
|
||||
u64 module_base;
|
||||
u32 pstate;
|
||||
u32 afsr0;
|
||||
u32 afsr1;
|
||||
u32 esr;
|
||||
u64 far;
|
||||
u64 report_identifier; // Normally just system tick.
|
||||
u64 stack_trace_size;
|
||||
u64 stack_dump_size;
|
||||
u64 stack_trace[0x20];
|
||||
u8 stack_dump[0x100];
|
||||
u8 tls[0x100];
|
||||
} atm_fatal_error_ctx;
|
||||
|
||||
#define ATM_FATAL_ERR_CTX_ADDR 0x4003E000
|
||||
#define ATM_FATAL_MAGIC 0x30454641 // AFE0
|
||||
|
||||
#define ATM_WB_HEADER_OFF 0x244
|
||||
#define ATM_WB_MAGIC 0x30544257
|
||||
|
||||
// Exosphère mailbox defines.
|
||||
#define EXO_CFG_ADDR 0x8000F000
|
||||
#define EXO_MAGIC_VAL 0x304F5845
|
||||
#define EXO_FLAG_DBG_PRIV (1 << 1)
|
||||
#define EXO_FLAG_DBG_USER (1 << 2)
|
||||
#define EXO_FLAG_NO_USER_EXC (1 << 3)
|
||||
#define EXO_FLAG_USER_PMU (1 << 4)
|
||||
#define EXO_FLAG_CAL0_BLANKING (1 << 5)
|
||||
#define EXO_FLAG_CAL0_WRITES_SYS (1 << 6)
|
||||
|
||||
void config_exosphere(launch_ctxt_t *ctxt)
|
||||
{
|
||||
u32 exoFwNo = 0;
|
||||
u32 exoFlags = 0;
|
||||
u32 kb = ctxt->pkg1_id->kb;
|
||||
bool user_debug = false;
|
||||
bool cal0_blanking = false;
|
||||
bool cal0_allow_writes_sys = false;
|
||||
|
||||
memset((exo_cfg_t *)EXO_CFG_ADDR, 0, sizeof(exo_cfg_t));
|
||||
|
||||
volatile exo_cfg_t *exo_cfg = (exo_cfg_t *)EXO_CFG_ADDR;
|
||||
|
||||
switch (kb)
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
if (!strcmp(ctxt->pkg1_id->id, "20161121183008"))
|
||||
exoFwNo = 1;
|
||||
else
|
||||
exoFwNo = 2;
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
exoFwNo = 3;
|
||||
break;
|
||||
default:
|
||||
exoFwNo = kb + 1;
|
||||
if (!strcmp(ctxt->pkg1_id->id, "20190314172056") || (kb >= KB_FIRMWARE_VERSION_810))
|
||||
exoFwNo++; // ATM_TARGET_FW_800/810/900/910.
|
||||
if (!strcmp(ctxt->pkg1_id->id, "20200303104606"))
|
||||
exoFwNo++; // ATM_TARGET_FW_1000.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ctxt->stock)
|
||||
{
|
||||
// Parse exosphere.ini.
|
||||
LIST_INIT(ini_sections);
|
||||
if (ini_parse(&ini_sections, "exosphere.ini", false))
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
// Only parse exosphere section.
|
||||
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere"))
|
||||
continue;
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
{
|
||||
if (!strcmp("debugmode_user", kv->key))
|
||||
user_debug = atoi(kv->val);
|
||||
else if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
||||
{
|
||||
if (!strcmp("blank_prodinfo_emummc", kv->key))
|
||||
cal0_blanking = atoi(kv->val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp("blank_prodinfo_sysmmc", kv->key))
|
||||
cal0_blanking = atoi(kv->val);
|
||||
else if (!strcmp("allow_writing_to_cal_sysmmc", kv->key))
|
||||
cal0_allow_writes_sys = atoi(kv->val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To avoid problems, make private debug mode always on if not semi-stock.
|
||||
if (!ctxt->stock || (emu_cfg.enabled && !h_cfg.emummc_force_disable))
|
||||
exoFlags |= EXO_FLAG_DBG_PRIV;
|
||||
|
||||
// Enable user debug.
|
||||
if (user_debug)
|
||||
exoFlags |= EXO_FLAG_DBG_USER;
|
||||
|
||||
// Disable proper failure handling.
|
||||
if (ctxt->exo_cfg.no_user_exceptions)
|
||||
exoFlags |= EXO_FLAG_NO_USER_EXC;
|
||||
|
||||
// Enable user access to PMU.
|
||||
if (ctxt->exo_cfg.user_pmu)
|
||||
exoFlags |= EXO_FLAG_USER_PMU;
|
||||
|
||||
// Check if exo ini value is overridden and enable prodinfo blanking.
|
||||
if ((ctxt->exo_cfg.cal0_blank && *ctxt->exo_cfg.cal0_blank)
|
||||
|| (!ctxt->exo_cfg.cal0_blank && cal0_blanking))
|
||||
exoFlags |= EXO_FLAG_CAL0_BLANKING;
|
||||
|
||||
// Check if exo ini value is overridden and allow prodinfo writes.
|
||||
if ((ctxt->exo_cfg.cal0_allow_writes_sys && *ctxt->exo_cfg.cal0_allow_writes_sys)
|
||||
|| (!ctxt->exo_cfg.cal0_allow_writes_sys && cal0_allow_writes_sys))
|
||||
exoFlags |= EXO_FLAG_CAL0_WRITES_SYS;
|
||||
|
||||
// Set mailbox values.
|
||||
exo_cfg->magic = EXO_MAGIC_VAL;
|
||||
exo_cfg->fwno = exoFwNo;
|
||||
exo_cfg->flags = exoFlags;
|
||||
|
||||
// If warmboot is lp0fw, add in RSA modulus.
|
||||
volatile wb_cfg_t *wb_cfg = (wb_cfg_t *)(ctxt->pkg1_id->warmboot_base + ATM_WB_HEADER_OFF);
|
||||
|
||||
if (wb_cfg->magic == ATM_WB_MAGIC)
|
||||
{
|
||||
wb_cfg->fwno = exoFwNo;
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
// Set warmboot binary rsa modulus.
|
||||
u8 *rsa_mod = (u8 *)malloc(512);
|
||||
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 1, 1, rsa_mod);
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
// Patch AutoRCM out.
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
rsa_mod[0x10] = 0xF7;
|
||||
else
|
||||
rsa_mod[0x10] = 0x37;
|
||||
|
||||
memcpy((void *)(ctxt->pkg1_id->warmboot_base + 0x10), rsa_mod + 0x10, 0x100);
|
||||
}
|
||||
|
||||
if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
||||
{
|
||||
exo_cfg->emummc_cfg.base_cfg.magic = EMUMMC_MAGIC;
|
||||
exo_cfg->emummc_cfg.base_cfg.type = emu_cfg.sector ? emuMMC_Partition : emuMMC_File;
|
||||
exo_cfg->emummc_cfg.base_cfg.fs_ver = emu_cfg.fs_ver;
|
||||
exo_cfg->emummc_cfg.base_cfg.id = emu_cfg.id;
|
||||
|
||||
if (emu_cfg.sector)
|
||||
exo_cfg->emummc_cfg.partition_cfg.start_sector = emu_cfg.sector;
|
||||
else
|
||||
strcpy((char *)exo_cfg->emummc_cfg.file_cfg.path, emu_cfg.path);
|
||||
|
||||
if (emu_cfg.nintendo_path && !ctxt->stock)
|
||||
strcpy((char *)exo_cfg->emummc_cfg.nintendo_path, emu_cfg.nintendo_path);
|
||||
else if (ctxt->stock)
|
||||
strcpy((char *)exo_cfg->emummc_cfg.nintendo_path, "Nintendo");
|
||||
else
|
||||
exo_cfg->emummc_cfg.nintendo_path[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_error_desc(u32 error_desc)
|
||||
{
|
||||
switch (error_desc)
|
||||
{
|
||||
case 0x100:
|
||||
return "Instruction Abort";
|
||||
case 0x101:
|
||||
return "Data Abort";
|
||||
case 0x102:
|
||||
return "PC Misalignment";
|
||||
case 0x103:
|
||||
return "SP Misalignment";
|
||||
case 0x104:
|
||||
return "Trap";
|
||||
case 0x106:
|
||||
return "SError";
|
||||
case 0x301:
|
||||
return "Bad SVC";
|
||||
case 0xFFE:
|
||||
return "std::abort()";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void secmon_exo_check_panic()
|
||||
{
|
||||
volatile atm_fatal_error_ctx *rpt = (atm_fatal_error_ctx *)ATM_FATAL_ERR_CTX_ADDR;
|
||||
|
||||
// Mask magic to maintain compatibility with any AFE version, thanks to additive struct members.
|
||||
if ((rpt->magic & 0xF0FFFFFF) != ATM_FATAL_MAGIC)
|
||||
return;
|
||||
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
WPRINTF("Panic occurred while running Atmosphere.\n\n");
|
||||
WPRINTFARGS("Title ID: %08X%08X", (u32)((u64)rpt->title_id >> 32), (u32)rpt->title_id);
|
||||
WPRINTFARGS("Error Desc: %s (0x%x)\n", get_error_desc(rpt->error_desc), rpt->error_desc);
|
||||
|
||||
// Save context to the SD card.
|
||||
char filepath[0x40];
|
||||
f_mkdir("atmosphere/fatal_errors");
|
||||
strcpy(filepath, "/atmosphere/fatal_errors/report_");
|
||||
itoa((u32)((u64)rpt->report_identifier >> 32), filepath + strlen(filepath), 16);
|
||||
itoa((u32)(rpt->report_identifier), filepath + strlen(filepath), 16);
|
||||
strcat(filepath, ".bin");
|
||||
|
||||
sd_save_to_file((void *)rpt, sizeof(atm_fatal_error_ctx), filepath);
|
||||
|
||||
gfx_con.fntsz = 8;
|
||||
WPRINTFARGS("Report saved to %s\n", filepath);
|
||||
|
||||
// Change magic to invalid, to prevent double-display of error/bootlooping.
|
||||
rpt->magic = 0x0;
|
||||
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_printf("\n\nPress POWER to continue.\n");
|
||||
|
||||
display_backlight_brightness(100, 1000);
|
||||
msleep(1000);
|
||||
|
||||
u32 btn = btn_wait();
|
||||
while (!(btn & BTN_POWER))
|
||||
btn = btn_wait();
|
||||
|
||||
display_backlight_brightness(0, 1000);
|
||||
gfx_con_setpos(0, 0);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _SECMON_EXO_H_
|
||||
#define _SECMON_EXO_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
void config_exosphere(launch_ctxt_t *ctxt);
|
||||
void secmon_exo_check_panic();
|
||||
|
||||
#endif
|
||||
@@ -1,257 +0,0 @@
|
||||
/*
|
||||
* 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 "hos.h"
|
||||
#include "fss.h"
|
||||
#include "sept.h"
|
||||
#include "../config/config.h"
|
||||
#include "../gfx/di.h"
|
||||
#include "../ianos/ianos.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../soc/hw_init.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
#include "../gfx/gfx.h"
|
||||
|
||||
#define RELOC_META_OFF 0x7C
|
||||
#define PATCHED_RELOC_SZ 0x94
|
||||
|
||||
#define WB_RST_ADDR 0x40010ED0
|
||||
#define WB_RST_SIZE 0x30
|
||||
|
||||
u8 warmboot_reboot[] = {
|
||||
0x14, 0x00, 0x9F, 0xE5, // LDR R0, =0x7000E450
|
||||
0x01, 0x10, 0xB0, 0xE3, // MOVS R1, #1
|
||||
0x00, 0x10, 0x80, 0xE5, // STR R1, [R0]
|
||||
0x0C, 0x00, 0x9F, 0xE5, // LDR R0, =0x7000E400
|
||||
0x10, 0x10, 0xB0, 0xE3, // MOVS R1, #0x10
|
||||
0x00, 0x10, 0x80, 0xE5, // STR R1, [R0]
|
||||
0xFE, 0xFF, 0xFF, 0xEA, // LOOP
|
||||
0x50, 0xE4, 0x00, 0x70, // #0x7000E450
|
||||
0x00, 0xE4, 0x00, 0x70 // #0x7000E400
|
||||
};
|
||||
|
||||
#define SEPT_PRI_ADDR 0x4003F000
|
||||
|
||||
#define SEPT_PK1T_ADDR 0xC0400000
|
||||
#define SEPT_TCSZ_ADDR (SEPT_PK1T_ADDR - 0x4)
|
||||
#define SEPT_STG1_ADDR (SEPT_PK1T_ADDR + 0x2E100)
|
||||
#define SEPT_STG2_ADDR (SEPT_PK1T_ADDR + 0x60E0)
|
||||
#define SEPT_PKG_SZ (0x2F100 + WB_RST_SIZE)
|
||||
|
||||
extern boot_cfg_t b_cfg;
|
||||
extern hekate_config h_cfg;
|
||||
extern const volatile ipl_ver_meta_t ipl_ver;
|
||||
|
||||
extern bool is_ipl_updated(void *buf);
|
||||
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
|
||||
|
||||
void check_sept(ini_sec_t *cfg_sec)
|
||||
{
|
||||
hos_eks_get();
|
||||
|
||||
// Check if non-hekate payload is used for sept and restore it.
|
||||
if (h_cfg.sept_run)
|
||||
{
|
||||
if (!f_stat("sept/payload.bak", NULL))
|
||||
{
|
||||
f_unlink("sept/payload.bin");
|
||||
f_rename("sept/payload.bak", "sept/payload.bin");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
int res = emummc_storage_init_mmc(&storage, &sdmmc);
|
||||
if (res)
|
||||
{
|
||||
if (res == 2)
|
||||
EPRINTF("Failed to init eMMC");
|
||||
else
|
||||
EPRINTF("Failed to init emuMMC");
|
||||
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTF("Unknown pkg1 version.");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
|
||||
{
|
||||
u8 key_idx = pkg1_id->kb - KB_FIRMWARE_VERSION_700;
|
||||
if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx)))
|
||||
{
|
||||
h_cfg.sept_run = true;
|
||||
EMC(EMC_SCRATCH0) |= EMC_SEPT_RUN;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off, pkg1_id->kb, cfg_sec);
|
||||
}
|
||||
|
||||
out_free:
|
||||
free(pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
}
|
||||
|
||||
int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec)
|
||||
{
|
||||
FIL fp;
|
||||
bool fss0_sept_used = false;
|
||||
|
||||
// Copy warmboot reboot code and TSEC fw.
|
||||
u32 tsec_fw_size = 0x3000;
|
||||
if (kb > KB_FIRMWARE_VERSION_700)
|
||||
tsec_fw_size = 0x3300;
|
||||
memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot));
|
||||
memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_fw_size);
|
||||
*(vu32 *)SEPT_TCSZ_ADDR = tsec_fw_size;
|
||||
|
||||
if (cfg_sec)
|
||||
{
|
||||
fss0_sept_t sept_ctxt;
|
||||
sept_ctxt.kb = kb;
|
||||
sept_ctxt.cfg_sec = cfg_sec;
|
||||
sept_ctxt.sept_primary = (void *)SEPT_STG1_ADDR;
|
||||
sept_ctxt.sept_secondary = (void *)SEPT_STG2_ADDR;
|
||||
|
||||
fss0_sept_used = load_sept_from_ffs0(&sept_ctxt);
|
||||
}
|
||||
|
||||
if (!fss0_sept_used)
|
||||
{
|
||||
// Copy sept-primary.
|
||||
if (f_open(&fp, "sept/sept-primary.bin", FA_READ))
|
||||
goto error;
|
||||
|
||||
if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
|
||||
{
|
||||
f_close(&fp);
|
||||
goto error;
|
||||
}
|
||||
f_close(&fp);
|
||||
|
||||
// Copy sept-secondary.
|
||||
if (kb < KB_FIRMWARE_VERSION_810)
|
||||
{
|
||||
if (f_open(&fp, "sept/sept-secondary_00.enc", FA_READ))
|
||||
if (f_open(&fp, "sept/sept-secondary.enc", FA_READ)) // Try the deprecated version.
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f_open(&fp, "sept/sept-secondary_01.enc", FA_READ))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
|
||||
{
|
||||
f_close(&fp);
|
||||
goto error;
|
||||
}
|
||||
f_close(&fp);
|
||||
}
|
||||
|
||||
b_cfg.boot_cfg |= (BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_SEPT_RUN);
|
||||
|
||||
bool update_sept_payload = true;
|
||||
if (!f_open(&fp, "sept/payload.bin", FA_READ | FA_WRITE))
|
||||
{
|
||||
ipl_ver_meta_t tmp_ver;
|
||||
f_lseek(&fp, PATCHED_RELOC_SZ + sizeof(boot_cfg_t));
|
||||
f_read(&fp, &tmp_ver, sizeof(ipl_ver_meta_t), NULL);
|
||||
|
||||
if (tmp_ver.magic == ipl_ver.magic)
|
||||
{
|
||||
if (tmp_ver.version == ipl_ver.version)
|
||||
{
|
||||
// Save auto boot config to sept payload, if any.
|
||||
boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
|
||||
memcpy(tmp_cfg, &b_cfg, sizeof(boot_cfg_t));
|
||||
f_lseek(&fp, PATCHED_RELOC_SZ);
|
||||
f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL);
|
||||
update_sept_payload = false;
|
||||
}
|
||||
|
||||
f_close(&fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
f_close(&fp);
|
||||
f_rename("sept/payload.bin", "sept/payload.bak"); // Backup foreign payload.
|
||||
}
|
||||
}
|
||||
|
||||
if (update_sept_payload)
|
||||
{
|
||||
volatile reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF);
|
||||
f_mkdir("sept");
|
||||
f_open(&fp, "sept/payload.bin", FA_WRITE | FA_CREATE_ALWAYS);
|
||||
f_write(&fp, (u8 *)reloc->start, reloc->end - reloc->start, NULL);
|
||||
f_close(&fp);
|
||||
}
|
||||
|
||||
sd_unmount();
|
||||
|
||||
u32 pk1t_sept = SEPT_PK1T_ADDR - (ALIGN(PATCHED_RELOC_SZ, 0x10) + WB_RST_SIZE);
|
||||
|
||||
void (*sept)() = (void *)pk1t_sept;
|
||||
|
||||
reloc_patcher(WB_RST_ADDR, pk1t_sept, SEPT_PKG_SZ);
|
||||
|
||||
// Patch SDRAM init to perform an SVC immediately after second write.
|
||||
PMC(APBDEV_PMC_SCRATCH45) = 0x2E38DFFF;
|
||||
PMC(APBDEV_PMC_SCRATCH46) = 0x6001DC28;
|
||||
// Set SVC handler to jump to sept-primary in IRAM.
|
||||
PMC(APBDEV_PMC_SCRATCH33) = SEPT_PRI_ADDR;
|
||||
PMC(APBDEV_PMC_SCRATCH40) = 0x6000F208;
|
||||
|
||||
reconfig_hw_workaround(false, 0);
|
||||
|
||||
(*sept)();
|
||||
|
||||
error:
|
||||
gfx_con.mute = false;
|
||||
EPRINTF("Failed to run sept\n");
|
||||
|
||||
btn_wait();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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 _SEPT_H_
|
||||
#define _SEPT_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
void check_sept(ini_sec_t *cfg_sec);
|
||||
int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec);
|
||||
|
||||
#endif
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* 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 "../../common/common_module.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../libs/elfload/elfload.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../utils/types.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 = &gfx_con;
|
||||
bdkParameters->gfxCtx = &gfx_ctxt;
|
||||
bdkParameters->memcpy = (memcpy_t)&memcpy;
|
||||
bdkParameters->memset = (memset_t)&memset;
|
||||
bdkParameters->sharedHeap = &_heap;
|
||||
|
||||
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(bool sdmount, char *path, elfType_t type, void *moduleConfig)
|
||||
{
|
||||
uintptr_t epaddr = 0;
|
||||
|
||||
if (sdmount)
|
||||
{
|
||||
if (!sd_mount())
|
||||
goto elfLoadFinalOut;
|
||||
}
|
||||
|
||||
fileBuf = sd_file_read(path, NULL);
|
||||
|
||||
if (sdmount)
|
||||
sd_unmount();
|
||||
|
||||
if (!fileBuf)
|
||||
goto elfLoadFinalOut;
|
||||
|
||||
|
||||
el_ctx ctx;
|
||||
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;
|
||||
sd_unmount();
|
||||
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;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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(bool sdmount, char *path, elfType_t type, void* config);
|
||||
|
||||
#endif
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 rajkosto
|
||||
* Copyright (c) 2018 SciresM
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "blz.h"
|
||||
|
||||
const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter)
|
||||
{
|
||||
if (compDataLen < sizeof(blz_footer))
|
||||
return NULL;
|
||||
|
||||
const blz_footer *srcFooter = (const blz_footer*)&compData[compDataLen - sizeof(blz_footer)];
|
||||
if (outFooter != NULL)
|
||||
memcpy(outFooter, srcFooter, sizeof(blz_footer)); // Must be a memcpy because no umaligned accesses on ARMv4.
|
||||
|
||||
return srcFooter;
|
||||
}
|
||||
|
||||
// From https://github.com/SciresM/hactool/blob/master/kip.c which is exactly how kernel does it, thanks SciresM!
|
||||
int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer)
|
||||
{
|
||||
u32 addl_size = footer->addl_size;
|
||||
u32 header_size = footer->header_size;
|
||||
u32 cmp_and_hdr_size = footer->cmp_and_hdr_size;
|
||||
|
||||
unsigned char* cmp_start = &dataBuf[compSize] - cmp_and_hdr_size;
|
||||
u32 cmp_ofs = cmp_and_hdr_size - header_size;
|
||||
u32 out_ofs = cmp_and_hdr_size + addl_size;
|
||||
|
||||
while (out_ofs)
|
||||
{
|
||||
unsigned char control = cmp_start[--cmp_ofs];
|
||||
for (unsigned int i=0; i<8; i++)
|
||||
{
|
||||
if (control & 0x80)
|
||||
{
|
||||
if (cmp_ofs < 2)
|
||||
return 0; // Out of bounds.
|
||||
|
||||
cmp_ofs -= 2;
|
||||
u16 seg_val = ((unsigned int)(cmp_start[cmp_ofs + 1]) << 8) | cmp_start[cmp_ofs];
|
||||
u32 seg_size = ((seg_val >> 12) & 0xF) + 3;
|
||||
u32 seg_ofs = (seg_val & 0x0FFF) + 3;
|
||||
if (out_ofs < seg_size) // Kernel restricts segment copy to stay in bounds.
|
||||
seg_size = out_ofs;
|
||||
|
||||
out_ofs -= seg_size;
|
||||
|
||||
for (unsigned int j = 0; j < seg_size; j++)
|
||||
cmp_start[out_ofs + j] = cmp_start[out_ofs + j + seg_ofs];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy directly.
|
||||
if (cmp_ofs < 1)
|
||||
return 0; //out of bounds
|
||||
|
||||
cmp_start[--out_ofs] = cmp_start[--cmp_ofs];
|
||||
}
|
||||
control <<= 1;
|
||||
if (out_ofs == 0) // Blz works backwards, so if it reaches byte 0, it's done.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize)
|
||||
{
|
||||
blz_footer footer;
|
||||
const blz_footer *compFooterPtr = blz_get_footer(compData, compDataLen, &footer);
|
||||
if (compFooterPtr == NULL)
|
||||
return 0;
|
||||
|
||||
// Decompression must be done in-place, so need to copy the relevant compressed data first.
|
||||
unsigned int numCompBytes = (const unsigned char*)(compFooterPtr)-compData;
|
||||
memcpy(dstData, compData, numCompBytes);
|
||||
memset(&dstData[numCompBytes], 0, dstSize - numCompBytes);
|
||||
|
||||
return blz_uncompress_inplace(dstData, compDataLen, &footer);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 rajkosto
|
||||
*
|
||||
* 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 _BLZ_H_
|
||||
#define _BLZ_H_
|
||||
|
||||
#include "../../utils/types.h"
|
||||
|
||||
typedef struct _blz_footer
|
||||
{
|
||||
u32 cmp_and_hdr_size;
|
||||
u32 header_size;
|
||||
u32 addl_size;
|
||||
} blz_footer;
|
||||
|
||||
// Returns pointer to footer in compData if present, additionally copies it to outFooter if not NULL.
|
||||
const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter);
|
||||
// Returns 0 on failure.
|
||||
int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer);
|
||||
// Returns 0 on failure.
|
||||
int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize);
|
||||
|
||||
#endif
|
||||
@@ -1,589 +0,0 @@
|
||||
/* $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
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,324 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* 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/gfx.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
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "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
|
||||
@@ -1,39 +0,0 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Sample Code of OS Dependent Functions for FatFs */
|
||||
/* (C) ChaN, 2018 */
|
||||
/* (C) CTCaer, 2018 */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "ff.h"
|
||||
#include "../../mem/heap.h"
|
||||
|
||||
|
||||
|
||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Allocate a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||
UINT msize /* Number of bytes to allocate */
|
||||
)
|
||||
{
|
||||
return malloc(msize); /* Allocate a new memory block with POSIX API */
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Free a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void ff_memfree (
|
||||
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||
)
|
||||
{
|
||||
free(mblock); /* Free the memory block with POSIX API */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
PROVIDE(__ipl_start = IPL_LOAD_ADDR);
|
||||
. = __ipl_start;
|
||||
.text : {
|
||||
*(.text._start);
|
||||
*(._boot_cfg);
|
||||
*(._ipl_version);
|
||||
*(.text._irq_setup);
|
||||
*(.text*);
|
||||
}
|
||||
.data : {
|
||||
*(.data*);
|
||||
*(.rodata*);
|
||||
}
|
||||
. = ALIGN(0x10);
|
||||
__ipl_end = .;
|
||||
.bss : {
|
||||
__bss_start = .;
|
||||
*(COMMON)
|
||||
*(.bss*)
|
||||
__bss_end = .;
|
||||
}
|
||||
}
|
||||
1512
bootloader/main.c
1512
bootloader/main.c
File diff suppressed because it is too large
Load Diff
@@ -1,693 +0,0 @@
|
||||
/*
|
||||
* 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_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_SPARE 0x100
|
||||
#define EMC_FBIO_CFG5 0x104
|
||||
#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_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 (1 << 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_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_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_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
|
||||
{
|
||||
u8 dev0_ch0;
|
||||
u8 dev0_ch1;
|
||||
u8 dev1_ch0;
|
||||
u8 dev1_ch1;
|
||||
} emc_mr_data_t;
|
||||
|
||||
#endif
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "heap.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../../common/common_heap.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 *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, num * 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;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "../../common/common_heap.h"
|
||||
|
||||
void heap_init(u32 base);
|
||||
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
|
||||
@@ -1,14 +0,0 @@
|
||||
#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();
|
||||
void mc_disable_ahb_redirect();
|
||||
void mc_enable();
|
||||
|
||||
#endif
|
||||
@@ -1,516 +0,0 @@
|
||||
/*
|
||||
* 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_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 (1 << 22)
|
||||
|
||||
#define SEC_CARVEOUT_CFG_TZ_GLOBAL_WR_EN_BYPASS_CHECK (1 << 23)
|
||||
#define SEC_CARVEOUT_CFG_TZ_GLOBAL_RD_EN_BYPASS_CHECK (1 << 24)
|
||||
|
||||
#define SEC_CARVEOUT_CFG_ALLOW_APERTURE_ID_MISMATCH (1 << 25)
|
||||
#define SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH (1 << 26)
|
||||
|
||||
#define SEC_CARVEOUT_CFG_IS_WPR (1 << 27)
|
||||
|
||||
#endif
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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/fuse.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#include "../soc/clock.h"
|
||||
#include "../ianos/ianos.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../soc/t210.h"
|
||||
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
u32 minerva_init()
|
||||
{
|
||||
u32 curr_ram_idx = 0;
|
||||
|
||||
minerva_cfg = NULL;
|
||||
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
|
||||
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_odm(4) >> 3) & 0x1F;
|
||||
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
|
||||
|
||||
u32 ep_addr = ianos_loader(false, "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;
|
||||
|
||||
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 = 204000;
|
||||
mtc_cfg->train_mode = OP_TRAIN;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
mtc_cfg->rate_to = 800000;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
mtc_cfg->rate_to = 1600000;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
// FSP WAR.
|
||||
mtc_cfg->train_mode = OP_SWITCH;
|
||||
mtc_cfg->rate_to = 800000;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
// Switch to max.
|
||||
mtc_cfg->rate_to = 1600000;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void minerva_change_freq(minerva_freq_t freq)
|
||||
{
|
||||
if (!minerva_cfg)
|
||||
return;
|
||||
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
s32 rate_to;
|
||||
s32 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;
|
||||
|
||||
void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
|
||||
u32 minerva_init();
|
||||
void minerva_change_freq(minerva_freq_t freq);
|
||||
void minerva_periodic_training();
|
||||
|
||||
#endif
|
||||
@@ -1,560 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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 _SDRAM_H_
|
||||
#define _SDRAM_H_
|
||||
|
||||
#include "emc.h"
|
||||
#include "sdram_param_t210.h"
|
||||
|
||||
void sdram_init();
|
||||
sdram_params_t *sdram_get_params();
|
||||
sdram_params_t *sdram_get_params_patched();
|
||||
void sdram_lp0_save_params(const void *params);
|
||||
emc_mr_data_t sdram_read_mrx(emc_mr_t mrx);
|
||||
|
||||
#endif
|
||||
@@ -1,697 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#define DRAM_ID(x) (1 << (x))
|
||||
|
||||
#define DRAM_4GB_SAMSUNG_K4F6E304HB_MGCH 0
|
||||
#define DRAM_4GB_HYNIX_H9HCNNNBPUMLHR_NLN 1
|
||||
#define DRAM_4GB_MICRON_MT53B512M32D2NP_062_WT 2
|
||||
#define DRAM_4GB_COPPER_UNK_3 3 // Samsung?
|
||||
#define DRAM_6GB_SAMSUNG_K4FHE3D4HM_MFCH 4
|
||||
#define DRAM_4GB_COPPER_UNK_5 5 // Samsung?
|
||||
#define DRAM_4GB_COPPER_UNK_6 6 // Samsung?
|
||||
|
||||
typedef struct _sdram_vendor_patch_t
|
||||
{
|
||||
u32 val;
|
||||
u16 addr:9;
|
||||
u16 dramid:7;
|
||||
} sdram_vendor_patch_t;
|
||||
|
||||
static const sdram_params_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,
|
||||
|
||||
/*
|
||||
* 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,
|
||||
.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,
|
||||
.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,
|
||||
.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,
|
||||
.mc_emem_adr_cfg_dev0 = 0x00070302,
|
||||
.mc_emem_adr_cfg_dev1 = 0x00070302,
|
||||
.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,
|
||||
|
||||
/* 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[] = {
|
||||
{ 0x0000003A, 59, DRAM_ID(6) }, // emc_rfc. Auto refresh.
|
||||
{ 0x0000001D, 60, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh.
|
||||
{ 0x0000000D, 67, DRAM_ID(1) | DRAM_ID(5) }, // emc_r2w.
|
||||
{ 0x00000001, 91, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_extra.
|
||||
{ 0x80000000, 92, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_width.
|
||||
{ 0x00000012, 108, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden.
|
||||
{ 0x0000003B, 112, DRAM_ID(6) }, // emc_txsr.
|
||||
{ 0x0000003B, 113, DRAM_ID(6) }, // emc_txsr_dll.
|
||||
{ 0x00000003, 119, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_tclkstable.
|
||||
{ 0x00120015, 205, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x00160012, 206, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
|
||||
{ 0x00120015, 211, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00160012, 212, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
|
||||
{ 0x002F0032, 213, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00310032, 214, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00360034, 215, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0033002F, 216, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
|
||||
{ 0x00000006, 217, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x002F0032, 219, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00310032, 220, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00360034, 221, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0033002F, 222, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
|
||||
{ 0x00000006, 223, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00150015, 233, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x00120012, 235, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_2.
|
||||
{ 0x00160016, 236, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_3.
|
||||
{ 0x00000015, 237, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x00000012, 295, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2.
|
||||
{ 0x00000012, 296, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3.
|
||||
{ 0x00000210, 317, DRAM_ID(1) | DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode.
|
||||
{ 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density.
|
||||
{ 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density.
|
||||
{ 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density.
|
||||
{ 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w.
|
||||
{ 0x00000007, 370, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh.
|
||||
{ 0x72A30504, 373, DRAM_ID(6) } // mc_emem_arb_misc0.
|
||||
};
|
||||
@@ -1,964 +0,0 @@
|
||||
/*
|
||||
* 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 __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__
|
||||
#define __SOC_NVIDIA_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
|
||||
{
|
||||
|
||||
/* 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__ */
|
||||
@@ -1,931 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/* 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_t;
|
||||
|
||||
#endif
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
|
||||
{
|
||||
u8 data;
|
||||
|
||||
switch (prop) {
|
||||
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, 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 = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, 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 = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_PORConfig);
|
||||
*value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1;
|
||||
*value *= 100;
|
||||
*value += 3000;
|
||||
break;
|
||||
case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, 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 = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, 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 = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, 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 = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_ChrgVolt);
|
||||
data &= BQ24193_IRTHERMAL_THERM_MASK;
|
||||
if (data)
|
||||
*value = 300;
|
||||
else
|
||||
*value = 100;
|
||||
break;
|
||||
case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC).
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, 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 = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Status);
|
||||
*value = (data & BQ24193_STATUS_CHRG_MASK) >> 4;
|
||||
break;
|
||||
case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_FaultReg);
|
||||
*value = data & BQ24193_FAULT_THERM_MASK;
|
||||
break;
|
||||
case BQ24193_DevID: // Dev ID.
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_VendorPart);
|
||||
*value = data & BQ24193_VENDORPART_DEV_MASK;
|
||||
break;
|
||||
case BQ24193_ProductNumber: // Product number.
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_VendorPart);
|
||||
*value = (data & BQ24193_VENDORPART_PN_MASK) >> 3;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bq24193_fake_battery_removal()
|
||||
{
|
||||
u8 value;
|
||||
|
||||
// Disable watchdog to keep BATFET disabled.
|
||||
value = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, 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 = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc);
|
||||
value |= BQ24193_MISC_BATFET_DI_MASK;
|
||||
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value);
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* 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_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_fake_battery_removal();
|
||||
|
||||
#endif /* __BQ24193_H_ */
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
/* Status register bits */
|
||||
#define STATUS_POR_BIT (1 << 1)
|
||||
#define STATUS_BST_BIT (1 << 3)
|
||||
#define STATUS_VMN_BIT (1 << 8)
|
||||
#define STATUS_TMN_BIT (1 << 9)
|
||||
#define STATUS_SMN_BIT (1 << 10)
|
||||
#define STATUS_BI_BIT (1 << 11)
|
||||
#define STATUS_VMX_BIT (1 << 12)
|
||||
#define STATUS_TMX_BIT (1 << 13)
|
||||
#define STATUS_SMX_BIT (1 << 14)
|
||||
#define STATUS_BR_BIT (1 << 15)
|
||||
|
||||
#define VFSOC0_LOCK 0x0000
|
||||
#define VFSOC0_UNLOCK 0x0080
|
||||
|
||||
#define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
static u32 battery_voltage = 0;
|
||||
u32 max17050_get_cached_batt_volt()
|
||||
{
|
||||
return battery_voltage;
|
||||
}
|
||||
|
||||
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).
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Age);
|
||||
*value = data >> 8; /* Show MSB. 1% increments */
|
||||
break;
|
||||
case MAX17050_Cycles: // Cycle count.
|
||||
i2c_recv_buf_small((u8 *)value, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Cycles);
|
||||
break;
|
||||
case MAX17050_MinVolt: // Voltage max/min
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MinMaxVolt);
|
||||
*value = (data & 0xff) * 20; /* Voltage MIN. Units of 20mV */
|
||||
break;
|
||||
case MAX17050_MaxVolt: // Voltage max/min
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MinMaxVolt);
|
||||
*value = (data >> 8) * 20; /* Voltage MAX. Units of LSB = 20mV */
|
||||
break;
|
||||
case MAX17050_V_empty: // Voltage min design.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_V_empty);
|
||||
*value = (data >> 7) * 10; /* Units of LSB = 10mV */
|
||||
break;
|
||||
case MAX17050_VCELL: // Voltage now.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_VCELL);
|
||||
*value = data * 625 / 8 / 1000;
|
||||
battery_voltage = *value;
|
||||
break;
|
||||
case MAX17050_AvgVCELL: // Voltage avg.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgVCELL);
|
||||
*value = data * 625 / 8 / 1000;
|
||||
break;
|
||||
case MAX17050_OCVInternal: // Voltage ocv.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_OCVInternal);
|
||||
*value = data * 625 / 8 / 1000;
|
||||
break;
|
||||
case MAX17050_RepSOC: // Capacity %.
|
||||
i2c_recv_buf_small((u8 *)value, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepSOC);
|
||||
break;
|
||||
case MAX17050_DesignCap: // Charge full design.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_DesignCap);
|
||||
data = data * 5 / 10;
|
||||
*value = data;
|
||||
break;
|
||||
case MAX17050_FullCAP: // Charge full.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_FullCAP);
|
||||
data = data * 5 / 10;
|
||||
*value = data;
|
||||
break;
|
||||
case MAX17050_RepCap: // Charge now.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepCap);
|
||||
data = data * 5 / 10;
|
||||
*value = data;
|
||||
break;
|
||||
case MAX17050_TEMP: // Temp.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_TEMP);
|
||||
*value = (s16)data;
|
||||
*value = *value * 10 / 256;
|
||||
break;
|
||||
case MAX17050_Current: // Current now.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_Current);
|
||||
*value = (s16)data;
|
||||
*value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR;
|
||||
break;
|
||||
case MAX17050_AvgCurrent: // Current avg.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgCurrent);
|
||||
*value = (s16)data;
|
||||
*value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR;
|
||||
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);
|
||||
i2c_recv_buf_small((u8 *)&read_value, 2, I2C_1, MAXIM17050_I2C_ADDR, 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;
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Fuel gauge driver for Nintendo Switch's Maxim 17050
|
||||
* Note that Maxim 8966 and 8997 are mfd and this is its subdevice.
|
||||
*
|
||||
* 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"
|
||||
|
||||
#define MAX17050_STATUS_BattAbsent (1 << 3)
|
||||
#define MAX17050_DEFAULT_SNS_RESISTOR 10000
|
||||
|
||||
/* 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_ */
|
||||
@@ -1,340 +0,0 @@
|
||||
/*
|
||||
* Defining registers address and its bit definitions of MAX77620 and MAX20024
|
||||
*
|
||||
* Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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_LBDAC_EN (1 << 7)
|
||||
#define MAX77620_CNFGGLBL1_MPPLD (1 << 6)
|
||||
#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4))
|
||||
#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_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_LBRSTEN (1 << 0)
|
||||
|
||||
#define MAX77620_REG_CNFGGLBL2 0x01
|
||||
#define MAX77620_REG_CNFGGLBL3 0x02
|
||||
#define MAX77620_WDTC_MASK 0x3
|
||||
#define MAX77620_WDTOFFC (1 << 4)
|
||||
#define MAX77620_WDTSLPC (1 << 3)
|
||||
#define MAX77620_WDTEN (1 << 2)
|
||||
#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_REG_CNFG1_32K 0x03
|
||||
#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2)
|
||||
|
||||
#define MAX77620_REG_CNFGBBC 0x04
|
||||
#define MAX77620_CNFGBBC_ENABLE (1 << 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 (1 << 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_IRQ_TOP_GLBL_MASK (1 << 7)
|
||||
#define MAX77620_IRQ_TOP_SD_MASK (1 << 6)
|
||||
#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5)
|
||||
#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4)
|
||||
#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3)
|
||||
#define MAX77620_IRQ_TOP_32K_MASK (1 << 2)
|
||||
#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1)
|
||||
|
||||
#define MAX77620_REG_INTLBT 0x06
|
||||
#define MAX77620_REG_IRQTOPM 0x0D
|
||||
#define MAX77620_IRQ_LBM_MASK (1 << 3)
|
||||
#define MAX77620_IRQ_TJALRM1_MASK (1 << 2)
|
||||
#define MAX77620_IRQ_TJALRM2_MASK (1 << 1)
|
||||
|
||||
#define MAX77620_REG_IRQSD 0x07
|
||||
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08
|
||||
#define MAX77620_REG_IRQ_LVL2_L8 0x09
|
||||
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A
|
||||
#define MAX77620_REG_ONOFFIRQ 0x0B
|
||||
#define MAX77620_REG_NVERC 0x0C
|
||||
|
||||
#define MAX77620_REG_INTENLBT 0x0E
|
||||
#define MAX77620_GLBLM_MASK (1 << 0)
|
||||
|
||||
#define MAX77620_REG_IRQMASKSD 0x0F
|
||||
#define MAX77620_REG_IRQ_MSK_L0_7 0x10
|
||||
#define MAX77620_REG_IRQ_MSK_L8 0x11
|
||||
#define MAX77620_REG_ONOFFIRQM 0x12
|
||||
#define MAX77620_REG_STATLBT 0x13
|
||||
#define MAX77620_REG_STATSD 0x14
|
||||
#define MAX77620_REG_ONOFFSTAT 0x15
|
||||
|
||||
/* 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_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_DVSSD0 0x1B
|
||||
#define MAX77620_REG_DVSSD1 0x1C
|
||||
#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_REG_SD_CFG2 0x22
|
||||
#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
|
||||
#define MAX77620_LDO_POWER_MODE_MASK 0xC0
|
||||
#define MAX77620_LDO_POWER_MODE_SHIFT 6
|
||||
#define MAX77620_POWER_MODE_NORMAL 3
|
||||
#define MAX77620_POWER_MODE_LPM 2
|
||||
#define MAX77620_POWER_MODE_GLPM 1
|
||||
#define MAX77620_POWER_MODE_DISABLE 0
|
||||
#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2)
|
||||
#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_SS_MASK (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_FAST (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_SLOW 0
|
||||
|
||||
#define MAX77620_REG_LDO_CFG3 0x35
|
||||
#define MAX77620_TRACK4_MASK (1 << 5)
|
||||
#define MAX77620_TRACK4_SHIFT 5
|
||||
|
||||
#define MAX77620_LDO_SLEW_RATE_MASK 0x1
|
||||
|
||||
#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_REG_PUE_GPIO 0x3E
|
||||
#define MAX77620_REG_PDE_GPIO 0x3F
|
||||
#define MAX77620_REG_AME_GPIO 0x40
|
||||
#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_REG_ONOFFCNFG1 0x41
|
||||
#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7)
|
||||
#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
|
||||
#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
|
||||
#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2)
|
||||
#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1)
|
||||
#define MAX20024_ONOFFCNFG1_CLRSE 0x18
|
||||
|
||||
#define MAX77620_REG_ONOFFCNFG2 0x42
|
||||
#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7)
|
||||
#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6)
|
||||
#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5)
|
||||
#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2)
|
||||
#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0)
|
||||
|
||||
/* FPS Registers */
|
||||
#define MAX77620_REG_FPS_CFG0 0x43
|
||||
#define MAX77620_REG_FPS_CFG1 0x44
|
||||
#define MAX77620_REG_FPS_CFG2 0x45
|
||||
#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_NONE 0
|
||||
#define MAX77620_FPS_SRC_MASK 0xC0
|
||||
#define MAX77620_FPS_SRC_SHIFT 6
|
||||
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
|
||||
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
|
||||
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
|
||||
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
|
||||
|
||||
/* Minimum and maximum FPS period time (in microseconds) are
|
||||
* different for MAX77620 and Max20024.
|
||||
*/
|
||||
#define MAX77620_FPS_COUNT 3
|
||||
|
||||
#define MAX77620_FPS_PERIOD_MIN_US 40
|
||||
#define MAX20024_FPS_PERIOD_MIN_US 20
|
||||
|
||||
#define MAX77620_FPS_PERIOD_MAX_US 2560
|
||||
#define MAX20024_FPS_PERIOD_MAX_US 5120
|
||||
|
||||
#define MAX77620_REG_FPS_GPIO1 0x54
|
||||
#define MAX77620_REG_FPS_GPIO2 0x55
|
||||
#define MAX77620_REG_FPS_GPIO3 0x56
|
||||
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
|
||||
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
|
||||
#define MAX77620_FPS_EN_SRC_MASK 0x06
|
||||
#define MAX77620_FPS_EN_SRC_SHIFT 1
|
||||
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
|
||||
#define MAX77620_FPS_ENFPS_SW 0x01
|
||||
|
||||
#define MAX77620_REG_FPS_RSO 0x57
|
||||
#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
|
||||
#define MAX77620_REG_CID5 0x5D
|
||||
|
||||
#define MAX77620_REG_DVSSD4 0x5E
|
||||
#define MAX20024_REG_MAX_ADD 0x70
|
||||
|
||||
#define MAX77620_CID_DIDM_MASK 0xF0
|
||||
#define MAX77620_CID_DIDM_SHIFT 4
|
||||
|
||||
/* CNCG2SD */
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1)
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2)
|
||||
|
||||
/* Device Identification Metal */
|
||||
#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF)
|
||||
/* Device Indentification OTP */
|
||||
#define MAX77620_CID5_DIDO(n) ((n) & 0xF)
|
||||
|
||||
/* SD CNFG1 */
|
||||
#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 (1 << 3)
|
||||
#define MAX77620_SD_CFG1_ADE_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 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 (1 << 2)
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2)
|
||||
#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1)
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0)
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0)
|
||||
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 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,
|
||||
};
|
||||
|
||||
enum max77620_chip_id {
|
||||
MAX77620,
|
||||
MAX20024,
|
||||
};
|
||||
|
||||
#endif /* _MFD_MAX77620_H_ */
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* 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 "max7762x.h"
|
||||
#include "max77620.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#define REGULATOR_SD 0
|
||||
#define REGULATOR_LDO 1
|
||||
|
||||
typedef struct _max77620_regulator_t
|
||||
{
|
||||
u8 type;
|
||||
const char *name;
|
||||
u8 reg_sd;
|
||||
|
||||
u32 mv_step;
|
||||
u32 mv_min;
|
||||
u32 mv_default;
|
||||
u32 mv_max;
|
||||
|
||||
u8 volt_addr;
|
||||
u8 cfg_addr;
|
||||
|
||||
u8 volt_mask;
|
||||
u8 enable_mask;
|
||||
u8 enable_shift;
|
||||
u8 status_mask;
|
||||
|
||||
u8 fps_addr;
|
||||
u8 fps_src;
|
||||
u8 pd_period;
|
||||
u8 pu_period;
|
||||
} max77620_regulator_t;
|
||||
|
||||
static const max77620_regulator_t _pmic_regulators[] = {
|
||||
{ REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x80, MAX77620_REG_FPS_SD0, 1, 7, 1 },
|
||||
{ REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x40, MAX77620_REG_FPS_SD1, 0, 1, 5 },
|
||||
{ REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x20, MAX77620_REG_FPS_SD2, 1, 5, 2 },
|
||||
{ REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x10, MAX77620_REG_FPS_SD3, 0, 3, 3 },
|
||||
{ REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO0, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO1, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO2, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO3, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO4, 0, 7, 1 },
|
||||
{ REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO5, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO6, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO7, 1, 4, 3 },
|
||||
{ REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 }
|
||||
};
|
||||
|
||||
static void _max77620_try_set_reg(u8 reg, u8 val)
|
||||
{
|
||||
u8 tmp;
|
||||
do
|
||||
{
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val);
|
||||
tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg);
|
||||
} while (val != tmp);
|
||||
}
|
||||
|
||||
int max77620_regulator_get_status(u32 id)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
if (reg->type == REGULATOR_SD)
|
||||
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1;
|
||||
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & 8) ? 1 : 0;
|
||||
}
|
||||
|
||||
int max77620_regulator_config_fps(u32 id)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
_max77620_try_set_reg(reg->fps_addr,
|
||||
(reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int max77620_regulator_set_voltage(u32 id, u32 mv)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
if (mv < reg->mv_min || mv > reg->mv_max)
|
||||
return 0;
|
||||
|
||||
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
||||
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr);
|
||||
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
|
||||
_max77620_try_set_reg(reg->volt_addr, val);
|
||||
usleep(1000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int max77620_regulator_enable(u32 id, int enable)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr;
|
||||
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, addr);
|
||||
if (enable)
|
||||
val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask);
|
||||
else
|
||||
val &= ~reg->enable_mask;
|
||||
_max77620_try_set_reg(addr, val);
|
||||
usleep(1000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// LDO only.
|
||||
int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
if (mv < reg->mv_min || mv > reg->mv_max)
|
||||
return 0;
|
||||
|
||||
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
||||
u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask);
|
||||
_max77620_try_set_reg(reg->volt_addr, val);
|
||||
usleep(1000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void max77620_config_default()
|
||||
{
|
||||
for (u32 i = 1; i <= REGULATOR_MAX; i++)
|
||||
{
|
||||
i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4);
|
||||
max77620_regulator_config_fps(i);
|
||||
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
|
||||
if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE)
|
||||
max77620_regulator_enable(i, 1);
|
||||
}
|
||||
_max77620_try_set_reg(MAX77620_REG_SD_CFG2, 4);
|
||||
}
|
||||
|
||||
void max77620_low_battery_monitor_config(bool enable)
|
||||
{
|
||||
_max77620_try_set_reg(MAX77620_REG_CNFGGLBL1,
|
||||
MAX77620_CNFGGLBL1_LBDAC_EN | (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) |
|
||||
MAX77620_CNFGGLBL1_LBHYST_200 | MAX77620_CNFGGLBL1_LBDAC_2800);
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* 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 _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 |
|
||||
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
|
||||
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V
|
||||
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 |
|
||||
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 |
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_MAX 12
|
||||
|
||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||
|
||||
#define MAX77621_VOUT_REG 0
|
||||
#define MAX77621_VOUT_DVC_REG 1
|
||||
#define MAX77621_CONTROL1_REG 2
|
||||
#define MAX77621_CONTROL2_REG 3
|
||||
|
||||
/* MAX77621_VOUT */
|
||||
#define MAX77621_VOUT_ENABLE (1 << 7)
|
||||
#define MAX77621_VOUT_MASK 0x7F
|
||||
#define MAX77621_VOUT_0_95V 0x37
|
||||
#define MAX77621_VOUT_1_09V 0x4F
|
||||
|
||||
/* MAX77621_VOUT_DVC_DVS */
|
||||
#define MAX77621_DVS_VOUT_MASK 0x7F
|
||||
|
||||
/* MAX77621_CONTROL1 */
|
||||
#define MAX77621_SNS_ENABLE (1 << 7)
|
||||
#define MAX77621_FPWM_EN_M (1 << 6)
|
||||
#define MAX77621_NFSR_ENABLE (1 << 5)
|
||||
#define MAX77621_AD_ENABLE (1 << 4)
|
||||
#define MAX77621_BIAS_ENABLE (1 << 3)
|
||||
#define MAX77621_FREQSHIFT_9PER (1 << 2)
|
||||
|
||||
#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
|
||||
|
||||
/* MAX77621_CONTROL2 */
|
||||
#define MAX77621_WDTMR_ENABLE (1 << 6)
|
||||
#define MAX77621_DISCH_ENBABLE (1 << 5)
|
||||
#define MAX77621_FT_ENABLE (1 << 4)
|
||||
#define MAX77621_T_JUNCTION_120 (1 << 7)
|
||||
|
||||
#define MAX77621_CKKADV_TRIP_DISABLE 0xC
|
||||
#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0
|
||||
#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4
|
||||
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8
|
||||
|
||||
#define MAX77621_INDUCTOR_MIN_30_PER 0x0
|
||||
#define MAX77621_INDUCTOR_NOMINAL 0x1
|
||||
#define MAX77621_INDUCTOR_PLUS_30_PER 0x2
|
||||
#define MAX77621_INDUCTOR_PLUS_60_PER 0x3
|
||||
|
||||
int max77620_regulator_get_status(u32 id);
|
||||
int max77620_regulator_config_fps(u32 id);
|
||||
int max77620_regulator_set_voltage(u32 id, u32 mv);
|
||||
int max77620_regulator_enable(u32 id, int enable);
|
||||
int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags);
|
||||
void max77620_config_default();
|
||||
void max77620_low_battery_monitor_config(bool enable);
|
||||
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* 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 "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, bool hos_encoding)
|
||||
{
|
||||
u32 year, month, epoch;
|
||||
|
||||
//Year
|
||||
year = time->year;
|
||||
//Month of year
|
||||
month = time->month;
|
||||
|
||||
if (!hos_encoding)
|
||||
{
|
||||
// Month/Year offset.
|
||||
if(month < 3)
|
||||
{
|
||||
month += 12;
|
||||
year--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
year -= 2000;
|
||||
month++;
|
||||
|
||||
// Month/Year offset.
|
||||
if(month < 3)
|
||||
{
|
||||
month += 9;
|
||||
year--;
|
||||
}
|
||||
else
|
||||
month -= 3;
|
||||
}
|
||||
|
||||
epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days.
|
||||
|
||||
if (!hos_encoding)
|
||||
{
|
||||
epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days.
|
||||
epoch -= 719561; // Epoch time is 1/1/1970.
|
||||
}
|
||||
else
|
||||
epoch += (30 * month) + ((3 * month + 2) / 5) + 59 + time->day; // Months to days.
|
||||
|
||||
epoch *= 86400; // Days to seconds.
|
||||
epoch += (3600 * time->hour) + (60 * time->min) + time->sec; // Add hours, minutes and seconds.
|
||||
|
||||
return epoch;
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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 (1 << 0)
|
||||
#define MAX77620_RTC_24H (1 << 1)
|
||||
|
||||
#define MAX77620_RTC_UPDATE0_REG 0x04
|
||||
#define MAX77620_RTC_WRITE_UPDATE (1 << 0)
|
||||
#define MAX77620_RTC_READ_UPDATE (1 << 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 (1 << 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 (1 << 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, bool hos_encoding);
|
||||
|
||||
#endif /* _MFD_MAX77620_RTC_H_ */
|
||||
@@ -1,394 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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 <string.h>
|
||||
|
||||
#include "../sec/se.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../soc/bpmp.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../sec/se_t210.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
typedef struct _se_ll_t
|
||||
{
|
||||
vu32 num;
|
||||
vu32 addr;
|
||||
vu32 size;
|
||||
} se_ll_t;
|
||||
|
||||
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 _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_OFFSET) = (u32)src;
|
||||
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst;
|
||||
}
|
||||
|
||||
static int _se_wait()
|
||||
{
|
||||
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET)))
|
||||
;
|
||||
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) ||
|
||||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN ||
|
||||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
se_ll_t *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_0) = SE(SE_ERR_STATUS_0);
|
||||
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
|
||||
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
|
||||
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;
|
||||
}
|
||||
|
||||
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(0x10);
|
||||
memset(block, 0, 0x10);
|
||||
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
|
||||
memcpy(block, src, src_size);
|
||||
int res = _se_execute(op, block, 0x10, block, 0x10);
|
||||
memcpy(dst, block, dst_size);
|
||||
|
||||
free(block);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void _se_aes_ctr_set(void *ctr)
|
||||
{
|
||||
u32 *data = (u32 *)ctr;
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
SE(SE_CRYPTO_CTR_REG_OFFSET + 4 * i) = data[i];
|
||||
}
|
||||
|
||||
void se_rsa_acc_ctrl(u32 rs, u32 flags)
|
||||
{
|
||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG)
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) =
|
||||
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |
|
||||
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG);
|
||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG)
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs);
|
||||
}
|
||||
|
||||
void se_key_acc_ctrl(u32 ks, u32 flags)
|
||||
{
|
||||
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
|
||||
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags;
|
||||
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG)
|
||||
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks);
|
||||
}
|
||||
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size)
|
||||
{
|
||||
u32 *data = (u32 *)key;
|
||||
for (u32 i = 0; i < size / 4; i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_key_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < TEGRA_SE_AES_MAX_KEY_SIZE / 4; i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
|
||||
|
||||
return _se_execute(OP_START, NULL, 0, input, 0x10);
|
||||
}
|
||||
|
||||
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_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
}
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
return _se_execute(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_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
}
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
return _se_execute(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, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
||||
{
|
||||
SE(SE_SPARE_0_REG_OFFSET) = 1;
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = 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_VAL(1);
|
||||
_se_aes_ctr_set(ctr);
|
||||
|
||||
u32 src_size_aligned = src_size & 0xFFFFFFF0;
|
||||
u32 src_size_delta = src_size & 0xF;
|
||||
|
||||
if (src_size_aligned)
|
||||
{
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
if (!_se_execute(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(OP_START, dst + src_size_aligned,
|
||||
MIN(src_size_delta, dst_size - src_size_aligned),
|
||||
src + src_size_aligned, src_size_delta);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
|
||||
{
|
||||
int res = 0;
|
||||
u8 *tweak = (u8 *)malloc(0x10);
|
||||
u8 *pdst = (u8 *)dst;
|
||||
u8 *psrc = (u8 *)src;
|
||||
|
||||
//Generate tweak.
|
||||
for (int i = 0xF; i >= 0; i--)
|
||||
{
|
||||
tweak[i] = sec & 0xFF;
|
||||
sec >>= 8;
|
||||
}
|
||||
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
|
||||
goto out;
|
||||
|
||||
//We are assuming a 0x10-aligned sector size in this implementation.
|
||||
for (u32 i = 0; i < secsize / 0x10; i++)
|
||||
{
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
pdst[j] = psrc[j] ^ tweak[j];
|
||||
if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst))
|
||||
goto out;
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
pdst[j] = pdst[j] ^ tweak[j];
|
||||
_gf256_mul_x(tweak);
|
||||
psrc += 0x10;
|
||||
pdst += 0x10;
|
||||
}
|
||||
|
||||
res = 1;
|
||||
|
||||
out:;
|
||||
free(tweak);
|
||||
return res;
|
||||
}
|
||||
|
||||
int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize, 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(ks1, ks2, enc, sec + i, pdst + secsize * i, psrc + secsize * i, secsize))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int se_calc_sha256(void *dst, const void *src, u32 src_size)
|
||||
{
|
||||
int res;
|
||||
// Setup config for SHA256, size = BITS(src_size).
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_SHA_CONFIG_REG_OFFSET) = SHA_INIT_HASH;
|
||||
SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(src_size << 3);
|
||||
SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(src_size << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0;
|
||||
|
||||
// Trigger the operation.
|
||||
res = _se_execute(OP_START, NULL, 0, src, src_size);
|
||||
|
||||
// Copy output hash.
|
||||
u32 *dst32 = (u32 *)dst;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
dst32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int se_gen_prng128(void *dst)
|
||||
{
|
||||
// Setup config for X931 PRNG.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
|
||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL);
|
||||
//SE(SE_RNG_SRC_CONFIG_REG_OFFSET) =
|
||||
// SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 1;
|
||||
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (16 >> 4) - 1;
|
||||
|
||||
// Trigger the operation.
|
||||
return _se_execute(OP_START, dst, 16, NULL, 0);
|
||||
}
|
||||
|
||||
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_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED);
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute(OP_START, NULL, 0, NULL, 0);
|
||||
|
||||
// Save AES keys.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
|
||||
for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++)
|
||||
{
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
||||
memcpy(keys + i * keysize, aligned_buf, 0x10);
|
||||
|
||||
if (keysize > 0x10)
|
||||
{
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
||||
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
// Save SRK to PMC secure scratches.
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK);
|
||||
SE(0x80) = 0; // SE_CRYPTO_LAST_BLOCK
|
||||
_se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// End context save.
|
||||
SE(SE_CONFIG_REG_OFFSET) = 0;
|
||||
_se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// Get SRK.
|
||||
u32 srk[4];
|
||||
srk[0] = PMC(0xC0);
|
||||
srk[1] = PMC(0xC4);
|
||||
srk[2] = PMC(0x224);
|
||||
srk[3] = PMC(0x228);
|
||||
|
||||
// Decrypt context.
|
||||
se_aes_key_clear(3);
|
||||
se_aes_key_set(3, srk, 0x10);
|
||||
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize);
|
||||
se_aes_key_clear(3);
|
||||
}
|
||||
@@ -1,288 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 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 "../sec/tsec.h"
|
||||
#include "../sec/tsec_t210.h"
|
||||
#include "../sec/se_t210.h"
|
||||
#include "../soc/bpmp.h"
|
||||
#include "../soc/clock.h"
|
||||
#include "../soc/kfuse.h"
|
||||
#include "../soc/smmu.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../mem/mc.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../hos/hos.h"
|
||||
|
||||
// #include "../gfx/gfx.h"
|
||||
|
||||
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(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
{
|
||||
int res = 0;
|
||||
u8 *fwbuf = NULL;
|
||||
u32 *pdir, *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
|
||||
u32 *pkg11_magic_off;
|
||||
|
||||
bpmp_mmu_disable();
|
||||
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();
|
||||
|
||||
// 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 (kb == KB_FIRMWARE_VERSION_620)
|
||||
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
|
||||
else
|
||||
{
|
||||
fwbuf = (u8 *)malloc(0x4000);
|
||||
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 (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
// 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, 0x1000);
|
||||
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, 0x400);
|
||||
fuse[0x82C / 4] = 0;
|
||||
fuse[0x9E0 / 4] = (1 << (kb + 2)) - 1;
|
||||
fuse[0x9E4 / 4] = (1 << (kb + 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, 0x1000);
|
||||
smmu_map(pdir, SE_BASE, (u32)se, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||
|
||||
// Memory controller.
|
||||
mc = page_alloc(1);
|
||||
memcpy(mc, (void *)MC_BASE, 0x1000);
|
||||
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 (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
u32 start = get_tmr_us();
|
||||
u32 k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
|
||||
u32 key[16] = {0};
|
||||
u32 kidx = 0;
|
||||
|
||||
while (*pkg11_magic_off != HOS_PKG11_MAGIC)
|
||||
{
|
||||
smmu_flush_all();
|
||||
|
||||
if (k != se[SE_KEYTABLE_DATA0_REG_OFFSET / 4])
|
||||
{
|
||||
k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 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, 0x10);
|
||||
}
|
||||
|
||||
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(BPMP_CLK_DEFAULT_BOOST);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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 (1 << 0)
|
||||
#define TSEC_ITFEN_MTHDEN (1 << 1)
|
||||
#define TSEC_IRQMSET 0x1010
|
||||
#define TSEC_IRQMSET_WDTMR (1 << 1)
|
||||
#define TSEC_IRQMSET_HALT (1 << 4)
|
||||
#define TSEC_IRQMSET_EXTERR (1 << 5)
|
||||
#define TSEC_IRQMSET_SWGEN0 (1 << 6)
|
||||
#define TSEC_IRQMSET_SWGEN1 (1 << 7)
|
||||
#define TSEC_IRQMSET_EXT(val) (((val) & 0xFF) << 8)
|
||||
#define TSEC_IRQDEST 0x101C
|
||||
#define TSEC_IRQDEST_HALT (1 << 4)
|
||||
#define TSEC_IRQDEST_EXTERR (1 << 5)
|
||||
#define TSEC_IRQDEST_SWGEN0 (1 << 6)
|
||||
#define TSEC_IRQDEST_SWGEN1 (1 << 7)
|
||||
#define TSEC_IRQDEST_EXT(val) (((val) & 0xFF) << 8)
|
||||
#define TSEC_CPUCTL 0x1100
|
||||
#define TSEC_CPUCTL_STARTCPU (1 << 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 (1 << 1)
|
||||
#define TSEC_DMATRFCMD_IMEM (1 << 4)
|
||||
#define TSEC_DMATRFCMD_SIZE_256B (6 << 8)
|
||||
#define TSEC_DMATRFFBOFFS 0x111C
|
||||
|
||||
#endif
|
||||
@@ -1,308 +0,0 @@
|
||||
/*
|
||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||
*
|
||||
* 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 "bpmp.h"
|
||||
#include "clock.h"
|
||||
#include "t210.h"
|
||||
#include "../../common/memory_map.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#define BPMP_MMU_CACHE_LINE_SIZE 0x20
|
||||
|
||||
#define BPMP_CACHE_CONFIG 0x0
|
||||
#define CFG_ENABLE_CACHE (1 << 0)
|
||||
#define CFG_ENABLE_SKEW_ASSOC (1 << 1)
|
||||
#define CFG_DISABLE_RANDOM_ALLOC (1 << 2)
|
||||
#define CFG_FORCE_WRITE_THROUGH (1 << 3)
|
||||
#define CFG_NEVER_ALLOCATE (1 << 6)
|
||||
#define CFG_ENABLE_INTERRUPT (1 << 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 (1 << 10)
|
||||
#define CFG_DISABLE_READ_BUFFER (1 << 11)
|
||||
#define CFG_ENABLE_HANG_DETECT (1 << 12)
|
||||
#define CFG_FULL_LINE_DIRTY (1 << 13)
|
||||
#define CFG_TAG_CHK_ABRT_ON_ERR (1 << 14)
|
||||
#define CFG_TAG_CHK_CLR_ERR (1 << 15)
|
||||
#define CFG_DISABLE_SAMELINE (1 << 16)
|
||||
#define CFG_OBS_BUS_EN (1 << 31)
|
||||
|
||||
#define BPMP_CACHE_LOCK 0x4
|
||||
#define LOCK_LINE(x) (1 << x)
|
||||
|
||||
#define BPMP_CACHE_SIZE 0xC
|
||||
#define BPMP_CACHE_LFSR 0x10
|
||||
|
||||
#define BPMP_CACHE_TAG_STATUS 0x14
|
||||
#define TAG_STATUS_TAG_CHECK_ERROR (1 << 0)
|
||||
#define TAG_STATUS_CONFLICT_ADDR_MASK 0xFFFFFFE0
|
||||
|
||||
#define BPMP_CACHE_CLKEN_OVERRIDE 0x18
|
||||
#define CLKEN_OVERRIDE_WR_MCCIF_CLKEN (1 << 0)
|
||||
#define CLKEN_OVERRIDE_RD_MCCIF_CLKEN (1 << 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 (1 << 0)
|
||||
#define INT_MAINT_ERROR (1 << 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 (1 << 0)
|
||||
#define MMU_CFG_SEQ_EN (1 << 1)
|
||||
#define MMU_CFG_TLB_EN (1 << 2)
|
||||
#define MMU_CFG_SEG_CHECK_ALL_ENTRIES (1 << 3)
|
||||
#define MMU_CFG_ABORT_STORE_LAST (1 << 4)
|
||||
#define MMU_CFG_CLR_ABORT (1 << 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 (1 << 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 (1 << 20)
|
||||
#define ABORT_STAT_PROT (1 << 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 (1 << 0)
|
||||
#define MMU_EN_EXEC (1 << 1)
|
||||
#define MMU_EN_READ (1 << 2)
|
||||
#define MMU_EN_WRITE (1 << 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) |= (1 << 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 < (sizeof(mmu_entries) / sizeof(bpmp_mmu_entry_t)); 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_clock_set = 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_clock_set = BPMP_CLK_NORMAL;
|
||||
else
|
||||
{
|
||||
bpmp_clock_set = 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_clock_set = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bpmp_clk_rate_set(bpmp_freq_t fid)
|
||||
{
|
||||
if (fid > (BPMP_CLK_MAX - 1))
|
||||
fid = BPMP_CLK_MAX - 1;
|
||||
|
||||
if (bpmp_clock_set == fid)
|
||||
return;
|
||||
|
||||
if (fid)
|
||||
{
|
||||
if (bpmp_clock_set)
|
||||
{
|
||||
// Restore to PLLP source during PLLC4 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_clock_set = 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;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||
*
|
||||
* 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 _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_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();
|
||||
void bpmp_clk_rate_set(bpmp_freq_t fid);
|
||||
void bpmp_usleep(u32 us);
|
||||
void bpmp_msleep(u32 ms);
|
||||
void bpmp_halt();
|
||||
|
||||
#endif
|
||||
@@ -1,645 +0,0 @@
|
||||
/*
|
||||
* 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/t210.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
|
||||
/*
|
||||
* CLOCK Peripherals:
|
||||
* L 0 - 31
|
||||
* H 32 - 63
|
||||
* U 64 - 95
|
||||
* V 96 - 127
|
||||
* W 128 - 159
|
||||
* X 160 - 191
|
||||
* Y 192 - 223
|
||||
*/
|
||||
|
||||
/* clock_t: reset, enable, source, index, clk_src, clk_div */
|
||||
|
||||
static const clock_t _clock_uart[] = {
|
||||
/* UART A */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, 6, 0, 2 },
|
||||
/* UART B */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, 7, 0, 2 },
|
||||
/* UART C */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, 23, 0, 2 },
|
||||
/* UART D */ { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, 1, 0, 2 },
|
||||
/* UART E */ { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, 20, 0, 2 }
|
||||
};
|
||||
|
||||
//I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26.
|
||||
static const clock_t _clock_i2c[] = {
|
||||
/* I2C1 */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, 12, 0, 19 }, //20.4MHz -> 100KHz
|
||||
/* I2C2 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, 22, 0, 4 }, //81.6MHz -> 400KHz
|
||||
/* I2C3 */ { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, 3, 0, 4 }, //81.6MHz -> 400KHz
|
||||
/* I2C4 */ { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, 7, 0, 19 }, //20.4MHz -> 100KHz
|
||||
/* I2C5 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, 15, 0, 4 }, //81.6MHz -> 400KHz
|
||||
/* I2C6 */ { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, 6, 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, 31, 0, 0
|
||||
};
|
||||
|
||||
static clock_t _clock_tzram = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, 30, 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, 28, 4, 3
|
||||
};
|
||||
static clock_t _clock_tsec = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, 19, 0, 2
|
||||
};
|
||||
static clock_t _clock_sor_safe = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, 30, 0, 0
|
||||
};
|
||||
static clock_t _clock_sor0 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, 22, 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, 23, 0, 2
|
||||
};
|
||||
static clock_t _clock_kfuse = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, 8, 0, 0
|
||||
};
|
||||
|
||||
static clock_t _clock_cl_dvfs = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, 27, 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, 9, 0, 4
|
||||
};
|
||||
|
||||
static clock_t _clock_pwm = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 17, 6, 4 // Fref: 6.2MHz.
|
||||
};
|
||||
|
||||
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, 1, 4, 66
|
||||
};
|
||||
|
||||
void clock_enable(const clock_t *clk)
|
||||
{
|
||||
// Put clock into reset.
|
||||
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~(1 << clk->index)) | (1 << clk->index);
|
||||
// Disable.
|
||||
CLOCK(clk->enable) &= ~(1 << 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) & ~(1 << clk->index)) | (1 << clk->index);
|
||||
usleep(2);
|
||||
|
||||
// Take clock off reset.
|
||||
CLOCK(clk->reset) &= ~(1 << clk->index);
|
||||
}
|
||||
|
||||
void clock_disable(const clock_t *clk)
|
||||
{
|
||||
// Put clock into reset.
|
||||
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~(1 << clk->index)) | (1 << clk->index);
|
||||
// Disable.
|
||||
CLOCK(clk->enable) &= ~(1 << clk->index);
|
||||
}
|
||||
|
||||
void clock_enable_fuse(bool enable)
|
||||
{
|
||||
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 (1 << 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);
|
||||
}
|
||||
|
||||
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_enable(&_clock_kfuse);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & 0xFFFFFEFF) | 0x100;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= 0xFFFFFEFF;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & 0xFFFFFEFF) | 0x100;
|
||||
usleep(10);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= 0xFFFFFEFF;
|
||||
usleep(20);
|
||||
}
|
||||
|
||||
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_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) = (1 << 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 L_SWR_SDMMC1_RST (1 << 14)
|
||||
#define L_SWR_SDMMC2_RST (1 << 9)
|
||||
#define L_SWR_SDMMC4_RST (1 << 15)
|
||||
#define U_SWR_SDMMC3_RST (1 << 5)
|
||||
|
||||
#define L_CLK_ENB_SDMMC1 (1 << 14)
|
||||
#define L_CLK_ENB_SDMMC2 (1 << 9)
|
||||
#define L_CLK_ENB_SDMMC4 (1 << 15)
|
||||
#define U_CLK_ENB_SDMMC3 (1 << 5)
|
||||
|
||||
#define L_SET_SDMMC1_RST (1 << 14)
|
||||
#define L_SET_SDMMC2_RST (1 << 9)
|
||||
#define L_SET_SDMMC4_RST (1 << 15)
|
||||
#define U_SET_SDMMC3_RST (1 << 5)
|
||||
|
||||
#define L_CLR_SDMMC1_RST (1 << 14)
|
||||
#define L_CLR_SDMMC2_RST (1 << 9)
|
||||
#define L_CLR_SDMMC4_RST (1 << 15)
|
||||
#define U_CLR_SDMMC3_RST (1 << 5)
|
||||
|
||||
#define L_SET_CLK_ENB_SDMMC1 (1 << 14)
|
||||
#define L_SET_CLK_ENB_SDMMC2 (1 << 9)
|
||||
#define L_SET_CLK_ENB_SDMMC4 (1 << 15)
|
||||
#define U_SET_CLK_ENB_SDMMC3 (1 << 5)
|
||||
|
||||
#define L_CLR_CLK_ENB_SDMMC1 (1 << 14)
|
||||
#define L_CLR_CLK_ENB_SDMMC2 (1 << 9)
|
||||
#define L_CLR_CLK_ENB_SDMMC4 (1 << 15)
|
||||
#define U_CLR_CLK_ENB_SDMMC3 (1 << 5)
|
||||
|
||||
static int _clock_sdmmc_is_reset(u32 id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case SDMMC_1:
|
||||
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC1_RST;
|
||||
case SDMMC_2:
|
||||
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC2_RST;
|
||||
case SDMMC_3:
|
||||
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & U_SWR_SDMMC3_RST;
|
||||
case SDMMC_4:
|
||||
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC4_RST;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _clock_sdmmc_set_reset(u32 id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case SDMMC_1:
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC1_RST;
|
||||
break;
|
||||
case SDMMC_2:
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC2_RST;
|
||||
break;
|
||||
case SDMMC_3:
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = U_SET_SDMMC3_RST;
|
||||
break;
|
||||
case SDMMC_4:
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC4_RST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _clock_sdmmc_clear_reset(u32 id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case SDMMC_1:
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC1_RST;
|
||||
break;
|
||||
case SDMMC_2:
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC2_RST;
|
||||
break;
|
||||
case SDMMC_3:
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = U_CLR_SDMMC3_RST;
|
||||
break;
|
||||
case SDMMC_4:
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC4_RST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _clock_sdmmc_is_enabled(u32 id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case SDMMC_1:
|
||||
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC1;
|
||||
case SDMMC_2:
|
||||
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC2;
|
||||
case SDMMC_3:
|
||||
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & U_CLK_ENB_SDMMC3;
|
||||
case SDMMC_4:
|
||||
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _clock_sdmmc_set_enable(u32 id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case SDMMC_1:
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC1;
|
||||
break;
|
||||
case SDMMC_2:
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC2;
|
||||
break;
|
||||
case SDMMC_3:
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = U_SET_CLK_ENB_SDMMC3;
|
||||
break;
|
||||
case SDMMC_4:
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _clock_sdmmc_clear_enable(u32 id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case SDMMC_1:
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC1;
|
||||
break;
|
||||
case SDMMC_2:
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC2;
|
||||
break;
|
||||
case SDMMC_3:
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = U_CLR_CLK_ENB_SDMMC3;
|
||||
break;
|
||||
case SDMMC_4:
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _clock_sdmmc_config_legacy_tm()
|
||||
{
|
||||
clock_t *clk = &_clock_sdmmc_legacy_tm;
|
||||
if (!(CLOCK(clk->enable) & (1 << 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:
|
||||
*pclock = 90667;
|
||||
divisor = 7; // 4.5 div.
|
||||
break;
|
||||
case 164000:
|
||||
*pclock = 163200;
|
||||
divisor = 3; // 2.5 div.
|
||||
break;
|
||||
case 200000:
|
||||
*pclock = 204000;
|
||||
divisor = 2; // 2 div.
|
||||
break;
|
||||
default:
|
||||
*pclock = 24728;
|
||||
divisor = 31; // 16.5 div.
|
||||
}
|
||||
|
||||
_clock_sdmmc_table[id].clock = val;
|
||||
_clock_sdmmc_table[id].real_clock = *pclock;
|
||||
|
||||
// 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_DDR52: // Actual IO Freq: 49.92 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);
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* 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_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_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_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_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
|
||||
|
||||
/*! PLL control and status bits */
|
||||
#define PLLCX_BASE_ENABLE (1 << 30)
|
||||
#define PLLCX_BASE_REF_DIS (1 << 29)
|
||||
#define PLLCX_BASE_LOCK (1 << 27)
|
||||
|
||||
#define PLLA_BASE_IDDQ (1 << 25)
|
||||
#define PLLA_OUT0_CLKEN (1 << 1)
|
||||
#define PLLA_OUT0_RSTN_CLR (1 << 0)
|
||||
|
||||
#define PLLC_MISC_RESET (1 << 30)
|
||||
#define PLLC_MISC1_IDDQ (1 << 27)
|
||||
#define PLLC_OUT1_CLKEN (1 << 1)
|
||||
#define PLLC_OUT1_RSTN_CLR (1 << 0)
|
||||
|
||||
#define PLLC4_MISC_EN_LCKDET (1 << 30)
|
||||
#define PLLC4_BASE_IDDQ (1 << 18)
|
||||
#define PLLC4_OUT3_CLKEN (1 << 1)
|
||||
#define PLLC4_OUT3_RSTN_CLR (1 << 0)
|
||||
|
||||
/*! Generic clock descriptor. */
|
||||
typedef struct _clock_t
|
||||
{
|
||||
u32 reset;
|
||||
u32 enable;
|
||||
u32 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_pllc(u32 divn);
|
||||
void clock_disable_pllc();
|
||||
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);
|
||||
|
||||
#endif
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* 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/cluster.h"
|
||||
#include "../soc/i2c.h"
|
||||
#include "../soc/clock.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../power/max77620.h"
|
||||
#include "../power/max7762x.h"
|
||||
|
||||
void _cluster_enable_power()
|
||||
{
|
||||
u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); // Get current pinmuxing
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~(1 << 5)); // Disable GPIO5 pinmuxing.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
|
||||
|
||||
// Enable cores power.
|
||||
// 1-3.x: MAX77621_NFSR_ENABLE.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG,
|
||||
MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE | MAX77621_RAMP_12mV_PER_US);
|
||||
// 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVC_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
|
||||
}
|
||||
|
||||
int _cluster_pmc_enable_partition(u32 part, int enable)
|
||||
{
|
||||
u32 part_mask = 1 << 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;
|
||||
}
|
||||
|
||||
void cluster_boot_cpu0(u32 entry)
|
||||
{
|
||||
// Set ACTIVE_CLUSER to FAST.
|
||||
FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE;
|
||||
|
||||
_cluster_enable_power();
|
||||
|
||||
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE.
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ.
|
||||
usleep(2);
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02;
|
||||
}
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000))
|
||||
;
|
||||
|
||||
// Configure MSELECT source and enable clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & 0xFFFFFFF7) | 8;
|
||||
|
||||
// Configure initial CPU clock frequency and enable clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888;
|
||||
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = 1;
|
||||
|
||||
clock_enable_coresight();
|
||||
|
||||
// CAR2PMC_CPU_ACK_WIDTH should be set to 0.
|
||||
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
|
||||
|
||||
// Enable CPU rail.
|
||||
_cluster_pmc_enable_partition(0, 1);
|
||||
// Enable cluster 0 non-CPU.
|
||||
_cluster_pmc_enable_partition(15, 1);
|
||||
// Enable CE0.
|
||||
_cluster_pmc_enable_partition(14, 1);
|
||||
|
||||
// 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_DEVICES_V) &= 0xFFFFFFF7;
|
||||
// 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;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* 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 _CLUSTER_H_
|
||||
#define _CLUSTER_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
void cluster_boot_cpu0(u32 entry);
|
||||
|
||||
#endif
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 shuffle2
|
||||
* Copyright (c) 2018 balika011
|
||||
* 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 "../soc/fuse.h"
|
||||
#include "../soc/t210.h"
|
||||
|
||||
#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x))
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
for (u32 i = 0; i < 192; 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 < ARRAYSIZE(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 >= ARRAYSIZE(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 >= ARRAYSIZE(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.
|
||||
if (FUSE(FUSE_RESERVED_SW) & (1<<7))
|
||||
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;
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 shuffle2
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
/*! 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))
|
||||
|
||||
void fuse_disable_program();
|
||||
u32 fuse_read_odm(u32 idx);
|
||||
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
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* 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 "gpio.h"
|
||||
#include "irq.h"
|
||||
#include "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))
|
||||
|
||||
static u8 gpio_bank_irq_ids[8] = {
|
||||
IRQ_GPIO1, IRQ_GPIO2, IRQ_GPIO3, IRQ_GPIO4,
|
||||
IRQ_GPIO5, IRQ_GPIO6, IRQ_GPIO7, IRQ_GPIO8
|
||||
};
|
||||
|
||||
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];
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* 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 (1 << 0)
|
||||
#define GPIO_PIN_1 (1 << 1)
|
||||
#define GPIO_PIN_2 (1 << 2)
|
||||
#define GPIO_PIN_3 (1 << 3)
|
||||
#define GPIO_PIN_4 (1 << 4)
|
||||
#define GPIO_PIN_5 (1 << 5)
|
||||
#define GPIO_PIN_6 (1 << 6)
|
||||
#define GPIO_PIN_7 (1 << 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
|
||||
@@ -1,365 +0,0 @@
|
||||
/*
|
||||
* 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 "hw_init.h"
|
||||
#include "bpmp.h"
|
||||
#include "clock.h"
|
||||
#include "fuse.h"
|
||||
#include "gpio.h"
|
||||
#include "i2c.h"
|
||||
#include "pinmux.h"
|
||||
#include "pmc.h"
|
||||
#include "t210.h"
|
||||
#include "uart.h"
|
||||
#include "../gfx/di.h"
|
||||
#include "../mem/mc.h"
|
||||
#include "../mem/minerva.h"
|
||||
#include "../mem/sdram.h"
|
||||
#include "../power/max77620.h"
|
||||
#include "../power/max7762x.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../sec/se_t210.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
extern boot_cfg_t b_cfg;
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
|
||||
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 SCLK div to 1.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set clk 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.
|
||||
}
|
||||
|
||||
void _config_gpios()
|
||||
{
|
||||
PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0;
|
||||
PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0;
|
||||
|
||||
// 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 pin mode for Joy-Con IsAttached and 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
|
||||
// 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 and 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);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void _mbist_workaround()
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
|
||||
|
||||
// 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.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = 0x40; // Clear reset APE.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = 0x40000; // Clear reset VIC.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X.
|
||||
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.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = 0x40; // Set reset APE.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1x.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = 0x40000; // Set reset VIC.
|
||||
|
||||
// Enable specific clocks and disable all others.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = 0xC0; // Enable clock PMC, FUSE.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80000130; // Enable clock RTC, TMR, GPIO, BPMP_CACHE.
|
||||
//CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80400130; // Keep USBD ON.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = 0x1F00200; // Enable clock CSITE, IRAMA, IRAMB, IRAMC, IRAMD, BPMP_CACHE_RAM.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = 0x80400808; // Enable clock MSELECT, APB2APE, SPDIF_DOUBLER, SE.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = 0x402000FC; // Enable clock PCIERX0, PCIERX1, PCIERX2, PCIERX3, PCIERX4, PCIERX5, ENTROPY, MC1.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = 0x23000780; // Enable clock MC_CAPA, MC_CAPB, MC_CPU, MC_BBC, DBGAPB, HPLL_ADSP, PLLG_REF.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = 0x300; // Enable clock MC_CDPA, 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.
|
||||
}
|
||||
|
||||
void _config_se_brom()
|
||||
{
|
||||
// Enable fuse clock.
|
||||
clock_enable_fuse(true);
|
||||
|
||||
// Skip SBK/SSK if sept was run.
|
||||
if (!(b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN))
|
||||
{
|
||||
// Bootrom part we skipped.
|
||||
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, 0x10);
|
||||
|
||||
// Lock SBK from being read.
|
||||
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 14 * 4) = 0x7E;
|
||||
|
||||
// Lock SSK (although it's not set and unused anyways).
|
||||
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 15 * 4) = 0x7E;
|
||||
}
|
||||
|
||||
// This memset needs to happen here, else TZRAM will behave weirdly later on.
|
||||
memset((void *)TZRAM_BASE, 0, 0x10000);
|
||||
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
|
||||
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void _config_regulators()
|
||||
{
|
||||
// Disable low battery shutdown monitor.
|
||||
max77620_low_battery_monitor_config(false);
|
||||
|
||||
// Disable SDMMC1 IO power.
|
||||
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 0);
|
||||
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,
|
||||
(1 << 6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
|
||||
|
||||
// Configure all Flexible Power Sequencers.
|
||||
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.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD0, 1125000);
|
||||
|
||||
// Fix CPU/GPU after a L4T warmboot.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVC_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVC_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
|
||||
}
|
||||
|
||||
void config_hw()
|
||||
{
|
||||
// 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;
|
||||
|
||||
_mbist_workaround();
|
||||
clock_enable_se();
|
||||
|
||||
// Enable fuse clock.
|
||||
clock_enable_fuse(true);
|
||||
|
||||
// Disable fuse programming.
|
||||
fuse_disable_program();
|
||||
|
||||
mc_enable();
|
||||
|
||||
_config_oscillators();
|
||||
APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0;
|
||||
_config_gpios();
|
||||
|
||||
#ifdef DEBUG_UART_PORT
|
||||
clock_enable_uart(DEBUG_UART_PORT);
|
||||
uart_init(DEBUG_UART_PORT, 115200);
|
||||
#endif
|
||||
|
||||
clock_enable_cl_dvfs();
|
||||
|
||||
clock_enable_i2c(I2C_1);
|
||||
clock_enable_i2c(I2C_5);
|
||||
|
||||
clock_enable_tzram();
|
||||
|
||||
i2c_init(I2C_1);
|
||||
i2c_init(I2C_5);
|
||||
|
||||
_config_regulators();
|
||||
|
||||
_config_pmc_scratch(); // Missing from 4.x+
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz).
|
||||
|
||||
sdram_init();
|
||||
|
||||
bpmp_mmu_enable();
|
||||
|
||||
// Clear flags from PMC_SCRATCH0
|
||||
PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD;
|
||||
}
|
||||
|
||||
void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
|
||||
{
|
||||
// Flush and disable MMU.
|
||||
bpmp_mmu_disable();
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
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) |= (1 << 10); // Enable AHUB clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
|
||||
|
||||
if (extra_reconfig)
|
||||
{
|
||||
msleep(10);
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Power off display.
|
||||
display_end();
|
||||
|
||||
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
|
||||
if (magic == 0xBAADF00D)
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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 _HW_INIT_H_
|
||||
#define _HW_INIT_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
void config_hw();
|
||||
void reconfig_hw_workaround(bool extra_reconfig, u32 magic);
|
||||
|
||||
#endif
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* 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 "i2c.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
static const u32 i2c_addrs[] = {
|
||||
0x7000C000, 0x7000C400, 0x7000C500,
|
||||
0x7000C700, 0x7000D000, 0x7000D100
|
||||
};
|
||||
|
||||
static void _i2c_wait(vu32 *base)
|
||||
{
|
||||
base[I2C_CONFIG_LOAD] = 0x25;
|
||||
for (u32 i = 0; i < 20; i++)
|
||||
{
|
||||
usleep(1);
|
||||
if (!(base[I2C_CONFIG_LOAD] & 1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
|
||||
{
|
||||
if (size > 8)
|
||||
return 0;
|
||||
|
||||
u32 tmp = 0;
|
||||
|
||||
vu32 *base = (vu32 *)i2c_addrs[idx];
|
||||
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
base[I2C_CNFG] = ((size - 1) << 1) | 0x2800; //Set size and send mode.
|
||||
_i2c_wait(base); //Kick transaction.
|
||||
|
||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
|
||||
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
while (base[I2C_STATUS] & 0x100)
|
||||
{
|
||||
if (get_tmr_ms() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (base[I2C_STATUS] << 28)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
|
||||
{
|
||||
if (size > 8)
|
||||
return 0;
|
||||
|
||||
vu32 *base = (vu32 *)i2c_addrs[idx];
|
||||
base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode).
|
||||
base[I2C_CNFG] = ((size - 1) << 1) | 0x2840; // Set size and recv mode.
|
||||
_i2c_wait(base); // Kick transaction.
|
||||
|
||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
|
||||
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
while (base[I2C_STATUS] & 0x100)
|
||||
{
|
||||
if (get_tmr_ms() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (base[I2C_STATUS] << 28)
|
||||
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;
|
||||
}
|
||||
|
||||
void i2c_init(u32 idx)
|
||||
{
|
||||
vu32 *base = (vu32 *)i2c_addrs[idx];
|
||||
|
||||
base[I2C_CLK_DIVISOR_REGISTER] = 0x50001;
|
||||
base[I2C_BUS_CLEAR_CONFIG] = 0x90003;
|
||||
_i2c_wait(base);
|
||||
|
||||
for (u32 i = 0; i < 10; i++)
|
||||
{
|
||||
usleep(20000);
|
||||
if (base[INTERRUPT_STATUS_REGISTER] & 0x800)
|
||||
break;
|
||||
}
|
||||
|
||||
(vu32)base[I2C_BUS_CLEAR_STATUS];
|
||||
base[INTERRUPT_STATUS_REGISTER] = base[INTERRUPT_STATUS_REGISTER];
|
||||
}
|
||||
|
||||
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size)
|
||||
{
|
||||
u8 tmp[4];
|
||||
|
||||
if (size > 7)
|
||||
return 0;
|
||||
|
||||
tmp[0] = y;
|
||||
memcpy(tmp + 1, buf, size);
|
||||
|
||||
return _i2c_send_pkt(idx, x, tmp, size + 1);
|
||||
}
|
||||
|
||||
int i2c_recv_buf(u8 *buf, u32 size, u32 idx, u32 x)
|
||||
{
|
||||
return _i2c_recv_pkt(idx, buf, size, x);
|
||||
}
|
||||
|
||||
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y)
|
||||
{
|
||||
int res = _i2c_send_pkt(idx, x, (u8 *)&y, 1);
|
||||
if (res)
|
||||
res = _i2c_recv_pkt(idx, buf, size, x);
|
||||
return res;
|
||||
}
|
||||
|
||||
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b)
|
||||
{
|
||||
return i2c_send_buf_small(idx, x, y, &b, 1);
|
||||
}
|
||||
|
||||
u8 i2c_recv_byte(u32 idx, u32 x, u32 y)
|
||||
{
|
||||
u8 tmp = 0;
|
||||
i2c_recv_buf_small(&tmp, 1, idx, x, y);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define I2C_CNFG 0x00
|
||||
#define I2C_CMD_ADDR0 0x01
|
||||
#define I2C_CMD_DATA1 0x03
|
||||
#define I2C_CMD_DATA2 0x04
|
||||
#define I2C_STATUS 0x07
|
||||
#define INTERRUPT_STATUS_REGISTER 0x1A
|
||||
#define I2C_CLK_DIVISOR_REGISTER 0x1B
|
||||
#define I2C_BUS_CLEAR_CONFIG 0x21
|
||||
#define I2C_BUS_CLEAR_STATUS 0x22
|
||||
#define I2C_CONFIG_LOAD 0x23
|
||||
|
||||
void i2c_init(u32 idx);
|
||||
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size);
|
||||
int i2c_recv_buf(u8 *buf, u32 size, u32 idx, u32 x);
|
||||
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y);
|
||||
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b);
|
||||
u8 i2c_recv_byte(u32 idx, u32 x, u32 y);
|
||||
|
||||
#endif
|
||||
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* 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 "t210.h"
|
||||
#include "../gfx/gfx.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) &= ~(1 << bit);
|
||||
|
||||
// Enable IRQ source.
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_SET) = 1 << 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) = 1 << 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) = 1 << 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;
|
||||
}
|
||||
}
|
||||
|
||||
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_ack_source(irq);
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF("IRQ: %d\n", irq);
|
||||
|
||||
int err = _irq_handle_source(irq);
|
||||
|
||||
//TODO: disable if unhandhled.
|
||||
if (err == IRQ_NONE)
|
||||
gfx_printf("Unhandled IRQ: %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()
|
||||
{
|
||||
_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--;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
* 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 = (1 << 0),
|
||||
IRQ_FLAG_REPLACEABLE = (1 << 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
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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_SOFTRESET (1 << 31)
|
||||
#define KFUSE_STATE_STOP (1 << 25)
|
||||
#define KFUSE_STATE_RESTART (1 << 24)
|
||||
#define KFUSE_STATE_CRCPASS (1 << 17)
|
||||
#define KFUSE_STATE_DONE (1 << 16)
|
||||
#define KFUSE_STATE_ERRBLOCK_MASK 0x3F00
|
||||
#define KFUSE_STATE_ERRBLOCK_SHIFT 8
|
||||
#define KFUSE_STATE_CURBLOCK_MASK 0x3F
|
||||
|
||||
#define KFUSE_KEYADDR_AUTOINC (1<<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
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
/*! 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 (1 << 4)
|
||||
#define PINMUX_PARKED (1 << 5)
|
||||
#define PINMUX_INPUT_ENABLE (1 << 6)
|
||||
#define PINMUX_LOCK (1 << 7)
|
||||
#define PINMUX_LPDR (1 << 8)
|
||||
#define PINMUX_HSM (1 << 9)
|
||||
|
||||
#define PINMUX_IO_HV (1 << 10)
|
||||
#define PINMUX_OPEN_DRAIN (1 << 11)
|
||||
#define PINMUX_SCHMT (1 << 12)
|
||||
|
||||
#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
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
*
|
||||
* 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_
|
||||
|
||||
/*! PMC registers. */
|
||||
#define APBDEV_PMC_CNTRL 0x0
|
||||
#define PMC_CNTRL_MAIN_RST (1 << 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_GPIO_IO_EN (1 << 21)
|
||||
#define PMC_NO_IOPOWER_AUDIO_HV (1 << 18)
|
||||
#define PMC_NO_IOPOWER_SDMMC1_IO_EN (1 << 12)
|
||||
#define APBDEV_PMC_SCRATCH0 0x50
|
||||
#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
|
||||
#define PMC_SCRATCH0_MODE_FASTBOOT (1 << 30)
|
||||
#define PMC_SCRATCH0_MODE_PAYLOAD (1 << 29)
|
||||
#define PMC_SCRATCH0_MODE_RCM (1 << 1)
|
||||
#define PMC_SCRATCH0_MODE_WARMBOOT (1 << 0)
|
||||
#define APBDEV_PMC_SCRATCH1 0x54
|
||||
#define APBDEV_PMC_SCRATCH20 0xA0
|
||||
#define APBDEV_PMC_PWR_DET_VAL 0xE4
|
||||
#define PMC_PWR_DET_GPIO_IO_EN (1 << 21)
|
||||
#define PMC_PWR_DET_AUDIO_HV (1 << 18)
|
||||
#define PMC_PWR_DET_SDMMC1_IO_EN (1 << 12)
|
||||
#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_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 (1 << 2)
|
||||
#define APBDEV_PMC_RST_STATUS 0x1B4
|
||||
#define APBDEV_PMC_IO_DPD_REQ 0x1B8
|
||||
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
|
||||
#define APBDEV_PMC_VDDP_SEL 0x1CC
|
||||
#define APBDEV_PMC_DDR_CFG 0x1D0
|
||||
#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_SCRATCH188 0x810
|
||||
#define APBDEV_PMC_SCRATCH190 0x818
|
||||
#define APBDEV_PMC_SCRATCH200 0x840
|
||||
|
||||
#endif
|
||||
@@ -1,564 +0,0 @@
|
||||
/*
|
||||
* 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_ */
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* 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 "smmu.h"
|
||||
#include "../soc/cluster.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../mem/mc_t210.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 += 0x1000 * num;
|
||||
memset(res, 0, 0x1000 * 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;
|
||||
|
||||
cluster_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 += 0x1000;
|
||||
page += 0x1000;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user