diff --git a/.gitignore b/.gitignore
index 30e95f0..de2d046 100755
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,9 @@
.vscode
build/*
output/*
+loader/payload_00.h
+loader/payload_01.h
+tools/bin2c/bin2c
+tools/bin2c/bin2c.exe
+tools/lz/lz77
+tools/lz/lz77.exe
diff --git a/Makefile b/Makefile
index b860e7a..be95d5c 100755
--- a/Makefile
+++ b/Makefile
@@ -16,21 +16,26 @@ TARGET := hekate
BUILDDIR := build
OUTPUTDIR := output
SOURCEDIR = bootloader
-VPATH = $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
+BDKDIR := bdk
+BDKINC := -I./$(BDKDIR)
+VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
+VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
# Main and graphics.
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
- start.o \
+ start.o exception_handlers.o \
main.o heap.o \
- gfx.o tui.o \
- fe_emmc_tools.o fe_info.o fe_tools.o \
+ gfx.o logos.o tui.o \
+ l4t.o fe_info.o fe_tools.o \
)
# Hardware.
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
- bpmp.o clock.o cluster.o di.o gpio.o i2c.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 \
+ bpmp.o ccplex.o clock.o di.o i2c.o irq.o timer.o \
+ mc.o sdram.o minerva.o \
+ gpio.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
+ fuse.o kfuse.o \
+ sdmmc.o sdmmc_driver.o emmc.o sd.o emummc.o \
bq24193.o max17050.o max7762x.o max77620-rtc.o \
hw_init.o \
)
@@ -43,67 +48,113 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
# 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 \
+ hos.o hos_config.o pkg1.o pkg2.o pkg3.o pkg2_ini_kippatch.o secmon_exo.o \
)
# Libraries.
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
- lz.o blz.o \
+ lz.o lz4.o blz.o \
diskio.o ff.o ffunicode.o ffsystem.o \
elfload.o elfreloc_arm.o \
)
+GFX_INC := '"../$(SOURCEDIR)/gfx/gfx.h"'
+FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
+
################################################################################
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
+CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_VER_RL=$(BLVERSION_REL)
+CUSTOMDEFINES += -DNYX_VER_MJ=$(NYXVERSION_MAJOR) -DNYX_VER_MN=$(NYXVERSION_MINOR) -DNYX_VER_HF=$(NYXVERSION_HOTFX) -DNYX_VER_RL=$(NYXVERSION_REL)
-# 0: UART_A, 1: UART_B.
-#CUSTOMDEFINES += -DDEBUG_UART_PORT=0
+# BDK defines.
+CUSTOMDEFINES += -DBDK_MALLOC_NO_DEFRAG -DBDK_MC_ENABLE_AHB_REDIRECT -DBDK_EMUMMC_ENABLE
+CUSTOMDEFINES += -DBDK_WATCHDOG_FIQ_ENABLE -DBDK_RESTART_BL_ON_WDT
+CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
#CUSTOMDEFINES += -DDEBUG
-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)
+# UART Logging: Max baudrate 12.5M.
+# DEBUG_UART_PORT - 0: UART_A, 1: UART_B, 2: UART_C.
+#CUSTOMDEFINES += -DDEBUG_UART_BAUDRATE=115200 -DDEBUG_UART_INVERT=0 -DDEBUG_UART_PORT=1
+
+#TODO: Considering reinstating some of these when pointer warnings have been fixed.
+WARNINGS := -Wall -Wsign-compare -Wtype-limits -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
+#-fno-delete-null-pointer-checks
+#-Wstack-usage=byte-size -fstack-usage
+
+ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork $(WARNINGS)
+CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
MODULEDIRS := $(wildcard modules/*)
NYXDIR := $(wildcard nyx)
+LDRDIR := $(wildcard loader)
+TOOLSLZ := $(wildcard tools/lz)
+TOOLSB2C := $(wildcard tools/bin2c)
+TOOLS := $(TOOLSLZ) $(TOOLSB2C)
################################################################################
-.PHONY: all clean $(MODULEDIRS) $(NYXDIR)
+.PHONY: all clean $(MODULEDIRS) $(NYXDIR) $(LDRDIR) $(TOOLS)
-all: $(TARGET).bin
- @echo -n "Payload size is "
- @wc -c < $(OUTPUTDIR)/$(TARGET).bin
- @echo "Max size is 126296 Bytes."
+all: $(TARGET).bin $(LDRDIR)
+ @printf ICTC49 >> $(OUTPUTDIR)/$(TARGET).bin
+ @echo "--------------------------------------"
+ @echo "$(TARGET) size:"
+ @echo -n "Uncompr: "
+ $(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET)_unc.bin))
+ @echo $(BIN_SIZE)" Bytes"
+ @if [ ${BIN_SIZE} -gt 140288 ]; then echo "\e[1;33mUncompr size exceeds limit!\e[0m"; fi
+ @echo -n "Payload: "
+ $(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
+ @echo $(BIN_SIZE)" Bytes"
+ @if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
+ @echo "--------------------------------------"
-clean:
+clean: $(TOOLS)
@rm -rf $(OBJS)
@rm -rf $(BUILDDIR)
@rm -rf $(OUTPUTDIR)
$(MODULEDIRS):
- $(MAKE) -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
+ @$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
$(NYXDIR):
- $(MAKE) -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
+ @$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
-$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR)
- $(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
- @printf ICTC49 >> $(OUTPUTDIR)/$@
+$(LDRDIR): $(TARGET).bin
+ @$(TOOLSLZ)/lz77 $(OUTPUTDIR)/$(TARGET).bin
+ @mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(TARGET)_unc.bin
+ @mv $(OUTPUTDIR)/$(TARGET).bin.00.lz payload_00
+ @mv $(OUTPUTDIR)/$(TARGET).bin.01.lz payload_01
+ @$(TOOLSB2C)/bin2c payload_00 > $(LDRDIR)/payload_00.h
+ @$(TOOLSB2C)/bin2c payload_01 > $(LDRDIR)/payload_01.h
+ @rm payload_00
+ @rm payload_01
+ @$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS) PAYLOAD_NAME=$(TARGET)
+
+$(TOOLS):
+ @$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
+
+$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR) $(TOOLS)
+ @$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
- $(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
+ @$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
+ @printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
$(BUILDDIR)/$(TARGET)/%.o: %.c
- $(CC) $(CFLAGS) -c $< -o $@
+ @echo Building $@
+ @$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
$(BUILDDIR)/$(TARGET)/%.o: %.S
+ @echo Building $@
+ @$(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJS): $(BUILDDIR)/$(TARGET)
+
+$(BUILDDIR)/$(TARGET):
@mkdir -p "$(BUILDDIR)"
@mkdir -p "$(BUILDDIR)/$(TARGET)"
@mkdir -p "$(OUTPUTDIR)"
- $(CC) $(CFLAGS) -c $< -o $@
diff --git a/README.md b/README.md
index 4627cf6..6101ca1 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,38 @@
-# hekate - CTCaer mod
+# hekate - Nyx

-Custom Nintendo Switch bootloader, firmware patcher, and more.
+Custom Graphical Nintendo Switch bootloader, firmware patcher, tools, and many more.
+
+
+
+- [Features](#features)
+- [Bootloader folders and files](#bootloader-folders-and-files)
+- [Bootloader configuration](#bootloader-configuration)
+ * [hekate global Configuration keys/values](#hekate-global-configuration-keysvalues-when-entry-is-config)
+ * [Boot entry key/value combinations](#boot-entry-keyvalue-combinations)
+ * [Boot entry key/value combinations for Exosphère](#boot-entry-keyvalue-combinations-for-exosphère)
+ * [Payload storage](#payload-storage)
+ * [Nyx Configuration keys/values](#nyx-configuration-keysvalues-nyxini)
+
+
+
+## Features
+
+- **Fully Configurable and Graphical** with Touchscreen and Joycon input support
+- **Launcher Style, Background and Color Themes**
+- **HOS (Switch OS) Bootloader** -- For CFW Sys/Emu, OFW Sys and Stock Sys
+- **Android & Linux Bootloader**
+- **Payload Launcher**
+- **eMMC/emuMMC Backup/Restore Tools**
+- **SD Card Partition Manager** -- Prepares and formats SD Card for any combo of HOS (Sys/emuMMC), Android and Linux
+- **emuMMC Creation & Manager** -- Can also migrate and fix existing emuMMC
+- **Switch Android & Linux flasher**
+- **USB Mass Storage (UMS) for SD/eMMC/emuMMC** -- Converts Switch into a SD Card Reader
+- **USB Gamepad** -- Converts Switch with Joycon into a USB HID Gamepad
+- **Hardware and Peripherals info** (SoC, Fuses, RAM, Display, Touch, eMMC, SD, Battery, PSU, Charger)
+- **Many other tools** like Archive Bit Fixer, Touch Calibration, SD/eMMC Benchmark, AutoRCM enabler and more
## Bootloader folders and files
@@ -11,28 +40,28 @@ Custom Nintendo Switch bootloader, firmware patcher, and more.
| 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. |
+| \|__ bootlogo.bmp | It is used if no `logopath` key is found. User provided. Can be skipped. |
+| \|__ hekate_ipl.ini | Main bootloader configuration and boot entries in `Launch` menu. |
+| \|__ nyx.ini | Nyx GUI configuration |
| \|__ 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. |
+| \|__ update.bin | If newer, it is loaded at boot. Normally for modchips. Auto updated and created at first boot. |
+| bootloader/ini/ | For individual inis. `More configs` menu. Autoboot is supported. |
| bootloader/res/ | Nyx user resources. Icons and more. |
-| \|__ background.bmp | Nyx - custom background. |
+| \|__ background.bmp | Nyx - Custom background. User provided. |
| \|__ 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/sys/ | hekate and Nyx system modules folder. !Important! |
+| \|__ emummc.kipm | emuMMC KIP1 module. |
+| \|__ libsys_lp0.bso | LP0 (sleep mode) module. |
+| \|__ libsys_minerva.bso | Minerva Training Cell. Used for DRAM Frequency training. |
+| \|__ nyx.bin | Nyx - hekate's GUI. |
+| \|__ res.pak | Nyx resources package. |
+| \|__ thk.bin | Atmosphère Tsec Hovi Keygen. |
+| \|__ /l4t/ | Folder with firmware relevant to L4T (Linux/Android). |
| 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. |
+| bootloader/payloads/ | For the `Payloads` menu. All CFW bootloaders, tools, Linux payloads are supported. Autoboot only supported by including them into an ini. |
+| bootloader/libtools/ | Reserved |
-**Note**: Sept files for booting 7.0.0 and up are expected at /sept folder at root of sd card.
## Bootloader configuration
@@ -43,85 +72,146 @@ The bootloader can be configured via 'bootloader/hekate_ipl.ini' (if it is prese
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)
+**You can find a template [Here](./res/hekate_ipl_template.ini)**
-### Global Configuration keys/values when boot entry is **config**:
+### hekate Global Configuration keys/values (when entry is *[config]*):
-| Config option | Description |
-| ------------------ | ---------------------------------------------------------- |
-| autoboot=0 | 0: Disable, #: Boot entry number to auto boot. |
+| 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. |
-| verification=2 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and not 100% reliable), 2: Full (sha256 based, slow and 100% reliable). |
+| bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. Max: 20s. |
+| noticker=0 | 0: Animated line is drawn during custom bootlogo, signifying time left to skip to menu. 1: Disable. |
| 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. |
+| bootprotect=0 | 0: Disable, 1: Protect bootloader folder from being corrupted by disallowing reading or editing in HOS. |
| updater2p=0 | 0: Disable, 1: Force updates (if needed) the reboot2payload binary to be hekate. |
-| backlight=100 | Screen backlight level. 0-255. |
+| backlight=100 | Screen backlight level. 0-255. |
-### Possible boot entry key/value combinations:
+### 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. |
-| 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) |
+| warmboot={FILE path} | Replaces the warmboot binary |
+| secmon={FILE path} | Replaces the security monitor binary |
+| kernel={FILE path} | Replaces the kernel binary |
+| kip1={FILE path} | Replaces/Adds kernel initial process. Multiple can be set. |
+| kip1={FOLDER path}/* | Loads every .kip/.kip1 inside a folder. Compatible with single kip1 keys. |
+| pkg3={FILE path} | Takes an Atmosphere `package3` binary and `extracts` all needed parts from it. kips, exosphere, warmboot and mesophere. |
+| fss0={FILE path} | Same as above. !Deprecated! |
+| pkg3ex=1 | Enables loading of experimental content from a PKG3/FSS0 storage |
+| pkg3kip1skip={KIP name} | Skips loading a kip from `pkg3`/`fss0`. Allows multiple and `,` as separator. The name must exactly match the name in `PKG3`. |
+| exofatal={FILE path} | Replaces the exosphere fatal binary for Mariko |
+| ---------------------- | ---------------------------------------------------------- |
+| kip1patch=patchname | Enables a kip1 patch. Allows multiple and `,` as separator. If actual patch is not found, a warning will show up. |
+| emupath={FOLDER path} | 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 | OFW via hekate bootloader. Disables unneeded kernel patching and CFW kips when running stock. `If emuMMC is enabled, emummc_force_disable=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`. |
+| fullsvcperm=1 | Disables SVC verification (full services permission). Doesn't work with Mesosphere as kernel. |
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
-| atmosphere=1 | Enables Atmosphère patching. |
-| nouserexceptions=1 | Disables usermode exception handlers when paired with Exosphère. |
-| userpmu=1 | Allows user access to PMU when paired with Exosphère. |
-| emummc_force_disable=1 | Disabled 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 to run completely stock. |
-| 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. |
+| kernelprocid=1 | Enables stock kernel process id send/recv patching. Not needed when `pkg3`/`fss0` is used. |
+| ---------------------- | ---------------------------------------------------------- |
+| payload={FILE path} | Payload launching. Tools, Android/Linux, CFW bootloaders, etc. Any key above when used with that, doesn't get into account. |
+| ---------------------- | ---------------------------------------------------------- |
+| l4t=1 | L4T Linux/Android native launching. |
+| boot_prefixes={FOLDER path} | L4T bootstack directory. |
+| ram_oc=0 | L4T RAM Overclocking. Check README_CONFIG.txt for more info. |
+| ram_oc_vdd2=1100 | L4T RAM VDD2 Voltage. Set VDD2 (T210B01) or VDD2/VDDQ (T210) voltage. 1050-1175. |
+| ram_oc_vddq=600 | L4T RAM VDDQ Voltage. Set VDDQ (T210B01). 550-650. |
+| uart_port=0 | Enables logging on serial port for L4T uboot/kernel. |
+| sld_type=0x31444C53 | Controls the type of seamless display support. 0x0: Disable, 0x31444C53: L4T seamless display. |
+| Additional keys | Each distro supports more keys. Check README_CONFIG.txt for more info. |
+| ---------------------- | ---------------------------------------------------------- |
+| bootwait=3 | Overrides global bootwait from `[config]`. |
+| id=IDNAME | Identifies boot entry for forced boot via id. Max 7 chars. |
+| logopath={FILE path} | If it exists, it will load the specified bitmap. Otherwise `bootloader/bootlogo.bmp` will be used if exists |
+| icon={FILE 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 defaults 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`.
+**Note2**: When using PKG3/FSS0 it parses exosphere, warmboot and all core kips. You can override the first 2 by using `secmon`/`warmboot` after defining `pkg3`/`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).
+**Warning**: Careful when you override *pkg3/fss core* kips with `kip1`.
+That's in case the kips are incompatible between them. If compatible, you can override `pkg3`/`fss0` kips with no issues (useful for testing with intermediate kip changes). In such cases, the `kip1` line must be **after** `pkg3`/`fss0` line.
+
+
+### Boot entry key/value combinations for Exosphère:
+
+| 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. |
+| usb3force=1 | Overrides system settings mitm config `usb30_force_enabled`. If that key doesn't exist, `system_settings.ini` will be used. |
+
+
+**Note**: `cal0blank`, `cal0writesys`, `usb3force`, as stated override the `exosphere.ini` or `system_settings.ini`. 0: Disable, 1: Enable, Key Missing: Use original value.
+
+
+**Note2**: `blank_prodinfo_{sys/emu}mmc`, `allow_writing_to_cal_sysmmc` and `usb30_force_enabled` in `exosphere.ini` and `system_settings.ini` respectively, are the only atmosphere config keys that can affect hekate booting configuration externally, **if** the equivalent keys in hekate config are missing.
### Payload storage:
-hekate has a boot storage in the binary that helps it configure it outside of BPMP enviroment:
+hekate has a boot storage in the binary that helps it configure it outside of BPMP environment:
-| Offset / Name | Description |
-| -------------------- | ----------------------------------------------------------------- |
-| '0x94' boot_cfg | bit0: Force AutoBoot, bit1: Show launch log, bit2: Boot from ID, 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' 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. |
-| '0x98' xt_str[128] | Depends on the set cfg bits. |
+| Offset / Name | Description |
+| ----------------------- | ----------------------------------------------------------------- |
+| '0x94' boot_cfg | bit0: `Force AutoBoot`, bit1: `Show launch log`, bit2: `Boot from ID`, bit3: `Boot to emuMMC`. |
+| '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 | When menu is forced: bit5: `Run UMS`. |
+| '0x98' xt_str[128] | Depends on the set cfg bits. |
+| '0x98' ums[1] | When `Run UMS` is set, it will launch the selected UMS. 0: SD, 1: eMMC BOOT0, 2: eMMC BOOT1, 3: eMMC GPP, 4: emuMMC BOOT0, 5: emuMMC BOOT1, 6: emuMMC GPP, |
+| '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.
+### Nyx Configuration keys/values (nyx.ini):
+
+| Config option | Description |
+| ------------------ | ---------------------------------------------------------- |
+| themebg=2d2d2d | Sets Nyx background color in HEX. EXPERIMENTAL. |
+| themecolor=167 | Sets Nyx color of text highlights. |
+| entries5col=0 | 1: Sets Launch entry columns from 4 to 5 per line. For a total of 10 entries. |
+| 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). |
+| ------------------ | ------- The following options can only be edited in nyx.ini ------- |
+| umsemmcrw=0 | 1: eMMC/emuMMC UMS will be mounted as writable by default. |
+| jcdisable=0 | 1: Disables Joycon driver completely. |
+| jcforceright=0 | 1: Forces right joycon to be used as main mouse control. |
+| bpmpclock=1 | 0: Auto, 1: Fastest, 2: Faster, 3: Fast. Use 2 or 3 if Nyx hangs or some functions like UMS/Backup Verification fail. |
```
-hekate (C) 2018 naehrwert, st4rk
-CTCaer mod (C) 2018 CTCaer.
+hekate (c) 2018, naehrwert, st4rk.
+ (c) 2018-2025, CTCaer.
+
+Nyx GUI (c) 2019-2025, 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-2018 Gabor Kiss-Vamosi
+ - FatFs R0.13c,
+ Copyright (c) 2006-2018, ChaN
+ Copyright (c) 2018-2022, CTCaer
+ - bcl-1.2.0,
+ Copyright (c) 2003-2006, Marcus Geelnard
+ - blz,
+ Copyright (c) 2018, SciresM
+ - elfload,
+ Copyright (c) 2014 Owen Shepherd,
+ Copyright (c) 2018 M4xw
___
.-' `'.
diff --git a/README_BOOTLOGO.md b/README_BOOTLOGO.md
index 40d81f8..0a2b2bc 100644
--- a/README_BOOTLOGO.md
+++ b/README_BOOTLOGO.md
@@ -4,13 +4,16 @@ 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.
+The process is to create a landscape bootlogo and then rotate it 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 (`logopath=`), this one will be loaded.
-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.
\ No newline at end of file
+If the above is not found or the format is not correct, it will try to load `bootloader/bootlogo.bmp`.
+If this is not found, the default hekate logo will be used.
+
+(`bootloader/bootlogo.bmp` is basically like a global bootlogo.)
diff --git a/Versions.inc b/Versions.inc
index 0d3805f..c2278c1 100644
--- a/Versions.inc
+++ b/Versions.inc
@@ -1,11 +1,11 @@
# IPL Version.
-BLVERSION_MAJOR := 5
-BLVERSION_MINOR := 1
-BLVERSION_HOTFX := 2
-BLVERSION_RSVD := 0
+BLVERSION_MAJOR := 6
+BLVERSION_MINOR := 3
+BLVERSION_HOTFX := 1
+BLVERSION_REL := 0
# Nyx Version.
-NYXVERSION_MAJOR := 0
-NYXVERSION_MINOR := 8
-NYXVERSION_HOTFX := 5
-NYXVERSION_RSVD := 0
+NYXVERSION_MAJOR := 1
+NYXVERSION_MINOR := 7
+NYXVERSION_HOTFX := 0
+NYXVERSION_REL := 0
diff --git a/bdk/bdk.h b/bdk/bdk.h
new file mode 100644
index 0000000..1d8a05e
--- /dev/null
+++ b/bdk/bdk.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2022 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 .
+ */
+
+#ifndef BDK_H
+#define BDK_H
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#endif
diff --git a/bdk/display/di.c b/bdk/display/di.c
new file mode 100644
index 0000000..3eaf922
--- /dev/null
+++ b/bdk/display/di.c
@@ -0,0 +1,1033 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2018-2025 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 .
+ */
+
+#include
+
+#include "di.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "di.inl"
+
+extern volatile nyx_storage_t *nyx_str;
+
+static u32 _display_id = 0;
+static u32 _dsi_bl = -1;
+static bool _nx_aula = false;
+
+static void _display_panel_and_hw_end(bool no_panel_deinit);
+
+void display_enable_interrupt(u32 intr)
+{
+ DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) |= intr;
+}
+
+void display_disable_interrupt(u32 intr)
+{
+ DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) &= ~intr;
+ DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = intr;
+}
+
+void display_wait_interrupt(u32 intr)
+{
+ DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = intr;
+
+ // Interrupts are masked. Poll status register for checking if fired.
+ while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & intr))
+ ;
+}
+
+static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
+{
+ u32 end = get_tmr_us() + timeout;
+ while (get_tmr_us() < end && DSI(off) & mask)
+ ;
+ usleep(5);
+}
+
+static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait)
+{
+ DSI(_DSIREG(DSI_WR_DATA)) = (param << 8) | cmd;
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+
+ if (wait)
+ usleep(wait);
+}
+
+static void _display_dsi_wait_vblank(bool enable)
+{
+ if (enable)
+ {
+ // Enable vblank interrupt.
+ display_enable_interrupt(DC_CMD_INT_FRAME_END_INT);
+
+ // Use the 4th line to transmit the host cmd packet.
+ DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE | DSI_DSI_LINE_TYPE(4);
+
+ // Wait for vblank before starting the transfer.
+ display_wait_interrupt(DC_CMD_INT_FRAME_END_INT);
+ }
+ else
+ {
+ // Wait for vblank before resetting sync points.
+ display_wait_interrupt(DC_CMD_INT_FRAME_END_INT);
+ usleep(14);
+
+ // Reset all states of syncpt block.
+ DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET;
+ usleep(300); // Stabilization delay.
+
+ // Clear syncpt block reset.
+ DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0;
+ usleep(300); // Stabilization delay.
+
+ // Restore video mode and host control.
+ DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
+
+ // Disable and clear vblank interrupt.
+ display_disable_interrupt(DC_CMD_INT_FRAME_END_INT);
+ }
+}
+
+static void _display_dsi_read_rx_fifo(u32 *data)
+{
+ u32 fifo_count = DSI(_DSIREG(DSI_STATUS)) & DSI_STATUS_RX_FIFO_SIZE;
+ if (fifo_count)
+ DSI(_DSIREG(DSI_TRIGGER)) = 0;
+
+ for (u32 i = 0; i < fifo_count; i++)
+ {
+ // Read or Drain RX FIFO.
+ if (data)
+ data[i] = DSI(_DSIREG(DSI_RD_DATA));
+ else
+ (void)DSI(_DSIREG(DSI_RD_DATA));
+ }
+}
+
+int display_dsi_read(u8 cmd, u32 len, void *data)
+{
+ int res = 0;
+ u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0};
+
+ // Drain RX FIFO.
+ _display_dsi_read_rx_fifo(NULL);
+
+ // Set reply size.
+ _display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
+ _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
+
+ // Request register read.
+ _display_dsi_send_cmd(MIPI_DSI_DCS_READ, cmd, 0);
+ _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
+
+ // Transfer bus control to device for transmitting the reply.
+ DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_IMM_BTA;
+
+ // Wait for reply to complete. DSI_HOST_CONTROL_IMM_BTA bit acts as a DSI host read busy.
+ _display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA);
+
+ // Wait a bit for the reply.
+ usleep(5000);
+
+ // Read RX FIFO.
+ _display_dsi_read_rx_fifo(fifo);
+
+ // Parse packet and copy over the data.
+ if ((fifo[0] & 0xFF) == DSI_ESCAPE_CMD)
+ {
+ // Act based on reply type.
+ switch (fifo[1] & 0xFF)
+ {
+ case GEN_LONG_RD_RES:
+ case DCS_LONG_RD_RES:
+ memcpy(data, &fifo[2], MIN((fifo[1] >> 8) & 0xFFFF, len));
+ break;
+
+ case GEN_1_BYTE_SHORT_RD_RES:
+ case DCS_1_BYTE_SHORT_RD_RES:
+ memcpy(data, &fifo[2], 1);
+ break;
+
+ case GEN_2_BYTE_SHORT_RD_RES:
+ case DCS_2_BYTE_SHORT_RD_RES:
+ memcpy(data, &fifo[2], 2);
+ break;
+
+ case ACK_ERROR_RES:
+ default:
+ res = 1;
+ break;
+ }
+ }
+ else
+ res = 1;
+
+ return res;
+}
+
+int display_dsi_vblank_read(u8 cmd, u32 len, void *data)
+{
+ int res = 0;
+ u32 host_control = 0;
+ u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0};
+
+ // Drain RX FIFO.
+ _display_dsi_read_rx_fifo(NULL);
+
+ // Save host control and enable host cmd packets during video.
+ host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
+
+ _display_dsi_wait_vblank(true);
+
+ // Set reply size.
+ _display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
+ _display_dsi_wait(0, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
+
+ // Request register read.
+ _display_dsi_send_cmd(MIPI_DSI_DCS_READ, cmd, 0);
+ _display_dsi_wait(0, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
+
+ _display_dsi_wait_vblank(false);
+
+ // Transfer bus control to device for transmitting the reply.
+ DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_IMM_BTA;
+
+ // Wait for reply to complete. DSI_HOST_CONTROL_IMM_BTA bit acts as a DSI host read busy.
+ _display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA);
+
+ // Wait a bit for the reply.
+ usleep(5000);
+
+ // Read RX FIFO.
+ _display_dsi_read_rx_fifo(fifo);
+
+ // Parse packet and copy over the data.
+ if ((fifo[0] & 0xFF) == DSI_ESCAPE_CMD)
+ {
+ // Act based on reply type.
+ switch (fifo[1] & 0xFF)
+ {
+ case GEN_LONG_RD_RES:
+ case DCS_LONG_RD_RES:
+ memcpy(data, &fifo[2], MIN((fifo[1] >> 8) & 0xFFFF, len));
+ break;
+
+ case GEN_1_BYTE_SHORT_RD_RES:
+ case DCS_1_BYTE_SHORT_RD_RES:
+ memcpy(data, &fifo[2], 1);
+ break;
+
+ case GEN_2_BYTE_SHORT_RD_RES:
+ case DCS_2_BYTE_SHORT_RD_RES:
+ memcpy(data, &fifo[2], 2);
+ break;
+
+ case ACK_ERROR_RES:
+ default:
+ res = 1;
+ break;
+ }
+ }
+ else
+ res = 1;
+
+ // Restore host control.
+ DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
+
+ return res;
+}
+
+void display_dsi_write(u8 cmd, u32 len, void *data)
+{
+ u32 host_control;
+ u32 fifo32[DSI_STATUS_TX_FIFO_SIZE] = {0};
+ u8 *fifo8 = (u8 *)fifo32;
+
+ // Prepare data for long write.
+ if (len >= 2)
+ {
+ memcpy(&fifo8[5], data, len);
+ memset(&fifo8[5] + len, 0, len % sizeof(u32));
+ len++; // Increase length by CMD.
+ }
+
+ // Save host control.
+ host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
+
+ // Enable host transfer trigger.
+ DSI(_DSIREG(DSI_HOST_CONTROL)) = (host_control & ~(DSI_HOST_CONTROL_TX_TRIG_MASK)) | DSI_HOST_CONTROL_TX_TRIG_HOST;
+
+ switch (len)
+ {
+ case 0:
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
+ break;
+
+ case 1:
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd | (*(u8 *)data << 8), 0);
+ break;
+
+ default:
+ fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
+ fifo8[4] = cmd;
+ len += sizeof(u32); // Increase length by length word and DCS CMD.
+ for (u32 i = 0; i < (ALIGN(len, sizeof(u32)) / sizeof(u32)); i++)
+ DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+ break;
+ }
+
+ // Wait for the write to happen.
+ _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST);
+
+ // Restore host control.
+ DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
+}
+
+void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
+{
+ u32 fifo32[DSI_STATUS_TX_FIFO_SIZE] = {0};
+ u8 *fifo8 = (u8 *)fifo32;
+
+ // Prepare data for long write.
+ if (len >= 2)
+ {
+ memcpy(&fifo8[5], data, len);
+ memset(&fifo8[5] + len, 0, len % sizeof(u32));
+ len++; // Increase length by CMD.
+ }
+
+ _display_dsi_wait_vblank(true);
+
+ switch (len)
+ {
+ case 0:
+ DSI(_DSIREG(DSI_WR_DATA)) = (cmd << 8) | MIPI_DSI_DCS_SHORT_WRITE;
+ break;
+
+ case 1:
+ DSI(_DSIREG(DSI_WR_DATA)) = ((cmd | (*(u8 *)data << 8)) << 8) | MIPI_DSI_DCS_SHORT_WRITE_PARAM;
+ break;
+
+ default:
+ fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
+ fifo8[4] = cmd;
+ len += sizeof(u32); // Increase length by length word and DCS CMD.
+ for (u32 i = 0; i < (ALIGN(len, sizeof(u32)) / sizeof(u32)); i++)
+ DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
+ break;
+ }
+
+ _display_dsi_wait_vblank(false);
+}
+
+void display_init()
+{
+ // Get Hardware type, as it's used in various DI functions.
+ _nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA;
+
+ // Check if display is already initialized.
+ if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1))
+ _display_panel_and_hw_end(true);
+
+ // Get Chip ID.
+ bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
+
+ // Enable DSI AVDD.
+ max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000);
+ max7762x_regulator_enable(REGULATOR_LDO0, true);
+
+ // Enable Display Interface specific clocks.
+ CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
+ CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_DISP1);
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_DISP1);
+
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_UART_FST_MIPI_CAL);
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = CLK_SRC_DIV(6); // Set PLLP_OUT3 and div 6 (68MHz).
+
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP);
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = CLK_SRC_DIV(6); // Set PLLP_OUT and div 6 (68MHz).
+
+ // Bring every IO rail out of deep power down.
+ PMC(APBDEV_PMC_IO_DPD_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
+ PMC(APBDEV_PMC_IO_DPD2_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
+
+ // Configure LCD/BL pins.
+ if (!_nx_aula)
+ {
+ // Configure LCD pins.
+ PINMUX_AUX(PINMUX_AUX_NFC_EN) = PINMUX_PULL_DOWN;
+ PINMUX_AUX(PINMUX_AUX_NFC_INT) = PINMUX_PULL_DOWN;
+
+ // Configure Backlight pins.
+ PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_PULL_DOWN;
+ PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) = PINMUX_PULL_DOWN;
+
+ // Enable LCD AVDD.
+ gpio_direction_output(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_HIGH);
+ usleep(10000); // Wait minimum 4.2ms to stabilize.
+
+ // Configure Backlight PWM/EN pins (BL PWM, BL EN).
+ gpio_direction_output(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1, GPIO_LOW);
+
+ // Enable Backlight power.
+ gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH);
+ }
+
+ // Configure LCD RST pin.
+ PINMUX_AUX(PINMUX_AUX_LCD_RST) = PINMUX_PULL_DOWN;
+ gpio_direction_output(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW);
+
+ // Power up supply regulator for display interface.
+ MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0;
+
+ if (!tegra_t210)
+ {
+ MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG0)) = 0;
+ APB_MISC(APB_MISC_GP_DSI_PAD_CONTROL) = 0;
+ }
+
+ // Set DISP1 clock source, parent clock and DSI/PCLK to low power mode.
+ // T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-PCLK): 50.0 MHz. (PCLK: 16.66 MHz)
+ // T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-PCLK): 48.9 MHz. (PCLK: 16.30 MHz)
+ clock_enable_plld(3, 20, true, tegra_t210);
+
+ // Setup Display Interface initial window configuration.
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_setup_win_config, ARRAY_SIZE(_di_dc_setup_win_config));
+
+ // Setup dsi init sequence packets.
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_reset_config0, ARRAY_SIZE(_di_dsi_seq_pkt_reset_config0));
+ DSI(_DSIREG(tegra_t210 ? DSI_INIT_SEQ_DATA_15 : DSI_INIT_SEQ_DATA_15_B01)) = 0;
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_reset_config1, ARRAY_SIZE(_di_dsi_seq_pkt_reset_config1));
+
+ // Reset pad trimmers for T210B01.
+ if (!tegra_t210)
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_init_pads_t210b01, ARRAY_SIZE(_di_dsi_init_pads_t210b01));
+
+ // Setup init seq packet lengths, timings and power on DSI.
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_init_config, ARRAY_SIZE(_di_dsi_init_config));
+ usleep(10000);
+
+ // Enable LCD Reset.
+ gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH);
+ usleep(60000);
+
+ // Setup DSI device takeover timeout.
+ DSI(_DSIREG(DSI_BTA_TIMING)) = _nx_aula ? 0x40103 : 0x50204;
+
+ // Get Display ID.
+ _display_id = 0xCCCCCC;
+ for (u32 i = 0; i < 3; i++)
+ {
+ if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id))
+ break;
+
+ usleep(10000);
+ }
+
+ // Save raw Display ID to Nyx storage.
+ nyx_str->info.disp_id = _display_id;
+
+ // Decode Display ID.
+ _display_id = ((_display_id >> 8) & 0xFF00) | (_display_id & 0xFF);
+
+ if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
+ _display_id = PANEL_JDI_XXX062M;
+
+ // For Aula ensure that we have a compatible panel id.
+ if (_nx_aula && _display_id == 0xCCCC)
+ _display_id = PANEL_SAM_AMS699VC01;
+
+ // Initialize display panel.
+ switch (_display_id)
+ {
+ case PANEL_SAM_AMS699VC01:
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
+ // Set color mode to basic (natural). Stock is Saturated (0x00). (Reset value is 0x20).
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM,
+ MIPI_DCS_PRIV_SM_SET_COLOR_MODE | (DCS_SM_COLOR_MODE_BASIC << 8), 0);
+ // Enable backlight and smooth PWM.
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM,
+ MIPI_DCS_SET_CONTROL_DISPLAY | ((DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL | DCS_CONTROL_DISPLAY_DIMMING_CTRL) << 8), 0);
+
+ // Unlock Level 2 registers.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x539; // MIPI_DSI_DCS_LONG_WRITE: 5 bytes.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x5A5A5AE2; // MIPI_DCS_PRIV_SM_SET_REGS_LOCK: Unlock Level 2 registers.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x5A;
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+
+ // Set registers offset and set PWM transition to 6 frames (100ms).
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_PRIV_SM_SET_REG_OFFSET | (7 << 8), 0);
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_PRIV_SM_SET_ELVSS | (6 << 8), 0);
+
+ // Relock Level 2 registers.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x539; // MIPI_DSI_DCS_LONG_WRITE: 5 bytes.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0xA55A5AE2; // MIPI_DCS_PRIV_SM_SET_REGS_LOCK: Lock Level 2 registers.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0xA5;
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+
+ // Set backlight to 0%.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x339; // MIPI_DSI_DCS_LONG_WRITE: 3 bytes.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x000051; // MIPI_DCS_SET_BRIGHTNESS 0000: 0%. FF07: 100%.
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+ usleep(5000);
+ _dsi_bl = 0;
+ break;
+
+ case PANEL_JDI_XXX062M:
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_init_config_jdi, ARRAY_SIZE(_di_dsi_panel_init_config_jdi));
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
+ break;
+
+ case PANEL_INL_P062CCA_AZ1:
+ case PANEL_AUO_A062TAN01:
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
+
+ // Unlock extension cmds.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+ usleep(5000);
+
+ // Set Power control.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x739; // MIPI_DSI_DCS_LONG_WRITE: 7 bytes.
+ if (_display_id == PANEL_INL_P062CCA_AZ1)
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
+ else // PANEL_AUO_A062TAN01.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x143209; // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32).
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+ usleep(5000);
+ break;
+
+ case PANEL_INL_2J055IA_27A:
+ case PANEL_AUO_A055TAN01:
+ case PANEL_SHP_LQ055T1SW10:
+ default: // Allow spare part displays to work.
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 120000);
+ break;
+ }
+
+ // Unblank display.
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
+
+ // Setup final dsi clock.
+ // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 468.0 MHz, PLLD_OUT0 (DSI): 234.0 MHz.
+ clock_enable_plld(1, 24, false, tegra_t210);
+
+ // Finalize DSI init packet sequence configuration.
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_video_non_burst_no_eot_config, ARRAY_SIZE(_di_dsi_seq_pkt_video_non_burst_no_eot_config));
+
+ // Set 1-by-1 pixel/clock and pixel clock to 234 / 3 = 78 MHz. For 60 Hz refresh rate.
+ DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3.
+
+ // Set DSI mode to HOST.
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_host_mode_config, ARRAY_SIZE(_di_dsi_host_mode_config));
+ usleep(10000);
+
+ /*
+ * Calibrate display communication pads.
+ * When switching to the 16ff pad brick, the clock lane termination control
+ * is separated from data lane termination. This change of the mipi cal
+ * brings in a bug that the DSI pad clock termination code can't be loaded
+ * in one time calibration on T210B01. Trigger calibration twice.
+ */
+ reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_pad_cal_config, ARRAY_SIZE(_di_mipi_pad_cal_config));
+ for (u32 i = 0; i < 2; i++)
+ {
+ // Set MIPI bias pad config.
+ MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0x10010;
+ MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG1)) = tegra_t210 ? 0x300 : 0;
+
+ // Set pad trimmers and set MIPI DSI cal offsets.
+ if (tegra_t210)
+ {
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210, ARRAY_SIZE(_di_dsi_pad_cal_config_t210));
+ reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_prod_config_t210, ARRAY_SIZE(_di_mipi_dsi_cal_prod_config_t210));
+ }
+ else
+ {
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210b01, ARRAY_SIZE(_di_dsi_pad_cal_config_t210b01));
+ reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_prod_config_t210b01, ARRAY_SIZE(_di_mipi_dsi_cal_prod_config_t210b01));
+ }
+
+ // Reset all unused MIPI cal offsets.
+ reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_unused_config, ARRAY_SIZE(_di_mipi_dsi_cal_unused_config));
+
+ // Set Prescale/filter and start calibration.
+ MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_CAL_CTRL)) = 0x2A000001;
+ }
+ usleep(10000);
+
+ // Enable video display controller.
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_video_enable_config, ARRAY_SIZE(_di_dc_video_enable_config));
+}
+
+void display_backlight_pwm_init()
+{
+ if (_display_id == PANEL_SAM_AMS699VC01)
+ return;
+
+ // Enable PWM clock.
+ clock_enable_pwm();
+
+ // Enable PWM and set it to 25KHz PFM. 29.5KHz is stock.
+ PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN;
+
+ PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode.
+ usleep(2);
+
+ gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
+}
+
+void display_backlight(bool enable)
+{
+ // Backlight PWM GPIO.
+ gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW);
+}
+
+static void _display_dsi_backlight_brightness(u32 duty)
+{
+ if (_dsi_bl == duty)
+ return;
+
+ // Convert duty to candela.
+ u32 candela = duty * PANEL_SM_BL_CANDELA_MAX / 255;
+
+ u16 bl_ctrl = byte_swap_16((u16)candela);
+ display_dsi_vblank_write(MIPI_DCS_SET_BRIGHTNESS, 2, &bl_ctrl);
+
+ // Wait for backlight to completely turn off. 6 frames.
+ if (!duty)
+ usleep(100000);
+
+ _dsi_bl = duty;
+}
+
+static void _display_pwm_backlight_brightness(u32 duty, u32 step_delay)
+{
+ u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF;
+ if (duty == old_value)
+ return;
+
+ if (old_value < duty)
+ {
+ for (u32 i = old_value; i < duty + 1; i++)
+ {
+ PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
+ usleep(step_delay);
+ }
+ }
+ else
+ {
+ for (u32 i = old_value; i > duty; i--)
+ {
+ PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
+ usleep(step_delay);
+ }
+ }
+ if (!duty)
+ PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
+}
+
+void display_backlight_brightness(u32 brightness, u32 step_delay)
+{
+ if (brightness > 255)
+ brightness = 255;
+
+ if (_display_id != PANEL_SAM_AMS699VC01)
+ _display_pwm_backlight_brightness(brightness, step_delay);
+ else
+ _display_dsi_backlight_brightness(brightness);
+}
+
+u32 display_get_backlight_brightness()
+{
+ if (_display_id != PANEL_SAM_AMS699VC01)
+ return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
+ else
+ return _dsi_bl;
+}
+
+static void _display_panel_and_hw_end(bool no_panel_deinit)
+{
+ if (no_panel_deinit)
+ goto skip_panel_deinit;
+
+ display_backlight_brightness(0, 1000);
+
+ // Enable host cmd packets during video.
+ DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE;
+
+ // Blank display.
+ DSI(_DSIREG(DSI_WR_DATA)) = (MIPI_DCS_SET_DISPLAY_OFF << 8) | MIPI_DSI_DCS_SHORT_WRITE;
+
+ // Wait for 5 frames (HOST1X_CH0_SYNC_SYNCPT_9).
+ // Not here. Wait for 1 frame manually.
+ usleep(20000);
+
+ // Propagate changes to all register buffers and disable host cmd packets during video.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX_ACTIVE | WRITE_MUX_ACTIVE;
+ DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
+
+ // De-initialize video controller.
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_video_disable_config, ARRAY_SIZE(_di_dc_video_disable_config));
+
+ // Set DISP1 clock source, parent clock and DSI/PCLK to low power mode.
+ // T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-PCLK): 50.0 MHz. (PCLK: 16.66 MHz)
+ // T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-PCLK): 48.9 MHz. (PCLK: 16.30 MHz)
+ clock_enable_plld(3, 20, true, hw_get_chip_id() == GP_HIDREV_MAJOR_T210);
+
+ // Set timings for lowpower clocks.
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_timing_deinit_config, ARRAY_SIZE(_di_dsi_timing_deinit_config));
+
+ if (_display_id != PANEL_SAM_AMS699VC01)
+ usleep(10000);
+
+ // De-initialize display panel.
+ switch (_display_id)
+ {
+ case PANEL_JDI_XXX062M:
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_jdi, ARRAY_SIZE(_di_dsi_panel_deinit_config_jdi));
+ break;
+
+ case PANEL_AUO_A062TAN01:
+ reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_auo, ARRAY_SIZE(_di_dsi_panel_deinit_config_auo));
+ usleep(5000);
+ break;
+
+ case PANEL_INL_2J055IA_27A:
+ case PANEL_AUO_A055TAN01:
+ case PANEL_SHP_LQ055T1SW10:
+ // Unlock extension cmds.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+ usleep(5000);
+
+ // Set Power control.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0xB39; // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
+ if (_display_id == PANEL_INL_2J055IA_27A)
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
+ else if (_display_id == PANEL_AUO_A055TAN01)
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
+ else // PANEL_SHP_LQ055T1SW10.
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x731348B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT3 / XDK, VRH gamma volt adj 51 / x40).
+ if (_display_id == PANEL_INL_2J055IA_27A || _display_id == PANEL_AUO_A055TAN01)
+ {
+ // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG).
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x71143209;
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x114D31; // (Unknown).
+ }
+ else // PANEL_SHP_LQ055T1SW10.
+ {
+ // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/48, Enter standby / PON / VCOMG).
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x71243209;
+ DSI(_DSIREG(DSI_WR_DATA)) = 0x004C31; // (Unknown).
+ }
+ DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
+ usleep(5000);
+ break;
+
+ case PANEL_INL_P062CCA_AZ1:
+ case PANEL_SAM_AMS699VC01:
+ default:
+ break;
+ }
+
+ // Blank - powerdown.
+ _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE,
+ (_display_id == PANEL_SAM_AMS699VC01) ? 120000 : 50000);
+
+skip_panel_deinit:
+ // Disable LCD power pins.
+ gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); // LCD Reset disable.
+ usleep(10000);
+
+ if (!_nx_aula) // HOS uses panel id.
+ {
+ gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD AVDD -5.4V disable.
+ gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD AVDD +5.4V disable.
+
+ // Make sure LCD PWM backlight pin is in PWM0 mode.
+ gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
+ PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_TRISTATE | PINMUX_PULL_DOWN | 1; // Set PWM0 mode.
+ }
+ usleep(10000);
+
+ // Disable Display Interface specific clocks.
+ CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
+ CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_DISP1);
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_DISP1);
+
+ // Power down pads.
+ DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) |
+ DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);
+ DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
+
+ // Disable DSI AVDD.
+ max7762x_regulator_enable(REGULATOR_LDO0, false);
+}
+
+void display_end() { _display_panel_and_hw_end(false); };
+
+u16 display_get_decoded_panel_id()
+{
+ return _display_id;
+}
+
+void display_set_decoded_panel_id(u32 id)
+{
+ // Get Hardware type, as it's used in various DI functions.
+ _nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA;
+
+ // Decode Display ID.
+ _display_id = ((id >> 8) & 0xFF00) | (id & 0xFF);
+
+ if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
+ _display_id = PANEL_JDI_XXX062M;
+
+ // For Aula ensure that we have a compatible panel id.
+ if (_nx_aula && _display_id == 0xCCCC)
+ _display_id = PANEL_SAM_AMS699VC01;
+}
+
+void display_color_screen(u32 color)
+{
+ // Disable all windows.
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_win_one_color, ARRAY_SIZE(_di_win_one_color));
+
+ // Configure display to show single color.
+ DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ;
+ usleep(35000); // Wait 2 frames. No need on Aula.
+
+ if (_display_id != PANEL_SAM_AMS699VC01)
+ display_backlight(true);
+ else
+ display_backlight_brightness(150, 0);
+}
+
+u32 *display_init_window_a_pitch()
+{
+ // Sanitize framebuffer area.
+ memset((u32 *)IPL_FB_ADDRESS, 0, IPL_FB_SZ);
+
+ // This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 720x1280 (line stride 720).
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch, ARRAY_SIZE(_di_winA_pitch));
+ //usleep(35000); // Wait 2 frames. No need on Aula.
+
+ return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
+}
+
+u32 *display_init_window_a_pitch_vic()
+{
+ // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280 (line stride 720).
+ if (_display_id != PANEL_SAM_AMS699VC01)
+ usleep(8000); // Wait half frame for PWM to apply.
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch_vic, ARRAY_SIZE(_di_winA_pitch_vic));
+ if (_display_id != PANEL_SAM_AMS699VC01)
+ usleep(35000); // Wait 2 frames.
+
+ return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
+}
+
+u32 *display_init_window_a_pitch_inv()
+{
+ // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280 (line stride 720).
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch_inv, ARRAY_SIZE(_di_winA_pitch_inv));
+ usleep(35000); // Wait 2 frames. No need on Aula.
+
+ return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
+}
+
+u32 *display_init_window_a_block()
+{
+ // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280.
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_block, ARRAY_SIZE(_di_winA_block));
+ usleep(35000); // Wait 2 frames. No need on Aula.
+
+ return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
+}
+
+u32 *display_init_window_d_console()
+{
+ // This configures the framebuffer @ LOG_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
+ reg_write_array((u32 *)DISPLAY_A_BASE, _di_winD_log, ARRAY_SIZE(_di_winD_log));
+
+ return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
+}
+
+void display_window_disable(u32 window)
+{
+ // Select window C.
+ DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window);
+
+ // Disable window C.
+ DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window);
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window);
+}
+
+void display_set_framebuffer(u32 window, void *fb)
+{
+ // Select window.
+ DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window);
+
+ // Set new fb address.
+ DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)) = (u32)fb;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window);
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window);
+}
+
+void display_move_framebuffer(u32 window, void *fb)
+{
+ // Select window.
+ DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window);
+
+ // Get current framebuffer address.
+ const void *fb_curr = (void *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
+ u32 win_size = DISPLAY_A(_DIREG(DC_WIN_PRESCALED_SIZE));
+ win_size = (win_size & 0x7FFF) * ((win_size >> 16) & 0x1FFF);
+
+ // Copy fb over.
+ memcpy(fb, fb_curr, win_size);
+
+ // Set new fb address.
+ DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)) = (u32)fb;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window);
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window);
+}
+
+void display_window_d_console_enable()
+{
+ // Only update active registers on vsync.
+ DISPLAY_A(_DIREG(DC_CMD_REG_ACT_CONTROL)) = DISPLAY_A(_DIREG(DC_CMD_REG_ACT_CONTROL)) & ~WIN_D_ACT_HCNTR_SEL;
+
+ // Select window D.
+ DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT;
+
+ // Enable and setup window D.
+ DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = WIN_ENABLE;
+ DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0xFF80; // X: -128.
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
+
+ // Pull-down effect.
+ for (u32 i = 0xFF80; i < 0x10000; i++)
+ {
+ // Set window position.
+ DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
+ usleep(1000);
+ }
+
+ DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
+}
+
+void display_window_d_console_disable()
+{
+ // Select window D.
+ DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT;
+
+ // Pull-up effect.
+ for (u32 i = 0xFFFF; i > 0xFF7F; i--)
+ {
+ // Set window position.
+ DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
+ usleep(500);
+ }
+
+ // Disable window D.
+ DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
+ DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
+}
+
+void display_cursor_init(void *crs_fb, u32 size)
+{
+ // Setup cursor.
+ DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10);
+ DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = CURSOR_BLEND_R8G8B8A8 |
+ CURSOR_BLEND_DST_FACTOR(CURSOR_BLEND_K1) |
+ CURSOR_BLEND_SRC_FACTOR(CURSOR_BLEND_K1) | 0xFF;
+
+ // Enable cursor window.
+ DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) |= CURSOR_ENABLE;
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
+}
+
+void display_cursor_set_pos(u32 x, u32 y)
+{
+ // Set cursor position.
+ DISPLAY_A(_DIREG(DC_DISP_CURSOR_POSITION)) = x | (y << 16);
+
+ // Arm and activate changes.
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
+}
+
+void display_cursor_deinit()
+{
+ DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = 0;
+ DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) &= ~CURSOR_ENABLE;
+
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
+ DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
+}
diff --git a/bdk/display/di.h b/bdk/display/di.h
new file mode 100644
index 0000000..9a35d4f
--- /dev/null
+++ b/bdk/display/di.h
@@ -0,0 +1,907 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2018-2025 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 .
+ */
+
+#ifndef _DI_H_
+#define _DI_H_
+
+#include
+#include
+
+#define DSI_VIDEO_DISABLED 0
+#define DSI_VIDEO_ENABLED 1
+
+#define WINDOW_A 0
+#define WINDOW_B 1
+#define WINDOW_C 2
+#define WINDOW_D 3
+
+/*! 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 SYNCPT_GENERAL_INDX(x) (((x) & 0xFF) << 0)
+#define SYNCPT_GENERAL_COND(x) (((x) & 0xFF) << 8)
+#define COND_REG_WR_SAFE 3
+
+#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
+#define SYNCPT_CNTRL_SOFT_RESET BIT(0)
+#define SYNCPT_CNTRL_NO_STALL BIT(8)
+
+#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
+#define SYNCPT_VSYNC_INDX(x) (((x) & 0xFF) << 0)
+#define SYNCPT_VSYNC_ENABLE BIT(8)
+
+#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
+
+#define DC_CMD_DISPLAY_COMMAND 0x32
+#define DISP_CTRL_MODE_STOP (0 << 5)
+#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
+#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
+#define DISP_CTRL_MODE_MASK (3 << 5)
+
+#define DC_CMD_DISPLAY_POWER_CONTROL 0x36
+#define PW0_ENABLE BIT(0)
+#define PW1_ENABLE BIT(2)
+#define PW2_ENABLE BIT(4)
+#define PW3_ENABLE BIT(6)
+#define PW4_ENABLE BIT(8)
+#define PM0_ENABLE BIT(16)
+#define PM1_ENABLE BIT(18)
+
+#define DC_CMD_INT_STATUS 0x37
+#define DC_CMD_INT_MASK 0x38
+#define DC_CMD_INT_ENABLE 0x39
+#define DC_CMD_INT_FRAME_END_INT BIT(1)
+#define DC_CMD_INT_V_BLANK_INT BIT(2)
+#define DC_CMD_INT_POLARITY 0x3B
+
+#define DC_CMD_STATE_ACCESS 0x40
+#define READ_MUX_ASSEMBLY 0x0
+#define WRITE_MUX_ASSEMBLY 0x0
+#define READ_MUX_ACTIVE BIT(0)
+#define WRITE_MUX_ACTIVE BIT(2)
+
+#define DC_CMD_STATE_CONTROL 0x41
+#define GENERAL_ACT_REQ BIT(0)
+#define WIN_ACT_REQ 1
+#define WIN_A_ACT_REQ BIT(1)
+#define WIN_B_ACT_REQ BIT(2)
+#define WIN_C_ACT_REQ BIT(3)
+#define WIN_D_ACT_REQ BIT(4)
+#define CURSOR_ACT_REQ BIT(7)
+#define GENERAL_UPDATE BIT(8)
+#define WIN_UPDATE 9
+#define WIN_A_UPDATE BIT(9)
+#define WIN_B_UPDATE BIT(10)
+#define WIN_C_UPDATE BIT(11)
+#define WIN_D_UPDATE BIT(12)
+#define CURSOR_UPDATE BIT(15)
+#define NC_HOST_TRIG BIT(24)
+
+#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
+#define WINDOW_SELECT 4
+#define WINDOW_A_SELECT BIT(4)
+#define WINDOW_B_SELECT BIT(5)
+#define WINDOW_C_SELECT BIT(6)
+#define WINDOW_D_SELECT BIT(7)
+
+#define DC_CMD_REG_ACT_CONTROL 0x43
+#define GENERAL_ACT_HCNTR_SEL BIT(0)
+#define WIN_A_ACT_HCNTR_SEL BIT(2)
+#define WIN_B_ACT_HCNTR_SEL BIT(4)
+#define WIN_C_ACT_HCNTR_SEL BIT(6)
+#define CURSOR_ACT_HCNTR_SEL BIT(7)
+#define WIN_D_ACT_HCNTR_SEL BIT(10)
+
+// 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 LSC0_OUTPUT_POLARITY_LOW BIT(24)
+
+// CMU registers.
+#define DC_COM_CMU_CSC_KRR 0x32A
+#define DC_COM_CMU_CSC_KGR 0x32B
+#define DC_COM_CMU_CSC_KBR 0x32C
+#define DC_COM_CMU_CSC_KRG 0x32D
+#define DC_COM_CMU_CSC_KGG 0x32E
+#define DC_COM_CMU_CSC_KBG 0x32F
+#define DC_COM_CMU_CSC_KRB 0x330
+#define DC_COM_CMU_CSC_KGB 0x331
+#define DC_COM_CMU_CSC_KBB 0x332
+#define DC_COM_CMU_LUT1 0x336
+#define LUT1_ADDR(x) ((x) & 0xFF)
+#define LUT1_DATA(x) (((x) & 0xFFF) << 16)
+#define LUT1_READ_DATA(x) (((x) >> 16) & 0xFFF)
+#define DC_COM_CMU_LUT2 0x337
+#define LUT2_ADDR(x) ((x) & 0x3FF)
+#define LUT2_DATA(x) (((x) & 0xFF) << 16)
+#define LUT2_READ_DATA(x) (((x) >> 16) & 0xFF)
+#define DC_COM_CMU_LUT1_READ 0x338
+#define LUT1_READ_ADDR(x) (((x) & 0xFF) << 8)
+#define LUT1_READ_EN BIT(0)
+#define DC_COM_CMU_LUT2_READ 0x339
+#define LUT2_READ_ADDR(x) (((x) & 0x3FF) << 8)
+#define LUT2_READ_EN BIT(0)
+
+#define DC_COM_DSC_TOP_CTL 0x33E
+
+// DC_DISP shadowed registers.
+#define DC_DISP_DISP_WIN_OPTIONS 0x402
+#define CURSOR_ENABLE BIT(16)
+#define SOR_ENABLE BIT(25)
+#define SOR1_ENABLE BIT(26)
+#define SOR1_TIMING_CYA BIT(27)
+#define DSI_ENABLE BIT(29)
+#define HDMI_ENABLE BIT(30)
+
+
+#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
+#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
+
+#define DC_DISP_DISP_TIMING_OPTIONS 0x405
+#define VSYNC_H_POSITION(x) (((x) & 0x1FFF) << 0)
+
+#define DC_DISP_REF_TO_SYNC 0x406
+#define H_REF_TO_SYNC(x) (((x) & 0x1FFF) << 0) // Min 0 pixel clock.
+#define V_REF_TO_SYNC(x) (((x) & 0x1FFF) << 16) // Min 1 line clock.
+
+#define DC_DISP_SYNC_WIDTH 0x407
+#define H_SYNC_WIDTH(x) (((x) & 0x1FFF) << 0) // Min 1 pixel clock.
+#define V_SYNC_WIDTH(x) (((x) & 0x1FFF) << 16) // Min 1 line clock.
+
+#define DC_DISP_BACK_PORCH 0x408
+#define H_BACK_PORCH(x) (((x) & 0x1FFF) << 0)
+#define V_BACK_PORCH(x) (((x) & 0x1FFF) << 16)
+
+#define DC_DISP_ACTIVE 0x409
+#define H_DISP_ACTIVE(x) (((x) & 0x1FFF) << 0) // Min 16 pixel clock.
+#define V_DISP_ACTIVE(x) (((x) & 0x1FFF) << 16) // Min 16 line clock.
+
+#define DC_DISP_FRONT_PORCH 0x40A
+#define H_FRONT_PORCH(x) (((x) & 0x1FFF) << 0) // Min -=PS_=-H_REF_TO_SYNC + 1
+#define V_FRONT_PORCH(x) (((x) & 0x1FFF) << 16) // Min -=PS_=-V_REF_TO_SYNC + 1
+
+#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
+#define SHIFT_CLK_DIVIDER(x) ((x) & 0xFF)
+#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
+#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
+#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
+#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
+#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
+#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
+#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
+#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
+#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
+#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
+#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
+#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
+#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
+
+#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F
+#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
+#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
+#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
+#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
+#define DISP_DATA_FORMAT_DF2S (4 << 0)
+#define DISP_DATA_FORMAT_DF3S (5 << 0)
+#define DISP_DATA_FORMAT_DFSPI (6 << 0)
+#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
+#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
+#define DISP_ALIGNMENT_MSB (0 << 8)
+#define DISP_ALIGNMENT_LSB (1 << 8)
+#define DISP_ORDER_RED_BLUE (0 << 9)
+#define DISP_ORDER_BLUE_RED (1 << 9)
+
+#define DC_DISP_DISP_COLOR_CONTROL 0x430
+#define 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 DITHER_CONTROL_MASK (3 << 8)
+#define DITHER_CONTROL_DISABLE (0 << 8)
+#define DITHER_CONTROL_ORDERED (2 << 8)
+#define DITHER_CONTROL_ERRDIFF (3 << 8)
+#define DISP_COLOR_SWAP BIT(16)
+#define BLANK_COLOR_WHITE BIT(17)
+#define CMU_ENABLE BIT(20)
+
+#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
+#define SC0_H_QUALIFIER_NONE BIT(0)
+#define SC1_H_QUALIFIER_NONE BIT(16)
+
+#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
+#define DE_SELECT_ACTIVE_BLANK (0 << 0)
+#define DE_SELECT_ACTIVE (1 << 0)
+#define DE_SELECT_ACTIVE_IS (2 << 0)
+#define DE_CONTROL_ONECLK (0 << 2)
+#define DE_CONTROL_NORMAL (1 << 2)
+#define DE_CONTROL_EARLY_EXT (2 << 2)
+#define DE_CONTROL_EARLY (3 << 2)
+#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
+
+// Cursor configuration registers.
+#define DC_DISP_CURSOR_FOREGROUND 0x43C
+#define DC_DISP_CURSOR_BACKGROUND 0x43D
+#define CURSOR_COLOR(r,g,b) (((r) & 0xFF) | (((g) & 0xFF) << 8) | (((b) & 0xFF) << 16))
+
+#define DC_DISP_CURSOR_START_ADDR 0x43E
+#define DC_DISP_CURSOR_START_ADDR_NS 0x43F
+#define CURSOR_CLIPPING(w) ((w) << 28)
+#define CURSOR_CLIP_WIN_A 1
+#define CURSOR_CLIP_WIN_B 2
+#define CURSOR_CLIP_WIN_C 3
+#define CURSOR_SIZE_32 (0 << 24)
+#define CURSOR_SIZE_64 (1 << 24)
+#define CURSOR_SIZE_128 (2 << 24)
+#define CURSOR_SIZE_256 (3 << 24)
+#define DC_DISP_CURSOR_POSITION 0x440
+#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
+#define DC_DISP_CURSOR_START_ADDR_HI 0x4EC
+#define DC_DISP_CURSOR_START_ADDR_HI_NS 0x4ED
+#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_WINC_COLOR_PALETTE 0x500
+#define COLOR_PALETTE_IDX(off) (DC_WINC_COLOR_PALETTE + (off))
+#define COLOR_PALETTE_RGB(rgb) (byte_swap_32(rgb) >> 8)
+#define DC_WINC_PALETTE_COLOR_EXT 0x600
+
+#define DC_WINC_H_FILTER_P(p) (0x601 + (p))
+#define DC_WINC_V_FILTER_P(p) (0x619 + (p))
+#define DC_WINC_H_FILTER_HI_P(p) (0x629 + (p))
+
+#define DC_WINC_CSC_YOF 0x611
+#define DC_WINC_CSC_KYRGB 0x612
+#define DC_WINC_CSC_KUR 0x613
+#define DC_WINC_CSC_KVR 0x614
+#define DC_WINC_CSC_KUG 0x615
+#define DC_WINC_CSC_KVG 0x616
+#define DC_WINC_CSC_KUB 0x617
+#define DC_WINC_CSC_KVB 0x618
+#define DC_WIN_AD_WIN_OPTIONS 0xB80
+#define DC_WIN_BD_WIN_OPTIONS 0xD80
+#define DC_WIN_CD_WIN_OPTIONS 0xF80
+
+// The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER).
+#define DC_WIN_WIN_OPTIONS 0x700
+#define H_DIRECTION BIT(0)
+#define V_DIRECTION BIT(2)
+#define SCAN_COLUMN BIT(4)
+#define COLOR_EXPAND BIT(6)
+#define H_FILTER_ENABLE BIT(8)
+#define V_FILTER_ENABLE BIT(10)
+#define COLOR_PALETTE_ENABLE BIT(16)
+#define CSC_ENABLE BIT(18)
+#define DV_ENABLE BIT(20)
+#define WIN_ENABLE BIT(30)
+#define H_FILTER_EXPAND BIT(31)
+
+#define DC_WIN_BUFFER_CONTROL 0x702
+#define BUFFER_CONTROL_HOST 0
+#define BUFFER_CONTROL_VI 1
+#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 WIN_COLOR_DEPTH_X1R5G5B5 0x1E
+#define WIN_COLOR_DEPTH_R5G5B5X1 0x1F
+#define WIN_COLOR_DEPTH_X1B5G5R5 0x20
+#define WIN_COLOR_DEPTH_B5G5R5X1 0x21
+#define WIN_COLOR_DEPTH_YCbCr444P 0x29
+#define WIN_COLOR_DEPTH_YCrCb420SP 0x2A
+#define WIN_COLOR_DEPTH_YCbCr420SP 0x2B
+#define WIN_COLOR_DEPTH_YCrCb422SP 0x2C
+#define WIN_COLOR_DEPTH_YCbCr422SP 0x2D
+#define WIN_COLOR_DEPTH_YUV444P 0x34
+#define WIN_COLOR_DEPTH_YVU420SP 0x35
+#define WIN_COLOR_DEPTH_YUV420SP 0x36
+#define WIN_COLOR_DEPTH_YVU422SP 0x37
+#define WIN_COLOR_DEPTH_YUV422SP 0x38
+#define WIN_COLOR_DEPTH_YVU444SP 0x3B
+#define WIN_COLOR_DEPTH_YUV444SP 0x3C
+
+#define DC_WIN_POSITION 0x704
+#define H_POSITION(x) (((x) & 0xFFFF) << 0) // Support negative.
+#define V_POSITION(x) (((x) & 0xFFFF) << 16) // Support negative.
+
+#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 DV_CTRL_R(r) (((r) & 7) << 16)
+#define DV_CTRL_G(g) (((g) & 7) << 8)
+#define DV_CTRL_B(b) (((b) & 7) << 0)
+
+#define DC_WINBUF_BLEND_LAYER_CONTROL 0x716
+#define WIN_BLEND_DEPTH(x) (((x) & 0xFF) << 0)
+#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)
+
+#define DC_WINBUF_MEMFETCH_CONTROL 0x82B
+
+/*! Display serial interface registers. */
+#define _DSIREG(reg) ((reg) * 4)
+
+#define DSI_INCR_SYNCPT_CNTRL 0x1
+#define DSI_INCR_SYNCPT_SOFT_RESET BIT(0)
+#define DSI_INCR_SYNCPT_NO_STALL BIT(8)
+
+#define DSI_RD_DATA 0x9
+#define DSI_WR_DATA 0xA
+
+#define DSI_POWER_CONTROL 0xB
+#define DSI_POWER_CONTROL_ENABLE 1
+
+#define DSI_INT_ENABLE 0xC
+#define DSI_INT_STATUS 0xD
+#define DSI_INT_MASK 0xE
+
+#define DSI_HOST_CONTROL 0xF
+#define DSI_HOST_CONTROL_ECC BIT(0)
+#define DSI_HOST_CONTROL_CS BIT(1)
+#define DSI_HOST_CONTROL_PKT_BTA BIT(2)
+#define DSI_HOST_CONTROL_IMM_BTA BIT(3)
+#define DSI_HOST_CONTROL_FIFO_SEL BIT(4)
+#define DSI_HOST_CONTROL_HS BIT(5)
+#define DSI_HOST_CONTROL_RAW BIT(6)
+#define DSI_HOST_CONTROL_TX_TRIG_MASK (3 << 12)
+#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
+#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
+#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
+#define DSI_HOST_CONTROL_CRC_RESET BIT(20)
+#define DSI_HOST_CONTROL_FIFO_RESET BIT(21)
+
+#define DSI_CONTROL 0x10
+#define DSI_CONTROL_HOST_ENABLE BIT(0)
+#define DSI_CONTROL_VIDEO_ENABLE BIT(1)
+#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
+#define DSI_CONTROL_DCS_ENABLE BIT(3)
+#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
+#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
+#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
+#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
+#define DSI_CONTROL_HS_CLK_CTRL BIT(20)
+
+#define DSI_SOL_DELAY 0x11
+#define DSI_MAX_THRESHOLD 0x12
+
+#define DSI_TRIGGER 0x13
+#define DSI_TRIGGER_VIDEO BIT(0)
+#define DSI_TRIGGER_HOST BIT(1)
+
+#define DSI_TX_CRC 0x14
+
+#define DSI_STATUS 0x15
+#define DSI_STATUS_RX_FIFO_SIZE 0x1F
+#define DSI_STATUS_TX_FIFO_SIZE 0x20 // Actual depth is 64.
+
+#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 PKT0_LEN(x) (((x) & 0xFFFF) << 0)
+#define PKT1_LEN(x) (((x) & 0xFFFF) << 16)
+
+#define DSI_PHY_TIMING_0 0x3C
+#define DSI_PHY_TIMING_1 0x3D
+#define DSI_PHY_TIMING_2 0x3E
+#define DSI_BTA_TIMING 0x3F
+
+#define DSI_TIMEOUT_0 0x44
+#define DSI_TIMEOUT_HTX(x) (((x) & 0xFFFF) << 0)
+#define DSI_TIMEOUT_LRX(x) (((x) & 0xFFFF) << 16)
+
+#define DSI_TIMEOUT_1 0x45
+#define DSI_TIMEOUT_TA(x) (((x) & 0xFFFF) << 0)
+#define DSI_TIMEOUT_PR(x) (((x) & 0xFFFF) << 16)
+
+#define DSI_TO_TALLY 0x46
+
+#define DSI_PAD_CONTROL_0 0x4B
+#define DSI_PAD_CONTROL_VS1_PDIO_CLK BIT(8)
+#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xF) << 0)
+#define DSI_PAD_CONTROL_VS1_PULLDN_CLK BIT(24)
+#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xF) << 16)
+
+#define DSI_PAD_CONTROL_CD 0x4C
+#define DSI_VIDEO_MODE_CONTROL 0x4E
+#define DSI_CMD_PKT_VID_ENABLE 1
+#define DSI_DSI_LINE_TYPE(x) ((x) << 1)
+
+#define DSI_PAD_CONTROL_1 0x4F
+#define DSI_PAD_CONTROL_2 0x50
+
+#define DSI_PAD_CONTROL_3 0x51
+#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
+#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
+#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
+#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
+
+#define DSI_PAD_CONTROL_4 0x52
+#define DSI_PAD_CONTROL_5_B01 0x53
+#define DSI_PAD_CONTROL_6_B01 0x54
+#define DSI_PAD_CONTROL_7_B01 0x55
+#define DSI_INIT_SEQ_DATA_15 0x5F
+#define DSI_INIT_SEQ_DATA_15_B01 0x62
+
+/*! DSI packet defines */
+#define DSI_ESCAPE_CMD 0x87
+#define DSI_ACK_NO_ERR 0x84
+
+#define ACK_ERROR_RES 0x02
+#define GEN_LONG_RD_RES 0x1A
+#define DCS_LONG_RD_RES 0x1C
+#define GEN_1_BYTE_SHORT_RD_RES 0x11
+#define DCS_1_BYTE_SHORT_RD_RES 0x21
+#define GEN_2_BYTE_SHORT_RD_RES 0x12
+#define DCS_2_BYTE_SHORT_RD_RES 0x22
+
+/*! MIPI registers. */
+#define MIPI_CAL_MIPI_CAL_CTRL (0x00 / 0x4)
+#define MIPI_CAL_CIL_MIPI_CAL_STATUS (0x08 / 0x4)
+#define MIPI_CAL_CILA_MIPI_CAL_CONFIG (0x14 / 0x4)
+#define MIPI_CAL_CILB_MIPI_CAL_CONFIG (0x18 / 0x4)
+#define MIPI_CAL_CILC_MIPI_CAL_CONFIG (0x1C / 0x4)
+#define MIPI_CAL_CILD_MIPI_CAL_CONFIG (0x20 / 0x4)
+#define MIPI_CAL_CILE_MIPI_CAL_CONFIG (0x24 / 0x4)
+#define MIPI_CAL_CILF_MIPI_CAL_CONFIG (0x28 / 0x4)
+#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG (0x38 / 0x4)
+#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG (0x3C / 0x4)
+#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG (0x40 / 0x4)
+#define MIPI_CAL_DSID_MIPI_CAL_CONFIG (0x44 / 0x4)
+#define MIPI_CAL_MIPI_BIAS_PAD_CFG0 (0x58 / 0x4)
+#define MIPI_CAL_MIPI_BIAS_PAD_CFG1 (0x5C / 0x4)
+#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 (0x60 / 0x4)
+#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2 (0x64 / 0x4)
+#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2 (0x68 / 0x4)
+#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2 (0x70 / 0x4)
+#define MIPI_CAL_DSID_MIPI_CAL_CONFIG_2 (0x74 / 0x4)
+
+/*! MIPI CMDs. */
+#define MIPI_DSI_V_SYNC_START 0x01
+#define MIPI_DSI_COLOR_MODE_OFF 0x02
+#define MIPI_DSI_END_OF_TRANSMISSION 0x08
+#define MIPI_DSI_NULL_PACKET 0x09
+#define MIPI_DSI_V_SYNC_END 0x11
+#define MIPI_DSI_COLOR_MODE_ON 0x12
+#define MIPI_DSI_BLANKING_PACKET 0x19
+#define MIPI_DSI_H_SYNC_START 0x21
+#define MIPI_DSI_SHUTDOWN_PERIPHERAL 0x22
+#define MIPI_DSI_H_SYNC_END 0x31
+#define MIPI_DSI_TURN_ON_PERIPHERAL 0x32
+#define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37
+
+#define MIPI_DSI_DCS_SHORT_WRITE 0x05
+#define MIPI_DSI_DCS_READ 0x06
+#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15
+#define MIPI_DSI_DCS_LONG_WRITE 0x39
+
+#define MIPI_DSI_GENERIC_LONG_WRITE 0x29
+#define MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM 0x03
+#define MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM 0x13
+#define MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM 0x23
+#define MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM 0x04
+#define MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM 0x14
+#define MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM 0x24
+
+/*! MIPI DCS CMDs. */
+#define MIPI_DCS_NOP 0x00
+#define MIPI_DCS_SOFT_RESET 0x01
+#define MIPI_DCS_GET_COMPRESSION_MODE 0x03
+#define MIPI_DCS_GET_DISPLAY_ID 0x04
+#define MIPI_DCS_GET_DISPLAY_ID1 0xDA // GET_DISPLAY_ID Byte0, Module Manufacturer ID.
+#define MIPI_DCS_GET_DISPLAY_ID2 0xDB // GET_DISPLAY_ID Byte1, Module/Driver Version ID.
+#define MIPI_DCS_GET_DISPLAY_ID3 0xDC // GET_DISPLAY_ID Byte2, Module/Driver ID.
+#define MIPI_DCS_GET_NUM_ERRORS 0x05 // 1 byte.
+#define MIPI_DCS_GET_RED_CHANNEL 0x06
+#define MIPI_DCS_GET_GREEN_CHANNEL 0x07
+#define MIPI_DCS_GET_BLUE_CHANNEL 0x08
+#define MIPI_DCS_GET_DISPLAY_STATUS 0x09 // 4 bytes.
+#define MIPI_DCS_GET_POWER_MODE 0x0A // 1 byte. 2: DISON, 3: NORON, 4: SLPOUT, 7: BSTON.
+#define MIPI_DCS_GET_ADDRESS_MODE 0x0B // Display Access Control. 1 byte. 0: GS, 1: SS, 3: BGR.
+#define MIPI_DCS_GET_PIXEL_FORMAT 0x0C // 1 byte. 4-6: DPI.
+#define MIPI_DCS_GET_DISPLAY_MODE 0x0D // 1 byte. 0-2: GCS, 3: ALLPOFF, 4: ALLPON, 5: INVON.
+#define MIPI_DCS_GET_SIGNAL_MODE 0x0E // 1 byte. 0: EODSI, 2: DEON, 3: PCLKON, 4: VSON, 5: HSON, 7: TEON.
+#define MIPI_DCS_GET_DIAGNOSTIC_RESULT 0x0F // 1 byte. 6: FUNDT, 7: REGLD.
+#define MIPI_DCS_ENTER_SLEEP_MODE 0x10
+#define MIPI_DCS_EXIT_SLEEP_MODE 0x11
+#define MIPI_DCS_ENTER_PARTIAL_MODE 0x12
+#define MIPI_DCS_ENTER_NORMAL_MODE 0x13
+#define MIPI_DCS_EXIT_INVERT_MODE 0x20
+#define MIPI_DCS_ENTER_INVERT_MODE 0x21
+#define MIPI_DCS_ALL_PIXELS_OFF 0x22
+#define MIPI_DCS_ALL_PIXELS_ON 0x23
+#define MIPI_DCS_SET_CONTRAST 0x25 // VCON in 40mV steps. 7-bit integer.
+#define MIPI_DCS_SET_GAMMA_CURVE 0x26 // 1 byte. 0-7: GC.
+#define MIPI_DCS_SET_DISPLAY_OFF 0x28
+#define MIPI_DCS_SET_DISPLAY_ON 0x29
+#define MIPI_DCS_SET_COLUMN_ADDRESS 0x2A
+#define MIPI_DCS_SET_PAGE_ADDRESS 0x2B
+#define MIPI_DCS_WRITE_MEMORY_START 0x2C
+#define MIPI_DCS_WRITE_LUT 0x2D // 24-bit: 192 bytes.
+#define MIPI_DCS_READ_MEMORY_START 0x2E
+#define MIPI_DCS_SET_PARTIAL_ROWS 0x30
+#define MIPI_DCS_SET_PARTIAL_COLUMNS 0x31
+#define MIPI_DCS_SET_SCROLL_AREA 0x33
+#define MIPI_DCS_SET_TEAR_OFF 0x34
+#define MIPI_DCS_SET_TEAR_ON 0x35
+#define MIPI_DCS_SET_ADDRESS_MODE 0x36 // Display Access Control. 1 byte. 0: GS, 1: SS, 3: BGR.
+#define MIPI_DCS_SET_SCROLL_START 0x37
+#define MIPI_DCS_EXIT_IDLE_MODE 0x38
+#define MIPI_DCS_ENTER_IDLE_MODE 0x39
+#define MIPI_DCS_SET_PIXEL_FORMAT 0x3A // 1 byte. 4-6: DPI.
+#define MIPI_DCS_WRITE_MEMORY_CONTINUE 0x3C
+#define MIPI_DCS_READ_MEMORY_CONTINUE 0x3E
+#define MIPI_DCS_GET_3D_CONTROL 0x3F
+#define MIPI_DCS_SET_VSYNC_TIMING 0x40
+#define MIPI_DCS_SET_TEAR_SCANLINE 0x44
+#define MIPI_DCS_GET_SCANLINE 0x45
+#define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46
+#define MIPI_DCS_GET_SCANLINE_WIDTH 0x47
+#define MIPI_DSI_AREA_COLOR_MODE 0x4C
+#define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. 1 byte. 0-7: DBV.
+#define MIPI_DCS_GET_BRIGHTNESS 0x52 // 1 byte. 0-7: DBV.
+#define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
+#define MIPI_DCS_GET_CONTROL_DISPLAY 0x54 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
+#define MIPI_DCS_SET_CABC_VALUE 0x55 // 1 byte. 0-32: C, 4-7: C.
+#define MIPI_DCS_GET_CABC_VALUE 0x56 // 1 byte. 0-32: C, 4-7: C.
+#define MIPI_DCS_SET_CABC_MIN_BRI 0x5E // 1 byte. 0-7: CMB.
+#define MIPI_DCS_GET_CABC_MIN_BRI 0x5F // 1 byte. 0-7: CMB.
+#define MIPI_DCS_GET_AUTO_BRI_DIAG_RES 0x68 // 1 byte. 6-7: D.
+#define MIPI_DCS_READ_DDB_START 0xA1
+#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
+
+/*! MIPI DCS Panel Private CMDs. */
+#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0 // 43 bytes.
+#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0
+#define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 // OLED backlight tuning. Byte7: PWM transition time in frames.
+#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
+#define MIPI_DCS_PRIV_SET_EXTC 0xB9 // Enable extended commands.
+#define MIPI_DCS_PRIV_UNK_BD 0xBD
+#define MIPI_DCS_PRIV_UNK_D5 0xD5
+#define MIPI_DCS_PRIV_UNK_D6 0xD6
+#define MIPI_DCS_PRIV_UNK_D8 0xD8
+#define MIPI_DCS_PRIV_UNK_D9 0xD9
+#define MIPI_DCS_PRIV_SM_DISPLAY_ID 0xDD
+ // LVL1 LVL2 LVL3 UNK0 UNK1
+#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK 0xE2 // Samsung: Lock (default): 5A5A A5A5 A5A5 A500 A500. Unlock: A5A5 5A5A 5A5A UNK UNK.
+#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
+#define MIPI_DCS_PRIV_SET_EXTC_CMD_REG 0xFF // EXTC Command Set enable register. 5 bytes. Pass: FF 98 06 04, PAGE.
+
+/*! MIPI DCS Panel Private CMDs PAGE 1. */
+#define MIPI_DCS_PRIV_GET_DISPLAY_ID4 0x00
+#define MIPI_DCS_PRIV_GET_DISPLAY_ID5 0x01
+#define MIPI_DCS_PRIV_GET_DISPLAY_ID6 0x02
+
+/*! MIPI DCS CMD Defines. */
+#define DCS_POWER_MODE_DISPLAY_ON BIT(2)
+#define DCS_POWER_MODE_NORMAL_MODE BIT(3)
+#define DCS_POWER_MODE_SLEEP_MODE BIT(4)
+#define DCS_POWER_MODE_PARTIAL_MODE BIT(5)
+#define DCS_POWER_MODE_IDLE_MODE BIT(6)
+
+#define DCS_ADDRESS_MODE_V_FLIP BIT(0)
+#define DCS_ADDRESS_MODE_H_FLIP BIT(1)
+#define DCS_ADDRESS_MODE_LATCH_RL BIT(2) // Latch Data Order.
+#define DCS_ADDRESS_MODE_BGR_COLOR BIT(3)
+#define DCS_ADDRESS_MODE_LINE_ORDER BIT(4) // Line Refresh Order.
+#define DCS_ADDRESS_MODE_SWAP_XY BIT(5) // Page/Column Addressing Reverse Order.
+#define DCS_ADDRESS_MODE_MIRROR_X BIT(6) // Column Address Order.
+#define DCS_ADDRESS_MODE_MIRROR_Y BIT(7) // Page Address Order.
+#define DCS_ADDRESS_MODE_ROTATION_MASK (0xF << 4)
+#define DCS_ADDRESS_MODE_ROTATION_90 (DCS_ADDRESS_MODE_SWAP_XY | DCS_ADDRESS_MODE_LINE_ORDER)
+#define DCS_ADDRESS_MODE_ROTATION_180 (DCS_ADDRESS_MODE_MIRROR_X | DCS_ADDRESS_MODE_LINE_ORDER)
+#define DCS_ADDRESS_MODE_ROTATION_270 (DCS_ADDRESS_MODE_SWAP_XY)
+
+#define DCS_GAMMA_CURVE_NONE 0
+#define DCS_GAMMA_CURVE_GC0_1_8 BIT(0)
+#define DCS_GAMMA_CURVE_GC1_2_5 BIT(1)
+#define DCS_GAMMA_CURVE_GC2_1_0 BIT(2)
+#define DCS_GAMMA_CURVE_GC3_1_0 BIT(3) // Are there more?
+
+#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT BIT(2)
+#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2)
+#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) // Transition fading.
+#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
+#define DCS_CONTROL_DISPLAY_HBM_CTRL0 BIT(6)
+#define DCS_CONTROL_DISPLAY_HBM_CTRL1 BIT(7)
+
+#define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Based on Vivid but over-saturated.
+#define DCS_SM_COLOR_MODE_WASHED 0x45
+#define DCS_SM_COLOR_MODE_BASIC 0x03 // Real natural profile.
+#define DCS_SM_COLOR_MODE_POR_RESET 0x20 // Reset value on power on.
+#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural.. Extra saturation.
+#define DCS_SM_COLOR_MODE_VIVID 0x65 // Saturated.
+#define DCS_SM_COLOR_MODE_NIGHT0 0x43 // Based on Washed Out.
+#define DCS_SM_COLOR_MODE_NIGHT1 0x15 // Based on Basic.
+#define DCS_SM_COLOR_MODE_NIGHT2 0x35 // Based on Natural.
+#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on Vivid.
+
+#define DCS_SM_COLOR_MODE_ENABLE BIT(0)
+
+#define PANEL_SM_BL_CANDELA_MAX 2047
+
+/* Switch Panels:
+ *
+ * 6.2" panels for Icosa and Iowa SKUs:
+ * [10] 81 [26]: JDI LPM062M326A
+ * [10] 96 [09]: JDI LAM062M109A
+ * [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
+ * [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1)
+ * [20] 96 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
+ * [20] 97 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
+ * [20] 98 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
+ * [20] 99 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
+ * [30] 93 [0F]: AUO A062TAN00 (59.06A33.000)
+ * [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
+ * [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
+ * [30] 97 [0F]: AUO A062TAN02 (59.06A33.002) [From photo of assumed same panel]
+ * [30] 98 [0F]: AUO A062TAN0? [UNCONFIRMED MODEL]
+ * [30] XX [0F]: AUO A062TAN03 (59.06A33.003) [UNCONFIRMED ID]
+ *
+ *
+ * 5.5" panels for Hoag SKU:
+ * [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1) (6203B001P4000)
+ * [20] 95 [10]: InnoLux 2J055IA-27A (Rev XX) [UNCONFIRMED MODEL+REV]
+ * [20] 96 [10]: InnoLux 2J055IA-27A (Rev XX) [UNCONFIRMED MODEL+REV]
+ * [30] 93 [10]: AUO A055TAN01 (59.05A30.001)
+ * [30] 94 [10]: AUO A055TAN02 (59.05A30.002)
+ * [30] 95 [10]: AUO A055TAN03 (59.05A30.003)
+ * [40] 94 [10]: Sharp LQ055T1SW10 (Rev P)
+ *
+ *
+ * 7.0" OLED panels for Aula SKU:
+ * [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5)
+ */
+
+/* Display ID Decoding:
+ *
+ * byte0: Vendor
+ * byte1: Model
+ * byte2: Board
+ *
+ * Vendors:
+ * 10h: Japan Display Inc.
+ * 20h: InnoLux Corporation
+ * 30h: AU Optronics
+ * 40h: Sharp
+ * 50h: Samsung
+ *
+ * Boards, Panel Size:
+ * 0Fh: Icosa/Iowa, 6.2"
+ * 10h: Hoag, 5.5"
+ * 20h: Aula, 7.0"
+ */
+
+enum
+{
+ PANEL_JDI_XXX062M = 0x10,
+ PANEL_JDI_LAM062M109A = 0x0910,
+ PANEL_JDI_LPM062M326A = 0x2610,
+ PANEL_INL_P062CCA_AZ1 = 0x0F20,
+ PANEL_AUO_A062TAN01 = 0x0F30,
+ PANEL_INL_2J055IA_27A = 0x1020,
+ PANEL_AUO_A055TAN01 = 0x1030,
+ PANEL_SHP_LQ055T1SW10 = 0x1040,
+ PANEL_SAM_AMS699VC01 = 0x2050,
+
+ // Found on 6/2" clones. Unknown markings. Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F].
+ PANEL_OEM_CLONE_6_2 = 0x0F83,
+ // Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
+ PANEL_OEM_CLONE_5_5 = 0x00B3,
+ // Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
+ PANEL_OEM_CLONE = 0x0000
+};
+
+void display_init();
+void display_backlight_pwm_init();
+void display_end();
+
+/*! Interrupt management. */
+void display_enable_interrupt(u32 intr);
+void display_disable_interrupt(u32 intr);
+void display_wait_interrupt(u32 intr);
+
+/*! Get/Set Display panel ID. */
+u16 display_get_decoded_panel_id();
+void display_set_decoded_panel_id(u32 id);
+
+/*! MIPI DCS register management */
+int display_dsi_read(u8 cmd, u32 len, void *data);
+int display_dsi_vblank_read(u8 cmd, u32 len, void *data);
+void display_dsi_write(u8 cmd, u32 len, void *data);
+void display_dsi_vblank_write(u8 cmd, u32 len, void *data);
+
+/*! Show one single color on the display. */
+void display_color_screen(u32 color);
+
+/*! Switches screen backlight ON/OFF. */
+void display_backlight(bool enable);
+void display_backlight_brightness(u32 brightness, u32 step_delay);
+u32 display_get_backlight_brightness();
+
+u32 *display_init_window_a_pitch();
+u32 *display_init_window_a_pitch_vic();
+u32 *display_init_window_a_pitch_inv();
+u32 *display_init_window_a_block();
+u32 *display_init_window_d_console();
+
+void display_window_disable(u32 window);
+
+void display_set_framebuffer(u32 window, void *fb);
+void display_move_framebuffer(u32 window, void *fb);
+
+void display_window_d_console_enable();
+void display_window_d_console_disable();
+
+void display_cursor_init(void *crs_fb, u32 size);
+void display_cursor_set_pos(u32 x, u32 y);
+void display_cursor_deinit();
+
+#endif
diff --git a/bdk/display/di.inl b/bdk/display/di.inl
new file mode 100644
index 0000000..d74130e
--- /dev/null
+++ b/bdk/display/di.inl
@@ -0,0 +1,573 @@
+/*
+* Copyright (c) 2018 naehrwert
+* Copyright (c) 2018-2024 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 .
+*/
+
+// Display A config.
+static const reg_cfg_t _di_dc_setup_win_config[] = {
+ {DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY},
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
+ {DC_CMD_REG_ACT_CONTROL, WIN_A_ACT_HCNTR_SEL | WIN_B_ACT_HCNTR_SEL | WIN_C_ACT_HCNTR_SEL},
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
+ {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 | SYNCPT_VSYNC_INDX(9)},
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ},
+
+ /* Setup Windows A/B/C */
+ {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT | WINDOW_D_SELECT},
+ {DC_WIN_WIN_OPTIONS, 0},
+ {DC_WIN_DV_CONTROL, 0},
+ /* Setup default YUV colorspace conversion coefficients */
+ {DC_WINC_CSC_YOF, 0xF0},
+ {DC_WINC_CSC_KYRGB, 0x12A},
+ {DC_WINC_CSC_KUR, 0},
+ {DC_WINC_CSC_KVR, 0x198},
+ {DC_WINC_CSC_KUG, 0x39B},
+ {DC_WINC_CSC_KVG, 0x32F},
+ {DC_WINC_CSC_KUB, 0x204},
+ {DC_WINC_CSC_KVB, 0},
+ /* End of color coefficients */
+
+ {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
+ {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
+ {DC_COM_PIN_OUTPUT_POLARITY(1), LSC0_OUTPUT_POLARITY_LOW},
+ {DC_COM_PIN_OUTPUT_POLARITY(3), 0},
+ {DC_DISP_BLEND_BACKGROUND_COLOR, 0},
+ {DC_COM_CRC_CONTROL, 0},
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ},
+ {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_BYPASS | WIN_BLEND_DEPTH(255)},
+ {DC_CMD_DISPLAY_COMMAND_OPTION0, 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 | WIN_D_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ}
+};
+
+// DSI Init config.
+static const reg_cfg_t _di_dsi_seq_pkt_reset_config0[] = {
+ {DSI_WR_DATA, 0},
+ {DSI_INT_ENABLE, 0},
+ {DSI_INT_STATUS, 0},
+ {DSI_INT_MASK, 0},
+ {DSI_INIT_SEQ_DATA_0, 0},
+ {DSI_INIT_SEQ_DATA_1, 0},
+ {DSI_INIT_SEQ_DATA_2, 0},
+ {DSI_INIT_SEQ_DATA_3, 0}
+};
+static const reg_cfg_t _di_dsi_seq_pkt_reset_config1[] = {
+ {DSI_DCS_CMDS, 0},
+ {DSI_PKT_SEQ_0_LO, 0},
+ {DSI_PKT_SEQ_1_LO, 0},
+ {DSI_PKT_SEQ_2_LO, 0},
+ {DSI_PKT_SEQ_3_LO, 0},
+ {DSI_PKT_SEQ_4_LO, 0},
+ {DSI_PKT_SEQ_5_LO, 0},
+ {DSI_PKT_SEQ_0_HI, 0},
+ {DSI_PKT_SEQ_1_HI, 0},
+ {DSI_PKT_SEQ_2_HI, 0},
+ {DSI_PKT_SEQ_3_HI, 0},
+ {DSI_PKT_SEQ_4_HI, 0},
+ {DSI_PKT_SEQ_5_HI, 0},
+ {DSI_CONTROL, 0}
+};
+static const reg_cfg_t _di_dsi_init_pads_t210b01[] = {
+ {DSI_PAD_CONTROL_1, 0},
+ {DSI_PAD_CONTROL_2, 0},
+ {DSI_PAD_CONTROL_3, 0},
+ {DSI_PAD_CONTROL_4, 0},
+ {DSI_PAD_CONTROL_5_B01, 0},
+ {DSI_PAD_CONTROL_6_B01, 0},
+ {DSI_PAD_CONTROL_7_B01, 0}
+};
+static const reg_cfg_t _di_dsi_init_config[] = {
+ {DSI_PAD_CONTROL_CD, 0},
+ {DSI_SOL_DELAY, 24},
+ {DSI_MAX_THRESHOLD, 480},
+ {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 timings */
+ {DSI_PHY_TIMING_0, 0x6070603},
+ {DSI_PHY_TIMING_1, 0x40A0E05},
+ {DSI_PHY_TIMING_2, 0x30109},
+ {DSI_BTA_TIMING, 0x190A14},
+ /* DSI timeout */
+ {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)}, // Power up.
+ {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 timings */
+ {DSI_PHY_TIMING_0, 0x6070603},
+ {DSI_PHY_TIMING_1, 0x40A0E05},
+ {DSI_PHY_TIMING_2, 0x30118},
+ {DSI_BTA_TIMING, 0x190A14},
+ /* DSI timeout */
+ {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, 64},
+ {DSI_TRIGGER, 0},
+ {DSI_TX_CRC, 0},
+ {DSI_INIT_SEQ_CONTROL, 0}
+};
+
+// DSI panel JDI config.
+static const reg_cfg_t _di_dsi_panel_init_config_jdi[] = {
+ {DSI_WR_DATA, 0x0439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
+ {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0xBD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x1939}, // MIPI_DSI_DCS_LONG_WRITE: 25 bytes.
+ {DSI_WR_DATA, 0xAAAAAAD8}, // Register: 0xD8.
+ {DSI_WR_DATA, 0xAAAAAAEB},
+ {DSI_WR_DATA, 0xAAEBAAAA},
+ {DSI_WR_DATA, 0xAAAAAAAA},
+ {DSI_WR_DATA, 0xAAAAAAEB},
+ {DSI_WR_DATA, 0xAAEBAAAA},
+ {DSI_WR_DATA, 0xAA},
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x01BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 1 to 0xBD.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x2739}, // MIPI_DSI_DCS_LONG_WRITE: 39 bytes.
+ {DSI_WR_DATA, 0xFFFFFFD8}, // Register: 0xD8.
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFF},
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x02BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 2 to 0xBD.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0xF39}, // MIPI_DSI_DCS_LONG_WRITE: 15 bytes.
+ {DSI_WR_DATA, 0xFFFFFFD8}, // Register: 0xD8.
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFFFF},
+ {DSI_WR_DATA, 0xFFFFFF},
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x06D915}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 6 to 0xD9.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
+ {DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST}
+};
+
+// DSI packet config.
+static const reg_cfg_t _di_dsi_seq_pkt_video_non_burst_no_eot_config[] = {
+ {DSI_PAD_CONTROL_1, 0},
+
+ /* DSI PHY timings */
+ {DSI_PHY_TIMING_0, 0x6070603},
+ {DSI_PHY_TIMING_1, 0x40A0E05},
+ {DSI_PHY_TIMING_2, 0x30172},
+ {DSI_BTA_TIMING, 0x190A14},
+ /* DSI timeout */
+ {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, PKT1_LEN(206) | PKT0_LEN(0)},
+ {DSI_PKT_LEN_2_3, PKT1_LEN(2160) | PKT0_LEN(418)},
+ {DSI_PKT_LEN_4_5, PKT1_LEN(0) | PKT0_LEN(400)},
+ {DSI_PKT_LEN_6_7, PKT1_LEN(0) | PKT0_LEN(400)},
+ {DSI_HOST_CONTROL, 0}
+};
+
+// DSI mode config.
+static const reg_cfg_t _di_dsi_host_mode_config[] = {
+ {DSI_TRIGGER, 0},
+ {DSI_CONTROL, 0},
+ {DSI_SOL_DELAY, 6},
+ {DSI_MAX_THRESHOLD, 480},
+ {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_TX_TRIG_SOL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
+ {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_TX_TRIG_SOL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}
+};
+
+// MIPI CAL config.
+static const reg_cfg_t _di_mipi_pad_cal_config[] = {
+ {MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
+ {MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
+ {MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0},
+ {MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0}
+};
+
+// DSI pad config.
+static const reg_cfg_t _di_dsi_pad_cal_config_t210[] = {
+ {DSI_PAD_CONTROL_1, 0},
+ {DSI_PAD_CONTROL_2, 0},
+ {DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)},
+ {DSI_PAD_CONTROL_4, 0}
+};
+static const reg_cfg_t _di_dsi_pad_cal_config_t210b01[] = {
+ {DSI_PAD_CONTROL_1, 0},
+ {DSI_PAD_CONTROL_2, 0},
+ {DSI_PAD_CONTROL_3, 0},
+ {DSI_PAD_CONTROL_4, 0x77777},
+ {DSI_PAD_CONTROL_5_B01, 0x77777},
+ {DSI_PAD_CONTROL_6_B01, DSI_PAD_PREEMP_PD_CLK(0x1) | DSI_PAD_PREEMP_PU_CLK(0x1) | DSI_PAD_PREEMP_PD(0x01) | DSI_PAD_PREEMP_PU(0x1)},
+ {DSI_PAD_CONTROL_7_B01, 0}
+};
+
+// MIPI CAL config.
+static const reg_cfg_t _di_mipi_dsi_cal_prod_config_t210[] = {
+ {MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
+ {MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
+ {MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
+ {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002}
+};
+static const reg_cfg_t _di_mipi_dsi_cal_prod_config_t210b01[] = {
+ {MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006},
+ {MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006},
+ {MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000},
+ {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000}
+};
+static const reg_cfg_t _di_mipi_dsi_cal_unused_config[] = {
+ {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}
+};
+
+// Display A enable config.
+static const reg_cfg_t _di_dc_video_enable_config[] = {
+ /* Set panel timings */
+ {DC_DISP_DISP_TIMING_OPTIONS, VSYNC_H_POSITION(0)},
+ {DC_DISP_REF_TO_SYNC, V_REF_TO_SYNC(1) | H_REF_TO_SYNC(0)},
+ {DC_DISP_SYNC_WIDTH, V_SYNC_WIDTH(1) | H_SYNC_WIDTH(72)},
+ {DC_DISP_BACK_PORCH, V_BACK_PORCH(9) | H_BACK_PORCH(72)},
+ {DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)},
+ {DC_DISP_ACTIVE, V_DISP_ACTIVE(1280) | H_DISP_ACTIVE(720)},
+ /* 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_CLOCK_CONTROL, 0},
+
+ /* Start continuous display. */
+ {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_CONTROL, GENERAL_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
+ {DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
+ {DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
+
+ {DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)}, // 4: div3.
+};
+
+// Display A disable config.
+static const reg_cfg_t _di_dc_video_disable_config[] = {
+ {DC_CMD_INT_MASK, 0},
+ {DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY},
+ {DC_CMD_INT_ENABLE, 0},
+ {DC_CMD_CONT_SYNCPT_VSYNC, 0},
+
+ /* Stop display. */
+ {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, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
+ {DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
+ // TODO: LCD panels should sleep for 40ms here.
+ {DC_CMD_DISPLAY_POWER_CONTROL, 0},
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
+};
+
+// DSI deinit config.
+static const reg_cfg_t _di_dsi_timing_deinit_config[] = {
+ {DSI_POWER_CONTROL, 0},
+ {DSI_PAD_CONTROL_1, 0},
+
+ /* DSI PHY timings */
+ {DSI_PHY_TIMING_0, 0x6070603},
+ {DSI_PHY_TIMING_1, 0x40A0E05},
+ {DSI_PHY_TIMING_2, 0x30118},
+ {DSI_BTA_TIMING, 0x190A14},
+ /* DSI timeout */
+ {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, 64},
+ {DSI_TRIGGER, 0},
+ {DSI_TX_CRC, 0},
+ {DSI_INIT_SEQ_CONTROL, 0}
+};
+
+// DSI panel JDI deinit config.
+static const reg_cfg_t _di_dsi_panel_deinit_config_jdi[] = {
+ {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
+ {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x2139}, // MIPI_DSI_DCS_LONG_WRITE: 33 bytes.
+ {DSI_WR_DATA, 0x191919D5}, // Register: 0xD5.
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19},
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
+ {DSI_WR_DATA, 0x4F0F41B1}, // MIPI_DCS_PRIV_SET_POWER_CONTROL.
+ {DSI_WR_DATA, 0xF179A433},
+ {DSI_WR_DATA, 0x002D81},
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
+ {DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST}
+};
+
+// DSI panel AUO deinit config.
+static const reg_cfg_t _di_dsi_panel_deinit_config_auo[] = {
+ {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
+ {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
+ {DSI_WR_DATA, 0x191919D5}, // Register: 0xD5.
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
+ {DSI_WR_DATA, 0x191919D6}, // Register: 0xD6.
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_WR_DATA, 0x19191919},
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
+ {DSI_WR_DATA, 0x711148B1}, // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
+ // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG).
+ {DSI_WR_DATA, 0x71143209},
+ {DSI_WR_DATA, 0x114D31}, // (Unknown).
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+ {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
+ {DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST}
+};
+
+/*
+static const reg_cfg_t _di_init_config_invert[] = {
+ {DSI_WR_DATA, 0x239},
+ {DSI_WR_DATA, 0x02C1}, // INV_EN.
+ {DSI_TRIGGER, DSI_TRIGGER_HOST},
+};
+*/
+
+// Display A Window A one color config.
+static const reg_cfg_t _di_win_one_color[] = {
+ {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT | WINDOW_D_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 Window A linear pitch config.
+static const reg_cfg_t _di_winA_pitch[] = {
+ {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_POSITION, 0}, //(0,0)
+ {DC_WIN_H_INITIAL_DDA, 0},
+ {DC_WIN_V_INITIAL_DDA, 0},
+ {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
+ {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
+ {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
+ {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
+ {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
+ {DC_WINBUF_SURFACE_KIND, PITCH},
+ {DC_WINBUF_START_ADDR, IPL_FB_ADDRESS}, // Framebuffer address.
+ {DC_WINBUF_ADDR_H_OFFSET, 0},
+ {DC_WINBUF_ADDR_V_OFFSET, 0},
+ {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD.
+ {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
+};
+
+// Display A Window A linear pitch + Win D support config.
+static const reg_cfg_t _di_winA_pitch_vic[] = {
+ {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_POSITION, 0}, //(0,0)
+ {DC_WIN_H_INITIAL_DDA, 0},
+ {DC_WIN_V_INITIAL_DDA, 0},
+ {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
+ {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
+ {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
+ {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
+ {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
+ {DC_WINBUF_SURFACE_KIND, PITCH},
+ {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
+ {DC_WINBUF_ADDR_H_OFFSET, 0},
+ {DC_WINBUF_ADDR_V_OFFSET, 0},
+ {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD.
+ {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
+};
+
+// Display A Window A linear pitch inverse + Win D support config.
+static const reg_cfg_t _di_winA_pitch_inv[] = {
+ {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_POSITION, 0}, //(0,0)
+ {DC_WIN_H_INITIAL_DDA, 0},
+ {DC_WIN_V_INITIAL_DDA, 0},
+ {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
+ {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
+ {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
+ {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
+ {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
+ {DC_WINBUF_SURFACE_KIND, PITCH},
+ {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
+ {DC_WINBUF_ADDR_H_OFFSET, 0}, // Linear: 0x383FFC, Block: 0x3813FC.
+ {DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0.
+ {DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD.
+ {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
+};
+
+// Display A Window A block linear config.
+static const reg_cfg_t _di_winA_block[] = {
+ {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_POSITION, 0}, //(0,0)
+ {DC_WIN_H_INITIAL_DDA, 0},
+ {DC_WIN_V_INITIAL_DDA, 0},
+ {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
+ {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
+ {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
+ {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
+ {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
+ {DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK},
+ {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
+ {DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC. Block in HOS: 0x13FF.
+ {DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0.
+ {DC_WIN_WIN_OPTIONS, WIN_ENABLE | SCAN_COLUMN | H_DIRECTION}, // Enable window AD. | SCAN_COLUMN | H_DIRECTION.
+ {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
+};
+
+// Display A Window D config.
+static const reg_cfg_t _di_winD_log[] = {
+ {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
+ {DC_WIN_WIN_OPTIONS, 0},
+ {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8},
+ {DC_WIN_POSITION, 0}, //(0,0)
+ {DC_WIN_H_INITIAL_DDA, 0},
+ {DC_WIN_V_INITIAL_DDA, 0},
+ {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)},
+ {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
+ {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)},
+ {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
+ {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
+ {DC_WINBUF_SURFACE_KIND, PITCH},
+ {DC_WINBUF_START_ADDR, LOG_FB_ADDRESS}, // Framebuffer address.
+ {DC_WINBUF_ADDR_H_OFFSET, 0},
+ {DC_WINBUF_ADDR_V_OFFSET, 0},
+ {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200) | WIN_BLEND_DEPTH(0)},
+ {DC_WINBUF_BLEND_MATCH_SELECT, WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 | WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1},
+ {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE},
+ {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ},
+};
diff --git a/bdk/display/vic.c b/bdk/display/vic.c
new file mode 100644
index 0000000..1044448
--- /dev/null
+++ b/bdk/display/vic.c
@@ -0,0 +1,560 @@
+/*
+ * VIC driver for Tegra X1
+ *
+ * Copyright (c) 2018-2024 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 .
+ */
+
+#include
+
+#include "vic.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* VIC Private registers */
+#define PVIC_FALCON_PA_OFFSET 0x1000
+#define PVIC_FALCON_ADDR 0x10AC
+#define PVIC_FALCON_IDLESTATE 0x104C
+
+/* VIC Control and Status registers. */
+/* Fetch Control registers. */
+#define VIC_FC_COMPOSE 0x10000
+#define COMPOSE_START BIT(0)
+
+#define VIC_FC_CFG_STRUCT_SLOT_INDEX 0x10B00
+
+#define VIC_FC_CFG_STRUCT_SLOT_CFG0 0x10B04
+#define SLOT_ENABLE BIT(0)
+#define FIELD_CURRENT_ENABLE BIT(8)
+
+#define VIC_FC_CFG_STRUCT_SLOT_CFG2 0x10B0C
+#define CACHE_WIDTH(n) ((n) << 16)
+#define CACHE_WIDTH_16BX16 0 // Block Linear.
+#define CACHE_WIDTH_32BX8 1 // Block Linear. Recommended for Block Linear.
+#define CACHE_WIDTH_64BX4 2 // Block Linear, Pitch. Recommended for Pitch.
+#define CACHE_WIDTH_128BX2 3 // Block Linear, Pitch.
+#define OUTPUT_FLIP_X BIT(20)
+#define OUTPUT_FLIP_Y BIT(21)
+#define OUTPUT_TRANSPOSE BIT(22)
+
+#define VIC_FC_CFG_STRUCT_SLOT_SFC_SIZE 0x10B10
+#define VIC_FC_CFG_STRUCT_SLOT_LUMA_SIZE 0x10B14
+#define VIC_FC_CFG_STRUCT_SLOT_CHROMA_SIZE 0x10B18
+#define VIC_FC_CFG_STRUCT_SLOT_SRC_RECT_LR 0x10B1C
+#define VIC_FC_CFG_STRUCT_SLOT_SRC_RECT_TB 0x10B20
+#define VIC_FC_CFG_STRUCT_SLOT_DST_RECT_LR 0x10B30
+#define VIC_FC_CFG_STRUCT_SLOT_DST_RECT_TB 0x10B34
+#define VIC_FC_CFG_STRUCT_TGT_RECT_LR 0x10B38
+#define VIC_FC_CFG_STRUCT_TGT_RECT_TB 0x10B3C
+#define VIC_FC_SLOT_MAP 0x10C00
+
+#define VIC_FC_FCE_CTRL 0x11000
+#define START_TRIGGER BIT(0)
+#define HALT_TRIGGER BIT(1)
+#define CLEAR_ERROR BIT(8)
+
+#define VIC_FC_FCE_UCODE_ADDR 0x11200
+#define VIC_FC_FCE_UCODE_INST 0x11300
+
+/* Surface List registers. */
+#define VIC_SL_CFG_STRUCT_SLOT_INDEX 0x12100
+#define VIC_SL_CFG_STRUCT_SLOT_DST_RECT_LR 0x12200
+#define VIC_SL_CFG_STRUCT_SLOT_DST_RECT_TB 0x12300
+#define VIC_SL_CFG_STRUCT_TGT_RECT_LR 0x12400
+#define VIC_SL_CFG_STRUCT_TGT_RECT_TB 0x12500
+#define VIC_SL_CFG_STRUCT_SLOT_CFG0 0x12600
+
+/* Surface Cache registers. */
+#define VIC_SC_PRAMBASE 0x14000
+#define VIC_SC_PRAMSIZE 0x14100
+#define VIC_SC_SFC0_BASE_LUMA(n) (0x14300 + (n) * 0x100)
+
+/* Blending Output registers. */
+#define VIC_BL_TARGET_BASADR 0x22000
+#define VIC_BL_CONFIG 0x22800
+#define SUBPARTITION_MODE BIT(0)
+#define PROCESS_CFG_STRUCT_TRIGGER BIT(2)
+#define SLOTMASK(n) ((n) << 8)
+
+#define VIC_BL_CFG_STRUCT_CFG0 0x22C00
+#define VIC_BL_CFG_STRUCT_SFC_SIZE 0x22C04
+#define VIC_BL_CFG_STRUCT_LUMA_SIZE 0x22C08
+#define VIC_BL_CFG_STRUCT_CHROMA_SIZE 0x22C0C
+#define VIC_BL_CFG_STRUCT_TGT_RECT_LR 0x22C10
+#define VIC_BL_CFG_STRUCT_TGT_RECT_TB 0x22C14
+
+// VIC_FC_CFG_STRUCT_SLOT_CFG2 & VIC_BL_CFG_STRUCT_CFG0.
+#define BLK_KIND(n) ((n) << 8)
+#define BLK_KIND_PITCH 0
+#define BLK_KIND_GENERIC_16BX2 1
+#define BLK_HEIGHT(n) ((n) << 12)
+#define BLK_HEIGHT_ONE_GOB 0
+#define BLK_HEIGHT_SIXTEEN_GOBS 4
+
+// Generic size macros.
+#define SIZE_WIDTH(n) (((n) - 1) << 0)
+#define SIZE_HEIGHT(n) (((n) - 1) << 16)
+#define RECT_LEFT(n) ((n) << 0)
+#define RECT_RIGHT(n) (((n) - 1) << 16)
+#define RECT_TOP(n) ((n) << 0)
+#define RECT_BOTTOM(n) (((n) - 1) << 16)
+
+#define FORMAT_PROGRESSIVE 0
+#define SOFT_CLAMP_MIN 0
+#define SOFT_CLAMP_MAX 0x3FFu
+#define ALPHA_1_0 0x3FFu
+
+typedef struct _OutputConfig {
+ u64 AlphaFillMode:3;
+ u64 AlphaFillSlot:3;
+ u64 BackgroundAlpha:10;
+ u64 BackgroundR:10;
+ u64 BackgroundG:10;
+ u64 BackgroundB:10;
+ u64 RegammaMode:2;
+ u64 OutputFlipX:1;
+ u64 OutputFlipY:1;
+ u64 OutputTranspose:1;
+ u64 rsvd1:1;
+ u64 rsvd2:12;
+ u64 TargetRectLeft:14;
+ u64 rsvd3:2;
+ u64 TargetRectRight:14;
+ u64 rsvd4:2;
+ u64 TargetRectTop:14;
+ u64 rsvd5:2;
+ u64 TargetRectBottom:14;
+ u64 rsvd6:2;
+} OutputConfig;
+
+typedef struct _OutputSurfaceConfig {
+ u64 OutPixelFormat:7;
+ u64 OutChromaLocHoriz:2;
+ u64 OutChromaLocVert:2;
+ u64 OutBlkKind:4;
+ u64 OutBlkHeight:4;
+ u64 rsvd0:3;
+ u64 rsvd1:10;
+ u64 OutSurfaceWidth:14;
+ u64 OutSurfaceHeight:14;
+ u64 rsvd2:4;
+ u64 OutLumaWidth:14;
+ u64 OutLumaHeight:14;
+ u64 rsvd3:4;
+ u64 OutChromaWidth:14;
+ u64 OutChromaHeight:14;
+ u64 rsvd4:4;
+} OutputSurfaceConfig;
+
+typedef struct _SlotConfig {
+ u64 SlotEnable:1;
+ u64 DeNoise:1;
+ u64 AdvancedDenoise:1;
+ u64 CadenceDetect:1;
+ u64 MotionMap:1;
+ u64 MMapCombine:1;
+ u64 IsEven:1;
+ u64 ChromaEven:1;
+ u64 CurrentFieldEnable:1;
+ u64 PrevFieldEnable:1;
+ u64 NextFieldEnable:1;
+ u64 NextNrFieldEnable:1;
+ u64 CurMotionFieldEnable:1;
+ u64 PrevMotionFieldEnable:1;
+ u64 PpMotionFieldEnable:1;
+ u64 CombMotionFieldEnable:1;
+ u64 FrameFormat:4;
+ u64 FilterLengthY:2;
+ u64 FilterLengthX:2;
+ u64 Panoramic:12;
+ u64 rsvd1:22;
+ u64 DetailFltClamp:6;
+ u64 FilterNoise:10;
+ u64 FilterDetail:10;
+ u64 ChromaNoise:10;
+ u64 ChromaDetail:10;
+ u64 DeinterlaceMode:4;
+ u64 MotionAccumWeight:3;
+ u64 NoiseIir:11;
+ u64 LightLevel:4;
+ u64 rsvd4:2;
+ u64 SoftClampLow:10;
+ u64 SoftClampHigh:10;
+ u64 rsvd5:3;
+ u64 rsvd6:9;
+ u64 PlanarAlpha:10;
+ u64 ConstantAlpha:1;
+ u64 StereoInterleave:3;
+ u64 ClipEnabled:1;
+ u64 ClearRectMask:8;
+ u64 DegammaMode:2;
+ u64 rsvd7:1;
+ u64 DecompressEnable:1;
+ u64 rsvd9:5;
+ u64 DecompressCtbCount:8;
+ u64 DecompressZbcColor:32;
+ u64 rsvd12:24;
+ u64 SourceRectLeft:30;
+ u64 rsvd14:2;
+ u64 SourceRectRight:30;
+ u64 rsvd15:2;
+ u64 SourceRectTop:30;
+ u64 rsvd16:2;
+ u64 SourceRectBottom:30;
+ u64 rsvd17:2;
+ u64 DestRectLeft:14;
+ u64 rsvd18:2;
+ u64 DestRectRight:14;
+ u64 rsvd19:2;
+ u64 DestRectTop:14;
+ u64 rsvd20:2;
+ u64 DestRectBottom:14;
+ u64 rsvd21:2;
+ u64 rsvd22:32;
+ u64 rsvd23:32;
+} SlotConfig;
+
+typedef struct _SlotSurfaceConfig {
+ u64 SlotPixelFormat:7;
+ u64 SlotChromaLocHoriz:2;
+ u64 SlotChromaLocVert:2;
+ u64 SlotBlkKind:4;
+ u64 SlotBlkHeight:4;
+ u64 SlotCacheWidth:3;
+ u64 rsvd0:10;
+ u64 SlotSurfaceWidth:14;
+ u64 SlotSurfaceHeight:14;
+ u64 rsvd1:4;
+ u64 SlotLumaWidth:14;
+ u64 SlotLumaHeight:14;
+ u64 rsvd2:4;
+ u64 SlotChromaWidth:14;
+ u64 SlotChromaHeight:14;
+ u64 rsvd3:4;
+} SlotSurfaceConfig;
+
+typedef struct _SlotStruct {
+ SlotConfig slot_cfg;
+ SlotSurfaceConfig slot_sfc_cfg;
+
+ // No need to configure. Reset to zeros.
+ u8 lumaKeyStruct[0x10];
+ u8 colorMatrixStruct[0x20];
+ u8 gamutMatrixStruct[0x20];
+ u8 blendingSlotStruct[0x10];
+} SlotStruct;
+
+typedef struct _vic_config_t {
+ // No need to configure. Reset to zeros.
+ u8 pipeConfig[0x10];
+
+ OutputConfig out_cfg;
+ OutputSurfaceConfig out_sfc_cfg;
+
+ // No need to configure. Reset to zeros.
+ u8 out_color_matrix[0x20];
+ u8 clear_rect[0x10 * 4];
+
+ SlotStruct slots[8];
+} vic_config_t;
+
+// VIC Fetch Control Engine microcode. Dumped from L4T r33.
+u8 vic_fce_ucode[] = {
+ 0x66, 0x00, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x42, 0x40, 0x10, 0x00, 0x4E, 0x01, 0x40, 0x00,
+ 0x6A, 0x07, 0x00, 0x00, 0x6E, 0x23, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x04, 0x00,
+ 0x6A, 0x0B, 0x00, 0x00, 0x6E, 0x1F, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x10, 0x00,
+ 0x6A, 0x0F, 0x00, 0x00, 0x6E, 0x1F, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x48, 0x80, 0x02, 0x00,
+ 0x0E, 0x11, 0x00, 0x00, 0x6A, 0x14, 0x00, 0x00, 0x6E, 0x08, 0x06, 0x00, 0x6C, 0x00, 0x00, 0x00,
+ 0x4E, 0x01, 0x08, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x6E, 0x26, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00,
+ 0x4E, 0x01, 0x20, 0x00, 0x6A, 0x1C, 0x00, 0x00, 0x6E, 0x26, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00,
+ 0x4E, 0x01, 0x02, 0x00, 0x6A, 0x20, 0x00, 0x00, 0x6E, 0x24, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,
+ 0x56, 0x00, 0x10, 0x00, 0x56, 0x40, 0x10, 0x00, 0x22, 0x41, 0x01, 0x00, 0x6C, 0x00, 0x00, 0x00,
+ 0x62, 0x80, 0x01, 0x00, 0x60, 0x47, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, 0x01, 0x4A, 0x00, 0x00,
+ 0x55, 0xC0, 0x20, 0x00, 0x00, 0x59, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00,
+ 0x01, 0x93, 0x00, 0x00, 0x40, 0x82, 0x02, 0x00, 0x4E, 0x02, 0x00, 0x00, 0x6B, 0x34, 0x00, 0x00,
+ 0x43, 0xC1, 0x10, 0x00, 0x42, 0x02, 0x03, 0x00, 0x00, 0x23, 0x01, 0x00, 0x24, 0xD4, 0x00, 0x00,
+ 0x56, 0x40, 0x3D, 0x00, 0x04, 0xEB, 0x00, 0x00, 0x60, 0x07, 0x01, 0x00, 0x60, 0x47, 0x00, 0x00,
+ 0x6A, 0x3E, 0x00, 0x00, 0x55, 0xC0, 0x30, 0x00, 0x48, 0x00, 0x01, 0x00, 0x48, 0x40, 0x01, 0x00,
+ 0x48, 0x80, 0x01, 0x00, 0x6B, 0x28, 0x02, 0x00, 0x56, 0x40, 0x09, 0x00, 0x04, 0x4D, 0x01, 0x00,
+ 0x06, 0x4D, 0x00, 0x00, 0x42, 0xC0, 0x03, 0x00, 0x56, 0x80, 0x09, 0x00, 0x04, 0xFE, 0x01, 0x00,
+ 0x00, 0xF9, 0x01, 0x00, 0x4E, 0x02, 0x00, 0x00, 0x6B, 0x32, 0x02, 0x00, 0x55, 0x40, 0x2F, 0x00,
+ 0x56, 0x80, 0x0D, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x6A, 0x0D, 0x02, 0x00, 0x55, 0x40, 0x31, 0x00,
+ 0x56, 0x80, 0x0B, 0x00, 0x0C, 0x2B, 0x00, 0x00, 0x6A, 0x13, 0x02, 0x00, 0x43, 0x45, 0x03, 0x00,
+ 0x42, 0x86, 0x03, 0x00, 0x4D, 0x06, 0x02, 0x00, 0x6A, 0x0D, 0x02, 0x00, 0x42, 0x86, 0x03, 0x00,
+ 0x22, 0x7E, 0x01, 0x00, 0x4E, 0x04, 0x00, 0x00, 0x6B, 0x32, 0x02, 0x00, 0x55, 0x40, 0x17, 0x00,
+ 0x0D, 0x2C, 0x00, 0x00, 0x56, 0xC0, 0x09, 0x00, 0x6A, 0x1E, 0x02, 0x00, 0x48, 0xC0, 0x01, 0x00,
+ 0x43, 0x04, 0x03, 0x00, 0x6C, 0x20, 0x02, 0x00, 0x55, 0x40, 0x19, 0x00, 0x01, 0x2C, 0x01, 0x00,
+ 0x65, 0x23, 0x01, 0x00, 0x42, 0x42, 0x03, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x24, 0x14, 0x01, 0x00,
+ 0x00, 0x2C, 0x01, 0x00, 0x24, 0x14, 0x01, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x42, 0x04, 0x09, 0x00,
+ 0x42, 0xC3, 0x02, 0x00, 0x65, 0x54, 0x01, 0x00, 0x65, 0x55, 0x01, 0x00, 0x42, 0x45, 0x0D, 0x00,
+ 0x62, 0x03, 0x00, 0x00, 0x62, 0x44, 0x00, 0x00, 0x62, 0x85, 0x00, 0x00, 0x62, 0xC2, 0x00, 0x00,
+ 0x22, 0x48, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x01, 0x00, 0x6C, 0x28, 0x02, 0x00,
+ 0x62, 0x80, 0x01, 0x00, 0x60, 0x07, 0x00, 0x00, 0x60, 0x47, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0x00, 0x43, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x01, 0xCA, 0x01, 0x00,
+ 0x60, 0x03, 0x01, 0x00, 0x01, 0xA0, 0x01, 0x00, 0x60, 0x40, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00,
+ 0x55, 0xC0, 0x2E, 0x00, 0x01, 0x18, 0x00, 0x00, 0x43, 0x00, 0x04, 0x00, 0x43, 0x41, 0x06, 0x00,
+ 0x6F, 0x00, 0x00, 0x00, 0x61, 0xC1, 0x00, 0x00, 0x61, 0x42, 0x01, 0x00, 0x65, 0xB5, 0x00, 0x00,
+ 0x65, 0x73, 0x01, 0x00, 0x65, 0x35, 0x01, 0x00, 0x65, 0x34, 0x01, 0x00, 0x42, 0x04, 0x0D, 0x00,
+ 0x01, 0x14, 0x01, 0x00, 0x42, 0x04, 0x03, 0x00, 0x00, 0x20, 0x00, 0x00, 0x43, 0x03, 0x05, 0x00,
+ 0x43, 0x85, 0x02, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x48, 0x46, 0x01, 0x00, 0x65, 0xEB, 0x00, 0x00,
+ 0x00, 0x9A, 0x00, 0x00, 0x65, 0xB2, 0x01, 0x00, 0x00, 0xA6, 0x01, 0x00, 0x42, 0x86, 0x0D, 0x00,
+ 0x61, 0x42, 0x01, 0x00, 0x01, 0xAE, 0x01, 0x00, 0x00, 0x71, 0x00, 0x00, 0x42, 0x82, 0x08, 0x00,
+ 0x42, 0xC3, 0x08, 0x00, 0x48, 0x40, 0x01, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x6E, 0x34, 0x02, 0x00,
+ 0x65, 0x79, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x6C, 0x36, 0x04, 0x00, 0x6E, 0x34, 0x02, 0x00,
+ 0x48, 0x7F, 0x01, 0x00, 0x6C, 0x0A, 0x06, 0x00, 0x6E, 0x34, 0x02, 0x00, 0x6E, 0x05, 0x04, 0x00,
+ 0x65, 0x79, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x41, 0x87, 0x03, 0x00, 0x65, 0xBA, 0x00, 0x00,
+ 0x65, 0xB2, 0x00, 0x00, 0x42, 0x82, 0x02, 0x00, 0x00, 0x51, 0x00, 0x00, 0x61, 0xC1, 0x00, 0x00,
+ 0x65, 0xFB, 0x00, 0x00, 0x65, 0xF3, 0x00, 0x00, 0x41, 0x87, 0x05, 0x00, 0x65, 0xF3, 0x00, 0x00,
+ 0x42, 0xC3, 0x08, 0x00, 0x00, 0x59, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00,
+ 0x56, 0xC0, 0x21, 0x00, 0x04, 0xDF, 0x01, 0x00, 0x43, 0xC7, 0x15, 0x00, 0x00, 0x38, 0x00, 0x00,
+ 0x00, 0x79, 0x00, 0x00, 0x42, 0xC3, 0x20, 0x00, 0x43, 0xC3, 0x04, 0x00, 0x42, 0x00, 0x30, 0x00,
+ 0x42, 0x41, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x60, 0xC7, 0x01, 0x00,
+ 0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00, 0x22, 0x7F, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00,
+ 0x6E, 0x34, 0x02, 0x00, 0x6E, 0x05, 0x04, 0x00, 0x4B, 0x41, 0x00, 0x00, 0x60, 0xC7, 0x01, 0x00,
+ 0x60, 0x87, 0x01, 0x00, 0x43, 0x86, 0x15, 0x00, 0x00, 0x30, 0x00, 0x00, 0x65, 0x39, 0x01, 0x00,
+ 0x42, 0x04, 0x05, 0x00, 0x4E, 0x05, 0x7E, 0x00, 0x6A, 0x1B, 0x06, 0x00, 0x55, 0xC0, 0x3D, 0x00,
+ 0x0A, 0x3C, 0x01, 0x00, 0x60, 0xC7, 0x01, 0x00, 0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00,
+ 0x22, 0x7C, 0x09, 0x00, 0x22, 0x7F, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x65, 0x7A, 0x01, 0x00,
+ 0x42, 0x45, 0x05, 0x00, 0x65, 0xBB, 0x01, 0x00, 0x42, 0x86, 0x05, 0x00, 0x55, 0xC0, 0x3D, 0x00,
+ 0x0A, 0x7D, 0x01, 0x00, 0x0A, 0xBE, 0x01, 0x00, 0x07, 0xC7, 0x01, 0x00, 0x0B, 0x7D, 0x01, 0x00,
+ 0x0B, 0xBE, 0x01, 0x00, 0x55, 0xC0, 0x3D, 0x00, 0x0A, 0x3C, 0x01, 0x00, 0x60, 0xC7, 0x01, 0x00,
+ 0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00, 0x22, 0x7A, 0x05, 0x00, 0x22, 0x7B, 0x07, 0x00,
+ 0x22, 0x7C, 0x09, 0x00, 0x22, 0x7D, 0x0B, 0x00, 0x22, 0x7E, 0x0D, 0x00, 0x22, 0x7F, 0x1F, 0x00,
+ 0x6F, 0x00, 0x00, 0x00
+};
+
+vic_config_t __attribute__((aligned (0x100))) vic_cfg = {0};
+
+u32 _vic_read_priv(u32 addr)
+{
+ u32 addr_lsb = addr & 0xFF;
+
+ // Set address LSB.
+ if (addr_lsb)
+ VIC(PVIC_FALCON_ADDR) = addr_lsb >> 2;
+
+ // Set address.
+ u32 val = VIC(PVIC_FALCON_PA_OFFSET + (addr >> 6));
+
+ // Unset address LSB.
+ if (addr_lsb)
+ VIC(PVIC_FALCON_ADDR) = 0;
+
+ return val;
+}
+
+static void _vic_write_priv(u32 addr, u32 data)
+{
+ u32 addr_lsb = addr & 0xFF;
+
+ // Set address LSB.
+ if (addr_lsb)
+ VIC(PVIC_FALCON_ADDR) = addr_lsb >> 2;
+
+ // Set address.
+ VIC(PVIC_FALCON_PA_OFFSET + (addr >> 6)) = data;
+
+ // Unset address LSB.
+ if (addr_lsb)
+ VIC(PVIC_FALCON_ADDR) = 0;
+}
+
+static int _vic_wait_idle()
+{
+ u32 timeout_count = 15000; // 150ms.
+
+ while (VIC(PVIC_FALCON_IDLESTATE))
+ {
+ usleep(10);
+
+ timeout_count--;
+ if (!timeout_count)
+ return -1;
+ };
+
+ return 0;
+}
+
+void vic_set_surface(const vic_surface_t *sfc)
+{
+ u32 flip_x = 0;
+ u32 flip_y = 0;
+ u32 swap_xy = 0;
+ u32 const_alpha = 0;
+
+ u32 width = sfc->width;
+ u32 height = sfc->height;
+ u32 pix_fmt = sfc->pix_fmt;
+ u32 src_buf = sfc->src_buf;
+ u32 dst_buf = sfc->dst_buf;
+
+ // Get format alpha type.
+ switch (sfc->pix_fmt)
+ {
+ case VIC_PIX_FORMAT_L8:
+ case VIC_PIX_FORMAT_X1B5G5R5:
+ case VIC_PIX_FORMAT_B5G5R5X1:
+ case VIC_PIX_FORMAT_X8B8G8R8:
+ case VIC_PIX_FORMAT_X8R8G8B8:
+ case VIC_PIX_FORMAT_B8G8R8X8:
+ case VIC_PIX_FORMAT_R8G8B8X8:
+ const_alpha = 1;
+ break;
+
+ case VIC_PIX_FORMAT_A8B8G8R8:
+ case VIC_PIX_FORMAT_A8R8G8B8:
+ case VIC_PIX_FORMAT_B8G8R8A8:
+ case VIC_PIX_FORMAT_R8G8B8A8:
+ default:
+ break;
+ }
+
+ // Get rotation parameters.
+ switch (sfc->rotation)
+ {
+ case VIC_ROTATION_90:
+ swap_xy = 1;
+ break;
+
+ case VIC_ROTATION_180:
+ flip_x = 1;
+ flip_y = 1;
+ break;
+
+ case VIC_ROTATION_270:
+ flip_x = 1;
+ swap_xy = 1;
+ break;
+
+ case VIC_ROTATION_0:
+ default:
+ break;
+ }
+
+ // Set output surface format.
+ vic_cfg.out_sfc_cfg.OutPixelFormat = pix_fmt;
+ vic_cfg.out_sfc_cfg.OutBlkKind = BLK_KIND_PITCH;
+ vic_cfg.out_sfc_cfg.OutBlkHeight = 0;
+
+ // Set output rotation/flip.
+ vic_cfg.out_cfg.OutputFlipX = flip_x;
+ vic_cfg.out_cfg.OutputFlipY = flip_y;
+ vic_cfg.out_cfg.OutputTranspose = swap_xy;
+
+ // Set output surface resolution.
+ vic_cfg.out_sfc_cfg.OutSurfaceWidth = width - 1;
+ vic_cfg.out_sfc_cfg.OutSurfaceHeight = height - 1;
+ vic_cfg.out_sfc_cfg.OutLumaWidth = width - 1;
+ vic_cfg.out_sfc_cfg.OutLumaHeight = height - 1;
+
+ // Set output destination rectangle. Anything outside will not be touched at output buffer.
+ vic_cfg.out_cfg.TargetRectLeft = 0;
+ vic_cfg.out_cfg.TargetRectRight = width - 1;
+ vic_cfg.out_cfg.TargetRectTop = 0;
+ vic_cfg.out_cfg.TargetRectBottom = height - 1;
+
+ // Initialize slot parameters.
+ vic_cfg.slots[0].slot_cfg.SlotEnable = 1;
+ vic_cfg.slots[0].slot_cfg.SoftClampLow = SOFT_CLAMP_MIN;
+ vic_cfg.slots[0].slot_cfg.SoftClampHigh = SOFT_CLAMP_MAX;
+ vic_cfg.slots[0].slot_cfg.PlanarAlpha = ALPHA_1_0;
+ vic_cfg.slots[0].slot_cfg.ConstantAlpha = const_alpha;
+ vic_cfg.slots[0].slot_cfg.FrameFormat = FORMAT_PROGRESSIVE;
+
+ // Set input source rectangle.
+ vic_cfg.slots[0].slot_cfg.SourceRectLeft = 0;
+ vic_cfg.slots[0].slot_cfg.SourceRectRight = (width - 1) << 16;
+ vic_cfg.slots[0].slot_cfg.SourceRectTop = 0;
+ vic_cfg.slots[0].slot_cfg.SourceRectBottom = (height - 1) << 16;
+
+ // Set input destination rectangle.
+ vic_cfg.slots[0].slot_cfg.DestRectLeft = 0;
+ vic_cfg.slots[0].slot_cfg.DestRectRight = (width - 1);
+ vic_cfg.slots[0].slot_cfg.DestRectTop = 0;
+ vic_cfg.slots[0].slot_cfg.DestRectBottom = (height - 1);
+
+ // Set input surface format.
+ vic_cfg.slots[0].slot_sfc_cfg.SlotPixelFormat = pix_fmt;
+ vic_cfg.slots[0].slot_sfc_cfg.SlotBlkKind = BLK_KIND_PITCH;
+ vic_cfg.slots[0].slot_sfc_cfg.SlotBlkHeight = 0;
+ vic_cfg.slots[0].slot_sfc_cfg.SlotCacheWidth = CACHE_WIDTH_64BX4;
+
+ // Set input surface resolution.
+ vic_cfg.slots[0].slot_sfc_cfg.SlotSurfaceWidth = width - 1;
+ vic_cfg.slots[0].slot_sfc_cfg.SlotSurfaceHeight = height - 1;
+ vic_cfg.slots[0].slot_sfc_cfg.SlotLumaWidth = width - 1;
+ vic_cfg.slots[0].slot_sfc_cfg.SlotLumaHeight = height - 1;
+
+ // Flush data.
+ bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false);
+
+ // Set parameters base and size. Causes a parse by surface cache.
+ _vic_write_priv(VIC_SC_PRAMBASE, (u32)&vic_cfg >> 8);
+ _vic_write_priv(VIC_SC_PRAMSIZE, sizeof(vic_config_t) >> 6);
+
+ // Wait for surface cache to get ready.
+ _vic_wait_idle();
+
+ // Set slot mapping.
+ _vic_write_priv(VIC_FC_SLOT_MAP, 0xFFFFFFF0);
+
+ // Set input surface buffer.
+ _vic_write_priv(VIC_SC_SFC0_BASE_LUMA(0), src_buf >> 8);
+
+ // Set output surface buffer.
+ _vic_write_priv(VIC_BL_TARGET_BASADR, dst_buf >> 8);
+
+ // Set blending config and push changes to surface cache.
+ _vic_write_priv(VIC_BL_CONFIG, SLOTMASK(0x1F) | PROCESS_CFG_STRUCT_TRIGGER | SUBPARTITION_MODE);
+
+ // Wait for surface cache to get ready.
+ _vic_wait_idle();
+}
+
+int vic_compose()
+{
+ // Wait for surface cache to get ready. Otherwise VIC will hang.
+ int res = _vic_wait_idle();
+
+ // Start composition of a single frame.
+ _vic_write_priv(VIC_FC_COMPOSE, COMPOSE_START);
+
+ return res;
+}
+
+int vic_init()
+{
+ clock_enable_vic();
+
+ // Load Fetch Control Engine microcode.
+ for (u32 i = 0; i < sizeof(vic_fce_ucode) / sizeof(u32); i++)
+ {
+ _vic_write_priv(VIC_FC_FCE_UCODE_ADDR, (i * sizeof(u32)));
+ _vic_write_priv(VIC_FC_FCE_UCODE_INST, *(u32 *)&vic_fce_ucode[i * sizeof(u32)]);
+ }
+
+ // Start Fetch Control Engine.
+ _vic_write_priv(VIC_FC_FCE_CTRL, START_TRIGGER);
+
+ return _vic_wait_idle();
+}
+
+void vic_end()
+{
+ clock_disable_vic();
+}
diff --git a/bdk/display/vic.h b/bdk/display/vic.h
new file mode 100644
index 0000000..20fbe6c
--- /dev/null
+++ b/bdk/display/vic.h
@@ -0,0 +1,66 @@
+/*
+ * VIC driver for Tegra X1
+ *
+ * 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 .
+ */
+
+#ifndef _VIC_H_
+#define _VIC_H_
+
+#include
+
+#define VIC_THI_SLCG_OVERRIDE_LOW_A 0x8C
+
+typedef enum _vic_rotation_t
+{
+ VIC_ROTATION_0 = 0,
+ VIC_ROTATION_90 = 1,
+ VIC_ROTATION_180 = 2,
+ VIC_ROTATION_270 = 3,
+} vic_rotation_t;
+
+typedef enum _vic_pix_format_t
+{
+ VIC_PIX_FORMAT_L8 = 1, // 8-bit LUT.
+ VIC_PIX_FORMAT_X1B5G5R5 = 21, // 16-bit XBGR.
+ VIC_PIX_FORMAT_B5G5R5X1 = 23, // 16-bit BGRX.
+
+ VIC_PIX_FORMAT_A8B8G8R8 = 31, // 32-bit ABGR.
+ VIC_PIX_FORMAT_A8R8G8B8 = 32, // 32-bit ARGB.
+ VIC_PIX_FORMAT_B8G8R8A8 = 33, // 32-bit BGRA.
+ VIC_PIX_FORMAT_R8G8B8A8 = 34, // 32-bit RGBA.
+
+ VIC_PIX_FORMAT_X8B8G8R8 = 35, // 32-bit XBGR.
+ VIC_PIX_FORMAT_X8R8G8B8 = 36, // 32-bit XRGB.
+ VIC_PIX_FORMAT_B8G8R8X8 = 37, // 32-bit BGRX.
+ VIC_PIX_FORMAT_R8G8B8X8 = 38, // 32-bit RGBX.
+} vic_pix_format_t;
+
+typedef struct _vic_surface_t
+{
+ u32 src_buf;
+ u32 dst_buf;
+ u32 width;
+ u32 height;
+ u32 pix_fmt;
+ u32 rotation;
+} vic_surface_t;
+
+void vic_set_surface(const vic_surface_t *sfc);
+int vic_compose();
+int vic_init();
+void vic_end();
+
+#endif
diff --git a/bdk/exception_handlers.S b/bdk/exception_handlers.S
new file mode 100644
index 0000000..2f38bb3
--- /dev/null
+++ b/bdk/exception_handlers.S
@@ -0,0 +1,239 @@
+/*
+ * 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 .
+ */
+
+/*
+ * 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 FIQ stack pointer */
+ MSR CPSR, #(MODE_FIQ | IRQ | FIQ) /* FIQ 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 .
+
+.globl excp_reset
+.type excp_reset, %function
+excp_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 excp_reset
+
+_undefined_handler:
+ LDR R0, =EXCP_TYPE_ADDR
+ LDR R1, =0x464455 /* UDF */
+ STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
+ B excp_reset
+
+_prefetch_abort_handler:
+ LDR R0, =EXCP_TYPE_ADDR
+ LDR R1, =0x54424150 /* PABT */
+ STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
+ B excp_reset
+
+_data_abort_handler:
+ LDR R0, =EXCP_TYPE_ADDR
+ LDR R1, =0x54424144 /* DABT */
+ STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
+ B excp_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
diff --git a/bootloader/hos/sept.h b/bdk/fatfs_cfg.h
similarity index 68%
rename from bootloader/hos/sept.h
rename to bdk/fatfs_cfg.h
index 8cfc8af..77b26dd 100644
--- a/bootloader/hos/sept.h
+++ b/bdk/fatfs_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 CTCaer
+ * 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,
@@ -14,12 +14,15 @@
* along with this program. If not, see .
*/
-#ifndef _SEPT_H_
-#define _SEPT_H_
+#ifndef _FATFS_CFG_H_
+#define _FATFS_CFG_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);
+// define FFCFG_INC in a project to use a specific FatFS configuration.
+// Example: FFCFG_INC := '"../$(PROJECT_DIR)/libs/fatfs/ffconf.h"'
+#ifdef FFCFG_INC
+#include FFCFG_INC
+#else
+#include "fatfs_conf.h"
+#endif
#endif
diff --git a/bdk/fatfs_conf.h b/bdk/fatfs_conf.h
new file mode 100644
index 0000000..e87219d
--- /dev/null
+++ b/bdk/fatfs_conf.h
@@ -0,0 +1,305 @@
+/*---------------------------------------------------------------------------/
+/ FatFs Functional Configurations
+/---------------------------------------------------------------------------*/
+
+#define FFCONF_DEF 86604 /* Revision ID */
+
+/*---------------------------------------------------------------------------/
+/ Function Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_FS_READONLY 0
+/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
+/ Read-only configuration removes writing API functions, f_write(), f_sync(),
+/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
+/ and optional writing functions as well. */
+
+
+#define FF_FS_MINIMIZE 0
+/* This option defines minimization level to remove some basic API functions.
+/
+/ 0: Basic functions are fully enabled.
+/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
+/ are removed.
+/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
+/ 3: f_lseek() function is removed in addition to 2. */
+
+
+#define FF_USE_STRFUNC 2
+/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
+/
+/ 0: Disable string functions.
+/ 1: Enable without LF-CRLF conversion.
+/ 2: Enable with LF-CRLF conversion. */
+
+
+#define FF_USE_FIND 1
+/* This option switches filtered directory read functions, f_findfirst() and
+/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
+
+
+#define FF_USE_MKFS 0
+/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
+
+#if FF_USE_MKFS
+#define FF_MKFS_LABEL "SWITCH SD "
+#endif
+/* This sets FAT/FAT32 label. Exactly 11 characters, all caps. */
+
+
+#define FF_USE_FASTSEEK 0
+/* This option switches fast seek function. (0:Disable or 1:Enable) */
+
+#define FF_FASTFS 0
+#if FF_FASTFS
+#undef FF_USE_FASTSEEK
+#define FF_USE_FASTSEEK 1
+#endif
+/* This option switches fast access to chained clusters. (0:Disable or 1:Enable) */
+
+
+#define FF_SIMPLE_GPT 1
+/* This option switches support for the first GPT partition. (0:Disable or 1:Enable) */
+
+
+#define FF_USE_EXPAND 0
+/* This option switches f_expand function. (0:Disable or 1:Enable) */
+
+
+#define FF_USE_CHMOD 1
+/* This option switches attribute manipulation functions, f_chmod() and f_utime().
+/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
+
+
+#define FF_USE_LABEL 0
+/* This option switches volume label functions, f_getlabel() and f_setlabel().
+/ (0:Disable or 1:Enable) */
+
+
+#define FF_USE_FORWARD 0
+/* This option switches f_forward() function. (0:Disable or 1:Enable) */
+
+
+/*---------------------------------------------------------------------------/
+/ Locale and Namespace Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_CODE_PAGE 850
+/* This option specifies the OEM code page to be used on the target system.
+/ Incorrect code page setting can cause a file open failure.
+/
+/ 437 - U.S.
+/ 720 - Arabic
+/ 737 - Greek
+/ 771 - KBL
+/ 775 - Baltic
+/ 850 - Latin 1
+/ 852 - Latin 2
+/ 855 - Cyrillic
+/ 857 - Turkish
+/ 860 - Portuguese
+/ 861 - Icelandic
+/ 862 - Hebrew
+/ 863 - Canadian French
+/ 864 - Arabic
+/ 865 - Nordic
+/ 866 - Russian
+/ 869 - Greek 2
+/ 932 - Japanese (DBCS)
+/ 936 - Simplified Chinese (DBCS)
+/ 949 - Korean (DBCS)
+/ 950 - Traditional Chinese (DBCS)
+/ 0 - Include all code pages above and configured by f_setcp()
+*/
+
+
+#define FF_USE_LFN 3
+#define FF_MAX_LFN 255
+/* The FF_USE_LFN switches the support for LFN (long file name).
+/
+/ 0: Disable LFN. FF_MAX_LFN has no effect.
+/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
+/ 2: Enable LFN with dynamic working buffer on the STACK.
+/ 3: Enable LFN with dynamic working buffer on the HEAP.
+/
+/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
+/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
+/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
+/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
+/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
+/ specification.
+/ When use stack for the working buffer, take care on stack overflow. When use heap
+/ memory for the working buffer, memory management functions, ff_memalloc() and
+/ ff_memfree() in ffsystem.c, need to be added to the project. */
+
+
+#define FF_LFN_UNICODE 0
+/* This option switches the character encoding on the API when LFN is enabled.
+/
+/ 0: ANSI/OEM in current CP (TCHAR = char)
+/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
+/ 2: Unicode in UTF-8 (TCHAR = char)
+/ 3: Unicode in UTF-32 (TCHAR = DWORD)
+/
+/ Also behavior of string I/O functions will be affected by this option.
+/ When LFN is not enabled, this option has no effect. */
+
+
+#define FF_LFN_BUF 255
+#define FF_SFN_BUF 12
+/* This set of options defines size of file name members in the FILINFO structure
+/ which is used to read out directory items. These values should be suffcient for
+/ the file names to read. The maximum possible length of the read file name depends
+/ on character encoding. When LFN is not enabled, these options have no effect. */
+
+
+#define FF_STRF_ENCODE 0
+/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
+/ f_putc(), f_puts and f_printf() convert the character encoding in it.
+/ This option selects assumption of character encoding ON THE FILE to be
+/ read/written via those functions.
+/
+/ 0: ANSI/OEM in current CP
+/ 1: Unicode in UTF-16LE
+/ 2: Unicode in UTF-16BE
+/ 3: Unicode in UTF-8
+*/
+
+
+#define FF_FS_RPATH 0
+/* This option configures support for relative path.
+/
+/ 0: Disable relative path and remove related functions.
+/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
+/ 2: f_getcwd() function is available in addition to 1.
+*/
+
+
+/*---------------------------------------------------------------------------/
+/ Drive/Volume Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_VOLUMES 1
+/* Number of volumes (logical drives) to be used. (1-10) */
+
+
+#define FF_STR_VOLUME_ID 0
+#define FF_VOLUME_STRS "sd"
+/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
+/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
+/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
+/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
+/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
+/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
+/ not defined, a user defined volume string table needs to be defined as:
+/
+/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
+/ Order is important. Any change to order, must also be reflected to diskio drive enum.
+*/
+
+
+#define FF_MULTI_PARTITION 0
+/* This option switches support for multiple volumes on the physical drive.
+/ By default (0), each logical drive number is bound to the same physical drive
+/ number and only an FAT volume found on the physical drive will be mounted.
+/ When this function is enabled (1), each logical drive number can be bound to
+/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
+/ funciton will be available. */
+
+
+#define FF_MIN_SS 512
+#define FF_MAX_SS 512
+/* This set of options configures the range of sector size to be supported. (512,
+/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
+/ harddisk. But a larger value may be required for on-board flash memory and some
+/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
+/ for variable sector size mode and disk_ioctl() function needs to implement
+/ GET_SECTOR_SIZE command. */
+
+
+#define FF_USE_TRIM 0
+/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
+/ To enable Trim function, also CTRL_TRIM command should be implemented to the
+/ disk_ioctl() function. */
+
+
+#define FF_FS_NOFSINFO 1
+/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
+/ option, and f_getfree() function at first time after volume mount will force
+/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
+/
+/ bit0=0: Use free cluster count in the FSINFO if available.
+/ bit0=1: Do not trust free cluster count in the FSINFO.
+/ bit1=0: Use last allocated cluster number in the FSINFO if available.
+/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
+*/
+
+
+
+/*---------------------------------------------------------------------------/
+/ System Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_FS_TINY 0
+/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
+/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
+/ Instead of private sector buffer eliminated from the file object, common sector
+/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
+
+
+#define FF_FS_EXFAT 1
+/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
+/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
+/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
+
+
+#define FF_FS_NORTC 1
+#define FF_NORTC_MON 1
+#define FF_NORTC_MDAY 1
+#define FF_NORTC_YEAR 2022
+/* The option FF_FS_NORTC switches timestamp function. If the system does not have
+/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
+/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
+/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
+/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
+/ added to the project to read current time form real-time clock. FF_NORTC_MON,
+/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
+/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */
+
+
+#define FF_FS_LOCK 0
+/* The option FF_FS_LOCK switches file lock function to control duplicated file open
+/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
+/ is 1.
+/
+/ 0: Disable file lock function. To avoid volume corruption, application program
+/ should avoid illegal open, remove and rename to the open objects.
+/ >0: Enable file lock function. The value defines how many files/sub-directories
+/ can be opened simultaneously under file lock control. Note that the file
+/ lock control is independent of re-entrancy. */
+
+
+/* #include // O/S definitions */
+#define FF_FS_REENTRANT 0
+#define FF_FS_TIMEOUT 1000
+#define FF_SYNC_t HANDLE
+/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
+/ module itself. Note that regardless of this option, file access to different
+/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
+/ and f_fdisk() function, are always not re-entrant. Only file/directory access
+/ to the same volume is under control of this function.
+/
+/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
+/ 1: Enable re-entrancy. Also user provided synchronization handlers,
+/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
+/ function, must be added to the project. Samples are available in
+/ option/syscall.c.
+/
+/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
+/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
+/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
+/ included somewhere in the scope of ff.h. */
+
+
+
+/*--- End of configuration options ---*/
diff --git a/nyx/nyx_gui/soc/cluster.h b/bdk/gfx_utils.h
similarity index 81%
rename from nyx/nyx_gui/soc/cluster.h
rename to bdk/gfx_utils.h
index 428c046..ca81a7f 100644
--- a/nyx/nyx_gui/soc/cluster.h
+++ b/bdk/gfx_utils.h
@@ -1,5 +1,5 @@
/*
- * 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,
@@ -14,11 +14,11 @@
* along with this program. If not, see .
*/
-#ifndef _CLUSTER_H_
-#define _CLUSTER_H_
+#ifndef _GFX_UTILS_H_
+#define _GFX_UTILS_H_
-#include "../utils/types.h"
-
-void cluster_boot_cpu0(u32 entry);
+#ifdef GFX_INC
+#include GFX_INC
+#endif
#endif
diff --git a/nyx/nyx_gui/libs/elfload/elf.h b/bdk/ianos/elfload/elf.h
similarity index 96%
rename from nyx/nyx_gui/libs/elfload/elf.h
rename to bdk/ianos/elfload/elf.h
index 196cf87..2a7111e 100644
--- a/nyx/nyx_gui/libs/elfload/elf.h
+++ b/bdk/ianos/elfload/elf.h
@@ -29,33 +29,34 @@
#ifndef ELF_H
#define ELF_H
-#include
-typedef uint8_t Elf_Byte;
+#include
-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 u8 Elf_Byte;
-typedef uint64_t Elf64_Addr;
-typedef uint64_t Elf64_Off;
-typedef int32_t Elf64_Shalf;
+typedef u32 Elf32_Addr; /* Unsigned program address */
+typedef u32 Elf32_Off; /* Unsigned file offset */
+typedef s32 Elf32_Sword; /* Signed large integer */
+typedef u32 Elf32_Word; /* Unsigned large integer */
+typedef u16 Elf32_Half; /* Unsigned medium integer */
+
+typedef u64 Elf64_Addr;
+typedef u64 Elf64_Off;
+typedef s32 Elf64_Shalf;
#ifdef __alpha__
-typedef int64_t Elf64_Sword;
-typedef uint64_t Elf64_Word;
+typedef s64 Elf64_Sword;
+typedef u64 Elf64_Word;
#else
-typedef int32_t Elf64_Sword;
-typedef uint32_t Elf64_Word;
+typedef s32 Elf64_Sword;
+typedef u32 Elf64_Word;
#endif
-typedef int64_t Elf64_Sxword;
-typedef uint64_t Elf64_Xword;
+typedef s64 Elf64_Sxword;
+typedef u64 Elf64_Xword;
-typedef uint32_t Elf64_Half;
-typedef uint16_t Elf64_Quarter;
+typedef u32 Elf64_Half;
+typedef u16 Elf64_Quarter;
/*
* e_ident[] identification indexes
@@ -376,7 +377,7 @@ typedef struct
#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))
+#define ELF64_R_INFO(s, t) (((s) << 32) + (u32)(t))
#if defined(__mips64__) && defined(__MIPSEL__)
/*
@@ -389,7 +390,7 @@ typedef struct
#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))
+#define ELF64_R_INFO(s, t) (((u64)swap32(t) << 32) + (u32)(s))
#endif /* __mips64__ && __MIPSEL__ */
/* Program Header */
@@ -444,7 +445,7 @@ typedef struct
/* Dynamic structure */
typedef struct
{
- Elf32_Sword d_tag; /* controls meaning of d_val */
+ Elf32_Word d_tag; /* controls meaning of d_val */
union {
Elf32_Word d_val; /* Multiple meanings - see d_tag */
Elf32_Addr d_ptr; /* program virtual address */
diff --git a/bootloader/libs/elfload/elfarch.h b/bdk/ianos/elfload/elfarch.h
similarity index 100%
rename from bootloader/libs/elfload/elfarch.h
rename to bdk/ianos/elfload/elfarch.h
diff --git a/bootloader/libs/elfload/elfload.c b/bdk/ianos/elfload/elfload.c
similarity index 95%
rename from bootloader/libs/elfload/elfload.c
rename to bdk/ianos/elfload/elfload.c
index 16f8200..daf561a 100644
--- a/bootloader/libs/elfload/elfload.c
+++ b/bdk/ianos/elfload/elfload.c
@@ -25,7 +25,7 @@ el_status el_pread(el_ctx *ctx, void *def, size_t nb, size_t offset)
}
#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 el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, u32 type, unsigned *i)
{
el_status rv = EL_OK;
for (; *i < ctx->ehdr.e_phnum; (*i)++)
@@ -44,7 +44,7 @@ el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i)
}
#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 el_findshdr(el_ctx *ctx, Elf_Shdr *shdr, u32 type, unsigned *i)
{
el_status rv = EL_OK;
@@ -213,7 +213,7 @@ el_status el_load(el_ctx *ctx, el_alloc_cb alloc)
return rv;
}
-el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t tag)
+el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, u32 tag)
{
el_status rv = EL_OK;
size_t ndyn = ctx->dynsize / sizeof(Elf_Dyn);
@@ -231,7 +231,7 @@ el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t tag)
return EL_OK;
}
-el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type)
+el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, u32 type)
{
el_status rv = EL_OK;
diff --git a/nyx/nyx_gui/libs/elfload/elfload.h b/bdk/ianos/elfload/elfload.h
similarity index 90%
rename from nyx/nyx_gui/libs/elfload/elfload.h
rename to bdk/ianos/elfload/elfload.h
index 3a15dc2..0a73e05 100644
--- a/nyx/nyx_gui/libs/elfload/elfload.h
+++ b/bdk/ianos/elfload/elfload.h
@@ -22,10 +22,8 @@
#include "elfarch.h"
#include "elf.h"
-#include "../../utils/types.h"
-
#ifdef DEBUG
-#include "../../gfx/gfx.h"
+#include
#define EL_DEBUG(format, ...) \
gfx_printf(format __VA_OPT__(, ) __VA_ARGS__)
#else
@@ -100,7 +98,7 @@ el_status el_load(el_ctx *ctx, el_alloc_cb alloccb);
* 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);
+el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, u32 type, unsigned *i);
/* Relocate the loaded executable */
el_status el_relocate(el_ctx *ctx);
@@ -108,7 +106,7 @@ 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);
+el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, u32 type);
typedef struct
{
@@ -122,6 +120,6 @@ typedef struct
* 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);
+el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, u32 type);
#endif
diff --git a/nyx/nyx_gui/libs/elfload/elfreloc_aarch64.c b/bdk/ianos/elfload/elfreloc_aarch64.c
similarity index 85%
rename from nyx/nyx_gui/libs/elfload/elfreloc_aarch64.c
rename to bdk/ianos/elfload/elfreloc_aarch64.c
index bbb0ce4..736ad46 100644
--- a/nyx/nyx_gui/libs/elfload/elfreloc_aarch64.c
+++ b/bdk/ianos/elfload/elfreloc_aarch64.c
@@ -23,9 +23,9 @@
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);
+ uptr *p = (uptr *)(rel->r_offset + ctx->base_load_paddr);
+ u32 type = ELF_R_TYPE(rel->r_info);
+ u32 sym = ELF_R_SYM(rel->r_info);
switch (type)
{
@@ -53,9 +53,9 @@ el_status el_applyrela(el_ctx *ctx, Elf_RelA *rel)
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);
+ uptr *p = (uptr *)(rel->r_offset + ctx->base_load_paddr);
+ u32 type = ELF_R_TYPE(rel->r_info);
+ u32 sym = ELF_R_SYM(rel->r_info);
switch (type)
{
diff --git a/nyx/nyx_gui/libs/elfload/elfreloc_arm.c b/bdk/ianos/elfload/elfreloc_arm.c
similarity index 86%
rename from nyx/nyx_gui/libs/elfload/elfreloc_arm.c
rename to bdk/ianos/elfload/elfreloc_arm.c
index 8b905cb..77ce654 100644
--- a/nyx/nyx_gui/libs/elfload/elfreloc_arm.c
+++ b/bdk/ianos/elfload/elfreloc_arm.c
@@ -20,9 +20,9 @@
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
+ u32 sym = ELF_R_SYM(rel->r_info); // Symbol offset
+ u32 type = ELF_R_TYPE(rel->r_info); // Relocation Type
+ uptr *p = (uptr *)(rel->r_offset + ctx->base_load_paddr); // Target Addr
#if 0 // For later symbol usage
Elf32_Sym *elfSym;
diff --git a/bootloader/ianos/ianos.c b/bdk/ianos/ianos.c
similarity index 77%
rename from bootloader/ianos/ianos.c
rename to bdk/ianos/ianos.c
index 18d4165..99a996d 100644
--- a/bootloader/ianos/ianos.c
+++ b/bdk/ianos/ianos.c
@@ -18,33 +18,36 @@
#include
#include "ianos.h"
-#include "../utils/types.h"
-#include "../libs/elfload/elfload.h"
-#include "../../common/common_module.h"
-#include "../mem/heap.h"
-#include "../gfx/gfx.h"
+#include "elfload/elfload.h"
+#include
+#include
+#include
+#include
+#include
+
+#include
#define IRAM_LIB_ADDR 0x4002B000
#define DRAM_LIB_ADDR 0xE0000000
extern heap_t _heap;
-extern void *sd_file_read(const char *path, u32 *fsize);
-extern bool sd_mount();
-extern void sd_unmount();
-
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->gfxCon = (void *)&gfx_con;
+ bdkParameters->gfxCtx = (void *)&gfx_ctxt;
bdkParameters->memcpy = (memcpy_t)&memcpy;
bdkParameters->memset = (memset_t)&memset;
bdkParameters->sharedHeap = &_heap;
+ // Extra functions.
+ bdkParameters->extension_magic = IANOS_EXT0;
+ bdkParameters->reg_voltage_set = (reg_voltage_set_t)&max7762x_regulator_set_voltage;
+
entrypoint(moduleConfig, bdkParameters);
}
@@ -66,30 +69,21 @@ static bool _ianos_read_cb(el_ctx *ctx, void *dest, size_t numberBytes, size_t o
}
//TODO: Support shared libraries.
-uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void *moduleConfig)
+uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig)
{
+ el_ctx ctx;
uintptr_t epaddr = 0;
- if (sdmount)
- {
- if (!sd_mount())
- goto elfLoadFinalOut;
- }
-
+ // Read library.
fileBuf = sd_file_read(path, NULL);
- if (sdmount)
- sd_unmount();
-
if (!fileBuf)
- goto elfLoadFinalOut;
+ goto out;
-
- el_ctx ctx;
ctx.pread = _ianos_read_cb;
if (el_init(&ctx))
- goto elfLoadFinalOut;
+ goto out;
// Set our relocated library's buffer.
switch (type & 0xFFFF)
@@ -97,22 +91,21 @@ uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void *moduleCon
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;
+ goto out;
// Load and relocate library.
ctx.base_load_vaddr = ctx.base_load_paddr = (uintptr_t)elfBuf;
if (el_load(&ctx, _ianos_alloc_cb))
- goto elfFreeOut;
+ goto out_free;
if (el_relocate(&ctx))
- goto elfFreeOut;
+ goto out_free;
// Launch.
epaddr = ctx.ehdr.e_entry + (uintptr_t)elfBuf;
@@ -120,12 +113,11 @@ uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void *moduleCon
_ianos_call_ep(ep, moduleConfig);
-elfFreeOut:
+out_free:
free(fileBuf);
elfBuf = NULL;
fileBuf = NULL;
-elfLoadFinalOut:
-
+out:
return epaddr;
}
\ No newline at end of file
diff --git a/nyx/nyx_gui/ianos/ianos.h b/bdk/ianos/ianos.h
similarity index 89%
rename from nyx/nyx_gui/ianos/ianos.h
rename to bdk/ianos/ianos.h
index 74d02c1..5ebec64 100644
--- a/nyx/nyx_gui/ianos/ianos.h
+++ b/bdk/ianos/ianos.h
@@ -18,7 +18,7 @@
#ifndef IANOS_H
#define IANOS_H
-#include "../utils/types.h"
+#include
typedef enum
{
@@ -29,6 +29,6 @@ typedef enum
KEEP_IN_RAM = (1 << 31) // Shared library mask.
} elfType_t;
-uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void* config);
+uintptr_t ianos_loader(char *path, elfType_t type, void* config);
#endif
\ No newline at end of file
diff --git a/bdk/input/als.c b/bdk/input/als.c
new file mode 100644
index 0000000..277f0d5
--- /dev/null
+++ b/bdk/input/als.c
@@ -0,0 +1,154 @@
+/*
+ * Ambient light sensor driver for Nintendo Switch's Rohm BH1730
+ *
+ * Copyright (c) 2018 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "als.h"
+#include
+#include
+#include
+#include
+#include
+
+#define BH1730_DEFAULT_GAIN BH1730_GAIN_64X
+#define BH1730_DEFAULT_ICYCLE 38
+
+#define BH1730_INTERNAL_CLOCK_NS 2800
+#define BH1730_ADC_CALC_DELAY_US 2000 /* BH1730_INTERNAL_CLOCK_MS * 714 */
+#define BH1730_ITIME_CYCLE_TO_US 2700 /* BH1730_INTERNAL_CLOCK_MS * 964 */
+
+#define BH1730_DEFAULT_ITIME_MS 100
+
+#define BH1730_LUX_MULTIPLIER 3600
+#define BH1730_LUX_MULTIPLIER_AULA 1410
+
+#define BH1730_LUX_MAX 100000
+
+typedef struct _opt_win_cal_t
+{
+ u32 rc;
+ u32 cv;
+ u32 ci;
+} opt_win_cal_t;
+
+// Nintendo Switch Icosa/Iowa Optical Window calibration.
+static const opt_win_cal_t opt_win_cal_default[] = {
+ { 500, 5002, 7502 },
+ { 754, 2250, 2000 },
+ { 1029, 1999, 1667 },
+ { 1373, 884, 583 },
+ { 1879, 309, 165 }
+};
+
+// Nintendo Switch Aula Optical Window calibration.
+static const opt_win_cal_t opt_win_cal_aula[] = {
+ { 231, 9697, 30300 },
+ { 993, 3333, 2778 },
+ { 1478, 1621, 1053 },
+ { 7500, 81, 10 }
+};
+
+static const u32 als_gain_idx_tbl[4] = { 1, 2, 64, 128 };
+
+void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
+{
+ if (gain > BH1730_GAIN_128X)
+ gain = BH1730_GAIN_128X;
+
+ if (!cycle)
+ cycle = 1;
+
+ i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
+ i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle));
+
+ als_ctxt->gain = gain;
+ als_ctxt->cycle = cycle;
+}
+
+void get_als_lux(als_ctxt_t *als_ctxt)
+{
+ u32 data[2];
+ u32 vi_light;
+ u32 ir_light;
+ u64 lux = 0;
+ u32 itime_us = BH1730_ITIME_CYCLE_TO_US * als_ctxt->cycle;
+
+ // Get visible and ir light raw data. Mode is continuous so waiting for new values doesn't matter.
+ data[0] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0LOW_REG)) +
+ (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8);
+ data[1] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1LOW_REG)) +
+ (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8);
+
+ vi_light = data[0];
+ ir_light = data[1];
+
+ als_ctxt->vi_light = vi_light;
+ als_ctxt->ir_light = ir_light;
+ als_ctxt->over_limit = vi_light > 65534 || ir_light > 65534;
+
+ if (!vi_light)
+ {
+ als_ctxt->lux = 0;
+
+ return;
+ }
+
+ // Set calibration parameters.
+ u32 lux_multiplier = BH1730_LUX_MULTIPLIER;
+ u32 opt_win_cal_count = ARRAY_SIZE(opt_win_cal_default);
+ const opt_win_cal_t *opt_win_cal = opt_win_cal_default;
+
+ // Apply optical window calibration coefficients.
+ for (u32 i = 0; i < opt_win_cal_count; i++)
+ {
+ if (1000 * ir_light / vi_light < opt_win_cal[i].rc)
+ {
+ lux = ((u64)opt_win_cal[i].cv * data[0]) - (opt_win_cal[i].ci * data[1]);
+ break;
+ }
+ }
+
+ lux *= BH1730_DEFAULT_ITIME_MS * lux_multiplier;
+ lux /= als_gain_idx_tbl[als_ctxt->gain] * itime_us;
+ lux /= 1000;
+
+ if (lux > BH1730_LUX_MAX)
+ lux = BH1730_LUX_MAX;
+
+ als_ctxt->lux = lux;
+}
+
+u8 als_power_on(als_ctxt_t *als_ctxt)
+{
+ // Enable power to ALS IC.
+ max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
+ max7762x_regulator_enable(REGULATOR_LDO6, true);
+
+ // Init I2C2.
+ pinmux_config_i2c(I2C_2);
+ clock_enable_i2c(I2C_2);
+ i2c_init(I2C_2);
+
+ // Initialize ALS.
+ u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12));
+ i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0);
+
+ set_als_cfg(als_ctxt, BH1730_DEFAULT_GAIN, BH1730_DEFAULT_ICYCLE);
+
+ i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG), BH1730_CTL_POWER_ON | BH1730_CTL_ADC_EN);
+
+ return id;
+}
diff --git a/nyx/nyx_gui/input/als.h b/bdk/input/als.h
similarity index 84%
rename from nyx/nyx_gui/input/als.h
rename to bdk/input/als.h
index 11f1e5e..0ce0956 100644
--- a/nyx/nyx_gui/input/als.h
+++ b/bdk/input/als.h
@@ -19,7 +19,7 @@
#ifndef __ALS_H_
#define __ALS_H_
-#include "../utils/types.h"
+#include
#define BH1730_I2C_ADDR 0x29
@@ -45,21 +45,21 @@
#define BH1730_DATA1LOW_REG 0x16
#define BH1730_DATA1HIGH_REG 0x17
-#define BH1730_ADDR(reg) (BH1730_CMD_MAGIC | BH1730_CMD_SETADDR | reg)
-#define BH1730_SPEC(cmd) (BH1730_CMD_MAGIC | BH1730_CMD_SPECCMD | cmd)
+#define BH1730_ADDR(reg) (BH1730_CMD_MAGIC | BH1730_CMD_SETADDR | (reg))
+#define BH1730_SPEC(cmd) (BH1730_CMD_MAGIC | BH1730_CMD_SPECCMD | (cmd))
-typedef struct _als_table_t
+typedef struct _als_ctxt_t
{
- float lux;
+ u32 lux;
bool over_limit;
- u32 vi_light;
- u32 ir_light;
- u8 gain;
- u8 itime;
-} als_table_t;
+ u32 vi_light;
+ u32 ir_light;
+ u8 gain;
+ u8 cycle;
+} als_ctxt_t;
-void set_als_cfg(als_table_t *als_val, u8 gain, u8 itime);
-void get_als_lux(als_table_t *als_val);
-u8 als_init(als_table_t *als_val);
+void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle);
+void get_als_lux(als_ctxt_t *als_ctxt);
+u8 als_power_on(als_ctxt_t *als_ctxt);
#endif /* __ALS_H_ */
diff --git a/bdk/input/joycon.c b/bdk/input/joycon.c
new file mode 100644
index 0000000..5e3243e
--- /dev/null
+++ b/bdk/input/joycon.c
@@ -0,0 +1,1274 @@
+/*
+ * Joy-Con UART driver for Nintendo Switch
+ *
+ * Copyright (c) 2019-2024 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 .
+ */
+
+#include
+
+#include "joycon.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// For disabling driver when logging is enabled.
+#include
+
+#define JC_WIRED_CMD 0x91
+#define JC_WIRED_HID 0x92
+#define JC_WIRED_INIT_REPLY 0x94
+#define JC_INIT_HANDSHAKE 0xA5
+
+#define JC_HORI_INPUT_RPT_CMD 0x9A
+#define JC_HORI_INPUT_RPT 0x00
+
+#define JC_WIRED_CMD_GET_INFO 0x01
+#define JC_WIRED_CMD_SET_CHARGER 0x02
+#define JC_WIRED_CMD_GET_CHARGER 0x03
+#define JC_WIRED_CMD_BATT_VOLT 0x06
+#define JC_WIRED_CMD_WAKE_REASON 0x07
+#define JC_WIRED_CMD_HID_CONN 0x10
+#define JC_WIRED_CMD_HID_DISC 0x11
+#define JC_WIRED_CMD_SET_HIDRATE 0x12 // Output report rate.
+#define JC_WIRED_CMD_SET_BRATE 0x20
+
+#define JC_HID_OUTPUT_RPT 0x01
+#define JC_HID_RUMBLE_RPT 0x10
+
+#define JC_HID_INPUT_RPT 0x30
+#define JC_HID_SUBMCD_RPT 0x21
+
+#define JC_HID_SUBCMD_HCI_STATE 0x06
+#define HCI_STATE_SLEEP 0x00
+#define HCI_STATE_RECONNECT 0x01
+#define HCI_STATE_PAIR 0x02
+#define HCI_STATE_HOME 0x04
+#define JC_HID_SUBCMD_SPI_READ 0x10
+#define SPI_READ_OFFSET 0x20
+#define JC_HID_SUBCMD_RUMBLE_CTL 0x48
+#define JC_HID_SUBCMD_SND_RUMBLE 0xFF
+
+#define JC_SIO_OUTPUT_RPT 0x91
+#define JC_SIO_INPUT_RPT 0x92
+#define JC_SIO_CMD_ACK 0x80
+
+#define JC_SIO_CMD_INIT 0x01
+#define JC_SIO_CMD_UNK02 0x02
+#define JC_SIO_CMD_VER_RPT 0x03
+#define JC_SIO_CMD_UNK20 0x20 // JC_WIRED_CMD_SET_BRATE
+#define JC_SIO_CMD_UNK21 0x21
+#define JC_SIO_CMD_UNK22 0x22
+#define JC_SIO_CMD_UNK40 0x40
+#define JC_SIO_CMD_STATUS 0x41
+#define JC_SIO_CMD_IAP_VER 0x42
+
+
+#define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status.
+#define JC_BTN_MASK_R 0x0056FF
+
+#define JC_ID_L 0x01 // Joycon (L). Mask for Hori (L).
+#define JC_ID_R 0x02 // Joycon (R). Mask for Hori (R).
+#define JC_ID_HORI 0x20 // Mask for Hori. Actual ids: 0x21, 0x22.
+
+#define JC_CRC8_POLY 0x8D
+
+enum
+{
+ JC_STATE_START = 0,
+ JC_STATE_HANDSHAKED = 1,
+ JC_STATE_BRATE_CHANGED = 2,
+ JC_STATE_BRATE_OK = 3,
+ JC_STATE_INIT_DONE = 4
+};
+
+enum
+{
+ JC_BATT_EMTPY = 0,
+ JC_BATT_CRIT = 1,
+ JC_BATT_LOW = 2,
+ JC_BATT_MID = 3,
+ JC_BATT_FULL = 4
+};
+
+static const u8 sio_init[] = {
+ JC_SIO_OUTPUT_RPT, JC_SIO_CMD_INIT,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x95
+};
+
+static const u8 sio_set_rpt_version[] = {
+ JC_SIO_OUTPUT_RPT, JC_SIO_CMD_VER_RPT,
+ // old fw: 0x00, 0x0D (0.13). New 3.4.
+ // force_update_en: 0x01
+ 0x00, 0x00, 0x03, 0x04, 0x00, 0xDA
+};
+
+// Every 8ms.
+static const u8 sio_pad_status[] = {
+ JC_SIO_OUTPUT_RPT, JC_SIO_CMD_STATUS,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0
+};
+
+static const u8 init_wake[] = {
+ 0xA1, 0xA2, 0xA3, 0xA4
+};
+
+static const u8 init_handshake[] = {
+ 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
+ JC_INIT_HANDSHAKE, 0x02, // Wired cmd and wired subcmd.
+ 0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data and crc.
+};
+
+static const u8 init_get_info[] = {
+ 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
+ JC_WIRED_CMD, JC_WIRED_CMD_GET_INFO, // Wired cmd and subcmd.
+ 0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc.
+};
+
+static const u8 init_switch_brate[] = {
+ 0x19, 0x01, 0x03, 0x0F, 0x00, // Uart header.
+ JC_WIRED_CMD, JC_WIRED_CMD_SET_BRATE, // Wired cmd and subcmd.
+ 0x08, 0x00, 0x00, 0xBD, 0xB1, // Wired subcmd data, data crc and crc.
+ // Baudrate 3 megabaud.
+ 0xC0, 0xC6, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 init_hid_disconnect[] = {
+ 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
+ JC_WIRED_CMD, JC_WIRED_CMD_HID_DISC, // Wired cmd and subcmd.
+ 0x00, 0x00, 0x00, 0x00, 0x0E // Wired subcmd data and crc.
+};
+
+static const u8 init_set_hid_rate[] = {
+ 0x19, 0x01, 0x03, 0x0B, 0x00, // Uart header.
+ JC_WIRED_CMD, JC_WIRED_CMD_SET_HIDRATE, // Wired cmd and subcmd.
+ 0x04, 0x00, 0x00, 0x12, 0xA6, // Wired subcmd data, data crc and crc.
+ // Output report rate 15 ms.
+ 0x0F, 0x00, 0x00, 0x00
+
+ // 5 ms.
+ // 0x04, 0x00, 0x00, 0x0E, 0xD5,
+ // 0x05, 0x00, 0x00, 0x00
+};
+
+static const u8 init_hid_connect[] = {
+ 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
+ JC_WIRED_CMD, JC_WIRED_CMD_HID_CONN, // Wired cmd and subcmd.
+ 0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data and crc.
+};
+
+static const u8 nx_pad_status[] = {
+ 0x19, 0x01, 0x03, 0x08, 0x00, // Uart header.
+ JC_WIRED_HID, 0x00, // Wired cmd and hid cmd.
+ 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data, data crc and crc.
+};
+
+static const u8 hori_pad_status[] = {
+ 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
+ JC_HORI_INPUT_RPT_CMD, 0x01, // Hori cmd and hori subcmd.
+ 0x00, 0x00, 0x00, 0x00, 0x48 // Hori cmd data and crc.
+};
+
+typedef struct _jc_uart_hdr_t
+{
+ u8 magic[3];
+ u8 total_size_lsb;
+ u8 total_size_msb;
+} jc_uart_hdr_t;
+
+typedef struct _jc_wired_hdr_t
+{
+ jc_uart_hdr_t uart_hdr;
+ u8 cmd;
+ u8 data[5];
+ u8 crc;
+ u8 payload[];
+} jc_wired_hdr_t;
+
+typedef struct _jc_hid_out_rpt_t
+{
+ u8 cmd;
+ u8 pkt_id;
+ u8 rumble[8];
+ u8 subcmd;
+ u8 subcmd_data[];
+} jc_hid_out_rpt_t;
+
+typedef struct _jc_hid_out_spi_read_t
+{
+ u32 addr;
+ u8 size;
+} jc_hid_out_spi_read_t;
+
+typedef struct _jc_hid_in_rpt_t
+{
+ u8 cmd;
+ u8 pkt_id;
+ u8 conn_info:4; // Connection detect.
+ u8 batt_info:4; // Power info.
+ u8 btn_right;
+ u8 btn_shared;
+ u8 btn_left;
+ u8 stick_h_left;
+ u8 stick_m_left;
+ u8 stick_v_left;
+ u8 stick_h_right;
+ u8 stick_m_right;
+ u8 stick_v_right;
+ u8 vib_decider; // right:4, left:4 (bit3 en, bit2-0 buffer avail).
+ u8 submcd_ack;
+ u8 subcmd;
+ u8 subcmd_data[];
+} jc_hid_in_rpt_t;
+
+typedef struct _jc_hid_in_spi_read_t
+{
+ u32 addr;
+ u8 size;
+ u8 data[];
+} jc_hid_in_spi_read_t;
+
+typedef struct _jc_hid_in_pair_data_t
+{
+ u8 magic;
+ u8 size;
+ u16 checksum;
+ u8 mac[6];
+ u8 ltk[16];
+ u8 pad0[10];
+ u8 bt_caps; // bit3: Secure conn supported host, bit5: Paired to TBFC supported host, bit6: iTBFC page supported
+ u8 pad1;
+} jc_hid_in_pair_data_t;
+
+typedef struct _jc_sio_out_rpt_t
+{
+ u8 cmd;
+ u8 subcmd;
+ u16 payload_size;
+ u8 data[2];
+ u8 crc_payload;
+ u8 crc_hdr;
+ u8 payload[];
+} jc_sio_out_rpt_t;
+
+typedef struct _jc_sio_in_rpt_t
+{
+ u8 cmd;
+ u8 ack;
+ u16 payload_size;
+ u8 status;
+ u8 unk;
+ u8 crc_payload;
+ u8 crc_hdr;
+ u8 payload[];
+} jc_sio_in_rpt_t;
+
+typedef struct _jc_hid_in_sixaxis_rpt_t
+{
+ s16 acc_x;
+ s16 acc_y;
+ s16 acc_z;
+ s16 gyr_x;
+ s16 gyr_y;
+ s16 gyr_z;
+} __attribute__((packed)) jc_hid_in_sixaxis_rpt_t;
+
+typedef struct _jc_sio_hid_in_rpt_t
+{
+ u8 type;
+ u8 pkt_id;
+ u8 unk;
+ u8 btn_right;
+ u8 btn_shared;
+ u8 btn_left;
+ u8 stick_h_left;
+ u8 stick_m_left;
+ u8 stick_v_left;
+ u8 stick_h_right;
+ u8 stick_m_right;
+ u8 stick_v_right;
+ u8 siaxis_rpt; // bit0-3: report num. bit4-7: imu type.
+ // Each report is 800 us?
+ jc_hid_in_sixaxis_rpt_t sixaxis[15];
+} jc_sio_hid_in_rpt_t;
+
+typedef struct _joycon_ctxt_t
+{
+ u8 buf[0x100]; //FIXME: If heap is used, dumping breaks.
+ u8 uart;
+ u8 type;
+ u8 state;
+ u32 last_received_time;
+ u32 last_status_req_time;
+ u8 mac[6];
+ u8 pkt_id;
+ u8 rumble_sent;
+ u8 connected;
+ u8 detected;
+ u8 sio_mode;
+} joycon_ctxt_t;
+
+static joycon_ctxt_t jc_l = {0};
+static joycon_ctxt_t jc_r = {0};
+
+static bool jc_init_done = false;
+
+static jc_gamepad_rpt_t jc_gamepad;
+
+static u8 _jc_crc(const u8 *data, u16 len, u8 init)
+{
+ u8 crc = init;
+ for (u16 i = 0; i < len; i++)
+ {
+ crc ^= data[i];
+ for (u16 j = 0; j < 8; j++)
+ {
+ if ((crc & 0x80) != 0)
+ crc = (u8)((crc << 1) ^ JC_CRC8_POLY);
+ else
+ crc <<= 1;
+ }
+ }
+ return crc;
+}
+
+static void _jc_power_supply(u8 uart, bool enable)
+{
+ if (enable)
+ {
+ if (regulator_5v_get_dev_enabled(1 << uart))
+ return;
+
+ regulator_5v_enable(1 << uart);
+
+ if (jc_gamepad.sio_mode)
+ return;
+
+ if (jc_init_done)
+ {
+ if (uart == UART_C)
+ gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_HIGH);
+ else
+ gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_HIGH);
+ return;
+ }
+
+ if (uart == UART_C)
+ {
+ // Joy-Con(L) Charge Enable.
+ PINMUX_AUX(PINMUX_AUX_SPDIF_IN) = PINMUX_PULL_DOWN | 1;
+ gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_3, GPIO_HIGH);
+ }
+ else
+ {
+ // Joy-Con(R) Charge Enable.
+ PINMUX_AUX(PINMUX_AUX_GPIO_PK3) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN | 2;
+ gpio_direction_output(GPIO_PORT_K, GPIO_PIN_3, GPIO_HIGH);
+ }
+ }
+ else
+ {
+ if (!regulator_5v_get_dev_enabled(1 << uart))
+ return;
+
+ regulator_5v_disable(1 << uart);
+
+ if (jc_gamepad.sio_mode)
+ return;
+
+ if (uart == UART_C)
+ gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW);
+ else
+ gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_LOW);
+ }
+}
+
+static void _jc_detect()
+{
+ if (!jc_gamepad.sio_mode)
+ {
+ // Turn on Joy-Con detect. (UARTB/C TX). UART CTS also if HW flow control and irq is enabled.
+ PINMUX_AUX(PINMUX_AUX_UART2_TX) = PINMUX_INPUT_ENABLE;
+ PINMUX_AUX(PINMUX_AUX_UART3_TX) = PINMUX_INPUT_ENABLE;
+ gpio_direction_input(GPIO_PORT_G, GPIO_PIN_0);
+ gpio_direction_input(GPIO_PORT_D, GPIO_PIN_1);
+ usleep(20);
+
+ //! HW BUG: Unlatch gpio buffer.
+ (void)gpio_read(GPIO_PORT_H, GPIO_PIN_6);
+ (void)gpio_read(GPIO_PORT_E, GPIO_PIN_6);
+
+ // Read H6/E6 which are shared with UART TX pins.
+ jc_r.detected = !gpio_read(GPIO_PORT_H, GPIO_PIN_6);
+ jc_l.detected = !gpio_read(GPIO_PORT_E, GPIO_PIN_6);
+
+ // Turn off Joy-Con detect. (UARTB/C TX).
+ PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0;
+ PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0;
+ gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
+ gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
+ usleep(20);
+ }
+ else
+ {
+ //! TODO: Is there a way to detect a broken Sio?
+ jc_l.detected = true;
+ }
+}
+
+static void _jc_conn_check()
+{
+ _jc_detect();
+
+ if (jc_gamepad.sio_mode)
+ return;
+
+ // Check if a Joy-Con was disconnected.
+ if (!jc_l.detected)
+ {
+ if (jc_l.connected)
+ _jc_power_supply(UART_C, false);
+
+ jc_l.pkt_id = 0;
+
+ jc_l.connected = false;
+ jc_l.rumble_sent = false;
+
+ jc_gamepad.conn_l = false;
+
+ jc_gamepad.batt_info_l = 0;
+ jc_gamepad.bt_conn_l.type = 0;
+ jc_gamepad.buttons &= ~JC_BTN_MASK_L;
+ }
+
+ if (!jc_r.detected)
+ {
+ if (jc_r.connected)
+ _jc_power_supply(UART_B, false);
+
+ jc_r.pkt_id = 0;
+
+ jc_r.connected = false;
+ jc_r.rumble_sent = false;
+
+ jc_gamepad.conn_r = false;
+
+ jc_gamepad.batt_info_r = 0;
+ jc_gamepad.bt_conn_r.type = 0;
+ jc_gamepad.buttons &= ~JC_BTN_MASK_R;
+ }
+}
+
+static void _joycon_send_raw(u8 uart_port, const u8 *buf, u16 size)
+{
+ uart_send(uart_port, buf, size);
+ uart_wait_xfer(uart_port, UART_TX_IDLE);
+}
+
+static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, const u8 *data, u16 size, bool crc)
+{
+ out->uart_hdr.magic[0] = 0x19;
+ out->uart_hdr.magic[1] = 0x01;
+ out->uart_hdr.magic[2] = 0x3;
+
+ out->uart_hdr.total_size_lsb = sizeof(jc_wired_hdr_t) - sizeof(jc_uart_hdr_t);
+ out->uart_hdr.total_size_msb = 0;
+ out->cmd = wired_cmd;
+
+ if (data)
+ memcpy(out->data, data, size);
+
+ out->crc = crc ? _jc_crc(&out->uart_hdr.total_size_msb,
+ sizeof(out->uart_hdr.total_size_msb) +
+ sizeof(out->cmd) + sizeof(out->data), 0) : 0;
+
+ return sizeof(jc_wired_hdr_t);
+}
+
+static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, const u8 *payload, u16 size, bool crc)
+{
+ u16 pkt_size = _jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc);
+ pkt_size += size;
+
+ rpt->uart_hdr.total_size_lsb += size;
+ rpt->data[0] = size >> 8;
+ rpt->data[1] = size & 0xFF;
+
+ if (payload)
+ memcpy(rpt->payload, payload, size);
+
+ return pkt_size;
+}
+
+static void _jc_send_hid_output_rpt(joycon_ctxt_t *jc, jc_hid_out_rpt_t *hid_pkt, u16 size, bool crc)
+{
+ u8 rpt[0x50];
+ memset(rpt, 0, sizeof(rpt));
+
+ hid_pkt->pkt_id = (jc->pkt_id++ & 0xF);
+ u32 rpt_size = _jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, (u8 *)hid_pkt, size, crc);
+
+ _joycon_send_raw(jc->uart, rpt, rpt_size);
+}
+
+static void _jc_send_hid_cmd(joycon_ctxt_t *jc, u8 subcmd, const u8 *data, u16 size)
+{
+ static const u8 rumble_neutral[8] = { 0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40 };
+ static const u8 rumble_init[8] = { 0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72 };
+
+ u8 temp[0x30] = {0};
+
+ jc_hid_out_rpt_t *hid_pkt = (jc_hid_out_rpt_t *)temp;
+ memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
+
+ if (subcmd == JC_HID_SUBCMD_SND_RUMBLE)
+ {
+ bool send_r_rumble = jc_r.connected && !jc_r.rumble_sent;
+ bool send_l_rumble = jc_l.connected && !jc_l.rumble_sent;
+
+ // Enable rumble.
+ hid_pkt->cmd = JC_HID_OUTPUT_RPT;
+ hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
+ hid_pkt->subcmd_data[0] = 1;
+ if (send_r_rumble)
+ _jc_send_hid_output_rpt(&jc_r, hid_pkt, 0x10, false);
+ if (send_l_rumble)
+ _jc_send_hid_output_rpt(&jc_l, hid_pkt, 0x10, false);
+
+ // Send rumble.
+ hid_pkt->cmd = JC_HID_RUMBLE_RPT;
+ memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init));
+ if (send_r_rumble)
+ _jc_send_hid_output_rpt(&jc_r, hid_pkt, 10, false);
+ if (send_l_rumble)
+ _jc_send_hid_output_rpt(&jc_l, hid_pkt, 10, false);
+
+ msleep(15);
+
+ // Disable rumble.
+ hid_pkt->cmd = JC_HID_OUTPUT_RPT;
+ hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
+ hid_pkt->subcmd_data[0] = 0;
+ memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
+ if (send_r_rumble)
+ _jc_send_hid_output_rpt(&jc_r, hid_pkt, 0x10, false);
+ if (send_l_rumble)
+ _jc_send_hid_output_rpt(&jc_l, hid_pkt, 0x10, false);
+ }
+ else
+ {
+ bool crc_needed = jc->type & JC_ID_HORI;
+
+ hid_pkt->cmd = JC_HID_OUTPUT_RPT;
+ hid_pkt->subcmd = subcmd;
+ if (data)
+ memcpy(hid_pkt->subcmd_data, data, size);
+
+ _jc_send_hid_output_rpt(jc, hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
+ }
+}
+
+static void _jc_charging_decider(u8 batt, u8 uart)
+{
+ u32 system_batt_enough = max17050_get_cached_batt_volt() > 4000;
+
+ // Power supply control based on battery levels and charging.
+ if ((batt >> 1) < JC_BATT_LOW) // Level without checking charging.
+ _jc_power_supply(uart, true);
+ else if (batt > (system_batt_enough ? JC_BATT_FULL : JC_BATT_MID) << 1) // Addresses the charging bit.
+ _jc_power_supply(uart, false);
+}
+
+static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8 *packet, int size)
+{
+ u32 btn_tmp;
+ jc_hid_in_rpt_t *hid_pkt = (jc_hid_in_rpt_t *)packet;
+
+ switch (hid_pkt->cmd)
+ {
+ case JC_HORI_INPUT_RPT:
+ if (!(jc->type & JC_ID_HORI))
+ return;
+
+ case JC_HID_INPUT_RPT:
+ // Discard incomplete hid packets.
+ if (size < 12)
+ break;
+
+ btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
+
+ if (jc->type & JC_ID_L)
+ {
+ jc_gamepad.buttons &= ~JC_BTN_MASK_L;
+ jc_gamepad.buttons |= (btn_tmp & JC_BTN_MASK_L);
+
+ jc_gamepad.lstick_x = hid_pkt->stick_h_left | ((hid_pkt->stick_m_left & 0xF) << 8);
+ jc_gamepad.lstick_y = (hid_pkt->stick_m_left >> 4) | (hid_pkt->stick_v_left << 4);
+
+ jc_gamepad.batt_info_l = hid_pkt->batt_info;
+ }
+ else if (jc->type & JC_ID_R)
+ {
+ jc_gamepad.buttons &= ~JC_BTN_MASK_R;
+ jc_gamepad.buttons |= (btn_tmp & JC_BTN_MASK_R);
+
+ jc_gamepad.rstick_x = hid_pkt->stick_h_right | ((hid_pkt->stick_m_right & 0xF) << 8);
+ jc_gamepad.rstick_y = (hid_pkt->stick_m_right >> 4) | (hid_pkt->stick_v_right << 4);
+
+ jc_gamepad.batt_info_r = hid_pkt->batt_info;
+ }
+
+ jc_gamepad.conn_l = jc_l.connected;
+ jc_gamepad.conn_r = jc_r.connected;
+
+ if (hid_pkt->cmd == JC_HID_INPUT_RPT)
+ _jc_charging_decider(hid_pkt->batt_info, jc->uart);
+ break;
+ case JC_HID_SUBMCD_RPT:
+ if (hid_pkt->subcmd == JC_HID_SUBCMD_SPI_READ)
+ {
+ jc_bt_conn_t *bt_conn;
+
+ if (jc->type & JC_ID_L)
+ bt_conn = &jc_gamepad.bt_conn_l;
+ else
+ bt_conn = &jc_gamepad.bt_conn_r;
+
+ jc_hid_in_spi_read_t *spi_info = (jc_hid_in_spi_read_t *)hid_pkt->subcmd_data;
+ jc_hid_in_pair_data_t *pair_data = (jc_hid_in_pair_data_t *)spi_info->data;
+
+ // Check if the reply is pairing info.
+ if (spi_info->size == 0x1A && pair_data->magic == 0x95 && pair_data->size == 0x22)
+ {
+ bt_conn->type = jc->type;
+
+ memcpy(bt_conn->mac, jc->mac, 6);
+ memcpy(bt_conn->host_mac, pair_data->mac, 6);
+ for (u32 i = 16; i > 0; i--)
+ bt_conn->ltk[16 - i] = pair_data->ltk[i - 1];
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void _jc_parse_wired_init(joycon_ctxt_t *jc, const u8 *data, int size)
+{
+ // Discard empty packets.
+ if (size <= 0)
+ return;
+
+ switch (data[0])
+ {
+ case JC_WIRED_CMD_GET_INFO:
+ for (int i = 12; i > 6; i--)
+ jc->mac[12 - i] = data[i];
+ jc->type = data[6];
+ jc->connected = true;
+ break;
+ case JC_WIRED_CMD_SET_BRATE:
+ jc->state = JC_STATE_BRATE_CHANGED;
+ break;
+ case JC_WIRED_CMD_HID_DISC:
+ jc->state = JC_STATE_BRATE_OK;
+ break;
+ case JC_WIRED_CMD_HID_CONN:
+ case JC_WIRED_CMD_SET_HIDRATE:
+ // done.
+ default:
+ break;
+ }
+}
+
+static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, int size)
+{
+ switch (pkt->cmd)
+ {
+ case JC_HORI_INPUT_RPT_CMD:
+ case JC_WIRED_HID:
+ _jc_parse_wired_hid(jc, pkt->payload, size - sizeof(jc_wired_hdr_t));
+ break;
+ case JC_WIRED_INIT_REPLY:
+ _jc_parse_wired_init(jc, pkt->data, size - sizeof(jc_uart_hdr_t) - 1);
+ break;
+ case JC_INIT_HANDSHAKE:
+ jc->state = JC_STATE_HANDSHAKED;
+ break;
+ default:
+ break;
+ }
+
+ jc->last_received_time = get_tmr_ms();
+}
+
+static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8 *payload, int size)
+{
+ switch (cmd)
+ {
+ case JC_SIO_CMD_STATUS:
+ // Discard incomplete packets.
+ if (size < 12)
+ break;
+
+ jc_sio_hid_in_rpt_t *hid_pkt = (jc_sio_hid_in_rpt_t *)payload;
+ jc_gamepad.buttons = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
+ jc_gamepad.home = !gpio_read(GPIO_PORT_V, GPIO_PIN_3);
+
+ jc_gamepad.lstick_x = hid_pkt->stick_h_left | ((hid_pkt->stick_m_left & 0xF) << 8);
+ jc_gamepad.lstick_y = (hid_pkt->stick_m_left >> 4) | (hid_pkt->stick_v_left << 4);
+ jc_gamepad.rstick_x = hid_pkt->stick_h_right | ((hid_pkt->stick_m_right & 0xF) << 8);
+ jc_gamepad.rstick_y = (hid_pkt->stick_m_right >> 4) | (hid_pkt->stick_v_right << 4);
+
+ jc_gamepad.batt_info_l = jc_l.connected;
+ jc_gamepad.batt_info_r = gpio_read(GPIO_PORT_E, GPIO_PIN_7); // Set IRQ status.
+
+ jc_gamepad.conn_l = jc_l.connected;
+ jc_gamepad.conn_r = jc_l.connected;
+ break;
+ default:
+ break;
+ }
+}
+
+static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt, int size)
+{
+ if (pkt->crc_hdr != _jc_crc((u8 *)pkt, sizeof(jc_sio_in_rpt_t) - 1, 0))
+ return;
+
+ u8 cmd = pkt->ack & (~JC_SIO_CMD_ACK);
+ switch (cmd)
+ {
+ case JC_SIO_CMD_INIT:
+ jc->connected = pkt->status == 0;
+ break;
+ case JC_SIO_CMD_VER_RPT:
+ if (jc->connected)
+ jc->connected = pkt->status == 0;
+ break;
+ case JC_SIO_CMD_IAP_VER:
+ case JC_SIO_CMD_STATUS:
+ _jc_sio_parse_payload(jc, cmd, pkt->payload, size - sizeof(jc_sio_in_rpt_t));
+ break;
+ case JC_SIO_CMD_UNK02:
+ case JC_SIO_CMD_UNK20:
+ case JC_SIO_CMD_UNK21:
+ case JC_SIO_CMD_UNK22:
+ case JC_SIO_CMD_UNK40:
+ default:
+ break;
+ }
+
+ jc->last_received_time = get_tmr_ms();
+}
+
+static void _jc_rcv_pkt(joycon_ctxt_t *jc)
+{
+ if (!jc->detected)
+ return;
+
+ u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
+ if (len < 8)
+ return;
+
+ // For Joycon, check uart reply magic.
+ jc_wired_hdr_t *jc_pkt = (jc_wired_hdr_t *)jc->buf;
+ if (!jc->sio_mode && !memcmp(jc_pkt->uart_hdr.magic, "\x19\x81\x03", 3))
+ {
+ _jc_uart_pkt_parse(jc, jc_pkt, len);
+
+ return;
+ }
+
+ // For Sio, check uart output report and command ack.
+ jc_sio_in_rpt_t *sio_pkt = (jc_sio_in_rpt_t *)(jc->buf);
+ if (jc->sio_mode && sio_pkt->cmd == JC_SIO_INPUT_RPT && (sio_pkt->ack & JC_SIO_CMD_ACK) == JC_SIO_CMD_ACK)
+ {
+ _jc_sio_uart_pkt_parse(jc, sio_pkt, len);
+
+ return;
+ }
+}
+
+static bool _jc_send_init_rumble(joycon_ctxt_t *jc)
+{
+ // Send init rumble or request nx pad status report.
+ if ((jc_r.connected && !jc_r.rumble_sent) || (jc_l.connected && !jc_l.rumble_sent))
+ {
+ _jc_send_hid_cmd(jc, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0);
+
+ if (jc_l.connected)
+ jc_l.rumble_sent = true;
+ if (jc_r.connected)
+ jc_r.rumble_sent = true;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void _jc_req_nx_pad_status(joycon_ctxt_t *jc)
+{
+ if (!jc->detected)
+ return;
+
+ bool is_nxpad = !(jc->type & JC_ID_HORI) && !jc->sio_mode;
+
+ if (jc->last_status_req_time > get_tmr_ms() || !jc->connected)
+ return;
+
+ if (is_nxpad)
+ {
+ bool sent_rumble = _jc_send_init_rumble(jc);
+
+ if (sent_rumble)
+ return;
+ }
+
+ if (is_nxpad)
+ _joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status));
+ else if (jc->sio_mode)
+ _joycon_send_raw(jc->uart, sio_pad_status, sizeof(sio_pad_status));
+ else
+ _joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status));
+
+ jc->last_status_req_time = get_tmr_ms() + (!jc->sio_mode ? 15 : 7);
+}
+
+static bool _jc_validate_pairing_info(const u8 *buf, bool *is_hos)
+{
+ u8 crc = 0;
+ for (u32 i = 0; i < 0x22; i++)
+ crc += buf[4 + i];
+
+ crc += 0x68; // Host is Switch.
+
+ if ((crc ^ 0x55) == buf[2])
+ *is_hos = true;
+
+ crc -= 0x68;
+ crc += 0x08; // Host is PC.
+
+ if (*is_hos || (crc ^ 0x55) == buf[2])
+ return true;
+
+ return false;
+}
+
+jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos)
+{
+ u8 retries;
+ jc_bt_conn_t *bt_conn;
+
+ if (!jc_init_done || jc_gamepad.sio_mode)
+ return NULL;
+
+ bt_conn = &jc_gamepad.bt_conn_l;
+ memset(bt_conn->host_mac, 0, 6);
+ memset(bt_conn->ltk, 0, 16);
+
+ bt_conn = &jc_gamepad.bt_conn_r;
+ memset(bt_conn->host_mac, 0, 6);
+ memset(bt_conn->ltk, 0, 16);
+
+ _jc_conn_check();
+
+ while (jc_l.last_status_req_time > get_tmr_ms())
+ {
+ _jc_rcv_pkt(&jc_r);
+ _jc_rcv_pkt(&jc_l);
+ }
+
+ jc_hid_in_spi_read_t subcmd_data_l;
+ subcmd_data_l.addr = 0x2000;
+ subcmd_data_l.size = 0x1A;
+
+ jc_hid_in_spi_read_t subcmd_data_r;
+ subcmd_data_r.addr = 0x2000;
+ subcmd_data_r.size = 0x1A;
+
+ bool jc_r_found = jc_r.connected ? false : true;
+ bool jc_l_found = jc_l.connected ? false : true;
+
+ // Set mode to HW controlled RTS.
+ uart_set_mode(jc_l.uart, UART_AO_TX_HW_RX);
+ uart_set_mode(jc_r.uart, UART_AO_TX_HW_RX);
+
+ u32 total_retries = 10;
+retry:
+ retries = 10;
+ while (retries)
+ {
+ u32 time_now = get_tmr_ms();
+ if ((!jc_l_found && jc_l.last_status_req_time < time_now) || (!jc_r_found && jc_r.last_status_req_time < time_now))
+ {
+ if (!jc_l_found)
+ {
+ _jc_send_hid_cmd(&jc_l, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5);
+ jc_l.last_status_req_time = get_tmr_ms() + 15;
+ }
+
+ if (!jc_r_found)
+ {
+ _jc_send_hid_cmd(&jc_r, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5);
+ jc_r.last_status_req_time = get_tmr_ms() + 15;
+ }
+
+ retries--;
+ }
+
+ // Wait for the first 36 bytes to arrive.
+ msleep(5);
+
+ if (!jc_l_found)
+ {
+ memset(jc_l.buf, 0, 0x100);
+ _jc_rcv_pkt(&jc_l);
+
+ bool is_hos = false;
+ if (_jc_validate_pairing_info(&jc_l.buf[SPI_READ_OFFSET], &is_hos))
+ {
+ bool is_active = jc_l.buf[SPI_READ_OFFSET] == 0x95;
+
+ if (!is_active)
+ subcmd_data_l.addr += 0x26; // Get next slot.
+ else
+ jc_l_found = true; // Entry is active.
+
+ if (jc_l_found && is_hos)
+ *is_l_hos = true;
+ }
+ }
+
+ if (!jc_r_found)
+ {
+ memset(jc_r.buf, 0, 0x100);
+ _jc_rcv_pkt(&jc_r);
+
+ bool is_hos = false;
+ if (_jc_validate_pairing_info(&jc_r.buf[SPI_READ_OFFSET], &is_hos))
+ {
+ bool is_active = jc_r.buf[SPI_READ_OFFSET] == 0x95;
+
+ if (!is_active)
+ subcmd_data_r.addr += 0x26; // Get next slot.
+ else
+ jc_r_found = true; // Entry is active.
+
+ if (jc_r_found && is_hos)
+ *is_r_hos = true;
+ }
+ }
+
+ if (jc_l_found && jc_r_found)
+ break;
+ }
+
+ if (!jc_l_found || !jc_r_found)
+ {
+ if (total_retries)
+ {
+ total_retries--;
+ goto retry;
+ }
+
+ if (!jc_l_found)
+ {
+ bt_conn = &jc_gamepad.bt_conn_l;
+ memset(bt_conn->host_mac, 0, 6);
+ memset(bt_conn->ltk, 0, 16);
+ }
+
+ if (!jc_r_found)
+ {
+ bt_conn = &jc_gamepad.bt_conn_r;
+ memset(bt_conn->host_mac, 0, 6);
+ memset(bt_conn->ltk, 0, 16);
+ }
+ }
+
+ // Restore mode to manual RTS.
+ uart_set_mode(jc_l.uart, UART_AO_TX_MN_RX);
+ uart_set_mode(jc_r.uart, UART_AO_TX_MN_RX);
+
+ return &jc_gamepad;
+}
+
+static void _jc_init_conn(joycon_ctxt_t *jc)
+{
+ if (!jc->detected)
+ return;
+
+ if (((u32)get_tmr_ms() - jc->last_received_time) > 1000)
+ {
+ _jc_power_supply(jc->uart, true);
+
+ // Mask out buttons and set connected to false.
+ if (jc->uart == UART_B)
+ {
+ jc_gamepad.buttons &= ~JC_BTN_MASK_R;
+ jc_gamepad.conn_r = false;
+ }
+ else
+ {
+ jc_gamepad.buttons &= ~JC_BTN_MASK_L;
+ jc_gamepad.conn_l = false;
+ }
+
+ // Initialize uart to 1 megabaud and manual RTS.
+ uart_init(jc->uart, 1000000, UART_AO_TX_MN_RX);
+
+ if (!jc->sio_mode)
+ {
+ jc->state = JC_STATE_START;
+
+ // Set TX and RTS inversion for Joycon.
+ uart_invert(jc->uart, true, UART_INVERT_TXD | UART_INVERT_RTS);
+
+ // Wake up the controller.
+ _joycon_send_raw(jc->uart, init_wake, sizeof(init_wake));
+ _jc_rcv_pkt(jc); // Clear RX FIFO.
+
+ // Do a handshake.
+ u32 retries = 10;
+ while (retries && jc->state != JC_STATE_HANDSHAKED)
+ {
+ _joycon_send_raw(jc->uart, init_handshake, sizeof(init_handshake));
+ msleep(5);
+ _jc_rcv_pkt(jc);
+ retries--;
+ }
+
+ if (jc->state != JC_STATE_HANDSHAKED)
+ goto out;
+
+ // Get info about the controller.
+ _joycon_send_raw(jc->uart, init_get_info, sizeof(init_get_info));
+ msleep(2);
+ _jc_rcv_pkt(jc);
+
+ if (!(jc->type & JC_ID_HORI))
+ {
+ // Request 3 megabaud change.
+ _joycon_send_raw(jc->uart, init_switch_brate, sizeof(init_switch_brate));
+ msleep(2);
+ _jc_rcv_pkt(jc);
+
+ if (jc->state == JC_STATE_BRATE_CHANGED)
+ {
+ // Reinitialize uart to 3 megabaud and manual RTS.
+ uart_init(jc->uart, 3000000, UART_AO_TX_MN_RX);
+ uart_invert(jc->uart, true, UART_INVERT_TXD | UART_INVERT_RTS);
+
+ // Disconnect HID.
+ retries = 10;
+ while (retries && jc->state != JC_STATE_BRATE_OK)
+ {
+ _joycon_send_raw(jc->uart, init_hid_disconnect, sizeof(init_hid_disconnect));
+ msleep(5);
+ _jc_rcv_pkt(jc);
+ retries--;
+ }
+
+ if (jc->state != JC_STATE_BRATE_OK)
+ goto out;
+ }
+
+ // Create HID connection with the new rate.
+ _joycon_send_raw(jc->uart, init_hid_connect, sizeof(init_hid_connect));
+ msleep(2);
+ _jc_rcv_pkt(jc);
+
+ // Set hid packet rate.
+ _joycon_send_raw(jc->uart, init_set_hid_rate, sizeof(init_set_hid_rate));
+ msleep(2);
+ _jc_rcv_pkt(jc);
+ }
+ else // Hori. Unset RTS inversion.
+ uart_invert(jc->uart, false, UART_INVERT_RTS);
+ }
+ else
+ {
+ // Set Sio NPOR low to configure BOOT0 mode.
+ gpio_write(GPIO_PORT_CC, GPIO_PIN_5, GPIO_LOW);
+ usleep(300);
+ gpio_write(GPIO_PORT_T, GPIO_PIN_0, GPIO_LOW);
+ gpio_write(GPIO_PORT_CC, GPIO_PIN_5, GPIO_HIGH);
+ msleep(100);
+
+ // Clear RX FIFO.
+ _jc_rcv_pkt(jc);
+
+ // Initialize the controller.
+ u32 retries = 10;
+ while (!jc->connected && retries)
+ {
+ _joycon_send_raw(jc->uart, sio_init, sizeof(sio_init));
+ msleep(5);
+ _jc_rcv_pkt(jc);
+ retries--;
+ }
+
+ if (!jc->connected)
+ goto out;
+
+ // Set output report version.
+ _joycon_send_raw(jc->uart, sio_set_rpt_version, sizeof(sio_set_rpt_version));
+ msleep(5);
+ _jc_rcv_pkt(jc);
+ }
+
+ // Initialization done.
+ jc->state = JC_STATE_INIT_DONE;
+
+out:
+ jc->last_received_time = get_tmr_ms();
+
+ if (!jc->sio_mode && jc->connected && !(jc->type & JC_ID_HORI))
+ _jc_power_supply(jc->uart, false);
+ }
+}
+
+void jc_init_hw()
+{
+ jc_l.uart = UART_C;
+ jc_r.uart = UART_B;
+
+ jc_l.sio_mode = fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG;
+ jc_gamepad.sio_mode = jc_l.sio_mode;
+
+#if !defined(DEBUG_UART_PORT) || !(DEBUG_UART_PORT)
+ _jc_power_supply(UART_C, true);
+ _jc_power_supply(UART_B, true);
+
+ // Sio Initialization.
+ if (jc_gamepad.sio_mode)
+ {
+ // Enable 4 MHz clock to Sio.
+ clock_enable_extperiph2();
+ PINMUX_AUX(PINMUX_AUX_TOUCH_CLK) = PINMUX_PULL_DOWN;
+
+ // Configure Sio HOME BUTTON.
+ PINMUX_AUX(PINMUX_AUX_LCD_GPIO1) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 1;
+ gpio_direction_input(GPIO_PORT_V, GPIO_PIN_3);
+
+ // Configure Sio IRQ
+ PINMUX_AUX(PINMUX_AUX_GPIO_PE7) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP;
+ gpio_direction_input(GPIO_PORT_E, GPIO_PIN_7);
+
+ // Configure Sio NRST and BOOT0.
+ PINMUX_AUX(PINMUX_AUX_CAM1_STROBE) = PINMUX_PULL_DOWN | 1;
+ PINMUX_AUX(PINMUX_AUX_CAM2_PWDN) = PINMUX_PULL_DOWN | 1;
+
+ // Set BOOT0 to flash mode. (output high is sram mode).
+ gpio_direction_output(GPIO_PORT_T, GPIO_PIN_0, GPIO_LOW);
+
+ // NRST to pull down.
+ gpio_direction_input(GPIO_PORT_T, GPIO_PIN_1);
+
+ // Configure Sio NPOR.
+ PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN1) = PINMUX_IO_HV | PINMUX_LPDR | 1;
+ gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_5, GPIO_LOW);
+ }
+
+#if 0 // Already set by hw init.
+ // Set Joy-Con IsAttached pinmux. Shared with UARTB/UARTC TX.
+ PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
+ PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
+
+ // Set Joy-Con IsAttached mode. Shared with UARTB/UARTC TX.
+ gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO);
+ gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO);
+#endif
+
+ // Configure pinmuxing for UART B and C.
+ if (!jc_gamepad.sio_mode)
+ pinmux_config_uart(UART_B);
+ pinmux_config_uart(UART_C);
+
+ // Enable UART B and C clocks.
+ if (!jc_gamepad.sio_mode)
+ clock_enable_uart(UART_B);
+ clock_enable_uart(UART_C);
+
+ jc_init_done = true;
+#endif
+}
+
+void jc_deinit()
+{
+ if (!jc_init_done)
+ return;
+
+ // Disable power.
+ _jc_power_supply(UART_B, false);
+ _jc_power_supply(UART_C, false);
+
+ if (!jc_gamepad.sio_mode)
+ {
+ // Send sleep command.
+ u8 data = HCI_STATE_SLEEP;
+ if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
+ {
+ _jc_send_hid_cmd(&jc_r, JC_HID_SUBCMD_HCI_STATE, &data, 1);
+ _jc_rcv_pkt(&jc_r);
+ }
+ if (jc_l.connected && !(jc_l.type & JC_ID_HORI))
+ {
+ _jc_send_hid_cmd(&jc_l, JC_HID_SUBCMD_HCI_STATE, &data, 1);
+ _jc_rcv_pkt(&jc_l);
+ }
+ }
+ else
+ {
+ // Disable Sio NPOR.
+ gpio_write(GPIO_PORT_CC, GPIO_PIN_5, GPIO_LOW);
+
+ // Disable 4 MHz clock to Sio.
+ clock_disable_extperiph2();
+ }
+
+ // Disable UART B and C clocks.
+ if (!jc_gamepad.sio_mode)
+ clock_disable_uart(UART_B);
+ clock_disable_uart(UART_C);
+}
+
+jc_gamepad_rpt_t *joycon_poll()
+{
+ if (!jc_init_done)
+ return NULL;
+
+ _jc_conn_check();
+
+ _jc_init_conn(&jc_r);
+ _jc_init_conn(&jc_l);
+
+ _jc_req_nx_pad_status(&jc_r);
+ _jc_req_nx_pad_status(&jc_l);
+
+ _jc_rcv_pkt(&jc_r);
+ _jc_rcv_pkt(&jc_l);
+
+ return &jc_gamepad;
+}
diff --git a/bdk/input/joycon.h b/bdk/input/joycon.h
new file mode 100644
index 0000000..fbb789f
--- /dev/null
+++ b/bdk/input/joycon.h
@@ -0,0 +1,108 @@
+/*
+ * Ambient light sensor driver for Nintendo Switch's Rohm BH1730
+ *
+ * Copyright (c) 2018 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __JOYCON_H_
+#define __JOYCON_H_
+
+#include
+
+#define JC_BTNS_DIRECTION_PAD 0xF0000
+#define JC_BTNS_PREV_NEXT 0x800080
+#define JC_BTNS_ENTER 0x400008
+#define JC_BTNS_ESC 0x4
+
+#define JC_BTNS_ALL (JC_BTNS_PREV_NEXT | JC_BTNS_ENTER | JC_BTNS_DIRECTION_PAD | JC_BTNS_ESC)
+
+typedef struct _jc_bt_conn_t
+{
+ u8 type;
+ u8 mac[6];
+ u8 host_mac[6];
+ u8 ltk[16];
+} jc_bt_conn_t;
+
+typedef struct _jc_gamepad_rpt_t
+{
+ union
+ {
+ struct
+ {
+ // Joy-Con (R).
+/*00*/ u32 y:1;
+/*01*/ u32 x:1;
+/*02*/ u32 b:1;
+/*03*/ u32 a:1;
+/*04*/ u32 sr_r:1;
+/*05*/ u32 sl_r:1;
+/*06*/ u32 r:1;
+/*07*/ u32 zr:1;
+
+ // Shared
+/*08*/ u32 minus:1;
+/*09*/ u32 plus:1;
+/*10*/ u32 r3:1;
+/*11*/ u32 l3:1;
+/*12*/ u32 home:1;
+/*13*/ u32 cap:1;
+/*14*/ u32 pad:1;
+/*15*/ u32 wired:1;
+
+ // Joy-Con (L).
+/*16*/ u32 down:1;
+/*17*/ u32 up:1;
+/*18*/ u32 right:1;
+/*19*/ u32 left:1;
+/*20*/ u32 sr_l:1;
+/*21*/ u32 sl_l:1;
+/*22*/ u32 l:1;
+/*23*/ u32 zl:1;
+ };
+ u32 buttons;
+ };
+
+ u16 lstick_x;
+ u16 lstick_y;
+ u16 rstick_x;
+ u16 rstick_y;
+ bool center_stick_l;
+ bool center_stick_r;
+ bool conn_l;
+ bool conn_r;
+ bool sio_mode;
+ u8 batt_info_l; // Also Sio Connected status.
+ u8 batt_info_r; // Also Sio IRQ.
+ jc_bt_conn_t bt_conn_l;
+ jc_bt_conn_t bt_conn_r;
+} jc_gamepad_rpt_t;
+
+typedef struct _jc_calib_t
+{
+ u16 x_max:12;
+ u16 y_max:12;
+ u16 x_center:12;
+ u16 y_center:12;
+ u16 x_min:12;
+ u16 y_min:12;
+} __attribute__((packed)) jc_calib_t;
+
+void jc_init_hw();
+void jc_deinit();
+jc_gamepad_rpt_t *joycon_poll();
+jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos);
+
+#endif
diff --git a/bdk/input/touch.c b/bdk/input/touch.c
new file mode 100644
index 0000000..f5b5098
--- /dev/null
+++ b/bdk/input/touch.c
@@ -0,0 +1,461 @@
+/*
+ * Touch driver for Nintendo Switch's STM FingerTip S (4CD60D) touch controller
+ *
+ * Copyright (c) 2018 langerhans
+ * Copyright (c) 2018-2023 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 .
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "touch.h"
+
+
+#include
+#define DPRINTF(...) gfx_printf(__VA_ARGS__)
+
+static touch_panel_info_t _panels[] =
+{
+ { 0, 1, 1, 1, "NISSHA NFT-K12D" },// 0.
+ { 1, 0, 1, 1, "GiS GGM6 B2X" },// 1.
+ { 2, 0, 0, 0, "NISSHA NBF-K9A" },// 3.
+ { 3, 1, 0, 0, "GiS 5.5\"" },// 4.
+ { 4, 0, 0, 1, "Samsung TSP" },// 5?
+ { -1, 1, 0, 1, "GiS VA 6.2\"" } // 2.
+};
+
+static int touch_command(u8 cmd, u8 *buf, u8 size)
+{
+ int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd, buf, size);
+ if (!res)
+ return 1;
+ return 0;
+}
+
+static int touch_read_reg(u8 *cmd, u32 csize, u8 *buf, u32 size)
+{
+ int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd[0], &cmd[1], csize - 1);
+ if (res)
+ res = i2c_recv_buf(buf, size, I2C_3, STMFTS_I2C_ADDR);
+ if (!res)
+ return 1;
+
+ return 0;
+}
+
+static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf)
+{
+ u32 timer = get_tmr_ms() + timeout;
+ while (true)
+ {
+ u8 tmp[8] = {0};
+ i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT);
+ if (tmp[1] == event && tmp[2] == status)
+ {
+ if (buf)
+ memcpy(buf, &tmp[3], 5);
+ return 0;
+ }
+
+ if (get_tmr_ms() > timer)
+ return 1;
+ }
+}
+
+#define X_REAL_MAX 1264
+#define Y_REAL_MAX 704
+#define EDGE_OFFSET 15
+
+static void _touch_compensate_limits(touch_event *event, bool touching)
+{
+ event->x = MAX(event->x, EDGE_OFFSET);
+ event->x = MIN(event->x, X_REAL_MAX);
+ event->x -= EDGE_OFFSET;
+ u32 x_adj = (1280 * 1000) / (X_REAL_MAX - EDGE_OFFSET);
+ event->x = ((u32)event->x * x_adj) / 1000;
+
+ if (touching)
+ {
+ event->y = MAX(event->y, EDGE_OFFSET);
+ event->y = MIN(event->y, Y_REAL_MAX);
+ event->y -= EDGE_OFFSET;
+ u32 y_adj = (720 * 1000) / (Y_REAL_MAX - EDGE_OFFSET);
+ event->y = ((u32)event->y * y_adj) / 1000;
+ }
+}
+
+static void _touch_process_contact_event(touch_event *event, bool touching)
+{
+ event->x = (event->raw[2] << 4) | ((event->raw[4] & STMFTS_MASK_Y_LSB) >> 4);
+
+ // Normally, GUI elements have bigger horizontal estate.
+ // Avoid parsing y axis when finger is removed to minimize touch noise.
+ if (touching)
+ {
+ event->y = (event->raw[3] << 4) | (event->raw[4] & STMFTS_MASK_X_MSB);
+
+ event->z = event->raw[5] | (event->raw[6] << 8);
+ event->z = event->z << 6;
+
+ u16 tmp = 0x40;
+ if ((event->raw[7] & 0x3F) != 1 && (event->raw[7] & 0x3F) != 0x3F)
+ tmp = event->raw[7] & 0x3F;
+ event->z /= tmp + 0x40;
+
+ event->fingers = ((event->raw[1] & STMFTS_MASK_TOUCH_ID) >> 4) + 1;
+ }
+ else
+ event->fingers = 0;
+
+ _touch_compensate_limits(event, touching);
+}
+
+static void _touch_parse_event(touch_event *event)
+{
+ event->type = event->raw[1] & STMFTS_MASK_EVENT_ID;
+
+ switch (event->type)
+ {
+ case STMFTS_EV_MULTI_TOUCH_ENTER:
+ case STMFTS_EV_MULTI_TOUCH_MOTION:
+ _touch_process_contact_event(event, true);
+ if (event->z < 255) // Reject palm rest.
+ event->touch = true;
+ else
+ {
+ event->touch = false;
+ event->type = STMFTS_EV_MULTI_TOUCH_LEAVE;
+ }
+ break;
+ case STMFTS_EV_MULTI_TOUCH_LEAVE:
+ event->touch = false;
+ _touch_process_contact_event(event, false);
+ break;
+ case STMFTS_EV_NO_EVENT:
+ if (event->touch)
+ event->type = STMFTS_EV_MULTI_TOUCH_MOTION;
+ break;
+ default:
+ if (event->touch && event->raw[0] == STMFTS_EV_MULTI_TOUCH_MOTION)
+ event->type = STMFTS_EV_MULTI_TOUCH_MOTION;
+ else
+ event->type = STMFTS_EV_MULTI_TOUCH_LEAVE;
+ }
+
+ // gfx_con_setpos(0, 300);
+ // DPRINTF("x = %d \ny = %d \nz = %d \n", event->x, event->y, event->z);
+ // DPRINTF("0 = %02X\n1 = %02X\n2 = %02X\n3 = %02X\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]);
+ // DPRINTF("4 = %02X\n5 = %02X\n6 = %02X\n7 = %02X\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]);
+}
+
+void touch_poll(touch_event *event)
+{
+ i2c_recv_buf_small(event->raw, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_LATEST_EVENT);
+
+ _touch_parse_event(event);
+}
+
+touch_event touch_poll_wait()
+{
+ touch_event event;
+ do
+ {
+ touch_poll(&event);
+ } while (event.type != STMFTS_EV_MULTI_TOUCH_LEAVE);
+
+ return event;
+}
+
+touch_info touch_get_info()
+{
+ touch_info info;
+ u8 buf[8];
+ memset(&buf, 0, 8);
+ i2c_recv_buf_small(buf, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_INFO);
+
+ info.chip_id = buf[0] << 8 | buf[1];
+ info.fw_ver = buf[2] << 8 | buf[3];
+ info.config_id = buf[4];
+ info.config_ver = buf[5];
+
+ //DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02X, Cfg Ver: %d\n",
+ // info.chip_id, info.fw_ver >> 8, info.fw_ver & 0xFF, info.config_id, info.config_ver);
+
+ return info;
+}
+
+touch_panel_info_t *touch_get_panel_vendor()
+{
+ u8 buf[5] = {0};
+ u8 cmd = STMFTS_VENDOR_GPIO_STATE;
+ static touch_panel_info_t panel_info = { -2, 0, 0, 0, ""};
+
+ if (touch_command(STMFTS_VENDOR, &cmd, 1))
+ return NULL;
+
+ if (touch_wait_event(STMFTS_EV_VENDOR, STMFTS_VENDOR_GPIO_STATE, 2000, buf))
+ return NULL;
+
+ for (u32 i = 0; i < ARRAY_SIZE(_panels); i++)
+ {
+ touch_panel_info_t *panel = &_panels[i];
+ if (buf[0] == panel->gpio0 && buf[1] == panel->gpio1 && buf[2] == panel->gpio2)
+ return panel;
+ }
+
+ // Touch panel not found, return current gpios.
+ panel_info.gpio0 = buf[0];
+ panel_info.gpio1 = buf[1];
+ panel_info.gpio2 = buf[2];
+
+ return &panel_info;
+}
+
+int touch_get_fw_info(touch_fw_info_t *fw)
+{
+ u8 buf[8] = {0};
+
+ memset(fw, 0, sizeof(touch_fw_info_t));
+
+ // Get fw address info.
+ u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 };
+ int res = touch_read_reg(cmd, 3, buf, 3);
+ if (!res)
+ {
+ // Get fw info.
+ cmd[1] = buf[2]; cmd[2] = buf[1];
+ res = touch_read_reg(cmd, 3, buf, 8);
+ if (!res)
+ {
+ fw->fw_id = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4];
+ fw->ftb_ver = (buf[6] << 8) | buf[5];
+ }
+
+ cmd[2]++;
+ res = touch_read_reg(cmd, 3, buf, 8);
+ if (!res)
+ fw->fw_rev = (buf[7] << 8) | buf[6];
+ }
+
+ return res;
+}
+
+int touch_sys_reset()
+{
+ u8 cmd[3] = { 0, 0x28, 0x80 }; // System reset cmd.
+ for (u8 retries = 0; retries < 3; retries++)
+ {
+ if (touch_command(STMFTS_WRITE_REG, cmd, 3))
+ {
+ msleep(10);
+ continue;
+ }
+ msleep(10);
+ if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL))
+ continue;
+ else
+ return 0;
+ }
+
+ return 1;
+}
+
+int touch_panel_ito_test(u8 *err)
+{
+ int res = 0;
+
+ // Reset touchscreen module.
+ if (touch_sys_reset())
+ return res;
+
+ // Do ITO Production test.
+ u8 cmd[2] = { 1, 0 };
+ if (touch_command(STMFTS_ITO_CHECK, cmd, 2))
+ return res;
+
+ u32 timer = get_tmr_ms() + 2000;
+ while (true)
+ {
+ u8 tmp[8] = {0};
+ i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT);
+ if (tmp[1] == 0xF && tmp[2] == 0x5)
+ {
+ if (err)
+ {
+ err[0] = tmp[3];
+ err[1] = tmp[4];
+ }
+
+ res = 1;
+ break;
+ }
+
+ if (get_tmr_ms() > timer)
+ break;
+ }
+
+ // Reset touchscreen module.
+ touch_sys_reset();
+
+ return res;
+}
+
+int touch_get_fb_info(u8 *buf)
+{
+ u8 tmp[5];
+
+ u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0 };
+ int res = 0;
+
+
+ for (u32 i = 0; i < 0x10000; i += 4)
+ {
+ if (!res)
+ {
+ cmd[1] = (i >> 8) & 0xFF;
+ cmd[2] = i & 0xFF;
+ memset(tmp, 0xCC, 5);
+ res = touch_read_reg(cmd, 3, tmp, 5);
+ memcpy(&buf[i], tmp + 1, 4);
+ }
+ }
+
+ return res;
+}
+
+int touch_sense_enable()
+{
+ // Switch sense mode and enable multi-touch sensing.
+ u8 cmd = STMFTS_FINGER_MODE;
+ if (touch_command(STMFTS_SWITCH_SENSE_MODE, &cmd, 1))
+ return 0;
+
+ if (touch_command(STMFTS_MS_MT_SENSE_ON, NULL, 0))
+ return 0;
+
+ if (touch_command(STMFTS_CLEAR_EVENT_STACK, NULL, 0))
+ return 0;
+
+ return 1;
+}
+
+int touch_execute_autotune()
+{
+ // Reset touchscreen module.
+ if (touch_sys_reset())
+ return 0;
+
+ // Trim low power oscillator.
+ if (touch_command(STMFTS_LP_TIMER_CALIB, NULL, 0))
+ return 0;
+ msleep(200);
+
+ // Apply Mutual Sense Compensation tuning.
+ if (touch_command(STMFTS_MS_CX_TUNING, NULL, 0))
+ return 0;
+ if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000, NULL))
+ return 0;
+
+ // Apply Self Sense Compensation tuning.
+ if (touch_command(STMFTS_SS_CX_TUNING, NULL, 0))
+ return 0;
+ if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000, NULL))
+ return 0;
+
+ // Save Compensation data to EEPROM.
+ if (touch_command(STMFTS_SAVE_CX_TUNING, NULL, 0))
+ return 0;
+ if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000, NULL))
+ return 0;
+
+ return touch_sense_enable();
+}
+
+static int touch_init()
+{
+ // Initialize touchscreen module.
+ if (touch_sys_reset())
+ return 0;
+
+ return touch_sense_enable();
+}
+
+int touch_power_on()
+{
+ // Configure Touscreen and GCAsic shared GPIO.
+ PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
+ PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; // Unused.
+ gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
+
+ // Configure touchscreen Touch Reset pin.
+ PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
+ gpio_direction_output(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW);
+ usleep(20);
+
+ // Enable LDO6 for touchscreen AVDD and DVDD supply.
+ max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
+ max7762x_regulator_enable(REGULATOR_LDO6, true);
+
+ // Initialize I2C3.
+ pinmux_config_i2c(I2C_3);
+ clock_enable_i2c(I2C_3);
+ i2c_init(I2C_3);
+ usleep(1000);
+
+ // Set Touch Reset pin.
+ gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH);
+ usleep(10000);
+
+ // Wait for the touchscreen module to get ready.
+ touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL);
+
+ // Check for forced boot time calibration.
+ if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
+ {
+ u8 err[2];
+ if (touch_panel_ito_test(err))
+ if (!err[0] && !err[1])
+ return touch_execute_autotune();
+ }
+
+ // Initialize touchscreen.
+ u32 retries = 3;
+ while (retries)
+ {
+ if (touch_init())
+ return 1;
+ retries--;
+ }
+
+ return 0;
+}
+
+void touch_power_off()
+{
+ // Disable touchscreen power.
+ gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW);
+
+ // Disables LDO6 for touchscreen VDD, AVDD supply
+ max7762x_regulator_enable(REGULATOR_LDO6, false);
+
+ clock_disable_i2c(I2C_3);
+}
\ No newline at end of file
diff --git a/nyx/nyx_gui/input/touch.h b/bdk/input/touch.h
similarity index 65%
rename from nyx/nyx_gui/input/touch.h
rename to bdk/input/touch.h
index f38d41e..871659e 100644
--- a/nyx/nyx_gui/input/touch.h
+++ b/bdk/input/touch.h
@@ -1,8 +1,8 @@
/*
- * Touch driver for Nintendo Switch's STMicroelectronics FingerTip S touch controller
+ * Touch driver for Nintendo Switch's STM FingerTip S (4CD60D) touch controller
*
* Copyright (c) 2018 langerhans
- * Copyright (c) 2018 CTCaer
+ * 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,
@@ -20,7 +20,7 @@
#ifndef __TOUCH_H_
#define __TOUCH_H_
-#include "../utils/types.h"
+#include
#define STMFTS_I2C_ADDR 0x49
@@ -44,20 +44,30 @@
#define STMFTS_FULL_FORCE_CALIBRATION 0xA2
#define STMFTS_MS_CX_TUNING 0xA3
#define STMFTS_SS_CX_TUNING 0xA4
+#define STMFTS_ITO_CHECK 0xA7
#define STMFTS_RELEASEINFO 0xAA
#define STMFTS_WRITE_REG 0xB6
+#define STMFTS_SWITCH_SENSE_MODE 0xC3
#define STMFTS_NOISE_WRITE 0xC7
#define STMFTS_NOISE_READ 0xC8
-#define STMFTS_RW_FB_REG 0xD0 // read data
+#define STMFTS_RW_FRAMEBUFFER_REG 0xD0
#define STMFTS_SAVE_CX_TUNING 0xFC
-#define STMFTS_UNK0 0xB8 //Request compensation
-#define STMFTS_UNK1 0xCF
-#define STMFTS_UNK2 0xF7
-#define STMFTS_UNK3 0xFA
-#define STMFTS_UNK4 0xF9
+#define STMFTS_DETECTION_CONFIG 0xB0
+#define STMFTS_REQU_COMP_DATA 0xB8
+#define STMFTS_VENDOR 0xCF
+#define STMFTS_FLASH_UNLOCK 0xF7
+#define STMFTS_FLASH_WRITE_64K 0xF8
+#define STMFTS_FLASH_STATUS 0xF9
+#define STMFTS_FLASH_OP 0xFA
#define STMFTS_UNK5 0x62
+/* cmd parameters */
+#define STMFTS_VENDOR_GPIO_STATE 0x01
+#define STMFTS_VENDOR_SENSE_MODE 0x02
+#define STMFTS_STYLUS_MODE 0x00
+#define STMFTS_FINGER_MODE 0x01
+#define STMFTS_HOVER_MODE 0x02
/* events */
#define STMFTS_EV_NO_EVENT 0x00
@@ -72,12 +82,16 @@
#define STMFTS_EV_ERROR 0x0f
#define STMFTS_EV_NOISE_READ 0x17
#define STMFTS_EV_NOISE_WRITE 0x18
+#define STMFTS_EV_VENDOR 0x20
#define STMFTS_EV_CONTROLLER_READY 0x10
-#define STMFTS_EV_SLEEP_OUT_CONTROLLER_READY 0x11
#define STMFTS_EV_STATUS 0x16
#define STMFTS_EV_DEBUG 0xDB
+#define STMFTS_EV_STATUS_MS_CX_TUNING_DONE 1
+#define STMFTS_EV_STATUS_SS_CX_TUNING_DONE 2
+#define STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE 4
+
/* multi touch related event masks */
#define STMFTS_MASK_EVENT_ID 0x0F
#define STMFTS_MASK_TOUCH_ID 0xF0
@@ -95,16 +109,46 @@
#define STMFTS_DATA_MAX_SIZE (STMFTS_EVENT_SIZE * STMFTS_STACK_DEPTH)
#define STMFTS_MAX_FINGERS 10
+typedef enum _touch_ito_error {
+ ITO_NO_ERROR = 0,
+ ITO_FORCE_OPEN,
+ ITO_SENSE_OPEN,
+ ITO_FORCE_SHRT_GND,
+ ITO_SENSE_SHRT_GND,
+ ITO_FORCE_SHRT_VCM,
+ ITO_SENSE_SHRT_VCM,
+ ITO_FORCE_SHRT_FORCE,
+ ITO_SENSE_SHRT_SENSE,
+ ITO_F2E_SENSE,
+ ITO_FPC_FORCE_OPEN,
+ ITO_FPC_SENSE_OPEN,
+ ITO_KEY_FORCE_OPEN,
+ ITO_KEY_SENSE_OPEN,
+ ITO_RESERVED0,
+ ITO_RESERVED1,
+ ITO_RESERVED2,
+ ITO_MAX_ERR_REACHED = 0xFF
+} touch_ito_error;
+
typedef struct _touch_event {
u8 raw[8];
u16 type; // Event type.
u16 x; // Horizontal coordinates.
u16 y; // Vertical coordinates.
- u8 z;
+ u32 z;
u8 fingers;
bool touch;
} touch_event;
+typedef struct _touch_panel_info_t
+{
+ u8 idx;
+ u8 gpio0;
+ u8 gpio1;
+ u8 gpio2;
+ char *vendor;
+} touch_panel_info_t;
+
typedef struct _touch_info {
u16 chip_id;
u16 fw_ver;
@@ -112,10 +156,21 @@ typedef struct _touch_info {
u16 config_ver;
} touch_info;
-int touch_power_on();
-void touch_power_off();
+typedef struct _touch_fw_info_t {
+ u32 fw_id;
+ u16 ftb_ver;
+ u16 fw_rev;
+} touch_fw_info_t;
+
void touch_poll(touch_event *event);
touch_event touch_poll_wait();
+touch_panel_info_t *touch_get_panel_vendor();
+int touch_get_fw_info(touch_fw_info_t *fw);
touch_info touch_get_info();
+int touch_panel_ito_test(u8 *err);
+int touch_execute_autotune();
+int touch_sense_enable();
+int touch_power_on();
+void touch_power_off();
#endif /* __TOUCH_H_ */
\ No newline at end of file
diff --git a/bdk/libs/compr/blz.c b/bdk/libs/compr/blz.c
new file mode 100644
index 0000000..5bc9e49
--- /dev/null
+++ b/bdk/libs/compr/blz.c
@@ -0,0 +1,101 @@
+/*
+ * 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 .
+ */
+
+#include
+#include
+
+#include "blz.h"
+
+const blz_footer *blz_get_footer(const u8 *comp_data, u32 comp_data_size, blz_footer *out_footer)
+{
+ if (comp_data_size < sizeof(blz_footer))
+ return NULL;
+
+ const blz_footer *src_footer = (const blz_footer *)&comp_data[comp_data_size - sizeof(blz_footer)];
+ if (out_footer)
+ memcpy(out_footer, src_footer, sizeof(blz_footer)); // Must be a memcpy because no unaligned accesses on ARMv4.
+
+ return src_footer;
+}
+
+// From https://github.com/SciresM/hactool/blob/master/kip.c which is exactly how kernel does it, thanks SciresM!
+int blz_uncompress_inplace(u8 *data, u32 comp_size, 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;
+
+ u8 *cmp_start = &data[comp_size] - 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)
+ {
+ u8 control = cmp_start[--cmp_ofs];
+ for (u32 i = 0; i < 8; i++)
+ {
+ if (control & 0x80)
+ {
+ if (cmp_ofs < 2)
+ return 0; // Out of bounds.
+
+ cmp_ofs -= 2;
+ u16 seg_val = ((u32)(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;
+
+ // Kernel restricts segment copy to stay in bounds.
+ if (out_ofs < seg_size)
+ seg_size = out_ofs;
+
+ out_ofs -= seg_size;
+
+ for (u32 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) // Blz works backwards, so if it reaches byte 0, it's done.
+ return 1;
+ }
+ }
+
+ return 1;
+}
+
+int blz_uncompress_srcdest(const u8 *comp_data, u32 comp_data_size, u8 *dst_data, u32 dst_size)
+{
+ blz_footer footer;
+ const blz_footer *comp_footer = blz_get_footer(comp_data, comp_data_size, &footer);
+ if (!comp_footer)
+ return 0;
+
+ // Decompression happens in-place, so need to copy the relevant compressed data first.
+ u32 comp_bytes = (const u8 *)comp_footer - comp_data;
+ memcpy(dst_data, comp_data, comp_bytes);
+ memset(&dst_data[comp_bytes], 0, dst_size - comp_bytes);
+
+ return blz_uncompress_inplace(dst_data, comp_data_size, &footer);
+}
diff --git a/bootloader/libs/compr/blz.h b/bdk/libs/compr/blz.h
similarity index 63%
rename from bootloader/libs/compr/blz.h
rename to bdk/libs/compr/blz.h
index 4171049..bb058d8 100644
--- a/bootloader/libs/compr/blz.h
+++ b/bdk/libs/compr/blz.h
@@ -17,7 +17,7 @@
#ifndef _BLZ_H_
#define _BLZ_H_
-#include "../../utils/types.h"
+#include
typedef struct _blz_footer
{
@@ -26,11 +26,11 @@ typedef struct _blz_footer
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 pointer to footer in comp_data if present, additionally copies it to out_footer if not NULL.
+const blz_footer *blz_get_footer(const u8 *comp_data, u32 comp_data_size, blz_footer *out_footer);
// Returns 0 on failure.
-int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer);
+int blz_uncompress_inplace(u8 *data, u32 comp_size, 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);
+int blz_uncompress_srcdest(const u8 *comp_data, u32 comp_data_size, u8 *dst_data, u32 dst_size);
#endif
diff --git a/bootloader/libs/compr/lz.c b/bdk/libs/compr/lz.c
similarity index 98%
rename from bootloader/libs/compr/lz.c
rename to bdk/libs/compr/lz.c
index a17c6e4..94b64c6 100644
--- a/bootloader/libs/compr/lz.c
+++ b/bdk/libs/compr/lz.c
@@ -125,7 +125,7 @@ static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf )
* insize - Number of input bytes.
*************************************************************************/
-void LZ_Uncompress( const unsigned char *in, unsigned char *out,
+unsigned int LZ_Uncompress( const unsigned char *in, unsigned char *out,
unsigned int insize )
{
unsigned char marker, symbol;
@@ -134,7 +134,7 @@ void LZ_Uncompress( const unsigned char *in, unsigned char *out,
/* Do we have anything to uncompress? */
if( insize < 1 )
{
- return;
+ return 0;
}
/* Get marker symbol from input stream */
@@ -176,4 +176,6 @@ void LZ_Uncompress( const unsigned char *in, unsigned char *out,
}
}
while( inpos < insize );
+
+ return outpos;
}
diff --git a/bootloader/libs/compr/lz.h b/bdk/libs/compr/lz.h
similarity index 95%
rename from bootloader/libs/compr/lz.h
rename to bdk/libs/compr/lz.h
index 6f31b4a..ef67055 100644
--- a/bootloader/libs/compr/lz.h
+++ b/bdk/libs/compr/lz.h
@@ -41,7 +41,7 @@ extern "C" {
* Function prototypes
*************************************************************************/
-void LZ_Uncompress( const unsigned char *in, unsigned char *out,
+unsigned int LZ_Uncompress( const unsigned char *in, unsigned char *out,
unsigned int insize );
diff --git a/bdk/libs/compr/lz4.c b/bdk/libs/compr/lz4.c
new file mode 100644
index 0000000..d6c22c6
--- /dev/null
+++ b/bdk/libs/compr/lz4.c
@@ -0,0 +1,1671 @@
+/*
+ LZ4 - Fast LZ compression algorithm
+ Copyright (C) 2011-2017, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "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 COPYRIGHT
+ OWNER OR CONTRIBUTORS 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.
+
+ You can contact the author at :
+ - LZ4 homepage : http://www.lz4.org
+ - LZ4 source repository : https://github.com/lz4/lz4
+*/
+
+
+/*-************************************
+* Tuning parameters
+**************************************/
+/*
+ * ACCELERATION_DEFAULT :
+ * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
+ */
+#define ACCELERATION_DEFAULT 1
+
+
+/*-************************************
+* Dependency
+**************************************/
+#define LZ4_STATIC_LINKING_ONLY
+#include "lz4.h"
+/* see also "memory routines" below */
+
+
+/*-************************************
+* Compiler Options
+**************************************/
+#ifndef LZ4_FORCE_INLINE
+# ifdef _MSC_VER /* Visual Studio */
+# define LZ4_FORCE_INLINE static __forceinline
+# else
+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define LZ4_FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define LZ4_FORCE_INLINE static inline
+# endif
+# else
+# define LZ4_FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
+# endif /* _MSC_VER */
+#endif /* LZ4_FORCE_INLINE */
+
+/* LZ4_FORCE_O2_GCC_PPC64LE and LZ4_FORCE_O2_INLINE_GCC_PPC64LE
+ * Gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy,
+ * together with a simple 8-byte copy loop as a fall-back path.
+ * However, this optimization hurts the decompression speed by >30%,
+ * because the execution does not go to the optimized loop
+ * for typical compressible data, and all of the preamble checks
+ * before going to the fall-back path become useless overhead.
+ * This optimization happens only with the -O3 flag, and -O2 generates
+ * a simple 8-byte copy loop.
+ * With gcc on ppc64le, all of the LZ4_decompress_* and LZ4_wildCopy
+ * functions are annotated with __attribute__((optimize("O2"))),
+ * and also LZ4_wildCopy is forcibly inlined, so that the O2 attribute
+ * of LZ4_wildCopy does not affect the compression speed.
+ */
+#if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__)
+# define LZ4_FORCE_O2_GCC_PPC64LE __attribute__((optimize("O2")))
+# define LZ4_FORCE_O2_INLINE_GCC_PPC64LE __attribute__((optimize("O2"))) LZ4_FORCE_INLINE
+#else
+# define LZ4_FORCE_O2_GCC_PPC64LE
+# define LZ4_FORCE_O2_INLINE_GCC_PPC64LE static
+#endif
+
+/*-************************************
+* Memory routines
+**************************************/
+#include /* malloc, calloc, free */
+#define ALLOC(s) malloc(s)
+#define ALLOC_AND_ZERO(s) zalloc(s)
+#define FREEMEM free
+#include /* memset, memcpy */
+#define MEM_INIT memset
+
+
+/*-************************************
+* Basic Types
+**************************************/
+typedef uint16_t U16;
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint64_t U64;
+typedef uintptr_t uptrval;
+typedef size_t reg_t; /* 32-bits in x32 mode */
+
+/*-************************************
+* Reading and writing into memory
+**************************************/
+static unsigned LZ4_isLittleEndian(void)
+{
+ const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
+ return one.c[0];
+}
+
+static U16 LZ4_read16(const void* memPtr)
+{
+ U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
+}
+
+static U32 LZ4_read32(const void* memPtr)
+{
+ U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
+}
+
+static reg_t LZ4_read_ARCH(const void* memPtr)
+{
+ reg_t val; memcpy(&val, memPtr, sizeof(val)); return val;
+}
+
+static void LZ4_write16(void* memPtr, U16 value)
+{
+ memcpy(memPtr, &value, sizeof(value));
+}
+
+static void LZ4_write32(void* memPtr, U32 value)
+{
+ memcpy(memPtr, &value, sizeof(value));
+}
+
+static U16 LZ4_readLE16(const void* memPtr)
+{
+ if (LZ4_isLittleEndian()) {
+ return LZ4_read16(memPtr);
+ } else {
+ const BYTE* p = (const BYTE*)memPtr;
+ return (U16)((U16)p[0] + (p[1]<<8));
+ }
+}
+
+static void LZ4_writeLE16(void* memPtr, U16 value)
+{
+ if (LZ4_isLittleEndian()) {
+ LZ4_write16(memPtr, value);
+ } else {
+ BYTE* p = (BYTE*)memPtr;
+ p[0] = (BYTE) value;
+ p[1] = (BYTE)(value>>8);
+ }
+}
+
+/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */
+LZ4_FORCE_O2_INLINE_GCC_PPC64LE
+void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
+{
+ BYTE* d = (BYTE*)dstPtr;
+ const BYTE* s = (const BYTE*)srcPtr;
+ BYTE* const e = (BYTE*)dstEnd;
+
+ do { memcpy(d,s,8); d+=8; s+=8; } while (d=2)
+# include
+static int g_debuglog_enable = 1;
+# define DEBUGLOG(l, ...) { \
+ if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \
+ fprintf(stderr, __FILE__ ": "); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, " \n"); \
+ } }
+#else
+# define DEBUGLOG(l, ...) {} /* disabled */
+#endif
+
+
+/*-************************************
+* Common functions
+**************************************/
+static unsigned LZ4_NbCommonBytes (reg_t val)
+{
+ if (LZ4_isLittleEndian()) {
+ if (sizeof(val)==8) {
+ return (__builtin_ctzll((U64)val) >> 3);
+ } else /* 32 bits */ {
+ return (__builtin_ctz((U32)val) >> 3);
+ }
+ } else /* Big Endian CPU */ {
+ if (sizeof(val)==8) { /* 64-bits */
+ return (__builtin_clzll((U64)val) >> 3);
+ } else /* 32 bits */ {
+ return (__builtin_clz((U32)val) >> 3);
+ }
+ }
+}
+
+#define STEPSIZE sizeof(reg_t)
+LZ4_FORCE_INLINE
+unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
+{
+ const BYTE* const pStart = pIn;
+
+ if (likely(pIn < pInLimit-(STEPSIZE-1))) {
+ reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
+ if (!diff) {
+ pIn+=STEPSIZE; pMatch+=STEPSIZE;
+ } else {
+ return LZ4_NbCommonBytes(diff);
+ } }
+
+ while (likely(pIn < pInLimit-(STEPSIZE-1))) {
+ reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
+ if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
+ pIn += LZ4_NbCommonBytes(diff);
+ return (unsigned)(pIn - pStart);
+ }
+
+ if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
+ if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
+ if ((pIn compression run slower on incompressible data */
+
+
+/*-************************************
+* Local Structures and types
+**************************************/
+typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
+typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t;
+
+/**
+ * This enum distinguishes several different modes of accessing previous
+ * content in the stream.
+ *
+ * - noDict : There is no preceding content.
+ * - withPrefix64k : Table entries up to ctx->dictSize before the current blob
+ * blob being compressed are valid and refer to the preceding
+ * content (of length ctx->dictSize), which is available
+ * contiguously preceding in memory the content currently
+ * being compressed.
+ * - usingExtDict : Like withPrefix64k, but the preceding content is somewhere
+ * else in memory, starting at ctx->dictionary with length
+ * ctx->dictSize.
+ * - usingDictCtx : Like usingExtDict, but everything concerning the preceding
+ * content is in a separate context, pointed to by
+ * ctx->dictCtx. ctx->dictionary, ctx->dictSize, and table
+ * entries in the current context that refer to positions
+ * preceding the beginning of the current compression are
+ * ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx
+ * ->dictSize describe the location and size of the preceding
+ * content, and matches are found by looking in the ctx
+ * ->dictCtx->hashTable.
+ */
+typedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } dict_directive;
+typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
+
+typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
+typedef enum { full = 0, partial = 1 } earlyEnd_directive;
+
+
+/*-************************************
+* Local Utils
+**************************************/
+int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
+const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; }
+int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
+int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
+
+
+/*-******************************
+* Compression functions
+********************************/
+static U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
+{
+ if (tableType == byU16)
+ return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
+ else
+ return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
+}
+
+static U32 LZ4_hash5(U64 sequence, tableType_t const tableType)
+{
+ static const U64 prime5bytes = 889523592379ULL;
+ static const U64 prime8bytes = 11400714785074694791ULL;
+ const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
+ if (LZ4_isLittleEndian())
+ return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
+ else
+ return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
+}
+
+LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType)
+{
+ if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType);
+ return LZ4_hash4(LZ4_read32(p), tableType);
+}
+
+static void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType)
+{
+ switch (tableType)
+ {
+ default: /* fallthrough */
+ case clearedTable: /* fallthrough */
+ case byPtr: { /* illegal! */ return; }
+ case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = idx; return; }
+ case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)idx; return; }
+ }
+}
+
+static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
+{
+ switch (tableType)
+ {
+ case clearedTable: { /* illegal! */ return; }
+ case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
+ case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
+ case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
+ }
+}
+
+LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
+{
+ U32 const h = LZ4_hashPosition(p, tableType);
+ LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
+}
+
+/* LZ4_getIndexOnHash() :
+ * Index of match position registered in hash table.
+ * hash position must be calculated by using base+index, or dictBase+index.
+ * Assumption 1 : only valid if tableType == byU32 or byU16.
+ * Assumption 2 : h is presumed valid (within limits of hash table)
+ */
+static U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType)
+{
+ LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2);
+ if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; return hashTable[h]; }
+ if (tableType == byU16) { const U16* const hashTable = (const U16*) tableBase; return hashTable[h]; }
+ return 0; /* forbidden case */
+}
+
+static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType, const BYTE* srcBase)
+{
+ if (tableType == byPtr) { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; }
+ if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; return hashTable[h] + srcBase; }
+ { const U16* const hashTable = (const U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */
+}
+
+LZ4_FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, const void* tableBase, tableType_t tableType, const BYTE* srcBase)
+{
+ U32 const h = LZ4_hashPosition(p, tableType);
+ return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
+}
+
+LZ4_FORCE_INLINE void LZ4_prepareTable(
+ LZ4_stream_t_internal* const cctx,
+ const int inputSize,
+ const tableType_t tableType) {
+ /* If the table hasn't been used, it's guaranteed to be zeroed out, and is
+ * therefore safe to use no matter what mode we're in. Otherwise, we figure
+ * out if it's safe to leave as is or whether it needs to be reset.
+ */
+ if (cctx->tableType != clearedTable) {
+ if (cctx->tableType != tableType
+ || (tableType == byU16 && cctx->currentOffset + inputSize >= 0xFFFFU)
+ || (tableType == byU32 && cctx->currentOffset > 1 GB)
+ || tableType == byPtr
+ || inputSize >= 4 KB)
+ {
+ DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx);
+ MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE);
+ cctx->currentOffset = 0;
+ cctx->tableType = clearedTable;
+ } else {
+ DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)");
+ }
+ }
+
+ /* Adding a gap, so all previous entries are > MAX_DISTANCE back, is faster
+ * than compressing without a gap. However, compressing with
+ * currentOffset == 0 is faster still, so we preserve that case.
+ */
+ if (cctx->currentOffset != 0 && tableType == byU32) {
+ DEBUGLOG(5, "LZ4_prepareTable: adding 64KB to currentOffset");
+ cctx->currentOffset += 64 KB;
+ }
+
+ /* Finally, clear history */
+ cctx->dictCtx = NULL;
+ cctx->dictionary = NULL;
+ cctx->dictSize = 0;
+}
+
+/** LZ4_compress_generic() :
+ inlined, to ensure branches are decided at compilation time */
+LZ4_FORCE_INLINE int LZ4_compress_generic(
+ LZ4_stream_t_internal* const cctx,
+ const char* const source,
+ char* const dest,
+ const int inputSize,
+ const int maxOutputSize,
+ const limitedOutput_directive outputLimited,
+ const tableType_t tableType,
+ const dict_directive dictDirective,
+ const dictIssue_directive dictIssue,
+ const U32 acceleration)
+{
+ const BYTE* ip = (const BYTE*) source;
+
+ U32 const startIndex = cctx->currentOffset;
+ const BYTE* base = (const BYTE*) source - startIndex;
+ const BYTE* lowLimit;
+
+ const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx;
+ const BYTE* const dictionary =
+ dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary;
+ const U32 dictSize =
+ dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize;
+ const U32 dictDelta = (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; /* make indexes in dictCtx comparable with index in current context */
+
+ int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx);
+ U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */
+ const BYTE* const dictEnd = dictionary + dictSize;
+ const BYTE* anchor = (const BYTE*) source;
+ const BYTE* const iend = ip + inputSize;
+ const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1;
+ const BYTE* const matchlimit = iend - LASTLITERALS;
+
+ /* the dictCtx currentOffset is indexed on the start of the dictionary,
+ * while a dictionary in the current context precedes the currentOffset */
+ const BYTE* dictBase = dictDirective == usingDictCtx ?
+ dictionary + dictSize - dictCtx->currentOffset : /* is it possible that dictCtx->currentOffset != dictCtx->dictSize ? Yes if the dictionary context is not reset */
+ dictionary + dictSize - startIndex;
+
+ BYTE* op = (BYTE*) dest;
+ BYTE* const olimit = op + maxOutputSize;
+
+ U32 offset = 0;
+ U32 forwardH;
+
+ DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, tableType=%u", inputSize, tableType);
+ /* Init conditions */
+ if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported inputSize, too large (or negative) */
+
+ lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0);
+
+ if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
+
+ /* Update context state */
+ if (dictDirective == usingDictCtx) {
+ /* Subsequent linked blocks can't use the dictionary. */
+ /* Instead, they use the block we just compressed. */
+ cctx->dictCtx = NULL;
+ cctx->dictSize = (U32)inputSize;
+ } else {
+ cctx->dictSize += (U32)inputSize;
+ }
+ cctx->currentOffset += (U32)inputSize;
+ cctx->tableType = tableType;
+
+ if (inputSizehashTable, tableType, base);
+ ip++; forwardH = LZ4_hashPosition(ip, tableType);
+
+ /* Main Loop */
+ for ( ; ; ) {
+ const BYTE* match;
+ BYTE* token;
+
+ /* Find a match */
+ if (tableType == byPtr) {
+ const BYTE* forwardIp = ip;
+ unsigned step = 1;
+ unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
+ do {
+ U32 const h = forwardH;
+ ip = forwardIp;
+ forwardIp += step;
+ step = (searchMatchNb++ >> LZ4_skipTrigger);
+
+ if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals;
+
+ match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base);
+ forwardH = LZ4_hashPosition(forwardIp, tableType);
+ LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base);
+
+ } while ( (match+MAX_DISTANCE < ip)
+ || (LZ4_read32(match) != LZ4_read32(ip)) );
+
+ } else { /* byU32, byU16 */
+
+ const BYTE* forwardIp = ip;
+ unsigned step = 1;
+ unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
+ do {
+ U32 const h = forwardH;
+ U32 const current = (U32)(forwardIp - base);
+ U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType);
+ ip = forwardIp;
+ forwardIp += step;
+ step = (searchMatchNb++ >> LZ4_skipTrigger);
+
+ if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals;
+
+ if (dictDirective == usingDictCtx) {
+ if (matchIndex < startIndex) {
+ /* there was no match, try the dictionary */
+ matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32);
+ match = dictBase + matchIndex;
+ matchIndex += dictDelta; /* make dictCtx index comparable with current context */
+ lowLimit = dictionary;
+ } else {
+ match = base + matchIndex;
+ lowLimit = (const BYTE*)source;
+ }
+ } else if (dictDirective==usingExtDict) {
+ if (matchIndex < startIndex) {
+ DEBUGLOG(7, "extDict candidate: matchIndex=%5u < startIndex=%5u", matchIndex, startIndex);
+ match = dictBase + matchIndex;
+ lowLimit = dictionary;
+ } else {
+ match = base + matchIndex;
+ lowLimit = (const BYTE*)source;
+ }
+ } else { /* single continuous memory segment */
+ match = base + matchIndex;
+ }
+ forwardH = LZ4_hashPosition(forwardIp, tableType);
+ LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);
+
+ if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) continue; /* match outside of valid area */
+ if ((tableType != byU16) && (current - matchIndex > MAX_DISTANCE)) continue; /* too far - note: works even if matchIndex overflows */
+
+ if (LZ4_read32(match) == LZ4_read32(ip)) {
+ if (maybe_extMem) offset = current - matchIndex;
+ break; /* match found */
+ }
+
+ } while(1);
+ }
+
+ /* Catch up */
+ while (((ip>anchor) & (match > lowLimit)) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
+
+ /* Encode Literals */
+ { unsigned const litLength = (unsigned)(ip - anchor);
+ token = op++;
+ if ((outputLimited) && /* Check output buffer overflow */
+ (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)))
+ return 0;
+ if (litLength >= RUN_MASK) {
+ int len = (int)litLength-RUN_MASK;
+ *token = (RUN_MASK<= 255 ; len-=255) *op++ = 255;
+ *op++ = (BYTE)len;
+ }
+ else *token = (BYTE)(litLength< matchlimit) limit = matchlimit;
+ matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
+ ip += MINMATCH + matchCode;
+ if (ip==limit) {
+ unsigned const more = LZ4_count(limit, (const BYTE*)source, matchlimit);
+ matchCode += more;
+ ip += more;
+ }
+ DEBUGLOG(6, " with matchLength=%u starting in extDict", matchCode+MINMATCH);
+ } else {
+ matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
+ ip += MINMATCH + matchCode;
+ DEBUGLOG(6, " with matchLength=%u", matchCode+MINMATCH);
+ }
+
+ if ( outputLimited && /* Check output buffer overflow */
+ (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) )
+ return 0;
+ if (matchCode >= ML_MASK) {
+ *token += ML_MASK;
+ matchCode -= ML_MASK;
+ LZ4_write32(op, 0xFFFFFFFF);
+ while (matchCode >= 4*255) {
+ op+=4;
+ LZ4_write32(op, 0xFFFFFFFF);
+ matchCode -= 4*255;
+ }
+ op += matchCode / 255;
+ *op++ = (BYTE)(matchCode % 255);
+ } else
+ *token += (BYTE)(matchCode);
+ }
+
+ anchor = ip;
+
+ /* Test end of chunk */
+ if (ip >= mflimitPlusOne) break;
+
+ /* Fill table */
+ LZ4_putPosition(ip-2, cctx->hashTable, tableType, base);
+
+ /* Test next position */
+ if (tableType == byPtr) {
+
+ match = LZ4_getPosition(ip, cctx->hashTable, tableType, base);
+ LZ4_putPosition(ip, cctx->hashTable, tableType, base);
+ if ( (match+MAX_DISTANCE >= ip)
+ && (LZ4_read32(match) == LZ4_read32(ip)) )
+ { token=op++; *token=0; goto _next_match; }
+
+ } else { /* byU32, byU16 */
+
+ U32 const h = LZ4_hashPosition(ip, tableType);
+ U32 const current = (U32)(ip-base);
+ U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType);
+ if (dictDirective == usingDictCtx) {
+ if (matchIndex < startIndex) {
+ /* there was no match, try the dictionary */
+ matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32);
+ match = dictBase + matchIndex;
+ lowLimit = dictionary; /* required for match length counter */
+ matchIndex += dictDelta;
+ } else {
+ match = base + matchIndex;
+ lowLimit = (const BYTE*)source; /* required for match length counter */
+ }
+ } else if (dictDirective==usingExtDict) {
+ if (matchIndex < startIndex) {
+ match = dictBase + matchIndex;
+ lowLimit = dictionary; /* required for match length counter */
+ } else {
+ match = base + matchIndex;
+ lowLimit = (const BYTE*)source; /* required for match length counter */
+ }
+ } else { /* single memory segment */
+ match = base + matchIndex;
+ }
+ LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);
+ if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1)
+ && ((tableType==byU16) ? 1 : (current - matchIndex <= MAX_DISTANCE))
+ && (LZ4_read32(match) == LZ4_read32(ip)) ) {
+ token=op++;
+ *token=0;
+ if (maybe_extMem) offset = current - matchIndex;
+ DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i", (int)(anchor-(const BYTE*)source), 0, (int)(ip-(const BYTE*)source));
+ goto _next_match;
+ }
+ }
+
+ /* Prepare next loop */
+ forwardH = LZ4_hashPosition(++ip, tableType);
+
+ }
+
+_last_literals:
+ /* Encode Last Literals */
+ { size_t const lastRun = (size_t)(iend - anchor);
+ if ( (outputLimited) && /* Check output buffer overflow */
+ ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) )
+ return 0;
+ if (lastRun >= RUN_MASK) {
+ size_t accumulator = lastRun - RUN_MASK;
+ *op++ = RUN_MASK << ML_BITS;
+ for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
+ *op++ = (BYTE) accumulator;
+ } else {
+ *op++ = (BYTE)(lastRun<internal_donotuse;
+ if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
+ LZ4_resetStream((LZ4_stream_t*)state);
+ if (maxOutputSize >= LZ4_compressBound(inputSize)) {
+ if (inputSize < LZ4_64Klimit) {
+ return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
+ } else {
+ const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > MAX_DISTANCE)) ? byPtr : byU32;
+ return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, tableType, noDict, noDictIssue, acceleration);
+ }
+ } else {
+ if (inputSize < LZ4_64Klimit) {;
+ return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
+ } else {
+ const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > MAX_DISTANCE)) ? byPtr : byU32;
+ return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, noDict, noDictIssue, acceleration);
+ }
+ }
+}
+
+/**
+ * LZ4_compress_fast_extState_fastReset() :
+ * A variant of LZ4_compress_fast_extState().
+ *
+ * Using this variant avoids an expensive initialization step. It is only safe
+ * to call if the state buffer is known to be correctly initialized already
+ * (see comment in lz4.h on LZ4_resetStream_fast() for a definition of
+ * "correctly initialized").
+ */
+int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration)
+{
+ LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse;
+ if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
+
+ if (dstCapacity >= LZ4_compressBound(srcSize)) {
+ if (srcSize < LZ4_64Klimit) {
+ const tableType_t tableType = byU16;
+ LZ4_prepareTable(ctx, srcSize, tableType);
+ if (ctx->currentOffset) {
+ return LZ4_compress_generic(ctx, src, dst, srcSize, 0, notLimited, tableType, noDict, dictSmall, acceleration);
+ } else {
+ return LZ4_compress_generic(ctx, src, dst, srcSize, 0, notLimited, tableType, noDict, noDictIssue, acceleration);
+ }
+ } else {
+ const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > MAX_DISTANCE)) ? byPtr : byU32;
+ LZ4_prepareTable(ctx, srcSize, tableType);
+ return LZ4_compress_generic(ctx, src, dst, srcSize, 0, notLimited, tableType, noDict, noDictIssue, acceleration);
+ }
+ } else {
+ if (srcSize < LZ4_64Klimit) {
+ const tableType_t tableType = byU16;
+ LZ4_prepareTable(ctx, srcSize, tableType);
+ if (ctx->currentOffset) {
+ return LZ4_compress_generic(ctx, src, dst, srcSize, dstCapacity, limitedOutput, tableType, noDict, dictSmall, acceleration);
+ } else {
+ return LZ4_compress_generic(ctx, src, dst, srcSize, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration);
+ }
+ } else {
+ const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > MAX_DISTANCE)) ? byPtr : byU32;
+ LZ4_prepareTable(ctx, srcSize, tableType);
+ return LZ4_compress_generic(ctx, src, dst, srcSize, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration);
+ }
+ }
+}
+
+
+int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
+{
+ int result;
+ LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
+ LZ4_stream_t* const ctxPtr = ctx;
+ result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
+
+ FREEMEM(ctx);
+
+ return result;
+}
+
+
+int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)
+{
+ return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
+}
+
+
+/* hidden debug function */
+/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
+int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
+{
+ int result;
+ LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
+ LZ4_resetStream(ctx);
+
+ if (inputSize < LZ4_64Klimit)
+ result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
+ else
+ result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
+
+ FREEMEM(ctx);
+
+ return result;
+}
+
+
+/*-******************************
+* *_destSize() variant
+********************************/
+
+static int LZ4_compress_destSize_generic(
+ LZ4_stream_t_internal* const ctx,
+ const char* const src,
+ char* const dst,
+ int* const srcSizePtr,
+ const int targetDstSize,
+ const tableType_t tableType)
+{
+ const BYTE* ip = (const BYTE*) src;
+ const BYTE* base = (const BYTE*) src;
+ const BYTE* lowLimit = (const BYTE*) src;
+ const BYTE* anchor = ip;
+ const BYTE* const iend = ip + *srcSizePtr;
+ const BYTE* const mflimit = iend - MFLIMIT;
+ const BYTE* const matchlimit = iend - LASTLITERALS;
+
+ BYTE* op = (BYTE*) dst;
+ BYTE* const oend = op + targetDstSize;
+ BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
+ BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
+ BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
+
+ U32 forwardH;
+
+
+ /* Init conditions */
+ if (targetDstSize < 1) return 0; /* Impossible to store anything */
+ if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
+ if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
+ if (*srcSizePtrhashTable, tableType, base);
+ ip++; forwardH = LZ4_hashPosition(ip, tableType);
+
+ /* Main Loop */
+ for ( ; ; ) {
+ const BYTE* match;
+ BYTE* token;
+
+ /* Find a match */
+ { const BYTE* forwardIp = ip;
+ unsigned step = 1;
+ unsigned searchMatchNb = 1 << LZ4_skipTrigger;
+
+ do {
+ U32 h = forwardH;
+ ip = forwardIp;
+ forwardIp += step;
+ step = (searchMatchNb++ >> LZ4_skipTrigger);
+
+ if (unlikely(forwardIp > mflimit)) goto _last_literals;
+
+ match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base);
+ forwardH = LZ4_hashPosition(forwardIp, tableType);
+ LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base);
+
+ } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
+ || (LZ4_read32(match) != LZ4_read32(ip)) );
+ }
+
+ /* Catch up */
+ while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
+
+ /* Encode Literal length */
+ { unsigned litLength = (unsigned)(ip - anchor);
+ token = op++;
+ if (op + ((litLength+240)/255) + litLength > oMaxLit) {
+ /* Not enough space for a last match */
+ op--;
+ goto _last_literals;
+ }
+ if (litLength>=RUN_MASK) {
+ unsigned len = litLength - RUN_MASK;
+ *token=(RUN_MASK<= 255 ; len-=255) *op++ = 255;
+ *op++ = (BYTE)len;
+ }
+ else *token = (BYTE)(litLength< oMaxMatch) {
+ /* Match description too long : reduce it */
+ matchLength = (15-1) + (oMaxMatch-op) * 255;
+ }
+ ip += MINMATCH + matchLength;
+
+ if (matchLength>=ML_MASK) {
+ *token += ML_MASK;
+ matchLength -= ML_MASK;
+ while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
+ *op++ = (BYTE)matchLength;
+ }
+ else *token += (BYTE)(matchLength);
+ }
+
+ anchor = ip;
+
+ /* Test end of block */
+ if (ip > mflimit) break;
+ if (op > oMaxSeq) break;
+
+ /* Fill table */
+ LZ4_putPosition(ip-2, ctx->hashTable, tableType, base);
+
+ /* Test next position */
+ match = LZ4_getPosition(ip, ctx->hashTable, tableType, base);
+ LZ4_putPosition(ip, ctx->hashTable, tableType, base);
+ if ( (match+MAX_DISTANCE>=ip)
+ && (LZ4_read32(match)==LZ4_read32(ip)) )
+ { token=op++; *token=0; goto _next_match; }
+
+ /* Prepare next loop */
+ forwardH = LZ4_hashPosition(++ip, tableType);
+ }
+
+_last_literals:
+ /* Encode Last Literals */
+ { size_t lastRunSize = (size_t)(iend - anchor);
+ if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) {
+ /* adapt lastRunSize to fill 'dst' */
+ lastRunSize = (oend-op) - 1;
+ lastRunSize -= (lastRunSize+240)/255;
+ }
+ ip = anchor + lastRunSize;
+
+ if (lastRunSize >= RUN_MASK) {
+ size_t accumulator = lastRunSize - RUN_MASK;
+ *op++ = RUN_MASK << ML_BITS;
+ for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
+ *op++ = (BYTE) accumulator;
+ } else {
+ *op++ = (BYTE)(lastRunSize<= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */
+ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
+ } else {
+ if (*srcSizePtr < LZ4_64Klimit) {
+ return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, byU16);
+ } else {
+ tableType_t const tableType = ((sizeof(void*)==4) && ((uptrval)src > MAX_DISTANCE)) ? byPtr : byU32;
+ return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, tableType);
+ } }
+}
+
+
+int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
+{
+ LZ4_stream_t* ctxBody = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));;
+ LZ4_stream_t* ctx = ctxBody;
+
+ int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
+
+ FREEMEM(ctxBody);
+
+ return result;
+}
+
+
+
+/*-******************************
+* Streaming functions
+********************************/
+
+LZ4_stream_t* LZ4_createStream(void)
+{
+ LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
+ LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */
+ DEBUGLOG(4, "LZ4_createStream %p", lz4s);
+ if (lz4s == NULL) return NULL;
+ LZ4_resetStream(lz4s);
+ return lz4s;
+}
+
+void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
+{
+ DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream);
+ MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t));
+}
+
+void LZ4_resetStream_fast(LZ4_stream_t* ctx) {
+ LZ4_prepareTable(&(ctx->internal_donotuse), 0, byU32);
+}
+
+int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
+{
+ if (!LZ4_stream) return 0; /* support free on NULL */
+ DEBUGLOG(5, "LZ4_freeStream %p", LZ4_stream);
+ FREEMEM(LZ4_stream);
+ return (0);
+}
+
+
+#define HASH_UNIT sizeof(reg_t)
+int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
+{
+ LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse;
+ const tableType_t tableType = byU32;
+ const BYTE* p = (const BYTE*)dictionary;
+ const BYTE* const dictEnd = p + dictSize;
+ const BYTE* base;
+
+ DEBUGLOG(4, "LZ4_loadDict (%i bytes from %p into %p)", dictSize, dictionary, LZ4_dict);
+
+ LZ4_prepareTable(dict, 0, tableType);
+
+ /* We always increment the offset by 64 KB, since, if the dict is longer,
+ * we truncate it to the last 64k, and if it's shorter, we still want to
+ * advance by a whole window length so we can provide the guarantee that
+ * there are only valid offsets in the window, which allows an optimization
+ * in LZ4_compress_fast_continue() where it uses noDictIssue even when the
+ * dictionary isn't a full 64k. */
+
+ if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
+ base = dictEnd - 64 KB - dict->currentOffset;
+ dict->dictionary = p;
+ dict->dictSize = (U32)(dictEnd - p);
+ dict->currentOffset += 64 KB;
+ dict->tableType = tableType;
+
+ if (dictSize < (int)HASH_UNIT) {
+ return 0;
+ }
+
+ while (p <= dictEnd-HASH_UNIT) {
+ LZ4_putPosition(p, dict->hashTable, tableType, base);
+ p+=3;
+ }
+
+ return dict->dictSize;
+}
+
+void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dictionary_stream) {
+ if (dictionary_stream != NULL) {
+ /* If the current offset is zero, we will never look in the
+ * external dictionary context, since there is no value a table
+ * entry can take that indicate a miss. In that case, we need
+ * to bump the offset to something non-zero.
+ */
+ if (working_stream->internal_donotuse.currentOffset == 0) {
+ working_stream->internal_donotuse.currentOffset = 64 KB;
+ }
+ working_stream->internal_donotuse.dictCtx = &(dictionary_stream->internal_donotuse);
+ } else {
+ working_stream->internal_donotuse.dictCtx = NULL;
+ }
+}
+
+
+static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, int nextSize)
+{
+ if (LZ4_dict->currentOffset + nextSize > 0x80000000) { /* potential ptrdiff_t overflow (32-bits mode) */
+ /* rescale hash table */
+ U32 const delta = LZ4_dict->currentOffset - 64 KB;
+ const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
+ int i;
+ DEBUGLOG(4, "LZ4_renormDictT");
+ for (i=0; ihashTable[i] < delta) LZ4_dict->hashTable[i]=0;
+ else LZ4_dict->hashTable[i] -= delta;
+ }
+ LZ4_dict->currentOffset = 64 KB;
+ if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;
+ LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
+ }
+}
+
+
+int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
+{
+ const tableType_t tableType = byU32;
+ LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse;
+ const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
+
+ if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */
+ LZ4_renormDictT(streamPtr, inputSize); /* avoid index overflow */
+ if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
+
+ /* Check overlapping input/dictionary space */
+ { const BYTE* sourceEnd = (const BYTE*) source + inputSize;
+ if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) {
+ streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
+ if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
+ if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
+ streamPtr->dictionary = dictEnd - streamPtr->dictSize;
+ }
+ }
+
+ /* prefix mode : source data follows dictionary */
+ if (dictEnd == (const BYTE*)source) {
+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
+ return LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, withPrefix64k, dictSmall, acceleration);
+ else
+ return LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, withPrefix64k, noDictIssue, acceleration);
+ }
+
+ /* external dictionary mode */
+ { int result;
+ if (streamPtr->dictCtx) {
+ /* We depend here on the fact that dictCtx'es (produced by
+ * LZ4_loadDict) guarantee that their tables contain no references
+ * to offsets between dictCtx->currentOffset - 64 KB and
+ * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe
+ * to use noDictIssue even when the dict isn't a full 64 KB.
+ */
+ if (inputSize > 4 KB) {
+ /* For compressing large blobs, it is faster to pay the setup
+ * cost to copy the dictionary's tables into the active context,
+ * so that the compression loop is only looking into one table.
+ */
+ memcpy(streamPtr, streamPtr->dictCtx, sizeof(LZ4_stream_t));
+ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);
+ } else {
+ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration);
+ }
+ } else {
+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {
+ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, usingExtDict, dictSmall, acceleration);
+ } else {
+ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);
+ }
+ }
+ streamPtr->dictionary = (const BYTE*)source;
+ streamPtr->dictSize = (U32)inputSize;
+ return result;
+ }
+}
+
+
+/* Hidden debug function, to force-test external dictionary mode */
+int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize)
+{
+ LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse;
+ int result;
+
+ LZ4_renormDictT(streamPtr, srcSize);
+
+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {
+ result = LZ4_compress_generic(streamPtr, source, dest, srcSize, 0, notLimited, byU32, usingExtDict, dictSmall, 1);
+ } else {
+ result = LZ4_compress_generic(streamPtr, source, dest, srcSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
+ }
+
+ streamPtr->dictionary = (const BYTE*)source;
+ streamPtr->dictSize = (U32)srcSize;
+
+ return result;
+}
+
+
+/*! LZ4_saveDict() :
+ * If previously compressed data block is not guaranteed to remain available at its memory location,
+ * save it into a safer place (char* safeBuffer).
+ * Note : you don't need to call LZ4_loadDict() afterwards,
+ * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue().
+ * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
+ */
+int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
+{
+ LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
+ const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
+
+ if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */
+ if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
+
+ memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
+
+ dict->dictionary = (const BYTE*)safeBuffer;
+ dict->dictSize = (U32)dictSize;
+
+ return dictSize;
+}
+
+
+
+/*-*****************************
+* Decompression functions
+*******************************/
+/*! LZ4_decompress_generic() :
+ * This generic decompression function covers all use cases.
+ * It shall be instantiated several times, using different sets of directives.
+ * Note that it is important for performance that this function really get inlined,
+ * in order to remove useless branches during compilation optimization.
+ */
+LZ4_FORCE_O2_GCC_PPC64LE
+LZ4_FORCE_INLINE int LZ4_decompress_generic(
+ const char* const src,
+ char* const dst,
+ int srcSize,
+ int outputSize, /* If endOnInput==endOnInputSize, this value is `dstCapacity` */
+
+ int endOnInput, /* endOnOutputSize, endOnInputSize */
+ int partialDecoding, /* full, partial */
+ int targetOutputSize, /* only used if partialDecoding==partial */
+ int dict, /* noDict, withPrefix64k, usingExtDict */
+ const BYTE* const lowPrefix, /* always <= dst, == dst when no prefix */
+ const BYTE* const dictStart, /* only if dict==usingExtDict */
+ const size_t dictSize /* note : = 0 if noDict */
+ )
+{
+ const BYTE* ip = (const BYTE*) src;
+ const BYTE* const iend = ip + srcSize;
+
+ BYTE* op = (BYTE*) dst;
+ BYTE* const oend = op + outputSize;
+ BYTE* cpy;
+ BYTE* oexit = op + targetOutputSize;
+
+ const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
+ const unsigned inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};
+ const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
+
+ const int safeDecode = (endOnInput==endOnInputSize);
+ const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
+
+
+ /* Special cases */
+ if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => just decode everything */
+ if ((endOnInput) && (unlikely(outputSize==0))) return ((srcSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
+ if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
+
+ /* Main Loop : decode sequences */
+ while (1) {
+ size_t length;
+ const BYTE* match;
+ size_t offset;
+
+ unsigned const token = *ip++;
+
+ /* shortcut for common case :
+ * in most circumstances, we expect to decode small matches (<= 18 bytes) separated by few literals (<= 14 bytes).
+ * this shortcut was tested on x86 and x64, where it improves decoding speed.
+ * it has not yet been benchmarked on ARM, Power, mips, etc. */
+ if (((ip + 14 /*maxLL*/ + 2 /*offset*/ <= iend)
+ & (op + 14 /*maxLL*/ + 18 /*maxML*/ <= oend))
+ & ((token < (15<> ML_BITS;
+ size_t const off = LZ4_readLE16(ip+ll);
+ const BYTE* const matchPtr = op + ll - off; /* pointer underflow risk ? */
+ if ((off >= 8) /* do not deal with overlapping matches */ & (matchPtr >= lowPrefix)) {
+ size_t const ml = (token & ML_MASK) + MINMATCH;
+ memcpy(op, ip, 16); op += ll; ip += ll + 2 /*offset*/;
+ memcpy(op + 0, matchPtr + 0, 8);
+ memcpy(op + 8, matchPtr + 8, 8);
+ memcpy(op +16, matchPtr +16, 2);
+ op += ml;
+ continue;
+ }
+ }
+
+ /* decode literal length */
+ if ((length=(token>>ML_BITS)) == RUN_MASK) {
+ unsigned s;
+ do {
+ s = *ip++;
+ length += s;
+ } while ( likely(endOnInput ? ip(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
+ || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) )
+ {
+ if (partialDecoding) {
+ if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */
+ if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
+ } else {
+ if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
+ if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
+ }
+ memcpy(op, ip, length);
+ ip += length;
+ op += length;
+ break; /* Necessarily EOF, due to parsing restrictions */
+ }
+ LZ4_wildCopy(op, ip, cpy);
+ ip += length; op = cpy;
+
+ /* get offset */
+ offset = LZ4_readLE16(ip); ip+=2;
+ match = op - offset;
+ if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */
+ LZ4_write32(op, (U32)offset); /* costs ~1%; silence an msan warning when offset==0 */
+
+ /* get matchlength */
+ length = token & ML_MASK;
+ if (length == ML_MASK) {
+ unsigned s;
+ do {
+ s = *ip++;
+ if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
+ length += s;
+ } while (s==255);
+ if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */
+ }
+ length += MINMATCH;
+
+ /* check external dictionary */
+ if ((dict==usingExtDict) && (match < lowPrefix)) {
+ if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
+
+ if (length <= (size_t)(lowPrefix-match)) {
+ /* match can be copied as a single segment from external dictionary */
+ memmove(op, dictEnd - (lowPrefix-match), length);
+ op += length;
+ } else {
+ /* match encompass external dictionary and current block */
+ size_t const copySize = (size_t)(lowPrefix-match);
+ size_t const restSize = length - copySize;
+ memcpy(op, dictEnd - copySize, copySize);
+ op += copySize;
+ if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */
+ BYTE* const endOfMatch = op + restSize;
+ const BYTE* copyFrom = lowPrefix;
+ while (op < endOfMatch) *op++ = *copyFrom++;
+ } else {
+ memcpy(op, lowPrefix, restSize);
+ op += restSize;
+ } }
+ continue;
+ }
+
+ /* copy match within block */
+ cpy = op + length;
+ if (unlikely(offset<8)) {
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += inc32table[offset];
+ memcpy(op+4, match, 4);
+ match -= dec64table[offset];
+ } else { memcpy(op, match, 8); match+=8; }
+ op += 8;
+
+ if (unlikely(cpy>oend-12)) {
+ BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1);
+ if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
+ if (op < oCopyLimit) {
+ LZ4_wildCopy(op, match, oCopyLimit);
+ match += oCopyLimit - op;
+ op = oCopyLimit;
+ }
+ while (op16) LZ4_wildCopy(op+8, match+8, cpy);
+ }
+ op = cpy; /* correction */
+ }
+
+ /* end of decoding */
+ if (endOnInput)
+ return (int) (((char*)op)-dst); /* Nb of output bytes decoded */
+ else
+ return (int) (((const char*)ip)-src); /* Nb of input bytes read */
+
+ /* Overflow error detected */
+_output_error:
+ return (int) (-(((const char*)ip)-src))-1;
+}
+
+
+LZ4_FORCE_O2_GCC_PPC64LE
+int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
+}
+
+LZ4_FORCE_O2_GCC_PPC64LE
+int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
+}
+
+LZ4_FORCE_O2_GCC_PPC64LE
+int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
+{
+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB);
+}
+
+
+/*===== streaming decompression functions =====*/
+
+LZ4_streamDecode_t* LZ4_createStreamDecode(void)
+{
+ LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t));
+ return lz4s;
+}
+
+int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
+{
+ if (!LZ4_stream) return 0; /* support free on NULL */
+ FREEMEM(LZ4_stream);
+ return 0;
+}
+
+/*!
+ * LZ4_setStreamDecode() :
+ * Use this function to instruct where to find the dictionary.
+ * This function is not necessary if previous data is still available where it was decoded.
+ * Loading a size of 0 is allowed (same effect as no dictionary).
+ * Return : 1 if OK, 0 if error
+ */
+int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
+{
+ LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
+ lz4sd->prefixSize = (size_t) dictSize;
+ lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
+ lz4sd->externalDict = NULL;
+ lz4sd->extDictSize = 0;
+ return 1;
+}
+
+/*
+*_continue() :
+ These decoding functions allow decompression of multiple blocks in "streaming" mode.
+ Previously decoded blocks must still be available at the memory position where they were decoded.
+ If it's not possible, save the relevant part of decoded data into a safe buffer,
+ and indicate where it stands using LZ4_setStreamDecode()
+*/
+LZ4_FORCE_O2_GCC_PPC64LE
+int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
+{
+ LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
+ int result;
+
+ if (lz4sd->prefixEnd == (BYTE*)dest) {
+ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
+ endOnInputSize, full, 0,
+ usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0) return result;
+ lz4sd->prefixSize += result;
+ lz4sd->prefixEnd += result;
+ } else {
+ lz4sd->extDictSize = lz4sd->prefixSize;
+ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
+ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
+ endOnInputSize, full, 0,
+ usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0) return result;
+ lz4sd->prefixSize = result;
+ lz4sd->prefixEnd = (BYTE*)dest + result;
+ }
+
+ return result;
+}
+
+LZ4_FORCE_O2_GCC_PPC64LE
+int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
+{
+ LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
+ int result;
+
+ if (lz4sd->prefixEnd == (BYTE*)dest) {
+ result = LZ4_decompress_generic(source, dest, 0, originalSize,
+ endOnOutputSize, full, 0,
+ usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0) return result;
+ lz4sd->prefixSize += originalSize;
+ lz4sd->prefixEnd += originalSize;
+ } else {
+ lz4sd->extDictSize = lz4sd->prefixSize;
+ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
+ result = LZ4_decompress_generic(source, dest, 0, originalSize,
+ endOnOutputSize, full, 0,
+ usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0) return result;
+ lz4sd->prefixSize = originalSize;
+ lz4sd->prefixEnd = (BYTE*)dest + originalSize;
+ }
+
+ return result;
+}
+
+
+/*
+Advanced decoding functions :
+*_usingDict() :
+ These decoding functions work the same as "_continue" ones,
+ the dictionary must be explicitly provided within parameters
+*/
+
+LZ4_FORCE_O2_GCC_PPC64LE
+LZ4_FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
+{
+ if (dictSize==0)
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);
+ if (dictStart+dictSize == dest) {
+ if (dictSize >= (int)(64 KB - 1))
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
+ }
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
+}
+
+LZ4_FORCE_O2_GCC_PPC64LE
+int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
+{
+ return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
+}
+
+LZ4_FORCE_O2_GCC_PPC64LE
+int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
+{
+ return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
+}
+
+/* debug function */
+LZ4_FORCE_O2_GCC_PPC64LE
+int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
+}
+
+
+/*=*************************************************
+* Obsolete Functions
+***************************************************/
+/* obsolete compression functions */
+int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); }
+int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); }
+int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); }
+int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); }
+int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); }
+int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); }
+
+/*
+These function names are deprecated and should no longer be used.
+They are only provided here for compatibility with older user programs.
+- LZ4_uncompress is totally equivalent to LZ4_decompress_fast
+- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe
+*/
+int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); }
+int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); }
+
+/* Obsolete Streaming functions */
+
+int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }
+
+int LZ4_resetStreamState(void* state, char* inputBuffer)
+{
+ (void)inputBuffer;
+ LZ4_resetStream((LZ4_stream_t*)state);
+ return 0;
+}
+
+void* LZ4_create (char* inputBuffer)
+{
+ (void)inputBuffer;
+ return LZ4_createStream();
+}
+
+char* LZ4_slideInputBuffer (void* state)
+{
+ /* avoid const char * -> char * conversion warning */
+ return (char *)(uptrval)((LZ4_stream_t*)state)->internal_donotuse.dictionary;
+}
+
+/* Obsolete streaming decompression functions */
+
+int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
+}
+
+int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
+{
+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
+}
+
+#endif /* LZ4_COMMONDEFS_ONLY */
diff --git a/bdk/libs/compr/lz4.h b/bdk/libs/compr/lz4.h
new file mode 100644
index 0000000..0dfa19e
--- /dev/null
+++ b/bdk/libs/compr/lz4.h
@@ -0,0 +1,569 @@
+/*
+ * LZ4 - Fast LZ compression algorithm
+ * Header File
+ * Copyright (C) 2011-2017, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "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 COPYRIGHT
+ OWNER OR CONTRIBUTORS 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.
+
+ You can contact the author at :
+ - LZ4 homepage : http://www.lz4.org
+ - LZ4 source repository : https://github.com/lz4/lz4
+*/
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#ifndef LZ4_H_2983827168210
+#define LZ4_H_2983827168210
+
+/* --- Dependency --- */
+#include /* size_t */
+
+
+/**
+ Introduction
+
+ LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core,
+ scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
+ multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
+
+ The LZ4 compression library provides in-memory compression and decompression functions.
+ Compression can be done in:
+ - a single step (described as Simple Functions)
+ - a single step, reusing a context (described in Advanced Functions)
+ - unbounded multiple steps (described as Streaming compression)
+
+ lz4.h provides block compression functions. It gives full buffer control to user.
+ Decompressing an lz4-compressed block also requires metadata (such as compressed size).
+ Each application is free to encode such metadata in whichever way it wants.
+
+ An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md),
+ take care of encoding standard metadata alongside LZ4-compressed blocks.
+ If your application requires interoperability, it's recommended to use it.
+ A library is provided to take care of it, see lz4frame.h.
+*/
+
+/*^***************************************************************
+* Export parameters
+*****************************************************************/
+/*
+* LZ4_DLL_EXPORT :
+* Enable exporting of functions when building a Windows DLL
+* LZ4LIB_VISIBILITY :
+* Control library symbols visibility.
+*/
+#ifndef LZ4LIB_VISIBILITY
+# if defined(__GNUC__) && (__GNUC__ >= 4)
+# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
+# else
+# define LZ4LIB_VISIBILITY
+# endif
+#endif
+#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
+# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
+#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
+# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
+#else
+# define LZ4LIB_API LZ4LIB_VISIBILITY
+#endif
+
+/*------ Version ------*/
+#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
+#define LZ4_VERSION_MINOR 8 /* for new (non-breaking) interface capabilities */
+#define LZ4_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */
+
+#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
+
+#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
+#define LZ4_QUOTE(str) #str
+#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
+#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)
+
+LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */
+LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; unseful to check dll version */
+
+
+/*-************************************
+* Tuning parameter
+**************************************/
+/*!
+ * LZ4_MEMORY_USAGE :
+ * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
+ * Increasing memory usage improves compression ratio
+ * Reduced memory usage may improve speed, thanks to cache effect
+ * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
+ */
+#ifndef LZ4_MEMORY_USAGE
+# define LZ4_MEMORY_USAGE 14
+#endif
+
+/*-************************************
+* Simple Functions
+**************************************/
+/*! LZ4_compress_default() :
+ Compresses 'srcSize' bytes from buffer 'src'
+ into already allocated 'dst' buffer of size 'dstCapacity'.
+ Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
+ It also runs faster, so it's a recommended setting.
+ If the function cannot compress 'src' into a more limited 'dst' budget,
+ compression stops *immediately*, and the function result is zero.
+ Note : as a consequence, 'dst' content is not valid.
+ Note 2 : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
+ srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
+ dstCapacity : size of buffer 'dst' (which must be already allocated)
+ return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
+ or 0 if compression fails */
+LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
+
+/*! LZ4_decompress_safe() :
+ compressedSize : is the exact complete size of the compressed block.
+ dstCapacity : is the size of destination buffer, which must be already allocated.
+ return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
+ If destination buffer is not large enough, decoding will stop and output an error code (negative value).
+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
+ This function is protected against malicious data packets.
+*/
+LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
+
+
+/*-************************************
+* Advanced Functions
+**************************************/
+#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
+#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
+
+/*!
+LZ4_compressBound() :
+ Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
+ This function is primarily useful for memory allocation purposes (destination buffer size).
+ Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
+ Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)
+ inputSize : max supported value is LZ4_MAX_INPUT_SIZE
+ return : maximum output size in a "worst case" scenario
+ or 0, if input size is incorrect (too large or negative)
+*/
+LZ4LIB_API int LZ4_compressBound(int inputSize);
+
+/*!
+LZ4_compress_fast() :
+ Same as LZ4_compress_default(), but allows selection of "acceleration" factor.
+ The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
+ It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
+ An acceleration value of "1" is the same as regular LZ4_compress_default()
+ Values <= 0 will be replaced by ACCELERATION_DEFAULT (currently == 1, see lz4.c).
+*/
+LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
+
+
+/*!
+LZ4_compress_fast_extState() :
+ Same compression function, just using an externally allocated memory space to store compression state.
+ Use LZ4_sizeofState() to know how much memory must be allocated,
+ and allocate it on 8-bytes boundaries (using malloc() typically).
+ Then, provide it as 'void* state' to compression function.
+*/
+LZ4LIB_API int LZ4_sizeofState(void);
+LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
+
+
+/*!
+LZ4_compress_destSize() :
+ Reverse the logic : compresses as much data as possible from 'src' buffer
+ into already allocated buffer 'dst' of size 'targetDestSize'.
+ This function either compresses the entire 'src' content into 'dst' if it's large enough,
+ or fill 'dst' buffer completely with as much data as possible from 'src'.
+ *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
+ New value is necessarily <= old value.
+ return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
+ or 0 if compression fails
+*/
+LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
+
+
+/*!
+LZ4_decompress_fast() : **unsafe!**
+This function is a bit faster than LZ4_decompress_safe(),
+but doesn't provide any security guarantee.
+ originalSize : is the uncompressed size to regenerate
+ Destination buffer must be already allocated, and its size must be >= 'originalSize' bytes.
+ return : number of bytes read from source buffer (== compressed size).
+ If the source stream is detected malformed, the function stops decoding and return a negative result.
+ note : This function respects memory boundaries for *properly formed* compressed data.
+ However, it does not provide any protection against malicious input.
+ It also doesn't know 'src' size, and implies it's >= compressed size.
+ Use this function in trusted environment **only**.
+*/
+LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
+
+/*!
+LZ4_decompress_safe_partial() :
+ This function decompress a compressed block of size 'srcSize' at position 'src'
+ into destination buffer 'dst' of size 'dstCapacity'.
+ The function will decompress a minimum of 'targetOutputSize' bytes, and stop after that.
+ However, it's not accurate, and may write more than 'targetOutputSize' (but always <= dstCapacity).
+ @return : the number of bytes decoded in the destination buffer (necessarily <= dstCapacity)
+ Note : this number can also be < targetOutputSize, if compressed block contains less data.
+ Therefore, always control how many bytes were decoded.
+ If source stream is detected malformed, function returns a negative result.
+ This function is protected against malicious data packets.
+*/
+LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
+
+
+/*-*********************************************
+* Streaming Compression Functions
+***********************************************/
+typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
+
+/*! LZ4_createStream() and LZ4_freeStream() :
+ * LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure.
+ * LZ4_freeStream() releases its memory.
+ */
+LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
+LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
+
+/*! LZ4_resetStream() :
+ * An LZ4_stream_t structure can be allocated once and re-used multiple times.
+ * Use this function to start compressing a new stream.
+ */
+LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
+
+/*! LZ4_loadDict() :
+ * Use this function to load a static dictionary into LZ4_stream_t.
+ * Any previous data will be forgotten, only 'dictionary' will remain in memory.
+ * Loading a size of 0 is allowed, and is the same as reset.
+ * @return : dictionary size, in bytes (necessarily <= 64 KB)
+ */
+LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
+
+/*! LZ4_compress_fast_continue() :
+ * Compress 'src' content using data from previously compressed blocks, for better compression ratio.
+ * 'dst' buffer must be already allocated.
+ * If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
+ *
+ * Important : The previous 64KB of compressed data is assumed to remain present and unmodified in memory!
+ *
+ * Special 1 : When input is a double-buffer, they can have any size, including < 64 KB.
+ * Make sure that buffers are separated by at least one byte.
+ * This way, each block only depends on previous block.
+ * Special 2 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
+ *
+ * @return : size of compressed block
+ * or 0 if there is an error (typically, cannot fit into 'dst').
+ * After an error, the stream status is invalid, it can only be reset or freed.
+ */
+LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
+
+/*! LZ4_saveDict() :
+ * If last 64KB data cannot be guaranteed to remain available at its current memory location,
+ * save it into a safer place (char* safeBuffer).
+ * This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
+ * but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.
+ * @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.
+ */
+LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
+
+
+/*-**********************************************
+* Streaming Decompression Functions
+* Bufferless synchronous API
+************************************************/
+typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */
+
+/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
+ * creation / destruction of streaming decompression tracking structure.
+ * A tracking structure can be re-used multiple times sequentially. */
+LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
+LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
+
+/*! LZ4_setStreamDecode() :
+ * An LZ4_streamDecode_t structure can be allocated once and re-used multiple times.
+ * Use this function to start decompression of a new stream of blocks.
+ * A dictionary can optionnally be set. Use NULL or size 0 for a reset order.
+ * @return : 1 if OK, 0 if error
+ */
+LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
+
+/*! LZ4_decompress_*_continue() :
+ * These decoding functions allow decompression of consecutive blocks in "streaming" mode.
+ * A block is an unsplittable entity, it must be presented entirely to a decompression function.
+ * Decompression functions only accept one block at a time.
+ * The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded.
+ * If less than 64KB of data has been decoded all the data must be present.
+ *
+ * Special : if application sets a ring buffer for decompression, it must respect one of the following conditions :
+ * - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
+ * In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
+ * - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
+ * maxBlockSize is implementation dependent. It's the maximum size of any single block.
+ * In which case, encoding and decoding buffers do not need to be synchronized,
+ * and encoding ring buffer can have any size, including small ones ( < 64 KB).
+ * - _At least_ 64 KB + 8 bytes + maxBlockSize.
+ * In which case, encoding and decoding buffers do not need to be synchronized,
+ * and encoding ring buffer can have any size, including larger than decoding buffer.
+ * Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
+ * and indicate where it is saved using LZ4_setStreamDecode() before decompressing next block.
+*/
+LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
+LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
+
+
+/*! LZ4_decompress_*_usingDict() :
+ * These decoding functions work the same as
+ * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
+ * They are stand-alone, and don't need an LZ4_streamDecode_t structure.
+ */
+LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
+LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
+
+
+/*^**********************************************
+ * !!!!!! STATIC LINKING ONLY !!!!!!
+ ***********************************************/
+
+/*-************************************
+ * Unstable declarations
+ **************************************
+ * Declarations in this section should be considered unstable.
+ * Use at your own peril, etc., etc.
+ * They may be removed in the future.
+ * Their signatures may change.
+ **************************************/
+
+#ifdef LZ4_STATIC_LINKING_ONLY
+
+/*! LZ4_resetStream_fast() :
+ * When an LZ4_stream_t is known to be in a internally coherent state,
+ * it can often be prepared for a new compression with almost no work, only
+ * sometimes falling back to the full, expensive reset that is always required
+ * when the stream is in an indeterminate state (i.e., the reset performed by
+ * LZ4_resetStream()).
+ *
+ * LZ4_streams are guaranteed to be in a valid state when:
+ * - returned from LZ4_createStream()
+ * - reset by LZ4_resetStream()
+ * - memset(stream, 0, sizeof(LZ4_stream_t))
+ * - the stream was in a valid state and was reset by LZ4_resetStream_fast()
+ * - the stream was in a valid state and was then used in any compression call
+ * that returned success
+ * - the stream was in an indeterminate state and was used in a compression
+ * call that fully reset the state (LZ4_compress_fast_extState()) and that
+ * returned success
+ */
+LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
+
+/*! LZ4_compress_fast_extState_fastReset() :
+ * A variant of LZ4_compress_fast_extState().
+ *
+ * Using this variant avoids an expensive initialization step. It is only safe
+ * to call if the state buffer is known to be correctly initialized already
+ * (see above comment on LZ4_resetStream_fast() for a definition of "correctly
+ * initialized"). From a high level, the difference is that this function
+ * initializes the provided state with a call to LZ4_resetStream_fast() while
+ * LZ4_compress_fast_extState() starts with a call to LZ4_resetStream().
+ */
+LZ4LIB_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
+
+/*! LZ4_attach_dictionary() :
+ * This is an experimental API that allows for the efficient use of a
+ * static dictionary many times.
+ *
+ * Rather than re-loading the dictionary buffer into a working context before
+ * each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a
+ * working LZ4_stream_t, this function introduces a no-copy setup mechanism,
+ * in which the working stream references the dictionary stream in-place.
+ *
+ * Several assumptions are made about the state of the dictionary stream.
+ * Currently, only streams which have been prepared by LZ4_loadDict() should
+ * be expected to work.
+ *
+ * Alternatively, the provided dictionary stream pointer may be NULL, in which
+ * case any existing dictionary stream is unset.
+ *
+ * If a dictionary is provided, it replaces any pre-existing stream history.
+ * The dictionary contents are the only history that can be referenced and
+ * logically immediately precede the data compressed in the first subsequent
+ * compression call.
+ *
+ * The dictionary will only remain attached to the working stream through the
+ * first compression call, at the end of which it is cleared. The dictionary
+ * stream (and source buffer) must remain in-place / accessible / unchanged
+ * through the completion of the first compression call on the stream.
+ */
+LZ4LIB_API void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dictionary_stream);
+
+#endif
+
+/*-************************************
+ * Private definitions
+ **************************************
+ * Do not use these definitions.
+ * They are exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
+ * Using these definitions will expose code to API and/or ABI break in future versions of the library.
+ **************************************/
+#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
+#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
+#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
+
+#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
+#include
+
+typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
+struct LZ4_stream_t_internal {
+ uint32_t hashTable[LZ4_HASH_SIZE_U32];
+ uint32_t currentOffset;
+ uint16_t initCheck;
+ uint16_t tableType;
+ const uint8_t* dictionary;
+ const LZ4_stream_t_internal* dictCtx;
+ uint32_t dictSize;
+};
+
+typedef struct {
+ const uint8_t* externalDict;
+ size_t extDictSize;
+ const uint8_t* prefixEnd;
+ size_t prefixSize;
+} LZ4_streamDecode_t_internal;
+
+#else
+
+typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
+struct LZ4_stream_t_internal {
+ unsigned int hashTable[LZ4_HASH_SIZE_U32];
+ unsigned int currentOffset;
+ unsigned short initCheck;
+ unsigned short tableType;
+ const unsigned char* dictionary;
+ const LZ4_stream_t_internal* dictCtx;
+ unsigned int dictSize;
+};
+
+typedef struct {
+ const unsigned char* externalDict;
+ size_t extDictSize;
+ const unsigned char* prefixEnd;
+ size_t prefixSize;
+} LZ4_streamDecode_t_internal;
+
+#endif
+
+/*!
+ * LZ4_stream_t :
+ * information structure to track an LZ4 stream.
+ * init this structure before first use.
+ * note : only use in association with static linking !
+ * this definition is not API/ABI safe,
+ * it may change in a future version !
+ */
+#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
+#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long))
+union LZ4_stream_u {
+ unsigned long long table[LZ4_STREAMSIZE_U64];
+ LZ4_stream_t_internal internal_donotuse;
+} ; /* previously typedef'd to LZ4_stream_t */
+
+
+/*!
+ * LZ4_streamDecode_t :
+ * information structure to track an LZ4 stream during decompression.
+ * init this structure using LZ4_setStreamDecode (or memset()) before first use
+ * note : only use in association with static linking !
+ * this definition is not API/ABI safe,
+ * and may change in a future version !
+ */
+#define LZ4_STREAMDECODESIZE_U64 4
+#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
+union LZ4_streamDecode_u {
+ unsigned long long table[LZ4_STREAMDECODESIZE_U64];
+ LZ4_streamDecode_t_internal internal_donotuse;
+} ; /* previously typedef'd to LZ4_streamDecode_t */
+
+
+/*-************************************
+* Obsolete Functions
+**************************************/
+
+/*! Deprecation warnings
+ Should deprecation warnings be a problem,
+ it is generally possible to disable them,
+ typically with -Wno-deprecated-declarations for gcc
+ or _CRT_SECURE_NO_WARNINGS in Visual.
+ Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */
+#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
+# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
+#else
+# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
+# define LZ4_DEPRECATED(message) [[deprecated(message)]]
+# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__)
+# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
+# elif (LZ4_GCC_VERSION >= 301)
+# define LZ4_DEPRECATED(message) __attribute__((deprecated))
+# elif defined(_MSC_VER)
+# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
+# else
+# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
+# define LZ4_DEPRECATED(message)
+# endif
+#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
+
+/* Obsolete compression functions */
+LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* source, char* dest, int sourceSize);
+LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
+LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
+LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
+LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
+LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
+
+/* Obsolete decompression functions */
+LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
+LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
+
+/* Obsolete streaming functions; degraded functionality; do not use!
+ *
+ * In order to perform streaming compression, these functions depended on data
+ * that is no longer tracked in the state. They have been preserved as well as
+ * possible: using them will still produce a correct output. However, they don't
+ * actually retain any history between compression calls. The compression ratio
+ * achieved will therefore be no better than compressing each chunk
+ * independently.
+ */
+LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);
+LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);
+LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
+LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
+
+/* Obsolete streaming decoding functions */
+LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
+LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
+
+#endif /* LZ4_H_2983827168210 */
+
+
+#if defined (__cplusplus)
+}
+#endif
diff --git a/nyx/nyx_gui/libs/fatfs/diskio.h b/bdk/libs/fatfs/diskio.h
similarity index 88%
rename from nyx/nyx_gui/libs/fatfs/diskio.h
rename to bdk/libs/fatfs/diskio.h
index d6ae8f8..b5299c6 100644
--- a/nyx/nyx_gui/libs/fatfs/diskio.h
+++ b/bdk/libs/fatfs/diskio.h
@@ -9,7 +9,7 @@
extern "C" {
#endif
-#include "../../utils/types.h"
+#include
/* Status of Disk Functions */
typedef BYTE DSTATUS;
@@ -23,6 +23,14 @@ typedef enum {
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
+typedef enum {
+ DRIVE_SD = 0,
+ DRIVE_RAM = 1,
+ DRIVE_EMMC = 2,
+ DRIVE_BIS = 3,
+ DRIVE_EMU = 4
+} DDRIVE;
+
/*---------------------------------------*/
/* Prototypes for disk control functions */
@@ -33,6 +41,7 @@ DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
+DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
/* Disk Status Bits (DSTATUS) */
@@ -47,9 +56,11 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
+#define SET_SECTOR_COUNT 1 /* Set media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
+#define SET_SECTOR_OFFSET 5 /* Set media logical offset */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
diff --git a/nyx/nyx_gui/libs/fatfs/ff.c b/bdk/libs/fatfs/ff.c
similarity index 98%
rename from nyx/nyx_gui/libs/fatfs/ff.c
rename to bdk/libs/fatfs/ff.c
index f7fdf20..109e87b 100644
--- a/nyx/nyx_gui/libs/fatfs/ff.c
+++ b/bdk/libs/fatfs/ff.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
- * Copyright (c) 2018-2019 CTCaer
+ * Copyright (c) 2018-2022 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,
@@ -38,7 +38,8 @@
#include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */
-#include "../../gfx/gfx.h"
+#include
+#include
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
//#define EFSPRINTF(...)
@@ -3273,7 +3274,6 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
stat = disk_status(fs->pdrv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */
- EFSPRINTF("WPEN1");
return FR_WRITE_PROTECTED;
}
return FR_OK; /* The filesystem object is valid */
@@ -3284,14 +3284,13 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */
fs->fs_type = 0; /* Clear the filesystem object */
+ fs->part_type = 0; /* Clear the Partition object */
fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
- EFSPRINTF("MDNR");
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
}
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
- EFSPRINTF("WPEN2");
return FR_WRITE_PROTECTED;
}
#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */
@@ -3318,6 +3317,20 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
EFSPRINTF("BRNL");
return FR_DISK_ERR; /* An error occured in the disk I/O layer */
}
+#if FF_SIMPLE_GPT
+ if (fmt >= 2) {
+ /* If GPT Check the first partition */
+ gpt_header_t *gpt_header = (gpt_header_t *)fs->win;
+ if (move_window(fs, 1) != FR_OK) return FR_DISK_ERR;
+ if (!mem_cmp(&gpt_header->signature, "EFI PART", 8)) {
+ if (move_window(fs, gpt_header->part_ent_lba) != FR_OK) return FR_DISK_ERR;
+ gpt_entry_t *gpt_entry = (gpt_entry_t *)fs->win;
+ fs->part_type = 1;
+ bsect = gpt_entry->lba_start;
+ fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
+ }
+ }
+#endif
if (fmt >= 2) {
EFSPRINTF("NOFAT");
return FR_NO_FILESYSTEM; /* No FAT volume is found */
@@ -3906,11 +3919,11 @@ FRESULT f_read (
-#ifdef FF_FASTFS
+#if FF_FASTFS && FF_USE_FASTSEEK
/*-----------------------------------------------------------------------*/
/* Fast Read Aligned Sized File Without a Cache */
/*-----------------------------------------------------------------------*/
-#if FF_USE_FASTSEEK
+
FRESULT f_read_fast (
FIL* fp, /* Pointer to the file object */
const void* buff, /* Pointer to the data to be written */
@@ -3988,7 +4001,6 @@ FRESULT f_read_fast (
LEAVE_FF(fs, FR_OK);
}
#endif
-#endif
@@ -4132,11 +4144,11 @@ FRESULT f_write (
-#ifdef FF_FASTFS
+#if FF_FASTFS && FF_USE_FASTSEEK
/*-----------------------------------------------------------------------*/
/* Fast Write Aligned Sized File Without a Cache */
/*-----------------------------------------------------------------------*/
-#if FF_USE_FASTSEEK
+
FRESULT f_write_fast (
FIL* fp, /* Pointer to the file object */
const void* buff, /* Pointer to the data to be written */
@@ -4219,7 +4231,6 @@ FRESULT f_write_fast (
LEAVE_FF(fs, FR_OK);
}
#endif
-#endif
@@ -4680,35 +4691,40 @@ FRESULT f_lseek (
-#ifdef FF_FASTFS
-#if FF_USE_FASTSEEK
+#if FF_FASTFS && FF_USE_FASTSEEK
/*-----------------------------------------------------------------------*/
/* Seek File Read/Write Pointer */
/*-----------------------------------------------------------------------*/
DWORD *f_expand_cltbl (
FIL* fp, /* Pointer to the file object */
- UINT tblsz, /* Size of table */
+ UINT tblsz, /* Size of table (2 DWORDs + 2 DWORDs per fragment) */
FSIZE_t ofs /* File pointer from top of file */
)
{
+ /*
+ * Cluster table structure:
+ * Size (DWORD)
+ * Padding (DWORD)
+ * (Cluster Offset (DWORD) + Sequential clusters (DWORD)) * Fragments
+ */
if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */
if (!fp->cltbl) { /* Allocate memory for cluster link table */
fp->cltbl = (DWORD *)ff_memalloc(tblsz);
+ if (!fp->cltbl) return (void *)0;
fp->cltbl[0] = tblsz;
}
if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */
ff_memfree(fp->cltbl);
- fp->cltbl = NULL;
+ fp->cltbl = (void *)0;
EFSPRINTF("CLTBLSZ");
- return NULL;
+ return (void *)0;
}
f_lseek(fp, 0);
return fp->cltbl;
}
#endif
-#endif
@@ -5842,7 +5858,7 @@ FRESULT f_mkfs (
UINT len /* Size of working buffer [byte] */
)
{
- const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */
+ const UINT n_fats = 2; /* Number of FATs for FAT/FAT32 volume (1 or 2) */
const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */
static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */
static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */
@@ -5870,7 +5886,7 @@ FRESULT f_mkfs (
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
- if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */
+ if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 131072 || (sz_blk & (sz_blk - 1))) sz_blk = 2048; /* Erase block to align data area. 1MB minimum */
#if FF_MAX_SS != FF_MIN_SS /* Get sector size of the medium if variable sector size cfg. */
if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
@@ -5906,7 +5922,7 @@ FRESULT f_mkfs (
} else {
/* Create a single-partition in this function */
if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
- b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */
+ b_vol = (opt & FM_SFD) ? 0 : sz_blk; /* Volume start sector */
if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);
sz_vol -= b_vol; /* Volume size */
}
@@ -6130,6 +6146,9 @@ FRESULT f_mkfs (
if (fmt == FS_FAT32) { /* FAT32: Move FAT base */
sz_rsv += n; b_fat += n;
} else { /* FAT: Expand FAT size */
+ if (n % n_fats) { /* Adjust fractional error if needed */
+ n--; sz_rsv++; b_fat++;
+ }
sz_fat += n / n_fats;
}
@@ -6170,7 +6189,9 @@ FRESULT f_mkfs (
#endif
/* Create FAT VBR */
mem_set(buf, 0, ss);
- mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */
+ /* Boot jump code (x86), OEM name */
+ if (!(opt & FM_PRF2)) mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "NYX1.0.0", 11);
+ else mem_cpy(buf + BS_JmpBoot, "\xEB\xE9\x90\x00\x00\x00\x00\x00\x00\x00\x00", 11);
st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */
@@ -6183,23 +6204,27 @@ FRESULT f_mkfs (
}
buf[BPB_Media] = 0xF8; /* Media descriptor byte */
st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */
- st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */
+ st_word(buf + BPB_NumHeads, (opt & FM_PRF2) ? 16 : 255); /* Number of heads (for int13) */
st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */
if (fmt == FS_FAT32) {
- st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */
+ st_dword(buf + BS_VolID32, (opt & FM_PRF2) ? 0 : GET_FATTIME()); /* VSN */
st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */
st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig32] = 0x29; /* Extended boot signature */
- mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */
+ /* Volume label, FAT signature */
+ if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab32, FF_MKFS_LABEL "FAT32 ", 19);
+ else mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19);
} else {
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig] = 0x29; /* Extended boot signature */
- mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
+ /* Volume label, FAT signature */
+ if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab, FF_MKFS_LABEL "FAT ", 19);
+ else mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19);
}
st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */
if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
@@ -6210,13 +6235,35 @@ FRESULT f_mkfs (
mem_set(buf, 0, ss);
st_dword(buf + FSI_LeadSig, 0x41615252);
st_dword(buf + FSI_StrucSig, 0x61417272);
- st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */
- st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */
+ if (opt & FM_PRF2) {
+ st_dword(buf + FSI_Free_Count, 0xFFFFFFFF); /* Invalidate free count */
+ st_dword(buf + FSI_Nxt_Free, 0xFFFFFFFF); /* Invalidate last allocated cluster */
+ } else {
+ st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */
+ st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */
+ }
st_word(buf + BS_55AA, 0xAA55);
disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */
disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */
}
+ /* Create PRF2SAFE info */
+ if (fmt == FS_FAT32 && opt & FM_PRF2) {
+ mem_set(buf, 0, ss);
+ st_dword(buf + 0, 0x32465250); /* Magic PRF2 */
+ st_dword(buf + 4, 0x45464153); /* Magic SAFE */
+ buf[16] = 0x64; /* Record type */
+ st_dword(buf + 32, 0x03); /* Unknown. SYSTEM: 0x3F00. USER: 0x03. Volatile. */
+ if (sz_vol < 0x1000000) {
+ st_dword(buf + 36, 21 + 1); /* 22 Entries. */
+ st_dword(buf + 508, 0x90BB2F39); /* Sector CRC32 */
+ } else {
+ st_dword(buf + 36, 21 + 2); /* 23 Entries. */
+ st_dword(buf + 508, 0x5EA8AFC8); /* Sector CRC32 */
+ }
+ disk_write(pdrv, buf, b_vol + 3, 1); /* Write PRF2SAFE info (VBR + 3) */
+ }
+
/* Initialize FAT area */
mem_set(buf, 0, (UINT)szb_buf);
sect = b_fat; /* FAT start sector */
@@ -6706,6 +6753,8 @@ int f_puts (
putbuff pb;
+ if (str == (void *)0) return EOF; /* String is NULL */
+
putc_init(&pb, fp);
while (*str) putc_bfd(&pb, *str++); /* Put the string */
return putc_flush(&pb);
@@ -6732,6 +6781,8 @@ int f_printf (
TCHAR c, d, str[32], *p;
+ if (fmt == (void *)0) return EOF; /* String is NULL */
+
putc_init(&pb, fp);
va_start(arp, fmt);
diff --git a/nyx/nyx_gui/libs/fatfs/ff.h b/bdk/libs/fatfs/ff.h
similarity index 96%
rename from nyx/nyx_gui/libs/fatfs/ff.h
rename to bdk/libs/fatfs/ff.h
index bf6f39a..3a6c423 100644
--- a/nyx/nyx_gui/libs/fatfs/ff.h
+++ b/bdk/libs/fatfs/ff.h
@@ -26,8 +26,8 @@
extern "C" {
#endif
-#include "../../utils/types.h" /* Basic integer types */
-#include "ffconf.h" /* FatFs configuration options */
+#include /* Basic integer types */
+#include /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF
#error Wrong configuration file (ffconf.h).
@@ -95,8 +95,8 @@ typedef DWORD FSIZE_t;
/* Filesystem object structure (FATFS) */
typedef struct {
- BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
BYTE fs_type; /* Filesystem type (0:not mounted) */
+ BYTE part_type; /* Partition type (0:MBR, 1:GPT) */
BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
@@ -138,6 +138,7 @@ typedef struct {
DWORD bitbase; /* Allocation bitmap base sector */
#endif
DWORD winsect; /* Current sector appearing in the win[] */
+ BYTE win[FF_MAX_SS] __attribute__((aligned(8))); /* Disk access window for Directory, FAT (and file data at tiny cfg). DMA aligned. */
} FATFS;
@@ -168,9 +169,6 @@ typedef struct {
/* File object structure (FIL) */
typedef struct {
-#if !FF_FS_TINY
- BYTE buf[FF_MAX_SS]; /* File private data read/write window */
-#endif
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
@@ -184,6 +182,9 @@ typedef struct {
#if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
+#if !FF_FS_TINY
+ BYTE buf[FF_MAX_SS] __attribute__((aligned(8))); /* File private data read/write window. DMA aligned. */
+#endif
} FIL;
@@ -246,7 +247,7 @@ typedef enum {
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
-#ifdef FF_FASTFS
+#if FF_FASTFS
FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */
FR_CLTBL_NO_INIT /* (20) The cluster table for fast seek/read/write was not created */
#else
@@ -263,10 +264,8 @@ FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a f
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
-#ifdef FF_FASTFS
FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */
FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */
-#endif
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
@@ -288,9 +287,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
-#ifdef FF_FASTFS
DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, FSIZE_t ofs); /* Expand file and populate cluster table */
-#endif
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
@@ -369,6 +366,7 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
+#define FM_PRF2 0x10
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
@@ -380,8 +378,11 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
+#define AM_VOL 0x08 /* Volume */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
+#define AM_DEV 0x40 /* Device */
+#define AM_RVD 0x80 /* Reserved */
#ifdef __cplusplus
diff --git a/nyx/nyx_gui/libs/fatfs/ffsystem.c b/bdk/libs/fatfs/ffsystem.c
similarity index 59%
rename from nyx/nyx_gui/libs/fatfs/ffsystem.c
rename to bdk/libs/fatfs/ffsystem.c
index fa44f8e..b4af454 100644
--- a/nyx/nyx_gui/libs/fatfs/ffsystem.c
+++ b/bdk/libs/fatfs/ffsystem.c
@@ -1,14 +1,12 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
-/* (C) ChaN, 2018 */
-/* (C) CTCaer, 2018 */
+/* (C) ChaN, 2018 */
+/* (C) CTCaer, 2018-2024 */
/*------------------------------------------------------------------------*/
+#include
-#include "ff.h"
-#include "../../mem/heap.h"
-
-
+#include
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
@@ -20,7 +18,8 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if no
UINT msize /* Number of bytes to allocate */
)
{
- return malloc(msize); /* Allocate a new memory block with POSIX API */
+ // Ensure size is aligned to SDMMC block size.
+ return malloc(ALIGN(msize, SDMMC_DAT_BLOCKSIZE)); /* Allocate a new memory block with POSIX API */
}
@@ -37,3 +36,22 @@ void ff_memfree (
#endif
+#if FF_FS_NORTC == 0
+
+/*------------------------------------------------------------------------*/
+/* Get real time clock */
+/*------------------------------------------------------------------------*/
+
+DWORD get_fattime (
+ void
+)
+{
+ rtc_time_t time;
+
+ max77620_rtc_get_time_adjusted(&time);
+
+ return (((DWORD)(time.year - 1980) << 25) | ((DWORD)time.month << 21) | ((DWORD)time.day << 16) |
+ ((DWORD)time.hour << 11) | ((DWORD)time.min << 5) | (time.sec >> 1));
+}
+
+#endif
diff --git a/bootloader/libs/fatfs/ffunicode.c b/bdk/libs/fatfs/ffunicode.c
similarity index 100%
rename from bootloader/libs/fatfs/ffunicode.c
rename to bdk/libs/fatfs/ffunicode.c
diff --git a/nyx/nyx_gui/libs/lv_conf.h b/bdk/libs/lv_conf.h
similarity index 94%
rename from nyx/nyx_gui/libs/lv_conf.h
rename to bdk/libs/lv_conf.h
index 70ce4ff..89dc555 100644
--- a/nyx/nyx_gui/libs/lv_conf.h
+++ b/bdk/libs/lv_conf.h
@@ -17,8 +17,8 @@
#ifndef LV_CONF_H
#define LV_CONF_H
-#include "../utils/types.h"
-#include "../../../common/memory_map.h"
+#include
+#include
/*===================
Dynamic memory
*===================*/
@@ -32,7 +32,7 @@
# define LV_MEM_ADR NYX_LV_MEM_ADR /*Set an address for memory pool instead of allocation it as an array. Can be in external SRAM too.*/
# define LV_MEM_AUTO_DEFRAG 1 /*Automatically defrag on free*/
#else /*LV_MEM_CUSTOM*/
-# define LV_MEM_CUSTOM_INCLUDE "../../../mem/heap.h" /*Header for the dynamic memory function*/
+# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/
# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/
# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/
#endif /*LV_MEM_CUSTOM*/
@@ -147,15 +147,19 @@
#define LV_COMPILER_VLA_SUPPORTED 1 /* 1: Variable length array is supported*/
/*HAL settings*/
-#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */
+#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */
#if LV_TICK_CUSTOM == 1
-#define LV_TICK_CUSTOM_INCLUDE "../../../utils/util.h" /*Header for the sys time function*/
-#define LV_TICK_CUSTOM_SYS_TIME_EXPR (get_tmr_ms()) /*Expression evaluating to current systime in ms*/
+#define LV_TICK_CUSTOM_INCLUDE /*Header for the sys time function*/
+#define LV_TICK_CUSTOM_SYS_TIME_EXPR ((u32)get_tmr_ms()) /*Expression evaluating to current systime in ms*/
#endif /*LV_TICK_CUSTOM*/
/*Log settings*/
-#define USE_LV_LOG 0 /*Enable/disable the log module*/
+#ifdef DEBUG_UART_LV_LOG
+# define USE_LV_LOG 1 /*Enable/disable the log module*/
+#else
+# define USE_LV_LOG 0 /*Enable/disable the log module*/
+#endif
#if USE_LV_LOG
/* How important log should be added:
* LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
@@ -163,7 +167,7 @@
* LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't caused problem
* LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
*/
-# define LV_LOG_LEVEL LV_LOG_LEVEL_ERROR
+# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
/* 1: Print the log with 'printf'; 0: user need to register a callback*/
# define LV_LOG_PRINTF 1
#endif /*USE_LV_LOG*/
@@ -292,6 +296,9 @@
/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/
#define USE_LV_MBOX 1
+#if USE_LV_MBOX != 0
+# define LV_MBOX_CLOSE_ANIM_TIME 200 /*ms*/
+#endif
/*Text area (dependencies: lv_label, lv_page)*/
#define USE_LV_TA 1
diff --git a/nyx/nyx_gui/libs/lvgl/docs/CODE_OF_CONDUCT.md b/bdk/libs/lvgl/docs/CODE_OF_CONDUCT.md
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/docs/CODE_OF_CONDUCT.md
rename to bdk/libs/lvgl/docs/CODE_OF_CONDUCT.md
diff --git a/nyx/nyx_gui/libs/lvgl/docs/CONTRIBUTING.md b/bdk/libs/lvgl/docs/CONTRIBUTING.md
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/docs/CONTRIBUTING.md
rename to bdk/libs/lvgl/docs/CONTRIBUTING.md
diff --git a/nyx/nyx_gui/libs/lvgl/docs/astyle_c b/bdk/libs/lvgl/docs/astyle_c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/docs/astyle_c
rename to bdk/libs/lvgl/docs/astyle_c
diff --git a/nyx/nyx_gui/libs/lvgl/docs/astyle_h b/bdk/libs/lvgl/docs/astyle_h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/docs/astyle_h
rename to bdk/libs/lvgl/docs/astyle_h
diff --git a/nyx/nyx_gui/libs/lvgl/licence.txt b/bdk/libs/lvgl/licence.txt
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/licence.txt
rename to bdk/libs/lvgl/licence.txt
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_core.mk b/bdk/libs/lvgl/lv_core/lv_core.mk
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_core.mk
rename to bdk/libs/lvgl/lv_core/lv_core.mk
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_group.c b/bdk/libs/lvgl/lv_core/lv_group.c
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_group.c
rename to bdk/libs/lvgl/lv_core/lv_group.c
index 3fd4120..cedef7f 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_core/lv_group.c
+++ b/bdk/libs/lvgl/lv_core/lv_group.c
@@ -546,8 +546,8 @@ static void obj_to_foreground(lv_obj_t * obj)
/*Move the last_top object to the foreground*/
lv_obj_t * par = lv_obj_get_parent(last_top);
/*After list change it will be the new head*/
- lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top);
- lv_obj_invalidate(last_top);
+ if (lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top))
+ lv_obj_invalidate(last_top); /*Only invalidate if not top*/
}
}
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_group.h b/bdk/libs/lvgl/lv_core/lv_group.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_group.h
rename to bdk/libs/lvgl/lv_core/lv_group.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_indev.c b/bdk/libs/lvgl/lv_core/lv_indev.c
similarity index 98%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_indev.c
rename to bdk/libs/lvgl/lv_core/lv_indev.c
index 24cc798..d1dc582 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_core/lv_indev.c
+++ b/bdk/libs/lvgl/lv_core/lv_indev.c
@@ -357,7 +357,10 @@ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data)
if(i->cursor != NULL &&
(i->proc.last_point.x != data->point.x ||
i->proc.last_point.y != data->point.y)) {
- lv_obj_set_pos(i->cursor, data->point.x, data->point.y);
+ /*Use cursor's center as pointer*/
+ uint32_t off_x = lv_obj_get_width(i->cursor) >> 1;
+ uint32_t off_y = lv_obj_get_height(i->cursor) >> 1;
+ lv_obj_set_pos(i->cursor, data->point.x - off_x, data->point.y - off_y);
}
i->proc.act_point.x = data->point.x;
@@ -643,8 +646,8 @@ static void indev_proc_press(lv_indev_proc_t * proc)
/*Move the last_top object to the foreground*/
lv_obj_t * par = lv_obj_get_parent(last_top);
/*After list change it will be the new head*/
- lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top);
- lv_obj_invalidate(last_top);
+ if (lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top))
+ lv_obj_invalidate(last_top); /*Only invalidate if not top*/
}
/*Send a signal about the press*/
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_indev.h b/bdk/libs/lvgl/lv_core/lv_indev.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_indev.h
rename to bdk/libs/lvgl/lv_core/lv_indev.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_lang.c b/bdk/libs/lvgl/lv_core/lv_lang.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_lang.c
rename to bdk/libs/lvgl/lv_core/lv_lang.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_lang.h b/bdk/libs/lvgl/lv_core/lv_lang.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_lang.h
rename to bdk/libs/lvgl/lv_core/lv_lang.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_obj.c b/bdk/libs/lvgl/lv_core/lv_obj.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_obj.c
rename to bdk/libs/lvgl/lv_core/lv_obj.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_obj.h b/bdk/libs/lvgl/lv_core/lv_obj.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_obj.h
rename to bdk/libs/lvgl/lv_core/lv_obj.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_refr.c b/bdk/libs/lvgl/lv_core/lv_refr.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_refr.c
rename to bdk/libs/lvgl/lv_core/lv_refr.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_refr.h b/bdk/libs/lvgl/lv_core/lv_refr.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_refr.h
rename to bdk/libs/lvgl/lv_core/lv_refr.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_style.c b/bdk/libs/lvgl/lv_core/lv_style.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_style.c
rename to bdk/libs/lvgl/lv_core/lv_style.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_style.h b/bdk/libs/lvgl/lv_core/lv_style.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_style.h
rename to bdk/libs/lvgl/lv_core/lv_style.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_vdb.c b/bdk/libs/lvgl/lv_core/lv_vdb.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_vdb.c
rename to bdk/libs/lvgl/lv_core/lv_vdb.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_core/lv_vdb.h b/bdk/libs/lvgl/lv_core/lv_vdb.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_core/lv_vdb.h
rename to bdk/libs/lvgl/lv_core/lv_vdb.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw.c b/bdk/libs/lvgl/lv_draw/lv_draw.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw.c
rename to bdk/libs/lvgl/lv_draw/lv_draw.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw.h b/bdk/libs/lvgl/lv_draw/lv_draw.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw.h
rename to bdk/libs/lvgl/lv_draw/lv_draw.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw.mk b/bdk/libs/lvgl/lv_draw/lv_draw.mk
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw.mk
rename to bdk/libs/lvgl/lv_draw/lv_draw.mk
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_arc.c b/bdk/libs/lvgl/lv_draw/lv_draw_arc.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_arc.c
rename to bdk/libs/lvgl/lv_draw/lv_draw_arc.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_arc.h b/bdk/libs/lvgl/lv_draw/lv_draw_arc.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_arc.h
rename to bdk/libs/lvgl/lv_draw/lv_draw_arc.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_img.c b/bdk/libs/lvgl/lv_draw/lv_draw_img.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_img.c
rename to bdk/libs/lvgl/lv_draw/lv_draw_img.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_img.h b/bdk/libs/lvgl/lv_draw/lv_draw_img.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_img.h
rename to bdk/libs/lvgl/lv_draw/lv_draw_img.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_label.c b/bdk/libs/lvgl/lv_draw/lv_draw_label.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_label.c
rename to bdk/libs/lvgl/lv_draw/lv_draw_label.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_label.h b/bdk/libs/lvgl/lv_draw/lv_draw_label.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_label.h
rename to bdk/libs/lvgl/lv_draw/lv_draw_label.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_line.c b/bdk/libs/lvgl/lv_draw/lv_draw_line.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_line.c
rename to bdk/libs/lvgl/lv_draw/lv_draw_line.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_line.h b/bdk/libs/lvgl/lv_draw/lv_draw_line.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_line.h
rename to bdk/libs/lvgl/lv_draw/lv_draw_line.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_rbasic.c b/bdk/libs/lvgl/lv_draw/lv_draw_rbasic.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_rbasic.c
rename to bdk/libs/lvgl/lv_draw/lv_draw_rbasic.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_rbasic.h b/bdk/libs/lvgl/lv_draw/lv_draw_rbasic.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_rbasic.h
rename to bdk/libs/lvgl/lv_draw/lv_draw_rbasic.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_rect.c b/bdk/libs/lvgl/lv_draw/lv_draw_rect.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_rect.c
rename to bdk/libs/lvgl/lv_draw/lv_draw_rect.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_rect.h b/bdk/libs/lvgl/lv_draw/lv_draw_rect.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_rect.h
rename to bdk/libs/lvgl/lv_draw/lv_draw_rect.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_triangle.c b/bdk/libs/lvgl/lv_draw/lv_draw_triangle.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_triangle.c
rename to bdk/libs/lvgl/lv_draw/lv_draw_triangle.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_triangle.h b/bdk/libs/lvgl/lv_draw/lv_draw_triangle.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_triangle.h
rename to bdk/libs/lvgl/lv_draw/lv_draw_triangle.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_vbasic.c b/bdk/libs/lvgl/lv_draw/lv_draw_vbasic.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_vbasic.c
rename to bdk/libs/lvgl/lv_draw/lv_draw_vbasic.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_vbasic.h b/bdk/libs/lvgl/lv_draw/lv_draw_vbasic.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_draw/lv_draw_vbasic.h
rename to bdk/libs/lvgl/lv_draw/lv_draw_vbasic.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_120.c b/bdk/libs/lvgl/lv_fonts/hekate_symbol_120.c
similarity index 98%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_120.c
rename to bdk/libs/lvgl/lv_fonts/hekate_symbol_120.c
index 9a27deb..c97eda6 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_120.c
+++ b/bdk/libs/lvgl/lv_fonts/hekate_symbol_120.c
@@ -16,7 +16,7 @@
#include "../lv_misc/lv_font.h"
-#include "../../../../../common/memory_map.h"
+#include
#if USE_HEKATE_SYMBOL_120 != 0 /*Can be enabled in lv_conf.h*/
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_20.c b/bdk/libs/lvgl/lv_fonts/hekate_symbol_20.c
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_20.c
rename to bdk/libs/lvgl/lv_fonts/hekate_symbol_20.c
index 8ded987..426bde8 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_20.c
+++ b/bdk/libs/lvgl/lv_fonts/hekate_symbol_20.c
@@ -16,7 +16,7 @@
#include "../lv_misc/lv_font.h"
-#include "../../../../../common/memory_map.h"
+#include
#if USE_HEKATE_SYMBOL_20 != 0 /*Can be enabled in lv_conf.h*/
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_30.c b/bdk/libs/lvgl/lv_fonts/hekate_symbol_30.c
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_30.c
rename to bdk/libs/lvgl/lv_fonts/hekate_symbol_30.c
index 08842d2..4e0da47 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_fonts/hekate_symbol_30.c
+++ b/bdk/libs/lvgl/lv_fonts/hekate_symbol_30.c
@@ -16,7 +16,7 @@
#include "../lv_misc/lv_font.h"
-#include "../../../../../common/memory_map.h"
+#include
#if USE_HEKATE_SYMBOL_30 != 0 /*Can be enabled in lv_conf.h*/
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/interui_20.c b/bdk/libs/lvgl/lv_fonts/interui_20.c
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/interui_20.c
rename to bdk/libs/lvgl/lv_fonts/interui_20.c
index db0bbe5..5f50c6c 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_fonts/interui_20.c
+++ b/bdk/libs/lvgl/lv_fonts/interui_20.c
@@ -16,7 +16,7 @@
#include "../lv_misc/lv_font.h"
-#include "../../../../../common/memory_map.h"
+#include
#if USE_INTERUI_20 != 0 /*Can be enabled in lv_conf.h*/
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/interui_30.c b/bdk/libs/lvgl/lv_fonts/interui_30.c
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/interui_30.c
rename to bdk/libs/lvgl/lv_fonts/interui_30.c
index 1f97abf..238bcb1 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_fonts/interui_30.c
+++ b/bdk/libs/lvgl/lv_fonts/interui_30.c
@@ -16,7 +16,7 @@
#include "../lv_misc/lv_font.h"
-#include "../../../../../common/memory_map.h"
+#include
#if USE_INTERUI_30 != 0 /*Can be enabled in lv_conf.h*/
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/lv_font_builtin.c b/bdk/libs/lvgl/lv_fonts/lv_font_builtin.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/lv_font_builtin.c
rename to bdk/libs/lvgl/lv_fonts/lv_font_builtin.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/lv_font_builtin.h b/bdk/libs/lvgl/lv_fonts/lv_font_builtin.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/lv_font_builtin.h
rename to bdk/libs/lvgl/lv_fonts/lv_font_builtin.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/lv_fonts.mk b/bdk/libs/lvgl/lv_fonts/lv_fonts.mk
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/lv_fonts.mk
rename to bdk/libs/lvgl/lv_fonts/lv_fonts.mk
diff --git a/nyx/nyx_gui/libs/lvgl/lv_fonts/ubuntu_mono.c b/bdk/libs/lvgl/lv_fonts/ubuntu_mono.c
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_fonts/ubuntu_mono.c
rename to bdk/libs/lvgl/lv_fonts/ubuntu_mono.c
index b88cb2c..4c988fc 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_fonts/ubuntu_mono.c
+++ b/bdk/libs/lvgl/lv_fonts/ubuntu_mono.c
@@ -16,7 +16,7 @@
#include "../lv_misc/lv_font.h"
-#include "../../../../../common/memory_map.h"
+#include
#if USE_UBUNTU_MONO != 0 /*Can be enabled in lv_conf.h*/
diff --git a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal.h b/bdk/libs/lvgl/lv_hal/lv_hal.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal.h
rename to bdk/libs/lvgl/lv_hal/lv_hal.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal.mk b/bdk/libs/lvgl/lv_hal/lv_hal.mk
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal.mk
rename to bdk/libs/lvgl/lv_hal/lv_hal.mk
diff --git a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_disp.c b/bdk/libs/lvgl/lv_hal/lv_hal_disp.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_disp.c
rename to bdk/libs/lvgl/lv_hal/lv_hal_disp.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_disp.h b/bdk/libs/lvgl/lv_hal/lv_hal_disp.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_disp.h
rename to bdk/libs/lvgl/lv_hal/lv_hal_disp.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_indev.c b/bdk/libs/lvgl/lv_hal/lv_hal_indev.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_indev.c
rename to bdk/libs/lvgl/lv_hal/lv_hal_indev.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_indev.h b/bdk/libs/lvgl/lv_hal/lv_hal_indev.h
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_indev.h
rename to bdk/libs/lvgl/lv_hal/lv_hal_indev.h
index b9d4255..2355baa 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_indev.h
+++ b/bdk/libs/lvgl/lv_hal/lv_hal_indev.h
@@ -17,7 +17,7 @@ extern "C" {
*********************/
#include
#include "lv_hal.h"
-#include "../../../utils/types.h"
+#include
#include "../lv_misc/lv_area.h"
#include "../lv_core/lv_obj.h"
diff --git a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_tick.c b/bdk/libs/lvgl/lv_hal/lv_hal_tick.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_tick.c
rename to bdk/libs/lvgl/lv_hal/lv_hal_tick.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_tick.h b/bdk/libs/lvgl/lv_hal/lv_hal_tick.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_hal/lv_hal_tick.h
rename to bdk/libs/lvgl/lv_hal/lv_hal_tick.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_anim.c b/bdk/libs/lvgl/lv_misc/lv_anim.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_anim.c
rename to bdk/libs/lvgl/lv_misc/lv_anim.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_anim.h b/bdk/libs/lvgl/lv_misc/lv_anim.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_anim.h
rename to bdk/libs/lvgl/lv_misc/lv_anim.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_area.c b/bdk/libs/lvgl/lv_misc/lv_area.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_area.c
rename to bdk/libs/lvgl/lv_misc/lv_area.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_area.h b/bdk/libs/lvgl/lv_misc/lv_area.h
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_area.h
rename to bdk/libs/lvgl/lv_misc/lv_area.h
index bae0753..63ea059 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_area.h
+++ b/bdk/libs/lvgl/lv_misc/lv_area.h
@@ -15,7 +15,7 @@ extern "C" {
* INCLUDES
*********************/
#include
-#include "../../../utils/types.h"
+#include
/*********************
* DEFINES
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_circ.c b/bdk/libs/lvgl/lv_misc/lv_circ.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_circ.c
rename to bdk/libs/lvgl/lv_misc/lv_circ.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_circ.h b/bdk/libs/lvgl/lv_misc/lv_circ.h
similarity index 98%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_circ.h
rename to bdk/libs/lvgl/lv_misc/lv_circ.h
index f0fbb3f..bc1c1dd 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_circ.h
+++ b/bdk/libs/lvgl/lv_misc/lv_circ.h
@@ -16,7 +16,7 @@ extern "C" {
*********************/
#include
#include "lv_area.h"
-#include "../../../utils/types.h"
+#include
/*********************
* DEFINES
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_color.c b/bdk/libs/lvgl/lv_misc/lv_color.c
similarity index 62%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_color.c
rename to bdk/libs/lvgl/lv_misc/lv_color.c
index 81b20ed..8c12193 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_color.c
+++ b/bdk/libs/lvgl/lv_misc/lv_color.c
@@ -1,3 +1,19 @@
+/*
+ * 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 .
+ */
+
/**
* @file lv_color.c
*
@@ -12,6 +28,8 @@
* DEFINES
*********************/
+#define HUE_DEGREE 512
+
/**********************
* TYPEDEFS
**********************/
@@ -43,57 +61,68 @@
* @param v value [0..100]
* @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
*/
-lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)
+lv_color_t lv_color_hsv_to_rgb(uint16_t hue, uint8_t sat, uint8_t val)
{
- if(s == 0)
- return LV_COLOR_MAKE(v, v, v);
-
- h = (uint32_t)((uint32_t)h * 255) / 360;
- s = (uint16_t)((uint16_t)s * 255) / 100;
- v = (uint16_t)((uint16_t)v * 255) / 100;
-
uint8_t r, g, b;
- uint8_t region, remainder, p, q, t;
+ uint32_t h = (hue * 360 * HUE_DEGREE -1) / 360;
+ uint32_t s = sat * 255 / 100;
+ uint32_t v = val * 255 / 100;
+ uint32_t p = (256 * v - s * v) / 256;
+ uint32_t region = h / (60 * 512);
+
+ if(sat == 0)
+ return LV_COLOR_MAKE(v, v, v);
- region = h / 43;
- remainder = (h - (region * 43)) * 6;
+ if (region & 1)
+ {
+ uint32_t q = (256 * 60 * HUE_DEGREE * v - h * s * v + 60 * HUE_DEGREE * s * v * region) /
+ (256 * 60 * HUE_DEGREE);
- p = (v * (255 - s)) >> 8;
- q = (v * (255 - ((s * remainder) >> 8))) >> 8;
- t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
-
- switch(region) {
- case 0:
- r = v;
- g = t;
- b = p;
- break;
+ switch (region)
+ {
case 1:
r = q;
g = v;
b = p;
break;
+ case 3:
+ r = p;
+ g = q;
+ b = v;
+ break;
+ case 5:
+ default:
+ r = v;
+ g = p;
+ b = q;
+ break;
+ }
+ }
+ else
+ {
+ uint32_t t = (256 * 60 * HUE_DEGREE * v + h * s * v - 60 * HUE_DEGREE * s * v * (region + 1)) /
+ (256 * 60 * HUE_DEGREE);
+
+ switch (region)
+ {
+ case 0:
+ r = v;
+ g = t;
+ b = p;
+ break;
case 2:
r = p;
g = v;
b = t;
break;
- case 3:
- r = p;
- g = q;
- b = v;
- break;
case 4:
+ default:
r = t;
g = p;
b = v;
break;
- default:
- r = v;
- g = p;
- b = q;
- break;
+ }
}
return LV_COLOR_MAKE(r, g, b);
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_color.h b/bdk/libs/lvgl/lv_misc/lv_color.h
similarity index 95%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_color.h
rename to bdk/libs/lvgl/lv_misc/lv_color.h
index 45f95db..59f038f 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_color.h
+++ b/bdk/libs/lvgl/lv_misc/lv_color.h
@@ -412,17 +412,17 @@ static inline uint8_t lv_color_brightness(lv_color_t color)
#endif
#if LV_COLOR_DEPTH == 32 // Concatenate into one 32-bit set.
-#define LV_COLOR_HEX(c) ((lv_color_t){.full = (c | 0xFF000000)})
+#define LV_COLOR_HEX(c) ((lv_color_t){.full = ((c) | 0xFF000000)})
#else
-#define LV_COLOR_HEX(c) LV_COLOR_MAKE(((uint32_t)((uint32_t)c >> 16) & 0xFF), \
- ((uint32_t)((uint32_t)c >> 8) & 0xFF), \
- ((uint32_t) c & 0xFF))
+#define LV_COLOR_HEX(c) LV_COLOR_MAKE(((uint32_t)((uint32_t)(c) >> 16) & 0xFF), \
+ ((uint32_t)((uint32_t)(c) >> 8) & 0xFF), \
+ ((uint32_t) (c) & 0xFF))
#endif
/*Usage LV_COLOR_HEX3(0x16C) which means LV_COLOR_HEX(0x1166CC)*/
-#define LV_COLOR_HEX3(c) LV_COLOR_MAKE((((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), \
- ((uint32_t)(c & 0xF0) | ((c & 0xF0) >> 4)), \
- ((uint32_t)(c & 0xF) | ((c & 0xF) << 4)))
+#define LV_COLOR_HEX3(c) LV_COLOR_MAKE(((((c) >> 4) & 0xF0) | (((c) >> 8) & 0xF)), \
+ ((uint32_t)((c) & 0xF0) | (((c) & 0xF0) >> 4)), \
+ ((uint32_t)((c) & 0xF) | (((c) & 0xF) << 4)))
/**
@@ -432,7 +432,7 @@ static inline uint8_t lv_color_brightness(lv_color_t color)
* @param v value [0..100]
* @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
*/
-lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v);
+lv_color_t lv_color_hsv_to_rgb(uint16_t hue, uint8_t sat, uint8_t val);
/**
* Convert an RGB color to HSV
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_font.c b/bdk/libs/lvgl/lv_misc/lv_font.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_font.c
rename to bdk/libs/lvgl/lv_misc/lv_font.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_font.h b/bdk/libs/lvgl/lv_misc/lv_font.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_font.h
rename to bdk/libs/lvgl/lv_misc/lv_font.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_fs.c b/bdk/libs/lvgl/lv_misc/lv_fs.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_fs.c
rename to bdk/libs/lvgl/lv_misc/lv_fs.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_fs.h b/bdk/libs/lvgl/lv_misc/lv_fs.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_fs.h
rename to bdk/libs/lvgl/lv_misc/lv_fs.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_gc.c b/bdk/libs/lvgl/lv_misc/lv_gc.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_gc.c
rename to bdk/libs/lvgl/lv_misc/lv_gc.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_gc.h b/bdk/libs/lvgl/lv_misc/lv_gc.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_gc.h
rename to bdk/libs/lvgl/lv_misc/lv_gc.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_ll.c b/bdk/libs/lvgl/lv_misc/lv_ll.c
similarity index 98%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_ll.c
rename to bdk/libs/lvgl/lv_misc/lv_ll.c
index 43d8847..5583311 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_ll.c
+++ b/bdk/libs/lvgl/lv_misc/lv_ll.c
@@ -215,9 +215,12 @@ void lv_ll_clear(lv_ll_t * ll_p)
* @param ll_ori_p pointer to the original (old) linked list
* @param ll_new_p pointer to the new linked list
* @param node pointer to a node
+ * @return head changed
*/
-void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node)
+bool lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node)
{
+ bool changed = ll_new_p->head != node;
+
lv_ll_rem(ll_ori_p, node);
/*Set node as head*/
@@ -232,6 +235,8 @@ void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node)
if(ll_new_p->tail == NULL) { /*If there is no tail (first node) set the tail too*/
ll_new_p->tail = node;
}
+
+ return changed;
}
/**
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_ll.h b/bdk/libs/lvgl/lv_misc/lv_ll.h
similarity index 97%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_ll.h
rename to bdk/libs/lvgl/lv_misc/lv_ll.h
index 086ba40..5bde7e5 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_ll.h
+++ b/bdk/libs/lvgl/lv_misc/lv_ll.h
@@ -89,8 +89,9 @@ void lv_ll_clear(lv_ll_t * ll_p);
* @param ll_ori_p pointer to the original (old) linked list
* @param ll_new_p pointer to the new linked list
* @param node pointer to a node
+ * @return head changed
*/
-void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node);
+bool lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node);
/**
* Return with head node of the linked list
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_log.c b/bdk/libs/lvgl/lv_misc/lv_log.c
similarity index 91%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_log.c
rename to bdk/libs/lvgl/lv_misc/lv_log.c
index 79f8113..9cd3d49 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_log.c
+++ b/bdk/libs/lvgl/lv_misc/lv_log.c
@@ -11,9 +11,9 @@
#if LV_LOG_PRINTF
#include
-#include "../../../mem/heap.h"
-#include "../../../soc/uart.h"
-#include "../../../utils/sprintf.h"
+#include
+#include
+#include
#endif
/*********************
* DEFINES
@@ -63,11 +63,11 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char *
if(level >= LV_LOG_LEVEL) {
-#if LV_LOG_PRINTF
+#if LV_LOG_PRINTF && defined(DEBUG_UART_PORT)
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
char *log = (char *)malloc(0x1000);
s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line);
- uart_send(UART_B, (u8 *)log, strlen(log) + 1);
+ uart_send(DEBUG_UART_PORT, (u8 *)log, strlen(log) + 1);
//gfx_printf("%s: %s \t(%s #%d)\n", lvl_prefix[level], dsc, file, line);
#else
if(print_cb) print_cb(level, file, line, dsc);
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_log.h b/bdk/libs/lvgl/lv_misc/lv_log.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_log.h
rename to bdk/libs/lvgl/lv_misc/lv_log.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_math.c b/bdk/libs/lvgl/lv_misc/lv_math.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_math.c
rename to bdk/libs/lvgl/lv_misc/lv_math.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_math.h b/bdk/libs/lvgl/lv_misc/lv_math.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_math.h
rename to bdk/libs/lvgl/lv_misc/lv_math.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_mem.c b/bdk/libs/lvgl/lv_misc/lv_mem.c
similarity index 90%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_mem.c
rename to bdk/libs/lvgl/lv_misc/lv_mem.c
index 9156e86..08f52d5 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_mem.c
+++ b/bdk/libs/lvgl/lv_misc/lv_mem.c
@@ -1,3 +1,19 @@
+/*
+ * 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 .
+ */
+
/**
* @file lv_mem.c
* General and portable implementation of malloc and free.
@@ -11,6 +27,8 @@
#include "lv_math.h"
#include
+#include
+
#if LV_MEM_CUSTOM != 0
#include LV_MEM_CUSTOM_INCLUDE
#endif
@@ -38,12 +56,14 @@
typedef union {
struct {
MEM_UNIT used: 1; //1: if the entry is used
- MEM_UNIT d_size: 31; //Size off the data (1 means 4 bytes)
+ MEM_UNIT d_size: 31; //Size of the data
};
MEM_UNIT header; //The header (used + d_size)
- uint32_t align[7]; //Align header size to 32 bytes
+ MEM_UNIT align[8]; //Align header size to MEM_UNIT * 8 bytes
} lv_mem_header_t;
+static_assert(sizeof(lv_mem_header_t) == 32, "Node header must be 32 bytes!");
+
typedef struct {
lv_mem_header_t header;
uint8_t first_data; /*First data byte in the allocated data (Just for easily create a pointer)*/
@@ -110,10 +130,10 @@ void * lv_mem_alloc(uint32_t size)
return &zero_mem;
}
- /*Round the size up to 32*/
- if(size & 0x1F) {
- size = size & (~0x1F);
- size += 0x20;
+ /*Round the size to lv_mem_header_t*/
+ if(size & (sizeof(lv_mem_header_t) - 1)) {
+ size = size & (~(sizeof(lv_mem_header_t) - 1));
+ size += sizeof(lv_mem_header_t);
}
void * alloc = NULL;
@@ -213,6 +233,12 @@ void lv_mem_free(const void * data)
void * lv_mem_realloc(void * data_p, uint32_t new_size)
{
+ /*Round the size to lv_mem_header_t*/
+ if(new_size & (sizeof(lv_mem_header_t) - 1)) {
+ new_size = new_size & (~(sizeof(lv_mem_header_t) - 1));
+ new_size += sizeof(lv_mem_header_t);
+ }
+
/*data_p could be previously freed pointer (in this case it is invalid)*/
if(data_p != NULL) {
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *) data_p - sizeof(lv_mem_header_t));
@@ -424,13 +450,6 @@ static void * ent_alloc(lv_mem_ent_t * e, uint32_t size)
*/
static void ent_trunc(lv_mem_ent_t * e, uint32_t size)
{
-
- /*Round the size up to 32*/
- if(size & 0x1F) {
- size = size & (~0x1F);
- size += 0x20;
- }
-
/*Don't let empty space only for a header without data*/
if(e->header.d_size == size + sizeof(lv_mem_header_t)) {
size = e->header.d_size;
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_mem.h b/bdk/libs/lvgl/lv_misc/lv_mem.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_mem.h
rename to bdk/libs/lvgl/lv_misc/lv_mem.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_misc.mk b/bdk/libs/lvgl/lv_misc/lv_misc.mk
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_misc.mk
rename to bdk/libs/lvgl/lv_misc/lv_misc.mk
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_symbol_def.h b/bdk/libs/lvgl/lv_misc/lv_symbol_def.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_symbol_def.h
rename to bdk/libs/lvgl/lv_misc/lv_symbol_def.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_task.c b/bdk/libs/lvgl/lv_misc/lv_task.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_task.c
rename to bdk/libs/lvgl/lv_misc/lv_task.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_task.h b/bdk/libs/lvgl/lv_misc/lv_task.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_task.h
rename to bdk/libs/lvgl/lv_misc/lv_task.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_templ.c b/bdk/libs/lvgl/lv_misc/lv_templ.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_templ.c
rename to bdk/libs/lvgl/lv_misc/lv_templ.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_templ.h b/bdk/libs/lvgl/lv_misc/lv_templ.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_templ.h
rename to bdk/libs/lvgl/lv_misc/lv_templ.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_txt.c b/bdk/libs/lvgl/lv_misc/lv_txt.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_txt.c
rename to bdk/libs/lvgl/lv_misc/lv_txt.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_txt.h b/bdk/libs/lvgl/lv_misc/lv_txt.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_txt.h
rename to bdk/libs/lvgl/lv_misc/lv_txt.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_ufs.c b/bdk/libs/lvgl/lv_misc/lv_ufs.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_ufs.c
rename to bdk/libs/lvgl/lv_misc/lv_ufs.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_misc/lv_ufs.h b/bdk/libs/lvgl/lv_misc/lv_ufs.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_misc/lv_ufs.h
rename to bdk/libs/lvgl/lv_misc/lv_ufs.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_arc.c b/bdk/libs/lvgl/lv_objx/lv_arc.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_arc.c
rename to bdk/libs/lvgl/lv_objx/lv_arc.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_arc.h b/bdk/libs/lvgl/lv_objx/lv_arc.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_arc.h
rename to bdk/libs/lvgl/lv_objx/lv_arc.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_bar.c b/bdk/libs/lvgl/lv_objx/lv_bar.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_bar.c
rename to bdk/libs/lvgl/lv_objx/lv_bar.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_bar.h b/bdk/libs/lvgl/lv_objx/lv_bar.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_bar.h
rename to bdk/libs/lvgl/lv_objx/lv_bar.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_btn.c b/bdk/libs/lvgl/lv_objx/lv_btn.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_btn.c
rename to bdk/libs/lvgl/lv_objx/lv_btn.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_btn.h b/bdk/libs/lvgl/lv_objx/lv_btn.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_btn.h
rename to bdk/libs/lvgl/lv_objx/lv_btn.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_btnm.c b/bdk/libs/lvgl/lv_objx/lv_btnm.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_btnm.c
rename to bdk/libs/lvgl/lv_objx/lv_btnm.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_btnm.h b/bdk/libs/lvgl/lv_objx/lv_btnm.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_btnm.h
rename to bdk/libs/lvgl/lv_objx/lv_btnm.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_calendar.c b/bdk/libs/lvgl/lv_objx/lv_calendar.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_calendar.c
rename to bdk/libs/lvgl/lv_objx/lv_calendar.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_calendar.h b/bdk/libs/lvgl/lv_objx/lv_calendar.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_calendar.h
rename to bdk/libs/lvgl/lv_objx/lv_calendar.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_canvas.c b/bdk/libs/lvgl/lv_objx/lv_canvas.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_canvas.c
rename to bdk/libs/lvgl/lv_objx/lv_canvas.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_canvas.h b/bdk/libs/lvgl/lv_objx/lv_canvas.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_canvas.h
rename to bdk/libs/lvgl/lv_objx/lv_canvas.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_cb.c b/bdk/libs/lvgl/lv_objx/lv_cb.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_cb.c
rename to bdk/libs/lvgl/lv_objx/lv_cb.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_cb.h b/bdk/libs/lvgl/lv_objx/lv_cb.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_cb.h
rename to bdk/libs/lvgl/lv_objx/lv_cb.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_chart.c b/bdk/libs/lvgl/lv_objx/lv_chart.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_chart.c
rename to bdk/libs/lvgl/lv_objx/lv_chart.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_chart.h b/bdk/libs/lvgl/lv_objx/lv_chart.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_chart.h
rename to bdk/libs/lvgl/lv_objx/lv_chart.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_cont.c b/bdk/libs/lvgl/lv_objx/lv_cont.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_cont.c
rename to bdk/libs/lvgl/lv_objx/lv_cont.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_cont.h b/bdk/libs/lvgl/lv_objx/lv_cont.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_cont.h
rename to bdk/libs/lvgl/lv_objx/lv_cont.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_ddlist.c b/bdk/libs/lvgl/lv_objx/lv_ddlist.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_ddlist.c
rename to bdk/libs/lvgl/lv_objx/lv_ddlist.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_ddlist.h b/bdk/libs/lvgl/lv_objx/lv_ddlist.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_ddlist.h
rename to bdk/libs/lvgl/lv_objx/lv_ddlist.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_gauge.c b/bdk/libs/lvgl/lv_objx/lv_gauge.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_gauge.c
rename to bdk/libs/lvgl/lv_objx/lv_gauge.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_gauge.h b/bdk/libs/lvgl/lv_objx/lv_gauge.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_gauge.h
rename to bdk/libs/lvgl/lv_objx/lv_gauge.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_img.c b/bdk/libs/lvgl/lv_objx/lv_img.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_img.c
rename to bdk/libs/lvgl/lv_objx/lv_img.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_img.h b/bdk/libs/lvgl/lv_objx/lv_img.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_img.h
rename to bdk/libs/lvgl/lv_objx/lv_img.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_imgbtn.c b/bdk/libs/lvgl/lv_objx/lv_imgbtn.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_imgbtn.c
rename to bdk/libs/lvgl/lv_objx/lv_imgbtn.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_imgbtn.h b/bdk/libs/lvgl/lv_objx/lv_imgbtn.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_imgbtn.h
rename to bdk/libs/lvgl/lv_objx/lv_imgbtn.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_kb.c b/bdk/libs/lvgl/lv_objx/lv_kb.c
similarity index 93%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_kb.c
rename to bdk/libs/lvgl/lv_objx/lv_kb.c
index 395fc8d..8548d55 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_kb.c
+++ b/bdk/libs/lvgl/lv_objx/lv_kb.c
@@ -1,3 +1,18 @@
+/*
+ * 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 .
+ */
/**
* @file lv_kb.c
@@ -59,6 +74,13 @@ static const char * kb_map_num[] = {
"7", "8", "9", "\202Bksp", "\n",
"+/-", "0", ".", SYMBOL_LEFT, SYMBOL_RIGHT, ""
};
+
+static const char * kb_map_hex[] = {
+ "1", "2", "3", "A", "D", "\212", "\n",
+ "4", "5", "6", "B", "E", "\202Bksp", "\n",
+ "7", "8", "9", "C", "F", "\202"SYMBOL_OK, "\n",
+ "\211", "0", "\213", SYMBOL_LEFT, SYMBOL_RIGHT, ""
+};
/**********************
* MACROS
**********************/
@@ -183,6 +205,7 @@ void lv_kb_set_mode(lv_obj_t * kb, lv_kb_mode_t mode)
ext->mode = mode;
if(mode == LV_KB_MODE_TEXT) lv_btnm_set_map(kb, kb_map_lc);
else if(mode == LV_KB_MODE_NUM) lv_btnm_set_map(kb, kb_map_num);
+ else if (mode == LV_KB_MODE_HEX) lv_btnm_set_map(kb, kb_map_hex);
}
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_kb.h b/bdk/libs/lvgl/lv_objx/lv_kb.h
similarity index 88%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_kb.h
rename to bdk/libs/lvgl/lv_objx/lv_kb.h
index c729a4e..027b121 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_kb.h
+++ b/bdk/libs/lvgl/lv_objx/lv_kb.h
@@ -1,3 +1,19 @@
+/*
+ * 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 .
+ */
+
/**
* @file lv_kb.h
*
@@ -44,6 +60,7 @@ extern "C" {
enum {
LV_KB_MODE_TEXT,
LV_KB_MODE_NUM,
+ LV_KB_MODE_HEX
};
typedef uint8_t lv_kb_mode_t;
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_label.c b/bdk/libs/lvgl/lv_objx/lv_label.c
similarity index 99%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_label.c
rename to bdk/libs/lvgl/lv_objx/lv_label.c
index 77b087a..57ac2d0 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_label.c
+++ b/bdk/libs/lvgl/lv_objx/lv_label.c
@@ -156,7 +156,7 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
return;
}
- if(ext->text == text) {
+ if(ext->text == text && ext->static_txt == 0) {
/*If set its own text then reallocate it (maybe its size changed)*/
ext->text = lv_mem_realloc(ext->text, strlen(ext->text) + 1);
lv_mem_assert(ext->text);
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_label.h b/bdk/libs/lvgl/lv_objx/lv_label.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_label.h
rename to bdk/libs/lvgl/lv_objx/lv_label.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_led.c b/bdk/libs/lvgl/lv_objx/lv_led.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_led.c
rename to bdk/libs/lvgl/lv_objx/lv_led.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_led.h b/bdk/libs/lvgl/lv_objx/lv_led.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_led.h
rename to bdk/libs/lvgl/lv_objx/lv_led.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_line.c b/bdk/libs/lvgl/lv_objx/lv_line.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_line.c
rename to bdk/libs/lvgl/lv_objx/lv_line.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_line.h b/bdk/libs/lvgl/lv_objx/lv_line.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_line.h
rename to bdk/libs/lvgl/lv_objx/lv_line.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_list.c b/bdk/libs/lvgl/lv_objx/lv_list.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_list.c
rename to bdk/libs/lvgl/lv_objx/lv_list.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_list.h b/bdk/libs/lvgl/lv_objx/lv_list.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_list.h
rename to bdk/libs/lvgl/lv_objx/lv_list.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_lmeter.c b/bdk/libs/lvgl/lv_objx/lv_lmeter.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_lmeter.c
rename to bdk/libs/lvgl/lv_objx/lv_lmeter.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_lmeter.h b/bdk/libs/lvgl/lv_objx/lv_lmeter.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_lmeter.h
rename to bdk/libs/lvgl/lv_objx/lv_lmeter.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_mbox.c b/bdk/libs/lvgl/lv_objx/lv_mbox.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_mbox.c
rename to bdk/libs/lvgl/lv_objx/lv_mbox.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_mbox.h b/bdk/libs/lvgl/lv_objx/lv_mbox.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_mbox.h
rename to bdk/libs/lvgl/lv_objx/lv_mbox.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_objx.mk b/bdk/libs/lvgl/lv_objx/lv_objx.mk
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_objx.mk
rename to bdk/libs/lvgl/lv_objx/lv_objx.mk
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_objx_templ.c b/bdk/libs/lvgl/lv_objx/lv_objx_templ.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_objx_templ.c
rename to bdk/libs/lvgl/lv_objx/lv_objx_templ.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_objx_templ.h b/bdk/libs/lvgl/lv_objx/lv_objx_templ.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_objx_templ.h
rename to bdk/libs/lvgl/lv_objx/lv_objx_templ.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_page.c b/bdk/libs/lvgl/lv_objx/lv_page.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_page.c
rename to bdk/libs/lvgl/lv_objx/lv_page.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_page.h b/bdk/libs/lvgl/lv_objx/lv_page.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_page.h
rename to bdk/libs/lvgl/lv_objx/lv_page.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_preload.c b/bdk/libs/lvgl/lv_objx/lv_preload.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_preload.c
rename to bdk/libs/lvgl/lv_objx/lv_preload.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_preload.h b/bdk/libs/lvgl/lv_objx/lv_preload.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_preload.h
rename to bdk/libs/lvgl/lv_objx/lv_preload.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_roller.c b/bdk/libs/lvgl/lv_objx/lv_roller.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_roller.c
rename to bdk/libs/lvgl/lv_objx/lv_roller.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_roller.h b/bdk/libs/lvgl/lv_objx/lv_roller.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_roller.h
rename to bdk/libs/lvgl/lv_objx/lv_roller.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_slider.c b/bdk/libs/lvgl/lv_objx/lv_slider.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_slider.c
rename to bdk/libs/lvgl/lv_objx/lv_slider.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_slider.h b/bdk/libs/lvgl/lv_objx/lv_slider.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_slider.h
rename to bdk/libs/lvgl/lv_objx/lv_slider.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_spinbox.c b/bdk/libs/lvgl/lv_objx/lv_spinbox.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_spinbox.c
rename to bdk/libs/lvgl/lv_objx/lv_spinbox.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_spinbox.h b/bdk/libs/lvgl/lv_objx/lv_spinbox.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_spinbox.h
rename to bdk/libs/lvgl/lv_objx/lv_spinbox.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_sw.c b/bdk/libs/lvgl/lv_objx/lv_sw.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_sw.c
rename to bdk/libs/lvgl/lv_objx/lv_sw.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_sw.h b/bdk/libs/lvgl/lv_objx/lv_sw.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_sw.h
rename to bdk/libs/lvgl/lv_objx/lv_sw.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_ta.c b/bdk/libs/lvgl/lv_objx/lv_ta.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_ta.c
rename to bdk/libs/lvgl/lv_objx/lv_ta.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_ta.h b/bdk/libs/lvgl/lv_objx/lv_ta.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_ta.h
rename to bdk/libs/lvgl/lv_objx/lv_ta.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_table.c b/bdk/libs/lvgl/lv_objx/lv_table.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_table.c
rename to bdk/libs/lvgl/lv_objx/lv_table.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_table.h b/bdk/libs/lvgl/lv_objx/lv_table.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_table.h
rename to bdk/libs/lvgl/lv_objx/lv_table.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_tabview.c b/bdk/libs/lvgl/lv_objx/lv_tabview.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_tabview.c
rename to bdk/libs/lvgl/lv_objx/lv_tabview.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_tabview.h b/bdk/libs/lvgl/lv_objx/lv_tabview.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_tabview.h
rename to bdk/libs/lvgl/lv_objx/lv_tabview.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_tileview.c b/bdk/libs/lvgl/lv_objx/lv_tileview.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_tileview.c
rename to bdk/libs/lvgl/lv_objx/lv_tileview.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_tileview.h b/bdk/libs/lvgl/lv_objx/lv_tileview.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_tileview.h
rename to bdk/libs/lvgl/lv_objx/lv_tileview.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_win.c b/bdk/libs/lvgl/lv_objx/lv_win.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_win.c
rename to bdk/libs/lvgl/lv_objx/lv_win.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_objx/lv_win.h b/bdk/libs/lvgl/lv_objx/lv_win.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_objx/lv_win.h
rename to bdk/libs/lvgl/lv_objx/lv_win.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme.c b/bdk/libs/lvgl/lv_themes/lv_theme.c
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme.c
rename to bdk/libs/lvgl/lv_themes/lv_theme.c
diff --git a/nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme.h b/bdk/libs/lvgl/lv_themes/lv_theme.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme.h
rename to bdk/libs/lvgl/lv_themes/lv_theme.h
diff --git a/nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme_hekate.c b/bdk/libs/lvgl/lv_themes/lv_theme_hekate.c
similarity index 86%
rename from nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme_hekate.c
rename to bdk/libs/lvgl/lv_themes/lv_theme_hekate.c
index 423fcaf..f151dbe 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme_hekate.c
+++ b/bdk/libs/lvgl/lv_themes/lv_theme_hekate.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019 CTCaer
+ * Copyright (c) 2018-2022 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,
@@ -25,16 +25,23 @@
* DEFINES
*********************/
#define DEF_RADIUS 4
-#define COLOR_SHADOW_LIGHT LV_COLOR_HEX3(0xAAA)
+#define COLOR_SHADOW_LIGHT LV_COLOR_HEX(0xAAAAAA)
#define COLOR_SHADOW_DARK LV_COLOR_HEX(0x1F1F1F)
-#define COLOR_HOS_TURQUOISE LV_COLOR_HEX(0x00FFC9)
-#define COLOR_HOS_TEAL_LIGHTER LV_COLOR_HEX(0x00EDBA)
-#define COLOR_HOS_TEAL_LIGHT LV_COLOR_HEX(0x00B78F)
-#define COLOR_HOS_TEAL LV_COLOR_HEX(0x00A273)
-#define COLOR_HOS_BG LV_COLOR_HEX(0x2D2D2D)
-#define COLOR_HOS_BG_LIGHT LV_COLOR_HEX(0x3D3D3D)
+#define COLOR_HOS_TURQUOISE (lv_color_hsv_to_rgb(_hue, 100, 100)) // 0x00FFC9
+#define COLOR_HOS_TEAL_LIGHTER (lv_color_hsv_to_rgb(_hue, 100, 93)) // 0x00EDBA
+#define COLOR_HOS_TEAL_LIGHT (lv_color_hsv_to_rgb(_hue, 100, 72)) // 0x00B78F
+#define COLOR_HOS_TEAL (lv_color_hsv_to_rgb(_hue, 100, 64)) // 0x00A273
+#define COLOR_HOS_ORANGE LV_COLOR_HEX(0xFF5500)
#define COLOR_HOS_TXT_WHITE LV_COLOR_HEX(0xFBFBFB)
+#define COLOR_BG_DARKER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color - 0x121212) : 0x0B0B0B) // 0x1B1B1B.
+#define COLOR_BG_DARK LV_COLOR_HEX(theme_bg_color ? (theme_bg_color - 0x0B0B0B) : 0x121212) // 0x222222.
+#define COLOR_BG LV_COLOR_HEX(theme_bg_color) // 0x2D2D2D.
+#define COLOR_BG_LIGHT LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x101010) : 0x2D2D2D) // 0x3D3D3D.
+#define COLOR_BG_LIGHTER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x191919) : 0x363636) // 0x464646.
+#define COLOR_LIGHT_BORDER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x202020) : 0x3D3D3D) // 0x4D4D4D.
+
+
/**********************
* TYPEDEFS
**********************/
@@ -53,8 +60,9 @@ static lv_style_t def;
static lv_style_t sb;
/*Saved input parameters*/
-static uint16_t _hue;
+static uint16_t _hue;
static lv_font_t * _font;
+uint32_t theme_bg_color;
/**********************
* MACROS
@@ -76,18 +84,17 @@ static void basic_init(void)
//def.image.opa = LV_OPA_COVER;
lv_style_copy(&bg, &def);
- bg.body.main_color = COLOR_HOS_BG;
- //bg.body.main_color = LV_COLOR_BLACK;
+ bg.body.main_color = COLOR_BG;
bg.body.grad_color = bg.body.main_color;
bg.body.radius = 0;
bg.body.empty = 1;
lv_style_copy(&panel, &def);
panel.body.radius = DEF_RADIUS;
- panel.body.main_color = COLOR_HOS_BG;
- panel.body.grad_color = COLOR_HOS_BG;
+ panel.body.main_color = COLOR_BG;
+ panel.body.grad_color = COLOR_BG;
panel.body.border.width = 1;
- panel.body.border.color = LV_COLOR_HEX(0x4D4D4D);
+ panel.body.border.color = COLOR_LIGHT_BORDER;
panel.body.border.opa = LV_OPA_COVER;
panel.body.shadow.color = COLOR_SHADOW_LIGHT;
panel.body.shadow.type = LV_SHADOW_BOTTOM;
@@ -125,7 +132,7 @@ static void btn_init(void)
static lv_style_t rel, pr, tgl_rel, tgl_pr, ina;
lv_style_copy(&rel, &def);
- rel.body.main_color = COLOR_HOS_BG_LIGHT;
+ rel.body.main_color = COLOR_BG_LIGHT;
rel.body.grad_color = rel.body.main_color;
rel.body.radius = 6;
rel.body.padding.hor = LV_DPI / 3;
@@ -135,7 +142,7 @@ static void btn_init(void)
rel.body.shadow.type = LV_SHADOW_BOTTOM;
rel.body.shadow.width = 6;
rel.body.border.width = 0;
- rel.body.border.color = COLOR_HOS_BG_LIGHT;
+ rel.body.border.color = COLOR_BG_LIGHT;
rel.body.border.part = LV_BORDER_FULL;
//rel.text.color = COLOR_HOS_TXT_WHITE;
@@ -158,7 +165,7 @@ static void btn_init(void)
tgl_pr.body.shadow.width = 0;
lv_style_copy(&ina, &rel);
- ina.body.main_color = LV_COLOR_HEX(0x1B1B1B);
+ ina.body.main_color = COLOR_BG_DARK;
ina.body.grad_color = ina.body.main_color;
//ina.body.shadow.width = 0;
ina.text.color = LV_COLOR_HEX(0x888888);
@@ -183,10 +190,10 @@ static void label_init(void)
prim.text.color = COLOR_HOS_TXT_WHITE;
lv_style_copy(&sec, &prim);
- sec.text.color = LV_COLOR_HEX(0xFF5500);
+ sec.text.color = COLOR_HOS_ORANGE;
lv_style_copy(&hint, &prim);
- hint.text.color = LV_COLOR_HEX3(0xCCC);
+ hint.text.color = LV_COLOR_HEX(0xCCCCCC);
theme.label.prim = &prim;
theme.label.sec = &sec;
@@ -199,11 +206,11 @@ static void img_init(void)
#if USE_LV_IMG != 0
static lv_style_t img_light, img_dark;
lv_style_copy(&img_light, &def);
- img_light.image.color = LV_COLOR_HEX(0xffffff);
+ img_light.image.color = LV_COLOR_WHITE;
img_light.image.intense = LV_OPA_80;
lv_style_copy(&img_dark, &def);
- img_dark.image.color = LV_COLOR_HEX(0x1B1B1B);
+ img_dark.image.color = COLOR_BG_DARKER;
img_dark.image.intense = LV_OPA_80;
@@ -246,7 +253,7 @@ static void bar_init(void)
static lv_style_t bar_bg, bar_indic;
lv_style_copy(&bar_bg, &def);
- bar_bg.body.main_color = LV_COLOR_HEX(0x4D4D4D);
+ bar_bg.body.main_color = COLOR_LIGHT_BORDER;
bar_bg.body.grad_color = bar_bg.body.main_color;
bar_bg.body.radius = 3;
bar_bg.body.border.width = 0;
@@ -302,7 +309,7 @@ static void sw_init(void)
sw_knob_off.body.main_color = LV_COLOR_HEX(0xDADADA);
sw_knob_off.body.grad_color = sw_knob_off.body.main_color;
sw_knob_off.body.border.width = 1;
- sw_knob_off.body.border.color = LV_COLOR_HEX3(0x999);
+ sw_knob_off.body.border.color = LV_COLOR_HEX(0x999999);
sw_knob_off.body.border.opa = LV_OPA_COVER;
theme.sw.bg = &sw_bg;
@@ -321,7 +328,7 @@ static void lmeter_init(void)
lmeter.body.main_color = lv_color_hsv_to_rgb(_hue, 75, 90);
lmeter.body.grad_color = lmeter.body.main_color;
lmeter.body.padding.hor = LV_DPI / 10; // Scale line length.
- lmeter.line.color = LV_COLOR_HEX3(0x999);
+ lmeter.line.color = LV_COLOR_HEX(0x999999);
lmeter.line.width = 2;
theme.lmeter = &lmeter;
@@ -338,8 +345,8 @@ static void gauge_init(void)
gauge.body.grad_color = gauge.body.main_color;
gauge.body.padding.hor = LV_DPI / 16; // Scale line length.
gauge.body.padding.inner = LV_DPI / 8;
- gauge.body.border.color = LV_COLOR_HEX3(0x999);
- gauge.text.color = LV_COLOR_HEX3(0xddd);
+ gauge.body.border.color = LV_COLOR_HEX(0x999999);
+ gauge.text.color = LV_COLOR_HEX(0xDDDDDD);
gauge.line.width = 3;
gauge.line.color = lv_color_hsv_to_rgb(_hue, 95, 70);
@@ -428,7 +435,7 @@ static void cb_init(void)
rel.body.shadow.width = 3;
lv_style_copy(&pr, &rel);
- pr.body.main_color = LV_COLOR_HEX3(0xCCC);
+ pr.body.main_color = LV_COLOR_HEX(0xCCCCCC);
pr.body.grad_color = pr.body.main_color;
pr.body.shadow.width = 3;
@@ -462,18 +469,18 @@ static void btnm_init(void)
bg.body.padding.hor = 0;
bg.body.padding.ver = 0;
bg.body.padding.inner = 0;
- bg.text.color = LV_COLOR_HEX3(0x555);
+ bg.text.color = LV_COLOR_HEX(0x555555);
lv_style_copy(&rel, theme.panel);
rel.body.border.part = LV_BORDER_FULL | LV_BORDER_INTERNAL;
rel.body.border.width = 1;
- rel.body.border.color = LV_COLOR_HEX3(0xBBB);
+ rel.body.border.color = LV_COLOR_HEX(0xBBBBBB);
rel.body.empty = 1;
rel.body.shadow.width = 0;
lv_style_copy(&pr, &rel);
pr.glass = 0;
- pr.body.main_color = LV_COLOR_HEX3(0xDDD);
+ pr.body.main_color = LV_COLOR_HEX(0xDDDDDD);
pr.body.grad_color = pr.body.main_color;
pr.body.border.width = 0;
pr.body.empty = 0;
@@ -488,16 +495,14 @@ static void btnm_init(void)
tgl_pr.body.grad_color = tgl_pr.body.main_color;
tgl_pr.body.border.width = 0;
- lv_style_copy(&ina, &pr);
- ina.body.main_color = LV_COLOR_HEX3(0xCCC);
- ina.body.grad_color = ina.body.main_color;
+ lv_style_copy(&ina, theme.btn.ina);
theme.btnm.bg = &bg;
theme.btnm.btn.rel = &rel;
theme.btnm.btn.pr = ≺
theme.btnm.btn.tgl_rel = &tgl_rel;
theme.btnm.btn.tgl_pr = &tgl_pr;
- theme.btnm.btn.ina = &def;
+ theme.btnm.btn.ina = &ina;
#endif
}
@@ -508,7 +513,12 @@ static void kb_init(void)
static lv_style_t bg, rel;
lv_style_copy(&bg, theme.btnm.bg);
- bg.text.color = LV_COLOR_HEX3(0xCCC);
+ bg.text.color = LV_COLOR_HEX(0xCCCCCC);
+ bg.body.border.width = 0;
+ bg.body.radius = 0;
+ bg.body.shadow.color = COLOR_SHADOW_DARK;
+ bg.body.shadow.type = LV_SHADOW_BOTTOM;
+ bg.body.shadow.width = 4;
lv_style_copy(&rel, &lv_style_transp);
rel.text.font = _font;
@@ -529,9 +539,9 @@ static void mbox_init(void)
static lv_style_t bg;
lv_style_copy(&bg, theme.panel);
- bg.body.main_color = LV_COLOR_HEX(0x464646);
+ bg.body.main_color = COLOR_BG_LIGHTER;
bg.body.grad_color = bg.body.main_color;
- bg.body.shadow.color = COLOR_HOS_BG;
+ bg.body.shadow.color = COLOR_BG;
bg.body.shadow.type = LV_SHADOW_FULL;
bg.body.shadow.width = 8;
@@ -558,18 +568,24 @@ static void page_init(void)
static void ta_init(void)
{
#if USE_LV_TA
- static lv_style_t oneline;
+ static lv_style_t panel, oneline;
+
+ lv_style_copy(&panel, theme.panel);
+ panel.body.border.width = 0;
+ panel.body.shadow.color = COLOR_SHADOW_DARK;
+ panel.body.shadow.type = LV_SHADOW_FULL;
+ panel.body.shadow.width = 3;
lv_style_copy(&oneline, &def);
oneline.body.empty = 1;
oneline.body.radius = 0;
oneline.body.border.part = LV_BORDER_BOTTOM;
oneline.body.border.width = 3;
- oneline.body.border.color = LV_COLOR_HEX3(0x555);
+ oneline.body.border.color = LV_COLOR_HEX(0x555555);
oneline.body.border.opa = LV_OPA_COVER;
- oneline.text.color = LV_COLOR_HEX3(0x888);
+ oneline.text.color = LV_COLOR_HEX(0x888888);
- theme.ta.area = theme.panel;
+ theme.ta.area = &panel;
theme.ta.oneline = &oneline;
theme.ta.cursor = NULL; // Let library to calculate the cursor's style.
theme.ta.sb = &sb;
@@ -615,7 +631,7 @@ static void list_init(void)
// pr.text.font = _font;
lv_style_copy(&tgl_rel, &pr);
- tgl_rel.body.main_color = COLOR_HOS_BG_LIGHT;
+ tgl_rel.body.main_color = COLOR_BG_LIGHT;
tgl_rel.body.grad_color = tgl_rel.body.main_color;
//tgl_rel.text.color = lv_color_hsv_to_rgb(_hue, 5, 95);
tgl_rel.text.color = COLOR_HOS_TEAL_LIGHTER;
@@ -626,7 +642,7 @@ static void list_init(void)
tgl_pr.body.border.width = 0;
lv_style_copy(&ina, &pr);
- ina.body.main_color = LV_COLOR_HEX(0x1B1B1B);
+ ina.body.main_color = COLOR_BG_DARK;
ina.body.grad_color = ina.body.main_color;
theme.list.sb = &sb;
@@ -654,7 +670,7 @@ static void ddlist_init(void)
bg.text.color = COLOR_HOS_TURQUOISE;
lv_style_copy(&sel, &bg);
- sel.body.main_color = COLOR_HOS_BG_LIGHT;
+ sel.body.main_color = COLOR_BG_LIGHT;
sel.body.grad_color = sel.body.main_color;
theme.ddlist.bg = &bg;
@@ -676,7 +692,7 @@ static void roller_init(void)
roller_bg.text.line_space = LV_DPI / 8;
roller_bg.text.font = _font;
roller_bg.glass = 0;
- roller_bg.text.color = LV_COLOR_HEX3(0x444);
+ roller_bg.text.color = LV_COLOR_HEX(0x444444);
lv_style_copy(&roller_sel, &roller_bg);
roller_sel.text.color = COLOR_HOS_TURQUOISE;
@@ -700,12 +716,12 @@ static void tabview_init(void)
indic.body.opa = LV_OPA_0;
lv_style_copy(&btn_bg, &def);
- btn_bg.body.main_color = COLOR_HOS_BG;
+ btn_bg.body.main_color = COLOR_BG;
btn_bg.body.grad_color = btn_bg.body.main_color;
btn_bg.body.radius = 0;
btn_bg.body.empty = 1;
btn_bg.body.border.width = 0;
- btn_bg.body.border.color = LV_COLOR_HEX3(0xDDD);
+ btn_bg.body.border.color = LV_COLOR_HEX(0xDDDDDD);
btn_bg.body.border.part = LV_BORDER_BOTTOM;
btn_bg.body.border.opa = LV_OPA_COVER;
btn_bg.body.shadow.width = 0;
@@ -721,12 +737,12 @@ static void tabview_init(void)
rel.text.font = _font;
lv_style_copy(&pr, &def);
- pr.body.main_color = COLOR_HOS_BG_LIGHT;
+ pr.body.main_color = COLOR_BG_LIGHT;
pr.body.grad_color = pr.body.main_color;
pr.body.border.width = 0;
pr.body.empty = 0;
pr.body.radius = 0;
- pr.body.border.color = LV_COLOR_HEX3(0x888);
+ pr.body.border.color = LV_COLOR_HEX(0x888888);
pr.body.border.part = LV_BORDER_BOTTOM;
pr.body.border.opa = LV_OPA_COVER;
pr.text.color = COLOR_HOS_TURQUOISE;
@@ -737,7 +753,7 @@ static void tabview_init(void)
tgl_rel.text.color = COLOR_HOS_TURQUOISE;
lv_style_copy(&tgl_pr, &def);
- tgl_pr.body.main_color = COLOR_HOS_BG_LIGHT;
+ tgl_pr.body.main_color = COLOR_BG_LIGHT;
tgl_pr.body.grad_color = tgl_pr.body.main_color;
tgl_pr.body.border.width = 0;
tgl_pr.body.empty = 0;
@@ -784,11 +800,11 @@ static void win_init(void)
static lv_style_t header, rel, pr;
lv_style_copy(&header, &def);
- header.body.main_color = COLOR_HOS_BG;
+ header.body.main_color = COLOR_BG;
header.body.grad_color = header.body.main_color;
header.body.radius = 0;
header.body.border.width = 0;
- header.body.border.color = LV_COLOR_HEX3(0xDDD);
+ header.body.border.color = LV_COLOR_HEX(0xDDDDDD);
header.body.border.part = LV_BORDER_BOTTOM;
header.body.border.opa = LV_OPA_COVER;
header.body.shadow.width = 0;
@@ -830,10 +846,11 @@ static void win_init(void)
* @param font pointer to a font (NULL to use the default)
* @return pointer to the initialized theme
*/
-lv_theme_t * lv_theme_hekate_init(uint16_t hue, lv_font_t * font)
+lv_theme_t * lv_theme_hekate_init(uint32_t bg_color, uint16_t hue, lv_font_t * font)
{
if(font == NULL) font = LV_FONT_DEFAULT;
+ theme_bg_color = bg_color;
_hue = hue;
_font = font;
diff --git a/nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme_hekate.h b/bdk/libs/lvgl/lv_themes/lv_theme_hekate.h
similarity index 75%
rename from nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme_hekate.h
rename to bdk/libs/lvgl/lv_themes/lv_theme_hekate.h
index 0f906ea..45448b9 100644
--- a/nyx/nyx_gui/libs/lvgl/lv_themes/lv_theme_hekate.h
+++ b/bdk/libs/lvgl/lv_themes/lv_theme_hekate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019 CTCaer
+ * Copyright (c) 2018-2022 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,
@@ -14,8 +14,8 @@
* along with this program. If not, see .
*/
-#ifndef LV_THEME_MATERIAL_H
-#define LV_THEME_MATERIAL_H
+#ifndef LV_THEME_HEKATE_H
+#define LV_THEME_HEKATE_H
#ifdef __cplusplus
extern "C" {
@@ -35,6 +35,14 @@ extern "C" {
/*********************
* DEFINES
*********************/
+#define COLOR_HOS_BG_BASE_DEFAULT 0x1B1B1B
+#define COLOR_HOS_BG_BASE_BLACK 0x000000
+
+#define COLOR_HOS_BG_DARKER 0x1B1B1B
+#define COLOR_HOS_BG_DARK 0x222222
+#define COLOR_HOS_BG 0x2D2D2D
+#define COLOR_HOS_BG_LIGHT 0x3D3D3D
+#define COLOR_HOS_LIGHT_BORDER 0x4D4D4D
/**********************
* TYPEDEFS
@@ -44,13 +52,15 @@ extern "C" {
* GLOBAL PROTOTYPES
**********************/
+extern uint32_t theme_bg_color;
+
/**
* Initialize the material theme
* @param hue [0..360] hue value from HSV color space to define the theme's base color
* @param font pointer to a font (NULL to use the default)
* @return pointer to the initialized theme
*/
-lv_theme_t * lv_theme_hekate_init(uint16_t hue, lv_font_t *font);
+lv_theme_t * lv_theme_hekate_init(uint32_t bg_color, uint16_t hue, lv_font_t *font);
/**
* Get a pointer to the theme
diff --git a/nyx/nyx_gui/libs/lvgl/lv_themes/lv_themes.mk b/bdk/libs/lvgl/lv_themes/lv_themes.mk
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_themes/lv_themes.mk
rename to bdk/libs/lvgl/lv_themes/lv_themes.mk
diff --git a/nyx/nyx_gui/libs/lvgl/lv_version.h b/bdk/libs/lvgl/lv_version.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lv_version.h
rename to bdk/libs/lvgl/lv_version.h
diff --git a/nyx/nyx_gui/libs/lvgl/lvgl.h b/bdk/libs/lvgl/lvgl.h
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lvgl.h
rename to bdk/libs/lvgl/lvgl.h
diff --git a/nyx/nyx_gui/libs/lvgl/lvgl.mk b/bdk/libs/lvgl/lvgl.mk
similarity index 100%
rename from nyx/nyx_gui/libs/lvgl/lvgl.mk
rename to bdk/libs/lvgl/lvgl.mk
diff --git a/nyx/nyx_gui/mem/emc.h b/bdk/mem/emc.h
similarity index 94%
rename from nyx/nyx_gui/mem/emc.h
rename to bdk/mem/emc.h
index bfce612..a1b4c3a 100644
--- a/nyx/nyx_gui/mem/emc.h
+++ b/bdk/mem/emc.h
@@ -2,6 +2,7 @@
* arch/arm/mach-tegra/tegra21_emc.h
*
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2019-2024, 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
@@ -22,6 +23,7 @@
#ifndef _EMC_H_
#define _EMC_H_
+#define EMC_INTSTATUS 0x0
#define EMC_DBG 0x8
#define EMC_CFG 0xC
#define EMC_CONFIG_SAMPLE_DELAY 0x5f0
@@ -71,6 +73,7 @@
#define EMC_PDEX2MRR 0xb4
#define EMC_ODT_WRITE 0xb0
#define EMC_WEXT 0xb8
+#define EMC_CTT 0xBC
#define EMC_RFC_SLR 0xc0
#define EMC_MRS_WAIT_CNT2 0xc4
#define EMC_MRS_WAIT_CNT 0xc8
@@ -85,8 +88,13 @@
#define EMC_MRR 0xec
#define EMC_CMDQ 0xf0
#define EMC_MC2EMCQ 0xf4
+#define EMC_FBIO_TWTM 0xF8
+#define EMC_FBIO_TRATM 0xFC
+#define EMC_FBIO_TWATM 0x108
+#define EMC_FBIO_TR2REF 0x10C
#define EMC_FBIO_SPARE 0x100
#define EMC_FBIO_CFG5 0x104
+#define EMC_FBIO_CFG6 0x114
#define EMC_CFG_RSV 0x120
#define EMC_ACPD_CONTROL 0x124
#define EMC_MPC 0x128
@@ -210,6 +218,7 @@
#define EMC_AUTO_CAL_CONFIG6 0x5cc
#define EMC_AUTO_CAL_CONFIG7 0x574
#define EMC_AUTO_CAL_CONFIG8 0x2dc
+#define EMC_AUTO_CAL_CONFIG9 0x42C
#define EMC_AUTO_CAL_VREF_SEL_0 0x2f8
#define EMC_AUTO_CAL_VREF_SEL_1 0x300
#define EMC_AUTO_CAL_INTERVAL 0x2a8
@@ -231,6 +240,7 @@
#define EMC_COMP_PAD_SW_CTRL 0x57c
#define EMC_REQ_CTRL 0x2b0
#define EMC_EMC_STATUS 0x2b4
+#define EMC_STATUS_MRR_DIVLD BIT(20)
#define EMC_CFG_2 0x2b8
#define EMC_CFG_DIG_DLL 0x2bc
#define EMC_CFG_DIG_DLL_PERIOD 0x2c0
@@ -384,6 +394,8 @@
#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4
#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8
#define EMC_TRAINING_DRAMC_TIMING 0xedc
+#define EMC_PMACRO_DATA_PI_CTRL 0x110
+#define EMC_PMACRO_CMD_PI_CTRL 0x114
#define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600
#define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604
#define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608
@@ -648,6 +660,7 @@
#define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60
#define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64
#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68
+#define EMC_PMACRO_DSR_VTTGEN_CTRL0 0xC6C
#define EMC_PMACRO_BRICK_MAPPING_0 0xc80
#define EMC_PMACRO_BRICK_MAPPING_1 0xc84
#define EMC_PMACRO_BRICK_MAPPING_2 0xc88
@@ -660,8 +673,61 @@
#define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c
#define EMC_PMACRO_TRAINING_CTRL_0 0xcf8
#define EMC_PMACRO_TRAINING_CTRL_1 0xcfc
+#define EMC_PMACRO_PERBIT_FGCG_CTRL_0 0xD40
+#define EMC_PMACRO_PERBIT_FGCG_CTRL_1 0xD44
+#define EMC_PMACRO_PERBIT_FGCG_CTRL_2 0xD48
+#define EMC_PMACRO_PERBIT_FGCG_CTRL_3 0xD4C
+#define EMC_PMACRO_PERBIT_FGCG_CTRL_4 0xD50
+#define EMC_PMACRO_PERBIT_FGCG_CTRL_5 0xD54
+#define EMC_PMACRO_PERBIT_RFU_CTRL_0 0xD60
+#define EMC_PMACRO_PERBIT_RFU_CTRL_1 0xD64
+#define EMC_PMACRO_PERBIT_RFU_CTRL_2 0xD68
+#define EMC_PMACRO_PERBIT_RFU_CTRL_3 0xD6C
+#define EMC_PMACRO_PERBIT_RFU_CTRL_4 0xD70
+#define EMC_PMACRO_PERBIT_RFU_CTRL_5 0xD74
+#define EMC_PMACRO_PERBIT_RFU1_CTRL_0 0xD80
+#define EMC_PMACRO_PERBIT_RFU1_CTRL_1 0xD84
+#define EMC_PMACRO_PERBIT_RFU1_CTRL_2 0xD88
+#define EMC_PMACRO_PERBIT_RFU1_CTRL_3 0xD8C
+#define EMC_PMACRO_PERBIT_RFU1_CTRL_4 0xD90
+#define EMC_PMACRO_PERBIT_RFU1_CTRL_5 0xD94
#define EMC_PMC_SCRATCH1 0x440
#define EMC_PMC_SCRATCH2 0x444
#define EMC_PMC_SCRATCH3 0x448
+#define EMC_STATUS_UPDATE_TIMEOUT 1000
+
+typedef enum _emc_mr_t
+{
+ MR0_FEAT = 0,
+ MR4_TEMP = 4,
+ 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_chip_data_t
+{
+ // Device 0.
+ u8 rank0_ch0;
+ u8 rank0_ch1;
+
+ // Device 1.
+ u8 rank1_ch0;
+ u8 rank1_ch1;
+} emc_mr_chip_data_t;
+
+typedef struct _emc_mr_data_t
+{
+ emc_mr_chip_data_t chip0;
+ emc_mr_chip_data_t chip1;
+} emc_mr_data_t;
+
#endif
diff --git a/bootloader/mem/heap.c b/bdk/mem/heap.c
similarity index 66%
rename from bootloader/mem/heap.c
rename to bdk/mem/heap.c
index 833c2d3..ad70729 100644
--- a/bootloader/mem/heap.c
+++ b/bdk/mem/heap.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
- * Copyright (c) 2018 M4xw
+ * Copyright (c) 2018-2024 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,
@@ -17,36 +17,46 @@
#include
#include "heap.h"
-#include "../gfx/gfx.h"
-#include "../../common/common_heap.h"
+#include
-static void _heap_create(heap_t *heap, u32 start)
+heap_t _heap;
+
+static void _heap_create(void *start)
{
- heap->start = start;
- heap->first = NULL;
+ _heap.start = start;
+ _heap.first = NULL;
+ _heap.last = NULL;
}
// Node info is before node address.
-static u32 _heap_alloc(heap_t *heap, u32 size)
+static void *_heap_alloc(u32 size)
{
hnode_t *node, *new_node;
// Align to cache line size.
size = ALIGN(size, sizeof(hnode_t));
- if (!heap->first)
+ // First allocation.
+ if (!_heap.first)
{
- node = (hnode_t *)heap->start;
+ 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);
+ _heap.first = node;
+ _heap.last = node;
+
+ return (void *)node + sizeof(hnode_t);
}
- node = heap->first;
+#ifdef BDK_MALLOC_NO_DEFRAG
+ // Get the last allocated block.
+ node = _heap.last;
+#else
+ // Get first block and find the first available one.
+ node = _heap.first;
while (true)
{
// Check if there's available unused node.
@@ -54,7 +64,7 @@ static u32 _heap_alloc(heap_t *heap, u32 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);
+ new_node = (hnode_t *)((void *)node + sizeof(hnode_t) + size);
// If there's aligned unused space from the old node,
// create a new one and set the leftover size.
@@ -77,7 +87,7 @@ static u32 _heap_alloc(heap_t *heap, u32 size)
node->size = size;
node->used = 1;
- return (u32)node + sizeof(hnode_t);
+ return (void *)node + sizeof(hnode_t);
}
// No unused node found, try the next one.
@@ -86,23 +96,29 @@ static u32 _heap_alloc(heap_t *heap, u32 size)
else
break;
}
+#endif
// No unused node found, create a new one.
- new_node = (hnode_t *)((u32)node + sizeof(hnode_t) + node->size);
+ new_node = (hnode_t *)((void *)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);
+ node->next = new_node;
+ _heap.last = new_node;
+
+ return (void *)new_node + sizeof(hnode_t);
}
-static void _heap_free(heap_t *heap, u32 addr)
+static void _heap_free(void *addr)
{
hnode_t *node = (hnode_t *)(addr - sizeof(hnode_t));
node->used = 0;
- node = heap->first;
+ node = _heap.first;
+
+#ifndef BDK_MALLOC_NO_DEFRAG
+ // Do simple defragmentation on next blocks.
while (node)
{
if (!node->used)
@@ -118,31 +134,42 @@ static void _heap_free(heap_t *heap, u32 addr)
}
node = node->next;
}
+#endif
}
-heap_t _heap;
-
-void heap_init(u32 base)
+void heap_init(void *base)
{
- _heap_create(&_heap, base);
+ _heap_create(base);
+}
+
+void heap_set(heap_t *heap)
+{
+ memcpy(&_heap, heap, sizeof(heap_t));
}
void *malloc(u32 size)
{
- return (void *)_heap_alloc(&_heap, size);
+ return _heap_alloc(size);
}
void *calloc(u32 num, u32 size)
{
- void *res = (void *)_heap_alloc(&_heap, num * size);
- memset(res, 0, num * size);
+ void *res = (void *)_heap_alloc(num * size);
+ memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size.
+ return res;
+}
+
+void *zalloc(u32 size)
+{
+ void *res = (void *)_heap_alloc(size);
+ memset(res, 0, ALIGN(size, sizeof(hnode_t))); // Clear the aligned size.
return res;
}
void free(void *buf)
{
- if ((u32)buf >= _heap.start)
- _heap_free(&_heap, (u32)buf);
+ if (buf >= _heap.start)
+ _heap_free(buf);
}
void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
@@ -154,7 +181,10 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
while (true)
{
if (node->used)
+ {
+ mon->nodes_used++;
mon->used += node->size + sizeof(hnode_t);
+ }
else
mon->total += node->size + sizeof(hnode_t);
@@ -163,11 +193,12 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
count, node->used, (u32)node + sizeof(hnode_t), node->size);
count++;
-
+
if (node->next)
node = node->next;
else
break;
}
mon->total += mon->used;
+ mon->nodes_total = count;
}
diff --git a/common/common_heap.h b/bdk/mem/heap.h
similarity index 67%
rename from common/common_heap.h
rename to bdk/mem/heap.h
index 110f013..c898ee0 100644
--- a/common/common_heap.h
+++ b/bdk/mem/heap.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
- * Copyright (c) 2018 M4xw
+ * Copyright (c) 2018-2024 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,
@@ -13,11 +13,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*/
+ */
-#pragma once
-//TODO: Move it to BDK
-#include "../bootloader/utils/types.h"
+#ifndef _HEAP_H_
+#define _HEAP_H_
+
+#include
typedef struct _hnode
{
@@ -30,12 +31,25 @@ typedef struct _hnode
typedef struct _heap
{
- u32 start;
+ void *start;
hnode_t *first;
+ hnode_t *last;
} heap_t;
typedef struct
{
- u32 total;
- u32 used;
+ u32 total;
+ u32 used;
+ u32 nodes_total;
+ u32 nodes_used;
} heap_monitor_t;
+
+void heap_init(void *base);
+void heap_set(heap_t *heap);
+void *malloc(u32 size);
+void *calloc(u32 num, u32 size);
+void *zalloc(u32 size);
+void free(void *buf);
+void heap_monitor(heap_monitor_t *mon, bool print_node_stats);
+
+#endif
diff --git a/bdk/mem/mc.c b/bdk/mem/mc.c
new file mode 100644
index 0000000..4e6ede6
--- /dev/null
+++ b/bdk/mem/mc.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2018-2024 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+void mc_config_tzdram_carveout(u32 bom, u32 size1mb, bool lock)
+{
+ MC(MC_SEC_CARVEOUT_BOM) = bom;
+ MC(MC_SEC_CARVEOUT_SIZE_MB) = size1mb;
+ if (lock)
+ MC(MC_SEC_CARVEOUT_REG_CTRL) = 1;
+}
+
+void mc_config_carveout()
+{
+ // Enable ACR GSR3.
+ *(vu32 *)0x8005FFFC = 0xC0EDBBCC;
+ MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1;
+ MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0;
+ MC(MC_VIDEO_PROTECT_BOM) = 0;
+ MC(MC_VIDEO_PROTECT_REG_CTRL) = VPR_CTRL_LOCKED;
+
+ // Configure TZDRAM carveout @ 0x90000000, 1MB.
+ //mc_config_tzdram_carveout(0x90000000, 1, false);
+ mc_config_tzdram_carveout(0, 0, true);
+
+ MC(MC_MTS_CARVEOUT_BOM) = 0;
+ MC(MC_MTS_CARVEOUT_REG_CTRL) = 1;
+
+ MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0;
+ MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0;
+ MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0;
+ MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
+ SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
+ SEC_CARVEOUT_CFG_APERTURE_ID(0) |
+ SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH;
+
+ MC(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000;
+ MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU | SEC_CARVEOUT_CA2_R_TSEC;
+
+ MC(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0;
+ MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = 0;
+ MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = 0;
+ MC(MC_SECURITY_CARVEOUT4_CFG0) = SEC_CARVEOUT_CFG_TZ_SECURE |
+ SEC_CARVEOUT_CFG_LOCKED |
+ SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
+ SEC_CARVEOUT_CFG_RD_NS |
+ SEC_CARVEOUT_CFG_WR_NS;
+
+ MC(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0;
+ MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = 0;
+ MC(MC_SECURITY_CARVEOUT5_CFG0) = SEC_CARVEOUT_CFG_TZ_SECURE |
+ SEC_CARVEOUT_CFG_LOCKED |
+ SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
+ SEC_CARVEOUT_CFG_RD_NS |
+ SEC_CARVEOUT_CFG_WR_NS;
+}
+
+void mc_enable_ahb_redirect()
+{
+ // Enable ARC_CLK_OVR_ON.
+ CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) |= BIT(19);
+ //MC(MC_IRAM_REG_CTRL) &= ~BIT(0);
+ MC(MC_IRAM_BOM) = IRAM_BASE;
+ MC(MC_IRAM_TOM) = DRAM_START; // Default is only IRAM: 0x4003F000.
+}
+
+void mc_disable_ahb_redirect()
+{
+ MC(MC_IRAM_BOM) = 0xFFFFF000;
+ MC(MC_IRAM_TOM) = 0;
+ // Disable IRAM_CFG_WRITE_ACCESS (sticky).
+ //MC(MC_IRAM_REG_CTRL) |= BIT(0);
+ // Disable ARC_CLK_OVR_ON.
+ CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) &= ~BIT(19);
+}
+
+bool mc_client_has_access(void *address)
+{
+ // Check if address is in DRAM or if arbitration for IRAM is enabled.
+ if ((u32)address >= DRAM_START)
+ return true; // Access by default.
+ else if ((u32)address >= IRAM_BASE && MC(MC_IRAM_BOM) == IRAM_BASE)
+ return true; // Access by AHB arbitration.
+
+ // No access to address space.
+ return false;
+}
+
+void mc_enable()
+{
+ // Reset EMC source to PLLP.
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | (2 << 29u);
+ // Enable and clear reset for memory clocks.
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
+ CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
+ usleep(5);
+
+#ifdef BDK_MC_ENABLE_AHB_REDIRECT
+ mc_enable_ahb_redirect();
+#else
+ mc_disable_ahb_redirect();
+#endif
+}
diff --git a/bootloader/soc/hw_init.h b/bdk/mem/mc.h
similarity index 66%
rename from bootloader/soc/hw_init.h
rename to bdk/mem/mc.h
index b92814b..300bbfd 100644
--- a/bootloader/soc/hw_init.h
+++ b/bdk/mem/mc.h
@@ -1,6 +1,5 @@
/*
* 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,
@@ -15,12 +14,18 @@
* along with this program. If not, see .
*/
-#ifndef _HW_INIT_H_
-#define _HW_INIT_H_
+#ifndef _MC_H_
+#define _MC_H_
-#include "../utils/types.h"
+#include
+#include
-void config_hw();
-void reconfig_hw_workaround(bool extra_reconfig, u32 magic);
+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();
+bool mc_client_has_access(void *address);
+void mc_enable();
#endif
diff --git a/bootloader/mem/mc_t210.h b/bdk/mem/mc_t210.h
similarity index 81%
rename from bootloader/mem/mc_t210.h
rename to bdk/mem/mc_t210.h
index 602915f..ff96b9d 100644
--- a/bootloader/mem/mc_t210.h
+++ b/bdk/mem/mc_t210.h
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2014, NVIDIA Corporation.
+ * Copyright (c) 2018-2023, CTCaer
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -14,6 +15,22 @@
#ifndef _MC_T210_H_
#define _MC_T210_H_
+/*! MC SMMU registers */
+#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_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
+
+/*! MC General registers */
#define MC_INTSTATUS 0x0
#define MC_INTMASK 0x4
#define MC_ERR_STATUS 0x8
@@ -461,6 +478,158 @@
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08
#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
+#define MC_UNTRANSLATED_REGION_CHECK 0x948
#define MC_DA_CONFIG0 0x9dc
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS0 */
+#define SEC_CARVEOUT_CA0_R_PTCR BIT(0)
+#define SEC_CARVEOUT_CA0_R_DISPLAY0A BIT(1)
+#define SEC_CARVEOUT_CA0_R_DISPLAY0AB BIT(2)
+#define SEC_CARVEOUT_CA0_R_DISPLAY0B BIT(3)
+#define SEC_CARVEOUT_CA0_R_DISPLAY0BB BIT(4)
+#define SEC_CARVEOUT_CA0_R_DISPLAY0C BIT(5)
+#define SEC_CARVEOUT_CA0_R_DISPLAY0CB BIT(6)
+#define SEC_CARVEOUT_CA0_R_AFI BIT(14)
+#define SEC_CARVEOUT_CA0_R_BPMP_C BIT(15)
+#define SEC_CARVEOUT_CA0_R_DISPLAYHC BIT(16)
+#define SEC_CARVEOUT_CA0_R_DISPLAYHCB BIT(17)
+#define SEC_CARVEOUT_CA0_R_HDA BIT(21)
+#define SEC_CARVEOUT_CA0_R_HOST1XDMA BIT(22)
+#define SEC_CARVEOUT_CA0_R_HOST1X BIT(23)
+#define SEC_CARVEOUT_CA0_R_NVENC BIT(28)
+#define SEC_CARVEOUT_CA0_R_PPCSAHBDMA BIT(29)
+#define SEC_CARVEOUT_CA0_R_PPCSAHBSLV BIT(30)
+#define SEC_CARVEOUT_CA0_R_SATAR BIT(31)
+
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS1 */
+#define SEC_CARVEOUT_CA1_R_VDEBSEV BIT(2)
+#define SEC_CARVEOUT_CA1_R_VDEMBE BIT(3)
+#define SEC_CARVEOUT_CA1_R_VDEMCE BIT(4)
+#define SEC_CARVEOUT_CA1_R_VDETPE BIT(5)
+#define SEC_CARVEOUT_CA1_R_CCPLEXLP_C BIT(6)
+#define SEC_CARVEOUT_CA1_R_CCPLEX_C BIT(7)
+#define SEC_CARVEOUT_CA1_W_NVENC BIT(11)
+#define SEC_CARVEOUT_CA1_W_AFI BIT(17)
+#define SEC_CARVEOUT_CA1_W_BPMP_C BIT(18)
+#define SEC_CARVEOUT_CA1_W_HDA BIT(21)
+#define SEC_CARVEOUT_CA1_W_HOST1X BIT(22)
+#define SEC_CARVEOUT_CA1_W_CCPLEXLP_C BIT(24)
+#define SEC_CARVEOUT_CA1_W_CCPLEX_C BIT(25)
+#define SEC_CARVEOUT_CA1_W_PPCSAHBDMA BIT(27)
+#define SEC_CARVEOUT_CA1_W_PPCSAHBSLV BIT(28)
+#define SEC_CARVEOUT_CA1_W_SATA BIT(29)
+#define SEC_CARVEOUT_CA1_W_VDEBSEV BIT(30)
+#define SEC_CARVEOUT_CA1_W_VDEDBG BIT(31)
+
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS2 */
+#define SEC_CARVEOUT_CA2_W_VDEMBE BIT(0)
+#define SEC_CARVEOUT_CA2_W_VDETPM BIT(1)
+#define SEC_CARVEOUT_CA2_R_ISPRA BIT(4)
+#define SEC_CARVEOUT_CA2_W_ISPWA BIT(6)
+#define SEC_CARVEOUT_CA2_W_ISPWB BIT(7)
+#define SEC_CARVEOUT_CA2_R_XUSB_HOST BIT(10)
+#define SEC_CARVEOUT_CA2_W_XUSB_HOST BIT(11)
+#define SEC_CARVEOUT_CA2_R_XUSB_DEV BIT(12)
+#define SEC_CARVEOUT_CA2_W_XUSB_DEV BIT(13)
+#define SEC_CARVEOUT_CA2_R_SE2 BIT(14)
+#define SEC_CARVEOUT_CA2_W_SE2 BIT(16)
+#define SEC_CARVEOUT_CA2_R_TSEC BIT(20)
+#define SEC_CARVEOUT_CA2_W_TSEC BIT(21)
+#define SEC_CARVEOUT_CA2_R_ADSP_SC BIT(22)
+#define SEC_CARVEOUT_CA2_W_ADSP_SC BIT(23)
+#define SEC_CARVEOUT_CA2_R_GPU BIT(24)
+#define SEC_CARVEOUT_CA2_W_GPU BIT(25)
+#define SEC_CARVEOUT_CA2_R_DISPLAYT BIT(26)
+
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS3 */
+#define SEC_CARVEOUT_CA3_R_SDMMCA BIT(0)
+#define SEC_CARVEOUT_CA3_R_SDMMCAA BIT(1)
+#define SEC_CARVEOUT_CA3_R_SDMMC BIT(2)
+#define SEC_CARVEOUT_CA3_R_SDMMCAB BIT(3)
+#define SEC_CARVEOUT_CA3_W_SDMMCA BIT(4)
+#define SEC_CARVEOUT_CA3_W_SDMMCAA BIT(5)
+#define SEC_CARVEOUT_CA3_W_SDMMC BIT(6)
+#define SEC_CARVEOUT_CA3_W_SDMMCAB BIT(7)
+#define SEC_CARVEOUT_CA3_R_VIC BIT(12)
+#define SEC_CARVEOUT_CA3_W_VIC BIT(13)
+#define SEC_CARVEOUT_CA3_W_VIW BIT(18)
+#define SEC_CARVEOUT_CA3_R_DISPLAYD BIT(19)
+#define SEC_CARVEOUT_CA3_R_NVDEC BIT(24)
+#define SEC_CARVEOUT_CA3_W_NVDEC BIT(25)
+#define SEC_CARVEOUT_CA3_R_APE BIT(26)
+#define SEC_CARVEOUT_CA3_W_APE BIT(27)
+#define SEC_CARVEOUT_CA3_R_NVJPG BIT(30)
+#define SEC_CARVEOUT_CA3_W_NVJPG BIT(31)
+
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS4 */
+#define SEC_CARVEOUT_CA4_R_SE BIT(0)
+#define SEC_CARVEOUT_CA4_W_SE BIT(1)
+#define SEC_CARVEOUT_CA4_R_AXIAP BIT(2)
+#define SEC_CARVEOUT_CA4_W_AXIAP BIT(3)
+#define SEC_CARVEOUT_CA4_R_ETR BIT(4)
+#define SEC_CARVEOUT_CA4_W_ETR BIT(5)
+#define SEC_CARVEOUT_CA4_R_TSECB BIT(6)
+#define SEC_CARVEOUT_CA4_W_TSECB BIT(7)
+#define SEC_CARVEOUT_CA4_R_GPU2 BIT(8)
+#define SEC_CARVEOUT_CA4_W_GPU2 BIT(9)
+
+// MC_VIDEO_PROTECT_REG_CTRL
+#define VPR_LOCK_MODE_SHIFT 0
+#define VPR_CTRL_UNLOCKED (0 << VPR_LOCK_MODE_SHIFT)
+#define VPR_CTRL_LOCKED (1 << VPR_LOCK_MODE_SHIFT)
+#define VPR_PROTECT_MODE_SHIFT 1
+#define SEC_CTRL_SECURE (0 << VPR_PROTECT_MODE_SHIFT)
+#define VPR_CTRL_TZ_SECURE (1 << VPR_PROTECT_MODE_SHIFT)
+
+// MC_SECURITY_CARVEOUTX_CFG0
+// Mode of LOCK_MODE.
+#define PROTECT_MODE_SHIFT 0
+#define SEC_CARVEOUT_CFG_ALL_SECURE (0 << PROTECT_MODE_SHIFT)
+#define SEC_CARVEOUT_CFG_TZ_SECURE (1 << PROTECT_MODE_SHIFT)
+// 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_NS (1 << READ_ACCESS_LEVEL_SHIFT)
+#define SEC_CARVEOUT_CFG_RD_SEC (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_NS (1 << WRITE_ACCESS_LEVEL_SHIFT)
+#define SEC_CARVEOUT_CFG_WR_SEC (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 SEC_CARVEOUT_CFG_APERTURE_ID(id) ((id) << 11)
+
+#define DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT 14
+#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_NS (1 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
+#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_SEC (2 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
+#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_FLCN_LS (4 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
+#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_FLCN_HS (8 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
+
+#define DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT 18
+#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_NS (1 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
+#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_SEC (2 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
+#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_FLCN_LS (4 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
+#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_FLCN_HS (8 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
+
+#define SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU BIT(22)
+
+#define SEC_CARVEOUT_CFG_TZ_GLOBAL_WR_EN_BYPASS_CHECK BIT(23)
+#define SEC_CARVEOUT_CFG_TZ_GLOBAL_RD_EN_BYPASS_CHECK BIT(24)
+
+#define SEC_CARVEOUT_CFG_ALLOW_APERTURE_ID_MISMATCH BIT(25)
+#define SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH BIT(26)
+
+#define SEC_CARVEOUT_CFG_IS_WPR BIT(27)
+
#endif
diff --git a/bdk/mem/minerva.c b/bdk/mem/minerva.c
new file mode 100644
index 0000000..3fd05e4
--- /dev/null
+++ b/bdk/mem/minerva.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2019-2024 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 .
+ */
+
+#include
+#include
+
+#include "minerva.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define TABLE_FREQ_KHZ_OFFSET 0x40
+#define TABLE_LA_REGS_T210_OFFSET 0x1284
+#define TABLE_LA_REGS_T210B01_OFFSET 0xFA4
+#define LA_SDMMC1_INDEX 6
+
+extern volatile nyx_storage_t *nyx_str;
+
+void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
+
+u32 minerva_init()
+{
+ u32 tbl_idx = 0;
+
+ minerva_cfg = NULL;
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+
+ //!TODO: Not supported on T210B01 yet.
+ if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
+ return 0;
+
+#ifdef BDK_MINERVA_CFG_FROM_RAM
+ // Set table to nyx storage.
+ mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
+
+ // Check if Minerva is already initialized.
+ if (mtc_cfg->init_done == MTC_INIT_MAGIC)
+ {
+ mtc_cfg->train_mode = OP_PERIODIC_TRAIN; // Retrain if needed.
+ u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
+ minerva_cfg = (void *)ep_addr;
+
+ return !minerva_cfg ? 1 : 0;
+ }
+ else
+ {
+ mtc_config_t mtc_tmp;
+
+ mtc_tmp.mtc_table = mtc_cfg->mtc_table;
+ mtc_tmp.sdram_id = fuse_read_dramid(false);
+ mtc_tmp.init_done = MTC_NEW_MAGIC;
+
+ u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp);
+
+ // Ensure that Minerva is new.
+ if (mtc_tmp.init_done == MTC_INIT_MAGIC)
+ minerva_cfg = (void *)ep_addr;
+ else
+ mtc_cfg->init_done = 0;
+
+ // Copy Minerva context to Nyx storage.
+ if (minerva_cfg)
+ memcpy(mtc_cfg, (void *)&mtc_tmp, sizeof(mtc_config_t));
+ }
+#else
+ memset(mtc_cfg, 0, sizeof(mtc_config_t));
+
+ // Set table to nyx storage.
+ mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
+
+ mtc_cfg->sdram_id = fuse_read_dramid(false);
+ mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
+
+ u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
+
+ // Ensure that Minerva is new.
+ if (mtc_cfg->init_done == MTC_INIT_MAGIC)
+ minerva_cfg = (void *)ep_addr;
+ else
+ mtc_cfg->init_done = 0;
+#endif
+
+ if (!minerva_cfg)
+ return 1;
+
+ // Get current frequency
+ u32 current_emc_clk_src = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC);
+ for (tbl_idx = 0; tbl_idx < mtc_cfg->table_entries; tbl_idx++)
+ {
+ if (current_emc_clk_src == mtc_cfg->mtc_table[tbl_idx].clk_src_emc)
+ break;
+ }
+
+ mtc_cfg->rate_from = mtc_cfg->mtc_table[tbl_idx].rate_khz;
+ mtc_cfg->rate_to = FREQ_204;
+ mtc_cfg->train_mode = OP_TRAIN;
+ minerva_cfg(mtc_cfg, NULL);
+ mtc_cfg->rate_to = FREQ_800;
+ minerva_cfg(mtc_cfg, NULL);
+ mtc_cfg->rate_to = FREQ_1600;
+ minerva_cfg(mtc_cfg, NULL);
+
+ // FSP WAR.
+ mtc_cfg->train_mode = OP_SWITCH;
+ mtc_cfg->rate_to = FREQ_800;
+ minerva_cfg(mtc_cfg, NULL);
+
+ // Switch to max.
+ mtc_cfg->rate_to = FREQ_1600;
+ minerva_cfg(mtc_cfg, NULL);
+
+ return 0;
+}
+
+void minerva_change_freq(minerva_freq_t freq)
+{
+ if (!minerva_cfg)
+ return;
+
+ // Check if requested frequency is different. Do not allow otherwise because it will hang.
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+ if (mtc_cfg->rate_from != freq)
+ {
+ mtc_cfg->rate_to = freq;
+ mtc_cfg->train_mode = OP_SWITCH;
+ minerva_cfg(mtc_cfg, NULL);
+ }
+}
+
+void minerva_sdmmc_la_program(void *table, bool t210b01)
+{
+
+ u32 freq = *(u32 *)(table + TABLE_FREQ_KHZ_OFFSET);
+ u32 *la_scale_regs = (u32 *)(table + (t210b01 ? TABLE_LA_REGS_T210B01_OFFSET : TABLE_LA_REGS_T210_OFFSET));
+
+ // Adjust SDMMC1 latency allowance.
+ switch (freq)
+ {
+ case 204000:
+ la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 50;
+ break;
+ case 408000:
+ la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 25;
+ break;
+ default:
+ la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 20;
+ break;
+ }
+}
+
+void minerva_prep_boot_freq()
+{
+ if (!minerva_cfg)
+ return;
+
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+
+ // Check if there's RAM OC. If not exit.
+ if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
+ return;
+
+ // FSP WAR.
+ minerva_change_freq(FREQ_204);
+ // Scale down to 800 MHz boot freq.
+ minerva_change_freq(FREQ_800);
+}
+
+void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom)
+{
+ if (!minerva_cfg)
+ return;
+
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+
+ // Program SDMMC LA regs.
+ for (u32 i = 0; i < mtc_cfg->table_entries; i++)
+ minerva_sdmmc_la_program(&mtc_cfg->mtc_table[i], false);
+
+ // Add OC frequency.
+ if (oc_freq && mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
+ {
+ memcpy(&mtc_cfg->mtc_table[mtc_cfg->table_entries],
+ &mtc_cfg->mtc_table[mtc_cfg->table_entries - 1],
+ sizeof(emc_table_t));
+
+ mtc_cfg->mtc_table[mtc_cfg->table_entries].opt_custom = opt_custom;
+ mtc_cfg->mtc_table[mtc_cfg->table_entries].rate_khz = oc_freq;
+ mtc_cfg->table_entries++;
+ }
+
+ // Trim table.
+ int entries = 0;
+ for (u32 i = 0; i < mtc_cfg->table_entries; i++)
+ {
+ // Copy frequencies from 204/408/800 MHz and 1333+ MHz.
+ int rate = mtc_cfg->mtc_table[i].rate_khz;
+ if (rate == FREQ_204 ||
+ rate == FREQ_408 ||
+ rate == FREQ_800 ||
+ rate >= FREQ_1333)
+ {
+ memcpy(&mtc_cfg->mtc_table[entries], &mtc_cfg->mtc_table[i], sizeof(emc_table_t));
+ entries++;
+ }
+ }
+ mtc_cfg->table_entries = entries;
+
+ // Set init frequency.
+ minerva_change_freq(FREQ_204);
+
+ // Train the rest of the frequencies.
+ mtc_cfg->train_mode = OP_TRAIN;
+ for (u32 i = 0; i < mtc_cfg->table_entries; i++)
+ {
+ // Skip already trained frequencies and OC freq (Arachne handles it).
+ if (mtc_cfg->mtc_table[i].trained || mtc_cfg->rate_to == oc_freq)
+ continue;
+
+ // Train frequency.
+ mtc_cfg->rate_to = mtc_cfg->mtc_table[i].rate_khz;
+ minerva_cfg(mtc_cfg, NULL);
+ }
+
+ // Do FSP WAR and scale to 800 MHz as boot freq.
+ bool fsp_opwr_disabled = !(EMC(EMC_MRW3) & 0xC0);
+ if (fsp_opwr_disabled)
+ minerva_change_freq(FREQ_1333);
+ minerva_change_freq(FREQ_800);
+
+ // Do not let other mtc ops.
+ mtc_cfg->init_done = 0;
+}
+
+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);
+ }
+}
+
+emc_table_t *minerva_get_mtc_table()
+{
+ if (!minerva_cfg)
+ return NULL;
+
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+ return mtc_cfg->mtc_table;
+}
+
+int minerva_get_mtc_table_entries()
+{
+ if (!minerva_cfg)
+ return 0;
+
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+ return mtc_cfg->table_entries;
+}
diff --git a/bootloader/mem/minerva.h b/bdk/mem/minerva.h
similarity index 76%
rename from bootloader/mem/minerva.h
rename to bdk/mem/minerva.h
index 00228f4..e78bb41 100644
--- a/bootloader/mem/minerva.h
+++ b/bdk/mem/minerva.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 CTCaer
+ * Copyright (c) 2019-2022 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,
@@ -18,7 +18,7 @@
#define _FE_MINERVA_H_
#include "mtc_table.h"
-#include "../utils/types.h"
+#include
#define MTC_INIT_MAGIC 0x3043544D
#define MTC_NEW_MAGIC 0x5243544D
@@ -27,8 +27,8 @@
typedef struct
{
- s32 rate_to;
- s32 rate_from;
+ u32 rate_to;
+ u32 rate_from;
emc_table_t *mtc_table;
u32 table_entries;
emc_table_t *current_emc_table;
@@ -38,7 +38,7 @@ typedef struct
bool emc_2X_clk_src_is_pllmb;
bool fsp_for_src_freq;
bool train_ram_patterns;
- bool init_done;
+ u32 init_done;
} mtc_config_t;
enum train_mode_t
@@ -53,13 +53,20 @@ enum train_mode_t
typedef enum
{
FREQ_204 = 204000,
+ FREQ_408 = 408000,
FREQ_800 = 800000,
+ FREQ_1333 = 1331200,
FREQ_1600 = 1600000
} minerva_freq_t;
-void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
+extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init();
void minerva_change_freq(minerva_freq_t freq);
+void minerva_sdmmc_la_program(void *table, bool t210b01);
+void minerva_prep_boot_freq();
+void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom);
void minerva_periodic_training();
+emc_table_t *minerva_get_mtc_table();
+int minerva_get_mtc_table_entries();
#endif
diff --git a/nyx/nyx_gui/mem/mtc_table.h b/bdk/mem/mtc_table.h
similarity index 99%
rename from nyx/nyx_gui/mem/mtc_table.h
rename to bdk/mem/mtc_table.h
index 38a3e2f..7802280 100644
--- a/nyx/nyx_gui/mem/mtc_table.h
+++ b/bdk/mem/mtc_table.h
@@ -20,7 +20,7 @@
#ifndef _MTC_TABLE_H_
#define _MTC_TABLE_H_
-#include "../utils/types.h"
+#include
typedef struct
{
@@ -481,7 +481,8 @@ typedef struct
u32 rate_khz;
u32 min_volt;
u32 gpu_min_volt;
- char clock_src[32];
+ char clock_src[28];
+ u32 opt_custom;
u32 clk_src_emc;
u32 needs_training;
u32 training_pattern;
diff --git a/bdk/mem/sdram.c b/bdk/mem/sdram.c
new file mode 100644
index 0000000..4aa98fa
--- /dev/null
+++ b/bdk/mem/sdram.c
@@ -0,0 +1,1582 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2018 balika011
+ * Copyright (c) 2019-2023 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 .
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRAM_ID(x) BIT(x)
+#define DRAM_CC(x) BIT(x)
+
+typedef struct _sdram_vendor_patch_t
+{
+ u32 val;
+ u32 dramcf:16;
+ u32 offset:16;
+} sdram_vendor_patch_t;
+
+static const u8 dram_encoding_t210b01[] = {
+/* 00 */ LPDDR4X_UNUSED,
+/* 01 */ LPDDR4X_UNUSED,
+/* 02 */ LPDDR4X_UNUSED,
+/* 03 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE,
+/* 04 */ LPDDR4X_UNUSED,
+/* 05 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE,
+/* 06 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE,
+/* 07 */ LPDDR4X_UNUSED,
+/* 08 */ LPDDR4X_NO_PATCH,
+/* 09 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ,
+/* 10 */ LPDDR4X_NO_PATCH,
+/* 11 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE,
+/* 12 */ LPDDR4X_NO_PATCH,
+/* 13 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ,
+/* 14 */ LPDDR4X_NO_PATCH,
+/* 15 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE,
+/* 16 */ LPDDR4X_UNUSED,
+/* 17 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
+/* 18 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
+/* 19 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
+/* 20 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL,
+/* 21 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL,
+/* 22 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL,
+/* 23 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
+/* 24 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
+/* 25 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
+/* 26 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
+/* 27 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
+/* 28 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
+/* 29 */ LPDDR4X_4GB_HYNIX_H54G46CYRBX267,
+/* 30 */ LPDDR4X_4GB_HYNIX_H54G46CYRBX267,
+/* 31 */ LPDDR4X_4GB_HYNIX_H54G46CYRBX267,
+/* 32 */ LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB,
+/* 33 */ LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB,
+/* 34 */ LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB,
+};
+
+#include "sdram_config.inl"
+#include "sdram_config_t210b01.inl"
+
+static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel)
+{
+ bool err = true;
+
+ for (s32 i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; i++)
+ {
+ if (emc_channel)
+ {
+ if (emc_channel != 1)
+ goto done;
+
+ if (((EMC_CH1(reg_offset) & bit_mask) != 0) == updated_state)
+ {
+ err = false;
+ break;
+ }
+ }
+ else if (((EMC(reg_offset) & bit_mask) != 0) == updated_state)
+ {
+ err = false;
+ break;
+ }
+ usleep(1);
+ }
+
+done:
+ return err;
+}
+
+static void _sdram_req_mrr_data(u32 data, bool dual_channel)
+{
+ EMC(EMC_MRR) = data;
+ _sdram_wait_emc_status(EMC_EMC_STATUS, EMC_STATUS_MRR_DIVLD, true, EMC_CHAN0);
+ if (dual_channel)
+ _sdram_wait_emc_status(EMC_EMC_STATUS, EMC_STATUS_MRR_DIVLD, true, EMC_CHAN1);
+}
+
+emc_mr_data_t sdram_read_mrx(emc_mr_t mrx)
+{
+ emc_mr_data_t data;
+ u32 mrr;
+ bool dual_rank = EMC(EMC_ADR_CFG) & 1;
+ bool dual_channel = (EMC(EMC_FBIO_CFG7) >> 2) & 1; // Each EMC channel is a RAM chip module.
+
+ // Clear left overs.
+ for (u32 i = 0; i < 16; i++)
+ {
+ (void)EMC(EMC_MRR);
+ usleep(1);
+ }
+
+ memset(&data, 0xFF, sizeof(emc_mr_data_t));
+
+ /*
+ * When a dram chip has only one rank, then the info from the 2 ranks differs.
+ * Info not matching is only allowed on different channels.
+ */
+
+ // Get Device 0 (Rank 0) info from both dram chips (channels).
+ _sdram_req_mrr_data((2u << 30) | (mrx << 16), dual_channel);
+
+ // Ram module 0 info.
+ mrr = EMC_CH0(EMC_MRR);
+ data.chip0.rank0_ch0 = mrr & 0xFF;
+ data.chip0.rank0_ch1 = (mrr & 0xFF00 >> 8);
+
+ // Ram module 1 info.
+ if (dual_channel)
+ {
+ mrr = EMC_CH1(EMC_MRR);
+ data.chip1.rank0_ch0 = mrr & 0xFF;
+ data.chip1.rank0_ch1 = (mrr & 0xFF00 >> 8);
+ }
+
+ // If Rank 1 exists, get info.
+ if (dual_rank)
+ {
+ // Get Device 1 (Rank 1) info from both dram chips (channels).
+ _sdram_req_mrr_data((1u << 30) | (mrx << 16), dual_channel);
+
+ // Ram module 0 info.
+ mrr = EMC_CH0(EMC_MRR);
+ data.chip0.rank1_ch0 = mrr & 0xFF;
+ data.chip0.rank1_ch1 = (mrr & 0xFF00 >> 8);
+
+ // Ram module 1 info.
+ if (dual_channel)
+ {
+ mrr = EMC_CH1(EMC_MRR);
+ data.chip1.rank1_ch0 = mrr & 0xFF;
+ data.chip1.rank1_ch1 = (mrr & 0xFF00 >> 8);
+ }
+ }
+
+ return data;
+}
+
+void sdram_src_pllc(bool enable)
+{
+ static bool enabled = false;
+
+ if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210 || enable == enabled)
+ return;
+
+ enabled = enable;
+
+ // Clear CC interrupt.
+ EMC(EMC_INTSTATUS) = BIT(4);
+ (void)EMC(EMC_INTSTATUS);
+
+ u32 clk_src_emc = _dram_cfg_08_10_12_14_samsung_hynix_4gb.emc_clock_source;
+
+ if (enable)
+ {
+ // Check if clock source is not the expected one.
+ if (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) != clk_src_emc)
+ return;
+
+ // Set source as PLLC_OUT0.
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = 0x20188004;
+ }
+ else
+ {
+ // Restore MC/EMC clock.
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = clk_src_emc;
+ }
+
+ // Wait for CC interrupt.
+ while (!(EMC(EMC_INTSTATUS) & BIT(4)))
+ usleep(1);
+}
+
+static void _sdram_config_t210(const sdram_params_t210_t *params)
+{
+ // VDDP Select.
+ PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
+ usleep(params->pmc_vddp_sel_wait);
+
+ // Set DDR pad voltage.
+ PMC(APBDEV_PMC_DDR_PWR) = PMC(APBDEV_PMC_DDR_PWR); // Normally params->pmc_ddr_pwr.
+
+ // Turn on MEM IO Power.
+ PMC(APBDEV_PMC_NO_IOPOWER) &= PMC_NO_IOPOWER_SDMMC1; // Only keep SDMMC1 state. (Was params->pmc_no_io_power).
+ PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short;
+
+ PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl;
+
+ // Patch 1 using BCT spare variables
+ if (params->emc_bct_spare0)
+ *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1;
+
+ // Program DPD3/DPD4 regs (coldboot path).
+ // Enable sel_dpd on unused pins.
+ u32 dpd_req = (params->emc_pmc_scratch1 & 0x3FFFFFFF) | PMC_IO_DPD_REQ_DPD_ON;
+ PMC(APBDEV_PMC_IO_DPD3_REQ) = (dpd_req ^ 0xFFFF) & 0xC000FFFF;
+ usleep(params->pmc_io_dpd3_req_wait);
+
+ // Disable e_dpd_vttgen.
+ dpd_req = (params->emc_pmc_scratch2 & 0x3FFFFFFF) | PMC_IO_DPD_REQ_DPD_ON;
+ PMC(APBDEV_PMC_IO_DPD4_REQ) = (dpd_req & 0xFFFF0000) ^ 0x3FFF0000;
+ usleep(params->pmc_io_dpd4_req_wait);
+
+ // Disable e_dpd_bg.
+ PMC(APBDEV_PMC_IO_DPD4_REQ) = (dpd_req ^ 0xFFFF) & 0xC000FFFF;
+ usleep(params->pmc_io_dpd4_req_wait);
+
+ PMC(APBDEV_PMC_WEAK_BIAS) = 0;
+ usleep(1);
+
+ // Start PLLM.
+ CLOCK(CLK_RST_CONTROLLER_PLLM_MISC1) = params->pllm_setup_control;
+ CLOCK(CLK_RST_CONTROLLER_PLLM_MISC2) = 0;
+
+ u32 pllm_div = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20);
+ CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div;
+ CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div | PLLCX_BASE_ENABLE;
+
+ u32 wait_end = get_tmr_us() + 300;
+ while (!(CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) & BIT(27)))
+ {
+ if (get_tmr_us() >= wait_end)
+ goto lock_timeout;
+ }
+ usleep(10);
+
+lock_timeout:
+ // Set clock sources.
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = ((params->mc_emem_arb_misc0 >> 11) & 0x10000) | (params->emc_clock_source & 0xFFFEFFFF);
+ if (params->emc_clock_source_dll)
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll;
+ if (params->clear_clock2_mc1)
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_MC1); // Clear Reset to MC1.
+
+ // Enable and clear reset for memory clocks.
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
+ CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
+ CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
+
+ // Set pad vtt levels.
+ EMC(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0;
+ EMC(EMC_PMACRO_VTTGEN_CTRL_1) = params->emc_pmacro_vttgen_ctrl1;
+ EMC(EMC_PMACRO_VTTGEN_CTRL_2) = params->emc_pmacro_vttgen_ctrl2;
+
+ // Trigger timing update so above writes take place.
+ EMC(EMC_TIMING_CONTROL) = 1;
+ usleep(10); // Ensure the regulators settle.
+
+ // Select EMC write mux.
+ EMC(EMC_DBG) = (params->emc_dbg_write_mux << 1) | params->emc_dbg;
+
+ // Patch 2 using BCT spare variables.
+ if (params->emc_bct_spare2)
+ *(vu32 *)params->emc_bct_spare2 = params->emc_bct_spare3;
+
+ // Program CMD mapping. Required before brick mapping, else
+ // we can't guarantee CK will be differential at all times.
+ EMC(EMC_FBIO_CFG7) = params->emc_fbio_cfg7;
+ EMC(EMC_CMD_MAPPING_CMD0_0) = params->emc_cmd_mapping_cmd0_0;
+ EMC(EMC_CMD_MAPPING_CMD0_1) = params->emc_cmd_mapping_cmd0_1;
+ EMC(EMC_CMD_MAPPING_CMD0_2) = params->emc_cmd_mapping_cmd0_2;
+ EMC(EMC_CMD_MAPPING_CMD1_0) = params->emc_cmd_mapping_cmd1_0;
+ EMC(EMC_CMD_MAPPING_CMD1_1) = params->emc_cmd_mapping_cmd1_1;
+ EMC(EMC_CMD_MAPPING_CMD1_2) = params->emc_cmd_mapping_cmd1_2;
+ EMC(EMC_CMD_MAPPING_CMD2_0) = params->emc_cmd_mapping_cmd2_0;
+ EMC(EMC_CMD_MAPPING_CMD2_1) = params->emc_cmd_mapping_cmd2_1;
+ EMC(EMC_CMD_MAPPING_CMD2_2) = params->emc_cmd_mapping_cmd2_2;
+ EMC(EMC_CMD_MAPPING_CMD3_0) = params->emc_cmd_mapping_cmd3_0;
+ EMC(EMC_CMD_MAPPING_CMD3_1) = params->emc_cmd_mapping_cmd3_1;
+ EMC(EMC_CMD_MAPPING_CMD3_2) = params->emc_cmd_mapping_cmd3_2;
+ EMC(EMC_CMD_MAPPING_BYTE) = params->emc_cmd_mapping_byte;
+
+ // Program brick mapping.
+ EMC(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0;
+ EMC(EMC_PMACRO_BRICK_MAPPING_1) = params->emc_pmacro_brick_mapping1;
+ EMC(EMC_PMACRO_BRICK_MAPPING_2) = params->emc_pmacro_brick_mapping2;
+
+ EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = (params->emc_pmacro_brick_ctrl_rfu1 & 0x1120112) | 0x1EED1EED;
+
+ // This is required to do any reads from the pad macros.
+ EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay;
+
+ // Set data pipes mode.
+ EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8;
+
+ // Set swizzle for Rank 0.
+ EMC(EMC_SWIZZLE_RANK0_BYTE0) = params->emc_swizzle_rank0_byte0;
+ EMC(EMC_SWIZZLE_RANK0_BYTE1) = params->emc_swizzle_rank0_byte1;
+ EMC(EMC_SWIZZLE_RANK0_BYTE2) = params->emc_swizzle_rank0_byte2;
+ EMC(EMC_SWIZZLE_RANK0_BYTE3) = params->emc_swizzle_rank0_byte3;
+ // Set swizzle for Rank 1.
+ EMC(EMC_SWIZZLE_RANK1_BYTE0) = params->emc_swizzle_rank1_byte0;
+ EMC(EMC_SWIZZLE_RANK1_BYTE1) = params->emc_swizzle_rank1_byte1;
+ EMC(EMC_SWIZZLE_RANK1_BYTE2) = params->emc_swizzle_rank1_byte2;
+ EMC(EMC_SWIZZLE_RANK1_BYTE3) = params->emc_swizzle_rank1_byte3;
+
+ // Patch 3 using BCT spare variables.
+ if (params->emc_bct_spare6)
+ *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7;
+
+ // Program calibration impedance.
+ EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl;
+ EMC(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2;
+ EMC(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3;
+
+ // Program Autocal controls.
+ EMC(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2;
+ EMC(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3;
+ EMC(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4;
+ EMC(EMC_AUTO_CAL_CONFIG5) = params->emc_auto_cal_config5;
+ EMC(EMC_AUTO_CAL_CONFIG6) = params->emc_auto_cal_config6;
+ EMC(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7;
+ EMC(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8;
+
+ // Program termination and drive strength
+ EMC(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term;
+ EMC(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive;
+ EMC(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive;
+ EMC(EMC_PMACRO_CMD_TX_DRV) = params->emc_pmacro_cmd_tx_drive;
+ EMC(EMC_PMACRO_AUTOCAL_CFG_COMMON) = params->emc_pmacro_auto_cal_common;
+ EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel;
+ EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl;
+
+ // Program dll config.
+ EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0;
+ EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1;
+ EMC(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1;
+
+ // Program barrelshift.
+ EMC(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0;
+ EMC(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1;
+ EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0;
+ EMC(EMC_DQS_BRLSHFT_1) = params->emc_dqs_brlshft1;
+ EMC(EMC_CMD_BRLSHFT_0) = params->emc_cmd_brlshft0;
+ EMC(EMC_CMD_BRLSHFT_1) = params->emc_cmd_brlshft1;
+ EMC(EMC_CMD_BRLSHFT_2) = params->emc_cmd_brlshft2;
+ EMC(EMC_CMD_BRLSHFT_3) = params->emc_cmd_brlshft3;
+ EMC(EMC_QUSE_BRLSHFT_0) = params->emc_quse_brlshft0;
+ EMC(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1;
+ EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2;
+ EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3;
+
+ // Program pad macros controls and termination.
+ EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = (params->emc_pmacro_brick_ctrl_rfu1 & 0x1BF01BF) | 0x1E401E40;
+ EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl;
+
+ EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd;
+ EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2 & 0xFF7FFF7F;
+ EMC(EMC_PMACRO_DATA_BRICK_CTRL_FDPD) = params->emc_pmacro_data_brick_ctrl_fdpd;
+ EMC(EMC_PMACRO_BG_BIAS_CTRL_0) = params->emc_pmacro_bg_bias_ctrl0;
+ EMC(EMC_PMACRO_DATA_PAD_RX_CTRL) = params->emc_pmacro_data_pad_rx_ctrl;
+ EMC(EMC_PMACRO_CMD_PAD_RX_CTRL) = params->emc_pmacro_cmd_pad_rx_ctrl;
+ EMC(EMC_PMACRO_DATA_PAD_TX_CTRL) = params->emc_pmacro_data_pad_tx_ctrl;
+ EMC(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode;
+ EMC(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode;
+ EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl;
+
+ // Program pad macro pins/bytes.
+ EMC(EMC_CFG_3) = params->emc_cfg3;
+ EMC(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0;
+ EMC(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1;
+ EMC(EMC_PMACRO_TX_PWRD_2) = params->emc_pmacro_tx_pwrd2;
+ EMC(EMC_PMACRO_TX_PWRD_3) = params->emc_pmacro_tx_pwrd3;
+ EMC(EMC_PMACRO_TX_PWRD_4) = params->emc_pmacro_tx_pwrd4;
+ EMC(EMC_PMACRO_TX_PWRD_5) = params->emc_pmacro_tx_pwrd5;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_0) = params->emc_pmacro_tx_sel_clk_src0;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_1) = params->emc_pmacro_tx_sel_clk_src1;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_2) = params->emc_pmacro_tx_sel_clk_src2;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_3) = params->emc_pmacro_tx_sel_clk_src3;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_4) = params->emc_pmacro_tx_sel_clk_src4;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_5) = params->emc_pmacro_tx_sel_clk_src5;
+ EMC(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass;
+ EMC(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0;
+ EMC(EMC_PMACRO_DDLL_PWRD_1) = params->emc_pmacro_ddll_pwrd1;
+ EMC(EMC_PMACRO_DDLL_PWRD_2) = params->emc_pmacro_ddll_pwrd2;
+ EMC(EMC_PMACRO_CMD_CTRL_0) = params->emc_pmacro_cmd_ctrl0;
+ EMC(EMC_PMACRO_CMD_CTRL_1) = params->emc_pmacro_cmd_ctrl1;
+ EMC(EMC_PMACRO_CMD_CTRL_2) = params->emc_pmacro_cmd_ctrl2;
+
+ // Program inbound vref setting.
+ EMC(EMC_PMACRO_IB_VREF_DQ_0) = params->emc_pmacro_ib_vref_dq_0;
+ EMC(EMC_PMACRO_IB_VREF_DQ_1) = params->emc_pmacro_ib_vref_dq_1;
+ EMC(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0;
+ EMC(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1;
+ EMC(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt;
+
+ // Program quse trimmers.
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_3) = params->emc_pmacro_quse_ddll_rank0_3;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_4) = params->emc_pmacro_quse_ddll_rank0_4;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_5) = params->emc_pmacro_quse_ddll_rank0_5;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_0) = params->emc_pmacro_quse_ddll_rank1_0;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_1) = params->emc_pmacro_quse_ddll_rank1_1;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_2) = params->emc_pmacro_quse_ddll_rank1_2;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_3) = params->emc_pmacro_quse_ddll_rank1_3;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_4) = params->emc_pmacro_quse_ddll_rank1_4;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5;
+ EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1;
+
+ // Program outbound trimmers.
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3) = params->emc_pmacro_ob_ddll_long_dq_rank0_3;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4) = params->emc_pmacro_ob_ddll_long_dq_rank0_4;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5) = params->emc_pmacro_ob_ddll_long_dq_rank0_5;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0) = params->emc_pmacro_ob_ddll_long_dq_rank1_0;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1) = params->emc_pmacro_ob_ddll_long_dq_rank1_1;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2) = params->emc_pmacro_ob_ddll_long_dq_rank1_2;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3) = params->emc_pmacro_ob_ddll_long_dq_rank1_3;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4) = params->emc_pmacro_ob_ddll_long_dq_rank1_4;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5) = params->emc_pmacro_ob_ddll_long_dq_rank1_5;
+
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ob_ddll_long_dqs_rank0_0;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ob_ddll_long_dqs_rank0_1;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ob_ddll_long_dqs_rank0_2;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ob_ddll_long_dqs_rank0_3;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4) = params->emc_pmacro_ob_ddll_long_dqs_rank0_4;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5) = params->emc_pmacro_ob_ddll_long_dqs_rank0_5;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ob_ddll_long_dqs_rank1_0;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ob_ddll_long_dqs_rank1_1;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ob_ddll_long_dqs_rank1_2;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ob_ddll_long_dqs_rank1_3;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4) = params->emc_pmacro_ob_ddll_long_dqs_rank1_4;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5) = params->emc_pmacro_ob_ddll_long_dqs_rank1_5;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ib_ddll_long_dqs_rank0_0;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ib_ddll_long_dqs_rank0_1;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ib_ddll_long_dqs_rank0_2;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ib_ddll_long_dqs_rank0_3;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ib_ddll_long_dqs_rank1_0;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ib_ddll_long_dqs_rank1_1;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3;
+
+ // Program clock trimmers.
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0;
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1;
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2;
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_3) = params->emc_pmacro_ddll_long_cmd_3;
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_4) = params->emc_pmacro_ddll_long_cmd_4;
+ EMC(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0;
+ EMC(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1;
+ EMC(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2;
+
+ // Common pad macro (cpm).
+ EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = (params->emc_pmacro_common_pad_tx_ctrl & 1) | 0xE;
+
+ // Patch 4 using BCT spare variables.
+ if (params->emc_bct_spare4)
+ *(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5;
+
+ // Trigger timing update so above writes take place.
+ EMC(EMC_TIMING_CONTROL) = 1;
+
+ // Initialize MC VPR settings.
+ MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom;
+ MC(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi;
+ MC(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb;
+ MC(MC_VIDEO_PROTECT_VPR_OVERRIDE) = params->mc_video_protect_vpr_override;
+ MC(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1;
+ MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = params->mc_video_protect_gpu_override0;
+ MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = params->mc_video_protect_gpu_override1;
+
+ // Program SDRAM geometry parameters.
+ MC(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg;
+ MC(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0;
+ MC(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1;
+ MC(MC_EMEM_ADR_CFG_CHANNEL_MASK) = params->mc_emem_adr_cfg_channel_mask;
+
+ // Program bank swizzling.
+ MC(MC_EMEM_ADR_CFG_BANK_MASK_0) = params->mc_emem_adr_cfg_bank_mask0;
+ MC(MC_EMEM_ADR_CFG_BANK_MASK_1) = params->mc_emem_adr_cfg_bank_mask1;
+ MC(MC_EMEM_ADR_CFG_BANK_MASK_2) = params->mc_emem_adr_cfg_bank_mask2;
+
+ // Program external memory aperture (base and size).
+ MC(MC_EMEM_CFG) = params->mc_emem_cfg;
+
+ // Program SEC carveout (base and size).
+ MC(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom;
+ MC(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi;
+ MC(MC_SEC_CARVEOUT_SIZE_MB) = params->mc_sec_carveout_size_mb;
+
+ // Program MTS carveout (base and size).
+ MC(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom;
+ MC(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi;
+ MC(MC_MTS_CARVEOUT_SIZE_MB) = params->mc_mts_carveout_size_mb;
+
+ // Program the memory arbiter.
+ MC(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg;
+ MC(MC_EMEM_ARB_OUTSTANDING_REQ) = params->mc_emem_arb_outstanding_req;
+ MC(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl;
+ MC(MC_EMEM_ARB_REFPB_BANK_CTRL) = params->emc_emem_arb_refpb_bank_ctrl;
+ MC(MC_EMEM_ARB_TIMING_RCD) = params->mc_emem_arb_timing_rcd;
+ MC(MC_EMEM_ARB_TIMING_RP) = params->mc_emem_arb_timing_rp;
+ MC(MC_EMEM_ARB_TIMING_RC) = params->mc_emem_arb_timing_rc;
+ MC(MC_EMEM_ARB_TIMING_RAS) = params->mc_emem_arb_timing_ras;
+ MC(MC_EMEM_ARB_TIMING_FAW) = params->mc_emem_arb_timing_faw;
+ MC(MC_EMEM_ARB_TIMING_RRD) = params->mc_emem_arb_timing_rrd;
+ MC(MC_EMEM_ARB_TIMING_RAP2PRE) = params->mc_emem_arb_timing_rap2pre;
+ MC(MC_EMEM_ARB_TIMING_WAP2PRE) = params->mc_emem_arb_timing_wap2pre;
+ MC(MC_EMEM_ARB_TIMING_R2R) = params->mc_emem_arb_timing_r2r;
+ MC(MC_EMEM_ARB_TIMING_W2W) = params->mc_emem_arb_timing_w2w;
+ MC(MC_EMEM_ARB_TIMING_CCDMW) = params->mc_emem_arb_timing_ccdmw;
+ MC(MC_EMEM_ARB_TIMING_R2W) = params->mc_emem_arb_timing_r2w;
+ MC(MC_EMEM_ARB_TIMING_W2R) = params->mc_emem_arb_timing_w2r;
+ MC(MC_EMEM_ARB_TIMING_RFCPB) = params->mc_emem_arb_timing_rfcpb;
+ MC(MC_EMEM_ARB_DA_TURNS) = params->mc_emem_arb_da_turns;
+ MC(MC_EMEM_ARB_DA_COVERS) = params->mc_emem_arb_da_covers;
+ MC(MC_EMEM_ARB_MISC0) = params->mc_emem_arb_misc0;
+ MC(MC_EMEM_ARB_MISC1) = params->mc_emem_arb_misc1;
+ MC(MC_EMEM_ARB_MISC2) = params->mc_emem_arb_misc2;
+ MC(MC_EMEM_ARB_RING1_THROTTLE) = params->mc_emem_arb_ring1_throttle;
+ MC(MC_EMEM_ARB_OVERRIDE) = params->mc_emem_arb_override;
+ MC(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1;
+ MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv;
+ MC(MC_DA_CONFIG0) = params->mc_da_cfg0;
+
+ // Trigger MC timing update.
+ MC(MC_TIMING_CONTROL) = 1;
+
+ // Program second-level clock enable overrides.
+ MC(MC_CLKEN_OVERRIDE) = params->mc_clken_override;
+
+ // Program statistics gathering.
+ MC(MC_STAT_CONTROL) = params->mc_stat_control;
+
+ // Program SDRAM geometry parameters.
+ EMC(EMC_ADR_CFG) = params->emc_adr_cfg;
+
+ // Program second-level clock enable overrides.
+ EMC(EMC_CLKEN_OVERRIDE) = params->emc_clken_override;
+
+ // Program EMC pad auto calibration.
+ EMC(EMC_PMACRO_AUTOCAL_CFG_0) = params->emc_pmacro_auto_cal_cfg0;
+ EMC(EMC_PMACRO_AUTOCAL_CFG_1) = params->emc_pmacro_auto_cal_cfg1;
+ EMC(EMC_PMACRO_AUTOCAL_CFG_2) = params->emc_pmacro_auto_cal_cfg2;
+
+ EMC(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0;
+ EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1;
+
+ // Program/Start auto calibration.
+ EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval;
+ EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config;
+ usleep(params->emc_auto_cal_wait);
+
+ // Patch 5 using BCT spare variables.
+ if (params->emc_bct_spare8)
+ *(vu32 *)params->emc_bct_spare8 = params->emc_bct_spare9;
+
+ // Program EMC timing configuration.
+ EMC(EMC_CFG_2) = params->emc_cfg2;
+ EMC(EMC_CFG_PIPE) = params->emc_cfg_pipe;
+ EMC(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1;
+ EMC(EMC_CFG_PIPE_2) = params->emc_cfg_pipe2;
+ EMC(EMC_CMDQ) = params->emc_cmd_q;
+ EMC(EMC_MC2EMCQ) = params->emc_mc2emc_q;
+ EMC(EMC_MRS_WAIT_CNT) = params->emc_mrs_wait_cnt;
+ EMC(EMC_MRS_WAIT_CNT2) = params->emc_mrs_wait_cnt2;
+ EMC(EMC_FBIO_CFG5) = params->emc_fbio_cfg5;
+ EMC(EMC_RC) = params->emc_rc;
+ EMC(EMC_RFC) = params->emc_rfc;
+ EMC(EMC_RFCPB) = params->emc_rfc_pb;
+ EMC(EMC_REFCTRL2) = params->emc_ref_ctrl2;
+ EMC(EMC_RFC_SLR) = params->emc_rfc_slr;
+ EMC(EMC_RAS) = params->emc_ras;
+ EMC(EMC_RP) = params->emc_rp;
+ EMC(EMC_TPPD) = params->emc_tppd;
+ EMC(EMC_R2R) = params->emc_r2r;
+ EMC(EMC_W2W) = params->emc_w2w;
+ EMC(EMC_R2W) = params->emc_r2w;
+ EMC(EMC_W2R) = params->emc_w2r;
+ EMC(EMC_R2P) = params->emc_r2p;
+ EMC(EMC_W2P) = params->emc_w2p;
+ EMC(EMC_CCDMW) = params->emc_ccdmw;
+ EMC(EMC_RD_RCD) = params->emc_rd_rcd;
+ EMC(EMC_WR_RCD) = params->emc_wr_rcd;
+ EMC(EMC_RRD) = params->emc_rrd;
+ EMC(EMC_REXT) = params->emc_rext;
+ EMC(EMC_WEXT) = params->emc_wext;
+ EMC(EMC_WDV) = params->emc_wdv;
+ EMC(EMC_WDV_CHK) = params->emc_wdv_chk;
+ EMC(EMC_WSV) = params->emc_wsv;
+ EMC(EMC_WEV) = params->emc_wev;
+ EMC(EMC_WDV_MASK) = params->emc_wdv_mask;
+ EMC(EMC_WS_DURATION) = params->emc_ws_duration;
+ EMC(EMC_WE_DURATION) = params->emc_we_duration;
+ EMC(EMC_QUSE) = params->emc_quse;
+ EMC(EMC_QUSE_WIDTH) = params->emc_quse_width;
+ EMC(EMC_IBDLY) = params->emc_ibdly;
+ EMC(EMC_OBDLY) = params->emc_obdly;
+ EMC(EMC_EINPUT) = params->emc_einput;
+ EMC(EMC_EINPUT_DURATION) = params->emc_einput_duration;
+ EMC(EMC_PUTERM_EXTRA) = params->emc_puterm_extra;
+ EMC(EMC_PUTERM_WIDTH) = params->emc_puterm_width;
+
+ EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = params->emc_pmacro_common_pad_tx_ctrl;
+ EMC(EMC_DBG) = params->emc_dbg;
+
+ // Clear read fifo.
+ EMC(EMC_QRST) = params->emc_qrst;
+ EMC(EMC_ISSUE_QRST) = 1;
+ EMC(EMC_ISSUE_QRST) = 0;
+
+ // Program the rest of EMC timing configuration.
+ EMC(EMC_QSAFE) = params->emc_qsafe;
+ EMC(EMC_RDV) = params->emc_rdv;
+ EMC(EMC_RDV_MASK) = params->emc_rdv_mask;
+ EMC(EMC_RDV_EARLY) = params->emc_rdv_early;
+ EMC(EMC_RDV_EARLY_MASK) = params->emc_rdv_early_mask;
+ EMC(EMC_QPOP) = params->emc_qpop;
+ EMC(EMC_REFRESH) = params->emc_refresh;
+ EMC(EMC_BURST_REFRESH_NUM) = params->emc_burst_refresh_num;
+ EMC(EMC_PRE_REFRESH_REQ_CNT) = params->emc_prerefresh_req_cnt;
+ EMC(EMC_PDEX2WR) = params->emc_pdex2wr;
+ EMC(EMC_PDEX2RD) = params->emc_pdex2rd;
+ EMC(EMC_PCHG2PDEN) = params->emc_pchg2pden;
+ EMC(EMC_ACT2PDEN) = params->emc_act2pden;
+ EMC(EMC_AR2PDEN) = params->emc_ar2pden;
+ EMC(EMC_RW2PDEN) = params->emc_rw2pden;
+ EMC(EMC_CKE2PDEN) = params->emc_cke2pden;
+ EMC(EMC_PDEX2CKE) = params->emc_pdex2che;
+ EMC(EMC_PDEX2MRR) = params->emc_pdex2mrr;
+ EMC(EMC_TXSR) = params->emc_txsr;
+ EMC(EMC_TXSRDLL) = params->emc_txsr_dll;
+ EMC(EMC_TCKE) = params->emc_tcke;
+ EMC(EMC_TCKESR) = params->emc_tckesr;
+ EMC(EMC_TPD) = params->emc_tpd;
+ EMC(EMC_TFAW) = params->emc_tfaw;
+ EMC(EMC_TRPAB) = params->emc_trpab;
+ EMC(EMC_TCLKSTABLE) = params->emc_tclkstable;
+ EMC(EMC_TCLKSTOP) = params->emc_tclkstop;
+ EMC(EMC_TREFBW) = params->emc_trefbw;
+ EMC(EMC_ODT_WRITE) = params->emc_odt_write;
+ EMC(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll;
+ EMC(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period;
+
+ // Don't write CFG_ADR_EN (bit 1) here - lock bit written later.
+ EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD;
+ EMC(EMC_CFG_RSV) = params->emc_cfg_rsv;
+ EMC(EMC_PMC_SCRATCH1) = params->emc_pmc_scratch1;
+ EMC(EMC_PMC_SCRATCH2) = params->emc_pmc_scratch2;
+ EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3;
+ EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control;
+ EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen;
+
+ // Set pipe bypass enable bits before sending any DRAM commands.
+ EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000;
+
+ // Patch BootROM.
+ if (params->boot_rom_patch_control & BIT(31))
+ {
+ *(vu32 *)(APB_MISC_BASE + params->boot_rom_patch_control * 4) = params->boot_rom_patch_data;
+
+ // Trigger MC timing update.
+ MC(MC_TIMING_CONTROL) = 1;
+ }
+
+ // Release SEL_DPD_CMD.
+ PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | PMC_IO_DPD_REQ_DPD_OFF;
+ usleep(params->pmc_io_dpd3_req_wait);
+
+ // Stall auto call measurements if periodic calibration is disabled.
+ if (!params->emc_auto_cal_interval)
+ EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config | 0x200;
+
+ EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2;
+
+ // ZQ CAL setup (not actually issuing ZQ CAL now).
+ if (params->emc_zcal_warm_cold_boot_enables & 1)
+ {
+ EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt;
+ EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd;
+ }
+
+ // Trigger timing update so above writes take place.
+ EMC(EMC_TIMING_CONTROL) = 1;
+ usleep(params->emc_timing_control_wait);
+
+ // Deassert HOLD_CKE_LOW.
+ PMC(APBDEV_PMC_DDR_CNTRL) &= 0xFFF8007F;
+ usleep(params->pmc_ddr_ctrl_wait);
+
+ // Set clock enable signal.
+ u32 pin_gpio_cfg = (params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12);
+ EMC(EMC_PIN) = pin_gpio_cfg;
+ (void)EMC(EMC_PIN);
+ usleep(params->emc_pin_extra_wait + 200);
+ EMC(EMC_PIN) = pin_gpio_cfg | 0x100;
+ (void)EMC(EMC_PIN);
+
+ usleep(params->emc_pin_extra_wait + 2000);
+
+ // Enable clock enable signal.
+ EMC(EMC_PIN) = pin_gpio_cfg | 0x101;
+ (void)EMC(EMC_PIN);
+ usleep(params->emc_pin_program_wait);
+
+ // Init zq calibration,
+ // Patch 6 using BCT spare variables.
+ if (params->emc_bct_spare10)
+ *(vu32 *)params->emc_bct_spare10 = params->emc_bct_spare11;
+
+ // Write mode registers.
+ EMC(EMC_MRW2) = params->emc_mrw2;
+ EMC(EMC_MRW) = params->emc_mrw1;
+ EMC(EMC_MRW3) = params->emc_mrw3;
+ EMC(EMC_MRW4) = params->emc_mrw4;
+ EMC(EMC_MRW6) = params->emc_mrw6;
+ EMC(EMC_MRW14) = params->emc_mrw14;
+
+ EMC(EMC_MRW8) = params->emc_mrw8;
+ EMC(EMC_MRW12) = params->emc_mrw12;
+ EMC(EMC_MRW9) = params->emc_mrw9;
+ EMC(EMC_MRW13) = params->emc_mrw13;
+
+ if (params->emc_zcal_warm_cold_boot_enables & 1)
+ {
+ // Issue ZQCAL start, device 0.
+ EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0;
+ usleep(params->emc_zcal_init_wait);
+
+ // Issue ZQCAL latch.
+ EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0 ^ 3;
+ // Same for device 1.
+ if (!(params->emc_dev_select & 2))
+ {
+ EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1;
+ usleep(params->emc_zcal_init_wait);
+ EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1 ^ 3;
+ }
+ }
+
+ // Set package and DPD pad control.
+ PMC(APBDEV_PMC_DDR_CFG) = params->pmc_ddr_cfg;
+
+ // Start periodic ZQ calibration (LPDDRx only).
+ EMC(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval;
+ EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt;
+ EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd;
+
+ // Patch 7 using BCT spare variables.
+ if (params->emc_bct_spare12)
+ *(vu32 *)params->emc_bct_spare12 = params->emc_bct_spare13;
+
+ // Trigger timing update so above writes take place.
+ EMC(EMC_TIMING_CONTROL) = 1;
+
+ if (params->emc_extra_refresh_num)
+ EMC(EMC_REF) = (((1 << params->emc_extra_refresh_num) - 1) << 8) | (params->emc_dev_select << 30) | 3;
+
+ // Enable refresh.
+ EMC(EMC_REFCTRL) = params->emc_dev_select | BIT(31);
+
+ EMC(EMC_DYN_SELF_REF_CONTROL) = params->emc_dyn_self_ref_control;
+ EMC(EMC_CFG_UPDATE) = params->emc_cfg_update;
+ EMC(EMC_CFG) = params->emc_cfg;
+ EMC(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq;
+ EMC(EMC_FDPD_CTRL_CMD) = params->emc_fdpd_ctrl_cmd;
+ EMC(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl;
+
+ // Write addr swizzle lock bit.
+ EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | BIT(1);
+
+ // Re-trigger timing to latch power saving functions.
+ EMC(EMC_TIMING_CONTROL) = 1;
+
+ // Enable EMC pipe clock gating.
+ EMC(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk;
+
+ // Depending on freqency, enable CMD/CLK fdpd.
+ EMC(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp;
+
+ // Enable arbiter.
+ SYSREG(AHB_ARBITRATION_XBAR_CTRL) = (SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF) | (params->ahb_arbitration_xbar_ctrl_meminit_done << 16);
+
+ // Lock carveouts per BCT cfg.
+ MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access;
+ MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access;
+ MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl;
+
+ // Disable write access to a bunch of EMC registers.
+ MC(MC_EMEM_CFG_ACCESS_CTRL) = 1;
+}
+
+static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
+{
+ // VDDP Select.
+ PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
+ usleep(params->pmc_vddp_sel_wait);
+
+ // Turn on MEM IO Power.
+ PMC(APBDEV_PMC_NO_IOPOWER) &= PMC_NO_IOPOWER_SDMMC1; // Only keep SDMMC1 state. (Was params->pmc_no_io_power).
+ PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short;
+
+ PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl;
+
+ // Patch 1 using BCT spare variables
+ if (params->emc_bct_spare0)
+ *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1;
+
+ // Override HW FSM if needed.
+ if (params->clk_rst_pllm_misc20_override_enable)
+ CLOCK(CLK_RST_CONTROLLER_PLLM_MISC2) = params->clk_rst_pllm_misc20_override;
+
+ // Program DPD3/DPD4 regs (coldboot path).
+ // Enable sel_dpd on unused pins.
+ u32 pmc_scratch1 = ~params->emc_pmc_scratch1;
+ PMC(APBDEV_PMC_WEAK_BIAS) = (pmc_scratch1 & 0x1000) << 19 | (pmc_scratch1 & 0xFFF) << 18 | (pmc_scratch1 & 0x8000) << 15;
+ PMC(APBDEV_PMC_IO_DPD3_REQ) = (pmc_scratch1 & 0x9FFF) | PMC_IO_DPD_REQ_DPD_ON;
+ usleep(params->pmc_io_dpd3_req_wait);
+
+ // Disable e_dpd_vttgen.
+ u32 pmc_scratch2 = ~params->emc_pmc_scratch2;
+ PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x3FFF0000) | PMC_IO_DPD_REQ_DPD_ON;
+ usleep(params->pmc_io_dpd4_req_wait);
+
+ // Disable e_dpd_bg.
+ PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x1FFF) | PMC_IO_DPD_REQ_DPD_ON;
+ usleep(1);
+
+ // Program CMD mapping. Required before brick mapping, else
+ // we can't guarantee CK will be differential at all times.
+ EMC(EMC_FBIO_CFG7) = params->emc_fbio_cfg7;
+ EMC(EMC_CMD_MAPPING_CMD0_0) = params->emc_cmd_mapping_cmd0_0;
+ EMC(EMC_CMD_MAPPING_CMD0_1) = params->emc_cmd_mapping_cmd0_1;
+ EMC(EMC_CMD_MAPPING_CMD0_2) = params->emc_cmd_mapping_cmd0_2;
+ EMC(EMC_CMD_MAPPING_CMD1_0) = params->emc_cmd_mapping_cmd1_0;
+ EMC(EMC_CMD_MAPPING_CMD1_1) = params->emc_cmd_mapping_cmd1_1;
+ EMC(EMC_CMD_MAPPING_CMD1_2) = params->emc_cmd_mapping_cmd1_2;
+ EMC(EMC_CMD_MAPPING_CMD2_0) = params->emc_cmd_mapping_cmd2_0;
+ EMC(EMC_CMD_MAPPING_CMD2_1) = params->emc_cmd_mapping_cmd2_1;
+ EMC(EMC_CMD_MAPPING_CMD2_2) = params->emc_cmd_mapping_cmd2_2;
+ EMC(EMC_CMD_MAPPING_CMD3_0) = params->emc_cmd_mapping_cmd3_0;
+ EMC(EMC_CMD_MAPPING_CMD3_1) = params->emc_cmd_mapping_cmd3_1;
+ EMC(EMC_CMD_MAPPING_CMD3_2) = params->emc_cmd_mapping_cmd3_2;
+ EMC(EMC_CMD_MAPPING_BYTE) = params->emc_cmd_mapping_byte;
+
+ // Program brick mapping.
+ EMC(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0;
+ EMC(EMC_PMACRO_BRICK_MAPPING_1) = params->emc_pmacro_brick_mapping1;
+ EMC(EMC_PMACRO_BRICK_MAPPING_2) = params->emc_pmacro_brick_mapping2;
+
+ // Set pad macros.
+ EMC(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0;
+ EMC(EMC_PMACRO_VTTGEN_CTRL_1) = params->emc_pmacro_vttgen_ctrl1;
+ EMC(EMC_PMACRO_VTTGEN_CTRL_2) = params->emc_pmacro_vttgen_ctrl2;
+
+ // Set pad macros bias.
+ EMC(EMC_PMACRO_BG_BIAS_CTRL_0) = params->emc_pmacro_bg_bias_ctrl0;
+
+ // Patch 1 to 3 using BCT spare secure variables.
+ if (params->emc_bct_spare_secure0)
+ *(vu32 *)params->emc_bct_spare_secure0 = params->emc_bct_spare_secure1;
+ if (params->emc_bct_spare_secure2)
+ *(vu32 *)params->emc_bct_spare_secure2 = params->emc_bct_spare_secure3;
+ if (params->emc_bct_spare_secure4)
+ *(vu32 *)params->emc_bct_spare_secure4 = params->emc_bct_spare_secure5;
+
+ // Trigger timing update so above writes take place.
+ EMC(EMC_TIMING_CONTROL) = 1;
+ usleep(params->pmc_vddp_sel_wait + 2); // Ensure the regulators settle.
+
+ // Set clock sources.
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = params->emc_clock_source;
+ CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll;
+
+ // Select EMC write mux.
+ EMC(EMC_DBG) = (params->emc_dbg_write_mux << 1) | params->emc_dbg;
+
+ // Patch 2 using BCT spare variables.
+ if (params->emc_bct_spare2)
+ *(vu32 *)params->emc_bct_spare2 = params->emc_bct_spare3;
+
+ // This is required to do any reads from the pad macros.
+ EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay;
+
+ // Set data pipes mode.
+ EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8;
+
+ // Set swizzle for Rank 0.
+ EMC(EMC_SWIZZLE_RANK0_BYTE0) = params->emc_swizzle_rank0_byte0;
+ EMC(EMC_SWIZZLE_RANK0_BYTE1) = params->emc_swizzle_rank0_byte1;
+ EMC(EMC_SWIZZLE_RANK0_BYTE2) = params->emc_swizzle_rank0_byte2;
+ EMC(EMC_SWIZZLE_RANK0_BYTE3) = params->emc_swizzle_rank0_byte3;
+ // Set swizzle for Rank 1.
+ EMC(EMC_SWIZZLE_RANK1_BYTE0) = params->emc_swizzle_rank1_byte0;
+ EMC(EMC_SWIZZLE_RANK1_BYTE1) = params->emc_swizzle_rank1_byte1;
+ EMC(EMC_SWIZZLE_RANK1_BYTE2) = params->emc_swizzle_rank1_byte2;
+ EMC(EMC_SWIZZLE_RANK1_BYTE3) = params->emc_swizzle_rank1_byte3;
+
+ // Patch 3 using BCT spare variables.
+ if (params->emc_bct_spare6)
+ *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7;
+
+ // Program calibration impedance.
+ EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl;
+ EMC(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2;
+ EMC(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3;
+
+ // Program Autocal controls.
+ EMC(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2;
+ EMC(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3;
+ EMC(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4;
+ EMC(EMC_AUTO_CAL_CONFIG5) = params->emc_auto_cal_config5;
+ EMC(EMC_AUTO_CAL_CONFIG6) = params->emc_auto_cal_config6;
+ EMC(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7;
+ EMC(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8;
+
+ // Program termination and drive strength
+ EMC(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term;
+ EMC(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive;
+ EMC(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive;
+ EMC(EMC_PMACRO_CMD_TX_DRV) = params->emc_pmacro_cmd_tx_drive;
+ EMC(EMC_PMACRO_AUTOCAL_CFG_COMMON) = params->emc_pmacro_auto_cal_common;
+ EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel;
+ EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl;
+
+ // Program dll config.
+ EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0;
+ EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1;
+ EMC(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1;
+
+ // Program barrelshift.
+ EMC(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0;
+ EMC(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1;
+ EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0;
+ EMC(EMC_DQS_BRLSHFT_1) = params->emc_dqs_brlshft1;
+ EMC(EMC_CMD_BRLSHFT_0) = params->emc_cmd_brlshft0;
+ EMC(EMC_CMD_BRLSHFT_1) = params->emc_cmd_brlshft1;
+ EMC(EMC_CMD_BRLSHFT_2) = params->emc_cmd_brlshft2;
+ EMC(EMC_CMD_BRLSHFT_3) = params->emc_cmd_brlshft3;
+ EMC(EMC_QUSE_BRLSHFT_0) = params->emc_quse_brlshft0;
+ EMC(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1;
+ EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2;
+ EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3;
+
+ // Program pad macros controls and termination.
+ EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1;
+ EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl;
+
+ EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd;
+ EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2;
+ EMC(EMC_PMACRO_DATA_BRICK_CTRL_FDPD) = params->emc_pmacro_data_brick_ctrl_fdpd;
+ EMC(EMC_PMACRO_DATA_PAD_RX_CTRL) = params->emc_pmacro_data_pad_rx_ctrl;
+ EMC(EMC_PMACRO_CMD_PAD_RX_CTRL) = params->emc_pmacro_cmd_pad_rx_ctrl;
+ EMC(EMC_PMACRO_DATA_PAD_TX_CTRL) = params->emc_pmacro_data_pad_tx_ctrl;
+ EMC(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode;
+ EMC(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode;
+ EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl & 0xEFFFFFFF;
+
+ // Program pad macro pins/bytes.
+ EMC(EMC_CFG_3) = params->emc_cfg3;
+ EMC(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0;
+ EMC(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1;
+ EMC(EMC_PMACRO_TX_PWRD_2) = params->emc_pmacro_tx_pwrd2;
+ EMC(EMC_PMACRO_TX_PWRD_3) = params->emc_pmacro_tx_pwrd3;
+ EMC(EMC_PMACRO_TX_PWRD_4) = params->emc_pmacro_tx_pwrd4;
+ EMC(EMC_PMACRO_TX_PWRD_5) = params->emc_pmacro_tx_pwrd5;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_0) = params->emc_pmacro_tx_sel_clk_src0;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_1) = params->emc_pmacro_tx_sel_clk_src1;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_2) = params->emc_pmacro_tx_sel_clk_src2;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_3) = params->emc_pmacro_tx_sel_clk_src3;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_4) = params->emc_pmacro_tx_sel_clk_src4;
+ EMC(EMC_PMACRO_TX_SEL_CLK_SRC_5) = params->emc_pmacro_tx_sel_clk_src5;
+
+ // Program per bit pad macros.
+ EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_0) = params->emc_pmacro_perbit_fgcg_ctrl0;
+ EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_1) = params->emc_pmacro_perbit_fgcg_ctrl1;
+ EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_2) = params->emc_pmacro_perbit_fgcg_ctrl2;
+ EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_3) = params->emc_pmacro_perbit_fgcg_ctrl3;
+ EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_4) = params->emc_pmacro_perbit_fgcg_ctrl4;
+ EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_5) = params->emc_pmacro_perbit_fgcg_ctrl5;
+ EMC(EMC_PMACRO_PERBIT_RFU_CTRL_0) = params->emc_pmacro_perbit_rfu_ctrl0;
+ EMC(EMC_PMACRO_PERBIT_RFU_CTRL_1) = params->emc_pmacro_perbit_rfu_ctrl1;
+ EMC(EMC_PMACRO_PERBIT_RFU_CTRL_2) = params->emc_pmacro_perbit_rfu_ctrl2;
+ EMC(EMC_PMACRO_PERBIT_RFU_CTRL_3) = params->emc_pmacro_perbit_rfu_ctrl3;
+ EMC(EMC_PMACRO_PERBIT_RFU_CTRL_4) = params->emc_pmacro_perbit_rfu_ctrl4;
+ EMC(EMC_PMACRO_PERBIT_RFU_CTRL_5) = params->emc_pmacro_perbit_rfu_ctrl5;
+ EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_0) = params->emc_pmacro_perbit_rfu1_ctrl0;
+ EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_1) = params->emc_pmacro_perbit_rfu1_ctrl1;
+ EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_2) = params->emc_pmacro_perbit_rfu1_ctrl2;
+ EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_3) = params->emc_pmacro_perbit_rfu1_ctrl3;
+ EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_4) = params->emc_pmacro_perbit_rfu1_ctrl4;
+ EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_5) = params->emc_pmacro_perbit_rfu1_ctrl5;
+ EMC(EMC_PMACRO_DATA_PI_CTRL) = params->emc_pmacro_data_pi_ctrl;
+ EMC(EMC_PMACRO_CMD_PI_CTRL) = params->emc_pmacro_cmd_pi_ctrl;
+
+ EMC(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass;
+ EMC(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0;
+ EMC(EMC_PMACRO_DDLL_PWRD_1) = params->emc_pmacro_ddll_pwrd1;
+ EMC(EMC_PMACRO_DDLL_PWRD_2) = params->emc_pmacro_ddll_pwrd2;
+ EMC(EMC_PMACRO_CMD_CTRL_0) = params->emc_pmacro_cmd_ctrl0;
+ EMC(EMC_PMACRO_CMD_CTRL_1) = params->emc_pmacro_cmd_ctrl1;
+ EMC(EMC_PMACRO_CMD_CTRL_2) = params->emc_pmacro_cmd_ctrl2;
+
+ // Program inbound vref setting.
+ EMC(EMC_PMACRO_IB_VREF_DQ_0) = params->emc_pmacro_ib_vref_dq_0;
+ EMC(EMC_PMACRO_IB_VREF_DQ_1) = params->emc_pmacro_ib_vref_dq_1;
+ EMC(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0;
+ EMC(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1;
+ EMC(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt;
+
+ // Program quse trimmers.
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_3) = params->emc_pmacro_quse_ddll_rank0_3;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_4) = params->emc_pmacro_quse_ddll_rank0_4;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK0_5) = params->emc_pmacro_quse_ddll_rank0_5;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_0) = params->emc_pmacro_quse_ddll_rank1_0;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_1) = params->emc_pmacro_quse_ddll_rank1_1;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_2) = params->emc_pmacro_quse_ddll_rank1_2;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_3) = params->emc_pmacro_quse_ddll_rank1_3;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_4) = params->emc_pmacro_quse_ddll_rank1_4;
+ EMC(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5;
+
+ // Program outbound trimmers.
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3) = params->emc_pmacro_ob_ddll_long_dq_rank0_3;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4) = params->emc_pmacro_ob_ddll_long_dq_rank0_4;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5) = params->emc_pmacro_ob_ddll_long_dq_rank0_5;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0) = params->emc_pmacro_ob_ddll_long_dq_rank1_0;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1) = params->emc_pmacro_ob_ddll_long_dq_rank1_1;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2) = params->emc_pmacro_ob_ddll_long_dq_rank1_2;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3) = params->emc_pmacro_ob_ddll_long_dq_rank1_3;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4) = params->emc_pmacro_ob_ddll_long_dq_rank1_4;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5) = params->emc_pmacro_ob_ddll_long_dq_rank1_5;
+
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ob_ddll_long_dqs_rank0_0;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ob_ddll_long_dqs_rank0_1;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ob_ddll_long_dqs_rank0_2;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ob_ddll_long_dqs_rank0_3;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4) = params->emc_pmacro_ob_ddll_long_dqs_rank0_4;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5) = params->emc_pmacro_ob_ddll_long_dqs_rank0_5;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ob_ddll_long_dqs_rank1_0;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ob_ddll_long_dqs_rank1_1;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ob_ddll_long_dqs_rank1_2;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ob_ddll_long_dqs_rank1_3;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4) = params->emc_pmacro_ob_ddll_long_dqs_rank1_4;
+ EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5) = params->emc_pmacro_ob_ddll_long_dqs_rank1_5;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ib_ddll_long_dqs_rank0_0;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ib_ddll_long_dqs_rank0_1;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ib_ddll_long_dqs_rank0_2;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ib_ddll_long_dqs_rank0_3;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ib_ddll_long_dqs_rank1_0;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ib_ddll_long_dqs_rank1_1;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2;
+ EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3;
+
+ // Program clock trimmers.
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0;
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1;
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2;
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_3) = params->emc_pmacro_ddll_long_cmd_3;
+ EMC(EMC_PMACRO_DDLL_LONG_CMD_4) = params->emc_pmacro_ddll_long_cmd_4;
+ EMC(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0;
+ EMC(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1;
+ EMC(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2;
+
+ // Set DLL periodic offset.
+ EMC(EMC_PMACRO_DDLL_PERIODIC_OFFSET) = params->emc_pmacro_ddll_periodic_offset;
+
+ // Patch 4 using BCT spare variables.
+ if (params->emc_bct_spare4)
+ *(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5;
+
+ // Patch 4 to 6 using BCT spare secure variables.
+ if (params->emc_bct_spare_secure6)
+ *(vu32 *)params->emc_bct_spare_secure6 = params->emc_bct_spare_secure7;
+ if (params->emc_bct_spare_secure8)
+ *(vu32 *)params->emc_bct_spare_secure8 = params->emc_bct_spare_secure9;
+ if (params->emc_bct_spare_secure10)
+ *(vu32 *)params->emc_bct_spare_secure10 = params->emc_bct_spare_secure11;
+
+ // Trigger timing update so above writes take place.
+ EMC(EMC_TIMING_CONTROL) = 1;
+
+ // Initialize MC VPR settings.
+ MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom;
+ MC(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi;
+ MC(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb;
+ MC(MC_VIDEO_PROTECT_VPR_OVERRIDE) = params->mc_video_protect_vpr_override;
+ MC(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1;
+ MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = params->mc_video_protect_gpu_override0;
+ MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = params->mc_video_protect_gpu_override1;
+
+ // Program SDRAM geometry parameters.
+ MC(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg;
+ MC(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0;
+ MC(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1;
+ MC(MC_EMEM_ADR_CFG_CHANNEL_MASK) = params->mc_emem_adr_cfg_channel_mask;
+
+ // Program bank swizzling.
+ MC(MC_EMEM_ADR_CFG_BANK_MASK_0) = params->mc_emem_adr_cfg_bank_mask0;
+ MC(MC_EMEM_ADR_CFG_BANK_MASK_1) = params->mc_emem_adr_cfg_bank_mask1;
+ MC(MC_EMEM_ADR_CFG_BANK_MASK_2) = params->mc_emem_adr_cfg_bank_mask2;
+
+ // Program external memory aperture (base and size).
+ MC(MC_EMEM_CFG) = params->mc_emem_cfg;
+
+ // Program SEC carveout (base and size).
+ MC(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom;
+ MC(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi;
+ MC(MC_SEC_CARVEOUT_SIZE_MB) = params->mc_sec_carveout_size_mb;
+
+ // Program MTS carveout (base and size).
+ MC(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom;
+ MC(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi;
+ MC(MC_MTS_CARVEOUT_SIZE_MB) = params->mc_mts_carveout_size_mb;
+
+ // Program the memory arbiter.
+ MC(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg;
+ MC(MC_EMEM_ARB_OUTSTANDING_REQ) = params->mc_emem_arb_outstanding_req;
+ MC(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl;
+ MC(MC_EMEM_ARB_REFPB_BANK_CTRL) = params->emc_emem_arb_refpb_bank_ctrl;
+ MC(MC_EMEM_ARB_TIMING_RCD) = params->mc_emem_arb_timing_rcd;
+ MC(MC_EMEM_ARB_TIMING_RP) = params->mc_emem_arb_timing_rp;
+ MC(MC_EMEM_ARB_TIMING_RC) = params->mc_emem_arb_timing_rc;
+ MC(MC_EMEM_ARB_TIMING_RAS) = params->mc_emem_arb_timing_ras;
+ MC(MC_EMEM_ARB_TIMING_FAW) = params->mc_emem_arb_timing_faw;
+ MC(MC_EMEM_ARB_TIMING_RRD) = params->mc_emem_arb_timing_rrd;
+ MC(MC_EMEM_ARB_TIMING_RAP2PRE) = params->mc_emem_arb_timing_rap2pre;
+ MC(MC_EMEM_ARB_TIMING_WAP2PRE) = params->mc_emem_arb_timing_wap2pre;
+ MC(MC_EMEM_ARB_TIMING_R2R) = params->mc_emem_arb_timing_r2r;
+ MC(MC_EMEM_ARB_TIMING_W2W) = params->mc_emem_arb_timing_w2w;
+ MC(MC_EMEM_ARB_TIMING_CCDMW) = params->mc_emem_arb_timing_ccdmw;
+ MC(MC_EMEM_ARB_TIMING_R2W) = params->mc_emem_arb_timing_r2w;
+ MC(MC_EMEM_ARB_TIMING_W2R) = params->mc_emem_arb_timing_w2r;
+ MC(MC_EMEM_ARB_TIMING_RFCPB) = params->mc_emem_arb_timing_rfcpb;
+ MC(MC_EMEM_ARB_DA_TURNS) = params->mc_emem_arb_da_turns;
+ MC(MC_EMEM_ARB_DA_COVERS) = params->mc_emem_arb_da_covers;
+ MC(MC_EMEM_ARB_MISC0) = params->mc_emem_arb_misc0;
+ MC(MC_EMEM_ARB_MISC1) = params->mc_emem_arb_misc1;
+ MC(MC_EMEM_ARB_MISC2) = params->mc_emem_arb_misc2;
+ MC(MC_EMEM_ARB_RING1_THROTTLE) = params->mc_emem_arb_ring1_throttle;
+ MC(MC_EMEM_ARB_OVERRIDE) = params->mc_emem_arb_override;
+ MC(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1;
+ MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv;
+ MC(MC_DA_CONFIG0) = params->mc_da_cfg0;
+
+ // Trigger MC timing update.
+ MC(MC_TIMING_CONTROL) = 1;
+
+ // Program second-level clock enable overrides.
+ MC(MC_CLKEN_OVERRIDE) = params->mc_clken_override;
+
+ // Program statistics gathering.
+ MC(MC_STAT_CONTROL) = params->mc_stat_control;
+
+ // Program SDRAM geometry parameters.
+ EMC(EMC_ADR_CFG) = params->emc_adr_cfg;
+
+ // Program second-level clock enable overrides.
+ EMC(EMC_CLKEN_OVERRIDE) = params->emc_clken_override;
+
+ // Program EMC pad auto calibration.
+ EMC(EMC_PMACRO_AUTOCAL_CFG_0) = params->emc_pmacro_auto_cal_cfg0;
+ EMC(EMC_PMACRO_AUTOCAL_CFG_1) = params->emc_pmacro_auto_cal_cfg1;
+ EMC(EMC_PMACRO_AUTOCAL_CFG_2) = params->emc_pmacro_auto_cal_cfg2;
+
+ EMC(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0;
+ EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1;
+
+ // Program/Start auto calibration.
+ EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval;
+ EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config;
+ usleep(params->emc_auto_cal_wait);
+
+ // Patch 5 using BCT spare variables.
+ if (params->emc_bct_spare8)
+ *(vu32 *)params->emc_bct_spare8 = params->emc_bct_spare9;
+
+ EMC(EMC_AUTO_CAL_CONFIG9) = params->emc_auto_cal_config9;
+
+ // Program EMC timing configuration.
+ EMC(EMC_CFG_2) = params->emc_cfg2;
+ EMC(EMC_CFG_PIPE) = params->emc_cfg_pipe;
+ EMC(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1;
+ EMC(EMC_CFG_PIPE_2) = params->emc_cfg_pipe2;
+ EMC(EMC_CMDQ) = params->emc_cmd_q;
+ EMC(EMC_MC2EMCQ) = params->emc_mc2emc_q;
+ EMC(EMC_MRS_WAIT_CNT) = params->emc_mrs_wait_cnt;
+ EMC(EMC_MRS_WAIT_CNT2) = params->emc_mrs_wait_cnt2;
+ EMC(EMC_FBIO_CFG5) = params->emc_fbio_cfg5;
+ EMC(EMC_RC) = params->emc_rc;
+ EMC(EMC_RFC) = params->emc_rfc;
+ EMC(EMC_RFCPB) = params->emc_rfc_pb;
+ EMC(EMC_REFCTRL2) = params->emc_ref_ctrl2;
+ EMC(EMC_RFC_SLR) = params->emc_rfc_slr;
+ EMC(EMC_RAS) = params->emc_ras;
+ EMC(EMC_RP) = params->emc_rp;
+ EMC(EMC_TPPD) = params->emc_tppd;
+ EMC(EMC_CTT) = params->emc_trtm;
+ EMC(EMC_FBIO_TWTM) = params->emc_twtm;
+ EMC(EMC_FBIO_TRATM) = params->emc_tratm;
+ EMC(EMC_FBIO_TWATM) = params->emc_twatm;
+ EMC(EMC_FBIO_TR2REF) = params->emc_tr2ref;
+ EMC(EMC_R2R) = params->emc_r2r;
+ EMC(EMC_W2W) = params->emc_w2w;
+ EMC(EMC_R2W) = params->emc_r2w;
+ EMC(EMC_W2R) = params->emc_w2r;
+ EMC(EMC_R2P) = params->emc_r2p;
+ EMC(EMC_W2P) = params->emc_w2p;
+ EMC(EMC_CCDMW) = params->emc_ccdmw;
+ EMC(EMC_RD_RCD) = params->emc_rd_rcd;
+ EMC(EMC_WR_RCD) = params->emc_wr_rcd;
+ EMC(EMC_RRD) = params->emc_rrd;
+ EMC(EMC_REXT) = params->emc_rext;
+ EMC(EMC_WEXT) = params->emc_wext;
+ EMC(EMC_WDV) = params->emc_wdv;
+ EMC(EMC_WDV_CHK) = params->emc_wdv_chk;
+ EMC(EMC_WSV) = params->emc_wsv;
+ EMC(EMC_WEV) = params->emc_wev;
+ EMC(EMC_WDV_MASK) = params->emc_wdv_mask;
+ EMC(EMC_WS_DURATION) = params->emc_ws_duration;
+ EMC(EMC_WE_DURATION) = params->emc_we_duration;
+ EMC(EMC_QUSE) = params->emc_quse;
+ EMC(EMC_QUSE_WIDTH) = params->emc_quse_width;
+ EMC(EMC_IBDLY) = params->emc_ibdly;
+ EMC(EMC_OBDLY) = params->emc_obdly;
+ EMC(EMC_EINPUT) = params->emc_einput;
+ EMC(EMC_EINPUT_DURATION) = params->emc_einput_duration;
+ EMC(EMC_PUTERM_EXTRA) = params->emc_puterm_extra;
+ EMC(EMC_PUTERM_WIDTH) = params->emc_puterm_width;
+
+ EMC(EMC_DBG) = params->emc_dbg;
+
+ // Clear read fifo.
+ EMC(EMC_QRST) = params->emc_qrst;
+ EMC(EMC_ISSUE_QRST) = 1;
+ EMC(EMC_ISSUE_QRST) = 0;
+
+ // Program the rest of EMC timing configuration.
+ EMC(EMC_QSAFE) = params->emc_qsafe;
+ EMC(EMC_RDV) = params->emc_rdv;
+ EMC(EMC_RDV_MASK) = params->emc_rdv_mask;
+ EMC(EMC_RDV_EARLY) = params->emc_rdv_early;
+ EMC(EMC_RDV_EARLY_MASK) = params->emc_rdv_early_mask;
+ EMC(EMC_QPOP) = params->emc_qpop;
+ EMC(EMC_REFRESH) = params->emc_refresh;
+ EMC(EMC_BURST_REFRESH_NUM) = params->emc_burst_refresh_num;
+ EMC(EMC_PRE_REFRESH_REQ_CNT) = params->emc_prerefresh_req_cnt;
+ EMC(EMC_PDEX2WR) = params->emc_pdex2wr;
+ EMC(EMC_PDEX2RD) = params->emc_pdex2rd;
+ EMC(EMC_PCHG2PDEN) = params->emc_pchg2pden;
+ EMC(EMC_ACT2PDEN) = params->emc_act2pden;
+ EMC(EMC_AR2PDEN) = params->emc_ar2pden;
+ EMC(EMC_RW2PDEN) = params->emc_rw2pden;
+ EMC(EMC_CKE2PDEN) = params->emc_cke2pden;
+ EMC(EMC_PDEX2CKE) = params->emc_pdex2che;
+ EMC(EMC_PDEX2MRR) = params->emc_pdex2mrr;
+ EMC(EMC_TXSR) = params->emc_txsr;
+ EMC(EMC_TXSRDLL) = params->emc_txsr_dll;
+ EMC(EMC_TCKE) = params->emc_tcke;
+ EMC(EMC_TCKESR) = params->emc_tckesr;
+ EMC(EMC_TPD) = params->emc_tpd;
+ EMC(EMC_TFAW) = params->emc_tfaw;
+ EMC(EMC_TRPAB) = params->emc_trpab;
+ EMC(EMC_TCLKSTABLE) = params->emc_tclkstable;
+ EMC(EMC_TCLKSTOP) = params->emc_tclkstop;
+ EMC(EMC_TREFBW) = params->emc_trefbw;
+ EMC(EMC_ODT_WRITE) = params->emc_odt_write;
+ EMC(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll;
+ EMC(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period;
+
+ // Don't write CFG_ADR_EN (bit 1) here - lock bit written later.
+ EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD;
+ EMC(EMC_CFG_RSV) = params->emc_cfg_rsv;
+ EMC(EMC_PMC_SCRATCH1) = params->emc_pmc_scratch1;
+ EMC(EMC_PMC_SCRATCH2) = params->emc_pmc_scratch2;
+ EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3;
+ EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control;
+ EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen;
+ EMC(EMC_PMACRO_DSR_VTTGEN_CTRL0) = params->emc_pmacro_dsr_vttgen_ctrl0;
+
+ // Set pipe bypass enable bits before sending any DRAM commands.
+ EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000;
+
+ // BootROM patching is used as a generic patch here.
+ if (params->boot_rom_patch_control)
+ {
+ *(vu32 *)params->boot_rom_patch_control = params->boot_rom_patch_data;
+
+ // Trigger MC timing update.
+ MC(MC_TIMING_CONTROL) = 1;
+ }
+
+ // Patch 7 to 9 using BCT spare secure variables.
+ if (params->emc_bct_spare_secure12)
+ *(vu32 *)params->emc_bct_spare_secure12 = params->emc_bct_spare_secure13;
+ if (params->emc_bct_spare_secure14)
+ *(vu32 *)params->emc_bct_spare_secure14 = params->emc_bct_spare_secure15;
+ if (params->emc_bct_spare_secure16)
+ *(vu32 *)params->emc_bct_spare_secure16 = params->emc_bct_spare_secure17;
+
+ // Release SEL_DPD_CMD.
+ PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | PMC_IO_DPD_REQ_DPD_OFF;
+ usleep(params->pmc_io_dpd3_req_wait);
+
+ // Set transmission pad control parameters.
+ EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl;
+
+ // ZQ CAL setup (not actually issuing ZQ CAL now).
+ if (params->emc_zcal_warm_cold_boot_enables & 1)
+ {
+ EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt;
+ EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd;
+ }
+
+ // Trigger timing update so above writes take place.
+ EMC(EMC_TIMING_CONTROL) = 1;
+ usleep(params->emc_timing_control_wait);
+
+ // Deassert HOLD_CKE_LOW.
+ PMC(APBDEV_PMC_DDR_CNTRL) &= 0xFF78007F;
+ usleep(params->pmc_ddr_ctrl_wait);
+
+ // Set clock enable signal.
+ u32 pin_gpio_cfg = (params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12);
+ EMC(EMC_PIN) = pin_gpio_cfg;
+ (void)EMC(EMC_PIN);
+ usleep(params->emc_pin_extra_wait + 200);
+ EMC(EMC_PIN) = pin_gpio_cfg | 0x100;
+ (void)EMC(EMC_PIN);
+
+ usleep(params->emc_pin_extra_wait + 2000);
+
+ // Enable clock enable signal.
+ EMC(EMC_PIN) = pin_gpio_cfg | 0x101;
+ (void)EMC(EMC_PIN);
+ usleep(params->emc_pin_program_wait);
+
+ // Init zq calibration,
+ // Patch 6 using BCT spare variables.
+ if (params->emc_bct_spare10)
+ *(vu32 *)params->emc_bct_spare10 = params->emc_bct_spare11;
+
+ // Write mode registers.
+ EMC(EMC_MRW2) = params->emc_mrw2;
+ EMC(EMC_MRW) = params->emc_mrw1;
+ EMC(EMC_MRW3) = params->emc_mrw3;
+ EMC(EMC_MRW4) = params->emc_mrw4;
+ EMC(EMC_MRW6) = params->emc_mrw6;
+ EMC(EMC_MRW14) = params->emc_mrw14;
+
+ EMC(EMC_MRW8) = params->emc_mrw8;
+ EMC(EMC_MRW12) = params->emc_mrw12;
+ EMC(EMC_MRW9) = params->emc_mrw9;
+ EMC(EMC_MRW13) = params->emc_mrw13;
+
+ if (params->emc_zcal_warm_cold_boot_enables & 1)
+ {
+ // Issue ZQCAL start, device 0.
+ EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0;
+ usleep(params->emc_zcal_init_wait);
+
+ // Issue ZQCAL latch.
+ EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0 ^ 3;
+ // Same for device 1.
+ if (!(params->emc_dev_select & 2))
+ {
+ EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1;
+ usleep(params->emc_zcal_init_wait);
+ EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1 ^ 3;
+ }
+ }
+
+ // Patch 10 to 12 using BCT spare secure variables.
+ if (params->emc_bct_spare_secure18)
+ *(vu32 *)params->emc_bct_spare_secure18 = params->emc_bct_spare_secure19;
+ if (params->emc_bct_spare_secure20)
+ *(vu32 *)params->emc_bct_spare_secure20 = params->emc_bct_spare_secure21;
+ if (params->emc_bct_spare_secure22)
+ *(vu32 *)params->emc_bct_spare_secure22 = params->emc_bct_spare_secure23;
+
+ // Set package and DPD pad control.
+ PMC(APBDEV_PMC_DDR_CFG) = params->pmc_ddr_cfg;
+
+ // Start periodic ZQ calibration (LPDDRx only).
+ EMC(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval;
+ EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt;
+ EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd;
+
+ // Patch 7 using BCT spare variables.
+ if (params->emc_bct_spare12)
+ *(vu32 *)params->emc_bct_spare12 = params->emc_bct_spare13;
+
+ // Trigger timing update so above writes take place.
+ EMC(EMC_TIMING_CONTROL) = 1;
+
+ if (params->emc_extra_refresh_num)
+ EMC(EMC_REF) = ((1 << params->emc_extra_refresh_num << 8) - 253) | (params->emc_dev_select << 30);
+
+ // Enable refresh.
+ EMC(EMC_REFCTRL) = params->emc_dev_select | BIT(31);
+
+ EMC(EMC_DYN_SELF_REF_CONTROL) = params->emc_dyn_self_ref_control;
+ EMC(EMC_CFG) = params->emc_cfg;
+ EMC(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq;
+ EMC(EMC_FDPD_CTRL_CMD) = params->emc_fdpd_ctrl_cmd;
+ EMC(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl;
+
+ // Write addr swizzle lock bit.
+ EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | BIT(1);
+
+ // Re-trigger timing to latch power saving functions.
+ EMC(EMC_TIMING_CONTROL) = 1;
+
+ EMC(EMC_CFG_UPDATE) = params->emc_cfg_update;
+
+ // Enable EMC pipe clock gating.
+ EMC(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk;
+
+ // Depending on freqency, enable CMD/CLK fdpd.
+ EMC(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp;
+
+ // Set untranslated region requirements.
+ MC(MC_UNTRANSLATED_REGION_CHECK) = params->mc_untranslated_region_check;
+
+ // Lock carveouts per BCT cfg.
+ MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access;
+ MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access;
+ MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl;
+
+ // Disable write access to a bunch of EMC registers.
+ MC(MC_EMEM_CFG_ACCESS_CTRL) = 1;
+
+ // Enable arbiter.
+ SYSREG(AHB_ARBITRATION_XBAR_CTRL) = (SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF) | (params->ahb_arbitration_xbar_ctrl_meminit_done << 16);
+}
+
+static void *_sdram_get_params_t210()
+{
+ // Check if id is proper.
+ u32 dramid = fuse_read_dramid(false);
+
+ // Copy base parameters.
+ u32 *params = (u32 *)SDRAM_PARAMS_ADDR;
+ memcpy(params, &_dram_cfg_0_samsung_4gb, sizeof(sdram_params_t210_t));
+
+ // Patch parameters if needed.
+ for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210); i++)
+ if (sdram_cfg_vendor_patches_t210[i].dramcf & DRAM_ID(dramid))
+ params[sdram_cfg_vendor_patches_t210[i].offset] = sdram_cfg_vendor_patches_t210[i].val;
+
+ return (void *)params;
+}
+
+void *sdram_get_params_t210b01()
+{
+ // Check if id is proper.
+ u32 dramid = fuse_read_dramid(false);
+
+ // Copy base parameters.
+ u32 *params = (u32 *)SDRAM_PARAMS_ADDR;
+ memcpy(params, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t));
+
+ // Patch parameters if needed.
+ u8 dram_code = dram_encoding_t210b01[dramid];
+ if (!dram_code)
+ return (void *)params;
+
+ for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210b01); i++)
+ if (sdram_cfg_vendor_patches_t210b01[i].dramcf & DRAM_CC(dram_code))
+ params[sdram_cfg_vendor_patches_t210b01[i].offset] = sdram_cfg_vendor_patches_t210b01[i].val;
+
+ return (void *)params;
+}
+
+/*
+ * Function: sdram_get_params_patched
+ *
+ * This code implements a warmboot exploit. Warmboot, that is actually so hot, it burns Nvidia once again.
+ * If the boot_rom_patch_control's MSB is set, it uses it as an index to
+ * APB_MISC_BASE (u32 array) and sets it to the value of boot_rom_patch_data.
+ * (The MSB falls out when it gets multiplied by sizeof(u32)).
+ * Because the bootrom does not do any boundary checks, it lets us write anywhere and anything.
+ * Ipatch hardware let us apply 12 changes to the bootrom and can be changed any time.
+ * The first patch is not needed any more when the exploit is triggered, so we overwrite that.
+ * 0x10459E is the address where it returns an error when the signature is not valid.
+ * We change that to MOV R0, #0, so we pass the check.
+ *
+ * Note: The modulus in the header must match and validated.
+ */
+
+void *sdram_get_params_patched()
+{
+ #define IPATCH_CONFIG(addr, data) ((((addr) - 0x100000) / 2) << 16 | ((data) & 0xffff))
+ sdram_params_t210_t *sdram_params = _sdram_get_params_t210();
+
+ // Disable Warmboot signature check.
+ sdram_params->boot_rom_patch_control = BIT(31) | (((IPATCH_BASE + 4) - APB_MISC_BASE) / 4);
+ sdram_params->boot_rom_patch_data = IPATCH_CONFIG(0x10459E, 0x2000);
+/*
+ // Disable SBK lock.
+ sdram_params->emc_bct_spare8 = (IPATCH_BASE + 7 * 4);
+ sdram_params->emc_bct_spare9 = IPATCH_CONFIG(0x10210E, 0x2000);
+
+ // Disable bootrom read lock.
+ sdram_params->emc_bct_spare10 = (IPATCH_BASE + 10 * 4);
+ sdram_params->emc_bct_spare11 = IPATCH_CONFIG(0x100FDC, 0xF000);
+ sdram_params->emc_bct_spare12 = (IPATCH_BASE + 11 * 4);
+ sdram_params->emc_bct_spare13 = IPATCH_CONFIG(0x100FDE, 0xE320);
+*/
+ return (void *)sdram_params;
+}
+
+void sdram_init()
+{
+ // Disable remote sense for SD1.
+ i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0 | MAX77620_SD_CNF2_RSVD);
+
+ if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
+ {
+ const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210();
+ if (params->memory_type != MEMORY_TYPE_LPDDR4)
+ return;
+
+ // Set DRAM voltage.
+ max7762x_regulator_set_voltage(REGULATOR_SD1, 1125000); // HOS: 1.125V. Bootloader: 1.1V.
+
+ _sdram_config_t210(params);
+ }
+ else
+ {
+ const sdram_params_t210b01_t *params = (const sdram_params_t210b01_t *)sdram_get_params_t210b01();
+ if (params->memory_type != MEMORY_TYPE_LPDDR4)
+ return;
+
+ _sdram_config_t210b01(params);
+ }
+}
diff --git a/bdk/mem/sdram.h b/bdk/mem/sdram.h
new file mode 100644
index 0000000..10fb705
--- /dev/null
+++ b/bdk/mem/sdram.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2020-2024 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 .
+ */
+
+#ifndef _SDRAM_H_
+#define _SDRAM_H_
+
+#include
+
+/*
+ * Tegra X1/X1+ EMC/DRAM Bandwidth Chart:
+ *
+ * Note: Max BWbits = Hz x ddr x bus width x channels = Hz x 2 x 32 x 2.
+ * Max BWbits = Hz x ddr x bus width x channels = Hz x 2 x 64 x 1.
+ * Configurations supported: 1x32, 2x32, 1x64.
+ * x64 ram modules can be used by combining the 2 32-bit channels into one.
+ *
+ * 204.0 MHz: 3.04 <-- Tegra X1/X1+ Init/SC7 Frequency
+ * 408.0 MHz: 6.08
+ * 665.6 MHz: 9.92
+ * 800.0 MHz: 11.92 <-- Tegra X1/X1+ Nvidia OS Boot Frequency
+ * 1065.6 MHz: 15.89
+ * 1331.2 MHz: 19.84
+ * 1600.0 MHz: 23.84
+ * 1862.4 MHz: 27.75 <-- Tegra X1 Official Max Frequency
+ * 2131.2 MHz: 31.76 <-- Tegra X1+ Official Max Frequency. Not all regs have support for > 2046 MHz.
+ */
+
+enum sdram_ids_erista
+{
+ // LPDDR4 3200Mbps.
+ LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, // Die-B. (2y-01).
+ LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, // Die-M. (2y-01).
+ LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC = 2, // Die-C. (2y-01).
+
+ LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, // Die-C. (2y-01).
+
+ /*
+ * Custom hekate/L4T supported 8GB. 7 dram id can be easily applied in fuses.
+ *
+ * 4GB modules:
+ * Samsung K4FBE3D4HM-MGCH/CJ/CL. MG/TF/GF/TH/GH: Package + Temperature.
+ * Hynix H9HCNNNCPUMLXR-NME/NEE/NEI. E/I: Temperature.
+ * Hynix H54G56BYYVX046/QX046/PX046. V/Q/P: Package + Temperature.
+ */
+ LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7, // XX: CH/CJ/CL.
+};
+
+enum sdram_ids_mariko
+{
+ /*
+ * Nintendo Switch LPDRR4X generations:
+ * - 1x nm are 1st-gen
+ * - 1y nm are 2nd-gen
+ * - 1z/a nm are 3rd-gen
+ */
+
+ // LPDDR4X 4266Mbps.
+ LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 3, // Die-M. (1y-01).
+ LPDDR4X_AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 5, // Die-M. (1y-01).
+ LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 6, // Die-M. (1y-01).
+
+ // LPDDR4X 3733Mbps.
+ LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, // Die-M. (1x-03).
+ LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, // Die-M. (1x-03).
+ LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, // Die-M. (1x-03).
+ LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, // Die-E. (1x-03). D9WGB. 4266Mbps.
+
+ LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, // Die-M. (1x-03).
+ LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, // Die-M. (1x-03).
+ LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, // Die-M. (1x-03).
+ LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, // Die-E. (1x-03). D9WGB. 4266Mbps.
+
+ // LPDDR4X 4266Mbps.
+ LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, // Die-A. (1y-X03).
+ LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, // Die-A. (1y-X03).
+ LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, // Die-A. (1y-X03).
+
+ LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 20, // Die-B. (1z-01). 40% lp.
+ LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 21, // Die-B. (1z-01). 40% lp.
+ LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 22, // Die-B. (1z-01). 40% lp.
+
+ LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, // Die-A. (1y-X03).
+ LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, // Die-A. (1y-X03).
+
+ LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, // Die-F. (1y-01). D9XRR.
+ LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, // Die-F. (1y-01). D9XRR.
+ LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, // Die-F. (1y-01). D9XRR.
+
+ LPDDR4X_AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, // Die-A. (1y-X03). 2nd gen.
+
+ // Old naming scheme: H9HCNNNBKMCLXR-NEE
+ LPDDR4X_IOWA_4GB_HYNIX_H54G46CYRBX267 = 29, // Die-C. (1a-01). 61% lp.
+ LPDDR4X_HOAG_4GB_HYNIX_H54G46CYRBX267 = 30, // Die-C. (1a-01). 61% lp.
+ LPDDR4X_AULA_4GB_HYNIX_H54G46CYRBX267 = 31, // Die-C. (1a-01). 61% lp.
+
+ LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 32, // Die-B. (1a-01). D8BQM. 61% lp.
+ LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB = 33, // Die-B. (1a-01). D8BQM. 61% lp.
+ LPDDR4X_AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 34, // Die-B. (1a-01). D8BQM. 61% lp.
+};
+
+enum sdram_codes_mariko
+{
+ LPDDR4X_NO_PATCH = 0,
+ LPDDR4X_UNUSED = 0,
+
+ // LPDDR4X_4GB_SAMSUNG_K4U6E3S4AM_MGCJ DRAM IDs: 08, 12.
+ // LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLHR_NME DRAM IDs: 10, 14.
+
+ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 1, // DRAM IDs: 09, 13.
+ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE = 2, // DRAM IDs: 11, 15.
+ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 3, // DRAM IDs: 17, 19, 24.
+ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 4, // DRAM IDs: 18, 23, 28.
+ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 5, // DRAM IDs: 20, 21, 22.
+ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF = 6, // DRAM IDs: 25, 26, 27.
+ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 7, // DRAM IDs: 03, 05, 06.
+ LPDDR4X_4GB_HYNIX_H54G46CYRBX267 = 8, // DRAM IDs: 29, 30, 31.
+ LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB = 9, // DRAM IDs: 32, 33, 34.
+};
+
+void sdram_init();
+void *sdram_get_params_patched();
+void *sdram_get_params_t210b01();
+void sdram_lp0_save_params(const void *params);
+void sdram_src_pllc(bool enable);
+emc_mr_data_t sdram_read_mrx(emc_mr_t mrx);
+
+#endif
diff --git a/bdk/mem/sdram_config.inl b/bdk/mem/sdram_config.inl
new file mode 100644
index 0000000..e6d6f0b
--- /dev/null
+++ b/bdk/mem/sdram_config.inl
@@ -0,0 +1,674 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2020-2024 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 .
+ */
+
+#define DRAM_CFG_T210_SIZE 1896
+
+static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
+ /* Specifies the type of memory device */
+ .memory_type = MEMORY_TYPE_LPDDR4,
+
+ /* MC/EMC clock source configuration */
+ .pllm_input_divider = 0x00000001, // M div.
+ .pllm_feedback_divider = 0x00000022, // N div.
+ .pllm_stable_time = 0x0000012C,
+ .pllm_setup_control = 0x00000000,
+ .pllm_post_divider = 0x00000000, // P div.
+ .pllm_kcp = 0x00000000,
+ .pllm_kvco = 0x00000000,
+
+ /* Spare BCT params */
+ .emc_bct_spare0 = 0x00000000,
+ .emc_bct_spare1 = 0x00000000,
+ .emc_bct_spare2 = 0x00000000,
+ .emc_bct_spare3 = 0x00000000,
+ .emc_bct_spare4 = 0x7001BC68, // EMC_PMACRO_COMMON_PAD_TX_CTRL.
+ .emc_bct_spare5 = 0x0000000A,
+ .emc_bct_spare6 = 0x7001B404, // EMC_SWIZZLE_RANK0_BYTE0.
+ .emc_bct_spare7 = 0x76543201,
+ .emc_bct_spare8 = 0x7000E6C8, // APBDEV_PMC_WEAK_BIAS.
+ .emc_bct_spare9 = 0x00000000,
+ .emc_bct_spare10 = 0x00000000,
+ .emc_bct_spare11 = 0x00000000,
+ .emc_bct_spare12 = 0x00000000, // Used to hold EMC_PMACRO_BG_BIAS_CTRL.
+ .emc_bct_spare13 = 0x00000034,
+
+ /* EMC clock configuration */
+ .emc_clock_source = 0x40188002,
+ .emc_clock_source_dll = 0x40000000,
+
+ .clk_rst_pllm_misc20_override = 0x00000000,
+ .clk_rst_pllm_misc20_override_enable = 0x00000000,
+
+ .clear_clock2_mc1 = 0x00000000,
+
+ /* Auto-calibration of EMC pads */
+ .emc_auto_cal_interval = 0x001FFFFF,
+
+ .emc_auto_cal_config = 0xA01A51D8,
+ .emc_auto_cal_config2 = 0x05500000,
+ .emc_auto_cal_config3 = 0x00770000,
+
+ .emc_auto_cal_config4 = 0x00770000,
+ .emc_auto_cal_config5 = 0x00770000,
+ .emc_auto_cal_config6 = 0x00770000,
+ .emc_auto_cal_config7 = 0x00770000,
+ .emc_auto_cal_config8 = 0x00770000,
+
+ .emc_auto_cal_vref_sel0 = 0xB3AFA6A6,
+ .emc_auto_cal_vref_sel1 = 0x00009E3C,
+
+ .emc_auto_cal_channel = 0xC1E00303,
+
+ .emc_pmacro_auto_cal_cfg0 = 0x04040404,
+ .emc_pmacro_auto_cal_cfg1 = 0x04040404,
+ .emc_pmacro_auto_cal_cfg2 = 0x00000000,
+
+ .emc_pmacro_rx_term = 0x1F1F1F1F,
+ .emc_pmacro_dq_tx_drive = 0x1F1F1F1F,
+ .emc_pmacro_ca_tx_drive = 0x1F1F1F1F,
+ .emc_pmacro_cmd_tx_drive = 0x00001F1F,
+ .emc_pmacro_auto_cal_common = 0x00000804,
+ .emc_pmacro_zcrtl = 0x00000550,
+
+ /* Specifies the time for the calibration to stabilize (in microseconds) */
+ .emc_auto_cal_wait = 0x000001A1,
+
+ .emc_xm2_comp_pad_ctrl = 0x00000032,
+ .emc_xm2_comp_pad_ctrl2 = 0x00000000,
+ .emc_xm2_comp_pad_ctrl3 = 0x00000000,
+
+ /*
+ * DRAM size information
+ * Specifies the value for EMC_ADR_CFG
+ */
+ .emc_adr_cfg = 0x00000001, // 2 Ranks.
+
+ /*
+ * Specifies the time to wait after asserting pin
+ * CKE (in microseconds)
+ */
+ .emc_pin_program_wait = 0x00000002,
+ /* Specifies the extra delay before/after pin RESET/CKE command */
+ .emc_pin_extra_wait = 0x00000000,
+
+ .emc_pin_gpio_enable = 0x00000003,
+ .emc_pin_gpio = 0x00000003,
+
+ /* Specifies the extra delay after the first writing of EMC_TIMING_CONTROL */
+ .emc_timing_control_wait = 0x0000001E,
+
+ /* Timing parameters required for the SDRAM */
+ .emc_rc = 0x0000000D,
+ .emc_rfc = 0x00000025,
+ .emc_rfc_pb = 0x00000013,
+ .emc_ref_ctrl2 = 0x00000000,
+ .emc_rfc_slr = 0x00000000,
+ .emc_ras = 0x00000009,
+ .emc_rp = 0x00000004,
+ .emc_r2r = 0x00000000,
+ .emc_w2w = 0x00000000,
+ .emc_r2w = 0x0000000B,
+ .emc_w2r = 0x0000000D,
+ .emc_r2p = 0x00000008,
+ .emc_w2p = 0x0000000B,
+ .emc_tppd = 0x00000004,
+ .emc_ccdmw = 0x00000020,
+ .emc_rd_rcd = 0x00000006,
+ .emc_wr_rcd = 0x00000006,
+ .emc_rrd = 0x00000006,
+ .emc_rext = 0x00000003,
+ .emc_wext = 0x00000000,
+ .emc_wdv = 0x00000004,
+ .emc_wdv_chk = 0x00000006,
+ .emc_wsv = 0x00000002,
+ .emc_wev = 0x00000000,
+ .emc_wdv_mask = 0x00000004,
+ .emc_ws_duration = 0x00000008,
+ .emc_we_duration = 0x0000000D,
+ .emc_quse = 0x00000005,
+ .emc_quse_width = 0x00000006,
+ .emc_ibdly = 0x00000000,
+ .emc_obdly = 0x00000000,
+ .emc_einput = 0x00000002,
+ .emc_einput_duration = 0x0000000D,
+ .emc_puterm_extra = 0x00000000,
+ .emc_puterm_width = 0x0000000B,
+ .emc_qrst = 0x00010000,
+ .emc_qsafe = 0x00000012,
+ .emc_rdv = 0x00000014,
+ .emc_rdv_mask = 0x00000016,
+ .emc_rdv_early = 0x00000012,
+ .emc_rdv_early_mask = 0x00000014,
+ .emc_qpop = 0x0000000A,
+ .emc_refresh = 0x00000304,
+ .emc_burst_refresh_num = 0x00000000,
+ .emc_prerefresh_req_cnt = 0x000000C1,
+ .emc_pdex2wr = 0x00000008,
+ .emc_pdex2rd = 0x00000008,
+ .emc_pchg2pden = 0x00000003,
+ .emc_act2pden = 0x00000003,
+ .emc_ar2pden = 0x00000003,
+ .emc_rw2pden = 0x00000014,
+ .emc_cke2pden = 0x00000005,
+ .emc_pdex2che = 0x00000002,
+ .emc_pdex2mrr = 0x0000000D,
+ .emc_txsr = 0x00000027,
+ .emc_txsr_dll = 0x00000027,
+ .emc_tcke = 0x00000005,
+ .emc_tckesr = 0x00000005,
+ .emc_tpd = 0x00000004,
+ .emc_tfaw = 0x00000009,
+ .emc_trpab = 0x00000005,
+ .emc_tclkstable = 0x00000004,
+ .emc_tclkstop = 0x00000009,
+ .emc_trefbw = 0x0000031C,
+
+ /* FBIO configuration values */
+ .emc_fbio_cfg5 = 0x9160A00D,
+ .emc_fbio_cfg7 = 0x00003BBF,
+ .emc_fbio_cfg8 = 0x0CF30000,
+
+ /* Command mapping for CMD brick 0 */
+ .emc_cmd_mapping_cmd0_0 = 0x061B0504,
+ .emc_cmd_mapping_cmd0_1 = 0x1C070302,
+ .emc_cmd_mapping_cmd0_2 = 0x05252523,
+ .emc_cmd_mapping_cmd1_0 = 0x0A091D08,
+ .emc_cmd_mapping_cmd1_1 = 0x0D1E0B24,
+ .emc_cmd_mapping_cmd1_2 = 0x0326260C,
+ .emc_cmd_mapping_cmd2_0 = 0x231C1B02,
+ .emc_cmd_mapping_cmd2_1 = 0x05070403,
+ .emc_cmd_mapping_cmd2_2 = 0x02252506,
+ .emc_cmd_mapping_cmd3_0 = 0x0D1D0B0A,
+ .emc_cmd_mapping_cmd3_1 = 0x1E090C08,
+ .emc_cmd_mapping_cmd3_2 = 0x08262624,
+ .emc_cmd_mapping_byte = 0x9A070624,
+
+ .emc_fbio_spare = 0x00000012,
+ .emc_cfg_rsv = 0xFF00FF00,
+
+ /* MRS command values */
+ .emc_mrs = 0x00000000,
+ .emc_emrs = 0x00000000,
+ .emc_emrs2 = 0x00000000,
+ .emc_emrs3 = 0x00000000,
+ .emc_mrw1 = 0x08010004,
+ .emc_mrw2 = 0x08020000,
+ .emc_mrw3 = 0x080D0000,
+ .emc_mrw4 = 0xC0000000,
+ .emc_mrw6 = 0x08037171,
+ .emc_mrw8 = 0x080B0000,
+ .emc_mrw9 = 0x0C0E7272,
+ .emc_mrw10 = 0x00000000,
+ .emc_mrw12 = 0x0C0D0808,
+ .emc_mrw13 = 0x0C0D0000,
+ .emc_mrw14 = 0x08161414,
+ .emc_mrw_extra = 0x08010004,
+ .emc_warm_boot_mrw_extra = 0x08110000,
+ .emc_warm_boot_extramode_reg_write_enable = 0x00000001,
+ .emc_extramode_reg_write_enable = 0x00000000,
+ .emc_mrw_reset_command = 0x00000000,
+ .emc_mrw_reset_ninit_wait = 0x00000000,
+ .emc_mrs_wait_cnt = 0x00CC0015,
+ .emc_mrs_wait_cnt2 = 0x0033000A,
+
+ /* EMC miscellaneous configurations */
+ .emc_cfg = 0xF3200000,
+ .emc_cfg2 = 0x00110805,
+ .emc_cfg_pipe = 0x0FFF0FFF,
+ .emc_cfg_pipe_clk = 0x00000000,
+ .emc_fdpd_ctrl_cmd_no_ramp = 0x00000001,
+ .emc_cfg_update = 0x70000301,
+ .emc_dbg = 0x01000C00,
+ .emc_dbg_write_mux = 0x00000001,
+ .emc_cmd_q = 0x10004408,
+ .emc_mc2emc_q = 0x06000404,
+ .emc_dyn_self_ref_control = 0x80000713,
+ .ahb_arbitration_xbar_ctrl_meminit_done = 0x00000001,
+ .emc_cfg_dig_dll = 0x002C00A0,
+ .emc_cfg_dig_dll_1 = 0x00003701,
+ .emc_cfg_dig_dll_period = 0x00008000,
+ .emc_dev_select = 0x00000000, // Both Ranks.
+ .emc_sel_dpd_ctrl = 0x00040008,
+
+ /* Pads trimmer delays */
+ .emc_fdpd_ctrl_dq = 0x8020221F,
+ .emc_fdpd_ctrl_cmd = 0x0220F40F,
+ .emc_pmacro_ib_vref_dq_0 = 0x28282828,
+ .emc_pmacro_ib_vref_dq_1 = 0x28282828,
+ .emc_pmacro_ib_vref_dqs_0 = 0x11111111,
+ .emc_pmacro_ib_vref_dqs_1 = 0x11111111,
+ .emc_pmacro_ib_rxrt = 0x000000BE,
+ .emc_cfg_pipe1 = 0x0FFF0FFF,
+ .emc_cfg_pipe2 = 0x0FFF0FFF,
+
+ .emc_pmacro_quse_ddll_rank0_0 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_1 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_2 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_3 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_4 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_5 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_0 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_1 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_2 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_3 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_4 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_5 = 0x00000000,
+
+ .emc_pmacro_ob_ddll_long_dq_rank0_0 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank0_1 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank0_2 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank0_3 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank0_4 = 0x00120014,
+ .emc_pmacro_ob_ddll_long_dq_rank0_5 = 0x00140010,
+ .emc_pmacro_ob_ddll_long_dq_rank1_0 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank1_1 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank1_2 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank1_3 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank1_4 = 0x00120014,
+ .emc_pmacro_ob_ddll_long_dq_rank1_5 = 0x00140010,
+
+ .emc_pmacro_ob_ddll_long_dqs_rank0_0 = 0x002E0030,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_1 = 0x00300033,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_2 = 0x00350033,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_3 = 0x00320030,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_4 = 0x00000005,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_5 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_0 = 0x002E0030,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_1 = 0x00300033,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_2 = 0x00350033,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_3 = 0x00320030,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_4 = 0x00000005,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_5 = 0x00000000,
+
+ .emc_pmacro_ib_ddll_long_dqs_rank0_0 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank0_1 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank0_2 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank0_3 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank1_0 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank1_1 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank1_2 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank1_3 = 0x00280028,
+
+ .emc_pmacro_ddll_long_cmd_0 = 0x00140014,
+ .emc_pmacro_ddll_long_cmd_1 = 0x00120012,
+ .emc_pmacro_ddll_long_cmd_2 = 0x00100010,
+ .emc_pmacro_ddll_long_cmd_3 = 0x00140014,
+ .emc_pmacro_ddll_long_cmd_4 = 0x00000014,
+ .emc_pmacro_ddll_short_cmd_0 = 0x00000000,
+ .emc_pmacro_ddll_short_cmd_1 = 0x00000000,
+ .emc_pmacro_ddll_short_cmd_2 = 0x00000000,
+
+ /*
+ * Specifies the delay after asserting CKE pin during a WarmBoot0
+ * sequence (in microseconds)
+ */
+ .warm_boot_wait = 0x00000001,
+
+ .emc_odt_write = 0x00000000,
+
+ /* Periodic ZQ calibration */
+
+ /*
+ * Specifies the value for EMC_ZCAL_INTERVAL
+ * Value 0 disables ZQ calibration
+ */
+ .emc_zcal_interval = 0x00064000,
+ .emc_zcal_wait_cnt = 0x000900CC,
+ .emc_zcal_mrw_cmd = 0x0051004F,
+
+ /* DRAM initialization sequence flow control */
+ .emc_mrs_reset_dll = 0x00000000,
+ .emc_zcal_init_dev0 = 0x80000001,
+ .emc_zcal_init_dev1 = 0x40000001,
+ /*
+ * Specifies the wait time after programming a ZQ initialization
+ * command (in microseconds)
+ */
+ .emc_zcal_init_wait = 0x00000001,
+ /*
+ * Specifies the enable for ZQ calibration at cold boot [bit 0]
+ * and warm boot [bit 1]
+ */
+ .emc_zcal_warm_cold_boot_enables = 0x00000003,
+
+ /*
+ * Specifies the MRW command to LPDDR2 for ZQ calibration
+ * on warmboot
+ */
+ /* Is issued to both devices separately */
+ .emc_mrw_lpddr2zcal_warm_boot = 0x040A00AB,
+ /*
+ * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
+ * Is issued to both devices separately
+ */
+ .emc_zqcal_ddr3_warm_boot = 0x00000011,
+ .emc_zqcal_lpddr4_warm_boot = 0x00000001,
+
+ /*
+ * Specifies the wait time for ZQ calibration on warmboot
+ * (in microseconds)
+ */
+ .emc_zcal_warm_boot_wait = 0x00000001,
+ /*
+ * Specifies the enable for DRAM Mode Register programming
+ * at warm boot
+ */
+ .emc_mrs_warm_boot_enable = 0x00000001,
+ .emc_mrs_reset_dll_wait = 0x00000000,
+ .emc_mrs_extra = 0x00000000,
+ .emc_warm_boot_mrs_extra = 0x00000000,
+ .emc_emrs_ddr2_dll_enable = 0x00000000,
+ .emc_mrs_ddr2_dll_reset = 0x00000000,
+ .emc_emrs_ddr2_ocd_calib = 0x00000000,
+ /*
+ * Specifies the wait between initializing DDR and setting OCD
+ * calibration (in microseconds)
+ */
+ .emc_ddr2_wait = 0x00000000,
+ .emc_clken_override = 0x00000000,
+ /*
+ * Specifies LOG2 of the extra refresh numbers after booting
+ * Program 0 to disable
+ */
+ .emc_extra_refresh_num = 0x00000002,
+ .emc_clken_override_allwarm_boot = 0x00000000,
+ .mc_clken_override_allwarm_boot = 0x00000000,
+ /* Specifies digital dll period, choosing between 4 to 64 ms */
+ .emc_cfg_dig_dll_period_warm_boot = 0x00000003,
+
+ /* Pad controls */
+ .pmc_vddp_sel = 0x00000001,
+ .pmc_vddp_sel_wait = 0x00000002,
+ .pmc_ddr_pwr = 0x0000000F,
+ .pmc_ddr_cfg = 0x04220100,
+ .pmc_io_dpd3_req = 0x4FAFFFFF,
+ .pmc_io_dpd3_req_wait = 0x00000001,
+ .pmc_io_dpd4_req_wait = 0x00000002,
+ .pmc_reg_short = 0x00000000,
+ .pmc_no_io_power = 0x00000000,
+ .pmc_ddr_ctrl_wait = 0x00000000,
+ .pmc_ddr_ctrl = 0x0007FF8B,
+ .emc_acpd_control = 0x00000000,
+
+ .emc_swizzle_rank0_byte0 = 0x76543201, // Overridden to 0x76543201 by spare6/7.
+ .emc_swizzle_rank0_byte1 = 0x65324710,
+ .emc_swizzle_rank0_byte2 = 0x25763410,
+ .emc_swizzle_rank0_byte3 = 0x25673401,
+ .emc_swizzle_rank1_byte0 = 0x32647501,
+ .emc_swizzle_rank1_byte1 = 0x34567201,
+ .emc_swizzle_rank1_byte2 = 0x56742310,
+ .emc_swizzle_rank1_byte3 = 0x67324501,
+
+ .emc_txdsrvttgen = 0x00000000,
+
+ .emc_data_brlshft0 = 0x00249249,
+ .emc_data_brlshft1 = 0x00249249,
+
+ .emc_dqs_brlshft0 = 0x00000000,
+ .emc_dqs_brlshft1 = 0x00000000,
+
+ .emc_cmd_brlshft0 = 0x00000000,
+ .emc_cmd_brlshft1 = 0x00000000,
+ .emc_cmd_brlshft2 = 0x0000001B,
+ .emc_cmd_brlshft3 = 0x0000001B,
+
+ .emc_quse_brlshft0 = 0x00000000,
+ .emc_quse_brlshft1 = 0x00000000,
+ .emc_quse_brlshft2 = 0x00000000,
+ .emc_quse_brlshft3 = 0x00000000,
+
+ .emc_dll_cfg0 = 0x1F13412F,
+ .emc_dll_cfg1 = 0x00010014,
+
+ .emc_pmc_scratch1 = 0x4FAFFFFF, // APBDEV_PMC_IO_DPD3_REQ.
+ .emc_pmc_scratch2 = 0x7FFFFFFF,
+ .emc_pmc_scratch3 = 0x4006D70B, // APBDEV_PMC_DDR_CNTRL.
+
+ .emc_pmacro_pad_cfg_ctrl = 0x00020000,
+ .emc_pmacro_vttgen_ctrl0 = 0x00030808,
+ .emc_pmacro_vttgen_ctrl1 = 0x00015C00,
+ .emc_pmacro_vttgen_ctrl2 = 0x00101010,
+ .emc_pmacro_brick_ctrl_rfu1 = 0x00001600,
+ .emc_pmacro_cmd_brick_ctrl_fdpd = 0x00000000,
+ .emc_pmacro_brick_ctrl_rfu2 = 0x00000000,
+ .emc_pmacro_data_brick_ctrl_fdpd = 0x00000000,
+ .emc_pmacro_bg_bias_ctrl0 = 0x00000034,
+ .emc_pmacro_data_pad_rx_ctrl = 0x00050037,
+ .emc_pmacro_cmd_pad_rx_ctrl = 0x00000000,
+ .emc_pmacro_data_rx_term_mode = 0x00000010,
+ .emc_pmacro_cmd_rx_term_mode = 0x00003000,
+ .emc_pmacro_data_pad_tx_ctrl = 0x02000111,
+ .emc_pmacro_common_pad_tx_ctrl = 0x00000008, // Overridden to 0x0000000A by spare4/5.
+ .emc_pmacro_cmd_pad_tx_ctrl = 0x0A000000,
+
+ .emc_cfg3 = 0x00000040,
+
+ .emc_pmacro_tx_pwrd0 = 0x10000000,
+ .emc_pmacro_tx_pwrd1 = 0x08000000,
+ .emc_pmacro_tx_pwrd2 = 0x08000000,
+ .emc_pmacro_tx_pwrd3 = 0x00000000,
+ .emc_pmacro_tx_pwrd4 = 0x00000000,
+ .emc_pmacro_tx_pwrd5 = 0x00001000,
+
+ .emc_config_sample_delay = 0x00000020,
+
+ .emc_pmacro_brick_mapping0 = 0x28091081,
+ .emc_pmacro_brick_mapping1 = 0x44A53293,
+ .emc_pmacro_brick_mapping2 = 0x76678A5B,
+
+ .emc_pmacro_tx_sel_clk_src0 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src1 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src2 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src3 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src4 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src5 = 0x00000000,
+
+ .emc_pmacro_ddll_bypass = 0xEFFFEFFF,
+
+ .emc_pmacro_ddll_pwrd0 = 0xC0C0C0C0,
+ .emc_pmacro_ddll_pwrd1 = 0xC0C0C0C0,
+ .emc_pmacro_ddll_pwrd2 = 0xDCDCDCDC,
+
+ .emc_pmacro_cmd_ctrl0 = 0x0A0A0A0A,
+ .emc_pmacro_cmd_ctrl1 = 0x0A0A0A0A,
+ .emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A,
+
+ /* DRAM size information */
+ .mc_emem_adr_cfg = 0x00000001, // 2 Ranks.
+ .mc_emem_adr_cfg_dev0 = 0x00070302, // Chip 0 Density 512MB.
+ .mc_emem_adr_cfg_dev1 = 0x00070302, // Chip 1 Density 512MB.
+ .mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
+ .mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
+ .mc_emem_adr_cfg_bank_mask1 = 0x39722800,
+ .mc_emem_adr_cfg_bank_mask2 = 0x4B9C1000,
+ /*
+ * Specifies the value for MC_EMEM_CFG which holds the external memory
+ * size (in KBytes)
+ */
+ .mc_emem_cfg = 0x00001000, // 4GB total density. Max 8GB.
+
+ /* 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,
+
+ // AFI, BPMP, HC, ISP2, CCPLEX, PPCS (AHB), SATA, VI, XUSB_HOST, XUSB_DEV, ADSP, PPCS1 (AHB), DC1, SDMMC1A, SDMMC2A, SDMMC3A. Plus TSEC, NVENC.
+ .mc_video_protect_vpr_override = 0xE4FACB43, // Default: 0xE4BAC343. New: 0xE4FACB43. + TSEC, NVENC.
+ // SDMMC4A, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR. Plus TSECB, TSEC1, TSECB1.
+ .mc_video_protect_vpr_override1 = 0x0000FED3, // Default: 0x00001ED3. New: 0x0000FED3. + TSECB, TSEC1, TSECB1.
+
+ .mc_video_protect_gpu_override0 = 0x2A800000, // Default: 0x00000000. Forced to 1 by HOS Secmon.
+ .mc_video_protect_gpu_override1 = 0x00000002, // Default: 0x00000000. Forced to 0 by HOS Secmon.
+
+ .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
+};
+
+#define DCFG_OFFSET_OF(m) (OFFSET_OF(sdram_params_t210_t, m) / 4)
+static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = {
+ // Hynix timing config.
+ { 0x0000000D, DRAM_ID(LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE), DCFG_OFFSET_OF(emc_r2w) },
+ { 0x00000001, DRAM_ID(LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE), DCFG_OFFSET_OF(emc_puterm_extra) },
+ { 0x80000000, DRAM_ID(LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE), DCFG_OFFSET_OF(emc_puterm_width) },
+ { 0x00000210, DRAM_ID(LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE), DCFG_OFFSET_OF(emc_pmacro_data_rx_term_mode) },
+ { 0x00000005, DRAM_ID(LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE), DCFG_OFFSET_OF(mc_emem_arb_timing_r2w) },
+
+ // Samsung 6GB density config.
+ { 0x000C0302, DRAM_ID(LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH), DCFG_OFFSET_OF(mc_emem_adr_cfg_dev0) }, // 768MB Chip 0 density.
+ { 0x000C0302, DRAM_ID(LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH), DCFG_OFFSET_OF(mc_emem_adr_cfg_dev1) }, // 768MB Chip 1 density.
+ { 0x00001800, DRAM_ID(LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH), DCFG_OFFSET_OF(mc_emem_cfg) }, // 6GB total density. Max 8GB.
+
+ // Samsung 8GB density config.
+ { 0x0000003A, DRAM_ID(LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX), DCFG_OFFSET_OF(emc_rfc) },
+ { 0x0000001D, DRAM_ID(LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX), DCFG_OFFSET_OF(emc_rfc_pb) },
+ { 0x0000003B, DRAM_ID(LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX), DCFG_OFFSET_OF(emc_txsr) },
+ { 0x0000003B, DRAM_ID(LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX), DCFG_OFFSET_OF(emc_txsr_dll) },
+ { 0x00080302, DRAM_ID(LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX), DCFG_OFFSET_OF(mc_emem_adr_cfg_dev0) }, // 1024MB Chip 0 density.
+ { 0x00080302, DRAM_ID(LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX), DCFG_OFFSET_OF(mc_emem_adr_cfg_dev1) }, // 1024MB Chip 1 density.
+ { 0x00002000, DRAM_ID(LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX), DCFG_OFFSET_OF(mc_emem_cfg) }, // 8GB total density. Max 8GB.
+};
+#undef DCFG_OFFSET_OF
diff --git a/bdk/mem/sdram_config_t210b01.inl b/bdk/mem/sdram_config_t210b01.inl
new file mode 100644
index 0000000..3879e0c
--- /dev/null
+++ b/bdk/mem/sdram_config_t210b01.inl
@@ -0,0 +1,812 @@
+/*
+ * Copyright (c) 2020-2024 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 .
+ */
+
+#define DRAM_CFG_T210B01_SIZE 2104
+
+static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
+ /* Specifies the type of memory device */
+ .memory_type = MEMORY_TYPE_LPDDR4,
+
+ /* MC/EMC clock source configuration */
+ .pllm_input_divider = 0x00000001, // M div.
+ .pllm_feedback_divider = 0x00000022, // N div.
+ .pllm_stable_time = 0x0000012C,
+ .pllm_setup_control = 0x00000000,
+ .pllm_post_divider = 0x00000000, // P div.
+ .pllm_kcp = 0x00000000,
+ .pllm_kvco = 0x00000000,
+
+ /* Spare BCT params */
+ .emc_bct_spare0 = 0x00000000,
+ .emc_bct_spare1 = 0x00000000,
+ .emc_bct_spare2 = 0x00000000,
+ .emc_bct_spare3 = 0x00000000,
+ .emc_bct_spare4 = 0x00000000,
+ .emc_bct_spare5 = 0x00000000,
+ .emc_bct_spare6 = 0x00000000,
+ .emc_bct_spare7 = 0x00000000,
+ .emc_bct_spare8 = 0x00000000,
+ .emc_bct_spare9 = 0x00000000,
+ .emc_bct_spare10 = 0x00000000,
+ .emc_bct_spare11 = 0x00000000,
+ .emc_bct_spare12 = 0x00000000,
+ .emc_bct_spare13 = 0x00000000,
+
+ .emc_bct_spare_secure0 = 0x00000000,
+ .emc_bct_spare_secure1 = 0x00000000,
+ .emc_bct_spare_secure2 = 0x00000000,
+ .emc_bct_spare_secure3 = 0x00000000,
+ .emc_bct_spare_secure4 = 0x00000000,
+ .emc_bct_spare_secure5 = 0x00000000,
+ .emc_bct_spare_secure6 = 0x00000000,
+ .emc_bct_spare_secure7 = 0x00000000,
+ .emc_bct_spare_secure8 = 0x00000000,
+ .emc_bct_spare_secure9 = 0x00000000,
+ .emc_bct_spare_secure10 = 0x00000000,
+ .emc_bct_spare_secure11 = 0x00000000,
+ .emc_bct_spare_secure12 = 0x00000000,
+ .emc_bct_spare_secure13 = 0x00000000,
+ .emc_bct_spare_secure14 = 0x00000000,
+ .emc_bct_spare_secure15 = 0x00000000,
+ .emc_bct_spare_secure16 = 0x00000000,
+ .emc_bct_spare_secure17 = 0x00000000,
+ .emc_bct_spare_secure18 = 0x00000000,
+ .emc_bct_spare_secure19 = 0x00000000,
+ .emc_bct_spare_secure20 = 0x00000000,
+ .emc_bct_spare_secure21 = 0x00000000,
+ .emc_bct_spare_secure22 = 0x00000000,
+ .emc_bct_spare_secure23 = 0x00000000,
+
+ /* EMC clock configuration */
+ .emc_clock_source = 0x40188002,
+ .emc_clock_source_dll = 0x40000000,
+
+ .clk_rst_pllm_misc20_override = 0x00000000,
+ .clk_rst_pllm_misc20_override_enable = 0x00000000,
+
+ .clear_clock2_mc1 = 0x00000000,
+
+ /* Auto-calibration of EMC pads */
+ .emc_auto_cal_interval = 0x001FFFFF,
+
+ .emc_auto_cal_config = 0xA01A51D8,
+ .emc_auto_cal_config2 = 0x00000000,
+ .emc_auto_cal_config3 = 0x00880000,
+
+ .emc_auto_cal_config4 = 0x00880000,
+ .emc_auto_cal_config5 = 0x00001220,
+ .emc_auto_cal_config6 = 0x00880000,
+ .emc_auto_cal_config7 = 0x00880000,
+ .emc_auto_cal_config8 = 0x00880000,
+ .emc_auto_cal_config9 = 0x00000000,
+
+ .emc_auto_cal_vref_sel0 = 0xB3C5BCBC,
+ .emc_auto_cal_vref_sel1 = 0x00009E3C,
+
+ .emc_auto_cal_channel = 0xC1E00302,
+
+ .emc_pmacro_auto_cal_cfg0 = 0x04040404,
+ .emc_pmacro_auto_cal_cfg1 = 0x04040404,
+ .emc_pmacro_auto_cal_cfg2 = 0x04040404,
+
+ .emc_pmacro_rx_term = 0x3F3F3F3F,
+ .emc_pmacro_dq_tx_drive = 0x3F3F3F3F,
+ .emc_pmacro_ca_tx_drive = 0x3F3F3F3F,
+ .emc_pmacro_cmd_tx_drive = 0x00001220,
+ .emc_pmacro_auto_cal_common = 0x00000804,
+ .emc_pmacro_zcrtl = 0x00505050,
+
+ /* Specifies the time for the calibration to stabilize (in microseconds) */
+ .emc_auto_cal_wait = 0x000001A1,
+
+ .emc_xm2_comp_pad_ctrl = 0x00000030,
+ .emc_xm2_comp_pad_ctrl2 = 0x16001000,
+ .emc_xm2_comp_pad_ctrl3 = 0x00901000,
+
+ /*
+ * DRAM size information
+ * Specifies the value for EMC_ADR_CFG
+ */
+ .emc_adr_cfg = 0x00000000, // 1 Rank.
+
+ /*
+ * Specifies the time to wait after asserting pin
+ * CKE (in microseconds)
+ */
+ .emc_pin_program_wait = 0x00000002,
+ /* Specifies the extra delay before/after pin RESET/CKE command */
+ .emc_pin_extra_wait = 0x00000000,
+
+ .emc_pin_gpio_enable = 0x00000003,
+ .emc_pin_gpio = 0x00000003,
+
+ /* Specifies the extra delay after the first writing of EMC_TIMING_CONTROL */
+ .emc_timing_control_wait = 0x0000001E,
+
+ /* Timing parameters required for the SDRAM */
+ .emc_rc = 0x0000000D,
+ .emc_rfc = 0x0000003A,
+ .emc_rfc_pb = 0x0000001D,
+ .emc_ref_ctrl2 = 0x00000000,
+ .emc_rfc_slr = 0x00000000,
+ .emc_ras = 0x00000009,
+ .emc_rp = 0x00000004,
+ .emc_r2r = 0x00000000,
+ .emc_w2w = 0x00000000,
+ .emc_r2w = 0x0000000B,
+ .emc_w2r = 0x0000000D,
+ .emc_r2p = 0x00000008,
+ .emc_w2p = 0x0000000B,
+ .emc_tppd = 0x00000004,
+ .emc_trtm = 0x00000017,
+ .emc_twtm = 0x00000015,
+ .emc_tratm = 0x00000017,
+ .emc_twatm = 0x0000001B,
+ .emc_tr2ref = 0x00000000,
+ .emc_ccdmw = 0x00000020,
+ .emc_rd_rcd = 0x00000006,
+ .emc_wr_rcd = 0x00000006,
+ .emc_rrd = 0x00000006,
+ .emc_rext = 0x00000003,
+ .emc_wext = 0x00000000,
+ .emc_wdv = 0x00000004,
+ .emc_wdv_chk = 0x00000006,
+ .emc_wsv = 0x00000002,
+ .emc_wev = 0x00000000,
+ .emc_wdv_mask = 0x00000004,
+ .emc_ws_duration = 0x00000008,
+ .emc_we_duration = 0x0000000E,
+ .emc_quse = 0x00000005,
+ .emc_quse_width = 0x00000006,
+ .emc_ibdly = 0x00000000,
+ .emc_obdly = 0x00000000,
+ .emc_einput = 0x00000002,
+ .emc_einput_duration = 0x0000000D,
+ .emc_puterm_extra = 0x00000001,
+ .emc_puterm_width = 0x80000000,
+ .emc_qrst = 0x00010000,
+ .emc_qsafe = 0x00000012,
+ .emc_rdv = 0x00000018,
+ .emc_rdv_mask = 0x0000001A,
+ .emc_rdv_early = 0x00000016,
+ .emc_rdv_early_mask = 0x00000018,
+ .emc_qpop = 0x0000000A,
+ .emc_refresh = 0x00000304,
+ .emc_burst_refresh_num = 0x00000000,
+ .emc_prerefresh_req_cnt = 0x000000C1,
+ .emc_pdex2wr = 0x00000008,
+ .emc_pdex2rd = 0x00000008,
+ .emc_pchg2pden = 0x00000003,
+ .emc_act2pden = 0x0000000A,
+ .emc_ar2pden = 0x00000003,
+ .emc_rw2pden = 0x00000014,
+ .emc_cke2pden = 0x00000005,
+ .emc_pdex2che = 0x00000002,
+ .emc_pdex2mrr = 0x0000000D,
+ .emc_txsr = 0x0000003B,
+ .emc_txsr_dll = 0x0000003B,
+ .emc_tcke = 0x00000005,
+ .emc_tckesr = 0x00000005,
+ .emc_tpd = 0x00000004,
+ .emc_tfaw = 0x00000009,
+ .emc_trpab = 0x00000005,
+ .emc_tclkstable = 0x00000004,
+ .emc_tclkstop = 0x00000009,
+ .emc_trefbw = 0x0000031C,
+
+ /* FBIO configuration values */
+ .emc_fbio_cfg5 = 0x9160A00D,
+ .emc_fbio_cfg7 = 0x00003A3F,
+ .emc_fbio_cfg8 = 0x0CF30000,
+
+ /* Command mapping for CMD brick 0 */
+ .emc_cmd_mapping_cmd0_0 = 0x061B0504,
+ .emc_cmd_mapping_cmd0_1 = 0x1C070302,
+ .emc_cmd_mapping_cmd0_2 = 0x05252523,
+ .emc_cmd_mapping_cmd1_0 = 0x0A091D08,
+ .emc_cmd_mapping_cmd1_1 = 0x0D1E0B24,
+ .emc_cmd_mapping_cmd1_2 = 0x0326260C,
+ .emc_cmd_mapping_cmd2_0 = 0x231C1B02,
+ .emc_cmd_mapping_cmd2_1 = 0x05070403,
+ .emc_cmd_mapping_cmd2_2 = 0x02252506,
+ .emc_cmd_mapping_cmd3_0 = 0x0D1D0B0A,
+ .emc_cmd_mapping_cmd3_1 = 0x1E090C08,
+ .emc_cmd_mapping_cmd3_2 = 0x08262624,
+ .emc_cmd_mapping_byte = 0x9A070624,
+
+ .emc_fbio_spare = 0x00000012,
+ .emc_cfg_rsv = 0xFF00FF00,
+
+ /* MRS command values */
+ .emc_mrs = 0x00000000,
+ .emc_emrs = 0x00000000,
+ .emc_emrs2 = 0x00000000,
+ .emc_emrs3 = 0x00000000,
+ .emc_mrw1 = 0x88010004,
+ .emc_mrw2 = 0x88020000,
+ .emc_mrw3 = 0x880D0000,
+ .emc_mrw4 = 0xC0000000,
+ .emc_mrw6 = 0x88033131,
+ .emc_mrw8 = 0x880B0000,
+ .emc_mrw9 = 0x8C0E5D5D,
+ .emc_mrw10 = 0x880C5D5D,
+ .emc_mrw12 = 0x8C0D0808,
+ .emc_mrw13 = 0x8C0D0000,
+ .emc_mrw14 = 0x88161616,
+ .emc_mrw_extra = 0x88010004,
+ .emc_warm_boot_mrw_extra = 0x08110000,
+ .emc_warm_boot_extramode_reg_write_enable = 0x00000001,
+ .emc_extramode_reg_write_enable = 0x00000000,
+ .emc_mrw_reset_command = 0x00000000,
+ .emc_mrw_reset_ninit_wait = 0x00000000,
+ .emc_mrs_wait_cnt = 0x00CC0010,
+ .emc_mrs_wait_cnt2 = 0x0033000A,
+
+ /* EMC miscellaneous configurations */
+ .emc_cfg = 0xF3200000,
+ .emc_cfg2 = 0x00110825,
+ .emc_cfg_pipe = 0x0FFF0000,
+ .emc_cfg_pipe_clk = 0x00000000,
+ .emc_fdpd_ctrl_cmd_no_ramp = 0x00000001,
+ .emc_cfg_update = 0x70000301,
+ .emc_dbg = 0x01000C00,
+ .emc_dbg_write_mux = 0x00000001,
+ .emc_cmd_q = 0x10004408,
+ .emc_mc2emc_q = 0x06000404,
+ .emc_dyn_self_ref_control = 0x00000713,
+ .ahb_arbitration_xbar_ctrl_meminit_done = 0x00000001,
+ .emc_cfg_dig_dll = 0x002C00A0,
+ .emc_cfg_dig_dll_1 = 0x000F3701,
+ .emc_cfg_dig_dll_period = 0x00008000,
+ .emc_dev_select = 0x00000002, // Rank 0 only.
+ .emc_sel_dpd_ctrl = 0x0004000C,
+
+ /* Pads trimmer delays */
+ .emc_fdpd_ctrl_dq = 0x8020221F,
+ .emc_fdpd_ctrl_cmd = 0x0220F40F,
+ .emc_pmacro_ib_vref_dq_0 = 0x29292929,
+ .emc_pmacro_ib_vref_dq_1 = 0x29292929,
+ .emc_pmacro_ib_vref_dqs_0 = 0x29292929,
+ .emc_pmacro_ib_vref_dqs_1 = 0x29292929,
+ .emc_pmacro_ib_rxrt = 0x00000078,
+ .emc_cfg_pipe1 = 0x0FFF0000,
+ .emc_cfg_pipe2 = 0x00000000,
+
+ .emc_pmacro_quse_ddll_rank0_0 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_1 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_2 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_3 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_4 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank0_5 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_0 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_1 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_2 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_3 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_4 = 0x00000000,
+ .emc_pmacro_quse_ddll_rank1_5 = 0x00000000,
+
+ .emc_pmacro_ob_ddll_long_dq_rank0_0 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank0_1 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank0_2 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank0_3 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank0_4 = 0x000D0016,
+ .emc_pmacro_ob_ddll_long_dq_rank0_5 = 0x0017000B,
+ .emc_pmacro_ob_ddll_long_dq_rank1_0 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank1_1 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank1_2 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank1_3 = 0x00000000,
+ .emc_pmacro_ob_ddll_long_dq_rank1_4 = 0x000D0016,
+ .emc_pmacro_ob_ddll_long_dq_rank1_5 = 0x0017000B,
+
+ .emc_pmacro_ob_ddll_long_dqs_rank0_0 = 0x00450043,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_1 = 0x00430045,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_2 = 0x00470046,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_3 = 0x00460041,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_4 = 0x0003000C,
+ .emc_pmacro_ob_ddll_long_dqs_rank0_5 = 0x000D0000,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_0 = 0x00450043,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_1 = 0x00430045,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_2 = 0x00470046,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_3 = 0x00460041,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_4 = 0x0003000C,
+ .emc_pmacro_ob_ddll_long_dqs_rank1_5 = 0x000D0000,
+
+ .emc_pmacro_ib_ddll_long_dqs_rank0_0 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank0_1 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank0_2 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank0_3 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank1_0 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank1_1 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank1_2 = 0x00280028,
+ .emc_pmacro_ib_ddll_long_dqs_rank1_3 = 0x00280028,
+
+ .emc_pmacro_ddll_long_cmd_0 = 0x00160016,
+ .emc_pmacro_ddll_long_cmd_1 = 0x000D000D,
+ .emc_pmacro_ddll_long_cmd_2 = 0x000B000B,
+ .emc_pmacro_ddll_long_cmd_3 = 0x00170017,
+ .emc_pmacro_ddll_long_cmd_4 = 0x00000016,
+ .emc_pmacro_ddll_short_cmd_0 = 0x00000000,
+ .emc_pmacro_ddll_short_cmd_1 = 0x00000000,
+ .emc_pmacro_ddll_short_cmd_2 = 0x00000000,
+
+ .emc_pmacro_ddll_periodic_offset = 0x00000000,
+
+ /*
+ * Specifies the delay after asserting CKE pin during a WarmBoot0
+ * sequence (in microseconds)
+ */
+ .warm_boot_wait = 0x00000001,
+
+ .emc_odt_write = 0x00000000,
+
+ /* Periodic ZQ calibration */
+
+ /*
+ * Specifies the value for EMC_ZCAL_INTERVAL
+ * Value 0 disables ZQ calibration
+ */
+ .emc_zcal_interval = 0x00064000,
+ .emc_zcal_wait_cnt = 0x000900CC,
+ .emc_zcal_mrw_cmd = 0x8051004F,
+
+ /* DRAM initialization sequence flow control */
+ .emc_mrs_reset_dll = 0x00000000,
+ .emc_zcal_init_dev0 = 0x80000001,
+ .emc_zcal_init_dev1 = 0x00000000,
+ /*
+ * Specifies the wait time after programming a ZQ initialization
+ * command (in microseconds)
+ */
+ .emc_zcal_init_wait = 0x00000001,
+ /*
+ * Specifies the enable for ZQ calibration at cold boot [bit 0]
+ * and warm boot [bit 1]
+ */
+ .emc_zcal_warm_cold_boot_enables = 0x00000003,
+
+ /*
+ * Specifies the MRW command to LPDDR2 for ZQ calibration
+ * on warmboot
+ */
+ /* Is issued to both devices separately */
+ .emc_mrw_lpddr2zcal_warm_boot = 0x040A00AB,
+ /*
+ * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
+ * Is issued to both devices separately
+ */
+ .emc_zqcal_ddr3_warm_boot = 0x00000011,
+ .emc_zqcal_lpddr4_warm_boot = 0x00000001,
+
+ /*
+ * Specifies the wait time for ZQ calibration on warmboot
+ * (in microseconds)
+ */
+ .emc_zcal_warm_boot_wait = 0x00000001,
+ /*
+ * Specifies the enable for DRAM Mode Register programming
+ * at warm boot
+ */
+ .emc_mrs_warm_boot_enable = 0x00000001,
+ .emc_mrs_reset_dll_wait = 0x00000000,
+ .emc_mrs_extra = 0x00000000,
+ .emc_warm_boot_mrs_extra = 0x00000000,
+ .emc_emrs_ddr2_dll_enable = 0x00000000,
+ .emc_mrs_ddr2_dll_reset = 0x00000000,
+ .emc_emrs_ddr2_ocd_calib = 0x00000000,
+ /*
+ * Specifies the wait between initializing DDR and setting OCD
+ * calibration (in microseconds)
+ */
+ .emc_ddr2_wait = 0x00000000,
+ .emc_clken_override = 0x00000000,
+ /*
+ * Specifies LOG2 of the extra refresh numbers after booting
+ * Program 0 to disable
+ */
+ .emc_extra_refresh_num = 0x00000002,
+ .emc_clken_override_allwarm_boot = 0x00000000,
+ .mc_clken_override_allwarm_boot = 0x00000000,
+ /* Specifies digital dll period, choosing between 4 to 64 ms */
+ .emc_cfg_dig_dll_period_warm_boot = 0x00000003,
+
+ /* Pad controls */
+ .pmc_vddp_sel = 0x00000001,
+ .pmc_vddp_sel_wait = 0x00000002,
+ .pmc_ddr_cfg = 0x04220100,
+ .pmc_io_dpd3_req = 0x4FAF9FFF,
+ .pmc_io_dpd3_req_wait = 0x00000001,
+ .pmc_io_dpd4_req_wait = 0x00000002,
+ .pmc_reg_short = 0x00000000,
+ .pmc_no_io_power = 0x00000000,
+ .pmc_ddr_ctrl_wait = 0x00000000,
+ .pmc_ddr_ctrl = 0x0037FF9F,
+ .emc_acpd_control = 0x00000000,
+
+ .emc_swizzle_rank0_byte0 = 0x76543201,
+ .emc_swizzle_rank0_byte1 = 0x65324710,
+ .emc_swizzle_rank0_byte2 = 0x25763410,
+ .emc_swizzle_rank0_byte3 = 0x25673401,
+ .emc_swizzle_rank1_byte0 = 0x32647501,
+ .emc_swizzle_rank1_byte1 = 0x34567201,
+ .emc_swizzle_rank1_byte2 = 0x56742310,
+ .emc_swizzle_rank1_byte3 = 0x67324501,
+
+ .emc_txdsrvttgen = 0x00000000,
+
+ .emc_data_brlshft0 = 0x00249249,
+ .emc_data_brlshft1 = 0x00249249,
+
+ .emc_dqs_brlshft0 = 0x00000000,
+ .emc_dqs_brlshft1 = 0x00000000,
+
+ .emc_cmd_brlshft0 = 0x00000000,
+ .emc_cmd_brlshft1 = 0x00000000,
+ .emc_cmd_brlshft2 = 0x00000012,
+ .emc_cmd_brlshft3 = 0x00000012,
+
+ .emc_quse_brlshft0 = 0x00000000,
+ .emc_quse_brlshft1 = 0x00000000,
+ .emc_quse_brlshft2 = 0x00000000,
+ .emc_quse_brlshft3 = 0x00000000,
+
+ .emc_dll_cfg0 = 0x1F134120,
+ .emc_dll_cfg1 = 0x00010014,
+
+ .emc_pmc_scratch1 = 0x4FAF9FFF,
+ .emc_pmc_scratch2 = 0x7FFFFFFF,
+ .emc_pmc_scratch3 = 0x4036D71F,
+
+ .emc_pmacro_pad_cfg_ctrl = 0x00000000,
+ .emc_pmacro_vttgen_ctrl0 = 0x00090000,
+ .emc_pmacro_vttgen_ctrl1 = 0x00103400,
+ .emc_pmacro_vttgen_ctrl2 = 0x00000000,
+ .emc_pmacro_dsr_vttgen_ctrl0 = 0x00000009,
+ .emc_pmacro_brick_ctrl_rfu1 = 0x00000000,
+ .emc_pmacro_cmd_brick_ctrl_fdpd = 0x00000000,
+ .emc_pmacro_brick_ctrl_rfu2 = 0x00000000,
+ .emc_pmacro_data_brick_ctrl_fdpd = 0x00000000,
+ .emc_pmacro_bg_bias_ctrl0 = 0x00000000,
+ .emc_pmacro_data_pad_rx_ctrl = 0x05050003,
+ .emc_pmacro_cmd_pad_rx_ctrl = 0x05000000,
+ .emc_pmacro_data_rx_term_mode = 0x00000210,
+ .emc_pmacro_cmd_rx_term_mode = 0x00002000,
+ .emc_pmacro_data_pad_tx_ctrl = 0x00000421,
+ .emc_pmacro_cmd_pad_tx_ctrl = 0x00000000,
+
+ .emc_cfg3 = 0x00000040,
+
+ .emc_pmacro_tx_pwrd0 = 0x10000000,
+ .emc_pmacro_tx_pwrd1 = 0x00000000,
+ .emc_pmacro_tx_pwrd2 = 0x00000000,
+ .emc_pmacro_tx_pwrd3 = 0x00000000,
+ .emc_pmacro_tx_pwrd4 = 0x00400080,
+ .emc_pmacro_tx_pwrd5 = 0x00801004,
+
+ .emc_config_sample_delay = 0x00000020,
+
+ .emc_pmacro_brick_mapping0 = 0x28091081,
+ .emc_pmacro_brick_mapping1 = 0x44A53293,
+ .emc_pmacro_brick_mapping2 = 0x76678A5B,
+
+ .emc_pmacro_tx_sel_clk_src0 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src1 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src2 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src3 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src4 = 0x00000000,
+ .emc_pmacro_tx_sel_clk_src5 = 0x00000000,
+
+ .emc_pmacro_perbit_fgcg_ctrl0 = 0x00000000,
+ .emc_pmacro_perbit_fgcg_ctrl1 = 0x00000000,
+ .emc_pmacro_perbit_fgcg_ctrl2 = 0x00000000,
+ .emc_pmacro_perbit_fgcg_ctrl3 = 0x00000000,
+ .emc_pmacro_perbit_fgcg_ctrl4 = 0x00000000,
+ .emc_pmacro_perbit_fgcg_ctrl5 = 0x00000000,
+ .emc_pmacro_perbit_rfu_ctrl0 = 0x00000000,
+ .emc_pmacro_perbit_rfu_ctrl1 = 0x00000000,
+ .emc_pmacro_perbit_rfu_ctrl2 = 0x00000000,
+ .emc_pmacro_perbit_rfu_ctrl3 = 0x00000000,
+ .emc_pmacro_perbit_rfu_ctrl4 = 0x00000000,
+ .emc_pmacro_perbit_rfu_ctrl5 = 0x00000000,
+ .emc_pmacro_perbit_rfu1_ctrl0 = 0x00000000,
+ .emc_pmacro_perbit_rfu1_ctrl1 = 0x00000000,
+ .emc_pmacro_perbit_rfu1_ctrl2 = 0x00000000,
+ .emc_pmacro_perbit_rfu1_ctrl3 = 0x00000000,
+ .emc_pmacro_perbit_rfu1_ctrl4 = 0x00000000,
+ .emc_pmacro_perbit_rfu1_ctrl5 = 0x00000000,
+
+ .emc_pmacro_data_pi_ctrl = 0x00001010,
+ .emc_pmacro_cmd_pi_ctrl = 0x00001010,
+
+ .emc_pmacro_ddll_bypass = 0xEF00EF00,
+
+ .emc_pmacro_ddll_pwrd0 = 0x00000000,
+ .emc_pmacro_ddll_pwrd1 = 0x00000000,
+ .emc_pmacro_ddll_pwrd2 = 0x1C1C1C1C,
+
+ .emc_pmacro_cmd_ctrl0 = 0x00000000,
+ .emc_pmacro_cmd_ctrl1 = 0x00000000,
+ .emc_pmacro_cmd_ctrl2 = 0x00000000,
+
+ /* DRAM size information */
+ .mc_emem_adr_cfg = 0x00000000, // 1 Rank.
+ .mc_emem_adr_cfg_dev0 = 0x00080302, // Chip 0 Density 1024MB.
+ .mc_emem_adr_cfg_dev1 = 0x00080302, // Chip 1 Density 1024MB.
+ .mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
+ .mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
+ .mc_emem_adr_cfg_bank_mask1 = 0x39722800,
+ .mc_emem_adr_cfg_bank_mask2 = 0x4B9C1000,
+ /*
+ * Specifies the value for MC_EMEM_CFG which holds the external memory
+ * size (in KBytes)
+ */
+ .mc_emem_cfg = 0x00001000, // 4GB total density. Max 8GB.
+
+ /* MC arbitration configuration */
+ .mc_emem_arb_cfg = 0x08000001,
+ .mc_emem_arb_outstanding_req = 0x8000004C,
+ .emc_emem_arb_refpb_hp_ctrl = 0x000A1020,
+ .emc_emem_arb_refpb_bank_ctrl = 0x80001028,
+
+ .mc_emem_arb_timing_rcd = 0x00000001,
+ .mc_emem_arb_timing_rp = 0x00000000,
+ .mc_emem_arb_timing_rc = 0x00000003,
+ .mc_emem_arb_timing_ras = 0x00000001,
+ .mc_emem_arb_timing_faw = 0x00000002,
+ .mc_emem_arb_timing_rrd = 0x00000001,
+ .mc_emem_arb_timing_rap2pre = 0x00000002,
+ .mc_emem_arb_timing_wap2pre = 0x00000005,
+ .mc_emem_arb_timing_r2r = 0x00000001,
+ .mc_emem_arb_timing_w2w = 0x00000001,
+ .mc_emem_arb_timing_r2w = 0x00000004,
+ .mc_emem_arb_timing_w2r = 0x00000005,
+ .mc_emem_arb_timing_rfcpb = 0x00000007,
+
+ .mc_emem_arb_da_turns = 0x02020000,
+ .mc_emem_arb_da_covers = 0x00030201,
+ .mc_emem_arb_misc0 = 0x72A30504,
+ .mc_emem_arb_misc1 = 0x70000F0F,
+ .mc_emem_arb_misc2 = 0x00000000,
+
+ .mc_emem_arb_ring1_throttle = 0x001F0000,
+ .mc_emem_arb_override = 0x10000000,
+ .mc_emem_arb_override1 = 0x00000000,
+ .mc_emem_arb_rsv = 0xFF00FF00,
+
+ .mc_da_cfg0 = 0x00000001,
+ .mc_emem_arb_timing_ccdmw = 0x00000008,
+
+ .mc_clken_override = 0x00008000,
+
+ .mc_stat_control = 0x00000000,
+ .mc_video_protect_bom = 0xFFF00000,
+ .mc_video_protect_bom_adr_hi = 0x00000000,
+ .mc_video_protect_size_mb = 0x00000000,
+
+ // AFI, BPMP, HC, ISP2, CCPLEX, PPCS (AHB), SATA, VI, XUSB_HOST, XUSB_DEV, ADSP, PPCS1 (AHB), DC1, SDMMC1A, SDMMC2A, SDMMC3A. Plus TSEC, NVENC.
+ .mc_video_protect_vpr_override = 0xE4FACB43, // Default: 0xE4BAC343.
+ // SDMMC4A, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR. Plus SE2, SE2B and TSECB, TSEC1, TSECB1.
+ .mc_video_protect_vpr_override1 = 0x0600FED3, // Default: 0x06001ED3.
+
+ .mc_video_protect_gpu_override0 = 0x2A800000, // Default: 0x00000000. Forced to 1 by HOS Secmon.
+ .mc_video_protect_gpu_override1 = 0x00000002, // Default: 0x00000000. Forced to 0 by HOS Secmon.
+
+ .mc_sec_carveout_bom = 0xFFF00000,
+ .mc_sec_carveout_adr_hi = 0x00000000,
+ .mc_sec_carveout_size_mb = 0x00000000,
+
+ .mc_video_protect_write_access = 0x00000000,
+ .mc_sec_carveout_protect_write_access = 0x00000000,
+
+ .mc_generalized_carveout1_bom = 0x00000000,
+ .mc_generalized_carveout1_bom_hi = 0x00000000,
+ .mc_generalized_carveout1_size_128kb = 0x00000008,
+ .mc_generalized_carveout1_access0 = 0x00000000,
+ .mc_generalized_carveout1_access1 = 0x00000000,
+ .mc_generalized_carveout1_access2 = 0x00300000,
+ .mc_generalized_carveout1_access3 = 0x03000000,
+ .mc_generalized_carveout1_access4 = 0x00000000,
+ .mc_generalized_carveout1_force_internal_access0 = 0x00000000,
+ .mc_generalized_carveout1_force_internal_access1 = 0x00000000,
+ .mc_generalized_carveout1_force_internal_access2 = 0x00000000,
+ .mc_generalized_carveout1_force_internal_access3 = 0x00000000,
+ .mc_generalized_carveout1_force_internal_access4 = 0x00000000,
+ .mc_generalized_carveout1_cfg0 = 0x04000C76,
+
+ .mc_generalized_carveout2_bom = 0x00000000,
+ .mc_generalized_carveout2_bom_hi = 0x00000000,
+ .mc_generalized_carveout2_size_128kb = 0x00000002,
+ .mc_generalized_carveout2_access0 = 0x00000000,
+ .mc_generalized_carveout2_access1 = 0x00000000,
+ .mc_generalized_carveout2_access2 = 0x03000000,
+ .mc_generalized_carveout2_access3 = 0x00000000,
+ .mc_generalized_carveout2_access4 = 0x00000300,
+ .mc_generalized_carveout2_force_internal_access0 = 0x00000000,
+ .mc_generalized_carveout2_force_internal_access1 = 0x00000000,
+ .mc_generalized_carveout2_force_internal_access2 = 0x00000000,
+ .mc_generalized_carveout2_force_internal_access3 = 0x00000000,
+ .mc_generalized_carveout2_force_internal_access4 = 0x00000000,
+ .mc_generalized_carveout2_cfg0 = 0x0440167E,
+
+ .mc_generalized_carveout3_bom = 0x00000000,
+ .mc_generalized_carveout3_bom_hi = 0x00000000,
+ .mc_generalized_carveout3_size_128kb = 0x00000000,
+ .mc_generalized_carveout3_access0 = 0x00000000,
+ .mc_generalized_carveout3_access1 = 0x00000000,
+ .mc_generalized_carveout3_access2 = 0x03000000,
+ .mc_generalized_carveout3_access3 = 0x00000000,
+ .mc_generalized_carveout3_access4 = 0x00000300,
+ .mc_generalized_carveout3_force_internal_access0 = 0x00000000,
+ .mc_generalized_carveout3_force_internal_access1 = 0x00000000,
+ .mc_generalized_carveout3_force_internal_access2 = 0x00000000,
+ .mc_generalized_carveout3_force_internal_access3 = 0x00000000,
+ .mc_generalized_carveout3_force_internal_access4 = 0x00000000,
+ .mc_generalized_carveout3_cfg0 = 0x04401E7E,
+
+ .mc_generalized_carveout4_bom = 0x00000000,
+ .mc_generalized_carveout4_bom_hi = 0x00000000,
+ .mc_generalized_carveout4_size_128kb = 0x00000008,
+ .mc_generalized_carveout4_access0 = 0x00000000,
+ .mc_generalized_carveout4_access1 = 0x00000000,
+ .mc_generalized_carveout4_access2 = 0x00300000,
+ .mc_generalized_carveout4_access3 = 0x00000000,
+ .mc_generalized_carveout4_access4 = 0x000000C0,
+ .mc_generalized_carveout4_force_internal_access0 = 0x00000000,
+ .mc_generalized_carveout4_force_internal_access1 = 0x00000000,
+ .mc_generalized_carveout4_force_internal_access2 = 0x00000000,
+ .mc_generalized_carveout4_force_internal_access3 = 0x00000000,
+ .mc_generalized_carveout4_force_internal_access4 = 0x00000000,
+ .mc_generalized_carveout4_cfg0 = 0x04002446,
+
+ .mc_generalized_carveout5_bom = 0x00000000,
+ .mc_generalized_carveout5_bom_hi = 0x00000000,
+ .mc_generalized_carveout5_size_128kb = 0x00000008,
+ .mc_generalized_carveout5_access0 = 0x00000000,
+ .mc_generalized_carveout5_access1 = 0x00000000,
+ .mc_generalized_carveout5_access2 = 0x00300000,
+ .mc_generalized_carveout5_access3 = 0x00000000,
+ .mc_generalized_carveout5_access4 = 0x00000000,
+ .mc_generalized_carveout5_force_internal_access0 = 0x00000000,
+ .mc_generalized_carveout5_force_internal_access1 = 0x00000000,
+ .mc_generalized_carveout5_force_internal_access2 = 0x00000000,
+ .mc_generalized_carveout5_force_internal_access3 = 0x00000000,
+ .mc_generalized_carveout5_force_internal_access4 = 0x00000000,
+ .mc_generalized_carveout5_cfg0 = 0x04002C46,
+
+ /* Specifies enable for CA training */
+ .emc_ca_training_enable = 0x00000000,
+ /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */
+ .swizzle_rank_byte_encode = 0x000000EC,
+
+ /* Specifies enable and offset for patched boot rom write */
+ .boot_rom_patch_control = 0x00000000,
+ /* Specifies data for patched boot rom write */
+ .boot_rom_patch_data = 0x00000000,
+
+ .mc_mts_carveout_bom = 0xFFF00000,
+ .mc_mts_carveout_adr_hi = 0x00000000,
+ .mc_mts_carveout_size_mb = 0x00000000,
+ .mc_mts_carveout_reg_ctrl = 0x00000000,
+
+ /* Specifies the untranslated memory access control */
+ .mc_untranslated_region_check = 0x00000000,
+
+ /* Just a place holder for special usage when there is no BCT for certain registers */
+ .bct_na = 0x00000000,
+};
+
+#define DRAM_CC_LPDDR4X_PMACRO_IB (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ))
+
+#define DRAM_CC_LPDDR4X_PUPD_VPR (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE) | \
+ DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \
+ DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \
+ DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
+ DRAM_CC(LPDDR4X_4GB_HYNIX_H54G46CYRBX267) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB) | \
+ DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL))
+
+#define DRAM_CC_LPDDR4X_DSR (DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE) | \
+ DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \
+ DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
+ DRAM_CC(LPDDR4X_4GB_HYNIX_H54G46CYRBX267) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB) | \
+ DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL))
+
+#define DRAM_CC_LPDDR4X_QUSE (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \
+ DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \
+ DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \
+ DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
+ DRAM_CC(LPDDR4X_4GB_HYNIX_H54G46CYRBX267) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB) | \
+ DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL))
+
+#define DRAM_CC_LPDDR4X_FAW (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \
+ DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB))
+
+#define DRAM_CC_LPDDR4X_VPR (DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
+ DRAM_CC(LPDDR4X_4GB_HYNIX_H54G46CYRBX267) | \
+ DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D1NP_046_WTB) | \
+ DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL))
+
+#define DRAM_CC_LPDDR4X_8GB (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \
+ DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL))
+
+#define DCFG_OFFSET_OF(m) (OFFSET_OF(sdram_params_t210b01_t, m) / 4)
+static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
+
+ // Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ Die-M for SDEV Iowa and Hoag.
+ { 0x35353535, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_vref_dq_0) },
+ { 0x35353535, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_vref_dq_1) },
+ { 0x00100010, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_ddll_long_dqs_rank0_0) },
+ { 0x00100010, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_ddll_long_dqs_rank0_1) },
+ { 0x00100010, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_ddll_long_dqs_rank0_2) },
+ { 0x00100010, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_ddll_long_dqs_rank0_3) },
+ { 0x00100010, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_ddll_long_dqs_rank1_0) },
+ { 0x00100010, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_ddll_long_dqs_rank1_1) },
+ { 0x00100010, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_ddll_long_dqs_rank1_2) },
+ { 0x00100010, DRAM_CC_LPDDR4X_PMACRO_IB, DCFG_OFFSET_OF(emc_pmacro_ib_ddll_long_dqs_rank1_3) },
+
+ /*! Shared patched between DRAM Codes. */
+ { 0x05500000, DRAM_CC_LPDDR4X_PUPD_VPR, DCFG_OFFSET_OF(emc_auto_cal_config2) },
+ { 0xC9AFBCBC, DRAM_CC_LPDDR4X_PUPD_VPR, DCFG_OFFSET_OF(emc_auto_cal_vref_sel0) },
+
+ // Moved to default config.
+ // { 0x2A800000, DRAM_CC_LPDDR4X_PUPD_VPR, DCFG_OFFSET_OF(mc_video_protect_gpu_override0) },
+ // { 0x00000002, DRAM_CC_LPDDR4X_PUPD_VPR, DCFG_OFFSET_OF(mc_video_protect_gpu_override1) },
+
+ { 0x88161414, DRAM_CC_LPDDR4X_DSR, DCFG_OFFSET_OF(emc_mrw14) },
+ { 0x80000713, DRAM_CC_LPDDR4X_DSR, DCFG_OFFSET_OF(emc_dyn_self_ref_control) },
+
+ { 0x00000006, DRAM_CC_LPDDR4X_QUSE, DCFG_OFFSET_OF(emc_quse) },
+ { 0x00000005, DRAM_CC_LPDDR4X_QUSE, DCFG_OFFSET_OF(emc_quse_width) },
+ { 0x00000003, DRAM_CC_LPDDR4X_QUSE, DCFG_OFFSET_OF(emc_einput) },
+ { 0x0000000C, DRAM_CC_LPDDR4X_QUSE, DCFG_OFFSET_OF(emc_einput_duration) },
+
+ { 0x00000008, DRAM_CC_LPDDR4X_FAW, DCFG_OFFSET_OF(emc_tfaw) },
+ { 0x00000001, DRAM_CC_LPDDR4X_FAW, DCFG_OFFSET_OF(mc_emem_arb_timing_faw) },
+
+ // Moved to default config.
+ // { 0xE4FACB43, DRAM_CC_LPDDR4X_VPR, DCFG_OFFSET_OF(mc_video_protect_vpr_override) }, // + TSEC, NVENC.
+ // { 0x0600FED3, DRAM_CC_LPDDR4X_VPR, DCFG_OFFSET_OF(mc_video_protect_vpr_override1) }, // + TSECB, TSEC1, TSECB1.
+
+ { 0x00000001, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_adr_cfg) }, // 2 Ranks.
+ { 0x08010004, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw1) },
+ { 0x08020000, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw2) },
+ { 0x080D0000, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw3) },
+ { 0x08033131, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw6) },
+ { 0x080B0000, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw8) },
+ { 0x0C0E5D5D, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw9) },
+ { 0x080C5D5D, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw10) },
+ { 0x0C0D0808, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw12) },
+ { 0x0C0D0000, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw13) },
+ { 0x08161414, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw14) },
+ { 0x08010004, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_mrw_extra) },
+ { 0x00000000, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_dev_select) }, // Both devices.
+ { 0x0051004F, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_zcal_mrw_cmd) },
+ { 0x40000001, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_zcal_init_dev1) },
+ { 0x00000000, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_pmacro_tx_pwrd4) },
+ { 0x00001000, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(emc_pmacro_tx_pwrd5) },
+ { 0x00000001, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(mc_emem_adr_cfg) }, // 2 Ranks.
+ { 0x00002000, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(mc_emem_cfg) }, // 8GB total density. Max 8GB.
+ { 0x00000002, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(mc_emem_arb_timing_r2r) },
+ { 0x02020001, DRAM_CC_LPDDR4X_8GB, DCFG_OFFSET_OF(mc_emem_arb_da_turns) },
+};
+#undef DCFG_OFFSET_OF
diff --git a/bootloader/mem/sdram_param_t210.h b/bdk/mem/sdram_param_t210.h
similarity index 99%
rename from bootloader/mem/sdram_param_t210.h
rename to bdk/mem/sdram_param_t210.h
index d926fa4..ed3341b 100644
--- a/bootloader/mem/sdram_param_t210.h
+++ b/bdk/mem/sdram_param_t210.h
@@ -26,18 +26,18 @@
#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_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_DDR3 2
+#define MEMORY_TYPE_DDR3L 2
#define MEMORY_TYPE_LPDDR4 3
/**
* Defines the SDRAM parameter structure
*/
-typedef struct _sdram_params
+typedef struct _sdram_params_t210_t
{
/* Specifies the type of memory device */
u32 memory_type;
@@ -113,7 +113,6 @@ typedef struct _sdram_params
/* 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;
@@ -926,6 +925,6 @@ typedef struct _sdram_params
u32 mc_mts_carveout_size_mb;
/* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */
u32 mc_mts_carveout_reg_ctrl;
-} sdram_params_t;
+} sdram_params_t210_t;
#endif
diff --git a/bdk/mem/sdram_param_t210b01.h b/bdk/mem/sdram_param_t210b01.h
new file mode 100644
index 0000000..f7b956c
--- /dev/null
+++ b/bdk/mem/sdram_param_t210b01.h
@@ -0,0 +1,989 @@
+/*
+ * Copyright (c) 2020 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _SDRAM_PARAM_T210B01_H_
+#define _SDRAM_PARAM_T210B01_H_
+
+typedef struct _sdram_params_t210b01_t
+{
+ /* Specifies the type of memory device */
+ u32 memory_type;
+
+ /* MC/EMC clock source configuration */
+
+ /* Specifies the M value for PllM */
+ u32 pllm_input_divider;
+ /* Specifies the N value for PllM */
+ u32 pllm_feedback_divider;
+ /* Specifies the time to wait for PLLM to lock (in microseconds) */
+ u32 pllm_stable_time;
+ /* Specifies misc. control bits */
+ u32 pllm_setup_control;
+ /* Specifies the P value for PLLM */
+ u32 pllm_post_divider;
+ /* Specifies value for Charge Pump Gain Control */
+ u32 pllm_kcp;
+ /* Specifies VCO gain */
+ u32 pllm_kvco;
+ /* Spare BCT param */
+ u32 emc_bct_spare0;
+ /* Spare BCT param */
+ u32 emc_bct_spare1;
+ /* Spare BCT param */
+ u32 emc_bct_spare2;
+ /* Spare BCT param */
+ u32 emc_bct_spare3;
+ /* Spare BCT param */
+ u32 emc_bct_spare4;
+ /* Spare BCT param */
+ u32 emc_bct_spare5;
+ /* Spare BCT param */
+ u32 emc_bct_spare6;
+ /* Spare BCT param */
+ u32 emc_bct_spare7;
+ /* Spare BCT param */
+ u32 emc_bct_spare8;
+ /* Spare BCT param */
+ u32 emc_bct_spare9;
+ /* Spare BCT param */
+ u32 emc_bct_spare10;
+ /* Spare BCT param */
+ u32 emc_bct_spare11;
+ /* Spare BCT param */
+ u32 emc_bct_spare12;
+ /* Spare BCT param */
+ u32 emc_bct_spare13;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure0;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure1;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure2;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure3;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure4;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure5;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure6;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure7;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure8;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure9;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure10;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure11;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure12;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure13;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure14;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure15;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure16;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure17;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure18;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure19;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure20;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure21;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure22;
+ /* Spare BCT param */
+ u32 emc_bct_spare_secure23;
+
+ /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */
+ u32 emc_clock_source;
+ u32 emc_clock_source_dll;
+
+ /* Defines possible override for PLLLM_MISC2 */
+ u32 clk_rst_pllm_misc20_override;
+ /* enables override for PLLLM_MISC2 */
+ u32 clk_rst_pllm_misc20_override_enable;
+ /* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */
+ u32 clear_clock2_mc1;
+
+ /* Auto-calibration of EMC pads */
+
+ /* Specifies the value for EMC_AUTO_CAL_INTERVAL */
+ u32 emc_auto_cal_interval;
+ /*
+ * Specifies the value for EMC_AUTO_CAL_CONFIG
+ * Note: Trigger bits are set by the SDRAM code.
+ */
+ u32 emc_auto_cal_config;
+
+ /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */
+ u32 emc_auto_cal_config2;
+
+ /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */
+ u32 emc_auto_cal_config3;
+ u32 emc_auto_cal_config4;
+ u32 emc_auto_cal_config5;
+ u32 emc_auto_cal_config6;
+ u32 emc_auto_cal_config7;
+ u32 emc_auto_cal_config8;
+ u32 emc_auto_cal_config9;
+
+ /* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */
+ u32 emc_auto_cal_vref_sel0;
+ u32 emc_auto_cal_vref_sel1;
+
+ /* Specifies the value for EMC_AUTO_CAL_CHANNEL */
+ u32 emc_auto_cal_channel;
+
+ /* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */
+ u32 emc_pmacro_auto_cal_cfg0;
+ u32 emc_pmacro_auto_cal_cfg1;
+ u32 emc_pmacro_auto_cal_cfg2;
+
+ u32 emc_pmacro_rx_term;
+ u32 emc_pmacro_dq_tx_drive;
+ u32 emc_pmacro_ca_tx_drive;
+ u32 emc_pmacro_cmd_tx_drive;
+ u32 emc_pmacro_auto_cal_common;
+ u32 emc_pmacro_zcrtl;
+
+ /*
+ * Specifies the time for the calibration
+ * to stabilize (in microseconds)
+ */
+ u32 emc_auto_cal_wait;
+
+ u32 emc_xm2_comp_pad_ctrl;
+ u32 emc_xm2_comp_pad_ctrl2;
+ u32 emc_xm2_comp_pad_ctrl3;
+
+ /*
+ * DRAM size information
+ * Specifies the value for EMC_ADR_CFG
+ */
+ u32 emc_adr_cfg;
+
+ /*
+ * Specifies the time to wait after asserting pin
+ * CKE (in microseconds)
+ */
+ u32 emc_pin_program_wait;
+ /* Specifies the extra delay before/after pin RESET/CKE command */
+ u32 emc_pin_extra_wait;
+
+ u32 emc_pin_gpio_enable;
+ u32 emc_pin_gpio;
+
+ /*
+ * Specifies the extra delay after the first writing
+ * of EMC_TIMING_CONTROL
+ */
+ u32 emc_timing_control_wait;
+
+ /* Timing parameters required for the SDRAM */
+
+ /* Specifies the value for EMC_RC */
+ u32 emc_rc;
+ /* Specifies the value for EMC_RFC */
+ u32 emc_rfc;
+
+ u32 emc_rfc_pb;
+ u32 emc_ref_ctrl2;
+
+ /* Specifies the value for EMC_RFC_SLR */
+ u32 emc_rfc_slr;
+ /* Specifies the value for EMC_RAS */
+ u32 emc_ras;
+ /* Specifies the value for EMC_RP */
+ u32 emc_rp;
+ /* Specifies the value for EMC_R2R */
+ u32 emc_r2r;
+ /* Specifies the value for EMC_W2W */
+ u32 emc_w2w;
+ /* Specifies the value for EMC_R2W */
+ u32 emc_r2w;
+ /* Specifies the value for EMC_W2R */
+ u32 emc_w2r;
+ /* Specifies the value for EMC_R2P */
+ u32 emc_r2p;
+ /* Specifies the value for EMC_W2P */
+ u32 emc_w2p;
+
+ u32 emc_tppd;
+ u32 emc_trtm;
+ u32 emc_twtm;
+ u32 emc_tratm;
+ u32 emc_twatm;
+ u32 emc_tr2ref;
+ u32 emc_ccdmw;
+
+ /* Specifies the value for EMC_RD_RCD */
+ u32 emc_rd_rcd;
+ /* Specifies the value for EMC_WR_RCD */
+ u32 emc_wr_rcd;
+ /* Specifies the value for EMC_RRD */
+ u32 emc_rrd;
+ /* Specifies the value for EMC_REXT */
+ u32 emc_rext;
+ /* Specifies the value for EMC_WEXT */
+ u32 emc_wext;
+ /* Specifies the value for EMC_WDV */
+ u32 emc_wdv;
+
+ u32 emc_wdv_chk;
+ u32 emc_wsv;
+ u32 emc_wev;
+
+ /* Specifies the value for EMC_WDV_MASK */
+ u32 emc_wdv_mask;
+
+ u32 emc_ws_duration;
+ u32 emc_we_duration;
+
+ /* Specifies the value for EMC_QUSE */
+ u32 emc_quse;
+ /* Specifies the value for EMC_QUSE_WIDTH */
+ u32 emc_quse_width;
+ /* Specifies the value for EMC_IBDLY */
+ u32 emc_ibdly;
+
+ u32 emc_obdly;
+
+ /* Specifies the value for EMC_EINPUT */
+ u32 emc_einput;
+ /* Specifies the value for EMC_EINPUT_DURATION */
+ u32 emc_einput_duration;
+ /* Specifies the value for EMC_PUTERM_EXTRA */
+ u32 emc_puterm_extra;
+ /* Specifies the value for EMC_PUTERM_WIDTH */
+ u32 emc_puterm_width;
+
+ u32 emc_qrst;
+ u32 emc_qsafe;
+ u32 emc_rdv;
+ u32 emc_rdv_mask;
+
+ u32 emc_rdv_early;
+ u32 emc_rdv_early_mask;
+
+ /* Specifies the value for EMC_QPOP */
+ u32 emc_qpop;
+
+ /* Specifies the value for EMC_REFRESH */
+ u32 emc_refresh;
+ /* Specifies the value for EMC_BURST_REFRESH_NUM */
+ u32 emc_burst_refresh_num;
+ /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */
+ u32 emc_prerefresh_req_cnt;
+ /* Specifies the value for EMC_PDEX2WR */
+ u32 emc_pdex2wr;
+ /* Specifies the value for EMC_PDEX2RD */
+ u32 emc_pdex2rd;
+ /* Specifies the value for EMC_PCHG2PDEN */
+ u32 emc_pchg2pden;
+ /* Specifies the value for EMC_ACT2PDEN */
+ u32 emc_act2pden;
+ /* Specifies the value for EMC_AR2PDEN */
+ u32 emc_ar2pden;
+ /* Specifies the value for EMC_RW2PDEN */
+ u32 emc_rw2pden;
+
+ u32 emc_cke2pden;
+ u32 emc_pdex2che;
+ u32 emc_pdex2mrr;
+
+ /* Specifies the value for EMC_TXSR */
+ u32 emc_txsr;
+ /* Specifies the value for EMC_TXSRDLL */
+ u32 emc_txsr_dll;
+ /* Specifies the value for EMC_TCKE */
+ u32 emc_tcke;
+ /* Specifies the value for EMC_TCKESR */
+ u32 emc_tckesr;
+ /* Specifies the value for EMC_TPD */
+ u32 emc_tpd;
+ /* Specifies the value for EMC_TFAW */
+ u32 emc_tfaw;
+ /* Specifies the value for EMC_TRPAB */
+ u32 emc_trpab;
+ /* Specifies the value for EMC_TCLKSTABLE */
+ u32 emc_tclkstable;
+ /* Specifies the value for EMC_TCLKSTOP */
+ u32 emc_tclkstop;
+ /* Specifies the value for EMC_TREFBW */
+ u32 emc_trefbw;
+
+ /* FBIO configuration values */
+
+ /* Specifies the value for EMC_FBIO_CFG5 */
+ u32 emc_fbio_cfg5;
+ /* Specifies the value for EMC_FBIO_CFG7 */
+ u32 emc_fbio_cfg7;
+ u32 emc_fbio_cfg8;
+
+ /* Command mapping for CMD brick 0 */
+ u32 emc_cmd_mapping_cmd0_0;
+ u32 emc_cmd_mapping_cmd0_1;
+ u32 emc_cmd_mapping_cmd0_2;
+ u32 emc_cmd_mapping_cmd1_0;
+ u32 emc_cmd_mapping_cmd1_1;
+ u32 emc_cmd_mapping_cmd1_2;
+ u32 emc_cmd_mapping_cmd2_0;
+ u32 emc_cmd_mapping_cmd2_1;
+ u32 emc_cmd_mapping_cmd2_2;
+ u32 emc_cmd_mapping_cmd3_0;
+ u32 emc_cmd_mapping_cmd3_1;
+ u32 emc_cmd_mapping_cmd3_2;
+ u32 emc_cmd_mapping_byte;
+
+ /* Specifies the value for EMC_FBIO_SPARE */
+ u32 emc_fbio_spare;
+
+ /* Specifies the value for EMC_CFG_RSV */
+ u32 emc_cfg_rsv;
+
+ /* MRS command values */
+
+ /* Specifies the value for EMC_MRS */
+ u32 emc_mrs;
+ /* Specifies the MP0 command to initialize mode registers */
+ u32 emc_emrs;
+ /* Specifies the MP2 command to initialize mode registers */
+ u32 emc_emrs2;
+ /* Specifies the MP3 command to initialize mode registers */
+ u32 emc_emrs3;
+ /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */
+ u32 emc_mrw1;
+ /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */
+ u32 emc_mrw2;
+ /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */
+ u32 emc_mrw3;
+ /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */
+ u32 emc_mrw4;
+
+ /* Specifies the programming to LPDDR4 Mode Register 3 at cold boot */
+ u32 emc_mrw6;
+ /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */
+ u32 emc_mrw8;
+ /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */
+ u32 emc_mrw9;
+ /* Specifies the programming to LPDDR4 Mode Register 12 at cold boot */
+ u32 emc_mrw10;
+ /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */
+ u32 emc_mrw12;
+ /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */
+ u32 emc_mrw13;
+ /* Specifies the programming to LPDDR4 Mode Register 22 at cold boot */
+ u32 emc_mrw14;
+
+ /*
+ * Specifies the programming to extra LPDDR2 Mode Register
+ * at cold boot
+ */
+ u32 emc_mrw_extra;
+ /*
+ * Specifies the programming to extra LPDDR2 Mode Register
+ * at warm boot
+ */
+ u32 emc_warm_boot_mrw_extra;
+ /*
+ * Specify the enable of extra Mode Register programming at
+ * warm boot
+ */
+ u32 emc_warm_boot_extramode_reg_write_enable;
+ /*
+ * Specify the enable of extra Mode Register programming at
+ * cold boot
+ */
+ u32 emc_extramode_reg_write_enable;
+
+ /* Specifies the EMC_MRW reset command value */
+ u32 emc_mrw_reset_command;
+ /* Specifies the EMC Reset wait time (in microseconds) */
+ u32 emc_mrw_reset_ninit_wait;
+ /* Specifies the value for EMC_MRS_WAIT_CNT */
+ u32 emc_mrs_wait_cnt;
+ /* Specifies the value for EMC_MRS_WAIT_CNT2 */
+ u32 emc_mrs_wait_cnt2;
+
+ /* EMC miscellaneous configurations */
+
+ /* Specifies the value for EMC_CFG */
+ u32 emc_cfg;
+ /* Specifies the value for EMC_CFG_2 */
+ u32 emc_cfg2;
+ /* Specifies the pipe bypass controls */
+ u32 emc_cfg_pipe;
+
+ u32 emc_cfg_pipe_clk;
+ u32 emc_fdpd_ctrl_cmd_no_ramp;
+ u32 emc_cfg_update;
+
+ /* Specifies the value for EMC_DBG */
+ u32 emc_dbg;
+
+ u32 emc_dbg_write_mux;
+
+ /* Specifies the value for EMC_CMDQ */
+ u32 emc_cmd_q;
+ /* Specifies the value for EMC_MC2EMCQ */
+ u32 emc_mc2emc_q;
+ /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */
+ u32 emc_dyn_self_ref_control;
+
+ /* Specifies the value for MEM_INIT_DONE */
+ u32 ahb_arbitration_xbar_ctrl_meminit_done;
+
+ /* Specifies the value for EMC_CFG_DIG_DLL */
+ u32 emc_cfg_dig_dll;
+ u32 emc_cfg_dig_dll_1;
+
+ /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */
+ u32 emc_cfg_dig_dll_period;
+ /* Specifies the value of *DEV_SELECTN of various EMC registers */
+ u32 emc_dev_select;
+
+ /* Specifies the value for EMC_SEL_DPD_CTRL */
+ u32 emc_sel_dpd_ctrl;
+
+ /* Pads trimmer delays */
+ u32 emc_fdpd_ctrl_dq;
+ u32 emc_fdpd_ctrl_cmd;
+ u32 emc_pmacro_ib_vref_dq_0;
+ u32 emc_pmacro_ib_vref_dq_1;
+ u32 emc_pmacro_ib_vref_dqs_0;
+ u32 emc_pmacro_ib_vref_dqs_1;
+ u32 emc_pmacro_ib_rxrt;
+ u32 emc_cfg_pipe1;
+ u32 emc_cfg_pipe2;
+
+ /* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */
+ u32 emc_pmacro_quse_ddll_rank0_0;
+ u32 emc_pmacro_quse_ddll_rank0_1;
+ u32 emc_pmacro_quse_ddll_rank0_2;
+ u32 emc_pmacro_quse_ddll_rank0_3;
+ u32 emc_pmacro_quse_ddll_rank0_4;
+ u32 emc_pmacro_quse_ddll_rank0_5;
+ u32 emc_pmacro_quse_ddll_rank1_0;
+ u32 emc_pmacro_quse_ddll_rank1_1;
+ u32 emc_pmacro_quse_ddll_rank1_2;
+ u32 emc_pmacro_quse_ddll_rank1_3;
+ u32 emc_pmacro_quse_ddll_rank1_4;
+ u32 emc_pmacro_quse_ddll_rank1_5;
+
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_0;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_1;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_2;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_3;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_4;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_5;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_0;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_1;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_2;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_3;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_4;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_5;
+
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_0;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_1;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_2;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_3;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_4;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_5;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_0;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_1;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_2;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_3;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_4;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_5;
+
+ u32 emc_pmacro_ib_ddll_long_dqs_rank0_0;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank0_1;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank0_2;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank0_3;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank1_0;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank1_1;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank1_2;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank1_3;
+
+ u32 emc_pmacro_ddll_long_cmd_0;
+ u32 emc_pmacro_ddll_long_cmd_1;
+ u32 emc_pmacro_ddll_long_cmd_2;
+ u32 emc_pmacro_ddll_long_cmd_3;
+ u32 emc_pmacro_ddll_long_cmd_4;
+ u32 emc_pmacro_ddll_short_cmd_0;
+ u32 emc_pmacro_ddll_short_cmd_1;
+ u32 emc_pmacro_ddll_short_cmd_2;
+
+ u32 emc_pmacro_ddll_periodic_offset;
+
+ /*
+ * Specifies the delay after asserting CKE pin during a WarmBoot0
+ * sequence (in microseconds)
+ */
+ u32 warm_boot_wait;
+
+ /* Specifies the value for EMC_ODT_WRITE */
+ u32 emc_odt_write;
+
+ /* Periodic ZQ calibration */
+
+ /*
+ * Specifies the value for EMC_ZCAL_INTERVAL
+ * Value 0 disables ZQ calibration
+ */
+ u32 emc_zcal_interval;
+ /* Specifies the value for EMC_ZCAL_WAIT_CNT */
+ u32 emc_zcal_wait_cnt;
+ /* Specifies the value for EMC_ZCAL_MRW_CMD */
+ u32 emc_zcal_mrw_cmd;
+
+ /* DRAM initialization sequence flow control */
+
+ /* Specifies the MRS command value for resetting DLL */
+ u32 emc_mrs_reset_dll;
+ /* Specifies the command for ZQ initialization of device 0 */
+ u32 emc_zcal_init_dev0;
+ /* Specifies the command for ZQ initialization of device 1 */
+ u32 emc_zcal_init_dev1;
+ /*
+ * Specifies the wait time after programming a ZQ initialization
+ * command (in microseconds)
+ */
+ u32 emc_zcal_init_wait;
+ /*
+ * Specifies the enable for ZQ calibration at cold boot [bit 0]
+ * and warm boot [bit 1]
+ */
+ u32 emc_zcal_warm_cold_boot_enables;
+
+ /*
+ * Specifies the MRW command to LPDDR2 for ZQ calibration
+ * on warmboot
+ */
+ /* Is issued to both devices separately */
+ u32 emc_mrw_lpddr2zcal_warm_boot;
+ /*
+ * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot
+ * Is issued to both devices separately
+ */
+ u32 emc_zqcal_ddr3_warm_boot;
+
+ u32 emc_zqcal_lpddr4_warm_boot;
+
+ /*
+ * Specifies the wait time for ZQ calibration on warmboot
+ * (in microseconds)
+ */
+ u32 emc_zcal_warm_boot_wait;
+ /*
+ * Specifies the enable for DRAM Mode Register programming
+ * at warm boot
+ */
+ u32 emc_mrs_warm_boot_enable;
+ /*
+ * Specifies the wait time after sending an MRS DLL reset command
+ * in microseconds)
+ */
+ u32 emc_mrs_reset_dll_wait;
+ /* Specifies the extra MRS command to initialize mode registers */
+ u32 emc_mrs_extra;
+ /* Specifies the extra MRS command at warm boot */
+ u32 emc_warm_boot_mrs_extra;
+ /* Specifies the EMRS command to enable the DDR2 DLL */
+ u32 emc_emrs_ddr2_dll_enable;
+ /* Specifies the MRS command to reset the DDR2 DLL */
+ u32 emc_mrs_ddr2_dll_reset;
+ /* Specifies the EMRS command to set OCD calibration */
+ u32 emc_emrs_ddr2_ocd_calib;
+ /*
+ * Specifies the wait between initializing DDR and setting OCD
+ * calibration (in microseconds)
+ */
+ u32 emc_ddr2_wait;
+ /* Specifies the value for EMC_CLKEN_OVERRIDE */
+ u32 emc_clken_override;
+ /*
+ * Specifies LOG2 of the extra refresh numbers after booting
+ * Program 0 to disable
+ */
+ u32 emc_extra_refresh_num;
+ /* Specifies the master override for all EMC clocks */
+ u32 emc_clken_override_allwarm_boot;
+ /* Specifies the master override for all MC clocks */
+ u32 mc_clken_override_allwarm_boot;
+ /* Specifies digital dll period, choosing between 4 to 64 ms */
+ u32 emc_cfg_dig_dll_period_warm_boot;
+
+ /* Pad controls */
+
+ /* Specifies the value for PMC_VDDP_SEL */
+ u32 pmc_vddp_sel;
+ /* Specifies the wait time after programming PMC_VDDP_SEL */
+ u32 pmc_vddp_sel_wait;
+ /* Specifies the value for PMC_DDR_CFG */
+ u32 pmc_ddr_cfg;
+ /* Specifies the value for PMC_IO_DPD3_REQ */
+ u32 pmc_io_dpd3_req;
+ /* Specifies the wait time after programming PMC_IO_DPD3_REQ */
+ u32 pmc_io_dpd3_req_wait;
+
+ u32 pmc_io_dpd4_req_wait;
+
+ /* Specifies the value for PMC_REG_SHORT */
+ u32 pmc_reg_short;
+ /* Specifies the value for PMC_NO_IOPOWER */
+ u32 pmc_no_io_power;
+
+ u32 pmc_ddr_ctrl_wait;
+ u32 pmc_ddr_ctrl;
+
+ /* Specifies the value for EMC_ACPD_CONTROL */
+ u32 emc_acpd_control;
+
+ /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */
+ u32 emc_swizzle_rank0_byte0;
+ /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */
+ u32 emc_swizzle_rank0_byte1;
+ /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */
+ u32 emc_swizzle_rank0_byte2;
+ /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */
+ u32 emc_swizzle_rank0_byte3;
+ /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */
+ u32 emc_swizzle_rank1_byte0;
+ /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */
+ u32 emc_swizzle_rank1_byte1;
+ /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */
+ u32 emc_swizzle_rank1_byte2;
+ /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */
+ u32 emc_swizzle_rank1_byte3;
+
+ /* Specifies the value for EMC_TXDSRVTTGEN */
+ u32 emc_txdsrvttgen;
+
+ /* Specifies the value for EMC_DATA_BRLSHFT_0 */
+ u32 emc_data_brlshft0;
+ u32 emc_data_brlshft1;
+
+ u32 emc_dqs_brlshft0;
+ u32 emc_dqs_brlshft1;
+
+ u32 emc_cmd_brlshft0;
+ u32 emc_cmd_brlshft1;
+ u32 emc_cmd_brlshft2;
+ u32 emc_cmd_brlshft3;
+
+ u32 emc_quse_brlshft0;
+ u32 emc_quse_brlshft1;
+ u32 emc_quse_brlshft2;
+ u32 emc_quse_brlshft3;
+
+ u32 emc_dll_cfg0;
+ u32 emc_dll_cfg1;
+
+ u32 emc_pmc_scratch1;
+ u32 emc_pmc_scratch2;
+ u32 emc_pmc_scratch3;
+
+ u32 emc_pmacro_pad_cfg_ctrl;
+
+ u32 emc_pmacro_vttgen_ctrl0;
+ u32 emc_pmacro_vttgen_ctrl1;
+ u32 emc_pmacro_vttgen_ctrl2;
+ u32 emc_pmacro_dsr_vttgen_ctrl0;
+ u32 emc_pmacro_brick_ctrl_rfu1;
+ u32 emc_pmacro_cmd_brick_ctrl_fdpd;
+ u32 emc_pmacro_brick_ctrl_rfu2;
+ u32 emc_pmacro_data_brick_ctrl_fdpd;
+ u32 emc_pmacro_bg_bias_ctrl0;
+ u32 emc_pmacro_data_pad_rx_ctrl;
+ u32 emc_pmacro_cmd_pad_rx_ctrl;
+ u32 emc_pmacro_data_rx_term_mode;
+ u32 emc_pmacro_cmd_rx_term_mode;
+ u32 emc_pmacro_data_pad_tx_ctrl;
+ u32 emc_pmacro_cmd_pad_tx_ctrl;
+ u32 emc_cfg3;
+
+ u32 emc_pmacro_tx_pwrd0;
+ u32 emc_pmacro_tx_pwrd1;
+ u32 emc_pmacro_tx_pwrd2;
+ u32 emc_pmacro_tx_pwrd3;
+ u32 emc_pmacro_tx_pwrd4;
+ u32 emc_pmacro_tx_pwrd5;
+
+ u32 emc_config_sample_delay;
+
+ u32 emc_pmacro_brick_mapping0;
+ u32 emc_pmacro_brick_mapping1;
+ u32 emc_pmacro_brick_mapping2;
+
+ u32 emc_pmacro_tx_sel_clk_src0;
+ u32 emc_pmacro_tx_sel_clk_src1;
+ u32 emc_pmacro_tx_sel_clk_src2;
+ u32 emc_pmacro_tx_sel_clk_src3;
+ u32 emc_pmacro_tx_sel_clk_src4;
+ u32 emc_pmacro_tx_sel_clk_src5;
+
+ u32 emc_pmacro_perbit_fgcg_ctrl0;
+ u32 emc_pmacro_perbit_fgcg_ctrl1;
+ u32 emc_pmacro_perbit_fgcg_ctrl2;
+ u32 emc_pmacro_perbit_fgcg_ctrl3;
+ u32 emc_pmacro_perbit_fgcg_ctrl4;
+ u32 emc_pmacro_perbit_fgcg_ctrl5;
+ u32 emc_pmacro_perbit_rfu_ctrl0;
+ u32 emc_pmacro_perbit_rfu_ctrl1;
+ u32 emc_pmacro_perbit_rfu_ctrl2;
+ u32 emc_pmacro_perbit_rfu_ctrl3;
+ u32 emc_pmacro_perbit_rfu_ctrl4;
+ u32 emc_pmacro_perbit_rfu_ctrl5;
+ u32 emc_pmacro_perbit_rfu1_ctrl0;
+ u32 emc_pmacro_perbit_rfu1_ctrl1;
+ u32 emc_pmacro_perbit_rfu1_ctrl2;
+ u32 emc_pmacro_perbit_rfu1_ctrl3;
+ u32 emc_pmacro_perbit_rfu1_ctrl4;
+ u32 emc_pmacro_perbit_rfu1_ctrl5;
+
+ u32 emc_pmacro_data_pi_ctrl;
+ u32 emc_pmacro_cmd_pi_ctrl;
+
+ u32 emc_pmacro_ddll_bypass;
+
+ u32 emc_pmacro_ddll_pwrd0;
+ u32 emc_pmacro_ddll_pwrd1;
+ u32 emc_pmacro_ddll_pwrd2;
+
+ u32 emc_pmacro_cmd_ctrl0;
+ u32 emc_pmacro_cmd_ctrl1;
+ u32 emc_pmacro_cmd_ctrl2;
+
+ /* DRAM size information */
+
+ /* Specifies the value for MC_EMEM_ADR_CFG */
+ u32 mc_emem_adr_cfg;
+ /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */
+ u32 mc_emem_adr_cfg_dev0;
+ /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */
+ u32 mc_emem_adr_cfg_dev1;
+
+ u32 mc_emem_adr_cfg_channel_mask;
+
+ /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */
+ u32 mc_emem_adr_cfg_bank_mask0;
+ /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */
+ u32 mc_emem_adr_cfg_bank_mask1;
+ /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */
+ u32 mc_emem_adr_cfg_bank_mask2;
+
+ /*
+ * Specifies the value for MC_EMEM_CFG which holds the external memory
+ * size (in KBytes)
+ */
+ u32 mc_emem_cfg;
+
+ /* MC arbitration configuration */
+
+ /* Specifies the value for MC_EMEM_ARB_CFG */
+ u32 mc_emem_arb_cfg;
+ /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */
+ u32 mc_emem_arb_outstanding_req;
+
+ u32 emc_emem_arb_refpb_hp_ctrl;
+ u32 emc_emem_arb_refpb_bank_ctrl;
+
+ /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */
+ u32 mc_emem_arb_timing_rcd;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_RP */
+ u32 mc_emem_arb_timing_rp;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_RC */
+ u32 mc_emem_arb_timing_rc;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */
+ u32 mc_emem_arb_timing_ras;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */
+ u32 mc_emem_arb_timing_faw;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */
+ u32 mc_emem_arb_timing_rrd;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */
+ u32 mc_emem_arb_timing_rap2pre;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */
+ u32 mc_emem_arb_timing_wap2pre;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */
+ u32 mc_emem_arb_timing_r2r;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */
+ u32 mc_emem_arb_timing_w2w;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */
+ u32 mc_emem_arb_timing_r2w;
+ /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */
+ u32 mc_emem_arb_timing_w2r;
+
+ u32 mc_emem_arb_timing_rfcpb;
+
+ /* Specifies the value for MC_EMEM_ARB_DA_TURNS */
+ u32 mc_emem_arb_da_turns;
+ /* Specifies the value for MC_EMEM_ARB_DA_COVERS */
+ u32 mc_emem_arb_da_covers;
+ /* Specifies the value for MC_EMEM_ARB_MISC0 */
+ u32 mc_emem_arb_misc0;
+ /* Specifies the value for MC_EMEM_ARB_MISC1 */
+ u32 mc_emem_arb_misc1;
+ u32 mc_emem_arb_misc2;
+
+ /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */
+ u32 mc_emem_arb_ring1_throttle;
+ /* Specifies the value for MC_EMEM_ARB_OVERRIDE */
+ u32 mc_emem_arb_override;
+ /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */
+ u32 mc_emem_arb_override1;
+ /* Specifies the value for MC_EMEM_ARB_RSV */
+ u32 mc_emem_arb_rsv;
+
+ u32 mc_da_cfg0;
+ u32 mc_emem_arb_timing_ccdmw;
+
+ /* Specifies the value for MC_CLKEN_OVERRIDE */
+ u32 mc_clken_override;
+
+ /* Specifies the value for MC_STAT_CONTROL */
+ u32 mc_stat_control;
+ /* Specifies the value for MC_VIDEO_PROTECT_BOM */
+ u32 mc_video_protect_bom;
+ /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */
+ u32 mc_video_protect_bom_adr_hi;
+ /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */
+ u32 mc_video_protect_size_mb;
+ /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */
+ u32 mc_video_protect_vpr_override;
+ /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */
+ u32 mc_video_protect_vpr_override1;
+ /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */
+ u32 mc_video_protect_gpu_override0;
+ /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */
+ u32 mc_video_protect_gpu_override1;
+ /* Specifies the value for MC_SEC_CARVEOUT_BOM */
+ u32 mc_sec_carveout_bom;
+ /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */
+ u32 mc_sec_carveout_adr_hi;
+ /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */
+ u32 mc_sec_carveout_size_mb;
+ /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */
+ u32 mc_video_protect_write_access;
+ /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */
+ u32 mc_sec_carveout_protect_write_access;
+
+ u32 mc_generalized_carveout1_bom;
+ u32 mc_generalized_carveout1_bom_hi;
+ u32 mc_generalized_carveout1_size_128kb;
+ u32 mc_generalized_carveout1_access0;
+ u32 mc_generalized_carveout1_access1;
+ u32 mc_generalized_carveout1_access2;
+ u32 mc_generalized_carveout1_access3;
+ u32 mc_generalized_carveout1_access4;
+ u32 mc_generalized_carveout1_force_internal_access0;
+ u32 mc_generalized_carveout1_force_internal_access1;
+ u32 mc_generalized_carveout1_force_internal_access2;
+ u32 mc_generalized_carveout1_force_internal_access3;
+ u32 mc_generalized_carveout1_force_internal_access4;
+ u32 mc_generalized_carveout1_cfg0;
+
+ u32 mc_generalized_carveout2_bom;
+ u32 mc_generalized_carveout2_bom_hi;
+ u32 mc_generalized_carveout2_size_128kb;
+ u32 mc_generalized_carveout2_access0;
+ u32 mc_generalized_carveout2_access1;
+ u32 mc_generalized_carveout2_access2;
+ u32 mc_generalized_carveout2_access3;
+ u32 mc_generalized_carveout2_access4;
+ u32 mc_generalized_carveout2_force_internal_access0;
+ u32 mc_generalized_carveout2_force_internal_access1;
+ u32 mc_generalized_carveout2_force_internal_access2;
+ u32 mc_generalized_carveout2_force_internal_access3;
+ u32 mc_generalized_carveout2_force_internal_access4;
+ u32 mc_generalized_carveout2_cfg0;
+
+ u32 mc_generalized_carveout3_bom;
+ u32 mc_generalized_carveout3_bom_hi;
+ u32 mc_generalized_carveout3_size_128kb;
+ u32 mc_generalized_carveout3_access0;
+ u32 mc_generalized_carveout3_access1;
+ u32 mc_generalized_carveout3_access2;
+ u32 mc_generalized_carveout3_access3;
+ u32 mc_generalized_carveout3_access4;
+ u32 mc_generalized_carveout3_force_internal_access0;
+ u32 mc_generalized_carveout3_force_internal_access1;
+ u32 mc_generalized_carveout3_force_internal_access2;
+ u32 mc_generalized_carveout3_force_internal_access3;
+ u32 mc_generalized_carveout3_force_internal_access4;
+ u32 mc_generalized_carveout3_cfg0;
+
+ u32 mc_generalized_carveout4_bom;
+ u32 mc_generalized_carveout4_bom_hi;
+ u32 mc_generalized_carveout4_size_128kb;
+ u32 mc_generalized_carveout4_access0;
+ u32 mc_generalized_carveout4_access1;
+ u32 mc_generalized_carveout4_access2;
+ u32 mc_generalized_carveout4_access3;
+ u32 mc_generalized_carveout4_access4;
+ u32 mc_generalized_carveout4_force_internal_access0;
+ u32 mc_generalized_carveout4_force_internal_access1;
+ u32 mc_generalized_carveout4_force_internal_access2;
+ u32 mc_generalized_carveout4_force_internal_access3;
+ u32 mc_generalized_carveout4_force_internal_access4;
+ u32 mc_generalized_carveout4_cfg0;
+
+ u32 mc_generalized_carveout5_bom;
+ u32 mc_generalized_carveout5_bom_hi;
+ u32 mc_generalized_carveout5_size_128kb;
+ u32 mc_generalized_carveout5_access0;
+ u32 mc_generalized_carveout5_access1;
+ u32 mc_generalized_carveout5_access2;
+ u32 mc_generalized_carveout5_access3;
+ u32 mc_generalized_carveout5_access4;
+ u32 mc_generalized_carveout5_force_internal_access0;
+ u32 mc_generalized_carveout5_force_internal_access1;
+ u32 mc_generalized_carveout5_force_internal_access2;
+ u32 mc_generalized_carveout5_force_internal_access3;
+ u32 mc_generalized_carveout5_force_internal_access4;
+ u32 mc_generalized_carveout5_cfg0;
+
+ /* Specifies enable for CA training */
+ u32 emc_ca_training_enable;
+ /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */
+ u32 swizzle_rank_byte_encode;
+ /* Specifies enable and offset for patched boot rom write */
+ u32 boot_rom_patch_control;
+ /* Specifies data for patched boot rom write */
+ u32 boot_rom_patch_data;
+
+ /* Specifies the value for MC_MTS_CARVEOUT_BOM */
+ u32 mc_mts_carveout_bom;
+ /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */
+ u32 mc_mts_carveout_adr_hi;
+ /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */
+ u32 mc_mts_carveout_size_mb;
+ /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */
+ u32 mc_mts_carveout_reg_ctrl;
+
+ /* Specifies the clients that are allowed to access untranslated memory */
+ u32 mc_untranslated_region_check;
+
+ /* Just a place holder for special usage when there is no BCT for certain registers */
+ u32 bct_na;
+} sdram_params_t210b01_t;
+
+#endif
diff --git a/bdk/mem/smmu.c b/bdk/mem/smmu.c
new file mode 100644
index 0000000..65b85aa
--- /dev/null
+++ b/bdk/mem/smmu.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2018 balika011
+ * Copyright (c) 2018-2024 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 .
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*! SMMU register defines */
+#define SMMU_ASID(asid) (((asid) << 24u) | ((asid) << 16u) | ((asid) << 8u) | (asid))
+#define SMMU_ENABLE BIT(31)
+#define SMMU_TLB_ACTIVE_LINES(l) ((l) << 0u)
+#define SMMU_TLB_RR_ARBITRATION BIT(28)
+#define SMMU_TLB_HIT_UNDER_MISS BIT(29)
+#define SMMU_TLB_STATS_ENABLE BIT(31)
+#define SMUU_PTC_INDEX_MAP(m) ((m) << 0u)
+#define SMUU_PTC_LINE_MASK(m) ((m) << 8u)
+#define SMUU_PTC_REQ_LIMIT(l) ((l) << 24u)
+#define SMUU_PTC_CACHE_ENABLE BIT(29)
+#define SMUU_PTC_STATS_ENABLE BIT(31)
+
+/*! Page table defines */
+#define SMMU_4MB_REGION 0
+#define SMMU_PAGE_TABLE 1
+#define SMMU_PDIR_COUNT 1024
+#define SMMU_PTBL_COUNT 1024
+#define SMMU_PAGE_SHIFT 12u
+#define SMMU_PTN_SHIFT SMMU_PAGE_SHIFT
+#define SMMU_PDN_SHIFT 22u
+#define SMMU_ADDR_TO_PFN(addr) ((addr) >> SMMU_PAGE_SHIFT)
+#define SMMU_ADDR_TO_PTN(addr) ((addr) >> SMMU_PTN_SHIFT)
+#define SMMU_ADDR_TO_PDN(addr) ((addr) >> SMMU_PDN_SHIFT)
+#define SMMU_PTN_TO_ADDR(ptn) ((ptn) << SMMU_PTN_SHIFT)
+#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << SMMU_PDN_SHIFT)
+#define SMMU_PTB(page, attr) (((attr) << 29u) | ((page) >> SMMU_PAGE_SHIFT))
+
+static void *smmu_heap = (void *)SMMU_HEAP_ADDR;
+
+// Enabling SMMU requires a TZ (EL3) secure write. MC(MC_SMMU_CONFIG) = 1;
+static const u8 smmu_enable_payload[] = {
+ 0xC1, 0x00, 0x00, 0x18, // 0x00: LDR W1, =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
+ 0x10, 0x90, 0x01, 0x70, // 0x18: MC_SMMU_CONFIG
+};
+
+void *smmu_page_zalloc(u32 num)
+{
+ void *page = smmu_heap;
+ memset(page, 0, SZ_PAGE * num);
+
+ smmu_heap += SZ_PAGE * num;
+
+ return page;
+}
+
+static pde_t *_smmu_pdir_alloc()
+{
+ pde_t *pdir = (pde_t *)smmu_page_zalloc(1);
+
+ // Initialize pdes with no permissions.
+ for (u32 pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++)
+ pdir[pdn].huge.page = pdn;
+
+ return pdir;
+}
+
+static void _smmu_flush_regs()
+{
+ (void)MC(MC_SMMU_PTB_DATA);
+}
+
+void smmu_flush_all()
+{
+
+ // Flush the entire page table cache.
+ MC(MC_SMMU_PTC_FLUSH) = 0;
+ _smmu_flush_regs();
+
+ // Flush the entire table.
+ MC(MC_SMMU_TLB_FLUSH) = 0;
+ _smmu_flush_regs();
+}
+
+void smmu_init()
+{
+ MC(MC_SMMU_PTB_ASID) = 0;
+ MC(MC_SMMU_PTB_DATA) = 0;
+ MC(MC_SMMU_TLB_CONFIG) = SMMU_TLB_HIT_UNDER_MISS | SMMU_TLB_RR_ARBITRATION | SMMU_TLB_ACTIVE_LINES(48);
+ MC(MC_SMMU_PTC_CONFIG) = SMUU_PTC_CACHE_ENABLE | SMUU_PTC_REQ_LIMIT(8) | SMUU_PTC_LINE_MASK(0xF) | SMUU_PTC_INDEX_MAP(0x3F);
+ MC(MC_SMMU_PTC_FLUSH) = 0;
+ MC(MC_SMMU_TLB_FLUSH) = 0;
+}
+
+void smmu_enable()
+{
+ static bool enabled = false;
+
+ if (enabled)
+ return;
+
+ // Launch payload on CCPLEX in order to set SMMU enable bit.
+ ccplex_boot_cpu0((u32)smmu_enable_payload, false);
+ msleep(100);
+ ccplex_powergate_cpu0();
+
+ smmu_flush_all();
+
+ enabled = true;
+}
+
+void smmu_reset_heap()
+{
+ smmu_heap = (void *)SMMU_HEAP_ADDR;
+}
+
+void *smmu_init_domain(u32 dev_base, u32 asid)
+{
+ void *ptb = _smmu_pdir_alloc();
+
+ MC(MC_SMMU_PTB_ASID) = asid;
+ MC(MC_SMMU_PTB_DATA) = SMMU_PTB((u32)ptb, SMMU_ATTR_ALL);
+ _smmu_flush_regs();
+
+ // Use the same macro for both quad and single domains. Reserved bits are not set anyway.
+ MC(dev_base) = SMMU_ENABLE | SMMU_ASID(asid);
+ _smmu_flush_regs();
+
+ return ptb;
+}
+
+void smmu_deinit_domain(u32 dev_base, u32 asid)
+{
+ MC(MC_SMMU_PTB_ASID) = asid;
+ MC(MC_SMMU_PTB_DATA) = 0;
+ MC(dev_base) = 0;
+ _smmu_flush_regs();
+}
+
+void smmu_domain_bypass(u32 dev_base, bool bypass)
+{
+ if (bypass)
+ {
+ smmu_flush_all();
+ bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
+ MC(dev_base) &= ~SMMU_ENABLE;
+ }
+ else
+ {
+ bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
+ MC(dev_base) |= SMMU_ENABLE;
+ smmu_flush_all();
+ }
+ _smmu_flush_regs();
+}
+
+static pte_t *_smmu_get_pte(pde_t *pdir, u32 iova)
+{
+ u32 pdn = SMMU_ADDR_TO_PDN(iova);
+ pte_t *ptbl;
+
+ // Get 4MB page table or initialize one.
+ if (pdir[pdn].tbl.attr)
+ ptbl = (pte_t *)(SMMU_PTN_TO_ADDR(pdir[pdn].tbl.table));
+ else
+ {
+ // Allocate page table.
+ ptbl = (pte_t *)smmu_page_zalloc(1);
+
+ // Get address.
+ u32 addr = SMMU_PDN_TO_ADDR(pdn);
+
+ // Initialize page table with no permissions.
+ for (u32 pn = 0; pn < SMMU_PTBL_COUNT; pn++, addr += SZ_PAGE)
+ ptbl[pn].page = SMMU_ADDR_TO_PFN(addr);
+
+ // Set page table to the page directory.
+ pdir[pdn].tbl.table = SMMU_ADDR_TO_PTN((u32)ptbl);
+ pdir[pdn].tbl.next = SMMU_PAGE_TABLE;
+ pdir[pdn].tbl.attr = SMMU_ATTR_ALL;
+
+ smmu_flush_all();
+ }
+
+ return &ptbl[SMMU_ADDR_TO_PTN(iova) % SMMU_PTBL_COUNT];
+}
+
+void smmu_map(void *ptb, u32 iova, u64 iopa, u32 pages, u32 attr)
+{
+ // Map pages to page table entries. VA/PA should be aligned to 4KB.
+ for (u32 i = 0; i < pages; i++)
+ {
+ pte_t *pte = _smmu_get_pte((pde_t *)ptb, iova);
+
+ pte->page = SMMU_ADDR_TO_PFN(iopa);
+ pte->attr = attr;
+
+ iova += SZ_PAGE;
+ iopa += SZ_PAGE;
+ }
+
+ smmu_flush_all();
+}
+
+void smmu_map_huge(void *ptb, u32 iova, u64 iopa, u32 regions, u32 attr)
+{
+ pde_t *pdir = (pde_t *)ptb;
+
+ // Map 4MB regions to page directory entries. VA/PA should be aligned to 4MB.
+ for (u32 i = 0; i < regions; i++)
+ {
+ u32 pdn = SMMU_ADDR_TO_PDN(iova);
+ pdir[pdn].huge.page = SMMU_ADDR_TO_PDN(iopa);
+ pdir[pdn].huge.next = SMMU_4MB_REGION;
+ pdir[pdn].huge.attr = attr;
+
+ iova += SZ_4M;
+ iopa += SZ_4M;
+ }
+
+ smmu_flush_all();
+}
diff --git a/bdk/mem/smmu.h b/bdk/mem/smmu.h
new file mode 100644
index 0000000..e45a672
--- /dev/null
+++ b/bdk/mem/smmu.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2018-2024 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 .
+ */
+
+#include
+
+#include
+
+#define MC_SMMU_AVPC_ASID 0x23C
+#define MC_SMMU_TSEC_ASID 0x294
+
+#define SMMU_NS BIT(0)
+#define SMMU_WRITE BIT(1)
+#define SMMU_READ BIT(2)
+#define SMMU_ATTR_ALL (SMMU_READ | SMMU_WRITE | SMMU_NS)
+
+typedef struct _pde_t {
+ union {
+ union {
+ struct {
+ u32 table:22;
+ u32 rsvd:6;
+ u32 next:1;
+ u32 attr:3;
+ } tbl;
+
+ struct {
+ u32 rsvd_:10;
+ u32 page:12;
+ u32 rsvd:6;
+ u32 next:1;
+ u32 attr:3;
+ } huge;
+ };
+
+ u32 pde;
+ };
+} pde_t;
+
+typedef struct _pte_t {
+ u32 page:22;
+ u32 rsvd:7;
+ u32 attr:3;
+} pte_t;
+
+static_assert(sizeof(pde_t) == sizeof(u32), "pde_t size is wrong!");
+static_assert(sizeof(pte_t) == sizeof(u32), "pte_t size is wrong!");
+
+void *smmu_page_zalloc(u32 num);
+void smmu_flush_all();
+void smmu_init();
+void smmu_enable();
+void smmu_reset_heap();
+void *smmu_init_domain(u32 dev_base, u32 asid);
+void smmu_deinit_domain(u32 dev_base, u32 asid);
+void smmu_domain_bypass(u32 dev_base, bool bypass);
+void smmu_map(void *ptb, u32 iova, u64 iopa, u32 pages, u32 attr);
+void smmu_map_huge(void *ptb, u32 iova, u64 iopa, u32 regions, u32 attr);
diff --git a/bdk/memory_map.h b/bdk/memory_map.h
new file mode 100644
index 0000000..c687f2c
--- /dev/null
+++ b/bdk/memory_map.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2019-2021 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef _MEMORY_MAP_H_
+#define _MEMORY_MAP_H_
+
+/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */
+/* --- IPL: 0x40008000 - 0x40028000 --- */
+#define LDR_LOAD_ADDR 0x40007000
+
+#define IPL_LOAD_ADDR 0x40008000
+#define IPL_SZ_MAX SZ_128K
+
+#define XUSB_RING_ADDR 0x40020000 // XUSB EP context and TRB ring buffers.
+
+#define SECMON_MIN_START 0x4002B000 // Minimum reserved address for secmon.
+
+#define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init.
+
+/* start.S / exception_handlers.S */
+#define SYS_STACK_TOP_INIT 0x4003FF00
+#define FIQ_STACK_TOP 0x40040000
+#define IRQ_STACK_TOP 0x40040000
+#define IPL_RELOC_ADDR 0x4003FF00
+#define IPL_RELOC_SZ 0x10
+#define EXCP_STORAGE_ADDR 0x4003FFF0
+#define EXCP_STORAGE_SZ 0x10
+
+/* --- DRAM START --- */
+#define DRAM_START 0x80000000
+#define HOS_RSVD SZ_16M // Do not write anything in this area.
+
+#define NYX_LOAD_ADDR 0x81000000
+#define NYX_SZ_MAX SZ_16M
+/* --- Gap: 0x82000000 - 0x82FFFFFF --- */
+
+/* Stack theoretical max: 33MB */
+#define IPL_STACK_TOP 0x83100000
+#define IPL_HEAP_START 0x84000000
+#define IPL_HEAP_SZ (SZ_512M - SZ_64M)
+
+#define SMMU_HEAP_ADDR 0xA0000000
+/* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */
+
+// Virtual disk / Chainloader buffers.
+#define RAM_DISK_ADDR 0xA4000000
+#define RAM_DISK_SZ 0x41000000 // 1040MB.
+#define RAM_DISK2_SZ 0x21000000 // 528MB.
+
+// NX BIS driver sector cache.
+#define NX_BIS_CACHE_ADDR 0xC5000000
+#define NX_BIS_CACHE_SZ 0x10020000 // 256MB.
+#define NX_BIS_LOOKUP_ADDR 0xD6000000
+#define NX_BIS_LOOKUP_SZ 0xF000000 // 240MB.
+
+// L4T Kernel Panic Storage (PSTORE).
+#define PSTORE_ADDR 0xB0000000
+#define PSTORE_SZ SZ_2M
+
+//#define DRAM_LIB_ADDR 0xE0000000
+/* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading.
+
+// SDMMC DMA buffers 1
+#define SDMMC_UPPER_BUFFER 0xE5000000
+#define SDMMC_UP_BUF_SZ SZ_128M
+
+// Nyx buffers.
+#define NYX_STORAGE_ADDR 0xED000000
+#define NYX_RES_ADDR 0xEE000000
+#define NYX_RES_SZ SZ_16M
+
+// SDMMC DMA buffers 2
+#define SDXC_BUF_ALIGNED 0xEF000000
+#define MIXD_BUF_ALIGNED 0xF0000000
+#define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED
+#define SDMMC_DMA_BUF_SZ SZ_16M // 4MB currently used.
+
+// Nyx LvGL buffers.
+#define NYX_LV_VDB_ADR 0xF1000000
+#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
+#define NYX_LV_MEM_ADR 0xF1400000
+#define NYX_LV_MEM_SZ 0x6600000 // 70MB.
+
+// Framebuffer addresses.
+#define IPL_FB_ADDRESS 0xF5A00000
+#define IPL_FB_SZ 0x384000 // 720 x 1280 x 4.
+#define LOG_FB_ADDRESS 0xF5E00000
+#define LOG_FB_SZ 0x334000 // 1280 x 656 x 4.
+#define NYX_FB_ADDRESS 0xF6200000
+#define NYX_FB2_ADDRESS 0xF6600000
+#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
+
+/* OBSOLETE: Very old hwinit based payloads were setting a carveout here. */
+#define DRAM_MEM_HOLE_ADR 0xF6A00000
+#define DRAM_MEM_HOLE_SZ 0x8140000
+/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
+#define DRAM_START2 0xFEB40000
+
+// USB buffers.
+#define USBD_ADDR 0xFEF00000
+#define USB_DESCRIPTOR_ADDR 0xFEF40000
+#define USB_EP_CONTROL_BUF_ADDR 0xFEF80000
+#define USB_EP_BULK_IN_BUF_ADDR 0xFF000000
+#define USB_EP_BULK_OUT_BUF_ADDR 0xFF800000
+#define USB_EP_BULK_OUT_MAX_XFER SZ_8M
+
+// #define EXT_PAYLOAD_ADDR 0xC0000000
+// #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
+// #define COREBOOT_ADDR (0xD0000000 - rom_size)
+
+#endif
diff --git a/common/common_module.h b/bdk/module.h
similarity index 81%
rename from common/common_module.h
rename to bdk/module.h
index 93a1541..acc048c 100644
--- a/common/common_module.h
+++ b/bdk/module.h
@@ -15,25 +15,32 @@
* along with this program. If not, see .
*/
-#pragma once
+#ifndef _MODULE_H_
+#define _MODULE_H_
+
#include
-//TODO: Move it to BDK
-#include "common_gfx.h"
-#include "common_heap.h"
+#include
+
+#define IANOS_EXT0 0x304E4149
// Module Callback
typedef void (*cbMainModule_t)(const char *s);
typedef void (*memcpy_t)(void *, void *, size_t);
typedef void (*memset_t)(void *, int, size_t);
+typedef int (*reg_voltage_set_t)(u32, u32);
typedef struct _bdkParams_t
{
- gfx_con_t *gfxCon;
- gfx_ctxt_t *gfxCtx;
+ void *gfxCon;
+ void *gfxCtx;
heap_t *sharedHeap;
memcpy_t memcpy;
memset_t memset;
+ u32 extension_magic;
+ reg_voltage_set_t reg_voltage_set;
} *bdkParams_t;
// Module Entrypoint
typedef void (*moduleEntrypoint_t)(void *, bdkParams_t);
+
+#endif
diff --git a/bdk/power/bm92t36.c b/bdk/power/bm92t36.c
new file mode 100644
index 0000000..371ed04
--- /dev/null
+++ b/bdk/power/bm92t36.c
@@ -0,0 +1,104 @@
+/*
+ * USB-PD driver for Nintendo Switch's TI BM92T36
+ *
+ * Copyright (c) 2020-2023 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 .
+ */
+
+#include
+
+#include "bm92t36.h"
+#include
+#include
+
+#define ALERT_STATUS_REG 0x2
+#define STATUS1_REG 0x3
+#define STATUS2_REG 0x4
+#define COMMAND_REG 0x5
+#define CONFIG1_REG 0x6
+#define DEV_CAPS_REG 0x7
+#define READ_PDOS_SRC_REG 0x8
+#define CONFIG2_REG 0x17
+#define DP_STATUS_REG 0x18
+#define DP_ALERT_EN_REG 0x19
+#define VENDOR_CONFIG_REG 0x1A
+#define AUTO_NGT_FIXED_REG 0x20
+#define AUTO_NGT_BATT_REG 0x23
+#define SYS_CONFIG1_REG 0x26
+#define SYS_CONFIG2_REG 0x27
+#define CURRENT_PDO_REG 0x28
+#define CURRENT_RDO_REG 0x2B
+#define ALERT_ENABLE_REG 0x2E
+#define SYS_CONFIG3_REG 0x2F
+#define SET_RDO_REG 0x30
+#define PDOS_SNK_REG 0x33
+#define PDOS_SRC_PROV_REG 0x3C
+#define FW_TYPE_REG 0x4B
+#define FW_REVISION_REG 0x4C
+#define MAN_ID_REG 0x4D
+#define DEV_ID_REG 0x4E
+#define REV_ID_REG 0x4F
+#define INCOMING_VDM_REG 0x50
+#define OUTGOING_VDM_REG 0x60
+
+#define STATUS1_INSERT BIT(7) // Cable inserted.
+
+typedef struct _pd_object_t {
+ unsigned int amp:10;
+ unsigned int volt:10;
+ unsigned int info:10;
+ unsigned int type:2;
+} __attribute__((packed)) pd_object_t;
+
+static int _bm92t36_read_reg(u8 *buf, u32 size, u32 reg)
+{
+ return i2c_recv_buf_big(buf, size, I2C_1, BM92T36_I2C_ADDR, reg);
+}
+
+void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd)
+{
+ u8 buf[32];
+ pd_object_t pdos[7];
+
+ if (inserted)
+ {
+ memset(buf, 0, sizeof(buf));
+ _bm92t36_read_reg(buf, 2, STATUS1_REG);
+ *inserted = (buf[0] & STATUS1_INSERT) ? true : false;
+ }
+
+ if (usb_pd)
+ {
+ memset(buf, 0, sizeof(buf));
+ _bm92t36_read_reg(buf, 29, READ_PDOS_SRC_REG);
+ memcpy(pdos, &buf[1], 28);
+
+ memset(usb_pd, 0, sizeof(usb_pd_objects_t));
+ usb_pd->pdo_no = buf[0] / sizeof(pd_object_t);
+
+ if (usb_pd->pdo_no > 7)
+ usb_pd->pdo_no = 7;
+
+ for (u32 i = 0; i < usb_pd->pdo_no; i++)
+ {
+ usb_pd->pdos[i].amperage = pdos[i].amp * 10;
+ usb_pd->pdos[i].voltage = (pdos[i].volt * 50) / 1000;
+ }
+
+ _bm92t36_read_reg(buf, 5, CURRENT_PDO_REG);
+ memcpy(pdos, &buf[1], 4);
+ usb_pd->selected_pdo.amperage = pdos[0].amp * 10;
+ usb_pd->selected_pdo.voltage = (pdos[0].volt * 50) / 1000;
+ }
+}
diff --git a/bootloader/mem/heap.h b/bdk/power/bm92t36.h
similarity index 57%
rename from bootloader/mem/heap.h
rename to bdk/power/bm92t36.h
index 4ec3fb0..e6740d8 100644
--- a/bootloader/mem/heap.h
+++ b/bdk/power/bm92t36.h
@@ -1,5 +1,7 @@
/*
- * Copyright (c) 2018 naehrwert
+ * USB-PD driver for Nintendo Switch's TI BM92T36
+ *
+ * Copyright (c) 2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -14,16 +16,26 @@
* along with this program. If not, see .
*/
-#ifndef _HEAP_H_
-#define _HEAP_H_
+#ifndef __BM92T36_H_
+#define __BM92T36_H_
-#include "../utils/types.h"
-#include "../../common/common_heap.h"
+#include
-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);
+#define BM92T36_I2C_ADDR 0x18
+
+typedef struct _usb_pd_object_t
+{
+ u32 amperage;
+ u32 voltage;
+} usb_pd_object_t;
+
+typedef struct _usb_pd_objects_t
+{
+ u32 pdo_no;
+ usb_pd_object_t pdos[7];
+ usb_pd_object_t selected_pdo;
+} usb_pd_objects_t;
+
+void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd);
#endif
diff --git a/bdk/power/bq24193.c b/bdk/power/bq24193.c
new file mode 100644
index 0000000..5194279
--- /dev/null
+++ b/bdk/power/bq24193.c
@@ -0,0 +1,179 @@
+/*
+ * 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 .
+ */
+
+#include "bq24193.h"
+#include
+#include
+
+static u8 bq24193_get_reg(u8 reg)
+{
+ return i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, reg);
+}
+
+int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
+{
+ u8 data;
+
+ switch (prop)
+ {
+ case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
+ data = bq24193_get_reg(BQ24193_InputSource);
+ data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;
+ *value = 0;
+ *value += ((data >> 0) & 1) ? 80 : 0;
+ *value += ((data >> 1) & 1) ? 160 : 0;
+ *value += ((data >> 2) & 1) ? 320 : 0;
+ *value += ((data >> 3) & 1) ? 640 : 0;
+ *value += 3880;
+ break;
+ case BQ24193_InputCurrentLimit: // Input current limit (mA).
+ data = bq24193_get_reg(BQ24193_InputSource);
+ data &= BQ24193_INCONFIG_INLIMIT_MASK;
+ switch (data)
+ {
+ case 0:
+ *value = 100;
+ break;
+ case 1:
+ *value = 150;
+ break;
+ case 2:
+ *value = 500;
+ break;
+ case 3:
+ *value = 900;
+ break;
+ case 4:
+ *value = 1200;
+ break;
+ case 5:
+ *value = 1500;
+ break;
+ case 6:
+ *value = 2000;
+ break;
+ case 7:
+ *value = 3000;
+ break;
+ }
+ break;
+ case BQ24193_SystemMinimumVoltage: // Minimum system voltage limit (mV).
+ data = bq24193_get_reg(BQ24193_PORConfig);
+ *value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1;
+ *value *= 100;
+ *value += 3000;
+ break;
+ case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
+ data = bq24193_get_reg(BQ24193_ChrgCurr);
+ data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2;
+ *value = 0;
+ *value += ((data >> 0) & 1) ? 64 : 0;
+ *value += ((data >> 1) & 1) ? 128 : 0;
+ *value += ((data >> 2) & 1) ? 256 : 0;
+ *value += ((data >> 3) & 1) ? 512 : 0;
+ *value += ((data >> 4) & 1) ? 1024 : 0;
+ *value += ((data >> 5) & 1) ? 2048 : 0;
+ *value += 512;
+ data = bq24193_get_reg(BQ24193_ChrgCurr);
+ data &= BQ24193_CHRGCURR_20PCT_MASK;
+ if (data)
+ *value = *value * 20 / 100; // Fast charge current limit is 20%.
+ break;
+ case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV).
+ data = bq24193_get_reg(BQ24193_ChrgVolt);
+ data = (data & BQ24193_CHRGVOLT_VREG) >> 2;
+ *value = 0;
+ *value += ((data >> 0) & 1) ? 16 : 0;
+ *value += ((data >> 1) & 1) ? 32 : 0;
+ *value += ((data >> 2) & 1) ? 64 : 0;
+ *value += ((data >> 3) & 1) ? 128 : 0;
+ *value += ((data >> 4) & 1) ? 256 : 0;
+ *value += ((data >> 5) & 1) ? 512 : 0;
+ *value += 3504;
+ break;
+ case BQ24193_RechargeThreshold: // Recharge voltage threshold less than voltage limit (mV).
+ data = bq24193_get_reg(BQ24193_ChrgVolt);
+ data &= BQ24193_IRTHERMAL_THERM_MASK;
+ if (data)
+ *value = 300;
+ else
+ *value = 100;
+ break;
+ case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC).
+ data = bq24193_get_reg(BQ24193_IRCompThermal);
+ data &= BQ24193_IRTHERMAL_THERM_MASK;
+ switch (data)
+ {
+ case 0:
+ *value = 60;
+ break;
+ case 1:
+ *value = 80;
+ break;
+ case 2:
+ *value = 100;
+ break;
+ case 3:
+ *value = 120;
+ break;
+ }
+ break;
+ case BQ24193_ChargeStatus: // 0: Not charging, 1: Pre-charge, 2: Fast charging, 3: Charge termination done
+ data = bq24193_get_reg(BQ24193_Status);
+ *value = (data & BQ24193_STATUS_CHRG_MASK) >> 4;
+ break;
+ case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
+ data = bq24193_get_reg(BQ24193_FaultReg);
+ *value = data & BQ24193_FAULT_THERM_MASK;
+ break;
+ case BQ24193_DevID: // Dev ID.
+ data = bq24193_get_reg(BQ24193_VendorPart);
+ *value = data & BQ24193_VENDORPART_DEV_MASK;
+ break;
+ case BQ24193_ProductNumber: // Product number.
+ data = bq24193_get_reg(BQ24193_VendorPart);
+ *value = (data & BQ24193_VENDORPART_PN_MASK) >> 3;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+void bq24193_enable_charger()
+{
+ u8 reg = bq24193_get_reg(BQ24193_PORConfig);
+
+ reg &= ~BQ24193_PORCONFIG_CHGCONFIG_MASK;
+ reg |= BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN;
+
+ i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_PORConfig, reg);
+}
+
+void bq24193_fake_battery_removal()
+{
+ // Disable watchdog to keep BATFET disabled.
+ u8 value = bq24193_get_reg(BQ24193_ChrgTermTimer);
+ value &= ~BQ24193_CHRGTERM_WATCHDOG_MASK;
+ i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_ChrgTermTimer, value);
+
+ // Force BATFET to disabled state. This disconnects the battery from the system.
+ value = bq24193_get_reg(BQ24193_Misc);
+ value |= BQ24193_MISC_BATFET_DI_MASK;
+ i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value);
+}
diff --git a/bootloader/power/bq24193.h b/bdk/power/bq24193.h
similarity index 95%
rename from bootloader/power/bq24193.h
rename to bdk/power/bq24193.h
index 34e9fbf..399e225 100644
--- a/bootloader/power/bq24193.h
+++ b/bdk/power/bq24193.h
@@ -28,8 +28,9 @@
// REG 1 masks.
#define BQ24193_PORCONFIG_BOOST_MASK (1<<0)
-#define BQ24193_PORCONFIG_SYSMIN_MASK (7<<1)
+#define BQ24193_PORCONFIG_SYSMIN_MASK (7<<1) // 3000uV HOS default.
#define BQ24193_PORCONFIG_CHGCONFIG_MASK (3<<4)
+#define BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN (1<<4)
#define BQ24193_PORCONFIG_I2CWATCHDOG_MASK (1<<6)
#define BQ24193_PORCONFIG_RESET_MASK (1<<7)
@@ -114,6 +115,7 @@ enum BQ24193_reg_prop {
};
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value);
+void bq24193_enable_charger();
void bq24193_fake_battery_removal();
#endif /* __BQ24193_H_ */
diff --git a/bootloader/power/max17050.c b/bdk/power/max17050.c
similarity index 70%
rename from bootloader/power/max17050.c
rename to bdk/power/max17050.c
index 635a437..8c4f658 100644
--- a/bootloader/power/max17050.c
+++ b/bdk/power/max17050.c
@@ -23,28 +23,42 @@
*/
#include "max17050.h"
-#include "../soc/i2c.h"
-#include "../utils/util.h"
+#include
+#include
+
+#define BASE_SNS_UOHM 5000
/* 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 STATUS_POR_BIT BIT(1)
+#define STATUS_BST_BIT BIT(3)
+#define STATUS_VMN_BIT BIT(8)
+#define STATUS_TMN_BIT BIT(9)
+#define STATUS_SMN_BIT BIT(10)
+#define STATUS_BI_BIT BIT(11)
+#define STATUS_VMX_BIT BIT(12)
+#define STATUS_TMX_BIT BIT(13)
+#define STATUS_SMX_BIT BIT(14)
+#define STATUS_BR_BIT BIT(15)
#define VFSOC0_LOCK 0x0000
#define VFSOC0_UNLOCK 0x0080
#define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */
-#pragma GCC push_options
-#pragma GCC optimize ("Os")
+static u32 battery_voltage = 0;
+u32 max17050_get_cached_batt_volt()
+{
+ return battery_voltage;
+}
+
+static u16 max17050_get_reg(u8 reg)
+{
+ u16 data = 0;
+
+ i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, reg);
+
+ return data;
+}
int max17050_get_property(enum MAX17050_reg reg, int *value)
{
@@ -53,68 +67,66 @@ int max17050_get_property(enum MAX17050_reg reg, int *value)
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);
+ data = max17050_get_reg(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);
+ *value = max17050_get_reg(MAX17050_Cycles);
break;
case MAX17050_MinVolt: // Voltage max/min
- i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MinMaxVolt);
+ data = max17050_get_reg(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);
+ data = max17050_get_reg(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);
+ data = max17050_get_reg(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;
+ data = max17050_get_reg(MAX17050_VCELL);
+ *value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */
+ battery_voltage = *value;
break;
case MAX17050_AvgVCELL: // Voltage avg.
- i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgVCELL);
- *value = data * 625 / 8 / 1000;
+ data = max17050_get_reg(MAX17050_AvgVCELL);
+ *value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */
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;
+ data = max17050_get_reg(MAX17050_OCVInternal);
+ *value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */
break;
case MAX17050_RepSOC: // Capacity %.
- i2c_recv_buf_small((u8 *)value, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepSOC);
+ *value = max17050_get_reg(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;
+ data = max17050_get_reg(MAX17050_DesignCap);
+ *value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN;
break;
case MAX17050_FullCAP: // Charge full.
- i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_FullCAP);
- data = data * 5 / 10;
- *value = data;
+ data = max17050_get_reg(MAX17050_FullCAP);
+ *value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN;
break;
case MAX17050_RepCap: // Charge now.
- i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_RepCap);
- data = data * 5 / 10;
- *value = data;
+ data = max17050_get_reg(MAX17050_RepCap);
+ *value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN;
break;
case MAX17050_TEMP: // Temp.
- i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_TEMP);
+ data = max17050_get_reg(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);
+ data = max17050_get_reg(MAX17050_Current);
*value = (s16)data;
- *value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR;
+ *value *= 1562500 / (MAX17050_BOARD_SNS_RESISTOR_UOHM * MAX17050_BOARD_CGAIN);
break;
case MAX17050_AvgCurrent: // Current avg.
- i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgCurrent);
+ data = max17050_get_reg(MAX17050_AvgCurrent);
*value = (s16)data;
- *value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR;
+ *value *= 1562500 / (MAX17050_BOARD_SNS_RESISTOR_UOHM * MAX17050_BOARD_CGAIN);
break;
default:
return -1;
@@ -131,7 +143,7 @@ static int _max17050_write_verify_reg(u8 reg, u16 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);
+ read_value = max17050_get_reg(reg);
if (read_value != value)
{
ret = -1;
@@ -268,4 +280,25 @@ int max17050_fix_configuration()
return 0;
}
-#pragma GCC pop_options
\ No newline at end of file
+void max17050_dump_regs(void *buf)
+{
+ u16 *buff = (u16 *)buf;
+
+ // Unlock model table.
+ u16 unlock = 0x59;
+ i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MODELEnable1, (u8 *)&unlock, 2);
+ unlock = 0xC4;
+ i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MODELEnable2, (u8 *)&unlock, 2);
+
+ // Dump all battery fuel gauge registers.
+ for (u32 i = 0; i < 0x100; i++)
+ {
+ buff[i] = max17050_get_reg(i);
+ msleep(1);
+ }
+
+ // Lock model table.
+ unlock = 0;
+ i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MODELEnable1, (u8 *)&unlock, 2);
+ i2c_send_buf_small(I2C_1, MAXIM17050_I2C_ADDR, MAX17050_MODELEnable2, (u8 *)&unlock, 2);
+}
diff --git a/nyx/nyx_gui/power/max17050.h b/bdk/power/max17050.h
similarity index 88%
rename from nyx/nyx_gui/power/max17050.h
rename to bdk/power/max17050.h
index 6104e5c..438f55a 100644
--- a/nyx/nyx_gui/power/max17050.h
+++ b/bdk/power/max17050.h
@@ -1,10 +1,9 @@
/*
* 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
- * Copyright (c) 2018 CTCaer
+ * 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
@@ -24,8 +23,13 @@
#ifndef __MAX17050_H_
#define __MAX17050_H_
-#define MAX17050_STATUS_BattAbsent (1 << 3)
-#define MAX17050_DEFAULT_SNS_RESISTOR 10000
+#include
+
+/* Board default values */
+#define MAX17050_BOARD_CGAIN 2 /* Actual: 1.99993 */
+#define MAX17050_BOARD_SNS_RESISTOR_UOHM 5000 /* 0.005 Ohm */
+
+#define MAX17050_STATUS_BattAbsent BIT(3)
/* Consider RepCap which is less then 10 units below FullCAP full */
#define MAX17050_FULL_THRESHOLD 10
@@ -126,7 +130,9 @@ enum MAX17050_reg {
MAX17050_VFSOC = 0xFF,
};
-int max17050_get_property(enum MAX17050_reg reg, int *value);
-int max17050_fix_configuration();
+int max17050_get_property(enum MAX17050_reg reg, int *value);
+int max17050_fix_configuration();
+void max17050_dump_regs(void *buf);
+u32 max17050_get_cached_batt_volt();
#endif /* __MAX17050_H_ */
diff --git a/bootloader/power/max77620.h b/bdk/power/max77620.h
similarity index 56%
rename from bootloader/power/max77620.h
rename to bdk/power/max77620.h
index 26ea855..3d41459 100644
--- a/bootloader/power/max77620.h
+++ b/bdk/power/max77620.h
@@ -1,8 +1,7 @@
/*
* Defining registers address and its bit definitions of MAX77620 and MAX20024
*
- * Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved.
- * Copyright (c) 2019 CTCaer
+ * 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,
@@ -16,13 +15,7 @@
/* 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_LBRSTEN BIT(0)
#define MAX77620_CNFGGLBL1_LBDAC_MASK 0x0E
#define MAX77620_CNFGGLBL1_LBDAC_2700 (0 << 1)
#define MAX77620_CNFGGLBL1_LBDAC_2800 (1 << 1)
@@ -32,30 +25,45 @@
#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_CNFGGLBL1_LBHYST_100 (0 << 4)
+#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4)
+#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4)
+#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4)
+#define MAX77620_CNFGGLBL1_MPPLD BIT(6)
+#define MAX77620_CNFGGLBL1_LBDAC_EN BIT(7)
#define MAX77620_REG_CNFGGLBL2 0x01
-#define MAX77620_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_WDTEN BIT(2)
+#define MAX77620_WDTSLPC BIT(3)
+#define MAX77620_WDTOFFC BIT(4)
+#define MAX77620_GLBL_LPM BIT(5)
+#define MAX77620_I2CTWD_MASK 0xC0
+#define MAX77620_I2CTWD_DISABLED 0x00
+#define MAX77620_I2CTWD_1_33ms 0x40
+#define MAX77620_I2CTWD_35_7ms 0x80
+#define MAX77620_I2CTWD_41_7ms 0xC0
+
+#define MAX77620_REG_CNFGGLBL3 0x02
+#define MAX77620_WDTC_MASK 0x3
#define MAX77620_REG_CNFG1_32K 0x03
-#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2)
+#define MAX77620_CNFG1_PWR_MD_32K_MASK 0x3
+#define MAX77620_CNFG1_32K_OUT0_EN BIT(2)
+#define MAX77620_CNFG1_32KLOAD_MASK 0x30
+#define MAX77620_CNFG1_32K_OK BIT(7)
#define MAX77620_REG_CNFGBBC 0x04
-#define MAX77620_CNFGBBC_ENABLE (1 << 0)
+#define MAX77620_CNFGBBC_ENABLE BIT(0)
#define MAX77620_CNFGBBC_CURRENT_MASK 0x06
#define MAX77620_CNFGBBC_CURRENT_SHIFT 1
#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18
#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3
-#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5)
+#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE BIT(5)
#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0
#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6
#define MAX77620_CNFGBBC_RESISTOR_100 (0 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
@@ -64,37 +72,63 @@
#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_IRQTOPM 0x0D
+#define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1)
+#define MAX77620_IRQ_TOP_32K_MASK BIT(2)
+#define MAX77620_IRQ_TOP_RTC_MASK BIT(3)
+#define MAX77620_IRQ_TOP_GPIO_MASK BIT(4)
+#define MAX77620_IRQ_TOP_LDO_MASK BIT(5)
+#define MAX77620_IRQ_TOP_SD_MASK BIT(6)
+#define MAX77620_IRQ_TOP_GLBL_MASK BIT(7)
#define MAX77620_REG_INTLBT 0x06
-#define MAX77620_REG_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_INTENLBT 0x0E
+#define MAX77620_IRQ_GLBLM_MASK BIT(0)
+#define MAX77620_IRQ_TJALRM2_MASK BIT(1)
+#define MAX77620_IRQ_TJALRM1_MASK BIT(2)
+#define MAX77620_IRQ_LBM_MASK BIT(3)
#define MAX77620_REG_IRQSD 0x07
-#define MAX77620_REG_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_IRQSD_PFI_SD3 BIT(4)
+#define MAX77620_IRQSD_PFI_SD2 BIT(5)
+#define MAX77620_IRQSD_PFI_SD1 BIT(6)
+#define MAX77620_IRQSD_PFI_SD0 BIT(7)
+
+#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 // LDO number that irq occurred.
#define MAX77620_REG_IRQ_MSK_L0_7 0x10
+#define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occurred. Only bit0: LDO8 is valid.
#define MAX77620_REG_IRQ_MSK_L8 0x11
+#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt.
+
+#define MAX77620_REG_ONOFFIRQ 0x0B
#define MAX77620_REG_ONOFFIRQM 0x12
+#define MAX77620_ONOFFIRQ_MRWRN BIT(0)
+#define MAX77620_ONOFFIRQ_EN0_1SEC BIT(1)
+#define MAX77620_ONOFFIRQ_EN0_F BIT(2)
+#define MAX77620_ONOFFIRQ_EN0_R BIT(3)
+#define MAX77620_ONOFFIRQ_LID_F BIT(4)
+#define MAX77620_ONOFFIRQ_LID_R BIT(5)
+#define MAX77620_ONOFFIRQ_ACOK_F BIT(6)
+#define MAX77620_ONOFFIRQ_ACOK_R BIT(7)
+
+#define MAX77620_REG_NVERC 0x0C // Shutdown reason (non-volatile).
+#define MAX77620_NVERC_SHDN BIT(0)
+#define MAX77620_NVERC_WTCHDG BIT(1)
+#define MAX77620_NVERC_HDRST BIT(2)
+#define MAX77620_NVERC_TOVLD BIT(3)
+#define MAX77620_NVERC_MBLSD BIT(4)
+#define MAX77620_NVERC_MBO BIT(5)
+#define MAX77620_NVERC_MBU BIT(6)
+#define MAX77620_NVERC_RSTIN BIT(7)
+
#define MAX77620_REG_STATLBT 0x13
#define MAX77620_REG_STATSD 0x14
+
#define MAX77620_REG_ONOFFSTAT 0x15
+#define MAX77620_ONOFFSTAT_LID BIT(0)
+#define MAX77620_ONOFFSTAT_ACOK BIT(1)
+#define MAX77620_ONOFFSTAT_EN0 BIT(2)
/* SD and LDO Registers */
#define MAX77620_REG_SD0 0x16
@@ -102,18 +136,42 @@
#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_SDX_VOLT_MASK 0xFF
+#define MAX77620_SD0_VOLT_MASK 0x7F // Max is 0x40.
+#define MAX77620_SD1_VOLT_MASK 0x7F // Max is 0x4C.
+#define MAX77620_LDO_VOLT_MASK 0x3F
+
#define MAX77620_REG_SD0_CFG 0x1D
#define MAX77620_REG_SD1_CFG 0x1E
#define MAX77620_REG_SD2_CFG 0x1F
#define MAX77620_REG_SD3_CFG 0x20
#define MAX77620_REG_SD4_CFG 0x21
+#define MAX77620_SD_SR_MASK 0xC0
+#define MAX77620_SD_SR_SHIFT 6
+#define MAX77620_SD_POWER_MODE_MASK 0x30
+#define MAX77620_SD_POWER_MODE_SHIFT 4
+#define MAX77620_SD_CFG1_ADE_MASK BIT(3)
+#define MAX77620_SD_CFG1_ADE_DISABLE 0
+#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3)
+#define MAX77620_SD_FPWM_MASK 0x04
+#define MAX77620_SD_FPWM_SHIFT 2
+#define MAX77620_SD_FSRADE_MASK 0x01
+#define MAX77620_SD_FSRADE_SHIFT 0
+#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2)
+#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
+#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2)
+#define MAX77620_SD_CFG1_MPOK_MASK BIT(1)
+#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0)
+#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
+#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0)
+
#define MAX77620_REG_SD_CFG2 0x22
+#define MAX77620_SD_CNF2_RSVD BIT(0)
+#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1)
+#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2)
+
#define MAX77620_REG_LDO0_CFG 0x23
#define MAX77620_REG_LDO0_CFG2 0x24
#define MAX77620_REG_LDO1_CFG 0x25
@@ -132,25 +190,35 @@
#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
+/*! LDO CFG */
#define MAX77620_LDO_POWER_MODE_SHIFT 6
+#define MAX77620_LDO_POWER_MODE_MASK (3 << MAX77620_LDO_POWER_MODE_SHIFT)
#define MAX77620_POWER_MODE_NORMAL 3
#define MAX77620_POWER_MODE_LPM 2
#define MAX77620_POWER_MODE_GLPM 1
#define MAX77620_POWER_MODE_DISABLE 0
-#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2)
+/*! LDO CFG2 */
+#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
+#define MAX77620_LDO_CFG2_SS_FAST (0 << 0)
+#define MAX77620_LDO_CFG2_SS_SLOW (1 << 0)
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
-#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
-#define MAX77620_LDO_CFG2_SS_FAST (1 << 0)
-#define MAX77620_LDO_CFG2_SS_SLOW 0
+#define MAX77620_LDO_CFG2_MPOK_MASK BIT(2)
+#define MAX77620_LDO_CFG2_POK_MASK BIT(3)
+#define MAX77620_LDO_CFG2_COMP_SHIFT 4
+#define MAX77620_LDO_CFG2_COMP_MASK (3 << MAX77620_LDO_COMP_SHIFT)
+#define MAX77620_LDO_CFG2_COMP_SLOW 3
+#define MAX77620_LDO_CFG2_COMP_MID_SLOW 2
+#define MAX77620_LDO_CFG2_COMP_MID_FAST 1
+#define MAX77620_LDO_CFG2_COMP_FAST 0
+#define MAX77620_LDO_CFG2_ALPM_EN_MASK BIT(6)
+#define MAX77620_LDO_CFG2_OVCLMP_MASK BIT(7)
#define MAX77620_REG_LDO_CFG3 0x35
-#define MAX77620_TRACK4_MASK (1 << 5)
+#define MAX77620_LDO_BIAS_EN BIT(0)
#define MAX77620_TRACK4_SHIFT 5
-
-#define MAX77620_LDO_SLEW_RATE_MASK 0x1
+#define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT)
#define MAX77620_REG_GPIO0 0x36
#define MAX77620_REG_GPIO1 0x37
@@ -160,9 +228,6 @@
#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)
@@ -181,26 +246,44 @@
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
+#define MAX77620_GPIO_OUTPUT_DISABLE 0
+#define MAX77620_GPIO_OUTPUT_ENABLE 1
+
+#define MAX77620_REG_PUE_GPIO 0x3E // Gpio Pullup resistor enable.
+#define MAX77620_REG_PDE_GPIO 0x3F // Gpio Pulldown resistor enable.
+
+#define MAX77620_REG_AME_GPIO 0x40 // Gpio pinmuxing. Clear bits are Standard GPIO.
#define MAX77620_REG_ONOFFCNFG1 0x41
-#define 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_ONOFFCNFG1_PWR_OFF BIT(1)
+#define MAX77620_ONOFFCNFG1_SLPEN BIT(2)
+#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
+#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
+#define MAX77620_ONOFFCNFG1_RSVD BIT(6)
+#define MAX77620_ONOFFCNFG1_SFT_RST BIT(7)
#define MAX77620_REG_ONOFFCNFG2 0x42
-#define MAX77620_ONOFFCNFG2_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)
+#define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0)
+#define MAX77620_ONOFFCNFG2_WK_ALARM2 BIT(1)
+#define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2)
+#define MAX77620_ONOFFCNFG2_WK_MBATT BIT(3) // MBATT event generates a wakeup signal. use it in android/l4t?
+#define MAX77620_ONOFFCNFG2_WK_ACOK BIT(4)
+#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5)
+#define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6)
+#define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7)
/* FPS Registers */
-#define MAX77620_REG_FPS_CFG0 0x43
-#define MAX77620_REG_FPS_CFG1 0x44
-#define MAX77620_REG_FPS_CFG2 0x45
+#define MAX77620_REG_FPS_CFG0 0x43 // FPS0.
+#define MAX77620_REG_FPS_CFG1 0x44 // FPS1.
+#define MAX77620_REG_FPS_CFG2 0x45 // FPS2.
+#define MAX77620_FPS_ENFPS_SW_MASK 0x01
+#define MAX77620_FPS_ENFPS_SW 0x01
+#define MAX77620_FPS_EN_SRC_SHIFT 1
+#define MAX77620_FPS_EN_SRC_MASK 0x06
+#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
+#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
+
#define MAX77620_REG_FPS_LDO0 0x46
#define MAX77620_REG_FPS_LDO1 0x47
#define MAX77620_REG_FPS_LDO2 0x48
@@ -215,86 +298,48 @@
#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_FPS_PD_PERIOD_SHIFT 0
+#define MAX77620_FPS_PD_PERIOD_MASK 0x07
+#define MAX77620_FPS_PU_PERIOD_SHIFT 3
+#define MAX77620_FPS_PU_PERIOD_MASK 0x38
+#define MAX77620_FPS_SRC_SHIFT 6
+#define MAX77620_FPS_SRC_MASK 0xC0
+
+#define MAX77620_FPS_COUNT 3
+#define MAX77620_FPS_PERIOD_MIN_US 40
+#define MAX77620_FPS_PERIOD_MAX_US 2560
+
#define MAX77620_REG_CID0 0x58
#define MAX77620_REG_CID1 0x59
#define MAX77620_REG_CID2 0x5A
#define MAX77620_REG_CID3 0x5B
-#define MAX77620_REG_CID4 0x5C
-#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)
+#define MAX77620_REG_CID4 0x5C // OTP version.
+#define MAX77620_REG_CID5 0x5D // ES version.
+#define MAX77620_CID_DIDO_MASK 0xF
+#define MAX77620_CID_DIDO_SHIFT 0
+#define MAX77620_CID_DIDM_MASK 0xF0
+#define MAX77620_CID_DIDM_SHIFT 4
/* Device Identification Metal */
#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF)
/* Device Indentification OTP */
#define MAX77620_CID5_DIDO(n) ((n) & 0xF)
-/* 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_REG_DVSSD4 0x5E
+#define MAX20024_REG_MAX_ADD 0x70
-#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)
+#define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0)
+#define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1)
+#define MAX77620_IRQ_LVL2_GPIO_EDGE2 BIT(2)
+#define MAX77620_IRQ_LVL2_GPIO_EDGE3 BIT(3)
+#define MAX77620_IRQ_LVL2_GPIO_EDGE4 BIT(4)
+#define MAX77620_IRQ_LVL2_GPIO_EDGE5 BIT(5)
+#define MAX77620_IRQ_LVL2_GPIO_EDGE6 BIT(6)
+#define MAX77620_IRQ_LVL2_GPIO_EDGE7 BIT(7)
/* Interrupts */
enum {
@@ -332,9 +377,4 @@ enum max77620_fps_src {
MAX77620_FPS_SRC_DEF,
};
-enum max77620_chip_id {
- MAX77620,
- MAX20024,
-};
-
#endif /* _MFD_MAX77620_H_ */
diff --git a/bdk/power/max7762x.c b/bdk/power/max7762x.c
new file mode 100644
index 0000000..f0aefb5
--- /dev/null
+++ b/bdk/power/max7762x.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2019-2020 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define REGULATOR_SD 0
+#define REGULATOR_LDO 1
+#define REGULATOR_BC0 2
+#define REGULATOR_BC1 3
+
+typedef struct _max77620_fps_t
+{
+ u8 fps_addr;
+ u8 fps_src;
+ u8 pd_period;
+ u8 pu_period;
+} max77620_fps_t;
+
+typedef struct _max77621_ctrl_t
+{
+ u8 ctrl1_por;
+ u8 ctrl1_hos;
+ u8 ctrl2_por;
+ u8 ctrl2_hos;
+} max77621_ctrl_t;
+
+typedef struct _max77812_ctrl_t
+{
+ u8 mask;
+ u8 shift;
+ u8 rsvd0;
+ u8 rsvd1;
+} max77812_en_t;
+
+typedef struct _max77620_regulator_t
+{
+ const char *name;
+
+ u32 uv_step;
+ u32 uv_min;
+ u32 uv_default;
+ u32 uv_max;
+
+ u8 type;
+ u8 volt_addr;
+ u8 cfg_addr;
+ u8 volt_mask;
+
+ union {
+ max77620_fps_t fps;
+ max77621_ctrl_t ctrl;
+ max77812_en_t enable;
+ };
+} max77620_regulator_t;
+
+static const max77620_regulator_t _pmic_regulators[] = {
+ { "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
+ { "sd1", 12500, 600000, 1125000, 1237500, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
+ { "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
+ { "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
+ { "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
+ { "ldo1", 25000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO1, 3, 7, 0 }} },
+ { "ldo2", 50000, 800000, 1800000, 3300000, REGULATOR_LDO, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO2, 3, 7, 0 }} },
+ { "ldo3", 50000, 800000, 3100000, 3100000, REGULATOR_LDO, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO3, 3, 7, 0 }} },
+ { "ldo4", 12500, 800000, 850000, 1000000, REGULATOR_LDO, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO4, 0, 7, 1 }} },
+ { "ldo5", 50000, 800000, 1800000, 1800000, REGULATOR_LDO, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO5, 3, 7, 0 }} },
+ { "ldo6", 50000, 800000, 2900000, 2900000, REGULATOR_LDO, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO6, 3, 7, 0 }} },
+ { "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} },
+ { "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} },
+
+ { "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_REG_VOUT, MAX77621_REG_VOUT_DVS, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
+ { "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_REG_VOUT, MAX77621_REG_VOUT_DVS, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
+ { "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} },
+ { "max77812_RAM", 5000, 250000, 600000, 650000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration.
+ //{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} },
+};
+
+static u8 _max77812_get_address()
+{
+ static u8 max77812_i2c_addr = 0;
+
+ if (max77812_i2c_addr)
+ return max77812_i2c_addr;
+
+ max77812_i2c_addr =
+ !(FUSE(FUSE_RESERVED_ODM28_B01) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
+
+ return max77812_i2c_addr;
+}
+
+static u8 _max7762x_get_i2c_address(u32 id)
+{
+ const max77620_regulator_t *reg = &_pmic_regulators[id];
+
+ // Choose the correct i2c address.
+ switch (reg->type)
+ {
+ case REGULATOR_SD:
+ case REGULATOR_LDO:
+ return MAX77620_I2C_ADDR;
+ case REGULATOR_BC0:
+ return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR);
+ case REGULATOR_BC1:
+ {
+ u8 reg_addr = _max77812_get_address();
+ if (id == REGULATOR_RAM0 && reg_addr == MAX77812_PHASE31_CPU_I2C_ADDR)
+ reg_addr = 0;
+ return reg_addr;
+ }
+ default:
+ return 0;
+ }
+}
+
+static void _max7762x_set_reg(u8 addr, u8 reg, u8 val)
+{
+ u32 retries = 100;
+ while (retries)
+ {
+ if (i2c_send_byte(I2C_5, addr, reg, val))
+ break;
+
+ usleep(50);
+ retries--;
+ }
+}
+
+int max77620_regulator_get_status(u32 id)
+{
+ if (id > REGULATOR_LDO8)
+ return 0;
+
+ const max77620_regulator_t *reg = &_pmic_regulators[id];
+
+ // SD power OK status.
+ if (reg->type == REGULATOR_SD)
+ {
+ u8 mask = 1u << (7 - id);
+ return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & mask) ? 0 : 1;
+ }
+
+ // LDO power OK status.
+ return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & MAX77620_LDO_CFG2_POK_MASK) ? 1 : 0;
+}
+
+int max77620_regulator_config_fps(u32 id)
+{
+ if (id > REGULATOR_LDO8)
+ return 0;
+
+ const max77620_regulator_t *reg = &_pmic_regulators[id];
+
+ // Set FPS configuration.
+ _max7762x_set_reg(MAX77620_I2C_ADDR,
+ reg->fps.fps_addr,
+ (reg->fps.fps_src << MAX77620_FPS_SRC_SHIFT) |
+ (reg->fps.pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) |
+ (reg->fps.pd_period << MAX77620_FPS_PD_PERIOD_SHIFT));
+
+ return 1;
+}
+
+int max7762x_regulator_set_voltage(u32 id, u32 uv)
+{
+ if (id > REGULATOR_MAX)
+ return 0;
+
+ const max77620_regulator_t *reg = &_pmic_regulators[id];
+
+ if (uv < reg->uv_min || uv > reg->uv_max)
+ return 0;
+
+ u8 addr = _max7762x_get_i2c_address(id);
+ if (!addr)
+ return 0;
+
+ // Calculate voltage multiplier.
+ u32 mult = (uv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step;
+ u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr);
+ val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
+
+ // Set voltage.
+ _max7762x_set_reg(addr, reg->volt_addr, val);
+
+ // If max77621 set DVS voltage also.
+ if (reg->type == REGULATOR_BC0)
+ _max7762x_set_reg(addr, reg->cfg_addr, MAX77621_VOUT_ENABLE_MASK | val);
+
+ // Wait for ramp up/down delay.
+ usleep(1000);
+
+ return 1;
+}
+
+int max7762x_regulator_enable(u32 id, bool enable)
+{
+ u8 reg_addr;
+ u8 enable_val;
+ u8 enable_mask;
+ u8 enable_shift;
+
+ if (id > REGULATOR_MAX)
+ return 0;
+
+ const max77620_regulator_t *reg = &_pmic_regulators[id];
+
+ // Choose the correct i2c and register addresses and mask/shift for each type.
+ switch (reg->type)
+ {
+ case REGULATOR_SD:
+ reg_addr = reg->cfg_addr;
+ enable_val = MAX77620_POWER_MODE_NORMAL;
+ enable_mask = MAX77620_SD_POWER_MODE_MASK;
+ enable_shift = MAX77620_SD_POWER_MODE_SHIFT;
+ break;
+ case REGULATOR_LDO:
+ reg_addr = reg->volt_addr;
+ enable_val = MAX77620_POWER_MODE_NORMAL;
+ enable_mask = MAX77620_LDO_POWER_MODE_MASK;
+ enable_shift = MAX77620_LDO_POWER_MODE_SHIFT;
+ break;
+ case REGULATOR_BC0:
+ reg_addr = reg->volt_addr;
+ enable_val = MAX77621_VOUT_ENABLE;
+ enable_mask = MAX77621_DVC_DVS_ENABLE_MASK;
+ enable_shift = MAX77621_DVC_DVS_ENABLE_SHIFT;
+ break;
+ case REGULATOR_BC1:
+ reg_addr = reg->cfg_addr;
+ enable_val = MAX77812_EN_CTRL_ENABLE;
+ enable_mask = reg->enable.mask;
+ enable_shift = reg->enable.shift;
+ break;
+ default:
+ return 0;
+ }
+
+ u8 addr = _max7762x_get_i2c_address(id);
+ if (!addr)
+ return 0;
+
+ // Read and enable/disable.
+ u8 val = i2c_recv_byte(I2C_5, addr, reg_addr);
+ val &= ~enable_mask;
+
+ if (enable)
+ val |= (enable_val << enable_shift);
+
+ // Set enable.
+ _max7762x_set_reg(addr, reg_addr, val);
+
+ // Wait for enable/disable ramp delay.
+ usleep(1000);
+
+ return 1;
+}
+
+void max77620_config_gpio(u32 gpio_id, bool enable)
+{
+ if (gpio_id > 7)
+ return;
+
+ // Configure as standard GPIO.
+ u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO);
+ i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, val & ~BIT(gpio_id));
+
+ // Set GPIO configuration.
+ if (enable)
+ val = MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DIR_OUTPUT | MAX77620_CNFG_GPIO_DRV_PUSHPULL;
+ else
+ val = MAX77620_CNFG_GPIO_DIR_INPUT | MAX77620_CNFG_GPIO_DRV_OPENDRAIN;
+ i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO0 + gpio_id, val);
+}
+
+void max77621_config_default(u32 id, bool por)
+{
+ const max77620_regulator_t *reg = &_pmic_regulators[id];
+
+ if (reg->type != REGULATOR_BC0)
+ return;
+
+ u8 addr = _max7762x_get_i2c_address(id);
+ if (!addr)
+ return;
+
+ if (por)
+ {
+ // Set voltage and disable power before changing the inductor.
+ max7762x_regulator_set_voltage(id, 1000000);
+ max7762x_regulator_enable(id, false);
+
+ // Configure to default.
+ i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL1, reg->ctrl.ctrl1_por);
+ i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL2, reg->ctrl.ctrl2_por);
+ }
+ else
+ {
+ i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL1, reg->ctrl.ctrl1_hos);
+ i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL2, reg->ctrl.ctrl2_hos);
+ }
+}
+
+void max77620_config_default()
+{
+ // Check if Erista OTP.
+ if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4) != 0x35)
+ return;
+
+ // Set default voltages and enable regulators.
+ for (u32 i = REGULATOR_SD1; i <= REGULATOR_LDO8; i++)
+ {
+ max77620_regulator_config_fps(i);
+ max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);
+ if (_pmic_regulators[i].fps.fps_src != MAX77620_FPS_SRC_NONE)
+ max7762x_regulator_enable(i, true);
+ }
+
+ // Enable SD0 output voltage sense and disable for SD1. Additionally disable the reserved bit.
+ _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
+}
+
+// Stock HOS: disabled.
+void max77620_low_battery_monitor_config(bool enable)
+{
+ _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
+ MAX77620_CNFGGLBL1_LBDAC_EN |
+ (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) |
+ MAX77620_CNFGGLBL1_LBHYST_200 |
+ MAX77620_CNFGGLBL1_LBDAC_2800);
+}
diff --git a/bdk/power/max7762x.h b/bdk/power/max7762x.h
new file mode 100644
index 0000000..342f40b
--- /dev/null
+++ b/bdk/power/max7762x.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2019-2020 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef _MAX7762X_H_
+#define _MAX7762X_H_
+
+#include
+
+/*
+ * SDx actual min is 625 mV. Multipliers 0/1 reserved.
+ * SD0 max is 1400 mV
+ * SD1 max is 1550 mV
+ * SD2 max is 3787.5 mV
+ * SD3 max is 3787.5 mV
+ */
+
+/*
+* Switch Power domains (max77620):
+* Name | Usage | uV step | uV min | uV default | uV max | Init
+*-------+---------------+---------+--------+------------+---------+------------------
+* sd0 | SoC | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
+* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1)
+* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv)
+* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 |
+* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1)
+* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
+* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
+* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
+* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv)
+* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
+* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv)
+* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
+* ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv)
+*/
+
+
+// GPIOs T210: 3: 3.3V, 5: CPU PMIC, 6: GPU PMIC, 7: DSI/VI 1.2V powered by ldo0.
+
+/*
+ * OTP: T210 - T210B01:
+ * SD0: 1.0V 1.05V - SoC. EN Based on FPSSRC.
+ * SD1: 1.15V 1.1V - DRAM for T210. EN Based on FPSSRC.
+ * SD2: 1.35V 1.35V
+ * SD3: 1.8V 1.8V
+ * All powered off?
+ * LDO0: -- -- - Display
+ * LDO1: 1.05V 1.05V
+ * LDO2: -- -- - SD
+ * LDO3: 3.1V 3.1V - GC ASIC
+ * LDO4: 1.0V 0.8V - Needed for RTC domain on T210.
+ * LDO5: 3.1V 3.1V
+ * LDO6: 2.8V 2.9V - Touch.
+ * LDO7: 1.05V 1.0V
+ * LDO8: 1.05V 1.0V
+ */
+
+/*
+* MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode
+* MAX77620_REG_GPIOx: 0x9 sets output and enable
+*/
+
+/*! MAX77620 partitions. */
+#define REGULATOR_SD0 0
+#define REGULATOR_SD1 1
+#define REGULATOR_SD2 2
+#define REGULATOR_SD3 3
+#define REGULATOR_LDO0 4
+#define REGULATOR_LDO1 5
+#define REGULATOR_LDO2 6
+#define REGULATOR_LDO3 7
+#define REGULATOR_LDO4 8
+#define REGULATOR_LDO5 9
+#define REGULATOR_LDO6 10
+#define REGULATOR_LDO7 11
+#define REGULATOR_LDO8 12
+#define REGULATOR_CPU0 13 // T210 CPU.
+#define REGULATOR_GPU0 14 // T210 CPU.
+#define REGULATOR_CPU1 15 // T210B01 CPU.
+#define REGULATOR_RAM0 16 // T210B01 RAM for PHASE211.
+//#define REGULATOR_GPU1 17 // T210B01 CPU.
+#define REGULATOR_MAX REGULATOR_RAM0
+
+#define MAX77621_CPU_I2C_ADDR 0x1B
+#define MAX77621_GPU_I2C_ADDR 0x1C
+
+#define MAX77621_REG_VOUT 0x00
+#define MAX77621_REG_VOUT_DVS 0x01
+#define MAX77621_REG_CONTROL1 0x02
+#define MAX77621_REG_CONTROL2 0x03
+#define MAX77621_REG_CHIPID1 0x04
+#define MAX77621_REG_CHIPID2 0x05
+
+/* MAX77621_VOUT_DVC_DVS */
+#define MAX77621_DVC_DVS_VOLT_MASK 0x7F
+#define MAX77621_DVC_DVS_ENABLE_SHIFT 7
+#define MAX77621_DVC_DVS_ENABLE_MASK (1 << MAX77621_DVC_DVS_ENABLE_SHIFT)
+
+/* MAX77621_VOUT */
+#define MAX77621_VOUT_DISABLE 0
+#define MAX77621_VOUT_ENABLE 1
+#define MAX77621_VOUT_ENABLE_MASK (MAX77621_VOUT_ENABLE << MAX77621_DVC_DVS_ENABLE_SHIFT)
+
+/* MAX77621_CONTROL1 */
+#define MAX77621_RAMP_12mV_PER_US 0x0
+#define MAX77621_RAMP_25mV_PER_US 0x1
+#define MAX77621_RAMP_50mV_PER_US 0x2
+#define MAX77621_RAMP_200mV_PER_US 0x3
+#define MAX77621_RAMP_MASK 0x3
+
+#define MAX77621_FREQSHIFT_9PER BIT(2)
+#define MAX77621_BIAS_ENABLE BIT(3)
+#define MAX77621_AD_ENABLE BIT(4)
+#define MAX77621_NFSR_ENABLE BIT(5)
+#define MAX77621_FPWM_EN_M BIT(6)
+#define MAX77621_SNS_ENABLE BIT(7)
+
+/* MAX77621_CONTROL2 */
+#define MAX77621_INDUCTOR_MIN_30_PER 0
+#define MAX77621_INDUCTOR_NOMINAL 1
+#define MAX77621_INDUCTOR_PLUS_30_PER 2
+#define MAX77621_INDUCTOR_PLUS_60_PER 3
+#define MAX77621_INDUCTOR_MASK 3
+
+#define MAX77621_CKKADV_TRIP_75mV_PER_US (0 << 2)
+#define MAX77621_CKKADV_TRIP_150mV_PER_US (1u << 2)
+#define MAX77621_CKKADV_TRIP_DISABLE (3u << 2)
+#define MAX77621_CKKADV_TRIP_MASK (3u << 2)
+
+#define MAX77621_FT_ENABLE BIT(4)
+#define MAX77621_DISCH_ENABLE BIT(5)
+#define MAX77621_WDTMR_ENABLE BIT(6)
+#define MAX77621_T_JUNCTION_120 BIT(7)
+
+#define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US)
+#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \
+ MAX77621_NFSR_ENABLE | \
+ MAX77621_SNS_ENABLE | \
+ MAX77621_RAMP_12mV_PER_US)
+#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \
+ MAX77621_FT_ENABLE | \
+ MAX77621_CKKADV_TRIP_DISABLE | \
+ MAX77621_INDUCTOR_NOMINAL)
+#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \
+ MAX77621_WDTMR_ENABLE | \
+ MAX77621_CKKADV_TRIP_75mV_PER_US | \
+ MAX77621_INDUCTOR_NOMINAL)
+
+#define MAX77621_CTRL_HOS_CFG 0
+#define MAX77621_CTRL_POR_CFG 1
+
+int max77620_regulator_get_status(u32 id);
+int max77620_regulator_config_fps(u32 id);
+int max7762x_regulator_set_voltage(u32 id, u32 uv);
+int max7762x_regulator_enable(u32 id, bool enable);
+void max77620_config_gpio(u32 id, bool enable);
+void max77620_config_default();
+void max77620_low_battery_monitor_config(bool enable);
+
+void max77621_config_default(u32 id, bool por);
+
+#endif
diff --git a/bdk/power/max77812.h b/bdk/power/max77812.h
new file mode 100644
index 0000000..b58e3ae
--- /dev/null
+++ b/bdk/power/max77812.h
@@ -0,0 +1,106 @@
+/*
+ * 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 .
+ */
+
+#ifndef _MAX77812_H_
+#define _MAX77812_H_
+
+#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // High power GPU. 2 Outputs: 3-phase M1 + 1-phase M4.
+#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // Low power GPU. 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4.
+
+#define MAX77812_REG_RSET 0x00
+#define MAX77812_REG_INT_SRC 0x01
+#define MAX77812_REG_INT_SRC_M 0x02
+#define MAX77812_REG_TOPSYS_INT 0x03
+#define MAX77812_REG_TOPSYS_INT_M 0x04
+#define MAX77812_REG_TOPSYS_STAT 0x05
+#define MAX77812_REG_EN_CTRL 0x06
+#define MAX77812_EN_CTRL_ENABLE 1
+#define MAX77812_EN_CTRL_EN_M1_SHIFT 0
+#define MAX77812_EN_CTRL_EN_M1_MASK (1 << MAX77812_EN_CTRL_EN_M1_SHIFT)
+#define MAX77812_EN_CTRL_EN_M2_SHIFT 2
+#define MAX77812_EN_CTRL_EN_M2_MASK (1 << MAX77812_EN_CTRL_EN_M2_SHIFT)
+#define MAX77812_EN_CTRL_EN_M3_SHIFT 4
+#define MAX77812_EN_CTRL_EN_M3_MASK (1 << MAX77812_EN_CTRL_EN_M3_SHIFT)
+#define MAX77812_EN_CTRL_EN_M4_SHIFT 6
+#define MAX77812_EN_CTRL_EN_M4_MASK (1 << MAX77812_EN_CTRL_EN_M4_SHIFT)
+#define MAX77812_REG_STUP_DLY2 0x07
+#define MAX77812_REG_STUP_DLY3 0x08
+#define MAX77812_REG_STUP_DLY4 0x09
+#define MAX77812_REG_SHDN_DLY1 0x0A
+#define MAX77812_REG_SHDN_DLY2 0x0B
+#define MAX77812_REG_SHDN_DLY3 0x0C
+#define MAX77812_REG_SHDN_DLY4 0x0D
+#define MAX77812_REG_WDTRSTB_DEB 0x0E
+#define MAX77812_REG_GPI_FUNC 0x0F
+#define MAX77812_REG_GPI_DEB1 0x10
+#define MAX77812_REG_GPI_DEB2 0x11
+#define MAX77812_REG_GPI_PD_CTRL 0x12
+#define MAX77812_REG_PROT_CFG 0x13
+#define MAX77812_REG_VERSION 0x14
+#define MAX77812_REG_I2C_CFG 0x15
+#define MAX77812_REG_BUCK_INT 0x20
+#define MAX77812_REG_BUCK_INT_M 0x21
+#define MAX77812_REG_BUCK_STAT 0x22
+#define MAX77812_REG_M1_VOUT 0x23 // GPU.
+#define MAX77812_REG_M2_VOUT 0x24
+#define MAX77812_REG_M3_VOUT 0x25 // DRAM on PHASE211.
+#define MAX77812_REG_M4_VOUT 0x26 // CPU.
+#define MAX77812_REG_M1_VOUT_D 0x27
+#define MAX77812_REG_M2_VOUT_D 0x28
+#define MAX77812_REG_M3_VOUT_D 0x29
+#define MAX77812_REG_M4_VOUT_D 0x2A
+#define MAX77812_REG_M1_VOUT_S 0x2B
+#define MAX77812_REG_M2_VOUT_S 0x2C
+#define MAX77812_REG_M3_VOUT_S 0x2D
+#define MAX77812_REG_M4_VOUT_S 0x2E
+#define MAX77812_REG_M1_CFG 0x2F // HOS: M1_ILIM - 7.2A/4.8A.
+#define MAX77812_REG_M2_CFG 0x30 // HOS: M2_ILIM - 7.2A/4.8A.
+#define MAX77812_REG_M3_CFG 0x31 // HOS: M3_ILIM - 7.2A/4.8A.
+#define MAX77812_REG_M4_CFG 0x32 // HOS: M4_ILIM - 7.2A/4.8A.
+#define MAX77812_REG_GLB_CFG1 0x33 // HOS: B_SD_SR/B_SS_SR - 5mV/us.
+#define MAX77812_REG_GLB_CFG2 0x34 // HOS: B_RD_SR/B_RU_SR - 5mV/us
+#define MAX77812_REG_GLB_CFG3 0x35
+
+/*! Protected area and settings only for MAX77812_ES2_VERSION */
+#define MAX77812_REG_GLB_CFG4 0x36 // QS: 0xBB.
+#define MAX77812_REG_GLB_CFG5 0x37 // QS: 0x39. ES2: Set to 0x3E.
+#define MAX77812_REG_GLB_CFG6 0x38 // QS: 0x88. ES2: Set to 0x90.
+#define MAX77812_REG_GLB_CFG7 0x39 // QS: 0x04.
+#define MAX77812_REG_GLB_CFG8 0x3A // QS: 0x3A. ES2: Set to 0x3A.
+
+#define MAX77812_REG_PROT_ACCESS 0xFD // 0x00: Lock, 0x5A: Unlock.
+#define MAX77812_REG_UNKNOWN 0xFE
+
+#define MAX77812_REG_EN_CTRL_MASK(n) BIT(n)
+#define MAX77812_START_SLEW_RATE_MASK 0x07
+#define MAX77812_SHDN_SLEW_RATE_MASK 0x70
+#define MAX77812_RAMPUP_SLEW_RATE_MASK 0x07
+#define MAX77812_RAMPDOWN_SLEW_RATE_MASK 0x70
+#define MAX77812_SLEW_RATE_SHIFT 4
+
+#define MAX77812_OP_ACTIVE_DISCHARGE_MASK BIT(7)
+#define MAX77812_PEAK_CURRENT_LMT_MASK 0x70
+#define MAX77812_SWITCH_FREQ_MASK 0x0C
+#define MAX77812_FORCED_PWM_MASK BIT(1)
+#define MAX77812_SLEW_RATE_CNTRL_MASK BIT(0)
+#define MAX77812_START_SHD_DELAY_MASK 0x1F
+#define MAX77812_VERSION_MASK 0x07
+#define MAX77812_ES2_VERSION 0x04
+#define MAX77812_QS_VERSION 0x05
+
+#define MAX77812_BUCK_VOLT_MASK 0xFF
+
+#endif
diff --git a/bdk/power/regulator_5v.c b/bdk/power/regulator_5v.c
new file mode 100644
index 0000000..55f81f7
--- /dev/null
+++ b/bdk/power/regulator_5v.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019-2023 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static u8 reg_5v_dev = 0;
+static bool usb_src = false;
+
+void regulator_5v_enable(u8 dev)
+{
+ bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
+
+ // The power supply selection from battery or USB is automatic.
+ if (!reg_5v_dev)
+ {
+ // Fan and Rail power from battery 5V regulator EN.
+ PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1;
+ gpio_direction_output(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
+
+ // Only Icosa has USB 5V VBUS rails.
+ if (tegra_t210)
+ {
+ // Fan and Rail power from USB 5V VBUS EN.
+ PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
+ gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
+ }
+
+ // Make sure GPIO IO power is enabled.
+ PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO;
+ (void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
+
+ // Inform GPIO IO pads that we switched to 1.8V.
+ PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_33V_GPIO;
+ (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
+
+ usb_src = false;
+ }
+ reg_5v_dev |= dev;
+}
+
+void regulator_5v_disable(u8 dev)
+{
+ bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
+
+ reg_5v_dev &= ~dev;
+
+ if (!reg_5v_dev)
+ {
+ // Rail power from battery 5V regulator.
+ gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
+
+ // Only Icosa has USB 5V VBUS rails.
+ if (tegra_t210)
+ {
+ // Rail power from USB 5V VBUS.
+ gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
+ usb_src = false;
+
+ }
+ }
+}
+
+bool regulator_5v_get_dev_enabled(u8 dev)
+{
+ return (reg_5v_dev & dev);
+}
+
+void regulator_5v_usb_src_enable(bool enable)
+{
+ // Only for Icosa.
+ if (hw_get_chip_id() != GP_HIDREV_MAJOR_T210)
+ return;
+
+ if (enable && !usb_src)
+ {
+ gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_HIGH);
+ usb_src = true;
+ }
+ else if (!enable && usb_src)
+ {
+ gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
+ usb_src = false;
+ }
+}
diff --git a/nyx/nyx_gui/power/regulator_5v.h b/bdk/power/regulator_5v.h
similarity index 72%
rename from nyx/nyx_gui/power/regulator_5v.h
rename to bdk/power/regulator_5v.h
index 7608881..527c18a 100644
--- a/nyx/nyx_gui/power/regulator_5v.h
+++ b/bdk/power/regulator_5v.h
@@ -17,18 +17,19 @@
#ifndef _REGULATOR_5V_H_
#define _REGULATOR_5V_H_
-#include "../utils/types.h"
+#include
enum
{
- REGULATOR_5V_FAN = (1 << 0),
- REGULATOR_5V_JC_R = (1 << 1),
- REGULATOR_5V_JC_L = (1 << 2),
+ REGULATOR_5V_FAN = BIT(0),
+ REGULATOR_5V_JC_R = BIT(1),
+ REGULATOR_5V_JC_L = BIT(2),
REGULATOR_5V_ALL = 0xFF
};
-void regulator_enable_5v(u8 dev);
-void regulator_disable_5v(u8 dev);
-bool regulator_get_5v_dev_enabled(u8 dev);
+void regulator_5v_enable(u8 dev);
+void regulator_5v_disable(u8 dev);
+bool regulator_5v_get_dev_enabled(u8 dev);
+void regulator_5v_usb_src_enable(bool enable);
#endif
\ No newline at end of file
diff --git a/nyx/nyx_gui/rtc/max77620-rtc.c b/bdk/rtc/max77620-rtc.c
similarity index 52%
rename from nyx/nyx_gui/rtc/max77620-rtc.c
rename to bdk/rtc/max77620-rtc.c
index 98243d2..6f813c0 100644
--- a/nyx/nyx_gui/rtc/max77620-rtc.c
+++ b/bdk/rtc/max77620-rtc.c
@@ -1,7 +1,7 @@
/*
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
*
- * Copyright (c) 2018-2019 CTCaer
+ * Copyright (c) 2018-2022 CTCaer
* Copyright (c) 2019 shchmue
*
* This program is free software; you can redistribute it and/or modify it
@@ -17,9 +17,18 @@
* along with this program. If not, see .
*/
-#include "max77620-rtc.h"
-#include "../soc/i2c.h"
-#include "../utils/util.h"
+#include
+#include
+#include
+#include
+#include
+
+int epoch_offset = 0;
+
+void max77620_rtc_prep_read()
+{
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
+}
void max77620_rtc_get_time(rtc_time_t *time)
{
@@ -35,10 +44,10 @@ void max77620_rtc_get_time(rtc_time_t *time)
// 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;
- time->hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG) & 0x1F;
-
- if (!(val & MAX77620_RTC_24H) && time->hour & MAX77620_RTC_HOUR_PM_MASK)
+ 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.
@@ -53,7 +62,7 @@ void max77620_rtc_get_time(rtc_time_t *time)
}
// Get date.
- time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f;
+ 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;
}
@@ -64,6 +73,7 @@ void max77620_rtc_stop_alarm()
// Update RTC regs from RTC clock.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
+ msleep(16);
// Stop alarm for both ALARM1 and ALARM2. Horizon uses ALARM2.
for (int i = 0; i < (MAX77620_RTC_NR_TIME_REGS * 2); i++)
@@ -82,9 +92,9 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
u32 tmp, edays, year, month, day;
// Set time.
- time->sec = epoch % 60;
+ time->sec = epoch % 60;
epoch /= 60;
- time->min = epoch % 60;
+ time->min = epoch % 60;
epoch /= 60;
time->hour = epoch % 24;
epoch /= 24;
@@ -99,14 +109,14 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
day = edays - month * 30 - month * 601 / 1000;
// Month/Year offset.
- if(month < 14)
+ if (month < 14)
{
year -= 4716;
month--;
}
else
{
- year -= 4715;
+ year -= 4715;
month -= 13;
}
@@ -119,7 +129,7 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
time->weekday = 0; //! TODO.
}
-u32 max77620_rtc_date_to_epoch(const rtc_time_t *time, bool hos_encoding)
+u32 max77620_rtc_date_to_epoch(const rtc_time_t *time)
{
u32 year, month, epoch;
@@ -128,42 +138,77 @@ u32 max77620_rtc_date_to_epoch(const rtc_time_t *time, bool hos_encoding)
//Month of year
month = time->month;
- if (!hos_encoding)
+ // Month/Year offset.
+ if (month < 3)
{
- // 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;
+ month += 12;
+ year--;
}
- epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days.
+ 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 += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days.
+ epoch -= 719561; // Epoch time is 1/1/1970.
epoch *= 86400; // Days to seconds.
epoch += (3600 * time->hour) + (60 * time->min) + time->sec; // Add hours, minutes and seconds.
return epoch;
}
+
+void max77620_rtc_get_time_adjusted(rtc_time_t *time)
+{
+ max77620_rtc_get_time(time);
+ if (epoch_offset)
+ {
+ u32 epoch = (u32)((s64)max77620_rtc_date_to_epoch(time) + epoch_offset);
+ max77620_rtc_epoch_to_date(epoch, time);
+ }
+}
+
+void max77620_rtc_set_epoch_offset(int offset)
+{
+ epoch_offset = offset;
+}
+
+void max77620_rtc_set_reboot_reason(rtc_reboot_reason_t *rr)
+{
+ max77620_rtc_stop_alarm();
+
+ // Set reboot reason.
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_YEAR_REG, rr->enc.val1);
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_YEAR_REG, rr->enc.val2);
+
+ // Set reboot reason magic.
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG, RTC_REBOOT_REASON_MAGIC);
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG, RTC_REBOOT_REASON_MAGIC);
+
+ // Update RTC clock from RTC regs.
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_WRITE_UPDATE);
+ msleep(16);
+}
+
+bool max77620_rtc_get_reboot_reason(rtc_reboot_reason_t *rr)
+{
+ u8 magic[2];
+
+ // Get reboot reason magic.
+ magic[0] = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG);
+ magic[1] = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG);
+
+ // Magic must be correct and match on both registers.
+ if (magic[0] != RTC_REBOOT_REASON_MAGIC || magic[0] != magic[1])
+ return false;
+
+ // Reboot reason setter is expected to have updated the actual regs already.
+ rr->enc.val1 = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_YEAR_REG);
+ rr->enc.val2 = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_YEAR_REG);
+
+ // Clear magic and update actual regs.
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG, 0);
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG, 0);
+ i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_WRITE_UPDATE);
+
+ // Return reboot reason. False if [config] was selected.
+ return true;
+}
diff --git a/bootloader/rtc/max77620-rtc.h b/bdk/rtc/max77620-rtc.h
similarity index 56%
rename from bootloader/rtc/max77620-rtc.h
rename to bdk/rtc/max77620-rtc.h
index 99199d2..b82c3e6 100644
--- a/bootloader/rtc/max77620-rtc.h
+++ b/bdk/rtc/max77620-rtc.h
@@ -1,7 +1,7 @@
/*
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
*
- * Copyright (c) 2018 CTCaer
+ * Copyright (c) 2018-2022 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,
@@ -19,25 +19,30 @@
#ifndef _MFD_MAX77620_RTC_H_
#define _MFD_MAX77620_RTC_H_
-#include "../utils/types.h"
+#include
#define MAX77620_RTC_I2C_ADDR 0x68
#define MAX77620_RTC_NR_TIME_REGS 7
+#define MAX77620_RTC_RTCINT_REG 0x00
+#define MAX77620_RTC_RTCINTM_REG 0x01
#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_BIN_FORMAT BIT(0)
+#define MAX77620_RTC_24H BIT(1)
#define MAX77620_RTC_UPDATE0_REG 0x04
-#define MAX77620_RTC_WRITE_UPDATE (1 << 0)
-#define MAX77620_RTC_READ_UPDATE (1 << 4)
+#define MAX77620_RTC_WRITE_UPDATE BIT(0)
+#define MAX77620_RTC_READ_UPDATE BIT(4)
+
+#define MAX77620_RTC_UPDATE1_REG 0x05
+#define MAX77620_RTC_RTCSMPL_REG 0x06
#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_HOUR_PM_MASK BIT(6)
#define MAX77620_RTC_WEEKDAY_REG 0x0A
#define MAX77620_RTC_MONTH_REG 0x0B
#define MAX77620_RTC_YEAR_REG 0x0C
@@ -57,7 +62,7 @@
#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)
+#define MAX77620_RTC_ALARM_EN_MASK BIT(7)
typedef struct _rtc_time_t {
u8 weekday;
@@ -69,9 +74,47 @@ typedef struct _rtc_time_t {
u16 year;
} rtc_time_t;
+#define RTC_REBOOT_REASON_MAGIC 0x77 // 7-bit reg.
+
+enum {
+ REBOOT_REASON_NOP = 0, // Use [config].
+ REBOOT_REASON_SELF = 1, // Use autoboot_idx/autoboot_list.
+ REBOOT_REASON_MENU = 2, // Force menu.
+ REBOOT_REASON_UMS = 3, // Force selected UMS partition.
+ REBOOT_REASON_REC = 4, // Set PMC_SCRATCH0_MODE_RECOVERY and reboot to self.
+ REBOOT_REASON_PANIC = 5 // Inform bootloader that panic occured if T210B01.
+};
+
+typedef struct _rtc_rr_decoded_t
+{
+ u16 reason:4;
+ u16 autoboot_idx:4;
+ u16 autoboot_list:1;
+ u16 ums_idx:3;
+} rtc_rr_decoded_t;
+
+typedef struct _rtc_rr_encoded_t
+{
+ u16 val1:6; // 6-bit reg.
+ u16 val2:6; // 6-bit reg.
+} rtc_rr_encoded_t;
+
+typedef struct _rtc_reboot_reason_t
+{
+ union {
+ rtc_rr_decoded_t dec;
+ rtc_rr_encoded_t enc;
+ };
+} rtc_reboot_reason_t;
+
+void max77620_rtc_prep_read();
void max77620_rtc_get_time(rtc_time_t *time);
+void max77620_rtc_get_time_adjusted(rtc_time_t *time);
+void max77620_rtc_set_epoch_offset(int offset);
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);
+u32 max77620_rtc_date_to_epoch(const rtc_time_t *time);
+void max77620_rtc_set_reboot_reason(rtc_reboot_reason_t *rr);
+bool max77620_rtc_get_reboot_reason(rtc_reboot_reason_t *rr);
#endif /* _MFD_MAX77620_RTC_H_ */
diff --git a/bdk/sec/se.c b/bdk/sec/se.c
new file mode 100644
index 0000000..4ed04ec
--- /dev/null
+++ b/bdk/sec/se.c
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2018 naehrwert
+ * Copyright (c) 2018-2025 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 .
+ */
+
+#include
+
+#include "se.h"
+#include