Compare commits
265 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01b6e645b3 | ||
|
|
db8c41cdaa | ||
|
|
b0fe84070f | ||
|
|
4d91d2baff | ||
|
|
c6fdb637ca | ||
|
|
bdd9e48606 | ||
|
|
25a7544010 | ||
|
|
821ad23341 | ||
|
|
981c986b3f | ||
|
|
09b3e47ac8 | ||
|
|
d2684f66a1 | ||
|
|
964381854e | ||
|
|
d8670fbd87 | ||
|
|
3c81ac91df | ||
|
|
147c82e0e2 | ||
|
|
339ce2d861 | ||
|
|
a7f0701cbf | ||
|
|
65b3b87c99 | ||
|
|
8d3700b76b | ||
|
|
d2595a00b6 | ||
|
|
c4bf129d5e | ||
|
|
503f4d4cd6 | ||
|
|
31d6c7d85d | ||
|
|
9a17ca2628 | ||
|
|
49bcaf3914 | ||
|
|
82d0346615 | ||
|
|
808da1bce0 | ||
|
|
6992ece762 | ||
|
|
734e70b755 | ||
|
|
681182540e | ||
|
|
9c29ee437a | ||
|
|
785baad5ea | ||
|
|
91b08f10fd | ||
|
|
c801ef8dda | ||
|
|
b47c01981f | ||
|
|
7e4c71748f | ||
|
|
a1910156d8 | ||
|
|
99d15eaac8 | ||
|
|
e31d6446db | ||
|
|
05ce867064 | ||
|
|
609a76045a | ||
|
|
000ea3096a | ||
|
|
0160df7fb9 | ||
|
|
05c989a1ce | ||
|
|
ebefd1c2d3 | ||
|
|
983d661da5 | ||
|
|
da08d00d21 | ||
|
|
6bd4c31965 | ||
|
|
af7bee2231 | ||
|
|
d61be73bca | ||
|
|
768b3ba2d9 | ||
|
|
0ff121284a | ||
|
|
bcc2512cb6 | ||
|
|
a2d18f0848 | ||
|
|
7fb10b0242 | ||
|
|
bcec028b0f | ||
|
|
8f9d52aa89 | ||
|
|
d368b93fdd | ||
|
|
d5322f384b | ||
|
|
03d027615c | ||
|
|
7fbab0122d | ||
|
|
f3f5687bc8 | ||
|
|
bbffcc20d7 | ||
|
|
197ed8c319 | ||
|
|
9363494c3f | ||
|
|
d8d32f7932 | ||
|
|
d575586d77 | ||
|
|
4326dcdc6c | ||
|
|
792a3511da | ||
|
|
9ba867f19e | ||
|
|
49943ee46f | ||
|
|
2a8c58af31 | ||
|
|
66cf88b967 | ||
|
|
f61e284ac0 | ||
|
|
9d69c9bd3f | ||
|
|
9258025eea | ||
|
|
063abb3e23 | ||
|
|
f5ec4a3a37 | ||
|
|
e9edcfeeb0 | ||
|
|
4b7e1f699d | ||
|
|
134f3dac52 | ||
|
|
1afb1a50c3 | ||
|
|
4914ce1d49 | ||
|
|
70a06a6cae | ||
|
|
5044f014bf | ||
|
|
7c72c9777a | ||
|
|
73df5e6743 | ||
|
|
9cf0b0f484 | ||
|
|
9541d1bbd3 | ||
|
|
3e15eb44ab | ||
|
|
bf89d9b841 | ||
|
|
d8995ee9c0 | ||
|
|
42f86cf82c | ||
|
|
a704679990 | ||
|
|
5876e1765d | ||
|
|
dcdf687a07 | ||
|
|
e94bd23d6f | ||
|
|
cd5b93feb1 | ||
|
|
f231173ebe | ||
|
|
561a96c62a | ||
|
|
57e6623d74 | ||
|
|
57623acc99 | ||
|
|
4f8d29d0b7 | ||
|
|
8eda2d805f | ||
|
|
432d4a4ffa | ||
|
|
539caf3d83 | ||
|
|
ce6926c36c | ||
|
|
8058d550ab | ||
|
|
9a21ff6976 | ||
|
|
1f4f41b6e6 | ||
|
|
a959196c2a | ||
|
|
3f22601022 | ||
|
|
a80a7ecba9 | ||
|
|
7c450f4a5f | ||
|
|
6316d3076d | ||
|
|
7181683d8e | ||
|
|
7d7134dd9e | ||
|
|
c29db97f73 | ||
|
|
05833bb38c | ||
|
|
253de81a6b | ||
|
|
21e6a0cf7e | ||
|
|
d0fefabad7 | ||
|
|
44db160ab1 | ||
|
|
cb633a8f32 | ||
|
|
66b7130641 | ||
|
|
80d9718770 | ||
|
|
dfbbca4c9f | ||
|
|
f4d08b2d9b | ||
|
|
588a834ae4 | ||
|
|
833dda7e7c | ||
|
|
6a4ab55930 | ||
|
|
d7ce2a81db | ||
|
|
4d90fa4830 | ||
|
|
501fdda138 | ||
|
|
678e8d34e3 | ||
|
|
07d1982abf | ||
|
|
fd05f83636 | ||
|
|
94e119fb51 | ||
|
|
c2ff4bf623 | ||
|
|
faf5651607 | ||
|
|
978e8344cf | ||
|
|
160d6eacc0 | ||
|
|
075d8e6393 | ||
|
|
28008ac7ac | ||
|
|
345d36287e | ||
|
|
edff6c551d | ||
|
|
d42a94f148 | ||
|
|
c01b8aa89c | ||
|
|
4958bd6a52 | ||
|
|
46038032a4 | ||
|
|
f66ddca100 | ||
|
|
6981c59de3 | ||
|
|
f21f13b15d | ||
|
|
ef5a01433d | ||
|
|
0e12d8545b | ||
|
|
9dbf745649 | ||
|
|
e8f73a42b8 | ||
|
|
dbe431095a | ||
|
|
513f77a2ad | ||
|
|
e8cf85bd65 | ||
|
|
be23d1fa15 | ||
|
|
4e7e5081a7 | ||
|
|
fff750e609 | ||
|
|
38ce46a158 | ||
|
|
7a27a7b3b5 | ||
|
|
c6ec175045 | ||
|
|
3b9ab66cf1 | ||
|
|
b6e458e97b | ||
|
|
c5152f6a9d | ||
|
|
e5689cfe57 | ||
|
|
f3f1d4d4f0 | ||
|
|
796b15a861 | ||
|
|
add351289a | ||
|
|
a4a056128a | ||
|
|
6e314933d9 | ||
|
|
a31bedda97 | ||
|
|
a25c82a8ce | ||
|
|
8ccc47dfa5 | ||
|
|
9de5a4ba66 | ||
|
|
84e437ae5b | ||
|
|
9e34c5995d | ||
|
|
497bbdf3cd | ||
|
|
8683a0ff58 | ||
|
|
874c801772 | ||
|
|
eea5463a5c | ||
|
|
af790aeaf8 | ||
|
|
a8a45b215a | ||
|
|
38f456a2ee | ||
|
|
a980eac647 | ||
|
|
ea83566fc9 | ||
|
|
0857d7ff0e | ||
|
|
48e98ab8c9 | ||
|
|
8cd438146d | ||
|
|
a80cc0ae2c | ||
|
|
2428736bfa | ||
|
|
a7bf8bf118 | ||
|
|
8038e1faa9 | ||
|
|
15a7e49dde | ||
|
|
8b30bd4b57 | ||
|
|
63d03303a2 | ||
|
|
0e40fef049 | ||
|
|
1a50425475 | ||
|
|
8fc5267110 | ||
|
|
f6a3b2c9ac | ||
|
|
7aa1e77642 | ||
|
|
2370ca0a44 | ||
|
|
abcf7f6f57 | ||
|
|
d1f0ea3de7 | ||
|
|
dbc8f4a4c2 | ||
|
|
c6c396ce2a | ||
|
|
74b91b0085 | ||
|
|
53c9ca8072 | ||
|
|
13e5216a4e | ||
|
|
147ccd3070 | ||
|
|
dc5c26e7c6 | ||
|
|
4914af1200 | ||
|
|
b57d26e99a | ||
|
|
f196b8bb0e | ||
|
|
7b460f7e56 | ||
|
|
9daa14abec | ||
|
|
bf8fd9a33b | ||
|
|
1f37b96359 | ||
|
|
46921aca22 | ||
|
|
41f96d4305 | ||
|
|
0959dc3a2d | ||
|
|
31baf3d19a | ||
|
|
f4696da0ef | ||
|
|
83ab79c51e | ||
|
|
745ac609d2 | ||
|
|
0f9aa51afe | ||
|
|
9fbb28e887 | ||
|
|
adf2045896 | ||
|
|
1a797bf93a | ||
|
|
1a9372b4ce | ||
|
|
87b91174ec | ||
|
|
26fff275ce | ||
|
|
53b44a525d | ||
|
|
8ce5d55eb8 | ||
|
|
afb749560a | ||
|
|
7a66e0298a | ||
|
|
e491a4cf57 | ||
|
|
b7789f1edb | ||
|
|
4949331f4c | ||
|
|
2c695e9a96 | ||
|
|
faaf801534 | ||
|
|
3fa775e3ad | ||
|
|
6663330de3 | ||
|
|
ed916360eb | ||
|
|
e4bc5c41ce | ||
|
|
d0d943c9c3 | ||
|
|
60b629e57f | ||
|
|
df80339060 | ||
|
|
cbbd427d3a | ||
|
|
dfcdb2e1e6 | ||
|
|
11ca6caf5f | ||
|
|
15afdf53e4 | ||
|
|
d15f958b48 | ||
|
|
5fd3bdede7 | ||
|
|
e2dd218f33 | ||
|
|
a85891ae00 | ||
|
|
2628044ba8 | ||
|
|
e620783a89 | ||
|
|
2fba9848ae | ||
|
|
52c65661d8 | ||
|
|
601c85c23e |
9
Makefile
9
Makefile
@@ -47,7 +47,7 @@ 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 pkg2_ini_kippatch.o fss.o secmon_exo.o \
|
||||
)
|
||||
|
||||
# Libraries.
|
||||
@@ -73,8 +73,11 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
|
||||
# DEBUG_UART_PORT - 0: UART_A, 1: UART_B, 2: UART_C.
|
||||
#CUSTOMDEFINES += -DDEBUG_UART_BAUDRATE=115200 -DDEBUG_UART_INVERT=0 -DDEBUG_UART_PORT=0
|
||||
|
||||
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
|
||||
WARNINGS := -Wall -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
|
||||
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||
CFLAGS = $(ARCH) -O2 -g -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES)
|
||||
CFLAGS = $(ARCH) -O2 -g -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
|
||||
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
|
||||
|
||||
MODULEDIRS := $(wildcard modules/*)
|
||||
@@ -103,7 +106,7 @@ all: $(TARGET).bin $(LDRDIR)
|
||||
@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)
|
||||
|
||||
210
README.md
210
README.md
@@ -6,33 +6,61 @@
|
||||
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
|
||||
|
||||
| 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! |
|
||||
| bootloader/sys/ | hekate and Nyx system modules folder. |
|
||||
| \|__ 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! |
|
||||
| \|__ libsys_minerva.bso | Minerva Training Cell. Used for DRAM Frequency training. !Important! |
|
||||
| \|__ nyx.bin | Nyx - hekate's GUI. !Important! |
|
||||
| \|__ res.pak | Nyx resources package. !Important! |
|
||||
| \|__ thk.bin | Atmosphère Tsec Hovi Keygen. !Important! |
|
||||
| bootloader/screenshots/ | Folder where Nyx screenshots are saved |
|
||||
| bootloader/payloads/ | For payloads. 'Payloads...' menu. Autoboot only supported by including them into an ini. All CFW bootloaders, tools, Linux payloads are supported. |
|
||||
| bootloader/libtools/ | Future reserved |
|
||||
| sept | Sept folder. This must 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,16 +71,16 @@ 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. |
|
||||
| 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. |
|
||||
| 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. |
|
||||
| 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. |
|
||||
@@ -60,7 +88,81 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
|
||||
| backlight=100 | Screen backlight level. 0-255. |
|
||||
|
||||
|
||||
### Nyx Global Configuration keys/values for (nyx.ini):
|
||||
### Boot entry key/value combinations:
|
||||
|
||||
| Config option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
| 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. |
|
||||
| fss0={FILE path} | Takes an Atmosphere `package3` binary (formerly fusee-secondary.bin) and `extracts` all needed parts from it. kips, exosphere, warmboot and mesophere if enabled. |
|
||||
| fss0experimental=1 | Enables loading of experimental content from a FSS0 storage |
|
||||
| exofatal={FILE path} | Replaces the exosphere fatal binary for Mariko |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
| kip1patch=patchname | Enables a kip1 patch. Specify with multiple lines and/or in one line with `,` 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 | Disables unneeded kernel patching and CFW kips when running stock or semi-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. Not needed when `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. |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
| 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`.
|
||||
You can define `kip1` to load an extra kip or many via the wildcard (`/*`) usage.
|
||||
|
||||
**Warning**: Careful when you define *fss0 core* kips when using `fss0` or the folder (when using `/*`) includes 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). In such cases, the `kip1` line must be under `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:
|
||||
|
||||
| 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 and only has the `[config]` entry.
|
||||
|
||||
|
||||
### Nyx Configuration keys/values (nyx.ini):
|
||||
|
||||
| Config option | Description |
|
||||
| ------------------ | ---------------------------------------------------------- |
|
||||
@@ -70,78 +172,14 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
|
||||
| verification=1 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and mostly reliable), 2: Full (sha256 based, slow and 100% reliable). |
|
||||
| umsemmcrw=0 | 1: eMMC/emuMMC UMS will be mounted as writable by default. |
|
||||
| jcdisable=0 | 1: Disables Joycon driver completely. |
|
||||
| newpowersave=1 | 0: Timer based, 1: DRAM frequency based (Better). Use 0 if Nyx hangs. |
|
||||
|
||||
|
||||
### Boot entry key/value combinations:
|
||||
|
||||
| Config option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
| warmboot={SD path} | Replaces the warmboot binary |
|
||||
| secmon={SD path} | Replaces the security monitor binary |
|
||||
| kernel={SD path} | Replaces the kernel binary |
|
||||
| kip1={SD path} | Replaces/Adds kernel initial process. Multiple can be set. |
|
||||
| kip1={SD folder}/* | Loads every .kip/.kip1 inside a folder. Compatible with single kip1 keys. |
|
||||
| fss0={SD path} | Takes a fusee-secondary binary and `extracts` all needed parts from it. kips, exosphere, warmboot and sept. |
|
||||
| fss0experimental=1 | Enables loading of experimental content from a FSS0 storage |
|
||||
| exofatal={SD path} | Replaces the exosphere fatal binary for Mariko |
|
||||
| kip1patch=patchname | Enables a kip1 patch. Specify with multiple lines and/or as CSV. If not found, an error will show up |
|
||||
| fullsvcperm=1 | Disables SVC verification (full services permission) |
|
||||
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
|
||||
| atmosphere=1 | Enables Atmosphère patching. |
|
||||
| emupath={SD folder} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
|
||||
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
|
||||
| emummc_force_disable=1 | Disables emuMMC, if it's enabled. |
|
||||
| stock=1 | Disables unneeded kernel patching when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disabled=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
||||
| id=idname | Identifies boot entry for forced boot via id. Max 7 chars. |
|
||||
| payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. |
|
||||
| logopath={SD path} | If no logopath, `bootloader/bootlogo.bmp` will be used if exists. If logopath exists, it will load the specified bitmap. |
|
||||
| icon={SD path} | Force Nyx to use the icon defined here. If this is not found, it will check for a bmp named as the boot entry ([Test 2] -> `bootloader/res/Test 2.bmp`). Otherwise default will be used. |
|
||||
|
||||
|
||||
### Boot entry key/value Exosphère combinations:
|
||||
|
||||
| Config option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
| nouserexceptions=1 | Disables usermode exception handlers when paired with Exosphère. |
|
||||
| userpmu=1 | Enables user access to PMU when paired with Exosphère. |
|
||||
| cal0blank=1 | Overrides Exosphère config `blank_prodinfo_{sys/emu}mmc`. If that key doesn't exist, `exosphere.ini` will be used. |
|
||||
| cal0writesys=1 | Overrides Exosphère config `allow_writing_to_cal_sysmmc`. If that key doesn't exist, `exosphere.ini` will be used. |
|
||||
|
||||
|
||||
**Note1**: When using the wildcard (`/*`) with `kip1` you can still use the normal `kip1` after that to load extra single kips.
|
||||
|
||||
**Note2**: When using FSS0 it parses exosphere, warmboot and all core kips. You can override the first 2 by using `secmon`/`warmboot` after defining `fss0`.
|
||||
You can define `kip1` to load an extra kip or many via the wildcard (`/*`) usage.
|
||||
|
||||
**Warning**: Never define *fss0 core* kips when using `fss0` and make sure that the folder (when using `/*`), does not include them.
|
||||
This is in case the kips are incompatible between them. If compatible, you can override `fss0` kips with no issues (useful for testing with intermediate kip changes).
|
||||
|
||||
|
||||
### Payload storage:
|
||||
|
||||
hekate has a boot storage in the binary that helps it configure it outside of BPMP enviroment:
|
||||
|
||||
| Offset / Name | Description |
|
||||
| ----------------------- | ----------------------------------------------------------------- |
|
||||
| '0x94' boot_cfg | bit0: `Force AutoBoot`, bit1: `Show launch log`, bit2: `Boot from ID`, bit3: `Boot to emuMMC`, bit7: `sept run`. |
|
||||
| '0x95' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. |
|
||||
| '0x96' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. |
|
||||
| '0x97' extra_cfg | When menu is forced: bit5: `Run UMS`, bit7: `Run Dump pkg1/2`. |
|
||||
| '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.
|
||||
| bpmpclock=1 | 0: Auto, 1: Faster, 2: Fast. Use 2 if Nyx hangs or some functions like UMS/Backup Verification fail. |
|
||||
|
||||
|
||||
```
|
||||
hekate (c) 2018, naehrwert, st4rk.
|
||||
(c) 2018-2020, CTCaer.
|
||||
(c) 2018-2021, CTCaer.
|
||||
|
||||
Nyx GUI (c) 2019-2020, CTCaer.
|
||||
Nyx GUI (c) 2019-2021, CTCaer.
|
||||
|
||||
Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8.
|
||||
Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
|
||||
|
||||
@@ -11,6 +11,7 @@ Lastly, the supported format is 32-bit (ARGB) BMP. Classic 24-bit (RGB) BMPs are
|
||||
|
||||
## 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 is 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.
|
||||
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.
|
||||
|
||||
10
Versions.inc
10
Versions.inc
@@ -1,11 +1,11 @@
|
||||
# IPL Version.
|
||||
BLVERSION_MAJOR := 5
|
||||
BLVERSION_MINOR := 5
|
||||
BLVERSION_HOTFX := 1
|
||||
BLVERSION_MINOR := 6
|
||||
BLVERSION_HOTFX := 5
|
||||
BLVERSION_RSVD := 0
|
||||
|
||||
# Nyx Version.
|
||||
NYXVERSION_MAJOR := 0
|
||||
NYXVERSION_MINOR := 9
|
||||
NYXVERSION_HOTFX := 7
|
||||
NYXVERSION_MAJOR := 1
|
||||
NYXVERSION_MINOR := 1
|
||||
NYXVERSION_HOTFX := 1
|
||||
NYXVERSION_RSVD := 0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -20,7 +20,9 @@
|
||||
#include "di.h"
|
||||
#include <power/max77620.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <mem/heap.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/i2c.h>
|
||||
@@ -34,6 +36,7 @@
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
static u32 _display_id = 0;
|
||||
static bool nx_aula = false;
|
||||
|
||||
static void _display_panel_and_hw_end(bool no_panel_deinit);
|
||||
|
||||
@@ -90,7 +93,7 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
|
||||
// Wait for vblank before starting the transfer.
|
||||
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
|
||||
while (DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)
|
||||
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
|
||||
;
|
||||
}
|
||||
|
||||
@@ -133,19 +136,22 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
case DCS_2_BYTE_SHORT_RD_RES:
|
||||
memcpy(data, &fifo[2], 2);
|
||||
break;
|
||||
|
||||
case ACK_ERROR_RES:
|
||||
default:
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
res = 1;
|
||||
|
||||
// Disable host cmd packets during video and restore host control.
|
||||
if (video_enabled)
|
||||
{
|
||||
// Wait for vblank before reseting sync points.
|
||||
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
|
||||
while (DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)
|
||||
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
|
||||
;
|
||||
|
||||
// Reset all states of syncpt block.
|
||||
@@ -170,9 +176,9 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
|
||||
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
{
|
||||
u8 *fifo8;
|
||||
u32 *fifo32;
|
||||
u32 host_control;
|
||||
u32 fifo32[DSI_STATUS_RX_FIFO_SIZE] = {0};
|
||||
u8 *fifo8 = (u8 *)fifo32;
|
||||
|
||||
// Enable host cmd packets during video and save host control.
|
||||
if (video_enabled)
|
||||
@@ -180,7 +186,7 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
|
||||
|
||||
// Enable host transfer trigger.
|
||||
DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_TX_TRIG_HOST;
|
||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control | DSI_HOST_CONTROL_TX_TRIG_HOST;
|
||||
|
||||
switch (len)
|
||||
{
|
||||
@@ -193,6 +199,8 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
break;
|
||||
|
||||
default:
|
||||
fifo32 = calloc(DSI_STATUS_RX_FIFO_SIZE * 8, 4);
|
||||
fifo8 = (u8 *)fifo32;
|
||||
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
|
||||
fifo8[4] = cmd;
|
||||
memcpy(&fifo8[5], data, len);
|
||||
@@ -200,6 +208,7 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
free(fifo32);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -212,10 +221,73 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
|
||||
}
|
||||
|
||||
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
|
||||
{
|
||||
u8 *fifo8;
|
||||
u32 *fifo32;
|
||||
|
||||
// Enable vblank interrupt.
|
||||
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = DC_CMD_INT_FRAME_END_INT;
|
||||
|
||||
// Use the 4th line to transmit the host cmd packet.
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE | DSI_DSI_LINE_TYPE(4);
|
||||
|
||||
// Wait for vblank before starting the transfer.
|
||||
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
|
||||
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
|
||||
;
|
||||
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = (cmd << 8) | MIPI_DSI_DCS_SHORT_WRITE;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = ((cmd | (*(u8 *)data << 8)) << 8) | MIPI_DSI_DCS_SHORT_WRITE_PARAM;
|
||||
break;
|
||||
|
||||
default:
|
||||
fifo32 = calloc(DSI_STATUS_RX_FIFO_SIZE * 8, 4);
|
||||
fifo8 = (u8 *)fifo32;
|
||||
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
|
||||
fifo8[4] = cmd;
|
||||
memcpy(&fifo8[5], data, len);
|
||||
len += 4 + 1; // Increase length by CMD/length word and DCS CMD.
|
||||
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
|
||||
free(fifo32);
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait for vblank before reseting sync points.
|
||||
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
|
||||
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
|
||||
;
|
||||
|
||||
// Reset all states of syncpt block.
|
||||
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET;
|
||||
usleep(300); // Stabilization delay.
|
||||
|
||||
// Clear syncpt block reset.
|
||||
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0;
|
||||
usleep(300); // Stabilization delay.
|
||||
|
||||
// Restore video mode and host control.
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
|
||||
|
||||
// Disable and clear vblank interrupt.
|
||||
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT;
|
||||
}
|
||||
|
||||
void display_init()
|
||||
{
|
||||
// Get Hardware type, as it's used in various DI functions.
|
||||
nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA;
|
||||
|
||||
// Check if display is already initialized.
|
||||
if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & BIT(CLK_L_DISP1))
|
||||
if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1))
|
||||
_display_panel_and_hw_end(true);
|
||||
|
||||
// Get Chip ID.
|
||||
@@ -225,19 +297,20 @@ void display_init()
|
||||
if (!tegra_t210)
|
||||
{
|
||||
// Set SD2 regulator voltage.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD2, 1325000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD2, 1325000);
|
||||
|
||||
// Set slew rate and enable SD2 regulator.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE);
|
||||
max77620_regulator_enable(REGULATOR_SD2, 1);
|
||||
max7762x_regulator_enable(REGULATOR_SD2, true);
|
||||
|
||||
}
|
||||
|
||||
// Enable power to display panel controller.
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V.
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO0, true);
|
||||
|
||||
if (tegra_t210)
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7,
|
||||
MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); // T210: LD0 -> GPIO7 -> Display panel.
|
||||
max77620_config_gpio(7, MAX77620_GPIO_OUTPUT_ENABLE); // T210: LD0 -> GPIO7 -> Display panel.
|
||||
|
||||
// Enable Display Interface specific clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
|
||||
@@ -265,22 +338,31 @@ void display_init()
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; // PULL_DOWN | 1
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
|
||||
// Set LCD +-5V pins mode and direction
|
||||
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE);
|
||||
if (nx_aula)
|
||||
{
|
||||
// Configure LCD RST pin.
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_2, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set LCD +-5V pins mode and direction
|
||||
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE);
|
||||
|
||||
// Enable LCD power.
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // LCD +5V enable.
|
||||
usleep(10000);
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // LCD -5V enable.
|
||||
usleep(10000);
|
||||
// Enable LCD power.
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // LCD +5V enable.
|
||||
usleep(10000);
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // LCD -5V enable.
|
||||
usleep(10000);
|
||||
|
||||
// Configure Backlight PWM/EN and LCD RST pins (BL PWM, BL EN, LCD RST).
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
|
||||
// Configure Backlight PWM/EN and LCD RST pins (BL PWM, BL EN, LCD RST).
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
|
||||
|
||||
// Enable Backlight power.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH);
|
||||
// Enable Backlight power.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH);
|
||||
}
|
||||
|
||||
// Power up supply regulator for display interface.
|
||||
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0;
|
||||
@@ -293,7 +375,7 @@ void display_init()
|
||||
|
||||
// Set DISP1 clock source and parent clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT.
|
||||
u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 96 MHz.
|
||||
u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 97.5 MHz (offset).
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
|
||||
if (tegra_t210)
|
||||
@@ -331,32 +413,18 @@ void display_init()
|
||||
usleep(60000);
|
||||
|
||||
// Setup DSI device takeover timeout.
|
||||
DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204;
|
||||
DSI(_DSIREG(DSI_BTA_TIMING)) = nx_aula ? 0x40103 : 0x50204;
|
||||
|
||||
#if 0
|
||||
// Get Display ID.
|
||||
_display_id = 0xCCCCCC;
|
||||
display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED);
|
||||
#else
|
||||
// Set reply size.
|
||||
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0);
|
||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||
|
||||
// Request register read.
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_READ, MIPI_DCS_GET_DISPLAY_ID, 0);
|
||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||
|
||||
// Transfer bus control to device for transmitting the reply.
|
||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
|
||||
_display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA);
|
||||
|
||||
// Wait a bit for the reply.
|
||||
usleep(5000);
|
||||
|
||||
// MIPI_DCS_GET_DISPLAY_ID reply is a long read, size 3 x u32.
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
_display_id = DSI(_DSIREG(DSI_RD_DATA)) & 0xFFFFFF; // Skip ack and msg type info and get the payload (display id).
|
||||
#endif
|
||||
{
|
||||
if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED))
|
||||
break;
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
// Save raw Display ID to Nyx storage.
|
||||
nyx_str->info.disp_id = _display_id;
|
||||
|
||||
@@ -366,9 +434,23 @@ void display_init()
|
||||
if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
|
||||
_display_id = PANEL_JDI_XXX062M;
|
||||
|
||||
// For Aula ensure that we have a compatible panel id.
|
||||
if (nx_aula && _display_id == 0xCCCC)
|
||||
_display_id = PANEL_SAM_AMS699VC01;
|
||||
|
||||
// Initialize display panel.
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_SAM_AMS699VC01:
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0xA0, 0); // Write 0 to 0xA0.
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_SET_CONTROL_DISPLAY | (DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL << 8), 0); // Enable brightness control.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x339; // MIPI_DSI_DCS_LONG_WRITE: 3 bytes.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x000051; // MIPI_DCS_SET_BRIGHTNESS 0000: 0%. FF07: 100%.
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
break;
|
||||
|
||||
case PANEL_JDI_XXX062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43);
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
@@ -407,11 +489,11 @@ void display_init()
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
|
||||
|
||||
// Configure PLLD for DISP1.
|
||||
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 230.4 MHz.
|
||||
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset, it's ddr btw, so normally div2).
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
|
||||
if (tegra_t210)
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP.
|
||||
else
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN.
|
||||
@@ -420,7 +502,7 @@ void display_init()
|
||||
DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0;
|
||||
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603;
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 19);
|
||||
// Set pixel clock dividers: 230.4 / 3 / 1 = 76.8 MHz. 60 Hz.
|
||||
// Set pixel clock dividers: 234 / 3 / 1 = 78 MHz (offset) for 60 Hz.
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10);
|
||||
usleep(10000);
|
||||
@@ -457,6 +539,9 @@ void display_init()
|
||||
|
||||
void display_backlight_pwm_init()
|
||||
{
|
||||
if (_display_id == PANEL_SAM_AMS699VC01)
|
||||
return;
|
||||
|
||||
clock_enable_pwm();
|
||||
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM. 29.5KHz is stock.
|
||||
@@ -470,20 +555,27 @@ void display_backlight(bool enable)
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); // Backlight PWM GPIO.
|
||||
}
|
||||
|
||||
void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
void display_dsi_backlight_brightness(u32 brightness)
|
||||
{
|
||||
// Normalize brightness value by 82% and a base of 45 duty.
|
||||
if (brightness)
|
||||
brightness = (brightness * PANEL_OLED_BL_COEFF / 100) + PANEL_OLED_BL_OFFSET;
|
||||
|
||||
u16 bl_ctrl = byte_swap_16((u16)(brightness * 8));
|
||||
display_dsi_vblank_write(MIPI_DCS_SET_BRIGHTNESS, 2, &bl_ctrl);
|
||||
}
|
||||
|
||||
void display_pwm_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
{
|
||||
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF;
|
||||
if (brightness == old_value)
|
||||
return;
|
||||
|
||||
if (brightness > 255)
|
||||
brightness = 255;
|
||||
|
||||
if (old_value < brightness)
|
||||
{
|
||||
for (u32 i = old_value; i < brightness + 1; i++)
|
||||
{
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
|
||||
usleep(step_delay);
|
||||
}
|
||||
}
|
||||
@@ -491,7 +583,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
{
|
||||
for (u32 i = old_value; i > brightness; i--)
|
||||
{
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
|
||||
usleep(step_delay);
|
||||
}
|
||||
}
|
||||
@@ -499,6 +591,22 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
|
||||
}
|
||||
|
||||
void display_backlight_brightness(u32 brightness, u32 step_delay)
|
||||
{
|
||||
if (brightness > 255)
|
||||
brightness = 255;
|
||||
|
||||
if (_display_id != PANEL_SAM_AMS699VC01)
|
||||
display_pwm_backlight_brightness(brightness, step_delay);
|
||||
else
|
||||
display_dsi_backlight_brightness(brightness);
|
||||
}
|
||||
|
||||
u32 display_get_backlight_brightness()
|
||||
{
|
||||
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
static void _display_panel_and_hw_end(bool no_panel_deinit)
|
||||
{
|
||||
if (no_panel_deinit)
|
||||
@@ -519,7 +627,9 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
|
||||
// De-initialize video controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_disable_config, 17);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_timing_deinit_config, 16);
|
||||
usleep(10000);
|
||||
|
||||
if (_display_id != PANEL_SAM_AMS699VC01)
|
||||
usleep(10000);
|
||||
|
||||
// De-initialize display panel.
|
||||
switch (_display_id)
|
||||
@@ -571,16 +681,23 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
|
||||
}
|
||||
|
||||
// Blank - powerdown.
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE, 50000);
|
||||
_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);
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD -5V disable.
|
||||
usleep(10000);
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD +5V disable.
|
||||
usleep(10000);
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); // LCD Reset disable.
|
||||
|
||||
if (!nx_aula) // HOS uses panel id.
|
||||
{
|
||||
usleep(10000);
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD -5V disable.
|
||||
usleep(10000);
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD +5V disable.
|
||||
usleep(10000);
|
||||
}
|
||||
else
|
||||
usleep(30000); // Aula Panel.
|
||||
|
||||
// Disable Display Interface specific clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
|
||||
@@ -593,9 +710,12 @@ skip_panel_deinit:
|
||||
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
|
||||
|
||||
// Switch LCD PWM backlight pin to special function mode and enable PWM0 mode.
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode.
|
||||
if (!nx_aula)
|
||||
{
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode.
|
||||
}
|
||||
}
|
||||
|
||||
void display_end() { _display_panel_and_hw_end(false); };
|
||||
@@ -607,11 +727,18 @@ u16 display_get_decoded_panel_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)
|
||||
@@ -624,9 +751,12 @@ void display_color_screen(u32 color)
|
||||
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ;
|
||||
usleep(35000);
|
||||
usleep(35000); // No need to wait on Aula.
|
||||
|
||||
display_backlight(true);
|
||||
if (_display_id != PANEL_SAM_AMS699VC01)
|
||||
display_backlight(true);
|
||||
else
|
||||
display_backlight_brightness(255, 0);
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_pitch()
|
||||
@@ -636,7 +766,7 @@ u32 *display_init_framebuffer_pitch()
|
||||
|
||||
// This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 32);
|
||||
usleep(35000);
|
||||
usleep(35000); // No need to wait on Aula.
|
||||
|
||||
return (u32 *)IPL_FB_ADDRESS;
|
||||
}
|
||||
@@ -645,8 +775,7 @@ u32 *display_init_framebuffer_pitch_inv()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch_inv, 34);
|
||||
|
||||
usleep(35000);
|
||||
usleep(35000); // No need to wait on Aula.
|
||||
|
||||
return (u32 *)NYX_FB_ADDRESS;
|
||||
}
|
||||
@@ -655,8 +784,7 @@ u32 *display_init_framebuffer_block()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_block, 34);
|
||||
|
||||
usleep(35000);
|
||||
usleep(35000); // No need to wait on Aula.
|
||||
|
||||
return (u32 *)NYX_FB_ADDRESS;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -547,17 +547,17 @@
|
||||
#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
|
||||
#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
|
||||
#define MIPI_DCS_GET_POWER_MODE 0x0A
|
||||
#define MIPI_DCS_GET_ADDRESS_MODE 0x0B
|
||||
#define MIPI_DCS_GET_PIXEL_FORMAT 0x0C
|
||||
#define MIPI_DCS_GET_DISPLAY_MODE 0x0D
|
||||
#define MIPI_DCS_GET_SIGNAL_MODE 0x0E
|
||||
#define MIPI_DCS_GET_DIAGNOSTIC_RESULT 0x0F
|
||||
#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
|
||||
@@ -567,7 +567,7 @@
|
||||
#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
|
||||
#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
|
||||
@@ -580,11 +580,11 @@
|
||||
#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
|
||||
#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
|
||||
#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
|
||||
@@ -593,26 +593,34 @@
|
||||
#define MIPI_DCS_GET_SCANLINE 0x45
|
||||
#define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46
|
||||
#define MIPI_DCS_GET_SCANLINE_WIDTH 0x47
|
||||
#define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL.
|
||||
#define MIPI_DCS_GET_BRIGHTNESS 0x52
|
||||
#define MIPI_DCS_SET_CONTROL_DISPLAY 0x53
|
||||
#define MIPI_DCS_GET_CONTROL_DISPLAY 0x54
|
||||
#define MIPI_DCS_SET_CABC_VALUE 0x55
|
||||
#define MIPI_DCS_GET_CABC_VALUE 0x56
|
||||
#define MIPI_DCS_SET_CABC_MIN_BRI 0x5E
|
||||
#define MIPI_DCS_GET_CABC_MIN_BRI 0x5F
|
||||
#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
|
||||
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
|
||||
|
||||
/*! MIPI DCS Panel Private CMDs. */
|
||||
#define MIPI_DCS_PRIV_UNK_A0 0xA0
|
||||
#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
|
||||
#define MIPI_DCS_PRIV_SET_EXTC 0xB9
|
||||
#define MIPI_DCS_PRIV_SET_EXTC 0xB9 // Enable extended commands.
|
||||
#define MIPI_DCS_PRIV_UNK_BD 0xBD
|
||||
#define MIPI_DCS_PRIV_UNK_D5 0xD5
|
||||
#define MIPI_DCS_PRIV_UNK_D6 0xD6
|
||||
#define MIPI_DCS_PRIV_UNK_D8 0xD8
|
||||
#define MIPI_DCS_PRIV_UNK_D9 0xD9
|
||||
#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
|
||||
#define MIPI_DCS_PRIV_SET_EXTC_CMD_REG 0xFF // EXTC Command Set enable register. 5 bytes. Pass: FF 98 06 04, PAGE.
|
||||
|
||||
/*! MIPI DCS Panel Private CMDs PAGE 1. */
|
||||
#define MIPI_DCS_PRIV_GET_DISPLAY_ID4 0x00
|
||||
#define MIPI_DCS_PRIV_GET_DISPLAY_ID5 0x01
|
||||
#define MIPI_DCS_PRIV_GET_DISPLAY_ID6 0x02
|
||||
|
||||
/*! MIPI DCS CMD Defines. */
|
||||
#define DCS_POWER_MODE_DISPLAY_ON BIT(2)
|
||||
@@ -644,20 +652,29 @@
|
||||
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3)
|
||||
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
|
||||
|
||||
#define PANEL_OLED_BL_COEFF 82 // 82%.
|
||||
#define PANEL_OLED_BL_OFFSET 45 // Least legible backlight duty.
|
||||
|
||||
/* Switch Panels:
|
||||
*
|
||||
* 6.2" panels for Icosa and Iowa skus:
|
||||
* [10] 81 [26]: JDI LPM062M326A
|
||||
* [10] 96 [09]: JDI LAM062M109A
|
||||
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
|
||||
* [20] 95 [0F]: InnoLux P062CCA-AZ2
|
||||
* [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1)
|
||||
* [20] 96 [0F]: InnoLux P062CCA-AZ3 [UNCONFIRMED MODEL REV]
|
||||
* [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV]
|
||||
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
|
||||
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
|
||||
* [30] XX [0F]: AUO A062TAN03 (59.06A33.003) [UNCONFIRMED ID]
|
||||
*
|
||||
* 5.5" panels for Hoag skus:
|
||||
* [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1)
|
||||
* [30] XX [10]: AUO A055TAN01 (59.05A30.001) [UNCONFIRMED ID]
|
||||
* [30] 93 [10]: AUO A055TAN01 (59.05A30.001)
|
||||
* [40] XX [10]: Vendor 40 [UNCONFIRMED ID]
|
||||
*
|
||||
* 7.0" OLED panels for Aula skus:
|
||||
* [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5)
|
||||
*/
|
||||
|
||||
/* Display ID Decoding:
|
||||
@@ -670,13 +687,13 @@
|
||||
* 10h: Japan Display Inc.
|
||||
* 20h: InnoLux Corporation
|
||||
* 30h: AU Optronics
|
||||
* 40h: Unknown1
|
||||
* 50h: Unknown2 (OLED? Samsung? LG?)
|
||||
* 40h: Unknown0
|
||||
* 50h: Samsung
|
||||
*
|
||||
* Boards, Panel Size:
|
||||
* 0Fh: Icosa/Iowa, 6.2"
|
||||
* 10h: Hoag, 5.5"
|
||||
* 20h: Unknown, x.x"
|
||||
* 20h: Aula, 7.0"
|
||||
*/
|
||||
|
||||
enum
|
||||
@@ -688,7 +705,8 @@ enum
|
||||
PANEL_AUO_A062TAN01 = 0x0F30,
|
||||
PANEL_INL_2J055IA_27A = 0x1020,
|
||||
PANEL_AUO_A055TAN01 = 0x1030,
|
||||
PANEL_V40_55_UNK = 0x1040
|
||||
PANEL_V40_55_UNK = 0x1040,
|
||||
PANEL_SAM_AMS699VC01 = 0x2050
|
||||
};
|
||||
|
||||
void display_init();
|
||||
@@ -705,6 +723,7 @@ void display_color_screen(u32 color);
|
||||
/*! Switches screen backlight ON/OFF. */
|
||||
void display_backlight(bool enable);
|
||||
void display_backlight_brightness(u32 brightness, u32 step_delay);
|
||||
u32 display_get_backlight_brightness();
|
||||
|
||||
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
|
||||
u32 *display_init_framebuffer_pitch();
|
||||
@@ -200,10 +200,10 @@ static const cfg_op_t _display_dsi_init_config_part6[14] = {
|
||||
|
||||
//DSI panel config.
|
||||
static const cfg_op_t _display_init_config_jdi[43] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 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, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD.
|
||||
{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.
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "elfload/elfload.h"
|
||||
#include <module.h>
|
||||
#include <mem/heap.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <storage/nx_sd.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
@@ -43,6 +44,10 @@ static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
158
bdk/input/als.c
158
bdk/input/als.c
@@ -17,102 +17,140 @@
|
||||
*/
|
||||
|
||||
#include "als.h"
|
||||
#include <power/max77620.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#define HOS_GAIN BH1730_GAIN_64X
|
||||
#define HOS_ITIME 38
|
||||
#define BH1730_DEFAULT_GAIN BH1730_GAIN_64X
|
||||
#define BH1730_DEFAULT_ICYCLE 38
|
||||
|
||||
void set_als_cfg(als_table_t *als_val, u8 gain, u8 itime)
|
||||
#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
|
||||
{
|
||||
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 - itime));
|
||||
u32 rc;
|
||||
u32 cv;
|
||||
u32 ci;
|
||||
} opt_win_cal_t;
|
||||
|
||||
als_val->gain = gain;
|
||||
als_val->itime = itime;
|
||||
// Nintendo Switch Icosa/Iowa Optical Window calibration.
|
||||
const opt_win_cal_t opt_win_cal_default[] = {
|
||||
{ 500, 5002, 7502 },
|
||||
{ 754, 2250, 2000 },
|
||||
{ 1029, 1999, 1667 },
|
||||
{ 1373, 884, 583 },
|
||||
{ 1879, 309, 165 }
|
||||
};
|
||||
|
||||
// Nintendo Switch Aula Optical Window calibration.
|
||||
const opt_win_cal_t opt_win_cal_aula[] = {
|
||||
{ 231, 9697, 30300 },
|
||||
{ 993, 3333, 2778 },
|
||||
{ 1478, 1621, 1053 },
|
||||
{ 7500, 81, 10 }
|
||||
};
|
||||
|
||||
const u32 als_gain_idx_tbl[4] = { 1, 2, 64, 128 };
|
||||
|
||||
void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
|
||||
{
|
||||
if (gain > BH1730_GAIN_128X)
|
||||
gain = BH1730_GAIN_128X;
|
||||
|
||||
if (!cycle)
|
||||
cycle = 1;
|
||||
else if (cycle > 255)
|
||||
cycle = 255;
|
||||
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle));
|
||||
|
||||
als_ctxt->gain = gain;
|
||||
als_ctxt->cycle = cycle;
|
||||
}
|
||||
|
||||
void get_als_lux(als_table_t *als_val)
|
||||
void get_als_lux(als_ctxt_t *als_ctxt)
|
||||
{
|
||||
u32 data[2];
|
||||
float pre_gain_lux;
|
||||
float visible_light;
|
||||
float ir_light;
|
||||
float light_ratio;
|
||||
u32 visible_light;
|
||||
u32 ir_light;
|
||||
u64 lux = 0;
|
||||
u32 itime_us = BH1730_ITIME_CYCLE_TO_US * als_ctxt->cycle;
|
||||
|
||||
u8 adc_ready = 0;
|
||||
u8 retries = 100;
|
||||
|
||||
const float als_gain_idx_tbl[4] = { 1.0, 2.0, 64.0, 128.0 };
|
||||
const float als_norm_res = 100.0;
|
||||
const float als_multiplier = 3.6;
|
||||
const float als_tint = 2.7;
|
||||
|
||||
// Wait for ADC to prepare new data.
|
||||
while (!(adc_ready & BH1730_CTL_ADC_VALID) && retries)
|
||||
{
|
||||
retries--;
|
||||
adc_ready = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG));
|
||||
}
|
||||
|
||||
// Get visible and ir light raw data.
|
||||
// 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);
|
||||
|
||||
als_val->over_limit = data[0] > 65534 || data[1] > 65534;
|
||||
als_val->vi_light = data[0];
|
||||
als_val->ir_light = data[1];
|
||||
visible_light = data[0];
|
||||
ir_light = data[1];
|
||||
|
||||
if (!data[0] || !retries)
|
||||
als_ctxt->over_limit = visible_light > 65534 || ir_light > 65534;
|
||||
als_ctxt->vi_light = visible_light;
|
||||
als_ctxt->ir_light = ir_light;
|
||||
|
||||
if (!visible_light)
|
||||
{
|
||||
als_val->lux = 0.0;
|
||||
als_ctxt->lux = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
visible_light = (float)data[0];
|
||||
ir_light = (float)data[1];
|
||||
light_ratio = (float)data[1] / (float)data[0];
|
||||
// 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;
|
||||
|
||||
// The following are specific to the light filter Switch uses.
|
||||
if (light_ratio < 0.5)
|
||||
pre_gain_lux = visible_light * 5.002 - ir_light * 7.502;
|
||||
else if (light_ratio < 0.754)
|
||||
pre_gain_lux = visible_light * 2.250 - ir_light * 2.000;
|
||||
else if (light_ratio < 1.029)
|
||||
pre_gain_lux = visible_light * 1.999 - ir_light * 1.667;
|
||||
else if (light_ratio < 1.373)
|
||||
pre_gain_lux = visible_light * 0.884 - ir_light * 0.583;
|
||||
else if (light_ratio < 1.879)
|
||||
pre_gain_lux = visible_light * 0.309 - ir_light * 0.165;
|
||||
else pre_gain_lux = 0.0;
|
||||
// Apply optical window calibration coefficients.
|
||||
for (u32 i = 0; i < opt_win_cal_count; i++)
|
||||
{
|
||||
if (1000 * ir_light / visible_light < opt_win_cal[i].rc)
|
||||
{
|
||||
lux = ((u64)opt_win_cal[i].cv * data[0]) - (opt_win_cal[i].ci * data[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
als_val->lux = (pre_gain_lux / als_gain_idx_tbl[als_val->gain]) * (als_norm_res / ((float)als_val->itime * als_tint)) * als_multiplier;
|
||||
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_init(als_table_t *als_val)
|
||||
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);
|
||||
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
|
||||
(MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE));
|
||||
|
||||
// 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);
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), HOS_GAIN);
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - HOS_ITIME));
|
||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG), BH1730_CTL_POWER_ON | BH1730_CTL_ADC_EN);
|
||||
|
||||
als_val->gain = HOS_GAIN;
|
||||
als_val->itime = HOS_ITIME;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -48,18 +48,18 @@
|
||||
#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_ */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Joy-Con UART driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* 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,
|
||||
@@ -39,6 +39,9 @@
|
||||
#define JC_WIRED_INIT_REPLY 0x94
|
||||
#define JC_INIT_HANDSHAKE 0xA5
|
||||
|
||||
#define JC_HORI_INPUT_RPT_CMD 0x9A
|
||||
#define JC_HORI_INPUT_RPT 0x00
|
||||
|
||||
#define JC_WIRED_CMD_MAC 0x01
|
||||
#define JC_WIRED_CMD_10 0x10
|
||||
|
||||
@@ -61,8 +64,12 @@
|
||||
#define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status.
|
||||
#define JC_BTN_MASK_R 0x0056FF
|
||||
|
||||
#define JC_ID_L 1
|
||||
#define JC_ID_R 2
|
||||
#define JC_ID_L 0x01
|
||||
#define JC_ID_R 0x02
|
||||
#define JC_ID_HORI 0x20
|
||||
|
||||
#define JC_CRC8_INIT 0x00
|
||||
#define JC_CRC8_POLY 0x8D
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -80,25 +87,31 @@ static const u8 init_jc[] = {
|
||||
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.
|
||||
0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data and crc.
|
||||
};
|
||||
|
||||
static const u8 init_get_info[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd.
|
||||
0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data.
|
||||
0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc.
|
||||
};
|
||||
|
||||
static const u8 init_finilize[] = {
|
||||
static const u8 init_finalize[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd.
|
||||
0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data.
|
||||
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.
|
||||
0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data and crc.
|
||||
};
|
||||
|
||||
static const u8 hori_pad_status[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_HORI_INPUT_RPT_CMD, 0x01, // Hori cmd and hori subcmd.
|
||||
0x00, 0x00, 0x00, 0x00, 0x48 // Hori cmd data and crc.
|
||||
};
|
||||
|
||||
typedef struct _jc_uart_hdr_t
|
||||
@@ -185,8 +198,8 @@ typedef struct _joycon_ctxt_t
|
||||
u8 connected;
|
||||
} joycon_ctxt_t;
|
||||
|
||||
static joycon_ctxt_t jc_l;
|
||||
static joycon_ctxt_t jc_r;
|
||||
static joycon_ctxt_t jc_l = {0};
|
||||
static joycon_ctxt_t jc_r = {0};
|
||||
|
||||
static bool jc_init_done = false;
|
||||
static u32 hid_pkt_inc = 0;
|
||||
@@ -195,13 +208,29 @@ static jc_gamepad_rpt_t jc_gamepad;
|
||||
|
||||
void jc_power_supply(u8 uart, bool enable);
|
||||
|
||||
static u8 jc_crc(u8 *data, u16 len)
|
||||
{
|
||||
u8 crc = JC_CRC8_INIT;
|
||||
u16 i, j;
|
||||
for (i = 0; i < len; i++) {
|
||||
crc ^= data[i];
|
||||
for (j = 0; j < 8; j++) {
|
||||
if ((crc & 0x80) != 0)
|
||||
crc = (u8)((crc << 1) ^ JC_CRC8_POLY);
|
||||
else
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size)
|
||||
{
|
||||
uart_send(uart_port, buf, size);
|
||||
uart_wait_idle(uart_port, UART_TX_IDLE);
|
||||
}
|
||||
|
||||
static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size)
|
||||
static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc)
|
||||
{
|
||||
out->uart_hdr.magic[0] = 0x19;
|
||||
out->uart_hdr.magic[1] = 0x01;
|
||||
@@ -214,14 +243,14 @@ static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u
|
||||
if (data)
|
||||
memcpy(out->data, data, size);
|
||||
|
||||
out->crc = 0; // wired crc8ccit can be skipped.
|
||||
out->crc = crc ? jc_crc(&out->uart_hdr.total_size_msb, sizeof(out->uart_hdr.total_size_msb) + sizeof(out->cmd) + sizeof(out->data)) : 0;
|
||||
|
||||
return sizeof(jc_wired_hdr_t);
|
||||
}
|
||||
|
||||
static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size)
|
||||
static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc)
|
||||
{
|
||||
u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0);
|
||||
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;
|
||||
@@ -234,12 +263,12 @@ static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size)
|
||||
return pkt_size;
|
||||
}
|
||||
|
||||
void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size)
|
||||
void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc)
|
||||
{
|
||||
u8 rpt[0x50];
|
||||
memset(rpt, 0, sizeof(rpt));
|
||||
|
||||
u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size);
|
||||
u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc);
|
||||
|
||||
joycon_send_raw(uart, rpt, rpt_size);
|
||||
}
|
||||
@@ -275,18 +304,18 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
|
||||
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
|
||||
hid_pkt->subcmd_data[0] = 1;
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10);
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10);
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
|
||||
|
||||
// Send rumble.
|
||||
hid_pkt->cmd = JC_HID_RUMBLE_RPT;
|
||||
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
|
||||
memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init));
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10);
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10);
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false);
|
||||
|
||||
msleep(15);
|
||||
|
||||
@@ -297,21 +326,21 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
|
||||
hid_pkt->subcmd_data[0] = 0;
|
||||
memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10);
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10);
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI);
|
||||
|
||||
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
|
||||
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
|
||||
hid_pkt->subcmd = subcmd;
|
||||
if (data)
|
||||
memcpy(hid_pkt->subcmd_data, data, size);
|
||||
|
||||
u8 pkt_size = sizeof(jc_hid_out_rpt_t) + size;
|
||||
|
||||
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, pkt_size);
|
||||
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,6 +362,7 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
|
||||
|
||||
switch (hid_pkt->cmd)
|
||||
{
|
||||
case JC_HORI_INPUT_RPT:
|
||||
case JC_HID_INPUT_RPT:
|
||||
btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
|
||||
|
||||
@@ -412,6 +442,7 @@ static void jc_uart_pkt_parse(joycon_ctxt_t *jc, const u8* packet, size_t size)
|
||||
jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet;
|
||||
switch (pkt->cmd)
|
||||
{
|
||||
case JC_HORI_INPUT_RPT_CMD:
|
||||
case JC_WIRED_HID:
|
||||
jc_parse_wired_hid(jc, pkt->payload, (pkt->data[0] << 8) | pkt->data[1]);
|
||||
break;
|
||||
@@ -432,7 +463,7 @@ static void jc_rcv_pkt(joycon_ctxt_t *jc)
|
||||
|
||||
// Check if device stopped sending data.
|
||||
u32 uart_irq = uart_get_IIR(jc->uart);
|
||||
if ((uart_irq & 0x8) != 0x8)
|
||||
if (uart_irq != UART_IIR_REDI)
|
||||
return;
|
||||
|
||||
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
|
||||
@@ -474,10 +505,15 @@ static bool jc_send_init_rumble(joycon_ctxt_t *jc)
|
||||
|
||||
static void jc_req_nx_pad_status(joycon_ctxt_t *jc)
|
||||
{
|
||||
bool sent_rumble = jc_send_init_rumble(jc);
|
||||
bool is_nxpad = !(jc->type & JC_ID_HORI);
|
||||
|
||||
if (sent_rumble)
|
||||
return;
|
||||
if (is_nxpad)
|
||||
{
|
||||
bool sent_rumble = jc_send_init_rumble(jc);
|
||||
|
||||
if (sent_rumble)
|
||||
return;
|
||||
}
|
||||
|
||||
if (jc->last_status_req_time > get_tmr_ms() || !jc->connected)
|
||||
return;
|
||||
@@ -488,7 +524,10 @@ static void jc_req_nx_pad_status(joycon_ctxt_t *jc)
|
||||
else
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
|
||||
joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status));
|
||||
if (is_nxpad)
|
||||
joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status));
|
||||
else
|
||||
joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status));
|
||||
|
||||
// Turn Joy-Con detect on.
|
||||
if (jc->uart == UART_B)
|
||||
@@ -655,24 +694,31 @@ retry:
|
||||
|
||||
void jc_deinit()
|
||||
{
|
||||
// Disable power.
|
||||
jc_power_supply(UART_B, false);
|
||||
jc_power_supply(UART_C, false);
|
||||
|
||||
// Turn off Joy-Con detect.
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
|
||||
// Send sleep command.
|
||||
u8 data = HCI_STATE_SLEEP;
|
||||
|
||||
if (jc_r.connected)
|
||||
if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
|
||||
{
|
||||
jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
jc_rcv_pkt(&jc_r);
|
||||
}
|
||||
if (jc_l.connected)
|
||||
if (jc_l.connected && !(jc_l.type & JC_ID_HORI))
|
||||
{
|
||||
jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
jc_rcv_pkt(&jc_l);
|
||||
}
|
||||
|
||||
jc_power_supply(UART_B, false);
|
||||
jc_power_supply(UART_C, false);
|
||||
// Disable UART B and C clocks.
|
||||
clock_disable_uart(UART_B);
|
||||
clock_disable_uart(UART_C);
|
||||
}
|
||||
|
||||
static void jc_init_conn(joycon_ctxt_t *jc)
|
||||
@@ -709,9 +755,12 @@ static void jc_init_conn(joycon_ctxt_t *jc)
|
||||
msleep(5);
|
||||
jc_rcv_pkt(jc);
|
||||
|
||||
joycon_send_raw(jc->uart, init_finilize, sizeof(init_finilize));
|
||||
msleep(5);
|
||||
jc_rcv_pkt(jc);
|
||||
if (!(jc->type & JC_ID_HORI))
|
||||
{
|
||||
joycon_send_raw(jc->uart, init_finalize, sizeof(init_finalize));
|
||||
msleep(5);
|
||||
jc_rcv_pkt(jc);
|
||||
}
|
||||
|
||||
// Turn Joy-Con detect on.
|
||||
if (jc->uart == UART_B)
|
||||
@@ -766,10 +815,10 @@ void jc_power_supply(u8 uart, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
if (regulator_get_5v_dev_enabled(1 << uart))
|
||||
if (regulator_5v_get_dev_enabled(1 << uart))
|
||||
return;
|
||||
|
||||
regulator_enable_5v(1 << uart);
|
||||
regulator_5v_enable(1 << uart);
|
||||
|
||||
if (jc_init_done)
|
||||
{
|
||||
@@ -799,10 +848,10 @@ void jc_power_supply(u8 uart, bool enable)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!regulator_get_5v_dev_enabled(1 << uart))
|
||||
if (!regulator_5v_get_dev_enabled(1 << uart))
|
||||
return;
|
||||
|
||||
regulator_disable_5v(1 << uart);
|
||||
regulator_5v_disable(1 << uart);
|
||||
|
||||
if (uart == UART_C)
|
||||
gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW);
|
||||
@@ -836,14 +885,14 @@ void jc_init_hw()
|
||||
pinmux_config_uart(UART_C);
|
||||
|
||||
// Ease the stress to APB.
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
// Enable UART B and C clocks.
|
||||
clock_enable_uart(UART_B);
|
||||
clock_enable_uart(UART_C);
|
||||
|
||||
// Restore OC.
|
||||
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST);
|
||||
bpmp_clk_rate_set(prev_fid);
|
||||
|
||||
// Turn Joy-Con detect on.
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <power/max77620.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/btn.h>
|
||||
@@ -34,6 +33,16 @@
|
||||
#include <gfx_utils.h>
|
||||
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
|
||||
static touch_panel_info_t _panels[] =
|
||||
{
|
||||
{ 0, 1, 1, 1, "NISSHA NFT-K12D" },
|
||||
{ 1, 0, 1, 1, "GiS GGM6 B2X" },
|
||||
{ 2, 0, 0, 0, "NISSHA NBF-K9A" },
|
||||
{ 3, 1, 0, 0, "GiS 5.5\"" },
|
||||
{ 4, 0, 0, 1, "Samsung BH2109" },
|
||||
{ -1, 1, 0, 1, "GiS VA 6.2\"" }
|
||||
};
|
||||
|
||||
static int touch_command(u8 cmd, u8 *buf, u8 size)
|
||||
{
|
||||
int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd, buf, size);
|
||||
@@ -53,7 +62,7 @@ static int touch_read_reg(u8 *cmd, u32 csize, u8 *buf, u32 size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int touch_wait_event(u8 event, u8 status, u32 timeout)
|
||||
static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf)
|
||||
{
|
||||
u32 timer = get_tmr_ms() + timeout;
|
||||
while (true)
|
||||
@@ -61,7 +70,11 @@ static int touch_wait_event(u8 event, u8 status, u32 timeout)
|
||||
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;
|
||||
@@ -147,10 +160,10 @@ static void _touch_parse_event(touch_event *event)
|
||||
event->type = STMFTS_EV_MULTI_TOUCH_LEAVE;
|
||||
}
|
||||
|
||||
// gfx_con_setpos(&gfx_con, 0, 300);
|
||||
// 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]);
|
||||
// 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)
|
||||
@@ -183,16 +196,45 @@ touch_info touch_get_info()
|
||||
info.config_id = buf[4];
|
||||
info.config_ver = buf[5];
|
||||
|
||||
//DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02x, Cfg Ver: %d\n",
|
||||
//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);
|
||||
@@ -227,7 +269,7 @@ int touch_sys_reset()
|
||||
continue;
|
||||
}
|
||||
msleep(10);
|
||||
if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20))
|
||||
if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL))
|
||||
continue;
|
||||
else
|
||||
return 0;
|
||||
@@ -284,7 +326,7 @@ int touch_get_fb_info(u8 *buf)
|
||||
int res = 0;
|
||||
|
||||
|
||||
for (u32 i = 0; i < 0x10000; i+=4)
|
||||
for (u32 i = 0; i < 0x10000; i += 4)
|
||||
{
|
||||
if (!res)
|
||||
{
|
||||
@@ -301,9 +343,9 @@ int touch_get_fb_info(u8 *buf)
|
||||
|
||||
int touch_sense_enable()
|
||||
{
|
||||
// Enable auto tuning calibration and multi-touch sensing.
|
||||
u8 cmd = 1;
|
||||
if (touch_command(STMFTS_AUTO_CALIBRATION, &cmd, 1))
|
||||
// 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))
|
||||
@@ -329,19 +371,19 @@ int touch_execute_autotune()
|
||||
// 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))
|
||||
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))
|
||||
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))
|
||||
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000, NULL))
|
||||
return 0;
|
||||
|
||||
return touch_sense_enable();
|
||||
@@ -358,12 +400,11 @@ static int touch_init()
|
||||
|
||||
int touch_power_on()
|
||||
{
|
||||
// Enables LDO6 for touchscreen VDD/AVDD supply
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
|
||||
(MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE));
|
||||
// Enable LDO6 for touchscreen AVDD supply.
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO6, true);
|
||||
|
||||
// Configure touchscreen GPIO.
|
||||
// Configure touchscreen VDD GPIO.
|
||||
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
|
||||
gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE);
|
||||
@@ -377,7 +418,7 @@ 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;
|
||||
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO);
|
||||
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
|
||||
|
||||
// Initialize I2C3.
|
||||
pinmux_config_i2c(I2C_3);
|
||||
@@ -385,7 +426,7 @@ int touch_power_on()
|
||||
i2c_init(I2C_3);
|
||||
|
||||
// Wait for the touchscreen module to get ready.
|
||||
touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20);
|
||||
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))
|
||||
@@ -414,9 +455,7 @@ void touch_power_off()
|
||||
gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW);
|
||||
|
||||
// Disables LDO6 for touchscreen VDD, AVDD supply
|
||||
max77620_regulator_enable(REGULATOR_LDO6, 0);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
|
||||
MAX77620_LDO_CFG2_ADE_ENABLE | (2 << 3) | (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT));
|
||||
max7762x_regulator_enable(REGULATOR_LDO6, false);
|
||||
|
||||
clock_disable_i2c(I2C_3);
|
||||
}
|
||||
@@ -47,19 +47,27 @@
|
||||
#define STMFTS_ITO_CHECK 0xA7
|
||||
#define STMFTS_RELEASEINFO 0xAA
|
||||
#define STMFTS_WRITE_REG 0xB6
|
||||
#define STMFTS_AUTO_CALIBRATION 0xC3
|
||||
#define STMFTS_SWITCH_SENSE_MODE 0xC3
|
||||
#define STMFTS_NOISE_WRITE 0xC7
|
||||
#define STMFTS_NOISE_READ 0xC8
|
||||
#define STMFTS_RW_FRAMEBUFFER_REG 0xD0
|
||||
#define STMFTS_SAVE_CX_TUNING 0xFC
|
||||
|
||||
#define STMFTS_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
|
||||
@@ -74,6 +82,7 @@
|
||||
#define STMFTS_EV_ERROR 0x0f
|
||||
#define STMFTS_EV_NOISE_READ 0x17
|
||||
#define STMFTS_EV_NOISE_WRITE 0x18
|
||||
#define STMFTS_EV_VENDOR 0x20
|
||||
|
||||
#define STMFTS_EV_CONTROLLER_READY 0x10
|
||||
#define STMFTS_EV_STATUS 0x16
|
||||
@@ -131,6 +140,15 @@ typedef struct _touch_event {
|
||||
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;
|
||||
@@ -146,6 +164,7 @@ typedef struct _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);
|
||||
|
||||
@@ -839,10 +839,12 @@ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst
|
||||
int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
|
||||
{
|
||||
int result;
|
||||
LZ4_stream_t ctx;
|
||||
LZ4_stream_t* const ctxPtr = &ctx;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -857,13 +859,18 @@ int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxO
|
||||
/* 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)
|
||||
{
|
||||
LZ4_stream_t ctx;
|
||||
LZ4_resetStream(&ctx);
|
||||
int result;
|
||||
LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
|
||||
LZ4_resetStream(ctx);
|
||||
|
||||
if (inputSize < LZ4_64Klimit)
|
||||
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
|
||||
result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
|
||||
else
|
||||
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
|
||||
result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
|
||||
|
||||
FREEMEM(ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1045,11 +1052,13 @@ static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src,
|
||||
|
||||
int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
|
||||
{
|
||||
LZ4_stream_t ctxBody;
|
||||
LZ4_stream_t* ctx = &ctxBody;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ typedef enum {
|
||||
DRIVE_SD = 0,
|
||||
DRIVE_RAM = 1,
|
||||
DRIVE_EMMC = 2,
|
||||
DRIVE_BIS = 3
|
||||
DRIVE_BIS = 3,
|
||||
DRIVE_EMU = 4
|
||||
} DDRIVE;
|
||||
|
||||
|
||||
@@ -59,6 +60,7 @@ DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
|
||||
#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 */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "ff.h" /* Declarations of FatFs API */
|
||||
#include "diskio.h" /* Declarations of device I/O functions */
|
||||
#include <storage/mbr_gpt.h>
|
||||
#include <gfx_utils.h>
|
||||
|
||||
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
|
||||
@@ -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 */
|
||||
@@ -4696,9 +4709,9 @@ DWORD *f_expand_cltbl (
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -6169,7 +6182,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 */
|
||||
@@ -6182,23 +6197,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, "SWITCH SD " "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, "SWITCH SD " "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 */
|
||||
@@ -6216,6 +6235,16 @@ FRESULT f_mkfs (
|
||||
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);
|
||||
buf[16] = 0x64; /* Record type */
|
||||
st_dword(buf + 32, 0x03); /* Unknown. SYSTEM: 0x3F00. USER: 0x03. Volatile. */
|
||||
st_dword(buf + 36, 25); /* Entries. SYSTEM: 22. USER: 25.Static? */
|
||||
st_dword(buf + 508, 0x517BBFE0); /* Custom CRC32. SYSTEM: 0x6B673904. USER: 0x517BBFE0. */
|
||||
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 */
|
||||
@@ -6705,6 +6734,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);
|
||||
@@ -6731,6 +6762,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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -365,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
|
||||
|
||||
23
bdk/mem/mc.c
23
bdk/mem/mc.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -15,11 +15,14 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <memory_map.h>
|
||||
#include <mem/mc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <soc/clock.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
//#define CONFIG_ENABLE_AHB_REDIRECT
|
||||
|
||||
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock)
|
||||
{
|
||||
MC(MC_SEC_CARVEOUT_BOM) = bom;
|
||||
@@ -122,13 +125,13 @@ void mc_config_carveout()
|
||||
MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F;
|
||||
}
|
||||
|
||||
void mc_enable_ahb_redirect()
|
||||
void mc_enable_ahb_redirect(bool full_aperture)
|
||||
{
|
||||
// Enable ARC_CLK_OVR_ON.
|
||||
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = (CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) & 0xFFF7FFFF) | 0x80000;
|
||||
//MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE;
|
||||
MC(MC_IRAM_BOM) = 0x40000000;
|
||||
MC(MC_IRAM_TOM) = 0x4003F000;
|
||||
MC(MC_IRAM_TOM) = full_aperture ? DRAM_START : 0x4003F000;
|
||||
}
|
||||
|
||||
void mc_disable_ahb_redirect()
|
||||
@@ -143,17 +146,19 @@ void mc_disable_ahb_redirect()
|
||||
|
||||
void mc_enable()
|
||||
{
|
||||
// Reset EMC source to PLLP.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
|
||||
// Enable memory clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_EMC)) | BIT(CLK_H_EMC);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_MEM)) | BIT(CLK_H_MEM);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & ~BIT(CLK_X_EMC_DLL)) | BIT(CLK_X_EMC_DLL);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
|
||||
// Clear clock resets for memory.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
|
||||
usleep(5);
|
||||
|
||||
//#ifdef CONFIG_ENABLE_AHB_REDIRECT
|
||||
#ifdef CONFIG_ENABLE_AHB_REDIRECT
|
||||
mc_enable_ahb_redirect();
|
||||
#else
|
||||
mc_disable_ahb_redirect();
|
||||
//mc_enable_ahb_redirect();
|
||||
//#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
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_enable_ahb_redirect(bool full_aperture);
|
||||
void mc_disable_ahb_redirect();
|
||||
void mc_enable();
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ u32 minerva_init()
|
||||
mtc_config_t mtc_tmp;
|
||||
|
||||
mtc_tmp.mtc_table = mtc_cfg->mtc_table;
|
||||
mtc_tmp.sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
|
||||
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);
|
||||
@@ -81,7 +81,7 @@ u32 minerva_init()
|
||||
// Set table to nyx storage.
|
||||
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
|
||||
|
||||
mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
|
||||
mtc_cfg->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);
|
||||
@@ -104,21 +104,21 @@ u32 minerva_init()
|
||||
}
|
||||
|
||||
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
|
||||
mtc_cfg->rate_to = 204000;
|
||||
mtc_cfg->rate_to = FREQ_204;
|
||||
mtc_cfg->train_mode = OP_TRAIN;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
mtc_cfg->rate_to = 800000;
|
||||
mtc_cfg->rate_to = FREQ_800;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
mtc_cfg->rate_to = 1600000;
|
||||
mtc_cfg->rate_to = FREQ_1600;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
// FSP WAR.
|
||||
mtc_cfg->train_mode = OP_SWITCH;
|
||||
mtc_cfg->rate_to = 800000;
|
||||
mtc_cfg->rate_to = FREQ_800;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
// Switch to max.
|
||||
mtc_cfg->rate_to = 1600000;
|
||||
mtc_cfg->rate_to = FREQ_1600;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
|
||||
return 0;
|
||||
@@ -129,6 +129,7 @@ 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)
|
||||
{
|
||||
@@ -138,6 +139,23 @@ void minerva_change_freq(minerva_freq_t freq)
|
||||
}
|
||||
}
|
||||
|
||||
void minerva_prep_boot_freq()
|
||||
{
|
||||
if (!minerva_cfg)
|
||||
return;
|
||||
|
||||
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
|
||||
|
||||
// Check if there's RAM OC. If not exit.
|
||||
if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
|
||||
return;
|
||||
|
||||
// FSP WAR.
|
||||
minerva_change_freq(FREQ_204);
|
||||
// Scale down to 800 MHz boot freq.
|
||||
minerva_change_freq(FREQ_800);
|
||||
}
|
||||
|
||||
void minerva_periodic_training()
|
||||
{
|
||||
if (!minerva_cfg)
|
||||
|
||||
@@ -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;
|
||||
@@ -60,6 +60,7 @@ typedef enum
|
||||
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
|
||||
u32 minerva_init();
|
||||
void minerva_change_freq(minerva_freq_t freq);
|
||||
void minerva_prep_boot_freq();
|
||||
void minerva_periodic_training();
|
||||
|
||||
#endif
|
||||
|
||||
159
bdk/mem/sdram.c
159
bdk/mem/sdram.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 balika011
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* 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,
|
||||
@@ -36,29 +36,48 @@
|
||||
|
||||
#define CONFIG_SDRAM_KEEP_ALIVE
|
||||
|
||||
//#define CONFIG_SDRAM_COMPRESS_CFG
|
||||
|
||||
typedef struct _sdram_vendor_patch_t
|
||||
{
|
||||
u32 val;
|
||||
u32 addr:10;
|
||||
u32 dramid:22;
|
||||
u32 offset:16;
|
||||
u32 dramcf:16;
|
||||
} sdram_vendor_patch_t;
|
||||
|
||||
#ifdef CONFIG_SDRAM_COMPRESS_CFG
|
||||
#include <libs/compr/lz.h>
|
||||
#include "sdram_config_lz.inl"
|
||||
#else
|
||||
#include "sdram_config.inl"
|
||||
#endif
|
||||
static const u8 dram_encoding_t210b01[] = {
|
||||
LPDDR4X_UNUSED,
|
||||
LPDDR4X_UNUSED,
|
||||
LPDDR4X_UNUSED,
|
||||
LPDDR4X_4GB_HYNIX_1Y_A,
|
||||
LPDDR4X_UNUSED,
|
||||
LPDDR4X_4GB_HYNIX_1Y_A,
|
||||
LPDDR4X_4GB_HYNIX_1Y_A,
|
||||
LPDDR4X_4GB_SAMSUNG_X1X2,
|
||||
LPDDR4X_NO_PATCH,
|
||||
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ,
|
||||
LPDDR4X_NO_PATCH,
|
||||
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE,
|
||||
LPDDR4X_NO_PATCH,
|
||||
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ,
|
||||
LPDDR4X_NO_PATCH,
|
||||
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE,
|
||||
LPDDR4X_4GB_SAMSUNG_Y,
|
||||
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
|
||||
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
|
||||
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
|
||||
LPDDR4X_4GB_SAMSUNG_1Y_Y,
|
||||
LPDDR4X_8GB_SAMSUNG_1Y_Y,
|
||||
LPDDR4X_UNUSED, // Removed.
|
||||
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
|
||||
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
|
||||
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
|
||||
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
|
||||
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
|
||||
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
|
||||
};
|
||||
|
||||
#include "sdram_config.inl"
|
||||
#include "sdram_config_t210b01.inl"
|
||||
|
||||
static u32 _sdram_get_id()
|
||||
{
|
||||
return ((fuse_read_odm(4) & 0xF8) >> 3);
|
||||
}
|
||||
|
||||
static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel)
|
||||
{
|
||||
bool err = true;
|
||||
@@ -1355,100 +1374,42 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
||||
SYSREG(AHB_ARBITRATION_XBAR_CTRL) = (SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF) | (params->ahb_arbitration_xbar_ctrl_meminit_done << 16);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SDRAM_COMPRESS_CFG
|
||||
static void _sdram_patch_model_params_t210(u32 dramid, u32 *params)
|
||||
{
|
||||
for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210); i++)
|
||||
if (sdram_cfg_vendor_patches_t210[i].dramid & DRAM_ID(dramid))
|
||||
params[sdram_cfg_vendor_patches_t210[i].addr] = sdram_cfg_vendor_patches_t210[i].val;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _sdram_patch_model_params_t210b01(u32 dramid, u32 *params)
|
||||
{
|
||||
for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210b01); i++)
|
||||
if (sdram_cfg_vendor_patches_t210b01[i].dramid & DRAM_ID2(dramid))
|
||||
params[sdram_cfg_vendor_patches_t210b01[i].addr] = sdram_cfg_vendor_patches_t210b01[i].val;
|
||||
}
|
||||
|
||||
static void *_sdram_get_params_t210()
|
||||
{
|
||||
// Check if id is proper.
|
||||
u32 dramid = _sdram_get_id();
|
||||
if (dramid > 6)
|
||||
dramid = 0;
|
||||
u32 dramid = fuse_read_dramid(false);
|
||||
|
||||
#ifdef CONFIG_SDRAM_COMPRESS_CFG
|
||||
// Copy base parameters.
|
||||
u32 *params = (u32 *)SDRAM_PARAMS_ADDR;
|
||||
memcpy(params, &_dram_cfg_0_samsung_4gb, sizeof(sdram_params_t210_t));
|
||||
|
||||
u8 *buf = (u8 *)SDRAM_PARAMS_ADDR;
|
||||
LZ_Uncompress(_dram_cfg_lz, buf, sizeof(_dram_cfg_lz));
|
||||
return (void *)&buf[sizeof(sdram_params_t210_t) * dramid];
|
||||
// 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;
|
||||
|
||||
#else
|
||||
|
||||
u32 *buf = (u32 *)SDRAM_PARAMS_ADDR;
|
||||
memcpy(buf, &_dram_cfg_0_samsung_4gb, sizeof(sdram_params_t210_t));
|
||||
|
||||
switch (dramid)
|
||||
{
|
||||
case LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH:
|
||||
case LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT:
|
||||
break;
|
||||
|
||||
case LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE:
|
||||
case LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH:
|
||||
#ifdef CONFIG_SDRAM_COPPER_SUPPORT
|
||||
case LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH:
|
||||
case LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE:
|
||||
case LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT:
|
||||
#endif
|
||||
_sdram_patch_model_params_t210(dramid, (u32 *)buf);
|
||||
break;
|
||||
}
|
||||
return (void *)buf;
|
||||
|
||||
#endif
|
||||
return (void *)params;
|
||||
}
|
||||
|
||||
void *sdram_get_params_t210b01()
|
||||
{
|
||||
// Check if id is proper.
|
||||
u32 dramid = _sdram_get_id();
|
||||
if (dramid > 27)
|
||||
dramid = 8;
|
||||
u32 dramid = fuse_read_dramid(false);
|
||||
|
||||
u32 *buf = (u32 *)SDRAM_PARAMS_ADDR;
|
||||
memcpy(buf, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t));
|
||||
// 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));
|
||||
|
||||
switch (dramid)
|
||||
{
|
||||
case LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ:
|
||||
case LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME:
|
||||
case LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ:
|
||||
case LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME:
|
||||
break;
|
||||
// Patch parameters if needed.
|
||||
u8 dram_code = dram_encoding_t210b01[dramid];
|
||||
if (!dram_code)
|
||||
return (void *)params;
|
||||
|
||||
case LPDDR4X_IOWA_4GB_SAMSUNG_X1X2:
|
||||
case LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ:
|
||||
case LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WT:
|
||||
case LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ:
|
||||
case LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WT:
|
||||
case LPDDR4X_IOWA_4GB_SAMSUNG_Y:
|
||||
case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y:
|
||||
case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y:
|
||||
case LPDDR4X_SDS_4GB_SAMSUNG_1Y_A:
|
||||
case LPDDR4X_SDS_8GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_SDS_4GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_IOWA_4GB_MICRON_1Y_A:
|
||||
case LPDDR4X_HOAG_4GB_MICRON_1Y_A:
|
||||
case LPDDR4X_SDS_4GB_MICRON_1Y_A:
|
||||
_sdram_patch_model_params_t210b01(dramid, (u32 *)buf);
|
||||
break;
|
||||
}
|
||||
return (void *)buf;
|
||||
for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210b01); i++)
|
||||
if (sdram_cfg_vendor_patches_t210b01[i].dramcf == dram_code)
|
||||
params[sdram_cfg_vendor_patches_t210b01[i].offset] = sdram_cfg_vendor_patches_t210b01[i].val;
|
||||
|
||||
return (void *)params;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1494,7 +1455,7 @@ static void _sdram_init_t210()
|
||||
const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210();
|
||||
|
||||
// Set DRAM voltage.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD1, 1100000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD1, 1100000); // HOS uses 1.125V
|
||||
|
||||
// VDDP Select.
|
||||
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
|
||||
@@ -1539,8 +1500,8 @@ static void _sdram_init_t210b01()
|
||||
|
||||
void sdram_init()
|
||||
{
|
||||
// Configure SD regulator for DRAM.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05);
|
||||
// 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)
|
||||
_sdram_init_t210();
|
||||
|
||||
106
bdk/mem/sdram.h
106
bdk/mem/sdram.h
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2020 CTCaer
|
||||
* Copyright (c) 2020-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -23,20 +23,26 @@
|
||||
/*
|
||||
* Tegra X1/X1+ EMC/DRAM Bandwidth Chart:
|
||||
*
|
||||
* 40.8 MHz: 0.61 GiB/s
|
||||
* 68.0 MHz: 1.01 GiB/s
|
||||
* 102.0 MHz: 1.52 GiB/s
|
||||
* 204.0 MHz: 3.04 GiB/s <-- Tegra X1/X1+ Init/SC7 Frequency
|
||||
* 408.0 MHz: 6.08 GiB/s
|
||||
* 665.6 MHz: 9.92 GiB/s
|
||||
* 800.0 MHz: 11.92 GiB/s <-- Tegra X1/X1+ Nvidia OS Boot Frequency
|
||||
* 1065.6 MHz: 15.89 GiB/s
|
||||
* 1331.2 MHz: 19.84 GiB/s
|
||||
* 1600.0 MHz: 23.84 GiB/s <-- Tegra X1 Official Max Frequency
|
||||
* 1862.4 MHz: 27.75 GiB/s <-- Tegra X1+ Official Max Frequency
|
||||
* 2131.2 MHz: 31.76 GiB/s
|
||||
* Note: BWbits T210 = Hz x ddr x bus width x channels = Hz x 2 x 32 x 2.
|
||||
* BWbits T210B01 = Hz x ddr x bus width x channels = Hz x 2 x 64 x 2.
|
||||
* Both assume that both sub-partitions are used and thus reaching max
|
||||
* bandwidth per channel. (T210: 2x16-bit, T210B01: 2x32-bit).
|
||||
* Retail Mariko use one sub-partition, in order to meet Erista perf.
|
||||
*
|
||||
* T210 T210B01
|
||||
* 40.8 MHz: 0.61 1.22 GiB/s
|
||||
* 68.0 MHz: 1.01 2.02 GiB/s
|
||||
* 102.0 MHz: 1.52 3.04 GiB/s
|
||||
* 204.0 MHz: 3.04 6.08 GiB/s <-- Tegra X1/X1+ Init/SC7 Frequency
|
||||
* 408.0 MHz: 6.08 12.16 GiB/s
|
||||
* 665.6 MHz: 9.92 19.84 GiB/s
|
||||
* 800.0 MHz: 11.92 23.84 GiB/s <-- Tegra X1/X1+ Nvidia OS Boot Frequency
|
||||
* 1065.6 MHz: 15.89 31.78 GiB/s
|
||||
* 1331.2 MHz: 19.84 39.68 GiB/s
|
||||
* 1600.0 MHz: 23.84 47.68 GiB/s <-- Tegra X1/X1+ HOS Max Frequency
|
||||
* 1862.4 MHz: 27.75 55.50 GiB/s <-- Tegra X1 Official Max Frequency
|
||||
* 2131.2 MHz: 31.76 63.52 GiB/s <-- Tegra X1+ Official Max Frequency
|
||||
*
|
||||
* Note: BWbits = Hz x bus width x channels = Hz x 64 x 2.
|
||||
*/
|
||||
|
||||
enum sdram_ids_erista
|
||||
@@ -44,46 +50,74 @@ enum sdram_ids_erista
|
||||
// LPDDR4 3200Mbps.
|
||||
LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0,
|
||||
LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1,
|
||||
LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2,
|
||||
LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3,
|
||||
LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, // WT:C.
|
||||
LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to Iowa Hynix 4GB 1Y-A.
|
||||
LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4,
|
||||
LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5,
|
||||
LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6,
|
||||
LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, // Changed to Hoag Hynix 4GB 1Y-A.
|
||||
LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, // Changed to Aula Hynix 4GB 1Y-A.
|
||||
};
|
||||
|
||||
enum sdram_ids_mariko
|
||||
{
|
||||
// LPDDR4X 4266Mbps.
|
||||
LPDDR4X_IOWA_4GB_HYNIX_1Y_A = 3, // Replaced from Copper.
|
||||
LPDDR4X_HOAG_4GB_HYNIX_1Y_A = 5, // Replaced from Copper.
|
||||
LPDDR4X_AULA_4GB_HYNIX_1Y_A = 6, // Replaced from Copper.
|
||||
|
||||
// LPDDR4X 3733Mbps.
|
||||
LPDDR4X_IOWA_4GB_SAMSUNG_X1X2 = 7,
|
||||
|
||||
LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8,
|
||||
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9,
|
||||
LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10,
|
||||
LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WT = 11, // 4266Mbps.
|
||||
LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, // Die-M.
|
||||
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, // Die-M.
|
||||
LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, // Die-M.
|
||||
LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, // 4266Mbps. Die-E.
|
||||
|
||||
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12,
|
||||
LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13,
|
||||
LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14,
|
||||
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WT = 15, // 4266Mbps.
|
||||
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, // Die-M.
|
||||
LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, // Die-M.
|
||||
LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, // Die-M.
|
||||
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, // 4266Mbps. Die-E.
|
||||
|
||||
// LPDDR4X 4266Mbps?
|
||||
// LPDDR4X 4266Mbps.
|
||||
LPDDR4X_IOWA_4GB_SAMSUNG_Y = 16,
|
||||
|
||||
LPDDR4X_IOWA_4GB_SAMSUNG_1Y_X = 17,
|
||||
LPDDR4X_IOWA_8GB_SAMSUNG_1Y_X = 18,
|
||||
LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X = 19,
|
||||
LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, // Die-A.
|
||||
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, // Die-A.
|
||||
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, // Die-A.
|
||||
|
||||
LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20,
|
||||
LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21,
|
||||
|
||||
LPDDR4X_SDS_4GB_SAMSUNG_1Y_A = 22,
|
||||
// LPDDR4X_AULA_8GB_SAMSUNG_1Y_A = 22, // Unused.
|
||||
|
||||
LPDDR4X_SDS_8GB_SAMSUNG_1Y_X = 23,
|
||||
LPDDR4X_SDS_4GB_SAMSUNG_1Y_X = 24,
|
||||
LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, // Die-A.
|
||||
LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, // Die-A.
|
||||
|
||||
LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25,
|
||||
LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26,
|
||||
LPDDR4X_SDS_4GB_MICRON_1Y_A = 27
|
||||
LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, // 4266Mbps. Die-F.
|
||||
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, // 4266Mbps. Die-F.
|
||||
LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, // 4266Mbps. Die-F.
|
||||
|
||||
LPDDR4X_AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, // Die-A.
|
||||
};
|
||||
|
||||
enum sdram_codes_mariko
|
||||
{
|
||||
LPDDR4X_NO_PATCH = 0,
|
||||
LPDDR4X_UNUSED = 0,
|
||||
|
||||
// LPDDR4X_4GB_SAMSUNG_K4U6E3S4AM_MGCJ DRAM IDs: 08, 12.
|
||||
// LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLHR_NME DRAM IDs: 10, 14.
|
||||
|
||||
LPDDR4X_4GB_SAMSUNG_X1X2 = 1, // DRAM IDs: 07.
|
||||
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 2, // DRAM IDs: 09, 13.
|
||||
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE = 3, // DRAM IDs: 11, 15.
|
||||
LPDDR4X_4GB_SAMSUNG_Y = 4, // DRAM IDs: 16.
|
||||
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 5, // DRAM IDs: 17, 19, 24.
|
||||
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 6, // DRAM IDs: 18, 23, 28.
|
||||
LPDDR4X_4GB_SAMSUNG_1Y_Y = 7, // DRAM IDs: 20.
|
||||
LPDDR4X_8GB_SAMSUNG_1Y_Y = 8, // DRAM IDs: 21.
|
||||
//LPDDR4X_8GB_SAMSUNG_1Y_A = 9, // DRAM IDs: 22. Unused.
|
||||
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF = 10, // DRAM IDs: 25, 26, 27.
|
||||
LPDDR4X_4GB_HYNIX_1Y_A = 11, // DRAM IDs: 03, 05, 06.
|
||||
};
|
||||
|
||||
void sdram_init();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2020 CTCaer
|
||||
* Copyright (c) 2020-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -97,7 +97,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
* DRAM size information
|
||||
* Specifies the value for EMC_ADR_CFG
|
||||
*/
|
||||
.emc_adr_cfg = 0x00000001, // 2 populated DRAM Devices.
|
||||
.emc_adr_cfg = 0x00000001, // 2 Ranks.
|
||||
|
||||
/*
|
||||
* Specifies the time to wait after asserting pin
|
||||
@@ -243,7 +243,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
.emc_cfg_dig_dll = 0x002C00A0,
|
||||
.emc_cfg_dig_dll_1 = 0x00003701,
|
||||
.emc_cfg_dig_dll_period = 0x00008000,
|
||||
.emc_dev_select = 0x00000000, // Both devices.
|
||||
.emc_dev_select = 0x00000000, // Both Ranks.
|
||||
.emc_sel_dpd_ctrl = 0x00040008,
|
||||
|
||||
/* Pads trimmer delays */
|
||||
@@ -406,7 +406,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
.pmc_ddr_ctrl = 0x0007FF8B,
|
||||
.emc_acpd_control = 0x00000000,
|
||||
|
||||
.emc_swizzle_rank0_byte0 = 0x76543201,
|
||||
.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,
|
||||
@@ -454,7 +454,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
.emc_pmacro_data_rx_term_mode = 0x00000010,
|
||||
.emc_pmacro_cmd_rx_term_mode = 0x00003000,
|
||||
.emc_pmacro_data_pad_tx_ctrl = 0x02000111,
|
||||
.emc_pmacro_common_pad_tx_ctrl = 0x00000008,
|
||||
.emc_pmacro_common_pad_tx_ctrl = 0x00000008, // Overridden to 0x0000000A by spare4/5.
|
||||
.emc_pmacro_cmd_pad_tx_ctrl = 0x0A000000,
|
||||
|
||||
.emc_cfg3 = 0x00000040,
|
||||
@@ -490,9 +490,9 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
.emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A,
|
||||
|
||||
/* DRAM size information */
|
||||
.mc_emem_adr_cfg = 0x00000001, // 2 populated DRAM Devices.
|
||||
.mc_emem_adr_cfg_dev0 = 0x00070302, // Density 512MB.
|
||||
.mc_emem_adr_cfg_dev1 = 0x00070302, // Density 512MB.
|
||||
.mc_emem_adr_cfg = 0x00000001, // 2 Ranks.
|
||||
.mc_emem_adr_cfg_dev0 = 0x00070302, // Rank 0 Density 512MB.
|
||||
.mc_emem_adr_cfg_dev1 = 0x00070302, // Rank 1 Density 512MB.
|
||||
.mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
|
||||
.mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
|
||||
.mc_emem_adr_cfg_bank_mask1 = 0x39722800,
|
||||
@@ -646,46 +646,51 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
|
||||
static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = {
|
||||
// Hynix timing config.
|
||||
{ 0x0000000D, 67, DRAM_ID(1) | DRAM_ID(5) }, // emc_r2w.
|
||||
{ 0x00000001, 91, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_extra.
|
||||
{ 0x80000000, 92, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_width.
|
||||
{ 0x00000210, 317, DRAM_ID(1) | DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode.
|
||||
{ 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w.
|
||||
{ 0x0000000D, 0x10C / 4, DRAM_ID(1) }, // emc_r2w.
|
||||
{ 0x00000001, 0x16C / 4, DRAM_ID(1) }, // emc_puterm_extra.
|
||||
{ 0x80000000, 0x170 / 4, DRAM_ID(1) }, // emc_puterm_width.
|
||||
{ 0x00000210, 0x4F4 / 4, DRAM_ID(1) }, // emc_pmacro_data_rx_term_mode.
|
||||
{ 0x00000005, 0x5C0 / 4, DRAM_ID(1) }, // mc_emem_arb_timing_r2w.
|
||||
|
||||
// Samsung 6GB density config.
|
||||
{ 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density.
|
||||
{ 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density.
|
||||
{ 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density.
|
||||
{ 0x000C0302, 0x56C / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB Rank 0 density.
|
||||
{ 0x000C0302, 0x570 / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density.
|
||||
{ 0x00001800, 0x584 / 4, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density.
|
||||
|
||||
#ifdef CONFIG_SDRAM_COPPER_SUPPORT
|
||||
// Copper prototype Samsung/Hynix/Micron timing configs.
|
||||
{ 0x0000003A, 59, DRAM_ID(6) }, // emc_rfc. Auto refresh.
|
||||
{ 0x0000001D, 60, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh.
|
||||
{ 0x00000012, 108, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden.
|
||||
{ 0x0000003B, 112, DRAM_ID(6) }, // emc_txsr.
|
||||
{ 0x0000003B, 113, DRAM_ID(6) }, // emc_txsr_dll.
|
||||
{ 0x00000003, 119, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_tclkstable.
|
||||
{ 0x00120015, 205, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x00160012, 206, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
|
||||
{ 0x00120015, 211, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00160012, 212, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
|
||||
{ 0x002F0032, 213, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00310032, 214, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00360034, 215, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0033002F, 216, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
|
||||
{ 0x00000006, 217, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x002F0032, 219, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00310032, 220, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00360034, 221, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0033002F, 222, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
|
||||
{ 0x00000006, 223, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00150015, 233, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x00120012, 235, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_2.
|
||||
{ 0x00160016, 236, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_3.
|
||||
{ 0x00000015, 237, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x00000012, 295, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2.
|
||||
{ 0x00000012, 296, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3.
|
||||
{ 0x00000007, 370, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh.
|
||||
{ 0x72A30504, 373, DRAM_ID(6) }, // mc_emem_arb_misc0.
|
||||
{ 0x0000003A, 0xEC / 4, DRAM_ID(6) }, // emc_rfc. Auto refresh.
|
||||
{ 0x0000001D, 0xF0 / 4, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh.
|
||||
{ 0x0000000D, 0x10C / 4, DRAM_ID(5) }, // emc_r2w.
|
||||
{ 0x00000001, 0x16C / 4, DRAM_ID(5) }, // emc_puterm_extra.
|
||||
{ 0x80000000, 0x170 / 4, DRAM_ID(5) }, // emc_puterm_width.
|
||||
{ 0x00000012, 0x1B0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden.
|
||||
{ 0x0000003B, 0x1C0 / 4, DRAM_ID(6) }, // emc_txsr.
|
||||
{ 0x0000003B, 0x1C4 / 4, DRAM_ID(6) }, // emc_txsr_dll.
|
||||
{ 0x00000003, 0x1DC / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_tclkstable.
|
||||
{ 0x00120015, 0x334 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x00160012, 0x338 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
|
||||
{ 0x00120015, 0x34C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00160012, 0x350 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
|
||||
{ 0x002F0032, 0x354 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00310032, 0x358 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00360034, 0x35C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0033002F, 0x360 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
|
||||
{ 0x00000006, 0x364 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x002F0032, 0x36C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00310032, 0x370 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00360034, 0x374 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0033002F, 0x378 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
|
||||
{ 0x00000006, 0x37C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00150015, 0x3A4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x00120012, 0x3AC / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_2.
|
||||
{ 0x00160016, 0x3B0 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_3.
|
||||
{ 0x00000015, 0x3B4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x00000012, 0x49C / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2.
|
||||
{ 0x00000012, 0x4A0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3.
|
||||
{ 0x00000210, 0x4F4 / 4, DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode.
|
||||
{ 0x00000005, 0x5C0 / 4, DRAM_ID(5) }, // mc_emem_arb_timing_r2w.
|
||||
{ 0x00000007, 0x5C8 / 4, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh.
|
||||
{ 0x72A30504, 0x5D4 / 4, DRAM_ID(6) }, // mc_emem_arb_misc0.
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
static const u8 _dram_cfg_lz[1262] = {
|
||||
0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
|
||||
0x00, 0x2C, 0x17, 0x04, 0x09, 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08,
|
||||
0x17, 0x10, 0x10, 0x00, 0x00, 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00,
|
||||
0x00, 0x04, 0xB4, 0x01, 0x70, 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00,
|
||||
0x70, 0x17, 0x10, 0x24, 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40,
|
||||
0x00, 0x00, 0x00, 0x17, 0x04, 0x04, 0x17, 0x09, 0x18, 0xFF, 0xFF, 0x1F,
|
||||
0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x77,
|
||||
0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, 0x17, 0x08, 0x08, 0xA6, 0xA6,
|
||||
0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x04, 0x04,
|
||||
0x04, 0x04, 0x17, 0x04, 0x04, 0x17, 0x04, 0x3C, 0x1F, 0x1F, 0x1F, 0x1F,
|
||||
0x17, 0x04, 0x04, 0x17, 0x06, 0x06, 0x00, 0x00, 0x04, 0x08, 0x17, 0x06,
|
||||
0x46, 0xA1, 0x01, 0x00, 0x00, 0x32, 0x17, 0x0B, 0x64, 0x01, 0x17, 0x04,
|
||||
0x7C, 0x17, 0x07, 0x0C, 0x03, 0x17, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1E,
|
||||
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13,
|
||||
0x17, 0x0B, 0x2C, 0x09, 0x00, 0x00, 0x00, 0x17, 0x05, 0x5D, 0x17, 0x07,
|
||||
0x10, 0x0B, 0x17, 0x07, 0x28, 0x08, 0x17, 0x07, 0x0C, 0x17, 0x04, 0x1C,
|
||||
0x20, 0x00, 0x00, 0x00, 0x06, 0x17, 0x04, 0x04, 0x17, 0x07, 0x08, 0x17,
|
||||
0x04, 0x50, 0x17, 0x04, 0x2C, 0x17, 0x04, 0x1C, 0x17, 0x04, 0x10, 0x17,
|
||||
0x08, 0x6C, 0x17, 0x04, 0x10, 0x17, 0x04, 0x38, 0x17, 0x04, 0x40, 0x05,
|
||||
0x17, 0x07, 0x1C, 0x17, 0x08, 0x58, 0x17, 0x04, 0x24, 0x17, 0x04, 0x18,
|
||||
0x17, 0x08, 0x64, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14,
|
||||
0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x09, 0x0C, 0x17, 0x05, 0x82,
|
||||
0x58, 0x17, 0x07, 0x61, 0xC1, 0x17, 0x07, 0x50, 0x17, 0x04, 0x04, 0x17,
|
||||
0x08, 0x81, 0x48, 0x17, 0x04, 0x04, 0x17, 0x04, 0x28, 0x17, 0x04, 0x60,
|
||||
0x17, 0x08, 0x54, 0x27, 0x17, 0x04, 0x04, 0x17, 0x07, 0x14, 0x17, 0x04,
|
||||
0x04, 0x04, 0x17, 0x07, 0x81, 0x58, 0x17, 0x0C, 0x0C, 0x1C, 0x03, 0x00,
|
||||
0x00, 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x17, 0x04, 0x5A, 0xF3, 0x0C,
|
||||
0x04, 0x05, 0x1B, 0x06, 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05,
|
||||
0x08, 0x1D, 0x09, 0x0A, 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03,
|
||||
0x02, 0x1B, 0x1C, 0x23, 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02,
|
||||
0x0A, 0x0B, 0x1D, 0x0D, 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08,
|
||||
0x24, 0x06, 0x07, 0x9A, 0x12, 0x17, 0x05, 0x83, 0x41, 0x00, 0xFF, 0x17,
|
||||
0x10, 0x83, 0x6C, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00,
|
||||
0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00,
|
||||
0x00, 0x0B, 0x08, 0x72, 0x72, 0x0E, 0x0C, 0x17, 0x04, 0x20, 0x08, 0x08,
|
||||
0x0D, 0x0C, 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x17, 0x06,
|
||||
0x2C, 0x11, 0x08, 0x17, 0x10, 0x84, 0x67, 0x15, 0x00, 0xCC, 0x00, 0x0A,
|
||||
0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, 0xFF,
|
||||
0x0F, 0xFF, 0x0F, 0x17, 0x08, 0x83, 0x4C, 0x01, 0x03, 0x00, 0x70, 0x00,
|
||||
0x0C, 0x00, 0x01, 0x17, 0x04, 0x0C, 0x08, 0x44, 0x00, 0x10, 0x04, 0x04,
|
||||
0x00, 0x06, 0x13, 0x07, 0x00, 0x80, 0x17, 0x04, 0x10, 0xA0, 0x00, 0x2C,
|
||||
0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x80, 0x17, 0x06, 0x48, 0x08, 0x00,
|
||||
0x04, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28,
|
||||
0x28, 0x28, 0x17, 0x04, 0x04, 0x11, 0x11, 0x11, 0x11, 0x17, 0x04, 0x04,
|
||||
0xBE, 0x00, 0x00, 0x17, 0x05, 0x58, 0x17, 0x08, 0x5C, 0x17, 0x22, 0x85,
|
||||
0x6A, 0x17, 0x1A, 0x1A, 0x14, 0x00, 0x12, 0x00, 0x10, 0x17, 0x05, 0x83,
|
||||
0x0A, 0x17, 0x16, 0x18, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00,
|
||||
0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x17, 0x05, 0x83, 0x0C, 0x17,
|
||||
0x04, 0x20, 0x17, 0x18, 0x18, 0x28, 0x00, 0x28, 0x17, 0x04, 0x04, 0x17,
|
||||
0x08, 0x08, 0x17, 0x10, 0x10, 0x00, 0x14, 0x17, 0x05, 0x5A, 0x17, 0x04,
|
||||
0x5C, 0x17, 0x04, 0x5E, 0x17, 0x04, 0x0E, 0x17, 0x0E, 0x78, 0x17, 0x09,
|
||||
0x82, 0x50, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51,
|
||||
0x17, 0x08, 0x18, 0x80, 0x01, 0x00, 0x00, 0x40, 0x17, 0x04, 0x20, 0x03,
|
||||
0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, 0x11, 0x17, 0x08, 0x82, 0x58,
|
||||
0x17, 0x0C, 0x38, 0x17, 0x1B, 0x81, 0x6C, 0x17, 0x08, 0x85, 0x60, 0x17,
|
||||
0x08, 0x86, 0x50, 0x17, 0x08, 0x86, 0x60, 0x17, 0x06, 0x83, 0x21, 0x22,
|
||||
0x04, 0xFF, 0xFF, 0xAF, 0x4F, 0x17, 0x0C, 0x86, 0x74, 0x17, 0x08, 0x2C,
|
||||
0x8B, 0xFF, 0x07, 0x17, 0x06, 0x81, 0x04, 0x32, 0x54, 0x76, 0x10, 0x47,
|
||||
0x32, 0x65, 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75,
|
||||
0x64, 0x32, 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45,
|
||||
0x32, 0x67, 0x17, 0x04, 0x24, 0x49, 0x92, 0x24, 0x17, 0x04, 0x04, 0x17,
|
||||
0x11, 0x7C, 0x1B, 0x17, 0x04, 0x04, 0x17, 0x13, 0x81, 0x14, 0x2F, 0x41,
|
||||
0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x17, 0x04, 0x7C, 0xFF, 0xFF, 0xFF,
|
||||
0x7F, 0x0B, 0xD7, 0x06, 0x40, 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03,
|
||||
0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x17, 0x06, 0x86, 0x59,
|
||||
0x17, 0x0F, 0x89, 0x14, 0x37, 0x17, 0x07, 0x82, 0x72, 0x10, 0x17, 0x06,
|
||||
0x83, 0x0D, 0x00, 0x11, 0x01, 0x17, 0x05, 0x85, 0x39, 0x17, 0x04, 0x0E,
|
||||
0x0A, 0x17, 0x07, 0x89, 0x29, 0x17, 0x04, 0x1B, 0x17, 0x08, 0x86, 0x77,
|
||||
0x17, 0x09, 0x12, 0x20, 0x00, 0x00, 0x00, 0x81, 0x10, 0x09, 0x28, 0x93,
|
||||
0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, 0x17, 0x18, 0x82, 0x2C, 0xFF,
|
||||
0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0x17, 0x04, 0x04, 0xDC, 0xDC,
|
||||
0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x17, 0x04, 0x04, 0x17, 0x04, 0x04,
|
||||
0x17, 0x05, 0x82, 0x24, 0x03, 0x07, 0x17, 0x04, 0x04, 0x00, 0x00, 0x24,
|
||||
0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, 0x00, 0x28, 0x72, 0x39, 0x00, 0x10,
|
||||
0x9C, 0x4B, 0x17, 0x04, 0x64, 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00,
|
||||
0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x17, 0x06, 0x85, 0x60, 0x17,
|
||||
0x10, 0x82, 0x74, 0x17, 0x08, 0x08, 0x17, 0x08, 0x88, 0x00, 0x17, 0x04,
|
||||
0x10, 0x04, 0x17, 0x0B, 0x87, 0x6C, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02,
|
||||
0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x17, 0x08, 0x8B, 0x18,
|
||||
0x1F, 0x17, 0x09, 0x81, 0x73, 0x00, 0xFF, 0x00, 0xFF, 0x17, 0x05, 0x86,
|
||||
0x48, 0x17, 0x04, 0x0C, 0x17, 0x07, 0x86, 0x34, 0x00, 0x00, 0xF0, 0x17,
|
||||
0x09, 0x87, 0x54, 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x17, 0x0C, 0x81,
|
||||
0x52, 0x17, 0x0A, 0x1C, 0x17, 0x10, 0x81, 0x6C, 0x17, 0x0A, 0x82, 0x21,
|
||||
0x17, 0x07, 0x82, 0x4D, 0x17, 0x0A, 0x8A, 0x1B, 0x17, 0x11, 0x2C, 0x76,
|
||||
0x0C, 0x17, 0x0A, 0x8A, 0x67, 0x17, 0x0F, 0x84, 0x28, 0x17, 0x06, 0x34,
|
||||
0x17, 0x17, 0x3A, 0x7E, 0x16, 0x40, 0x17, 0x0C, 0x8B, 0x1F, 0x17, 0x2A,
|
||||
0x38, 0x1E, 0x17, 0x0A, 0x38, 0x17, 0x13, 0x81, 0x28, 0x00, 0xC0, 0x17,
|
||||
0x17, 0x55, 0x46, 0x24, 0x17, 0x0A, 0x81, 0x28, 0x17, 0x14, 0x38, 0x17,
|
||||
0x18, 0x81, 0x60, 0x46, 0x2C, 0x17, 0x06, 0x38, 0xEC, 0x17, 0x0D, 0x16,
|
||||
0x17, 0x0E, 0x82, 0x3C, 0x17, 0x82, 0x0C, 0x8E, 0x68, 0x17, 0x04, 0x24,
|
||||
0x17, 0x5C, 0x8E, 0x68, 0x17, 0x07, 0x82, 0x5F, 0x80, 0x17, 0x87, 0x01,
|
||||
0x8E, 0x68, 0x02, 0x17, 0x81, 0x4A, 0x8E, 0x68, 0x17, 0x0C, 0x87, 0x78,
|
||||
0x17, 0x85, 0x28, 0x8E, 0x68, 0x17, 0x8E, 0x68, 0x9D, 0x50, 0x17, 0x81,
|
||||
0x24, 0x8E, 0x68, 0x17, 0x04, 0x2C, 0x17, 0x28, 0x8E, 0x68, 0x17, 0x04,
|
||||
0x30, 0x17, 0x85, 0x3C, 0x8E, 0x68, 0x12, 0x17, 0x07, 0x85, 0x70, 0x17,
|
||||
0x88, 0x74, 0x8E, 0x68, 0x17, 0x87, 0x3E, 0x9D, 0x50, 0x0C, 0x17, 0x04,
|
||||
0x04, 0x17, 0x12, 0x8E, 0x68, 0x18, 0x17, 0x87, 0x12, 0xBB, 0x20, 0x17,
|
||||
0x83, 0x04, 0x9D, 0x50, 0x15, 0x17, 0x05, 0x8D, 0x76, 0x17, 0x0F, 0x8B,
|
||||
0x49, 0x17, 0x0B, 0x18, 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00,
|
||||
0x34, 0x00, 0x36, 0x00, 0x2F, 0x00, 0x33, 0x17, 0x09, 0x84, 0x0C, 0x17,
|
||||
0x18, 0x18, 0x17, 0x20, 0x8E, 0x68, 0x15, 0x17, 0x07, 0x5A, 0x17, 0x06,
|
||||
0x5E, 0x16, 0x00, 0x15, 0x17, 0x82, 0x40, 0x9D, 0x50, 0x17, 0x86, 0x5F,
|
||||
0xBB, 0x20, 0x3A, 0x00, 0x00, 0x00, 0x1D, 0x17, 0x81, 0x4F, 0xAC, 0x38,
|
||||
0x3B, 0x17, 0x04, 0x04, 0x17, 0x86, 0x30, 0x8E, 0x68, 0x17, 0x81, 0x53,
|
||||
0xAC, 0x38, 0x07, 0x17, 0x0D, 0x8E, 0x68, 0xA3, 0x72, 0x17, 0x83, 0x10,
|
||||
0x8E, 0x68
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 CTCaer
|
||||
* Copyright (c) 2020-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
#define DRAM_CFG_T210B01_SIZE 2104
|
||||
|
||||
#define DRAM_ID2(x) BIT((x) - 7)
|
||||
|
||||
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,
|
||||
@@ -109,7 +107,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
|
||||
.emc_pmacro_ca_tx_drive = 0x3F3F3F3F,
|
||||
.emc_pmacro_cmd_tx_drive = 0x00001220,
|
||||
.emc_pmacro_auto_cal_common = 0x00000804,
|
||||
.emc_pmacro_zcrtl = 0x505050,
|
||||
.emc_pmacro_zcrtl = 0x00505050,
|
||||
|
||||
/* Specifies the time for the calibration to stabilize (in microseconds) */
|
||||
.emc_auto_cal_wait = 0x000001A1,
|
||||
@@ -122,7 +120,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
|
||||
* DRAM size information
|
||||
* Specifies the value for EMC_ADR_CFG
|
||||
*/
|
||||
.emc_adr_cfg = 0x00000000, // 1 populated DRAM Device.
|
||||
.emc_adr_cfg = 0x00000000, // 1 Rank.
|
||||
|
||||
/*
|
||||
* Specifies the time to wait after asserting pin
|
||||
@@ -273,7 +271,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
|
||||
.emc_cfg_dig_dll = 0x002C00A0,
|
||||
.emc_cfg_dig_dll_1 = 0x000F3701,
|
||||
.emc_cfg_dig_dll_period = 0x00008000,
|
||||
.emc_dev_select = 0x00000002, // Dev0 only.
|
||||
.emc_dev_select = 0x00000002, // Rank 0 only.
|
||||
.emc_sel_dpd_ctrl = 0x0004000C,
|
||||
|
||||
/* Pads trimmer delays */
|
||||
@@ -543,9 +541,9 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
|
||||
.emc_pmacro_cmd_ctrl2 = 0x00000000,
|
||||
|
||||
/* DRAM size information */
|
||||
.mc_emem_adr_cfg = 0x00000000, // 1 populated DRAM Device.
|
||||
.mc_emem_adr_cfg_dev0 = 0x00080302, // Density 1024MB.
|
||||
.mc_emem_adr_cfg_dev1 = 0x00080302, // Density 1024MB.
|
||||
.mc_emem_adr_cfg = 0x00000000, // 1 Rank.
|
||||
.mc_emem_adr_cfg_dev0 = 0x00080302, // Rank 0 Density 1024MB.
|
||||
.mc_emem_adr_cfg_dev1 = 0x00080302, // Rank 1 Density 1024MB.
|
||||
.mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
|
||||
.mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
|
||||
.mc_emem_adr_cfg_bank_mask1 = 0x39722800,
|
||||
@@ -708,295 +706,287 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
|
||||
static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
|
||||
// Samsung LPDDR4X 4GB X1X2 for prototype Iowa.
|
||||
{ 0x000E0022, 0x3AC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x001B0010, 0x3B0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
|
||||
{ 0x000E0022, 0x3C4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x001B0010, 0x3C8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
|
||||
{ 0x00490043, 0x3CC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00420045, 0x3D0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00490047, 0x3D4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x00460047, 0x3D8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
|
||||
{ 0x00000016, 0x3DC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x00100000, 0x3E0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_5.
|
||||
{ 0x00490043, 0x3E4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00420045, 0x3E8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00490047, 0x3EC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x00460047, 0x3F0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
|
||||
{ 0x00000016, 0x3F4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00100000, 0x3F8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_5.
|
||||
{ 0x00220022, 0x41C / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x000E000E, 0x420 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00100010, 0x424 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_2.
|
||||
{ 0x001B001B, 0x428 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_3.
|
||||
{ 0x00000022, 0x42C / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x000E0022, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x001B0010, 0x3B0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
|
||||
{ 0x000E0022, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x001B0010, 0x3C8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
|
||||
{ 0x00490043, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00420045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00490047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x00460047, 0x3D8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
|
||||
{ 0x00000016, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x00100000, 0x3E0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_5.
|
||||
{ 0x00490043, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00420045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00490047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x00460047, 0x3F0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
|
||||
{ 0x00000016, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00100000, 0x3F8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_5.
|
||||
{ 0x00220022, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x000E000E, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00100010, 0x424 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_2.
|
||||
{ 0x001B001B, 0x428 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_3.
|
||||
{ 0x00000022, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_4.
|
||||
|
||||
// Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ for SDEV Iowa and Hoag.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000006, 0x1CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput_duration.
|
||||
{ 0x08010004, 0x2B8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw1.
|
||||
{ 0x08020000, 0x2BC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw2.
|
||||
{ 0x080D0000, 0x2C0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw3.
|
||||
{ 0x08033131, 0x2C8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw6.
|
||||
{ 0x080B0000, 0x2CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw8.
|
||||
{ 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw9.
|
||||
{ 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw10.
|
||||
{ 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw12.
|
||||
{ 0x0C0D0000, 0x2DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw13.
|
||||
{ 0x08161414, 0x2E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw14.
|
||||
{ 0x08010004, 0x2E4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw_extra.
|
||||
{ 0x00000000, 0x340 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_dev_select. Both devices.
|
||||
{ 0x35353535, 0x350 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_vref_dq_0.
|
||||
{ 0x35353535, 0x354 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_vref_dq_1.
|
||||
{ 0x00100010, 0x3FC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
|
||||
{ 0x00100010, 0x400 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
|
||||
{ 0x00100010, 0x404 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
|
||||
{ 0x00100010, 0x408 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
|
||||
{ 0x00100010, 0x40C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
|
||||
{ 0x00100010, 0x410 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
|
||||
{ 0x00100010, 0x414 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
|
||||
{ 0x00100010, 0x418 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
|
||||
{ 0x0051004F, 0x450 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_mrw_cmd.
|
||||
{ 0x40000001, 0x45C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00002000, 0x64C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000002, 0x680 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_timing_r2r.
|
||||
{ 0x02020001, 0x694 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_da_turns.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_video_protect_gpu_override1.
|
||||
// Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ Die-M for SDEV Iowa and Hoag.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_adr_cfg. 2 Ranks.
|
||||
{ 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput_duration.
|
||||
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw1.
|
||||
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw2.
|
||||
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw3.
|
||||
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw6.
|
||||
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw8.
|
||||
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw9.
|
||||
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw10.
|
||||
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw12.
|
||||
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw13.
|
||||
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw14.
|
||||
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw_extra.
|
||||
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_dev_select. Both devices.
|
||||
{ 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_0.
|
||||
{ 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_1.
|
||||
{ 0x00100010, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
|
||||
{ 0x00100010, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
|
||||
{ 0x00100010, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
|
||||
{ 0x00100010, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
|
||||
{ 0x00100010, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
|
||||
{ 0x00100010, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
|
||||
{ 0x00100010, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
|
||||
{ 0x00100010, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
|
||||
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_mrw_cmd.
|
||||
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_adr_cfg. 2 Ranks.
|
||||
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_timing_r2r.
|
||||
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_da_turns.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT for Iowa and Hoag.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_dyn_self_ref_control.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // mc_video_protect_gpu_override1.
|
||||
// Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:E Die-E for retail Iowa and Hoag.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_dyn_self_ref_control.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 4GB Die-Y for Iowa.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(16) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(16) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(16) }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, DRAM_ID2(16) }, // emc_dyn_self_ref_control.
|
||||
{ 0x32323232, 0x350 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_vref_dq_0.
|
||||
{ 0x32323232, 0x354 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_vref_dq_1.
|
||||
{ 0x000F0018, 0x3AC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x000F0018, 0x3C4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00440048, 0x3CC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00440045, 0x3D0 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00470047, 0x3D4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0005000D, 0x3DC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x00440048, 0x3E4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00440045, 0x3E8 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00470047, 0x3EC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0005000D, 0x3F4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00780078, 0x3FC / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
|
||||
{ 0x00780078, 0x400 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
|
||||
{ 0x00780078, 0x404 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
|
||||
{ 0x00780078, 0x408 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
|
||||
{ 0x00780078, 0x40C / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
|
||||
{ 0x00780078, 0x410 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
|
||||
{ 0x00780078, 0x414 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
|
||||
{ 0x00780078, 0x418 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
|
||||
{ 0x00180018, 0x41C / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x000F000F, 0x420 / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00000018, 0x42C / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override1.
|
||||
// Samsung LPDDR4X 4GB (Y01) Die-? for Iowa.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_dyn_self_ref_control.
|
||||
{ 0x32323232, 0x350 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_0.
|
||||
{ 0x32323232, 0x354 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_1.
|
||||
{ 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00780078, 0x3FC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
|
||||
{ 0x00780078, 0x400 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
|
||||
{ 0x00780078, 0x404 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
|
||||
{ 0x00780078, 0x408 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
|
||||
{ 0x00780078, 0x40C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
|
||||
{ 0x00780078, 0x410 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
|
||||
{ 0x00780078, 0x414 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
|
||||
{ 0x00780078, 0x418 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
|
||||
{ 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and SDS.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000006, 0x1CC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_einput_duration.
|
||||
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_dyn_self_ref_control.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override1.
|
||||
// Samsung LPDDR4X 4GB K4U6E3S4AA-MGCL 10nm-class (1y-X03) Die-A for retail Iowa, Hoag and Aula.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput_duration.
|
||||
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_dyn_self_ref_control.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and SDS.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000006, 0x1CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput_duration.
|
||||
{ 0x00000008, 0x24C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_tfaw.
|
||||
{ 0x08010004, 0x2B8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw1.
|
||||
{ 0x08020000, 0x2BC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw2.
|
||||
{ 0x080D0000, 0x2C0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw3.
|
||||
{ 0x08033131, 0x2C8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw6.
|
||||
{ 0x080B0000, 0x2CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw8.
|
||||
{ 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw9.
|
||||
{ 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw10.
|
||||
{ 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw12.
|
||||
{ 0x0C0D0000, 0x2DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw13.
|
||||
{ 0x08161414, 0x2E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw14.
|
||||
{ 0x08010004, 0x2E4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw_extra.
|
||||
{ 0x00000000, 0x340 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_dev_select. Both devices.
|
||||
{ 0x0051004F, 0x450 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_mrw_cmd.
|
||||
{ 0x40000001, 0x45C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00002000, 0x64C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000001, 0x670 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_faw.
|
||||
{ 0x00000002, 0x680 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_r2r.
|
||||
{ 0x02020001, 0x694 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_da_turns.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_video_protect_gpu_override1.
|
||||
// Samsung LPDDR4X 8GB K4UBE3D4AA-MGCL 10nm-class (1y-X03) Die-A for SDEV Iowa, Hoag and Aula.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_adr_cfg. 2 Ranks.
|
||||
{ 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput_duration.
|
||||
{ 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_tfaw.
|
||||
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw1.
|
||||
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw2.
|
||||
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw3.
|
||||
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw6.
|
||||
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw8.
|
||||
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw9.
|
||||
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw10.
|
||||
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw12.
|
||||
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw13.
|
||||
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw14.
|
||||
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw_extra.
|
||||
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_dev_select. Both devices.
|
||||
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_mrw_cmd.
|
||||
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_adr_cfg. 2 Ranks.
|
||||
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_faw.
|
||||
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_r2r.
|
||||
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_da_turns.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-Y for Iowa.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(20) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(20) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000008, 0x24C / 4, DRAM_ID2(20) }, // emc_tfaw.
|
||||
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(20) }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, DRAM_ID2(20) }, // emc_dyn_self_ref_control.
|
||||
{ 0x000F0018, 0x3AC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x000F0018, 0x3C4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00440048, 0x3CC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00440045, 0x3D0 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00470047, 0x3D4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0005000D, 0x3DC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x00440048, 0x3E4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00440045, 0x3E8 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00470047, 0x3EC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0005000D, 0x3F4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00180018, 0x41C / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x000F000F, 0x420 / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00000018, 0x42C / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x00000001, 0x670 / 4, DRAM_ID2(20) }, // mc_emem_arb_timing_faw.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(20) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(20) }, // mc_video_protect_gpu_override1.
|
||||
// Samsung LPDDR4X 4GB 10nm-class (1y-Y01) Die-? for Iowa.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_tfaw.
|
||||
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_dyn_self_ref_control.
|
||||
{ 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-Y for SDEV Iowa.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(21) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(21) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000008, 0x24C / 4, DRAM_ID2(21) }, // emc_tfaw.
|
||||
{ 0x08010004, 0x2B8 / 4, DRAM_ID2(21) }, // emc_mrw1.
|
||||
{ 0x08020000, 0x2BC / 4, DRAM_ID2(21) }, // emc_mrw2.
|
||||
{ 0x080D0000, 0x2C0 / 4, DRAM_ID2(21) }, // emc_mrw3.
|
||||
{ 0x08033131, 0x2C8 / 4, DRAM_ID2(21) }, // emc_mrw6.
|
||||
{ 0x080B0000, 0x2CC / 4, DRAM_ID2(21) }, // emc_mrw8.
|
||||
{ 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(21) }, // emc_mrw9.
|
||||
{ 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(21) }, // emc_mrw10.
|
||||
{ 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(21) }, // emc_mrw12.
|
||||
{ 0x0C0D0000, 0x2DC / 4, DRAM_ID2(21) }, // emc_mrw13.
|
||||
{ 0x08161414, 0x2E0 / 4, DRAM_ID2(21) }, // emc_mrw14.
|
||||
{ 0x08010004, 0x2E4 / 4, DRAM_ID2(21) }, // emc_mrw_extra.
|
||||
{ 0x00000000, 0x340 / 4, DRAM_ID2(21) }, // emc_dev_select. Both devices.
|
||||
{ 0x32323232, 0x350 / 4, DRAM_ID2(21) }, // emc_pmacro_ib_vref_dq_0.
|
||||
{ 0x32323232, 0x354 / 4, DRAM_ID2(21) }, // emc_pmacro_ib_vref_dq_1.
|
||||
{ 0x000F0018, 0x3AC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x000F0018, 0x3C4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00440048, 0x3CC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00440045, 0x3D0 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00470047, 0x3D4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0005000D, 0x3DC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x00440048, 0x3E4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00440045, 0x3E8 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00470047, 0x3EC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0005000D, 0x3F4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00180018, 0x41C / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x000F000F, 0x420 / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00000018, 0x42C / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x0051004F, 0x450 / 4, DRAM_ID2(21) }, // emc_zcal_mrw_cmd.
|
||||
{ 0x40000001, 0x45C / 4, DRAM_ID2(21) }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00002000, 0x64C / 4, DRAM_ID2(21) }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000001, 0x670 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_faw.
|
||||
{ 0x00000002, 0x680 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_r2r.
|
||||
{ 0x02020001, 0x694 / 4, DRAM_ID2(21) }, // mc_emem_arb_da_turns.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override1.
|
||||
// Samsung LPDDR4X 8GB 10nm-class (1y-Y01) Die-? for SDEV Iowa.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_adr_cfg. 2 Ranks.
|
||||
{ 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_tfaw.
|
||||
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw1.
|
||||
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw2.
|
||||
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw3.
|
||||
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw6.
|
||||
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw8.
|
||||
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw9.
|
||||
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw10.
|
||||
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw12.
|
||||
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw13.
|
||||
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw14.
|
||||
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw_extra.
|
||||
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_dev_select. Both devices.
|
||||
{ 0x32323232, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_0.
|
||||
{ 0x32323232, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_1.
|
||||
{ 0x000F0018, 0x3AC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x00440048, 0x3CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x00440045, 0x3D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00470047, 0x3D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x0005000D, 0x3DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x00440048, 0x3E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x00440045, 0x3E8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00470047, 0x3EC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x00180018, 0x41C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x000F000F, 0x420 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00000018, 0x42C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_mrw_cmd.
|
||||
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_adr_cfg. 2 Ranks.
|
||||
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw.
|
||||
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_r2r.
|
||||
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_da_turns.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown SDS.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(22) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw.
|
||||
{ 0x1C041B06, 0x26C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_0.
|
||||
{ 0x02050307, 0x270 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_1.
|
||||
{ 0x03252500, 0x274 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_2.
|
||||
{ 0x081D1E00, 0x278 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_0.
|
||||
{ 0x090C0A0D, 0x27C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_1.
|
||||
{ 0x0526260B, 0x280 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_2.
|
||||
{ 0x05030402, 0x284 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_0.
|
||||
{ 0x1B1C0600, 0x288 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_1.
|
||||
{ 0x07252507, 0x28C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_2.
|
||||
{ 0x0C1D0B0A, 0x290 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_0.
|
||||
{ 0x0800090D, 0x294 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_1.
|
||||
{ 0x0926261E, 0x298 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_2.
|
||||
{ 0x2A080624, 0x29C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_byte.
|
||||
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(22) }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, DRAM_ID2(22) }, // emc_dyn_self_ref_control.
|
||||
{ 0x00140010, 0x3AC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
|
||||
{ 0x0013000B, 0x3B0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
|
||||
{ 0x00140010, 0x3C4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
|
||||
{ 0x0013000B, 0x3C8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
|
||||
{ 0x00450047, 0x3CC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
|
||||
{ 0x004D004F, 0x3D0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
|
||||
{ 0x00460046, 0x3D4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
|
||||
{ 0x00480048, 0x3D8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
|
||||
{ 0x000C0008, 0x3DC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
|
||||
{ 0x000B000C, 0x3E0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_5.
|
||||
{ 0x00450047, 0x3E4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
|
||||
{ 0x004D004F, 0x3E8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
|
||||
{ 0x00460046, 0x3EC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
|
||||
{ 0x00480048, 0x3F0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
|
||||
{ 0x000C0008, 0x3F4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
|
||||
{ 0x000B000C, 0x3F8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_5.
|
||||
{ 0x00100010, 0x41C / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_0.
|
||||
{ 0x00140014, 0x420 / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_1.
|
||||
{ 0x00130013, 0x428 / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_3.
|
||||
{ 0x00000010, 0x42C / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_4.
|
||||
{ 0x40280100, 0x4B4 / 4, DRAM_ID2(22) }, // pmc_ddr_cfg.
|
||||
{ 0x4F9F9FFF, 0x4B8 / 4, DRAM_ID2(22) }, // pmc_io_dpd3_req.
|
||||
{ 0x64032157, 0x4D8 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte0.
|
||||
{ 0x51320467, 0x4DC / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte1.
|
||||
{ 0x04735621, 0x4E0 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte2.
|
||||
{ 0x47356012, 0x4E4 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte3.
|
||||
{ 0x12045673, 0x4E8 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte0.
|
||||
{ 0x43657210, 0x4EC / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte1.
|
||||
{ 0x65402137, 0x4F0 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte2.
|
||||
{ 0x57302164, 0x4F4 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte3.
|
||||
{ 0x4F9F9FFF, 0x534 / 4, DRAM_ID2(22) }, // emc_pmc_scratch1.
|
||||
{ 0x4033CF1F, 0x53C / 4, DRAM_ID2(22) }, // emc_pmc_scratch3.
|
||||
{ 0x10000000, 0x590 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd3.
|
||||
{ 0x00030108, 0x594 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x01400050, 0x598 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x29081081, 0x5A0 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping0.
|
||||
{ 0x54A59332, 0x5A4 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping1.
|
||||
{ 0x87766B4A, 0x5A8 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping2.
|
||||
{ 0x00000001, 0x670 / 4, DRAM_ID2(22) }, // mc_emem_arb_timing_faw.
|
||||
{ 0xE4FACB43, 0x6D4 / 4, DRAM_ID2(22) }, // mc_video_protect_vpr_override. + TSEC, NVENC.
|
||||
{ 0x0600FED3, 0x6D8 / 4, DRAM_ID2(22) }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1.
|
||||
{ 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode.
|
||||
/*
|
||||
// Samsung LPDDR4X 8GB 10nm-class (1y-A01) Die-? for SDEV Aula?
|
||||
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_adr_cfg. 2 Ranks.
|
||||
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw1.
|
||||
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw2.
|
||||
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw3.
|
||||
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw6.
|
||||
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw8.
|
||||
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw9.
|
||||
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw10.
|
||||
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw12.
|
||||
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw13.
|
||||
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw14.
|
||||
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw_extra.
|
||||
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_dev_select. Both devices.
|
||||
{ 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_0.
|
||||
{ 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_1.
|
||||
{ 0x35353535, 0x358 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_0.
|
||||
{ 0x35353535, 0x35C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_1.
|
||||
{ 0x00480048, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
|
||||
{ 0x00480048, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
|
||||
{ 0x00480048, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
|
||||
{ 0x00480048, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
|
||||
{ 0x00480048, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
|
||||
{ 0x00480048, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
|
||||
{ 0x00480048, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
|
||||
{ 0x00480048, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
|
||||
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_mrw_cmd.
|
||||
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_init_dev1.
|
||||
{ 0x00010100, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00400010, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_adr_cfg. 2 Ranks.
|
||||
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000002, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_faw.
|
||||
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_r2r.
|
||||
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_da_turns.
|
||||
*/
|
||||
|
||||
// Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/SDS.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_einput_duration.
|
||||
{ 0x00000008, 0x24C / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_tfaw.
|
||||
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_dyn_self_ref_control.
|
||||
{ 0x00000001, 0x670 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_emem_arb_timing_faw.
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_video_protect_gpu_override1.
|
||||
// Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:F 10nm-class (1y-01) Die-F for Newer Iowa/Hoag/Aula.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput_duration.
|
||||
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_tfaw.
|
||||
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_dyn_self_ref_control.
|
||||
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_emem_arb_timing_faw.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Hynix LPDDR4X 4GB 10nm-class (1y-01) Die-A for Unknown Iowa/Hoag/Aula.
|
||||
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput.
|
||||
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput_duration.
|
||||
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_tfaw.
|
||||
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_mrw14.
|
||||
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_dyn_self_ref_control.
|
||||
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_emem_arb_timing_faw.
|
||||
{ 0xE4FACB43, 0x6D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override. + TSEC, NVENC.
|
||||
{ 0x0600FED3, 0x6D8 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
|
||||
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override1.
|
||||
|
||||
//!TODO: Too many duplicates.
|
||||
};
|
||||
|
||||
@@ -1385,24 +1385,24 @@ static void _sdram_lp0_save_params_t210b01(const void *params)
|
||||
s(emc_warm_boot_mrw_extra, 31:30, scratch6, 3:2);
|
||||
s(emc_mrw_lpddr2zcal_warm_boot, 27:26, scratch6, 5:4);
|
||||
s(emc_warm_boot_mrw_extra, 27:26, scratch6, 7:6);
|
||||
s(EmcMrw6, 27:0, scratch8, 27:0);
|
||||
s(EmcMrw6, 31:30, scratch8, 29:28);
|
||||
s(EmcMrw8, 27:0, scratch9, 27:0);
|
||||
s(EmcMrw8, 31:30, scratch9, 29:28);
|
||||
s(EmcMrw9, 27:0, scratch10, 27:0);
|
||||
s(EmcMrw9, 31:30, scratch10, 29:28);
|
||||
s(EmcMrw10, 27:0, scratch11, 27:0);
|
||||
s(EmcMrw10, 31:30, scratch11, 29:28);
|
||||
s(EmcMrw12, 27:0, scratch12, 27:0);
|
||||
s(EmcMrw12, 31:30, scratch12, 29:28);
|
||||
s(EmcMrw13, 27:0, scratch13, 27:0);
|
||||
s(EmcMrw13, 31:30, scratch13, 29:28);
|
||||
s(EmcMrw14, 27:0, scratch14, 27:0);
|
||||
s(EmcMrw14, 31:30, scratch14, 29:28);
|
||||
s(EmcMrw1, 7:0, scratch15, 7:0);
|
||||
s(EmcMrw1, 23:16, scratch15, 15:8);
|
||||
s(EmcMrw1, 27:26, scratch15, 17:16);
|
||||
s(EmcMrw1, 31:30, scratch15, 19:18);
|
||||
s(emc_mrw6, 27:0, scratch8, 27:0);
|
||||
s(emc_mrw6, 31:30, scratch8, 29:28);
|
||||
s(emc_mrw8, 27:0, scratch9, 27:0);
|
||||
s(emc_mrw8, 31:30, scratch9, 29:28);
|
||||
s(emc_mrw9, 27:0, scratch10, 27:0);
|
||||
s(emc_mrw9, 31:30, scratch10, 29:28);
|
||||
s(emc_mrw10, 27:0, scratch11, 27:0);
|
||||
s(emc_mrw10, 31:30, scratch11, 29:28);
|
||||
s(emc_mrw12, 27:0, scratch12, 27:0);
|
||||
s(emc_mrw12, 31:30, scratch12, 29:28);
|
||||
s(emc_mrw13, 27:0, scratch13, 27:0);
|
||||
s(emc_mrw13, 31:30, scratch13, 29:28);
|
||||
s(emc_mrw14, 27:0, scratch14, 27:0);
|
||||
s(emc_mrw14, 31:30, scratch14, 29:28);
|
||||
s(emc_mrw1, 7:0, scratch15, 7:0);
|
||||
s(emc_mrw1, 23:16, scratch15, 15:8);
|
||||
s(emc_mrw1, 27:26, scratch15, 17:16);
|
||||
s(emc_mrw1, 31:30, scratch15, 19:18);
|
||||
s(emc_warm_boot_mrw_extra, 7:0, scratch16, 7:0);
|
||||
s(emc_warm_boot_mrw_extra, 23:16, scratch16, 15:8);
|
||||
s(emc_warm_boot_mrw_extra, 27:26, scratch16, 17:16);
|
||||
@@ -1518,7 +1518,7 @@ static void _sdram_lp0_save_params_t210b01(const void *params)
|
||||
s(pllm_kcp, 1:0, scratch3, 23:22);
|
||||
|
||||
c32(0, scratch36);
|
||||
s(PllMSetupControl, 23:0, scratch36, 23:0);
|
||||
s(pllm_setup_control, 23:0, scratch36, 23:0);
|
||||
|
||||
c32(0, scratch4);
|
||||
s(pllm_stable_time, 9:0, scratch4, 9:0); // s32(pllm_stable_time, scratch4);, s(pllm_stable_time, 31:0, scratch4, 31:10);
|
||||
|
||||
@@ -48,8 +48,8 @@ u8 smmu_payload[] __attribute__((aligned(16))) = {
|
||||
void *page_alloc(u32 num)
|
||||
{
|
||||
u8 *res = _pageheap;
|
||||
_pageheap += 0x1000 * num;
|
||||
memset(res, 0, 0x1000 * num);
|
||||
_pageheap += SZ_PAGE * num;
|
||||
memset(res, 0, SZ_PAGE * num);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -150,8 +150,8 @@ void smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr)
|
||||
{
|
||||
u32 *pte = smmu_get_pte(pdir, addr);
|
||||
*pte = SMMU_ADDR_TO_PFN(page) | attr;
|
||||
addr += 0x1000;
|
||||
page += 0x1000;
|
||||
addr += SZ_PAGE;
|
||||
page += SZ_PAGE;
|
||||
}
|
||||
smmu_flush_all();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* 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,
|
||||
@@ -23,7 +23,7 @@
|
||||
#define LDR_LOAD_ADDR 0x40007000
|
||||
|
||||
#define IPL_LOAD_ADDR 0x40008000
|
||||
#define IPL_SZ_MAX 0x20000 // 128KB.
|
||||
#define IPL_SZ_MAX SZ_128K
|
||||
|
||||
/* --- XUSB EP context and TRB ring buffers --- */
|
||||
#define XUSB_RING_ADDR 0x40020000
|
||||
@@ -35,43 +35,50 @@
|
||||
|
||||
/* --- DRAM START --- */
|
||||
#define DRAM_START 0x80000000
|
||||
#define HOS_RSVD 0x1000000 // Do not write anything in this area.
|
||||
#define HOS_RSVD SZ_16M // Do not write anything in this area.
|
||||
|
||||
#define NYX_LOAD_ADDR 0x81000000
|
||||
#define NYX_SZ_MAX 0x1000000 // 16MB
|
||||
#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 0x20000000 // 512MB.
|
||||
#define IPL_HEAP_SZ SZ_512M
|
||||
/* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */
|
||||
|
||||
// Virtual disk / Chainloader buffers.
|
||||
#define RAM_DISK_ADDR 0xA4000000
|
||||
#define RAM_DISK_SZ 0x41000000 // 1040MB.
|
||||
#define RAM_DISK2_SZ 0x21000000 // 528MB.
|
||||
|
||||
// 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 0x200000 // 2MB.
|
||||
#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 0x8000000 // 128MB.
|
||||
#define SDMMC_UP_BUF_SZ SZ_128M
|
||||
|
||||
// Nyx buffers.
|
||||
#define NYX_STORAGE_ADDR 0xED000000
|
||||
#define NYX_RES_ADDR 0xEE000000
|
||||
#define NYX_RES_SZ 0x1000000 // 16MB.
|
||||
#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 0x1000000 // 16MB (4MB currently used).
|
||||
#define SDMMC_DMA_BUF_SZ SZ_16M // 4MB currently used.
|
||||
|
||||
// Nyx LvGL buffers.
|
||||
#define NYX_LV_VDB_ADR 0xF1000000
|
||||
@@ -93,17 +100,13 @@
|
||||
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
|
||||
#define DRAM_START2 0xFEB40000
|
||||
|
||||
// NX BIS driver sector cache.
|
||||
#define NX_BIS_CACHE_ADDR 0xFEE00000
|
||||
#define NX_BIS_CACHE_SZ 0x100000
|
||||
|
||||
// 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 0x800000
|
||||
#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))
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
#include <stddef.h>
|
||||
#include <mem/heap.h>
|
||||
|
||||
#define IANOS_EXT0 0x304E4149
|
||||
|
||||
// Module Callback
|
||||
typedef void (*cbMainModule_t)(const char *s);
|
||||
typedef void (*memcpy_t)(void *, void *, size_t);
|
||||
typedef void (*memset_t)(void *, int, size_t);
|
||||
typedef int (*reg_voltage_set_t)(u32, u32);
|
||||
|
||||
typedef struct _bdkParams_t
|
||||
{
|
||||
@@ -33,6 +36,8 @@ typedef struct _bdkParams_t
|
||||
heap_t *sharedHeap;
|
||||
memcpy_t memcpy;
|
||||
memset_t memset;
|
||||
u32 extension_magic;
|
||||
reg_voltage_set_t reg_voltage_set;
|
||||
} *bdkParams_t;
|
||||
|
||||
// Module Entrypoint
|
||||
|
||||
@@ -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,
|
||||
@@ -30,24 +29,33 @@
|
||||
#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4)
|
||||
#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4)
|
||||
#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4)
|
||||
#define MAX77620_CNFGGLBL1_LBHYST (BIT(5) | BIT(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_WDTEN BIT(2)
|
||||
#define MAX77620_WDTSLPC BIT(3)
|
||||
#define MAX77620_WDTOFFC BIT(4)
|
||||
#define MAX77620_TWD_MASK 0x3
|
||||
#define MAX77620_TWD_2s 0x0
|
||||
#define MAX77620_TWD_16s 0x1
|
||||
#define MAX77620_TWD_64s 0x2
|
||||
#define MAX77620_TWD_128s 0x3
|
||||
#define MAX77620_WDTEN BIT(2)
|
||||
#define MAX77620_WDTSLPC BIT(3)
|
||||
#define MAX77620_WDTOFFC BIT(4)
|
||||
#define MAX77620_GLBL_LPM BIT(5)
|
||||
#define MAX77620_I2CTWD_MASK 0xC0
|
||||
#define MAX77620_I2CTWD_DISABLED 0x00
|
||||
#define MAX77620_I2CTWD_1_33ms 0x40
|
||||
#define MAX77620_I2CTWD_35_7ms 0x80
|
||||
#define MAX77620_I2CTWD_41_7ms 0xC0
|
||||
|
||||
#define MAX77620_REG_CNFGGLBL3 0x02
|
||||
#define MAX77620_WDTC_MASK 0x3
|
||||
|
||||
#define MAX77620_REG_CNFG1_32K 0x03
|
||||
#define MAX77620_CNFG1_PWR_MD_32K_MASK 0x3
|
||||
#define MAX77620_CNFG1_32K_OUT0_EN BIT(2)
|
||||
#define MAX77620_CNFG1_32KLOAD_MASK 0x30
|
||||
#define MAX77620_CNFG1_32K_OK BIT(7)
|
||||
|
||||
#define MAX77620_REG_CNFGBBC 0x04
|
||||
#define MAX77620_CNFGBBC_ENABLE BIT(0)
|
||||
@@ -64,6 +72,7 @@
|
||||
#define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
|
||||
|
||||
#define MAX77620_REG_IRQTOP 0x05
|
||||
#define MAX77620_REG_IRQTOPM 0x0D
|
||||
#define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1)
|
||||
#define MAX77620_IRQ_TOP_32K_MASK BIT(2)
|
||||
#define MAX77620_IRQ_TOP_RTC_MASK BIT(3)
|
||||
@@ -73,28 +82,53 @@
|
||||
#define MAX77620_IRQ_TOP_GLBL_MASK BIT(7)
|
||||
|
||||
#define MAX77620_REG_INTLBT 0x06
|
||||
#define MAX77620_REG_IRQTOPM 0x0D
|
||||
#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 BIT(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 occured.
|
||||
#define MAX77620_REG_IRQ_MSK_L0_7 0x10
|
||||
#define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occured. Only bit0: LDO8 is valid.
|
||||
#define MAX77620_REG_IRQ_MSK_L8 0x11
|
||||
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt.
|
||||
|
||||
#define MAX77620_REG_ONOFFIRQ 0x0B
|
||||
#define MAX77620_REG_ONOFFIRQM 0x12
|
||||
#define MAX77620_ONOFFIRQ_MRWRN BIT(0)
|
||||
#define MAX77620_ONOFFIRQ_EN0_1SEC BIT(1)
|
||||
#define MAX77620_ONOFFIRQ_EN0_F BIT(2)
|
||||
#define MAX77620_ONOFFIRQ_EN0_R BIT(3)
|
||||
#define MAX77620_ONOFFIRQ_LID_F BIT(4)
|
||||
#define MAX77620_ONOFFIRQ_LID_R BIT(5)
|
||||
#define MAX77620_ONOFFIRQ_ACOK_F BIT(6)
|
||||
#define MAX77620_ONOFFIRQ_ACOK_R BIT(7)
|
||||
|
||||
#define MAX77620_REG_NVERC 0x0C // Shutdown reason (non-volatile).
|
||||
#define MAX77620_NVERC_SHDN BIT(0)
|
||||
#define MAX77620_NVERC_WTCHDG BIT(1)
|
||||
#define MAX77620_NVERC_HDRST BIT(2)
|
||||
#define MAX77620_NVERC_TOVLD BIT(3)
|
||||
#define MAX77620_NVERC_MBLSD BIT(4)
|
||||
#define MAX77620_NVERC_MBO BIT(5)
|
||||
#define MAX77620_NVERC_MBU BIT(6)
|
||||
#define MAX77620_NVERC_RSTIN BIT(7)
|
||||
|
||||
#define MAX77620_REG_STATLBT 0x13
|
||||
#define MAX77620_REG_STATSD 0x14
|
||||
|
||||
#define MAX77620_REG_ONOFFSTAT 0x15
|
||||
#define MAX77620_ONOFFSTAT_LID BIT(0)
|
||||
#define MAX77620_ONOFFSTAT_ACOK BIT(1)
|
||||
#define MAX77620_ONOFFSTAT_EN0 BIT(2)
|
||||
|
||||
/* SD and LDO Registers */
|
||||
#define MAX77620_REG_SD0 0x16
|
||||
@@ -102,18 +136,42 @@
|
||||
#define MAX77620_REG_SD2 0x18
|
||||
#define MAX77620_REG_SD3 0x19
|
||||
#define MAX77620_REG_SD4 0x1A
|
||||
#define MAX77620_REG_DVSSD0 0x1B
|
||||
#define MAX77620_REG_DVSSD1 0x1C
|
||||
#define MAX77620_SDX_VOLT_MASK 0xFF
|
||||
#define MAX77620_SD0_VOLT_MASK 0x3F
|
||||
#define MAX77620_SD1_VOLT_MASK 0x7F
|
||||
#define MAX77620_LDO_VOLT_MASK 0x3F
|
||||
#define MAX77620_REG_DVSSD0 0x1B
|
||||
#define MAX77620_REG_DVSSD1 0x1C
|
||||
#define MAX77620_REG_SD0_CFG 0x1D // SD CNFG1.
|
||||
#define MAX77620_REG_SD1_CFG 0x1E // SD CNFG1.
|
||||
#define MAX77620_REG_SD2_CFG 0x1F // SD CNFG1.
|
||||
#define MAX77620_REG_SD3_CFG 0x20 // SD CNFG1.
|
||||
#define MAX77620_REG_SD4_CFG 0x21 // SD CNFG1.
|
||||
|
||||
#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,26 +190,36 @@
|
||||
#define MAX77620_REG_LDO7_CFG2 0x32
|
||||
#define MAX77620_REG_LDO8_CFG 0x33
|
||||
#define MAX77620_REG_LDO8_CFG2 0x34
|
||||
#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_ADE_MASK (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
|
||||
#define MAX20024_LDO_CFG2_MPOK_MASK BIT(2)
|
||||
#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
|
||||
/*! LDO CFG2 */
|
||||
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_FAST (0 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_SLOW (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_MPOK_MASK BIT(2)
|
||||
#define MAX77620_LDO_CFG2_POK_MASK BIT(3)
|
||||
#define MAX77620_LDO_CFG2_COMP_SHIFT 4
|
||||
#define MAX77620_LDO_CFG2_COMP_MASK (3 << MAX77620_LDO_COMP_SHIFT)
|
||||
#define MAX77620_LDO_CFG2_COMP_SLOW 3
|
||||
#define MAX77620_LDO_CFG2_COMP_MID_SLOW 2
|
||||
#define MAX77620_LDO_CFG2_COMP_MID_FAST 1
|
||||
#define MAX77620_LDO_CFG2_COMP_FAST 0
|
||||
#define MAX77620_LDO_CFG2_ALPM_EN_MASK BIT(6)
|
||||
#define MAX77620_LDO_CFG2_OVCLMP_MASK BIT(7)
|
||||
|
||||
#define MAX77620_REG_LDO_CFG3 0x35
|
||||
#define MAX77620_LDO_BIAS_EN BIT(0)
|
||||
#define MAX77620_TRACK4_SHIFT 5
|
||||
#define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT)
|
||||
|
||||
#define MAX77620_LDO_SLEW_RATE_MASK 0x1
|
||||
|
||||
#define MAX77620_REG_GPIO0 0x36
|
||||
#define MAX77620_REG_GPIO1 0x37
|
||||
#define MAX77620_REG_GPIO2 0x38
|
||||
@@ -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,6 +246,13 @@
|
||||
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
|
||||
#define MAX77620_GPIO_OUTPUT_DISABLE 0
|
||||
#define MAX77620_GPIO_OUTPUT_ENABLE 1
|
||||
|
||||
#define MAX77620_REG_PUE_GPIO 0x3E // Gpio Pullup resistor enable.
|
||||
#define MAX77620_REG_PDE_GPIO 0x3F // Gpio Pulldown resistor enable.
|
||||
|
||||
#define MAX77620_REG_AME_GPIO 0x40 // Gpio pinmuxing. Clear bits are Standard GPIO.
|
||||
|
||||
#define MAX77620_REG_ONOFFCNFG1 0x41
|
||||
#define MAX20024_ONOFFCNFG1_CLRSE 0x18
|
||||
@@ -188,19 +260,30 @@
|
||||
#define MAX77620_ONOFFCNFG1_SLPEN BIT(2)
|
||||
#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
|
||||
#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
|
||||
#define MAX77620_ONOFFCNFG1_RSVD BIT(6)
|
||||
#define MAX77620_ONOFFCNFG1_SFT_RST BIT(7)
|
||||
|
||||
#define MAX77620_REG_ONOFFCNFG2 0x42
|
||||
#define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0)
|
||||
#define MAX77620_ONOFFCNFG2_WK_ALARM2 BIT(1)
|
||||
#define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2)
|
||||
#define MAX77620_ONOFFCNFG2_WK_MBATT BIT(3) // MBATT event generates a wakeup signal. use it in android/l4t?
|
||||
#define MAX77620_ONOFFCNFG2_WK_ACOK BIT(4)
|
||||
#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5)
|
||||
#define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6)
|
||||
#define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7)
|
||||
|
||||
/* FPS Registers */
|
||||
#define MAX77620_REG_FPS_CFG0 0x43
|
||||
#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,77 +298,39 @@
|
||||
#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_CID4 0x5C // OTP version.
|
||||
#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 BIT(1)
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2)
|
||||
#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 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 MAX20024_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_DVSSD4 0x5E
|
||||
#define MAX20024_REG_MAX_ADD 0x70
|
||||
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1)
|
||||
@@ -332,9 +377,4 @@ enum max77620_fps_src {
|
||||
MAX77620_FPS_SRC_DEF,
|
||||
};
|
||||
|
||||
enum max77620_chip_id {
|
||||
MAX77620,
|
||||
MAX20024,
|
||||
};
|
||||
|
||||
#endif /* _MFD_MAX77620_H_ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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,
|
||||
@@ -17,163 +17,323 @@
|
||||
|
||||
#include <power/max7762x.h>
|
||||
#include <power/max77620.h>
|
||||
#include <power/max77812.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#define REGULATOR_SD 0
|
||||
#define REGULATOR_SD 0
|
||||
#define REGULATOR_LDO 1
|
||||
#define REGULATOR_BC0 2
|
||||
#define REGULATOR_BC1 3
|
||||
|
||||
typedef struct _max77620_regulator_t
|
||||
typedef struct _max77620_fps_t
|
||||
{
|
||||
u8 type;
|
||||
const char *name;
|
||||
u8 reg_sd;
|
||||
|
||||
u32 mv_step;
|
||||
u32 mv_min;
|
||||
u32 mv_default;
|
||||
u32 mv_max;
|
||||
|
||||
u8 volt_addr;
|
||||
u8 cfg_addr;
|
||||
|
||||
u8 volt_mask;
|
||||
u8 enable_mask;
|
||||
u8 enable_shift;
|
||||
u8 status_mask;
|
||||
|
||||
u8 fps_addr;
|
||||
u8 fps_src;
|
||||
u8 pd_period;
|
||||
u8 pu_period;
|
||||
} max77620_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[] = {
|
||||
{ REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x80, MAX77620_REG_FPS_SD0, 1, 7, 1 },
|
||||
{ REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x40, MAX77620_REG_FPS_SD1, 0, 1, 5 },
|
||||
{ REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x20, MAX77620_REG_FPS_SD2, 1, 5, 2 },
|
||||
{ REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x10, MAX77620_REG_FPS_SD3, 0, 3, 3 },
|
||||
{ REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO0, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO1, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO2, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO3, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 1000000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO4, 0, 7, 1 },
|
||||
{ REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO5, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO6, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO7, 1, 4, 3 },
|
||||
{ REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 2800000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 }
|
||||
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
|
||||
{ "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
|
||||
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
|
||||
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
|
||||
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
|
||||
{ "ldo1", 25000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO1, 3, 7, 0 }} },
|
||||
{ "ldo2", 50000, 800000, 1800000, 3300000, REGULATOR_LDO, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO2, 3, 7, 0 }} },
|
||||
{ "ldo3", 50000, 800000, 3100000, 3100000, REGULATOR_LDO, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO3, 3, 7, 0 }} },
|
||||
{ "ldo4", 12500, 800000, 850000, 1000000, REGULATOR_LDO, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO4, 0, 7, 1 }} },
|
||||
{ "ldo5", 50000, 800000, 1800000, 1800000, REGULATOR_LDO, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO5, 3, 7, 0 }} },
|
||||
{ "ldo6", 50000, 800000, 2900000, 2900000, REGULATOR_LDO, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO6, 3, 7, 0 }} },
|
||||
{ "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} },
|
||||
{ "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} },
|
||||
|
||||
{ "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
|
||||
{ "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
|
||||
{ "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} },
|
||||
//{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} },
|
||||
//{ "max77812_RAM", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration.
|
||||
};
|
||||
|
||||
static void _max77620_set_reg(u8 reg, u8 val)
|
||||
static u8 _max77812_get_address()
|
||||
{
|
||||
static u8 max77812_i2c_addr = 0;
|
||||
|
||||
if (max77812_i2c_addr)
|
||||
return max77812_i2c_addr;
|
||||
|
||||
max77812_i2c_addr =
|
||||
!(FUSE(FUSE_RESERVED_ODM28_T210B01) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
|
||||
|
||||
return max77812_i2c_addr;
|
||||
}
|
||||
|
||||
static u8 _max7762x_get_i2c_address(u32 id)
|
||||
{
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
// Choose the correct i2c address.
|
||||
switch (reg->type)
|
||||
{
|
||||
case REGULATOR_SD:
|
||||
case REGULATOR_LDO:
|
||||
return MAX77620_I2C_ADDR;
|
||||
case REGULATOR_BC0:
|
||||
return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR);
|
||||
case REGULATOR_BC1:
|
||||
return _max77812_get_address();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void _max7762x_set_reg(u8 addr, u8 reg, u8 val)
|
||||
{
|
||||
u32 retries = 100;
|
||||
while (retries)
|
||||
{
|
||||
if (i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val))
|
||||
if (i2c_send_byte(I2C_5, addr, reg, val))
|
||||
break;
|
||||
usleep(100);
|
||||
|
||||
usleep(50);
|
||||
retries--;
|
||||
}
|
||||
}
|
||||
|
||||
int max77620_regulator_get_status(u32 id)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
if (id > REGULATOR_LDO8)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
// SD power OK status.
|
||||
if (reg->type == REGULATOR_SD)
|
||||
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1;
|
||||
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & 8) ? 1 : 0;
|
||||
{
|
||||
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_MAX)
|
||||
if (id > REGULATOR_LDO8)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
_max77620_set_reg(reg->fps_addr,
|
||||
(reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period));
|
||||
// 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 max77620_regulator_set_voltage(u32 id, u32 mv)
|
||||
int max7762x_regulator_set_voltage(u32 id, u32 mv)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
if (mv < reg->mv_min || mv > reg->mv_max)
|
||||
if (mv < reg->uv_min || mv > reg->uv_max)
|
||||
return 0;
|
||||
|
||||
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
||||
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr);
|
||||
u8 addr = _max7762x_get_i2c_address(id);
|
||||
|
||||
// Calculate voltage multiplier.
|
||||
u32 mult = (mv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step;
|
||||
u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr);
|
||||
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
|
||||
_max77620_set_reg(reg->volt_addr, val);
|
||||
|
||||
// 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 max77620_regulator_enable(u32 id, int enable)
|
||||
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];
|
||||
|
||||
u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr;
|
||||
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, addr);
|
||||
// Choose the correct i2c and register addresses and mask/shift for each type.
|
||||
switch (reg->type)
|
||||
{
|
||||
case REGULATOR_SD:
|
||||
reg_addr = reg->cfg_addr;
|
||||
enable_val = MAX77620_POWER_MODE_NORMAL;
|
||||
enable_mask = MAX77620_SD_POWER_MODE_MASK;
|
||||
enable_shift = MAX77620_SD_POWER_MODE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_LDO:
|
||||
reg_addr = reg->volt_addr;
|
||||
enable_val = MAX77620_POWER_MODE_NORMAL;
|
||||
enable_mask = MAX77620_LDO_POWER_MODE_MASK;
|
||||
enable_shift = MAX77620_LDO_POWER_MODE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_BC0:
|
||||
reg_addr = reg->volt_addr;
|
||||
enable_val = MAX77621_VOUT_ENABLE;
|
||||
enable_mask = MAX77621_DVC_DVS_ENABLE_MASK;
|
||||
enable_shift = MAX77621_DVC_DVS_ENABLE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_BC1:
|
||||
reg_addr = reg->cfg_addr;
|
||||
enable_val = MAX77812_EN_CTRL_ENABLE;
|
||||
enable_mask = reg->enable.mask;
|
||||
enable_shift = reg->enable.shift;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 addr = _max7762x_get_i2c_address(id);
|
||||
|
||||
// Read and enable/disable.
|
||||
u8 val = i2c_recv_byte(I2C_5, addr, reg_addr);
|
||||
val &= ~enable_mask;
|
||||
|
||||
if (enable)
|
||||
val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask);
|
||||
else
|
||||
val &= ~reg->enable_mask;
|
||||
_max77620_set_reg(addr, val);
|
||||
val |= (enable_val << enable_shift);
|
||||
|
||||
// Set enable.
|
||||
_max7762x_set_reg(addr, reg_addr, val);
|
||||
|
||||
// Wait for enable/disable ramp delay.
|
||||
usleep(1000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// LDO only.
|
||||
int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags)
|
||||
void max77620_config_gpio(u32 gpio_id, bool enable)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
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 (mv < reg->mv_min || mv > reg->mv_max)
|
||||
return 0;
|
||||
if (reg->type != REGULATOR_BC0)
|
||||
return;
|
||||
|
||||
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
||||
u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask);
|
||||
_max77620_set_reg(reg->volt_addr, val);
|
||||
usleep(1000);
|
||||
u8 addr = _max7762x_get_i2c_address(id);
|
||||
|
||||
return 1;
|
||||
if (por)
|
||||
{
|
||||
// Set voltage and disable power before changing the inductor.
|
||||
max7762x_regulator_set_voltage(id, 1000000);
|
||||
max7762x_regulator_enable(id, false);
|
||||
|
||||
// Configure to default.
|
||||
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_por);
|
||||
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_por);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_hos);
|
||||
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_hos);
|
||||
}
|
||||
}
|
||||
|
||||
void max77620_config_default()
|
||||
{
|
||||
for (u32 i = 1; i <= REGULATOR_MAX; i++)
|
||||
// Check if Erista OTP.
|
||||
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4) != 0x35)
|
||||
return;
|
||||
|
||||
// Set default voltages and enable regulators.
|
||||
for (u32 i = 1; i <= REGULATOR_LDO8; i++)
|
||||
{
|
||||
i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4);
|
||||
max77620_regulator_config_fps(i);
|
||||
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
|
||||
if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE)
|
||||
max77620_regulator_enable(i, 1);
|
||||
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);
|
||||
}
|
||||
_max77620_set_reg(MAX77620_REG_SD_CFG2, 4);
|
||||
|
||||
// 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)
|
||||
{
|
||||
_max77620_set_reg(MAX77620_REG_CNFGGLBL1,
|
||||
MAX77620_CNFGGLBL1_LBDAC_EN | (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) |
|
||||
MAX77620_CNFGGLBL1_LBHYST_200 | MAX77620_CNFGGLBL1_LBDAC_2800);
|
||||
_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);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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,
|
||||
@@ -32,11 +32,11 @@
|
||||
* 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 |
|
||||
* 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
|
||||
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 |
|
||||
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 |
|
||||
* 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)
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -45,10 +45,10 @@
|
||||
*/
|
||||
|
||||
/*! MAX77620 partitions. */
|
||||
#define REGULATOR_SD0 0
|
||||
#define REGULATOR_SD1 1
|
||||
#define REGULATOR_SD2 2
|
||||
#define REGULATOR_SD3 3
|
||||
#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
|
||||
@@ -58,26 +58,40 @@
|
||||
#define REGULATOR_LDO6 10
|
||||
#define REGULATOR_LDO7 11
|
||||
#define REGULATOR_LDO8 12
|
||||
#define REGULATOR_MAX 12
|
||||
#define REGULATOR_CPU0 13
|
||||
#define REGULATOR_GPU0 14
|
||||
#define REGULATOR_CPU1 15
|
||||
//#define REGULATOR_GPU1 16
|
||||
//#define REGULATOR_GPU1 17
|
||||
#define REGULATOR_MAX 15
|
||||
|
||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||
|
||||
#define MAX77621_VOUT_REG 0
|
||||
#define MAX77621_VOUT_DVS_REG 1
|
||||
#define MAX77621_CONTROL1_REG 2
|
||||
#define MAX77621_CONTROL2_REG 3
|
||||
|
||||
/* MAX77621_VOUT */
|
||||
#define MAX77621_VOUT_ENABLE BIT(7)
|
||||
#define MAX77621_VOUT_MASK 0x7F
|
||||
#define MAX77621_VOUT_0_95V 0x37
|
||||
#define MAX77621_VOUT_1_09V 0x4F
|
||||
#define MAX77621_VOUT_REG 0x00
|
||||
#define MAX77621_VOUT_DVS_REG 0x01
|
||||
#define MAX77621_CONTROL1_REG 0x02
|
||||
#define MAX77621_CONTROL2_REG 0x03
|
||||
#define MAX77621_CHIPID1_REG 0x04
|
||||
#define MAX77621_CHIPID2_REG 0x05
|
||||
|
||||
/* MAX77621_VOUT_DVC_DVS */
|
||||
#define MAX77621_DVS_VOUT_MASK 0x7F
|
||||
#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)
|
||||
@@ -85,34 +99,50 @@
|
||||
#define MAX77621_FPWM_EN_M BIT(6)
|
||||
#define MAX77621_SNS_ENABLE BIT(7)
|
||||
|
||||
#define MAX77621_RAMP_12mV_PER_US 0x0
|
||||
#define MAX77621_RAMP_25mV_PER_US 0x1
|
||||
#define MAX77621_RAMP_50mV_PER_US 0x2
|
||||
#define MAX77621_RAMP_200mV_PER_US 0x3
|
||||
#define MAX77621_RAMP_MASK 0x3
|
||||
|
||||
/* MAX77621_CONTROL2 */
|
||||
#define MAX77621_FT_ENABLE BIT(4)
|
||||
#define MAX77621_DISCH_ENBABLE BIT(5)
|
||||
#define MAX77621_WDTMR_ENABLE BIT(6)
|
||||
#define MAX77621_T_JUNCTION_120 BIT(7)
|
||||
#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_DISABLE 0xC
|
||||
#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0
|
||||
#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4
|
||||
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8
|
||||
#define MAX77621_CKKADV_TRIP_150mV_PER_US BIT(2)
|
||||
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS BIT(3)
|
||||
#define MAX77621_CKKADV_TRIP_DISABLE (BIT(2) | BIT(3))
|
||||
#define MAX77621_CKKADV_TRIP_MASK (BIT(2) | BIT(3))
|
||||
|
||||
#define MAX77621_INDUCTOR_MIN_30_PER 0x0
|
||||
#define MAX77621_INDUCTOR_NOMINAL 0x1
|
||||
#define MAX77621_INDUCTOR_PLUS_30_PER 0x2
|
||||
#define MAX77621_INDUCTOR_PLUS_60_PER 0x3
|
||||
#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)
|
||||
|
||||
int max77620_regulator_get_status(u32 id);
|
||||
int max77620_regulator_config_fps(u32 id);
|
||||
int max77620_regulator_set_voltage(u32 id, u32 mv);
|
||||
int max77620_regulator_enable(u32 id, int enable);
|
||||
int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags);
|
||||
#define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US)
|
||||
#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \
|
||||
MAX77621_NFSR_ENABLE | \
|
||||
MAX77621_SNS_ENABLE | \
|
||||
MAX77621_RAMP_12mV_PER_US)
|
||||
#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \
|
||||
MAX77621_FT_ENABLE | \
|
||||
MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | \
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | \
|
||||
MAX77621_INDUCTOR_NOMINAL)
|
||||
#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \
|
||||
MAX77621_WDTMR_ENABLE | \
|
||||
MAX77621_CKKADV_TRIP_75mV_PER_US | \
|
||||
MAX77621_INDUCTOR_NOMINAL)
|
||||
|
||||
#define MAX77621_CTRL_HOS_CFG 0
|
||||
#define MAX77621_CTRL_POR_CFG 1
|
||||
|
||||
int max77620_regulator_get_status(u32 id);
|
||||
int max77620_regulator_config_fps(u32 id);
|
||||
int max7762x_regulator_set_voltage(u32 id, u32 mv);
|
||||
int max7762x_regulator_enable(u32 id, bool enable);
|
||||
void max77620_config_gpio(u32 id, bool enable);
|
||||
void max77620_config_default();
|
||||
void max77620_low_battery_monitor_config(bool enable);
|
||||
|
||||
void max77621_config_default(u32 id, bool por);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#ifndef _MAX77812_H_
|
||||
#define _MAX77812_H_
|
||||
|
||||
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31
|
||||
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33
|
||||
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // 2 Outputs: 3-phase M1 + 1-phase M4.
|
||||
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4.
|
||||
|
||||
#define MAX77812_REG_RSET 0x00
|
||||
#define MAX77812_REG_INT_SRC 0x01
|
||||
@@ -27,7 +27,15 @@
|
||||
#define MAX77812_REG_TOPSYS_INT_M 0x04
|
||||
#define MAX77812_REG_TOPSYS_STAT 0x05
|
||||
#define MAX77812_REG_EN_CTRL 0x06
|
||||
#define MAX77812_EN_CTRL_EN_M4 BIT(6)
|
||||
#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
|
||||
@@ -46,11 +54,10 @@
|
||||
#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
|
||||
#define MAX77812_REG_M1_VOUT 0x23 // GPU.
|
||||
#define MAX77812_REG_M2_VOUT 0x24
|
||||
#define MAX77812_REG_M3_VOUT 0x25
|
||||
#define MAX77812_REG_M4_VOUT 0x26
|
||||
#define MAX77812_M4_VOUT_0_80V 0x6E
|
||||
#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
|
||||
@@ -66,6 +73,8 @@
|
||||
#define MAX77812_REG_GLB_CFG1 0x33
|
||||
#define MAX77812_REG_GLB_CFG2 0x34
|
||||
#define MAX77812_REG_GLB_CFG3 0x35
|
||||
|
||||
/*! Protected area and settings only for MAX77812_REG_VERSION 4 */
|
||||
#define MAX77812_REG_GLB_CFG4 0x36
|
||||
#define MAX77812_REG_GLB_CFG5 0x37
|
||||
#define MAX77812_REG_GLB_CFG6 0x38
|
||||
@@ -91,10 +100,6 @@
|
||||
#define MAX77812_ES2_VERSION 0x04
|
||||
#define MAX77812_QS_VERSION 0x05
|
||||
|
||||
#define MAX77812_VOUT_MASK 0xFF
|
||||
#define MAX77812_VOUT_N_VOLTAGE 0xFF
|
||||
#define MAX77812_VOUT_VMIN 250000
|
||||
#define MAX77812_VOUT_VMAX 1525000
|
||||
#define MAX77812_VOUT_STEP 5000
|
||||
#define MAX77812_BUCK_VOLT_MASK 0xFF
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* 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,
|
||||
@@ -14,63 +14,112 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
static u8 reg_5v_dev = 0;
|
||||
static bool usb_src = false;
|
||||
|
||||
void regulator_enable_5v(u8 dev)
|
||||
void regulator_5v_enable(u8 dev)
|
||||
{
|
||||
// The power supply selection from battery or USB is automatic.
|
||||
if (!reg_5v_dev)
|
||||
{
|
||||
// Fan and Rail power from internal 5V regulator (battery).
|
||||
// Fan and Rail power from battery 5V regulator.
|
||||
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1;
|
||||
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
|
||||
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
|
||||
|
||||
// Fan and Rail power from USB 5V VDD.
|
||||
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
|
||||
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE);
|
||||
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_HIGH);
|
||||
// Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula.
|
||||
u32 hw_type = fuse_read_hw_type();
|
||||
if (hw_type == FUSE_NX_HW_TYPE_ICOSA ||
|
||||
hw_type == FUSE_NX_HW_TYPE_IOWA)
|
||||
{
|
||||
// Fan and Rail power from USB 5V VBUS.
|
||||
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
|
||||
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE);
|
||||
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
|
||||
}
|
||||
|
||||
// Make sure GPIO power is enabled.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN;
|
||||
// Override power detect for GPIO AO IO rails.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN;
|
||||
// Enable GPIO AO IO rail for T210.
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||
{
|
||||
// Make sure GPIO power is enabled.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN;
|
||||
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
|
||||
|
||||
// Override power detect for GPIO AO IO rails.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
}
|
||||
usb_src = false;
|
||||
}
|
||||
reg_5v_dev |= dev;
|
||||
}
|
||||
|
||||
void regulator_disable_5v(u8 dev)
|
||||
void regulator_5v_disable(u8 dev)
|
||||
{
|
||||
reg_5v_dev &= ~dev;
|
||||
|
||||
if (!reg_5v_dev)
|
||||
{
|
||||
// Rail power from internal 5V regulator (battery).
|
||||
// Rail power from battery 5V regulator.
|
||||
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
|
||||
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE);
|
||||
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO);
|
||||
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE;
|
||||
|
||||
// Rail power from USB 5V VDD.
|
||||
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
|
||||
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
|
||||
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO);
|
||||
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE;
|
||||
// Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula.
|
||||
u32 hw_type = fuse_read_hw_type();
|
||||
if (hw_type == FUSE_NX_HW_TYPE_ICOSA ||
|
||||
hw_type == FUSE_NX_HW_TYPE_IOWA)
|
||||
{
|
||||
// Rail power from USB 5V VBUS.
|
||||
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
|
||||
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
|
||||
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO);
|
||||
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE;
|
||||
usb_src = false;
|
||||
|
||||
}
|
||||
|
||||
// GPIO AO IO rails.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN;
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||
{
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool regulator_get_5v_dev_enabled(u8 dev)
|
||||
bool regulator_5v_get_dev_enabled(u8 dev)
|
||||
{
|
||||
return (reg_5v_dev & dev);
|
||||
}
|
||||
|
||||
void regulator_5v_usb_src_enable(bool enable)
|
||||
{
|
||||
// Only for Icosa/Iowa. Skip on Hoag/Aula.
|
||||
u32 hw_type = fuse_read_hw_type();
|
||||
if (hw_type != FUSE_NX_HW_TYPE_ICOSA &&
|
||||
hw_type != FUSE_NX_HW_TYPE_IOWA)
|
||||
return;
|
||||
|
||||
if (enable && !usb_src)
|
||||
{
|
||||
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_HIGH);
|
||||
usb_src = true;
|
||||
}
|
||||
else if (!enable && usb_src)
|
||||
{
|
||||
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
|
||||
usb_src = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,9 @@ enum
|
||||
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
|
||||
277
bdk/sec/se.c
277
bdk/sec/se.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -57,17 +57,17 @@ static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size)
|
||||
|
||||
static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
|
||||
{
|
||||
SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src;
|
||||
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst;
|
||||
SE(SE_IN_LL_ADDR_REG) = (u32)src;
|
||||
SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
|
||||
}
|
||||
|
||||
static int _se_wait()
|
||||
{
|
||||
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET)))
|
||||
while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE))
|
||||
;
|
||||
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) ||
|
||||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN ||
|
||||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR)
|
||||
if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
|
||||
(SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
|
||||
SE(SE_ERR_STATUS_REG) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -92,12 +92,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
|
||||
|
||||
_se_ll_set(ll_dst, ll_src);
|
||||
|
||||
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0);
|
||||
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
|
||||
SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
|
||||
SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
|
||||
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
|
||||
SE(SE_OPERATION_REG) = op;
|
||||
|
||||
if (is_oneshot)
|
||||
{
|
||||
@@ -146,13 +146,13 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
||||
if (!src || !dst)
|
||||
return 0;
|
||||
|
||||
u8 *block = (u8 *)malloc(0x10);
|
||||
memset(block, 0, 0x10);
|
||||
u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
|
||||
memset(block, 0, SE_AES_BLOCK_SIZE);
|
||||
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||
|
||||
memcpy(block, src, src_size);
|
||||
int res = _se_execute_oneshot(op, block, 0x10, block, 0x10);
|
||||
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
|
||||
memcpy(dst, block, dst_size);
|
||||
|
||||
free(block);
|
||||
@@ -161,68 +161,68 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
||||
|
||||
static void _se_aes_ctr_set(void *ctr)
|
||||
{
|
||||
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
|
||||
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE);
|
||||
u32 data[SE_AES_IV_SIZE / 4];
|
||||
memcpy(data, ctr, SE_AES_IV_SIZE);
|
||||
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i];
|
||||
for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
|
||||
SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
|
||||
}
|
||||
|
||||
void se_rsa_acc_ctrl(u32 rs, u32 flags)
|
||||
{
|
||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG)
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) =
|
||||
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |
|
||||
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG);
|
||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG)
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs);
|
||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
|
||||
(((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
|
||||
SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
|
||||
if (flags & SE_RSA_KEY_LOCK_FLAG)
|
||||
SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
|
||||
}
|
||||
|
||||
void se_key_acc_ctrl(u32 ks, u32 flags)
|
||||
{
|
||||
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
|
||||
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags;
|
||||
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG)
|
||||
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks);
|
||||
SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
|
||||
if (flags & SE_KEY_LOCK_FLAG)
|
||||
SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks);
|
||||
}
|
||||
|
||||
u32 se_key_acc_ctrl_get(u32 ks)
|
||||
{
|
||||
return SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks);
|
||||
return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
|
||||
}
|
||||
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size)
|
||||
{
|
||||
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
|
||||
u32 data[SE_AES_MAX_KEY_SIZE / 4];
|
||||
memcpy(data, key, size);
|
||||
|
||||
for (u32 i = 0; i < (size / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_iv_set(u32 ks, void *iv)
|
||||
{
|
||||
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
|
||||
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE);
|
||||
u32 data[SE_AES_IV_SIZE / 4];
|
||||
memcpy(data, iv, SE_AES_IV_SIZE);
|
||||
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_key_get(u32 ks, void *key, u32 size)
|
||||
{
|
||||
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
|
||||
u32 data[SE_AES_MAX_KEY_SIZE / 4];
|
||||
|
||||
for (u32 i = 0; i < (size / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET);
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||
data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
|
||||
}
|
||||
|
||||
memcpy(key, data, size);
|
||||
@@ -230,78 +230,78 @@ void se_aes_key_get(u32 ks, void *key, u32 size)
|
||||
|
||||
void se_aes_key_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++)
|
||||
for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_iv_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
|
||||
|
||||
return _se_execute_oneshot(OP_START, NULL, 0, input, 0x10);
|
||||
return _se_execute_oneshot(SE_OP_START, NULL, 0, input, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
}
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
}
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
|
||||
{
|
||||
return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10);
|
||||
return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
||||
{
|
||||
SE(SE_SPARE_0_REG_OFFSET) = 1;
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
|
||||
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1);
|
||||
SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
|
||||
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
|
||||
_se_aes_ctr_set(ctr);
|
||||
|
||||
u32 src_size_aligned = src_size & 0xFFFFFFF0;
|
||||
@@ -309,13 +309,13 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
|
||||
|
||||
if (src_size_aligned)
|
||||
{
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned))
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||
if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (src_size - src_size_aligned && src_size_aligned < dst_size)
|
||||
return _se_execute_one_block(OP_START, dst + src_size_aligned,
|
||||
return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
|
||||
MIN(src_size_delta, dst_size - src_size_aligned),
|
||||
src + src_size_aligned, src_size_delta);
|
||||
|
||||
@@ -325,31 +325,31 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
|
||||
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
|
||||
{
|
||||
int res = 0;
|
||||
u8 *tweak = (u8 *)malloc(0x10);
|
||||
u8 *tweak = (u8 *)malloc(SE_AES_BLOCK_SIZE);
|
||||
u8 *pdst = (u8 *)dst;
|
||||
u8 *psrc = (u8 *)src;
|
||||
|
||||
//Generate tweak.
|
||||
// Generate tweak.
|
||||
for (int i = 0xF; i >= 0; i--)
|
||||
{
|
||||
tweak[i] = sec & 0xFF;
|
||||
sec >>= 8;
|
||||
}
|
||||
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
|
||||
if (!se_aes_crypt_block_ecb(ks1, ENCRYPT, tweak, tweak))
|
||||
goto out;
|
||||
|
||||
//We are assuming a 0x10-aligned sector size in this implementation.
|
||||
for (u32 i = 0; i < secsize / 0x10; i++)
|
||||
// We are assuming a 0x10-aligned sector size in this implementation.
|
||||
for (u32 i = 0; i < secsize / SE_AES_BLOCK_SIZE; i++)
|
||||
{
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
|
||||
pdst[j] = psrc[j] ^ tweak[j];
|
||||
if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst))
|
||||
goto out;
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
|
||||
pdst[j] = pdst[j] ^ tweak[j];
|
||||
_gf256_mul_x(tweak);
|
||||
psrc += 0x10;
|
||||
pdst += 0x10;
|
||||
psrc += SE_AES_BLOCK_SIZE;
|
||||
pdst += SE_AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
res = 1;
|
||||
@@ -374,62 +374,62 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u
|
||||
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
|
||||
{
|
||||
int res;
|
||||
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
|
||||
u32 hash32[SE_SHA_256_SIZE / 4];
|
||||
|
||||
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
|
||||
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
|
||||
return 0;
|
||||
|
||||
// Setup config for SHA256.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_SHA_CONFIG_REG_OFFSET) = sha_cfg;
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_SHA_CONFIG_REG) = sha_cfg;
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||
|
||||
// Set total size to current buffer size if empty.
|
||||
if (!total_size)
|
||||
total_size = src_size;
|
||||
|
||||
// Set total size: BITS(src_size), up to 2 EB.
|
||||
SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
|
||||
|
||||
// Set size left to hash.
|
||||
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
|
||||
|
||||
// If we hash in chunks, copy over the intermediate.
|
||||
if (sha_cfg == SHA_CONTINUE && msg_left)
|
||||
{
|
||||
// Restore message left to process.
|
||||
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0];
|
||||
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1];
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
|
||||
|
||||
// Restore hash reg.
|
||||
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]);
|
||||
memcpy(hash32, hash, SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
|
||||
}
|
||||
|
||||
// Trigger the operation.
|
||||
res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot);
|
||||
res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
|
||||
|
||||
if (is_oneshot)
|
||||
{
|
||||
// Backup message left.
|
||||
if (msg_left)
|
||||
{
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
|
||||
}
|
||||
|
||||
// Copy output hash.
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
||||
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
|
||||
memcpy(hash, hash32, SE_SHA_256_SIZE);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -442,20 +442,20 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
|
||||
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||
{
|
||||
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
|
||||
u32 hash32[SE_SHA_256_SIZE / 4];
|
||||
int res = _se_execute_finalize();
|
||||
|
||||
// Backup message left.
|
||||
if (msg_left)
|
||||
{
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
|
||||
}
|
||||
|
||||
// Copy output hash.
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
||||
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
|
||||
memcpy(hash, hash32, SE_SHA_256_SIZE);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -463,18 +463,17 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||
int se_gen_prng128(void *dst)
|
||||
{
|
||||
// Setup config for X931 PRNG.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL);
|
||||
//SE(SE_RNG_SRC_CONFIG_REG) =
|
||||
// SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) | SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG) = 1;
|
||||
|
||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL);
|
||||
//SE(SE_RNG_SRC_CONFIG_REG_OFFSET) =
|
||||
// SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 1;
|
||||
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (16 >> 4) - 1;
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (16 >> 4) - 1;
|
||||
|
||||
// Trigger the operation.
|
||||
return _se_execute_oneshot(OP_START, dst, 16, NULL, 0);
|
||||
return _se_execute_oneshot(SE_OP_START, dst, 16, NULL, 0);
|
||||
}
|
||||
|
||||
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
@@ -482,43 +481,43 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
|
||||
|
||||
// Set Secure Random Key.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_START, NULL, 0, NULL, 0);
|
||||
_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
|
||||
|
||||
// Save AES keys.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
|
||||
for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++)
|
||||
for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++)
|
||||
{
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3);
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
|
||||
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
||||
memcpy(keys + i * keysize, aligned_buf, 0x10);
|
||||
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
|
||||
memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
|
||||
|
||||
if (keysize > 0x10)
|
||||
if (keysize > SE_KEY_128_SIZE)
|
||||
{
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7);
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
|
||||
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
||||
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10);
|
||||
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
|
||||
memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
// Save SRK to PMC secure scratches.
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK);
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// End context save.
|
||||
SE(SE_CONFIG_REG_OFFSET) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
SE(SE_CONFIG_REG) = 0;
|
||||
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// Get SRK.
|
||||
u32 srk[4];
|
||||
@@ -529,7 +528,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
|
||||
// Decrypt context.
|
||||
se_aes_key_clear(3);
|
||||
se_aes_key_set(3, srk, 0x10);
|
||||
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize);
|
||||
se_aes_key_set(3, srk, SE_KEY_128_SIZE);
|
||||
se_aes_crypt_cbc(3, DECRYPT, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
|
||||
se_aes_key_clear(3);
|
||||
}
|
||||
|
||||
47
bdk/sec/se.h
47
bdk/sec/se.h
@@ -1,18 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SE_H_
|
||||
#define _SE_H_
|
||||
@@ -28,14 +29,14 @@ void se_aes_iv_set(u32 ks, void *iv);
|
||||
void se_aes_key_get(u32 ks, void *key, u32 size);
|
||||
void se_aes_key_clear(u32 ks);
|
||||
void se_aes_iv_clear(u32 ks);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
||||
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
||||
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
|
||||
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
|
||||
int se_gen_prng128(void *dst);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
||||
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
||||
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
|
||||
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
|
||||
int se_gen_prng128(void *dst);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,400 +1,326 @@
|
||||
/*
|
||||
* Driver for Tegra Security Engine
|
||||
*
|
||||
* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_TEGRA_SE_H
|
||||
#define _CRYPTO_TEGRA_SE_H
|
||||
#ifndef _SE_T210_H
|
||||
#define _SE_T210_H
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
#define TEGRA_SE_CRA_PRIORITY 300
|
||||
#define TEGRA_SE_COMPOSITE_PRIORITY 400
|
||||
#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50
|
||||
#define SE_MAX_SRC_SG_COUNT 50
|
||||
#define SE_MAX_DST_SG_COUNT 50
|
||||
#define SE_CRYPTO_QUEUE_LENGTH 50
|
||||
#define SE_MAX_SRC_SG_COUNT 50
|
||||
#define SE_MAX_DST_SG_COUNT 50
|
||||
|
||||
#define TEGRA_SE_KEYSLOT_COUNT 16
|
||||
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
|
||||
#define SE_AES_KEYSLOT_COUNT 16
|
||||
#define SE_RSA_KEYSLOT_COUNT 2
|
||||
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
|
||||
|
||||
#define SE_AES_BLOCK_SIZE 16
|
||||
#define SE_AES_IV_SIZE 16
|
||||
#define SE_AES_MIN_KEY_SIZE 16
|
||||
#define SE_AES_MAX_KEY_SIZE 32
|
||||
#define SE_KEY_128_SIZE 16
|
||||
#define SE_KEY_192_SIZE 24
|
||||
#define SE_KEY_256_SIZE 32
|
||||
#define SE_SHA_192_SIZE 24
|
||||
#define SE_SHA_256_SIZE 32
|
||||
#define SE_SHA_384_SIZE 48
|
||||
#define SE_SHA_512_SIZE 64
|
||||
#define SE_RNG_IV_SIZE 16
|
||||
#define SE_RNG_DT_SIZE 16
|
||||
#define SE_RNG_KEY_SIZE 16
|
||||
#define SE_RNG_SEED_SIZE (SE_RNG_IV_SIZE + SE_RNG_KEY_SIZE + SE_RNG_DT_SIZE)
|
||||
|
||||
#define SE_AES_CMAC_DIGEST_SIZE 16
|
||||
#define SE_RSA512_DIGEST_SIZE 64
|
||||
#define SE_RSA1024_DIGEST_SIZE 128
|
||||
#define SE_RSA1536_DIGEST_SIZE 192
|
||||
#define SE_RSA2048_DIGEST_SIZE 256
|
||||
|
||||
#define DECRYPT 0
|
||||
#define ENCRYPT 1
|
||||
|
||||
/* SE register definitions */
|
||||
#define SE_SECURITY_0 0x000
|
||||
#define SE_KEY_SCHED_READ_SHIFT 3
|
||||
#define SE_SE_SECURITY_REG 0x000
|
||||
#define SE_HARD_SETTING BIT(0)
|
||||
#define SE_ENG_DIS BIT(1)
|
||||
#define SE_PERKEY_SETTING BIT(2)
|
||||
#define SE_SOFT_SETTING BIT(16)
|
||||
|
||||
#define SE_TZRAM_SECURITY_0 0x004
|
||||
#define SE_TZRAM_SECURITY_REG 0x004
|
||||
#define SE_TZRAM_HARD_SETTING BIT(0)
|
||||
#define SE_TZRAM_ENG_DIS BIT(1)
|
||||
|
||||
#define SE_CONFIG_REG_OFFSET 0x014
|
||||
#define SE_CONFIG_ENC_ALG_SHIFT 12
|
||||
#define SE_CONFIG_DEC_ALG_SHIFT 8
|
||||
#define ALG_AES_ENC 1
|
||||
#define ALG_RNG 2
|
||||
#define ALG_SHA 3
|
||||
#define ALG_RSA 4
|
||||
#define ALG_NOP 0
|
||||
#define ALG_AES_DEC 1
|
||||
#define SE_CONFIG_ENC_ALG(x) ((x) << SE_CONFIG_ENC_ALG_SHIFT)
|
||||
#define SE_CONFIG_DEC_ALG(x) ((x) << SE_CONFIG_DEC_ALG_SHIFT)
|
||||
#define SE_CONFIG_DST_SHIFT 2
|
||||
#define DST_MEMORY 0
|
||||
#define DST_HASHREG 1
|
||||
#define DST_KEYTAB 2
|
||||
#define DST_SRK 3
|
||||
#define DST_RSAREG 4
|
||||
#define SE_CONFIG_DST(x) ((x) << SE_CONFIG_DST_SHIFT)
|
||||
#define SE_CONFIG_ENC_MODE_SHIFT 24
|
||||
#define SE_CONFIG_DEC_MODE_SHIFT 16
|
||||
#define MODE_KEY128 0
|
||||
#define MODE_KEY192 1
|
||||
#define MODE_KEY256 2
|
||||
#define MODE_SHA1 0
|
||||
#define MODE_SHA224 4
|
||||
#define MODE_SHA256 5
|
||||
#define MODE_SHA384 6
|
||||
#define MODE_SHA512 7
|
||||
#define SE_CONFIG_ENC_MODE(x) ((x) << SE_CONFIG_ENC_MODE_SHIFT)
|
||||
#define SE_CONFIG_DEC_MODE(x) ((x) << SE_CONFIG_DEC_MODE_SHIFT)
|
||||
#define SE_OPERATION_REG 0x008
|
||||
#define SE_OP_ABORT 0
|
||||
#define SE_OP_START 1
|
||||
#define SE_OP_RESTART_OUT 2
|
||||
#define SE_OP_CTX_SAVE 3
|
||||
#define SE_OP_RESTART_IN 4
|
||||
|
||||
#define SE_RNG_CONFIG_REG_OFFSET 0x340
|
||||
#define RNG_MODE_SHIFT 0
|
||||
#define RNG_MODE_NORMAL 0
|
||||
#define RNG_MODE_FORCE_INSTANTION 1
|
||||
#define RNG_MODE_FORCE_RESEED 2
|
||||
#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT)
|
||||
#define RNG_SRC_SHIFT 2
|
||||
#define RNG_SRC_NONE 0
|
||||
#define RNG_SRC_ENTROPY 1
|
||||
#define RNG_SRC_LFSR 2
|
||||
#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT)
|
||||
#define SE_INT_ENABLE_REG 0x00C
|
||||
#define SE_INT_STATUS_REG 0x010
|
||||
#define SE_INT_IN_LL_BUF_RD BIT(0)
|
||||
#define SE_INT_IN_DONE BIT(1)
|
||||
#define SE_INT_OUT_LL_BUF_WR BIT(2)
|
||||
#define SE_INT_OUT_DONE BIT(3)
|
||||
#define SE_INT_OP_DONE BIT(4)
|
||||
#define SE_INT_RESEED_NEEDED BIT(5)
|
||||
#define SE_INT_ERR_STAT BIT(16)
|
||||
|
||||
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344
|
||||
#define RNG_SRC_RO_ENT_SHIFT 1
|
||||
#define RNG_SRC_RO_ENT_ENABLE 1
|
||||
#define RNG_SRC_RO_ENT_DISABLE 0
|
||||
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT)
|
||||
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0
|
||||
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1
|
||||
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0
|
||||
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT)
|
||||
#define SE_CONFIG_REG 0x014
|
||||
#define DST_MEMORY 0
|
||||
#define DST_HASHREG 1
|
||||
#define DST_KEYTABLE 2
|
||||
#define DST_SRK 3
|
||||
#define DST_RSAREG 4
|
||||
#define SE_CONFIG_DST(x) ((x) << 2)
|
||||
#define ALG_NOP 0
|
||||
#define ALG_AES_DEC 1
|
||||
#define SE_CONFIG_DEC_ALG(x) ((x) << 8)
|
||||
#define ALG_NOP 0
|
||||
#define ALG_AES_ENC 1
|
||||
#define ALG_RNG 2
|
||||
#define ALG_SHA 3
|
||||
#define ALG_RSA 4
|
||||
#define SE_CONFIG_ENC_ALG(x) ((x) << 12)
|
||||
#define MODE_KEY128 0
|
||||
#define MODE_KEY192 1
|
||||
#define MODE_KEY256 2
|
||||
#define MODE_SHA1 0
|
||||
#define MODE_SHA224 4
|
||||
#define MODE_SHA256 5
|
||||
#define MODE_SHA384 6
|
||||
#define MODE_SHA512 7
|
||||
#define SE_CONFIG_DEC_MODE(x) ((x) << 16)
|
||||
#define SE_CONFIG_ENC_MODE(x) ((x) << 24)
|
||||
|
||||
#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348
|
||||
#define SE_IN_LL_ADDR_REG 0x018
|
||||
#define SE_IN_CUR_BYTE_ADDR_REG 0x01C
|
||||
#define SE_IN_CUR_LL_ID_REG 0x020
|
||||
#define SE_OUT_LL_ADDR_REG 0x024
|
||||
#define SE_OUT_CUR_BYTE_ADDR_REG 0x028
|
||||
#define SE_OUT_CUR_LL_ID_REG 0x02C
|
||||
|
||||
#define SE_KEYTABLE_REG_OFFSET 0x31c
|
||||
#define SE_KEYTABLE_SLOT_SHIFT 4
|
||||
#define SE_KEYTABLE_SLOT(x) ((x) << SE_KEYTABLE_SLOT_SHIFT)
|
||||
#define SE_KEYTABLE_QUAD_SHIFT 2
|
||||
#define QUAD_KEYS_128 0
|
||||
#define QUAD_KEYS_192 1
|
||||
#define QUAD_KEYS_256 1
|
||||
#define QUAD_ORG_IV 2
|
||||
#define QUAD_UPDTD_IV 3
|
||||
#define SE_KEYTABLE_QUAD(x) ((x) << SE_KEYTABLE_QUAD_SHIFT)
|
||||
#define SE_KEYTABLE_OP_TYPE_SHIFT 9
|
||||
#define OP_READ 0
|
||||
#define OP_WRITE 1
|
||||
#define SE_KEYTABLE_OP_TYPE(x) ((x) << SE_KEYTABLE_OP_TYPE_SHIFT)
|
||||
#define SE_KEYTABLE_TABLE_SEL_SHIFT 8
|
||||
#define TABLE_KEYIV 0
|
||||
#define TABLE_SCHEDULE 1
|
||||
#define SE_KEYTABLE_TABLE_SEL(x) ((x) << SE_KEYTABLE_TABLE_SEL_SHIFT)
|
||||
#define SE_KEYTABLE_PKT_SHIFT 0
|
||||
#define SE_KEYTABLE_PKT(x) ((x) << SE_KEYTABLE_PKT_SHIFT)
|
||||
#define SE_HASH_RESULT_REG 0x030
|
||||
#define SE_HASH_RESULT_REG_COUNT 16
|
||||
|
||||
#define SE_OP_DONE_SHIFT 4
|
||||
#define OP_DONE 1
|
||||
#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT))
|
||||
#define SE_CONTEXT_SAVE_CONFIG_REG 0x070
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define ORIGINAL_IV 2
|
||||
#define UPDATED_IV 3
|
||||
#define SE_CONTEXT_AES_WORD_QUAD(x) ((x) << 0)
|
||||
#define SE_CONTEXT_AES_KEY_INDEX(x) ((x) << 8)
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define KEYS_8_11 2
|
||||
#define KEYS_12_15 3
|
||||
#define SE_CONTEXT_RSA_WORD_QUAD(x) ((x) << 12)
|
||||
#define SLOT0_EXPONENT 0
|
||||
#define SLOT0_MODULUS 1
|
||||
#define SLOT1_EXPONENT 2
|
||||
#define SLOT1_MODULUS 3
|
||||
#define SE_CONTEXT_RSA_KEY_INDEX(x) ((x) << 16)
|
||||
#define STICKY_0_3 0
|
||||
#define STICKY_4_7 1
|
||||
#define SE_CONTEXT_STICKY_WORD_QUAD(x) ((x) << 24)
|
||||
#define STICKY_BITS 0
|
||||
#define RSA_KEYTABLE 1
|
||||
#define AES_KEYTABLE 2
|
||||
#define MEM 4
|
||||
#define SRK 6
|
||||
#define SE_CONTEXT_SRC(x) ((x) << 29)
|
||||
|
||||
#define SE_CRYPTO_LAST_BLOCK 0x080
|
||||
#define SE_CTX_SAVE_AUTO_T210B01_REG 0x074
|
||||
#define SE_CTX_SAVE_AUTO_ENABLE BIT(0)
|
||||
#define SE_CTX_SAVE_AUTO_LOCK BIT(8)
|
||||
#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
|
||||
|
||||
#define SE_CRYPTO_REG_OFFSET 0x304
|
||||
#define SE_CRYPTO_HASH_SHIFT 0
|
||||
#define HASH_DISABLE 0
|
||||
#define HASH_ENABLE 1
|
||||
#define SE_CRYPTO_HASH(x) ((x) << SE_CRYPTO_HASH_SHIFT)
|
||||
#define SE_CRYPTO_XOR_POS_SHIFT 1
|
||||
#define XOR_BYPASS 0
|
||||
#define XOR_TOP 2
|
||||
#define XOR_BOTTOM 3
|
||||
#define SE_CRYPTO_XOR_POS(x) ((x) << SE_CRYPTO_XOR_POS_SHIFT)
|
||||
#define SE_CRYPTO_INPUT_SEL_SHIFT 3
|
||||
#define INPUT_AHB 0
|
||||
#define INPUT_RANDOM 1
|
||||
#define INPUT_AESOUT 2
|
||||
#define INPUT_LNR_CTR 3
|
||||
#define SE_CRYPTO_INPUT_SEL(x) ((x) << SE_CRYPTO_INPUT_SEL_SHIFT)
|
||||
#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5
|
||||
#define VCTRAM_AHB 0
|
||||
#define VCTRAM_AESOUT 2
|
||||
#define VCTRAM_PREVAHB 3
|
||||
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
|
||||
#define SE_CRYPTO_IV_SEL_SHIFT 7
|
||||
#define IV_ORIGINAL 0
|
||||
#define IV_UPDATED 1
|
||||
#define SE_CRYPTO_IV_SEL(x) ((x) << SE_CRYPTO_IV_SEL_SHIFT)
|
||||
#define SE_CRYPTO_CORE_SEL_SHIFT 8
|
||||
#define CORE_DECRYPT 0
|
||||
#define CORE_ENCRYPT 1
|
||||
#define SE_CRYPTO_CORE_SEL(x) ((x) << SE_CRYPTO_CORE_SEL_SHIFT)
|
||||
#define SE_CRYPTO_CTR_VAL_SHIFT 11
|
||||
#define SE_CRYPTO_CTR_VAL(x) ((x) << SE_CRYPTO_CTR_VAL_SHIFT)
|
||||
#define SE_CRYPTO_KEY_INDEX_SHIFT 24
|
||||
#define SE_CRYPTO_KEY_INDEX(x) ((x) << SE_CRYPTO_KEY_INDEX_SHIFT)
|
||||
#define SE_CRYPTO_CTR_CNTN_SHIFT 11
|
||||
#define SE_CRYPTO_CTR_CNTN(x) ((x) << SE_CRYPTO_CTR_CNTN_SHIFT)
|
||||
#define SE_CRYPTO_LAST_BLOCK 0x080
|
||||
|
||||
#define SE_CRYPTO_CTR_REG_COUNT 4
|
||||
#define SE_CRYPTO_CTR_REG_OFFSET 0x308
|
||||
|
||||
#define SE_OPERATION_REG_OFFSET 0x008
|
||||
#define SE_OPERATION_SHIFT 0
|
||||
#define OP_ABORT 0
|
||||
#define OP_START 1
|
||||
#define OP_RESTART 2
|
||||
#define OP_CTX_SAVE 3
|
||||
#define OP_RESTART_IN 4
|
||||
#define SE_OPERATION(x) ((x) << SE_OPERATION_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070
|
||||
#define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define ORIG_IV 2
|
||||
#define UPD_IV 3
|
||||
#define SE_CONTEXT_SAVE_WORD_QUAD(x) ((x) << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8
|
||||
#define SE_CONTEXT_SAVE_KEY_INDEX(x) ((x) << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT 24
|
||||
#define STICKY_0_3 0
|
||||
#define STICKY_4_7 1
|
||||
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \
|
||||
((x) << SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_SRC_SHIFT 29
|
||||
#define STICKY_BITS 0
|
||||
#define KEYTABLE 2
|
||||
#define MEM 4
|
||||
#define SRK 6
|
||||
|
||||
#define RSA_KEYTABLE 1
|
||||
#define AES_KEYTABLE 2
|
||||
#define SE_CONTEXT_SAVE_SRC(x) ((x) << SE_CONTEXT_SAVE_SRC_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16
|
||||
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \
|
||||
((x) << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12
|
||||
#define SE_CONTEXT_RSA_WORD_QUAD(x) \
|
||||
((x) << SE_CONTEXT_RSA_WORD_QUAD_SHIFT)
|
||||
|
||||
#define SE_CTX_SAVE_AUTO 0x074
|
||||
#define CTX_SAVE_AUTO_ENABLE BIT(0)
|
||||
#define CTX_SAVE_AUTO_LOCK BIT(8)
|
||||
#define CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
|
||||
|
||||
#define SE_INT_ENABLE_REG_OFFSET 0x00c
|
||||
#define SE_INT_STATUS_REG_OFFSET 0x010
|
||||
#define INT_DISABLE 0
|
||||
#define INT_ENABLE 1
|
||||
#define INT_UNSET 0
|
||||
#define INT_SET 1
|
||||
#define SE_INT_OP_DONE_SHIFT 4
|
||||
#define SE_INT_OP_DONE(x) ((x) << SE_INT_OP_DONE_SHIFT)
|
||||
#define SE_INT_ERROR_SHIFT 16
|
||||
#define SE_INT_ERROR(x) ((x) << SE_INT_ERROR_SHIFT)
|
||||
|
||||
#define SE_STATUS_0 0x800
|
||||
#define SE_STATUS_0_STATE_WAIT_IN 3
|
||||
|
||||
#define SE_ERR_STATUS_0 0x804
|
||||
#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0
|
||||
|
||||
#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330
|
||||
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
|
||||
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \
|
||||
((x) << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT)
|
||||
|
||||
#define SE_KEY_INDEX_SHIFT 8
|
||||
#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) ((x) << SE_KEY_INDEX_SHIFT)
|
||||
|
||||
#define SE_IN_LL_ADDR_REG_OFFSET 0x018
|
||||
#define SE_OUT_LL_ADDR_REG_OFFSET 0x024
|
||||
|
||||
#define SE_KEYTABLE_DATA0_REG_OFFSET 0x320
|
||||
#define SE_KEYTABLE_REG_MAX_DATA 16
|
||||
|
||||
#define SE_BLOCK_COUNT_REG_OFFSET 0x318
|
||||
|
||||
#define SE_SPARE_0_REG_OFFSET 0x80c
|
||||
|
||||
#define SE_SHA_CONFIG_REG_OFFSET 0x200
|
||||
#define SE_SHA_CONFIG_REG 0x200
|
||||
#define SHA_CONTINUE 0
|
||||
#define SHA_INIT_HASH 1
|
||||
|
||||
#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204
|
||||
#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208
|
||||
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C
|
||||
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210
|
||||
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214
|
||||
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218
|
||||
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C
|
||||
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220
|
||||
#define SE_SHA_MSG_LENGTH_0_REG 0x204
|
||||
#define SE_SHA_MSG_LENGTH_1_REG 0x208
|
||||
#define SE_SHA_MSG_LENGTH_2_REG 0x20C
|
||||
#define SE_SHA_MSG_LENGTH_3_REG 0x210
|
||||
#define SE_SHA_MSG_LEFT_0_REG 0x214
|
||||
#define SE_SHA_MSG_LEFT_1_REG 0x218
|
||||
#define SE_SHA_MSG_LEFT_2_REG 0x21C
|
||||
#define SE_SHA_MSG_LEFT_3_REG 0x220
|
||||
|
||||
#define SE_HASH_RESULT_REG_COUNT 16
|
||||
#define SE_HASH_RESULT_REG_OFFSET 0x030
|
||||
#define TEGRA_SE_KEY_256_SIZE 32
|
||||
#define TEGRA_SE_KEY_192_SIZE 24
|
||||
#define TEGRA_SE_KEY_128_SIZE 16
|
||||
#define TEGRA_SE_AES_BLOCK_SIZE 16
|
||||
#define TEGRA_SE_AES_MIN_KEY_SIZE 16
|
||||
#define TEGRA_SE_AES_MAX_KEY_SIZE 32
|
||||
#define TEGRA_SE_AES_IV_SIZE 16
|
||||
#define TEGRA_SE_SHA_512_SIZE 64
|
||||
#define TEGRA_SE_SHA_384_SIZE 48
|
||||
#define TEGRA_SE_SHA_256_SIZE 32
|
||||
#define TEGRA_SE_SHA_192_SIZE 24
|
||||
#define TEGRA_SE_RNG_IV_SIZE 16
|
||||
#define TEGRA_SE_RNG_DT_SIZE 16
|
||||
#define TEGRA_SE_RNG_KEY_SIZE 16
|
||||
#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \
|
||||
TEGRA_SE_RNG_KEY_SIZE + \
|
||||
TEGRA_SE_RNG_DT_SIZE)
|
||||
#define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
|
||||
#define SE_KEY_LOCK_FLAG 0x80
|
||||
#define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
|
||||
#define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
|
||||
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
|
||||
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
|
||||
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
|
||||
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
|
||||
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
|
||||
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
||||
|
||||
#define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16
|
||||
#define TEGRA_SE_RSA512_DIGEST_SIZE 64
|
||||
#define TEGRA_SE_RSA1024_DIGEST_SIZE 128
|
||||
#define TEGRA_SE_RSA1536_DIGEST_SIZE 192
|
||||
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256
|
||||
#define SE_CRYPTO_CONFIG_REG 0x304
|
||||
#define HASH_DISABLE 0
|
||||
#define HASH_ENABLE 1
|
||||
#define SE_CRYPTO_HASH(x) ((x) << 0)
|
||||
#define XOR_BYPASS 0
|
||||
#define XOR_TOP 2
|
||||
#define XOR_BOTTOM 3
|
||||
#define SE_CRYPTO_XOR_POS(x) ((x) << 1)
|
||||
#define INPUT_MEMORY 0
|
||||
#define INPUT_RANDOM 1
|
||||
#define INPUT_AESOUT 2
|
||||
#define INPUT_LNR_CTR 3
|
||||
#define SE_CRYPTO_INPUT_SEL(x) ((x) << 3)
|
||||
#define VCTRAM_MEM 0
|
||||
#define VCTRAM_AESOUT 2
|
||||
#define VCTRAM_PREVMEM 3
|
||||
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << 5)
|
||||
#define IV_ORIGINAL 0
|
||||
#define IV_UPDATED 1
|
||||
#define SE_CRYPTO_IV_SEL(x) ((x) << 7)
|
||||
#define CORE_DECRYPT 0
|
||||
#define CORE_ENCRYPT 1
|
||||
#define SE_CRYPTO_CORE_SEL(x) ((x) << 8)
|
||||
#define SE_CRYPTO_KEYSCH_BYPASS BIT(10)
|
||||
#define SE_CRYPTO_CTR_CNTN(x) ((x) << 11)
|
||||
#define SE_CRYPTO_KEY_INDEX(x) ((x) << 24)
|
||||
#define MEMIF_AHB 0
|
||||
#define MEMIF_MCCIF 1
|
||||
#define SE_CRYPTO_MEMIF(x) ((x) << 31)
|
||||
|
||||
#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280
|
||||
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
|
||||
#define SE_CRYPTO_LINEAR_CTR_REG 0x308
|
||||
#define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
|
||||
|
||||
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284
|
||||
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
|
||||
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
|
||||
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
|
||||
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
|
||||
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
|
||||
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
||||
#define SE_CRYPTO_BLOCK_COUNT_REG 0x318
|
||||
|
||||
#define SE_KEY_READ_DISABLE_SHIFT 0
|
||||
#define SE_KEY_UPDATE_DISABLE_SHIFT 1
|
||||
#define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
|
||||
#define SE_KEYTABLE_PKT(x) ((x) << 0)
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define ORIGINAL_IV 2
|
||||
#define UPDATED_IV 3
|
||||
#define SE_KEYTABLE_QUAD(x) ((x) << 2)
|
||||
#define SE_KEYTABLE_SLOT(x) ((x) << 4)
|
||||
|
||||
#define SE_CONTEXT_BUFER_SIZE 1072
|
||||
#define SE_CONTEXT_DRBG_BUFER_SIZE 2112
|
||||
#define SE_CRYPTO_KEYTABLE_DATA_REG 0x320
|
||||
|
||||
#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0
|
||||
#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16
|
||||
#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \
|
||||
(SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE)
|
||||
#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16
|
||||
#define SE_CRYPTO_KEYTABLE_DST_REG 0x330
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define ORIGINAL_IV 2
|
||||
#define UPDATED_IV 3
|
||||
#define SE_KEYTABLE_DST_WORD_QUAD(x) ((x) << 0)
|
||||
#define SE_KEYTABLE_DST_KEY_INDEX(x) ((x) << 8)
|
||||
|
||||
#define SE_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
|
||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
|
||||
#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
|
||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \
|
||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
|
||||
#define SE_RNG_CONFIG_REG 0x340
|
||||
#define MODE_NORMAL 0
|
||||
#define MODE_FORCE_INSTANTION 1
|
||||
#define MODE_FORCE_RESEED 2
|
||||
#define SE_RNG_CONFIG_MODE(x) ((x) << 0)
|
||||
#define SRC_NONE 0
|
||||
#define SRC_ENTROPY 1
|
||||
#define SRC_LFSR 2
|
||||
#define SE_RNG_CONFIG_SRC(x) ((x) << 2)
|
||||
|
||||
#define SE_CONTEXT_SAVE_KEY_LENGTH 512
|
||||
#define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \
|
||||
SE_CONTEXT_SAVE_KEY_LENGTH)
|
||||
#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \
|
||||
SE_CONTEXT_SAVE_KEY_LENGTH)
|
||||
#define SE_RNG_SRC_CONFIG_REG 0x344
|
||||
#define RO_ENTR_LOCK_DISABLE 0
|
||||
#define RO_ENTR_LOCK_ENABLE 1
|
||||
#define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
|
||||
#define RO_ENTR_DISABLE 0
|
||||
#define RO_ENTR_ENABLE 1
|
||||
#define SE_RNG_SRC_CONFIG_ENTR_SRC(x) ((x) << 1)
|
||||
#define RO_HW_DIS_CYA_DISABLE 0
|
||||
#define RO_HW_DIS_CYA_ENABLE 1
|
||||
#define SE_RNG_SRC_CONFIG_HW_DIS_CYA(x) ((x) << 2)
|
||||
#define SE_RNG_SRC_CONFIG_ENTR_SUBSMPL(x) ((x) << 4)
|
||||
#define SE_RNG_SRC_CONFIG_ENTR_DATA_FLUSH BIT(8)
|
||||
|
||||
#define SE_CONTEXT_ORIGINAL_IV_LENGTH 256
|
||||
#define SE_RNG_RESEED_INTERVAL_REG 0x348
|
||||
|
||||
#define SE_CONTEXT_UPDATED_IV_OFFSET (SE_CONTEXT_ORIGINAL_IV_OFFSET + \
|
||||
SE_CONTEXT_ORIGINAL_IV_LENGTH)
|
||||
#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \
|
||||
SE_CONTEXT_ORIGINAL_IV_LENGTH)
|
||||
#define SE_RSA_CONFIG 0x400
|
||||
#define RSA_KEY_SLOT_ONE 0
|
||||
#define RSA_KEY_SLOT_TW0 1
|
||||
#define RSA_KEY_SLOT(x) ((x) << 24)
|
||||
|
||||
#define SE_CONTEXT_UPDATED_IV_LENGTH 256
|
||||
#define SE_RSA_KEY_SIZE_REG 0x404
|
||||
#define RSA_KEY_WIDTH_512 0
|
||||
#define RSA_KEY_WIDTH_1024 1
|
||||
#define RSA_KEY_WIDTH_1536 2
|
||||
#define RSA_KEY_WIDTH_2048 3
|
||||
|
||||
#define SE_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET (SE_CONTEXT_UPDATED_IV_OFFSET + \
|
||||
SE_CONTEXT_UPDATED_IV_LENGTH)
|
||||
#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \
|
||||
(SE11_CONTEXT_UPDATED_IV_OFFSET + \
|
||||
SE_CONTEXT_UPDATED_IV_LENGTH)
|
||||
#define SE_RSA_EXP_SIZE_REG 0x408
|
||||
|
||||
#define SE_CONTEXT_SAVE_RSA_KEYS_OFFSET SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET
|
||||
#define SE_RSA_SECURITY_PERKEY_REG 0x40C
|
||||
#define SE_RSA_KEY_LOCK_FLAG 0x80
|
||||
#define SE_RSA_KEYTABLE_ACCESS_REG 0x410
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG | SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG)
|
||||
|
||||
#define SE_CONTEXT_SAVE_RSA_KEY_LENGTH 1024
|
||||
#define SE_RSA_KEYTABLE_ADDR_REG 0x420
|
||||
#define SE_RSA_KEYTABLE_PKT(x) ((x) << 0)
|
||||
#define RSA_KEY_TYPE_EXP 0
|
||||
#define RSA_KEY_TYPE_MOD 1
|
||||
#define SE_RSA_KEYTABLE_TYPE(x) ((x) << 6)
|
||||
#define RSA_KEY_NUM(x) ((x) << 7)
|
||||
#define RSA_KEY_INPUT_MODE_REG 0
|
||||
#define RSA_KEY_INPUT_MODE_DMA 1
|
||||
#define SE_RSA_KEYTABLE_INPUT_MODE(x) ((x) << 8)
|
||||
#define RSA_KEY_READ 0
|
||||
#define RSA_KEY_WRITE 1
|
||||
#define SE_RSA_KEY_OP(x) ((x) << 10)
|
||||
|
||||
#define SE_CONTEXT_SAVE_RSA_KNOWN_PATTERN_OFFSET \
|
||||
(SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH)
|
||||
#define SE_RSA_KEYTABLE_DATA_REG 0x424
|
||||
|
||||
#define SE_CONTEXT_KNOWN_PATTERN_SIZE 16
|
||||
#define SE_RSA_OUTPUT_REG 0x428
|
||||
#define SE_RSA_OUTPUT_REG_COUNT 64
|
||||
|
||||
#define TEGRA_SE_RSA_KEYSLOT_COUNT 2
|
||||
#define SE_STATUS_REG 0x800
|
||||
#define SE_STATUS_STATE_IDLE 0
|
||||
#define SE_STATUS_STATE_BUSY 1
|
||||
#define SE_STATUS_STATE_WAIT_OUT 2
|
||||
#define SE_STATUS_STATE_WAIT_IN 3
|
||||
#define SE_STATUS_STATE_MASK 3
|
||||
|
||||
#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
|
||||
#define SE_ERR_STATUS_REG 0x804
|
||||
#define SE_ERR_STATUS_SE_NS_ACCESS BIT(0)
|
||||
#define SE_ERR_STATUS_BUSY_REG_WR BIT(1)
|
||||
#define SE_ERR_STATUS_DST BIT(2)
|
||||
#define SE_ERR_STATUS_SRK_USAGE_LIMIT BIT(3)
|
||||
#define SE_ERR_STATUS_TZRAM_NS_ACCESS BIT(24)
|
||||
#define SE_ERR_STATUS_TZRAM_ADDRESS BIT(25)
|
||||
|
||||
#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT BIT(2)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F
|
||||
#define SE_MISC_REG 0x808
|
||||
#define SE_ENTROPY_NEXT_192BIT BIT(0)
|
||||
#define SE_ENTROPY_VN_BYPASS BIT(1)
|
||||
#define SE_CLK_OVR_ON BIT(2)
|
||||
|
||||
#define SE_RSA_KEYTABLE_ADDR 0x420
|
||||
#define SE_RSA_KEYTABLE_DATA 0x424
|
||||
#define SE_RSA_OUTPUT 0x428
|
||||
#define SE_SPARE_REG 0x80C
|
||||
#define SE_ERRATA_FIX_DISABLE 0
|
||||
#define SE_ERRATA_FIX_ENABLE 1
|
||||
#define SE_ECO(x) ((x) << 0)
|
||||
|
||||
#define RSA_KEY_READ 0
|
||||
#define RSA_KEY_WRITE 1
|
||||
#define SE_RSA_KEY_OP_SHIFT 10
|
||||
#define SE_RSA_KEY_OP(x) ((x) << SE_RSA_KEY_OP_SHIFT)
|
||||
|
||||
#define RSA_KEY_INPUT_MODE_REG 0
|
||||
#define RSA_KEY_INPUT_MODE_DMA 1
|
||||
#define RSA_KEY_INPUT_MODE_SHIFT 8
|
||||
#define RSA_KEY_INPUT_MODE(x) ((x) << RSA_KEY_INPUT_MODE_SHIFT)
|
||||
|
||||
#define RSA_KEY_SLOT_ONE 0
|
||||
#define RSA_KEY_SLOT_TW0 1
|
||||
#define RSA_KEY_NUM_SHIFT 7
|
||||
#define RSA_KEY_NUM(x) ((x) << RSA_KEY_NUM_SHIFT)
|
||||
|
||||
#define RSA_KEY_TYPE_EXP 0
|
||||
#define RSA_KEY_TYPE_MOD 1
|
||||
#define RSA_KEY_TYPE_SHIFT 6
|
||||
#define RSA_KEY_TYPE(x) ((x) << RSA_KEY_TYPE_SHIFT)
|
||||
|
||||
#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404
|
||||
#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408
|
||||
|
||||
#define RSA_KEY_SLOT_SHIFT 24
|
||||
#define RSA_KEY_SLOT(x) ((x) << RSA_KEY_SLOT_SHIFT)
|
||||
#define SE_RSA_CONFIG 0x400
|
||||
|
||||
#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0
|
||||
#define RSA_KEY_PKT_WORD_ADDR(x) ((x) << RSA_KEY_PKT_WORD_ADDR_SHIFT)
|
||||
|
||||
#define RSA_KEY_WORD_ADDR_SHIFT 0
|
||||
#define RSA_KEY_WORD_ADDR(x) ((x) << RSA_KEY_WORD_ADDR_SHIFT)
|
||||
|
||||
#define SE_RSA_KEYTABLE_PKT_SHIFT 0
|
||||
#define SE_RSA_KEYTABLE_PKT(x) ((x) << SE_RSA_KEYTABLE_PKT_SHIFT)
|
||||
|
||||
#endif /* _CRYPTO_TEGRA_SE_H */
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/kfuse.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <mem/heap.h>
|
||||
#include <mem/mc.h>
|
||||
@@ -33,7 +34,8 @@
|
||||
// #include <gfx_utils.h>
|
||||
|
||||
#define PKG11_MAGIC 0x31314B50
|
||||
#define KB_TSEC_FW_EMU_COMPAT 6 // KB ID for HOS 6.2.0.
|
||||
|
||||
#define TSEC_HOS_KB_620 6
|
||||
|
||||
static int _tsec_dma_wait_idle()
|
||||
{
|
||||
@@ -62,15 +64,16 @@ static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offse
|
||||
return _tsec_dma_wait_idle();
|
||||
}
|
||||
|
||||
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
|
||||
{
|
||||
int res = 0;
|
||||
u8 *fwbuf = NULL;
|
||||
u32 type = tsec_ctxt->type;
|
||||
u32 *pdir, *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
|
||||
u32 *pkg11_magic_off;
|
||||
|
||||
bpmp_mmu_disable();
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
// Enable clocks.
|
||||
clock_enable_host1x();
|
||||
@@ -83,6 +86,18 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
|
||||
kfuse_wait_ready();
|
||||
|
||||
if (type == TSEC_FW_TYPE_NEW)
|
||||
{
|
||||
// Disable all CCPLEX core rails.
|
||||
pmc_enable_partition(POWER_RAIL_CE0, DISABLE);
|
||||
pmc_enable_partition(POWER_RAIL_CE1, DISABLE);
|
||||
pmc_enable_partition(POWER_RAIL_CE2, DISABLE);
|
||||
pmc_enable_partition(POWER_RAIL_CE3, DISABLE);
|
||||
|
||||
// Enable AHB aperture and set it to full mmio.
|
||||
mc_enable_ahb_redirect(true);
|
||||
}
|
||||
|
||||
// Configure Falcon.
|
||||
TSEC(TSEC_DMACTL) = 0;
|
||||
TSEC(TSEC_IRQMSET) =
|
||||
@@ -106,11 +121,11 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
}
|
||||
|
||||
// Load firmware or emulate memio environment for newer TSEC fw.
|
||||
if (kb == KB_TSEC_FW_EMU_COMPAT)
|
||||
if (type == TSEC_FW_TYPE_EMU)
|
||||
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
|
||||
else
|
||||
{
|
||||
fwbuf = (u8 *)malloc(0x4000);
|
||||
fwbuf = (u8 *)malloc(SZ_16K);
|
||||
u8 *fwbuf_aligned = (u8 *)ALIGN((u32)fwbuf, 0x100);
|
||||
memcpy(fwbuf_aligned, tsec_ctxt->fw, tsec_ctxt->size);
|
||||
TSEC(TSEC_DMATRFBASE) = (u32)fwbuf_aligned >> 8;
|
||||
@@ -125,7 +140,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
}
|
||||
}
|
||||
|
||||
if (kb == KB_TSEC_FW_EMU_COMPAT)
|
||||
if (type == TSEC_FW_TYPE_EMU)
|
||||
{
|
||||
// Init SMMU translation for TSEC.
|
||||
pdir = smmu_init_for_tsec();
|
||||
@@ -136,16 +151,16 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
|
||||
// Clock reset controller.
|
||||
car = page_alloc(1);
|
||||
memcpy(car, (void *)CLOCK_BASE, 0x1000);
|
||||
memcpy(car, (void *)CLOCK_BASE, SZ_PAGE);
|
||||
car[CLK_RST_CONTROLLER_CLK_SOURCE_TSEC / 4] = 2;
|
||||
smmu_map(pdir, CLOCK_BASE, (u32)car, 1, _WRITABLE | _READABLE | _NONSECURE);
|
||||
|
||||
// Fuse driver.
|
||||
fuse = page_alloc(1);
|
||||
memcpy((void *)&fuse[0x800/4], (void *)FUSE_BASE, 0x400);
|
||||
memcpy((void *)&fuse[0x800/4], (void *)FUSE_BASE, SZ_1K);
|
||||
fuse[0x82C / 4] = 0;
|
||||
fuse[0x9E0 / 4] = (1 << (kb + 2)) - 1;
|
||||
fuse[0x9E4 / 4] = (1 << (kb + 2)) - 1;
|
||||
fuse[0x9E0 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
|
||||
fuse[0x9E4 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
|
||||
smmu_map(pdir, (FUSE_BASE - 0x800), (u32)fuse, 1, _READABLE | _NONSECURE);
|
||||
|
||||
// Power management controller.
|
||||
@@ -158,12 +173,12 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
|
||||
// Security engine.
|
||||
se = page_alloc(1);
|
||||
memcpy(se, (void *)SE_BASE, 0x1000);
|
||||
memcpy(se, (void *)SE_BASE, SZ_PAGE);
|
||||
smmu_map(pdir, SE_BASE, (u32)se, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||
|
||||
// Memory controller.
|
||||
mc = page_alloc(1);
|
||||
memcpy(mc, (void *)MC_BASE, 0x1000);
|
||||
memcpy(mc, (void *)MC_BASE, SZ_PAGE);
|
||||
mc[MC_IRAM_BOM / 4] = 0;
|
||||
mc[MC_IRAM_TOM / 4] = 0x80000000;
|
||||
smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE);
|
||||
@@ -187,10 +202,10 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
TSEC(TSEC_BOOTVEC) = 0;
|
||||
TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU;
|
||||
|
||||
if (kb == KB_TSEC_FW_EMU_COMPAT)
|
||||
if (type == TSEC_FW_TYPE_EMU)
|
||||
{
|
||||
u32 start = get_tmr_us();
|
||||
u32 k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
|
||||
u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
|
||||
u32 key[16] = {0};
|
||||
u32 kidx = 0;
|
||||
|
||||
@@ -198,9 +213,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
{
|
||||
smmu_flush_all();
|
||||
|
||||
if (k != se[SE_KEYTABLE_DATA0_REG_OFFSET / 4])
|
||||
if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
|
||||
{
|
||||
k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
|
||||
k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
|
||||
key[kidx++] = k;
|
||||
}
|
||||
|
||||
@@ -269,7 +284,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
|
||||
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
|
||||
|
||||
memcpy(tsec_keys, &buf, 0x10);
|
||||
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
out_free:;
|
||||
@@ -284,7 +299,11 @@ out:;
|
||||
clock_disable_sor_safe();
|
||||
clock_disable_tsec();
|
||||
bpmp_mmu_enable();
|
||||
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST);
|
||||
bpmp_clk_rate_set(prev_fid);
|
||||
|
||||
// Disable AHB aperture.
|
||||
if (type == TSEC_FW_TYPE_NEW)
|
||||
mc_disable_ahb_redirect();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -20,15 +20,24 @@
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
enum tsec_fw_type
|
||||
{
|
||||
// Retail Hovi Keygen.
|
||||
TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0.
|
||||
TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated enviroment.
|
||||
TSEC_FW_TYPE_NEW = 2, // 7.0.0+.
|
||||
};
|
||||
|
||||
typedef struct _tsec_ctxt_t
|
||||
{
|
||||
void *fw;
|
||||
u32 size;
|
||||
u32 type;
|
||||
void *pkg1;
|
||||
u32 pkg11_off;
|
||||
u32 secmon_base;
|
||||
} tsec_ctxt_t;
|
||||
|
||||
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt);
|
||||
int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* 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,
|
||||
@@ -212,43 +212,45 @@ const u8 pll_divn[] = {
|
||||
//95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB.
|
||||
};
|
||||
|
||||
bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL;
|
||||
bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
|
||||
|
||||
void bpmp_clk_rate_get()
|
||||
{
|
||||
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
|
||||
|
||||
if (clk_src_is_pllp)
|
||||
bpmp_clock_set = BPMP_CLK_NORMAL;
|
||||
bpmp_fid_current = BPMP_CLK_NORMAL;
|
||||
else
|
||||
{
|
||||
bpmp_clock_set = BPMP_CLK_HIGH_BOOST;
|
||||
bpmp_fid_current = BPMP_CLK_HIGH_BOOST;
|
||||
|
||||
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
|
||||
for (u32 i = 1; i < sizeof(pll_divn); i++)
|
||||
{
|
||||
if (pll_divn[i] == pll_divn_curr)
|
||||
{
|
||||
bpmp_clock_set = i;
|
||||
bpmp_fid_current = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bpmp_clk_rate_set(bpmp_freq_t fid)
|
||||
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid)
|
||||
{
|
||||
bpmp_freq_t prev_fid = bpmp_fid_current;
|
||||
|
||||
if (fid > (BPMP_CLK_MAX - 1))
|
||||
fid = BPMP_CLK_MAX - 1;
|
||||
|
||||
if (bpmp_clock_set == fid)
|
||||
return;
|
||||
if (prev_fid == fid)
|
||||
return prev_fid;
|
||||
|
||||
if (fid)
|
||||
{
|
||||
if (bpmp_clock_set)
|
||||
if (prev_fid)
|
||||
{
|
||||
// Restore to PLLP source during PLLC4 configuration.
|
||||
// Restore to PLLP source during PLLC configuration.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
|
||||
msleep(1); // Wait a bit for clock source change.
|
||||
}
|
||||
@@ -269,7 +271,10 @@ void bpmp_clk_rate_set(bpmp_freq_t fid)
|
||||
// Disable PLLC to save power.
|
||||
clock_disable_pllc();
|
||||
}
|
||||
bpmp_clock_set = fid;
|
||||
bpmp_fid_current = fid;
|
||||
|
||||
// Return old fid in case of temporary swap.
|
||||
return prev_fid;
|
||||
}
|
||||
|
||||
// The following functions halt BPMP to reduce power while sleeping.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* 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,
|
||||
@@ -53,6 +53,7 @@ typedef enum
|
||||
BPMP_CLK_MAX
|
||||
} bpmp_freq_t;
|
||||
|
||||
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
|
||||
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
|
||||
|
||||
void bpmp_mmu_maintenance(u32 op, bool force);
|
||||
@@ -60,7 +61,7 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply);
|
||||
void bpmp_mmu_enable();
|
||||
void bpmp_mmu_disable();
|
||||
void bpmp_clk_rate_get();
|
||||
void bpmp_clk_rate_set(bpmp_freq_t fid);
|
||||
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid);
|
||||
void bpmp_usleep(u32 us);
|
||||
void bpmp_msleep(u32 ms);
|
||||
void bpmp_halt();
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <soc/ccplex.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/clock.h>
|
||||
@@ -29,27 +28,24 @@
|
||||
|
||||
void _ccplex_enable_power_t210()
|
||||
{
|
||||
u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); // Get current pinmuxing
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~BIT(5)); // Disable GPIO5 pinmuxing.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
|
||||
// Configure GPIO5 and enable output in order to power CPU pmic.
|
||||
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_ENABLE);
|
||||
|
||||
// Enable cores power.
|
||||
// Configure CPU pmic.
|
||||
// 1-3.x: MAX77621_NFSR_ENABLE.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG,
|
||||
MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE | MAX77621_RAMP_12mV_PER_US);
|
||||
// 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
|
||||
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_HOS_CFG);
|
||||
|
||||
// Set voltage and enable cores power.
|
||||
max7762x_regulator_set_voltage(REGULATOR_CPU0, 950000);
|
||||
max7762x_regulator_enable(REGULATOR_CPU0, true);
|
||||
}
|
||||
|
||||
void _ccplex_enable_power_t210b01()
|
||||
{
|
||||
u8 pmic_cpu_addr = !(FUSE(FUSE_RESERVED_ODM28) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
|
||||
u8 tmp = i2c_recv_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL);
|
||||
i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL, tmp | MAX77812_EN_CTRL_EN_M4);
|
||||
i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_M4_VOUT, MAX77812_M4_VOUT_0_80V);
|
||||
// Set voltage and enable cores power.
|
||||
max7762x_regulator_set_voltage(REGULATOR_CPU1, 800000);
|
||||
max7762x_regulator_enable(REGULATOR_CPU1, true);
|
||||
}
|
||||
|
||||
void ccplex_boot_cpu0(u32 entry)
|
||||
@@ -62,24 +58,14 @@ void ccplex_boot_cpu0(u32 entry)
|
||||
else
|
||||
_ccplex_enable_power_t210b01();
|
||||
|
||||
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE.
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ.
|
||||
usleep(2);
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02;
|
||||
}
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000))
|
||||
;
|
||||
clock_enable_pllx();
|
||||
|
||||
// Configure MSELECT source and enable clock.
|
||||
// Configure MSELECT source and enable clock to 102MHz.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & ~BIT(CLK_V_MSELECT)) | BIT(CLK_V_MSELECT);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT);
|
||||
|
||||
// Configure initial CPU clock frequency and enable clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888;
|
||||
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ.
|
||||
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG);
|
||||
|
||||
@@ -88,12 +74,12 @@ void ccplex_boot_cpu0(u32 entry)
|
||||
// CAR2PMC_CPU_ACK_WIDTH should be set to 0.
|
||||
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
|
||||
|
||||
// Enable CPU rail.
|
||||
pmc_enable_partition(0, 1);
|
||||
// Enable CPU main rail.
|
||||
pmc_enable_partition(POWER_RAIL_CRAIL, ENABLE);
|
||||
// Enable cluster 0 non-CPU rail.
|
||||
pmc_enable_partition(15, 1);
|
||||
// Enable CE0 rail.
|
||||
pmc_enable_partition(14, 1);
|
||||
pmc_enable_partition(POWER_RAIL_C0NC, ENABLE);
|
||||
// Enable CPU0 rail.
|
||||
pmc_enable_partition(POWER_RAIL_CE0, ENABLE);
|
||||
|
||||
// Request and wait for RAM repair.
|
||||
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1;
|
||||
@@ -113,7 +99,7 @@ void ccplex_boot_cpu0(u32 entry)
|
||||
// MC(MC_TZ_SECURITY_CTRL) = 1;
|
||||
|
||||
// Clear MSELECT reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= ~BIT(CLK_V_MSELECT);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT);
|
||||
// Clear NONCPU reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
|
||||
// Clear CPU0 reset.
|
||||
|
||||
124
bdk/soc/clock.c
124
bdk/soc/clock.c
@@ -21,6 +21,23 @@
|
||||
#include <storage/sdmmc.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
typedef struct _clock_osc_t
|
||||
{
|
||||
u32 freq;
|
||||
u16 min;
|
||||
u16 max;
|
||||
} clock_osc_t;
|
||||
|
||||
static const clock_osc_t _clock_osc_cnt[] = {
|
||||
{ 12000, 706, 757 },
|
||||
{ 13000, 766, 820 },
|
||||
{ 16800, 991, 1059 },
|
||||
{ 19200, 1133, 1210 },
|
||||
{ 26000, 1535, 1638 },
|
||||
{ 38400, 2268, 2418 },
|
||||
{ 48000, 2836, 3023 }
|
||||
};
|
||||
|
||||
/* clock_t: reset, enable, source, index, clk_src, clk_div */
|
||||
|
||||
static const clock_t _clock_uart[] = {
|
||||
@@ -42,7 +59,7 @@ static const clock_t _clock_i2c[] = {
|
||||
};
|
||||
|
||||
static clock_t _clock_se = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz.
|
||||
};
|
||||
|
||||
static clock_t _clock_tzram = {
|
||||
@@ -50,19 +67,19 @@ static clock_t _clock_tzram = {
|
||||
};
|
||||
|
||||
static clock_t _clock_host1x = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz.
|
||||
};
|
||||
static clock_t _clock_tsec = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz.
|
||||
};
|
||||
static clock_t _clock_sor_safe = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0
|
||||
};
|
||||
static clock_t _clock_sor0 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, CLK_X_SOR0, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0
|
||||
};
|
||||
static clock_t _clock_sor1 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 //204MHz.
|
||||
};
|
||||
static clock_t _clock_kfuse = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
|
||||
@@ -72,11 +89,11 @@ static clock_t _clock_cl_dvfs = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
|
||||
};
|
||||
static clock_t _clock_coresight = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz.
|
||||
};
|
||||
|
||||
static clock_t _clock_pwm = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. Stock PLLP / 54: 7.55MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
|
||||
};
|
||||
|
||||
static clock_t _clock_sdmmc_legacy_tm = {
|
||||
@@ -218,13 +235,13 @@ void clock_disable_sor1()
|
||||
|
||||
void clock_enable_kfuse()
|
||||
{
|
||||
u32 kfuse_clk_unmask = ~BIT(CLK_H_KFUSE);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= kfuse_clk_unmask;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE);
|
||||
usleep(10);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= kfuse_clk_unmask;
|
||||
usleep(20);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_KFUSE);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_KFUSE);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_KFUSE);
|
||||
usleep(10); // Wait 10s to prevent glitching.
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_KFUSE);
|
||||
usleep(20); // Wait 20s fo kfuse hw to init.
|
||||
}
|
||||
|
||||
void clock_disable_kfuse()
|
||||
@@ -262,6 +279,32 @@ void clock_disable_pwm()
|
||||
clock_disable(&_clock_pwm);
|
||||
}
|
||||
|
||||
void clock_enable_pllx()
|
||||
{
|
||||
// Configure and enable PLLX if disabled.
|
||||
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE.
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= ~PLLX_MISC3_IDDQ; // Disable IDDQ.
|
||||
usleep(2);
|
||||
|
||||
// Set div configuration.
|
||||
const u32 pllx_div_cfg = (2 << 20) | (156 << 8) | 2; // P div: 2 (3), N div: 156, M div: 2. 998.4 MHz.
|
||||
|
||||
// Bypass dividers.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | pllx_div_cfg;
|
||||
// Disable bypass
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = pllx_div_cfg;
|
||||
// Set PLLX_LOCK_ENABLE.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) |= PLLX_MISC_LOCK_EN;
|
||||
// Enable PLLX.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | pllx_div_cfg;
|
||||
}
|
||||
|
||||
// Wait for PLL to stabilize.
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK))
|
||||
;
|
||||
}
|
||||
|
||||
void clock_enable_pllc(u32 divn)
|
||||
{
|
||||
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
|
||||
@@ -721,3 +764,56 @@ void clock_sdmmc_disable(u32 id)
|
||||
_clock_sdmmc_is_reset(id);
|
||||
_clock_disable_pllc4(BIT(id));
|
||||
}
|
||||
|
||||
u32 clock_get_osc_freq()
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = OSC_FREQ_DET_TRIG | (2 - 1); // 2 periods of 32.76KHz window.
|
||||
while (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY)
|
||||
;
|
||||
u32 cnt = (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_CNT);
|
||||
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = 0;
|
||||
|
||||
// Return frequency in KHz.
|
||||
for (u32 i = 0; i < ARRAY_SIZE(_clock_osc_cnt); i++)
|
||||
if (cnt >= _clock_osc_cnt[i].min && cnt <= _clock_osc_cnt[i].max)
|
||||
return _clock_osc_cnt[i].freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 clock_get_dev_freq(clock_pto_id_t id)
|
||||
{
|
||||
const u32 pto_win = 16;
|
||||
const u32 pto_osc = 32768;
|
||||
|
||||
u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (pto_win - 1);
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
||||
usleep(2);
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST;
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
||||
usleep(2);
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
||||
usleep(2);
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN;
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
||||
usleep((1000000 * pto_win / pto_osc) + 12 + 2);
|
||||
|
||||
while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY)
|
||||
;
|
||||
|
||||
u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT;
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0;
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
||||
usleep(2);
|
||||
|
||||
u32 freq_khz = (u64)cnt * pto_osc / pto_win / 1000;
|
||||
|
||||
return freq_khz;
|
||||
}
|
||||
|
||||
|
||||
196
bdk/soc/clock.h
196
bdk/soc/clock.h
@@ -35,6 +35,10 @@
|
||||
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30
|
||||
#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48
|
||||
#define CLK_RST_CONTROLLER_OSC_CTRL 0x50
|
||||
#define CLK_RST_CONTROLLER_OSC_FREQ_DET 0x58
|
||||
#define CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS 0x5C
|
||||
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL 0x60
|
||||
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS 0x64
|
||||
#define CLK_RST_CONTROLLER_PLLC_BASE 0x80
|
||||
#define CLK_RST_CONTROLLER_PLLC_OUT 0x84
|
||||
#define CLK_RST_CONTROLLER_PLLC_MISC 0x88
|
||||
@@ -156,11 +160,20 @@
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710
|
||||
|
||||
#define CLK_NO_SOURCE 0x0
|
||||
#define CLK_NOT_USED 0x0
|
||||
|
||||
/*! PLL control and status bits */
|
||||
#define PLLX_BASE_LOCK BIT(27)
|
||||
#define PLLX_BASE_REF_DIS BIT(29)
|
||||
#define PLLX_BASE_ENABLE BIT(30)
|
||||
#define PLLX_BASE_BYPASS BIT(31)
|
||||
#define PLLX_MISC_LOCK_EN BIT(18)
|
||||
#define PLLX_MISC3_IDDQ BIT(3)
|
||||
|
||||
#define PLLCX_BASE_LOCK BIT(27)
|
||||
#define PLLCX_BASE_REF_DIS BIT(29)
|
||||
#define PLLCX_BASE_ENABLE BIT(30)
|
||||
#define PLLCX_BASE_BYPASS BIT(31)
|
||||
|
||||
#define PLLA_OUT0_RSTN_CLR BIT(0)
|
||||
#define PLLA_OUT0_CLKEN BIT(1)
|
||||
@@ -178,6 +191,169 @@
|
||||
|
||||
#define UTMIPLL_LOCK BIT(31)
|
||||
|
||||
/*! PTO_CLK_CNT */
|
||||
#define PTO_REF_CLK_WIN_CFG_MASK 0xF
|
||||
#define PTO_REF_CLK_WIN_CFG_16P 0xF
|
||||
#define PTO_CNT_EN BIT(9)
|
||||
#define PTO_CNT_RST BIT(10)
|
||||
#define PTO_CLK_ENABLE BIT(13)
|
||||
#define PTO_SRC_SEL_SHIFT 14
|
||||
#define PTO_SRC_SEL_MASK 0x1FF
|
||||
#define PTO_DIV_SEL_MASK (3 << 23)
|
||||
#define PTO_DIV_SEL_GATED (0 << 23)
|
||||
#define PTO_DIV_SEL_DIV1 (1 << 23)
|
||||
#define PTO_DIV_SEL_DIV2_RISING (2 << 23)
|
||||
#define PTO_DIV_SEL_DIV2_FALLING (3 << 23)
|
||||
#define PTO_DIV_SEL_CPU_EARLY (0 << 23)
|
||||
#define PTO_DIV_SEL_CPU_LATE (1 << 23)
|
||||
|
||||
#define PTO_CLK_CNT_BUSY BIT(31)
|
||||
#define PTO_CLK_CNT 0xFFFFFF
|
||||
|
||||
/*! OSC_FREQ_DET */
|
||||
#define OSC_REF_CLK_WIN_CFG_MASK 0xF
|
||||
#define OSC_FREQ_DET_TRIG BIT(31)
|
||||
|
||||
#define OSC_FREQ_DET_BUSY BIT(31)
|
||||
#define OSC_FREQ_DET_CNT 0xFFFF
|
||||
|
||||
/*! PTO IDs. */
|
||||
typedef enum _clock_pto_id_t
|
||||
{
|
||||
CLK_PTO_PCLK_SYS = 0x06,
|
||||
CLK_PTO_HCLK_SYS = 0x07,
|
||||
|
||||
CLK_PTO_UTMIP_240 = 0x0C,
|
||||
|
||||
CLK_PTO_CCLK_G = 0x12,
|
||||
CLK_PTO_CCLK_G_DIV2 = 0x13,
|
||||
|
||||
CLK_PTO_SPI1 = 0x17,
|
||||
CLK_PTO_SPI2 = 0x18,
|
||||
CLK_PTO_SPI3 = 0x19,
|
||||
CLK_PTO_SPI4 = 0x1A,
|
||||
CLK_PTO_MAUD = 0x1B,
|
||||
CLK_PTO_SCLK = 0x1C,
|
||||
|
||||
CLK_PTO_SDMMC1 = 0x20,
|
||||
CLK_PTO_SDMMC2 = 0x21,
|
||||
CLK_PTO_SDMMC3 = 0x22,
|
||||
CLK_PTO_SDMMC4 = 0x23,
|
||||
CLK_PTO_EMC = 0x24,
|
||||
|
||||
CLK_PTO_CCLK_LP = 0x2B,
|
||||
CLK_PTO_CCLK_LP_DIV2 = 0x2C,
|
||||
|
||||
CLK_PTO_MSELECT = 0x2F,
|
||||
|
||||
CLK_PTO_VIC = 0x36,
|
||||
|
||||
CLK_PTO_NVDEC = 0x39,
|
||||
|
||||
CLK_PTO_NVENC = 0x3A,
|
||||
CLK_PTO_NVJPG = 0x3B,
|
||||
CLK_PTO_TSEC = 0x3C,
|
||||
CLK_PTO_TSECB = 0x3D,
|
||||
CLK_PTO_SE = 0x3E,
|
||||
|
||||
CLK_PTO_DSIA_LP = 0x62,
|
||||
|
||||
CLK_PTO_ISP = 0x64,
|
||||
CLK_PTO_MC = 0x6A,
|
||||
|
||||
CLK_PTO_ACTMON = 0x6B,
|
||||
CLK_PTO_CSITE = 0x6C,
|
||||
|
||||
CLK_PTO_HOST1X = 0x6F,
|
||||
|
||||
CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE.
|
||||
CLK_PTO_SOC_THERM = 0x75,
|
||||
|
||||
CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC.
|
||||
|
||||
CLK_PTO_ACLK = 0x7C,
|
||||
CLK_PTO_QSPI = 0x7D,
|
||||
|
||||
CLK_PTO_I2S1 = 0x80,
|
||||
CLK_PTO_I2S2 = 0x81,
|
||||
CLK_PTO_I2S3 = 0x82,
|
||||
CLK_PTO_I2S4 = 0x83,
|
||||
CLK_PTO_I2S5 = 0x84,
|
||||
CLK_PTO_AHUB = 0x85,
|
||||
CLK_PTO_APE = 0x86,
|
||||
|
||||
CLK_PTO_DVFS_SOC = 0x88,
|
||||
CLK_PTO_DVFS_REF = 0x89,
|
||||
|
||||
CLK_PTO_SPDIF = 0x8F,
|
||||
CLK_PTO_SPDIF_IN = 0x90,
|
||||
CLK_PTO_UART_FST_MIPI_CAL = 0x91,
|
||||
|
||||
CLK_PTO_PWM = 0x93,
|
||||
CLK_PTO_I2C1 = 0x94,
|
||||
CLK_PTO_I2C2 = 0x95,
|
||||
CLK_PTO_I2C3 = 0x96,
|
||||
CLK_PTO_I2C4 = 0x97,
|
||||
CLK_PTO_I2C5 = 0x98,
|
||||
CLK_PTO_I2C6 = 0x99,
|
||||
CLK_PTO_I2C_SLOW = 0x9A,
|
||||
CLK_PTO_UARTAPE = 0x9B,
|
||||
|
||||
CLK_PTO_EXTPERIPH1 = 0x9D,
|
||||
CLK_PTO_EXTPERIPH2 = 0x9E,
|
||||
|
||||
CLK_PTO_ENTROPY = 0xA0,
|
||||
CLK_PTO_UARTA = 0xA1,
|
||||
CLK_PTO_UARTB = 0xA2,
|
||||
CLK_PTO_UARTC = 0xA3,
|
||||
CLK_PTO_UARTD = 0xA4,
|
||||
CLK_PTO_OWR = 0xA5,
|
||||
|
||||
CLK_PTO_HDA2CODEC_2X = 0xA7,
|
||||
CLK_PTO_HDA = 0xA8,
|
||||
|
||||
CLK_PTO_SDMMC_LEGACY_TM = 0xAB,
|
||||
|
||||
CLK_PTO_SOR0 = 0xC0,
|
||||
CLK_PTO_SOR1 = 0xC1,
|
||||
|
||||
CLK_PTO_DISP2 = 0xC4,
|
||||
CLK_PTO_DISP1 = 0xC5,
|
||||
|
||||
CLK_PTO_XUSB_FALCON = 0x110,
|
||||
|
||||
CLK_PTO_XUSB_FS = 0x136,
|
||||
CLK_PTO_XUSB_SS_HOST_DEV = 0x137,
|
||||
CLK_PTO_XUSB_CORE_HOST = 0x138,
|
||||
CLK_PTO_XUSB_CORE_DEV = 0x139,
|
||||
|
||||
/*
|
||||
* PLL need PTO enabled in MISC registers.
|
||||
* Normal div is 2 so result is multiplied with it.
|
||||
*/
|
||||
CLK_PTO_PLLC_DIV2 = 0x01,
|
||||
CLK_PTO_PLLM_DIV2 = 0x02,
|
||||
CLK_PTO_PLLP_DIV2 = 0x03,
|
||||
CLK_PTO_PLLA_DIV2 = 0x04,
|
||||
CLK_PTO_PLLX_DIV2 = 0x05,
|
||||
|
||||
CLK_PTO_PLLMB_DIV2 = 0x25,
|
||||
|
||||
CLK_PTO_PLLC4_DIV2 = 0x51,
|
||||
|
||||
CLK_PTO_PLLA1_DIV2 = 0x55,
|
||||
CLK_PTO_PLLC2_DIV2 = 0x58,
|
||||
CLK_PTO_PLLC3_DIV2 = 0x5A,
|
||||
|
||||
CLK_PTO_PLLD_DIV2 = 0xCB,
|
||||
CLK_PTO_PLLD2_DIV2 = 0xCD,
|
||||
CLK_PTO_PLLDP_DIV2 = 0xCF,
|
||||
|
||||
CLK_PTO_PLLU_DIV2 = 0x10D,
|
||||
|
||||
CLK_PTO_PLLREFE_DIV2 = 0x10F,
|
||||
} clock_pto_id_t;
|
||||
|
||||
/*
|
||||
* CLOCK Peripherals:
|
||||
* L 0 - 31
|
||||
@@ -216,7 +392,7 @@ enum CLK_L_DEV
|
||||
CLK_L_USBD = 22,
|
||||
CLK_L_ISP = 23,
|
||||
CLK_L_3D = 24, // HIDDEN.
|
||||
//CLK_L_ = 25,
|
||||
CLK_L_IDE = 25, // RESERVED.
|
||||
CLK_L_DISP2 = 26,
|
||||
CLK_L_DISP1 = 27,
|
||||
CLK_L_HOST1X = 28,
|
||||
@@ -244,11 +420,11 @@ enum CLK_H_DEV
|
||||
CLK_H_SPI3 = 14,
|
||||
CLK_H_I2C5 = 15,
|
||||
CLK_H_DSI = 16,
|
||||
//CLK_H_ = 17,
|
||||
CLK_H_TVO = 17, // RESERVED.
|
||||
CLK_H_HSI = 18, // HIDDEN.
|
||||
CLK_H_HDMI = 19, // HIDDEN.
|
||||
CLK_H_CSI = 20,
|
||||
//CLK_H_ = 21,
|
||||
CLK_H_TVDAC = 21, // RESERVED.
|
||||
CLK_H_I2C2 = 22,
|
||||
CLK_H_UARTC = 23,
|
||||
CLK_H_MIPI_CAL = 24,
|
||||
@@ -263,14 +439,14 @@ enum CLK_H_DEV
|
||||
|
||||
enum CLK_U_DEV
|
||||
{
|
||||
//CLK_U_ = 0,
|
||||
CLK_U_SPEEDO = 0, // RESERVED.
|
||||
CLK_U_UARTD = 1,
|
||||
CLK_U_UARTE = 2, // HIDDEN.
|
||||
CLK_U_I2C3 = 3,
|
||||
CLK_U_SPI4 = 4,
|
||||
CLK_U_SDMMC3 = 5,
|
||||
CLK_U_PCIE = 6,
|
||||
CLK_U_UNUSED = 7, // RESERVED
|
||||
CLK_U_OWR = 7, // RESERVED.
|
||||
CLK_U_AFI = 8,
|
||||
CLK_U_CSITE = 9,
|
||||
CLK_U_PCIEXCLK = 10, // Only reset.
|
||||
@@ -444,9 +620,9 @@ enum CLK_Y_DEV
|
||||
/*! Generic clock descriptor. */
|
||||
typedef struct _clock_t
|
||||
{
|
||||
u32 reset;
|
||||
u32 enable;
|
||||
u32 source;
|
||||
u16 reset;
|
||||
u16 enable;
|
||||
u16 source;
|
||||
u8 index;
|
||||
u8 clk_src;
|
||||
u8 clk_div;
|
||||
@@ -483,6 +659,7 @@ void clock_enable_coresight();
|
||||
void clock_disable_coresight();
|
||||
void clock_enable_pwm();
|
||||
void clock_disable_pwm();
|
||||
void clock_enable_pllx();
|
||||
void clock_enable_pllc(u32 divn);
|
||||
void clock_disable_pllc();
|
||||
void clock_enable_pllu();
|
||||
@@ -494,4 +671,7 @@ int clock_sdmmc_is_not_reset_and_enabled(u32 id);
|
||||
void clock_sdmmc_enable(u32 id, u32 val);
|
||||
void clock_sdmmc_disable(u32 id);
|
||||
|
||||
u32 clock_get_osc_freq();
|
||||
u32 clock_get_dev_freq(clock_pto_id_t id);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 shuffle2
|
||||
* Copyright (c) 2018 balika011
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* 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,
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/t210.h>
|
||||
@@ -76,32 +78,76 @@ u32 fuse_read_odm_keygen_rev()
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 fuse_read_dramid(bool raw_id)
|
||||
{
|
||||
u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3;
|
||||
|
||||
if (raw_id)
|
||||
return dramid;
|
||||
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||
{
|
||||
if (dramid > 6)
|
||||
dramid = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dramid > 28)
|
||||
dramid = 8;
|
||||
}
|
||||
|
||||
return dramid;
|
||||
}
|
||||
|
||||
u32 fuse_read_hw_state()
|
||||
{
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
return FUSE_NX_HW_STATE_PROD;
|
||||
else
|
||||
return FUSE_NX_HW_STATE_DEV;
|
||||
}
|
||||
|
||||
u32 fuse_read_hw_type()
|
||||
{
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
|
||||
{
|
||||
switch ((fuse_read_odm(4) & 0xF0000) >> 16)
|
||||
{
|
||||
case 1:
|
||||
return FUSE_NX_HW_TYPE_IOWA;
|
||||
case 2:
|
||||
return FUSE_NX_HW_TYPE_HOAG;
|
||||
case 4:
|
||||
return FUSE_NX_HW_TYPE_AULA;
|
||||
case 1:
|
||||
default:
|
||||
return FUSE_NX_HW_TYPE_IOWA;
|
||||
}
|
||||
}
|
||||
|
||||
return FUSE_NX_HW_TYPE_ICOSA;
|
||||
}
|
||||
|
||||
u8 fuse_count_burnt(u32 val)
|
||||
int fuse_set_sbk()
|
||||
{
|
||||
u8 burnt_fuses = 0;
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
if (FUSE(FUSE_PRIVATE_KEY0) != 0xFFFFFFFF)
|
||||
{
|
||||
if ((val >> i) & 1)
|
||||
burnt_fuses++;
|
||||
// Read SBK from fuses.
|
||||
u32 sbk[4] = {
|
||||
FUSE(FUSE_PRIVATE_KEY0),
|
||||
FUSE(FUSE_PRIVATE_KEY1),
|
||||
FUSE(FUSE_PRIVATE_KEY2),
|
||||
FUSE(FUSE_PRIVATE_KEY3)
|
||||
};
|
||||
|
||||
// Set SBK to slot 14.
|
||||
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
|
||||
|
||||
// Lock SBK from being read.
|
||||
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return burnt_fuses;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fuse_wait_idle()
|
||||
@@ -118,6 +164,7 @@ u32 fuse_read(u32 addr)
|
||||
FUSE(FUSE_ADDR) = addr;
|
||||
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
||||
fuse_wait_idle();
|
||||
|
||||
return FUSE(FUSE_RDATA);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 shuffle2
|
||||
* Copyright (c) 2018 balika011
|
||||
* 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,
|
||||
@@ -64,9 +65,10 @@
|
||||
#define FUSE_OPT_X_COORDINATE 0x214
|
||||
#define FUSE_OPT_Y_COORDINATE 0x218
|
||||
#define FUSE_GPU_IDDQ_CALIB 0x228
|
||||
#define FUSE_RESERVED_ODM28 0x240
|
||||
#define FUSE_USB_CALIB_EXT 0x350
|
||||
|
||||
#define FUSE_RESERVED_ODM28_T210B01 0x240
|
||||
|
||||
/*! Fuse commands. */
|
||||
#define FUSE_READ 0x1
|
||||
#define FUSE_WRITE 0x2
|
||||
@@ -80,14 +82,23 @@ enum
|
||||
{
|
||||
FUSE_NX_HW_TYPE_ICOSA,
|
||||
FUSE_NX_HW_TYPE_IOWA,
|
||||
FUSE_NX_HW_TYPE_HOAG
|
||||
FUSE_NX_HW_TYPE_HOAG,
|
||||
FUSE_NX_HW_TYPE_AULA
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FUSE_NX_HW_STATE_PROD,
|
||||
FUSE_NX_HW_STATE_DEV
|
||||
};
|
||||
|
||||
void fuse_disable_program();
|
||||
u32 fuse_read_odm(u32 idx);
|
||||
u32 fuse_read_odm_keygen_rev();
|
||||
u32 fuse_read_dramid(bool raw_id);
|
||||
u32 fuse_read_hw_state();
|
||||
u32 fuse_read_hw_type();
|
||||
u8 fuse_count_burnt(u32 val);
|
||||
int fuse_set_sbk();
|
||||
void fuse_wait_idle();
|
||||
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
|
||||
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <soc/hw_init.h>
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <input/joycon.h>
|
||||
#include <input/touch.h>
|
||||
#include <sec/se.h>
|
||||
@@ -42,11 +42,23 @@
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
#include <thermal/fan.h>
|
||||
#include <thermal/tmp451.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
extern boot_cfg_t b_cfg;
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
u32 hw_rst_status;
|
||||
u32 hw_rst_reason;
|
||||
|
||||
u32 hw_get_chip_id()
|
||||
{
|
||||
if (((APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01)
|
||||
return GP_HIDREV_MAJOR_T210B01;
|
||||
else
|
||||
return GP_HIDREV_MAJOR_T210;
|
||||
}
|
||||
|
||||
/*
|
||||
* CLK_OSC - 38.4 MHz crystal.
|
||||
* CLK_M - 19.2 MHz (osc/2).
|
||||
@@ -56,14 +68,6 @@ extern volatile nyx_storage_t *nyx_str;
|
||||
* PCLK - 68MHz init (-> 136MHz -> OC/4).
|
||||
*/
|
||||
|
||||
u32 hw_get_chip_id()
|
||||
{
|
||||
if (((APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01)
|
||||
return GP_HIDREV_MAJOR_T210B01;
|
||||
else
|
||||
return GP_HIDREV_MAJOR_T210;
|
||||
}
|
||||
|
||||
static void _config_oscillators()
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2.
|
||||
@@ -87,6 +91,7 @@ static void _config_oscillators()
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
|
||||
}
|
||||
|
||||
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
|
||||
static void _config_gpios(bool nx_hoag)
|
||||
{
|
||||
// Clamp inputs when tristated.
|
||||
@@ -248,36 +253,25 @@ static void _mbist_workaround()
|
||||
|
||||
static void _config_se_brom()
|
||||
{
|
||||
// Enable fuse clock.
|
||||
// Enable Fuse visibility.
|
||||
clock_enable_fuse(true);
|
||||
|
||||
// Skip SBK/SSK if sept was run.
|
||||
bool sbk_skip = b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN || FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
|
||||
if (!sbk_skip)
|
||||
{
|
||||
// Bootrom part we skipped.
|
||||
u32 sbk[4] = {
|
||||
FUSE(FUSE_PRIVATE_KEY0),
|
||||
FUSE(FUSE_PRIVATE_KEY1),
|
||||
FUSE(FUSE_PRIVATE_KEY2),
|
||||
FUSE(FUSE_PRIVATE_KEY3)
|
||||
};
|
||||
// Set SBK to slot 14.
|
||||
se_aes_key_set(14, sbk, 0x10);
|
||||
// Try to set SBK from fuses. If patched, skip.
|
||||
fuse_set_sbk();
|
||||
|
||||
// Lock SBK from being read.
|
||||
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||
|
||||
// Lock SSK (although it's not set and unused anyways).
|
||||
se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||
}
|
||||
// Lock SSK (although it's not set and unused anyways).
|
||||
// se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||
|
||||
// This memset needs to happen here, else TZRAM will behave weirdly later on.
|
||||
memset((void *)TZRAM_BASE, 0, 0x10000);
|
||||
memset((void *)TZRAM_BASE, 0, SZ_64K);
|
||||
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
|
||||
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
|
||||
SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
|
||||
|
||||
// Clear the boot reason to avoid problems later
|
||||
// Save reset reason.
|
||||
hw_rst_status = PMC(APBDEV_PMC_SCRATCH200);
|
||||
hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK;
|
||||
|
||||
// Clear the boot reason to avoid problems later.
|
||||
PMC(APBDEV_PMC_SCRATCH200) = 0x0;
|
||||
PMC(APBDEV_PMC_RST_STATUS) = 0x0;
|
||||
APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10);
|
||||
@@ -287,19 +281,19 @@ static void _config_regulators(bool tegra_t210)
|
||||
{
|
||||
// Set RTC/AO domain to POR voltage.
|
||||
if (tegra_t210)
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO4, 1000000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO4, 1000000);
|
||||
|
||||
// Disable low battery shutdown monitor.
|
||||
max77620_low_battery_monitor_config(false);
|
||||
|
||||
// Disable SDMMC1 IO power.
|
||||
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 0);
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, false);
|
||||
sd_power_cycle_time_start = get_tmr_ms();
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1,
|
||||
BIT(6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
|
||||
MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
|
||||
|
||||
if (tegra_t210)
|
||||
{
|
||||
@@ -317,28 +311,18 @@ static void _config_regulators(bool tegra_t210)
|
||||
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
|
||||
|
||||
// Set vdd_core voltage to 1.125V.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD0, 1125000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000);
|
||||
|
||||
// Fix CPU/GPU after a L4T warmboot.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
|
||||
// Fix CPU/GPU after L4T warmboot.
|
||||
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE);
|
||||
max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
|
||||
// Set POR configuration.
|
||||
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG);
|
||||
max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG);
|
||||
}
|
||||
else // Tegra X1+ set vdd_core voltage to 1.05V.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD0, 1050000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000);
|
||||
}
|
||||
|
||||
void hw_init()
|
||||
@@ -360,7 +344,7 @@ void hw_init()
|
||||
// Enable Security Engine clock.
|
||||
clock_enable_se();
|
||||
|
||||
// Enable Fuse clock.
|
||||
// Enable Fuse visibility.
|
||||
clock_enable_fuse(true);
|
||||
|
||||
// Disable Fuse programming.
|
||||
@@ -396,7 +380,10 @@ void hw_init()
|
||||
|
||||
//! TODO: Why? Device is NFC MCU on Lite.
|
||||
if (nx_hoag)
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO8, 2800000, MAX77620_POWER_MODE_NORMAL);
|
||||
{
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO8, true);
|
||||
}
|
||||
|
||||
// Initialize I2C1 for various power related devices.
|
||||
i2c_init(I2C_1);
|
||||
@@ -426,19 +413,18 @@ void hw_init()
|
||||
bpmp_mmu_enable();
|
||||
}
|
||||
|
||||
void hw_reinit_workaround(bool extra_reconfig, u32 magic)
|
||||
void hw_reinit_workaround(bool coreboot, u32 bl_magic)
|
||||
{
|
||||
// Disable BPMP max clock.
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
#ifdef NYX
|
||||
// Deinit touchscreen, 5V regulators and Joy-Con.
|
||||
touch_power_off();
|
||||
// Disable temperature sensor, touchscreen, 5V regulators and Joy-Con.
|
||||
tmp451_end();
|
||||
set_fan_duty(0);
|
||||
touch_power_off();
|
||||
jc_deinit();
|
||||
regulator_disable_5v(REGULATOR_5V_ALL);
|
||||
clock_disable_uart(UART_B);
|
||||
clock_disable_uart(UART_C);
|
||||
regulator_5v_disable(REGULATOR_5V_ALL);
|
||||
#endif
|
||||
|
||||
// Flush/disable MMU cache and set DRAM clock to 204MHz.
|
||||
@@ -450,10 +436,10 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic)
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
|
||||
|
||||
if (extra_reconfig)
|
||||
// Do coreboot mitigations.
|
||||
if (coreboot)
|
||||
{
|
||||
msleep(10);
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
|
||||
|
||||
clock_disable_cl_dvfs();
|
||||
|
||||
@@ -462,13 +448,27 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic)
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO);
|
||||
|
||||
// Reinstate SD controller power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
|
||||
}
|
||||
|
||||
// Power off display.
|
||||
display_end();
|
||||
// Seamless display or display power off.
|
||||
switch (bl_magic)
|
||||
{
|
||||
case BL_MAGIC_CRBOOT_SLD:;
|
||||
// Set pwm to 0%, switch to gpio mode and restore pwm duty.
|
||||
u32 brightness = display_get_backlight_brightness();
|
||||
display_backlight_brightness(0, 1000);
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO);
|
||||
display_backlight_brightness(brightness, 0);
|
||||
break;
|
||||
default:
|
||||
display_end();
|
||||
}
|
||||
|
||||
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
|
||||
if (magic == 0xBAADF00D)
|
||||
if (bl_magic == BL_MAGIC_BROKEN_HWI)
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
|
||||
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -20,8 +20,14 @@
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0.
|
||||
#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit.
|
||||
|
||||
extern u32 hw_rst_status;
|
||||
extern u32 hw_rst_reason;
|
||||
|
||||
void hw_init();
|
||||
void hw_reinit_workaround(bool extra_reconfig, u32 magic);
|
||||
void hw_reinit_workaround(bool coreboot, u32 magic);
|
||||
u32 hw_get_chip_id();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -133,6 +133,10 @@ static irq_status_t _irq_handle_source(u32 irq)
|
||||
}
|
||||
}
|
||||
|
||||
// Do not re-enable if not handled.
|
||||
if (status == IRQ_NONE)
|
||||
return status;
|
||||
|
||||
if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
|
||||
irq_free(irq);
|
||||
else
|
||||
@@ -148,7 +152,9 @@ void irq_handler()
|
||||
|
||||
if (!irq_init_done)
|
||||
{
|
||||
_irq_disable_source(irq);
|
||||
_irq_ack_source(irq);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -156,9 +162,10 @@ void irq_handler()
|
||||
|
||||
int err = _irq_handle_source(irq);
|
||||
|
||||
//TODO: disable if unhandhled.
|
||||
if (err == IRQ_NONE)
|
||||
gfx_printf("Unhandled IRQ: %d\n", irq);
|
||||
{
|
||||
DPRINTF("Unhandled IRQ got disabled: %d!\n", irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void _irq_init()
|
||||
@@ -170,6 +177,9 @@ static void _irq_init()
|
||||
|
||||
void irq_end()
|
||||
{
|
||||
if (!irq_init_done)
|
||||
return;
|
||||
|
||||
_irq_free_all();
|
||||
irq_disable_cpu_irq_exceptions();
|
||||
irq_init_done = false;
|
||||
|
||||
@@ -14,11 +14,69 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
int pmc_enable_partition(u32 part, int enable)
|
||||
void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
|
||||
{
|
||||
// Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address.
|
||||
if (lock_mask & PMC_SEC_LOCK_MISC)
|
||||
{
|
||||
PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119.
|
||||
|
||||
// SE2 context.
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
|
||||
{
|
||||
PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150.
|
||||
}
|
||||
}
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS)
|
||||
{
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF; // RW lock: 88-98.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF; // RW lock: 104-107.
|
||||
}
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_RST_VECTOR)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xF00000; // RW lock: 34-35.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_CARVEOUTS)
|
||||
{
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x30000; // RW lock: 16.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xC0000000; // RW lock: 39.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0xC0C00000; // RW lock: 51, 55.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0x3FF0; // RW lock: 74-78.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103.
|
||||
}
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_R)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xAA0000; // R lock: 112-115.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_W)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x55; // W lock: 24-27.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_SE_SRK)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7
|
||||
}
|
||||
|
||||
int pmc_enable_partition(pmc_power_rail_t part, u32 enable)
|
||||
{
|
||||
u32 part_mask = BIT(part);
|
||||
u32 desired_state = enable << part;
|
||||
|
||||
@@ -60,6 +60,13 @@
|
||||
#define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8
|
||||
#define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2)
|
||||
#define APBDEV_PMC_RST_STATUS 0x1B4
|
||||
#define PMC_RST_STATUS_MASK 0x7
|
||||
#define PMC_RST_STATUS_POR 0
|
||||
#define PMC_RST_STATUS_WATCHDOG 1
|
||||
#define PMC_RST_STATUS_SENSOR 2
|
||||
#define PMC_RST_STATUS_SW_MAIN 3
|
||||
#define PMC_RST_STATUS_LP0 4
|
||||
#define PMC_RST_STATUS_AOTAG 5
|
||||
#define APBDEV_PMC_IO_DPD_REQ 0x1B8
|
||||
#define PMC_IO_DPD_REQ_DPD_OFF BIT(30)
|
||||
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
|
||||
@@ -91,6 +98,8 @@
|
||||
#define APBDEV_PMC_SEC_DISABLE6 0x5B8
|
||||
#define APBDEV_PMC_SEC_DISABLE7 0x5BC
|
||||
#define APBDEV_PMC_SEC_DISABLE8 0x5C0
|
||||
#define APBDEV_PMC_SEC_DISABLE9 0x5C4
|
||||
#define APBDEV_PMC_SEC_DISABLE10 0x5C8
|
||||
#define APBDEV_PMC_SCRATCH188 0x810
|
||||
#define APBDEV_PMC_SCRATCH190 0x818
|
||||
#define APBDEV_PMC_SCRATCH200 0x840
|
||||
@@ -98,6 +107,54 @@
|
||||
#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC
|
||||
#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0
|
||||
|
||||
int pmc_enable_partition(u32 part, int enable);
|
||||
typedef enum _pmc_sec_lock_t
|
||||
{
|
||||
PMC_SEC_LOCK_MISC = BIT(0),
|
||||
PMC_SEC_LOCK_LP0_PARAMS = BIT(1),
|
||||
PMC_SEC_LOCK_RST_VECTOR = BIT(2),
|
||||
PMC_SEC_LOCK_CARVEOUTS = BIT(3),
|
||||
PMC_SEC_LOCK_TZ_CMAC_W = BIT(4),
|
||||
PMC_SEC_LOCK_TZ_CMAC_R = BIT(5),
|
||||
PMC_SEC_LOCK_TZ_KEK_W = BIT(6),
|
||||
PMC_SEC_LOCK_TZ_KEK_R = BIT(7),
|
||||
PMC_SEC_LOCK_SE_SRK = BIT(8),
|
||||
} pmc_sec_lock_t;
|
||||
|
||||
typedef enum _pmc_power_rail_t
|
||||
{
|
||||
POWER_RAIL_CRAIL = 0,
|
||||
POWER_RAIL_3D0 = 1,
|
||||
POWER_RAIL_VENC = 2,
|
||||
POWER_RAIL_PCIE = 3,
|
||||
POWER_RAIL_VDEC = 4,
|
||||
POWER_RAIL_L2C = 5,
|
||||
POWER_RAIL_MPE = 6,
|
||||
POWER_RAIL_HEG = 7,
|
||||
POWER_RAIL_SATA = 8,
|
||||
POWER_RAIL_CE1 = 9,
|
||||
POWER_RAIL_CE2 = 10,
|
||||
POWER_RAIL_CE3 = 11,
|
||||
POWER_RAIL_CELP = 12,
|
||||
POWER_RAIL_3D1 = 13,
|
||||
POWER_RAIL_CE0 = 14,
|
||||
POWER_RAIL_C0NC = 15,
|
||||
POWER_RAIL_C1NC = 16,
|
||||
POWER_RAIL_SOR = 17,
|
||||
POWER_RAIL_DIS = 18,
|
||||
POWER_RAIL_DISB = 19,
|
||||
POWER_RAIL_XUSBA = 20,
|
||||
POWER_RAIL_XUSBB = 21,
|
||||
POWER_RAIL_XUSBC = 22,
|
||||
POWER_RAIL_VIC = 23,
|
||||
POWER_RAIL_IRAM = 24,
|
||||
POWER_RAIL_NVDEC = 25,
|
||||
POWER_RAIL_NVJPG = 26,
|
||||
POWER_RAIL_AUD = 27,
|
||||
POWER_RAIL_DFD = 28,
|
||||
POWER_RAIL_VE2 = 29
|
||||
} pmc_power_rail_t;
|
||||
|
||||
void pmc_scratch_lock(pmc_sec_lock_t lock_mask);
|
||||
int pmc_enable_partition(pmc_power_rail_t part, u32 enable);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -281,7 +281,6 @@
|
||||
/*! Special registers. */
|
||||
#define EMC_SCRATCH0 0x324
|
||||
#define EMC_HEKA_UPD BIT(30)
|
||||
#define EMC_SEPT_RUN BIT(31)
|
||||
|
||||
/*! Flow controller registers. */
|
||||
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
|
||||
|
||||
@@ -122,7 +122,12 @@ u32 uart_get_IIR(u32 idx)
|
||||
{
|
||||
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
|
||||
|
||||
return uart->UART_IIR_FCR;
|
||||
u32 iir = uart->UART_IIR_FCR & UART_IIR_INT_MASK;
|
||||
|
||||
if (iir & UART_IIR_NO_INT)
|
||||
return 0;
|
||||
else
|
||||
return ((iir >> 1) + 1); // Return encoded interrupt.
|
||||
}
|
||||
|
||||
void uart_set_IIR(u32 idx)
|
||||
|
||||
@@ -54,6 +54,17 @@
|
||||
#define UART_IIR_FCR_RX_CLR 0x2
|
||||
#define UART_IIR_FCR_EN_FIFO 0x1
|
||||
|
||||
#define UART_IIR_NO_INT BIT(0)
|
||||
#define UART_IIR_INT_MASK 0xF
|
||||
/* Custom returned interrupt results. Actual interrupts are -1 */
|
||||
#define UART_IIR_NOI 0 // No interrupt.
|
||||
#define UART_IIR_MSI 1 // Modem status interrupt.
|
||||
#define UART_IIR_THRI 2 // Transmitter holding register empty.
|
||||
#define UART_IIR_RDI 3 // Receiver data interrupt.
|
||||
#define UART_IIR_ERROR 4 // Overrun Error, Parity Error, Framing Error, Break.
|
||||
#define UART_IIR_REDI 5 // Receiver end of data interrupt.
|
||||
#define UART_IIR_RDTI 7 // Receiver data timeout interrupt.
|
||||
|
||||
#define UART_MCR_RTS 0x2
|
||||
#define UART_MCR_DTR 0x1
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Header for MultiMediaCard (MMC)
|
||||
*
|
||||
* Copyright 2002 Hewlett-Packard Company
|
||||
* Copyright 2018-2021 CTCaer
|
||||
*
|
||||
* Use consistent with the GNU GPL is permitted,
|
||||
* provided that this copyright notice is
|
||||
@@ -21,8 +22,8 @@
|
||||
* 15 May 2002
|
||||
*/
|
||||
|
||||
#ifndef LINUX_MMC_MMC_H
|
||||
#define LINUX_MMC_MMC_H
|
||||
#ifndef MMC_H
|
||||
#define MMC_H
|
||||
|
||||
/* Standard MMC commands (4.1) type argument response */
|
||||
/* class 1 */
|
||||
@@ -84,6 +85,11 @@
|
||||
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
||||
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
||||
|
||||
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
|
||||
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
|
||||
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
|
||||
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
|
||||
|
||||
/* class 11 */
|
||||
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
|
||||
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
|
||||
@@ -92,29 +98,29 @@
|
||||
#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */
|
||||
|
||||
/*
|
||||
* MMC_SWITCH argument format:
|
||||
*
|
||||
* [31:26] Always 0
|
||||
* [25:24] Access Mode
|
||||
* [23:16] Location of target Byte in EXT_CSD
|
||||
* [15:08] Value Byte
|
||||
* [07:03] Always 0
|
||||
* [02:00] Command Set
|
||||
*/
|
||||
* MMC_SWITCH argument format:
|
||||
*
|
||||
* [31:26] Always 0
|
||||
* [25:24] Access Mode
|
||||
* [23:16] Location of target Byte in EXT_CSD
|
||||
* [15:08] Value Byte
|
||||
* [07:03] Always 0
|
||||
* [02:00] Command Set
|
||||
*/
|
||||
|
||||
/*
|
||||
MMC status in R1, for native mode (SPI bits are different)
|
||||
Type
|
||||
e : error bit
|
||||
s : status bit
|
||||
r : detected and set for the actual command response
|
||||
x : detected and set during command execution. the host must poll
|
||||
the card by sending status command in order to read these bits.
|
||||
Clear condition
|
||||
a : according to the card state
|
||||
b : always related to the previous command. Reception of
|
||||
a valid command will clear it (with a delay of one command)
|
||||
c : clear by read
|
||||
* MMC status in R1, for native mode (SPI bits are different)
|
||||
* Type
|
||||
* e : error bit
|
||||
* s : status bit
|
||||
* r : detected and set for the actual command response
|
||||
* x : detected and set during command execution. the host must poll
|
||||
* the card by sending status command in order to read these bits.
|
||||
* Clear condition
|
||||
* a : according to the card state
|
||||
* b : always related to the previous command. Reception of a valid
|
||||
* command will clear it (with a delay of one command)
|
||||
* c : clear by read
|
||||
*/
|
||||
|
||||
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
|
||||
@@ -146,6 +152,7 @@ c : clear by read
|
||||
#define R1_AKE_SEQ_ERROR (1 << 3)
|
||||
|
||||
/* R1_CURRENT_STATE 12:9 */
|
||||
#define R1_STATE(x) ((x) << 9)
|
||||
#define R1_STATE_IDLE 0
|
||||
#define R1_STATE_READY 1
|
||||
#define R1_STATE_IDENT 2
|
||||
@@ -157,9 +164,9 @@ c : clear by read
|
||||
#define R1_STATE_DIS 8
|
||||
|
||||
/*
|
||||
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
|
||||
* R1 is the low order byte; R2 is the next highest byte, when present.
|
||||
*/
|
||||
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
|
||||
* R1 is the low order byte; R2 is the next highest byte, when present.
|
||||
*/
|
||||
#define R1_SPI_IDLE (1 << 0)
|
||||
#define R1_SPI_ERASE_RESET (1 << 1)
|
||||
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
|
||||
@@ -180,13 +187,16 @@ c : clear by read
|
||||
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
|
||||
|
||||
/*
|
||||
* OCR bits are mostly in host.h
|
||||
*/
|
||||
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
|
||||
* OCR bits are mostly in host.h
|
||||
*/
|
||||
#define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */
|
||||
#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */
|
||||
#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */
|
||||
#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */
|
||||
|
||||
/*
|
||||
* Card Command Classes (CCC)
|
||||
*/
|
||||
* Card Command Classes (CCC)
|
||||
*/
|
||||
#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
|
||||
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
|
||||
/* (and for SPI, CMD58,59) */
|
||||
@@ -214,8 +224,8 @@ c : clear by read
|
||||
/* (CMD?) */
|
||||
|
||||
/*
|
||||
* CSD field definitions
|
||||
*/
|
||||
* CSD field definitions
|
||||
*/
|
||||
|
||||
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
|
||||
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
|
||||
@@ -229,8 +239,8 @@ c : clear by read
|
||||
#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
|
||||
|
||||
/*
|
||||
* EXT_CSD fields
|
||||
*/
|
||||
* EXT_CSD fields
|
||||
*/
|
||||
|
||||
#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */
|
||||
#define EXT_CSD_FLUSH_CACHE 32 /* W */
|
||||
@@ -244,6 +254,7 @@ c : clear by read
|
||||
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
||||
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
|
||||
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
|
||||
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
|
||||
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
|
||||
#define EXT_CSD_HPI_MGMT 161 /* R/W */
|
||||
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
||||
@@ -307,8 +318,8 @@ c : clear by read
|
||||
#define EXT_CSD_HPI_FEATURES 503 /* RO */
|
||||
|
||||
/*
|
||||
* EXT_CSD field definitions
|
||||
*/
|
||||
* EXT_CSD field definitions
|
||||
*/
|
||||
|
||||
#define EXT_CSD_WR_REL_PARAM_EN (1<<2)
|
||||
|
||||
@@ -384,8 +395,8 @@ c : clear by read
|
||||
#define EXT_CSD_PACKED_EVENT_EN (1<<3)
|
||||
|
||||
/*
|
||||
* EXCEPTION_EVENT_STATUS field
|
||||
*/
|
||||
* EXCEPTION_EVENT_STATUS field
|
||||
*/
|
||||
#define EXT_CSD_URGENT_BKOPS (1<<0)
|
||||
#define EXT_CSD_DYNCAP_NEEDED (1<<1)
|
||||
#define EXT_CSD_SYSPOOL_EXHAUSTED (1<<2)
|
||||
@@ -395,34 +406,34 @@ c : clear by read
|
||||
#define EXT_CSD_PACKED_INDEXED_ERROR (1<<1)
|
||||
|
||||
/*
|
||||
* BKOPS status level
|
||||
*/
|
||||
* BKOPS status level
|
||||
*/
|
||||
#define EXT_CSD_BKOPS_LEVEL_2 0x2
|
||||
|
||||
/*
|
||||
* BKOPS modes
|
||||
*/
|
||||
* BKOPS modes
|
||||
*/
|
||||
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01
|
||||
#define EXT_CSD_AUTO_BKOPS_MASK 0x02
|
||||
|
||||
/*
|
||||
* Command Queue
|
||||
*/
|
||||
* Command Queue
|
||||
*/
|
||||
#define EXT_CSD_CMDQ_MODE_ENABLED (1<<0)
|
||||
#define EXT_CSD_CMDQ_DEPTH_MASK 0x1F
|
||||
#define EXT_CSD_CMDQ_SUPPORTED (1<<0)
|
||||
|
||||
/*
|
||||
* MMC_SWITCH access modes
|
||||
*/
|
||||
* MMC_SWITCH access modes
|
||||
*/
|
||||
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
|
||||
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
|
||||
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
|
||||
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
|
||||
|
||||
/*
|
||||
* Erase/trim/discard
|
||||
*/
|
||||
* Erase/trim/discard
|
||||
*/
|
||||
#define MMC_ERASE_ARG 0x00000000
|
||||
#define MMC_SECURE_ERASE_ARG 0x80000000
|
||||
#define MMC_TRIM_ARG 0x00000001
|
||||
@@ -432,4 +443,9 @@ c : clear by read
|
||||
#define MMC_SECURE_ARGS 0x80000000
|
||||
#define MMC_TRIM_ARGS 0x00008001
|
||||
|
||||
#endif /* LINUX_MMC_MMC_H */
|
||||
/*
|
||||
* Vendor definitions and structs
|
||||
*/
|
||||
#define MMC_SANDISK_HEALTH_REPORT 0x96C9D71C
|
||||
|
||||
#endif /* MMC_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -45,12 +45,15 @@ extern FATFS sd_fs;
|
||||
void sd_error_count_increment(u8 type);
|
||||
u16 *sd_get_error_count();
|
||||
bool sd_get_card_removed();
|
||||
bool sd_get_card_initialized();
|
||||
bool sd_get_card_mounted();
|
||||
u32 sd_get_mode();
|
||||
int sd_init_retry(bool power_cycle);
|
||||
bool sd_initialize(bool power_cycle);
|
||||
bool sd_mount();
|
||||
void sd_unmount();
|
||||
void sd_end();
|
||||
bool sd_is_gpt();
|
||||
void *sd_file_read(const char *path, u32 *fsize);
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Ramdisk driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* 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,
|
||||
@@ -19,23 +19,40 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "ramdisk.h"
|
||||
#include <libs/fatfs/diskio.h>
|
||||
#include <mem/heap.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
#include <memory_map.h>
|
||||
|
||||
int ram_disk_init(FATFS *ram_fs)
|
||||
static u32 disk_size = 0;
|
||||
|
||||
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size)
|
||||
{
|
||||
int res;
|
||||
u8 *buf = malloc(0x400000);
|
||||
int res = 0;
|
||||
disk_size = ramdisk_size;
|
||||
|
||||
f_mount(NULL, "ram:", 1); // Unmount ramdisk.
|
||||
// If ramdisk is not raw, format it.
|
||||
if (ram_fs)
|
||||
{
|
||||
u8 *buf = malloc(0x400000);
|
||||
|
||||
res = f_mkfs("ram:", FM_EXFAT, RAMDISK_CLUSTER_SZ, buf, 0x400000); // Format as exFAT w/ 32KB cluster.
|
||||
if (!res)
|
||||
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk.
|
||||
// Set ramdisk size.
|
||||
ramdisk_size >>= 9;
|
||||
disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
|
||||
|
||||
free(buf);
|
||||
// Unmount ramdisk.
|
||||
f_mount(NULL, "ram:", 1);
|
||||
|
||||
// Format as exFAT w/ 32KB cluster with no MBR.
|
||||
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);
|
||||
|
||||
// Mount ramdisk.
|
||||
if (!res)
|
||||
res = f_mount(ram_fs, "ram:", 1);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf)
|
||||
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
|
||||
u32 bytes_count = sector_count << 9;
|
||||
|
||||
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
|
||||
if ((sector_off - RAM_DISK_ADDR) > disk_size)
|
||||
return 1;
|
||||
|
||||
memcpy(buf, (void *)sector_off, bytes_count);
|
||||
@@ -58,7 +75,7 @@ int ram_disk_write(u32 sector, u32 sector_count, const void *buf)
|
||||
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
|
||||
u32 bytes_count = sector_count << 9;
|
||||
|
||||
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
|
||||
if ((sector_off - RAM_DISK_ADDR) > disk_size)
|
||||
return 1;
|
||||
|
||||
memcpy((void *)sector_off, buf, bytes_count);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Ramdisk driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* 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,
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#define RAMDISK_CLUSTER_SZ 32768
|
||||
|
||||
int ram_disk_init(FATFS *ram_fs);
|
||||
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size);
|
||||
int ram_disk_read(u32 sector, u32 sector_count, void *buf);
|
||||
int ram_disk_write(u32 sector, u32 sector_count, const void *buf);
|
||||
|
||||
|
||||
121
bdk/storage/sd.h
121
bdk/storage/sd.h
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2021 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
|
||||
@@ -14,60 +14,79 @@
|
||||
/* SD commands type argument response */
|
||||
/* class 0 */
|
||||
/* This is basically the same command as for MMC with some quirks. */
|
||||
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
||||
|
||||
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
||||
/* class 10 */
|
||||
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
||||
|
||||
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
||||
/* class 5 */
|
||||
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
||||
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
||||
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
||||
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
||||
|
||||
/* Application commands */
|
||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||
#define SD_APP_SD_STATUS 13 /* adtc R1 */
|
||||
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||
#define SD_APP_SET_CLR_CARD_DETECT 42
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||
#define SD_APP_SD_STATUS 13 /* adtc R1 */
|
||||
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||
#define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
|
||||
/* Application secure commands */
|
||||
#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */
|
||||
#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */
|
||||
#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */
|
||||
#define SD_APP_SECURE_ERASE 38 /* adtc R1b */
|
||||
#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */
|
||||
#define SD_APP_GET_MID 44 /* adtc R1 */
|
||||
#define SD_APP_SET_CER_RN1 45 /* adtc R1 */
|
||||
#define SD_APP_GET_CER_RN2 46 /* adtc R1 */
|
||||
#define SD_APP_SET_CER_RES2 47 /* adtc R1 */
|
||||
#define SD_APP_GET_CER_RES1 48 /* adtc R1 */
|
||||
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
|
||||
|
||||
/* OCR bit definitions */
|
||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
|
||||
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
|
||||
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
|
||||
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
|
||||
|
||||
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||
#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
|
||||
|
||||
/*
|
||||
* SD_SWITCH argument format:
|
||||
*
|
||||
* [31] Check (0) or switch (1)
|
||||
* [30:24] Reserved (0)
|
||||
* [23:20] Function group 6
|
||||
* [19:16] Function group 5
|
||||
* [15:12] Function group 4
|
||||
* [11:8] Function group 3
|
||||
* [7:4] Function group 2
|
||||
* [3:0] Function group 1
|
||||
*/
|
||||
* SD_SWITCH argument format:
|
||||
*
|
||||
* [31] Check (0) or switch (1)
|
||||
* [30:24] Reserved (0)
|
||||
* [23:20] Function group 6
|
||||
* [19:16] Function group 5
|
||||
* [15:12] Function group 4
|
||||
* [11:8] Function group 3
|
||||
* [7:4] Function group 2
|
||||
* [3:0] Function group 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* SD_SEND_IF_COND argument format:
|
||||
*
|
||||
* [31:12] Reserved (0)
|
||||
* [11:8] Host Voltage Supply Flags
|
||||
* [7:0] Check Pattern (0xAA)
|
||||
*/
|
||||
* SD_SEND_IF_COND argument format:
|
||||
*
|
||||
* [31:12] Reserved (0)
|
||||
* [11:8] Host Voltage Supply Flags
|
||||
* [7:0] Check Pattern (0xAA)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCR field definitions
|
||||
*/
|
||||
* SD_APP_GET_MKB argument format:
|
||||
*
|
||||
* [31:24] Number of blocks to read (512 block size)
|
||||
* [23:16] MKB ID
|
||||
* [15:0] Block offset
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCR field definitions
|
||||
*/
|
||||
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
|
||||
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
|
||||
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
|
||||
@@ -75,14 +94,14 @@
|
||||
#define SD_SCR_BUS_WIDTH_4 (1<<2)
|
||||
|
||||
/*
|
||||
* SD bus widths
|
||||
*/
|
||||
* SD bus widths
|
||||
*/
|
||||
#define SD_BUS_WIDTH_1 0
|
||||
#define SD_BUS_WIDTH_4 2
|
||||
|
||||
/*
|
||||
* SD bus speeds
|
||||
*/
|
||||
* SD bus speeds
|
||||
*/
|
||||
#define UHS_SDR12_BUS_SPEED 0
|
||||
#define HIGH_SPEED_BUS_SPEED 1
|
||||
#define UHS_SDR25_BUS_SPEED 1
|
||||
@@ -112,19 +131,19 @@
|
||||
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
|
||||
|
||||
/*
|
||||
* SD_SWITCH mode
|
||||
*/
|
||||
* SD_SWITCH mode
|
||||
*/
|
||||
#define SD_SWITCH_CHECK 0
|
||||
#define SD_SWITCH_SET 1
|
||||
|
||||
/*
|
||||
* SD_SWITCH function groups
|
||||
*/
|
||||
* SD_SWITCH function groups
|
||||
*/
|
||||
#define SD_SWITCH_GRP_ACCESS 0
|
||||
|
||||
/*
|
||||
* SD_SWITCH access modes
|
||||
*/
|
||||
* SD_SWITCH access modes
|
||||
*/
|
||||
#define SD_SWITCH_ACCESS_DEF 0
|
||||
#define SD_SWITCH_ACCESS_HS 1
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -42,8 +42,8 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||
}
|
||||
|
||||
/*
|
||||
* Common functions for SD and MMC.
|
||||
*/
|
||||
* Common functions for SD and MMC.
|
||||
*/
|
||||
|
||||
static int _sdmmc_storage_check_card_status(u32 res)
|
||||
{
|
||||
@@ -88,20 +88,20 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u
|
||||
|
||||
static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
|
||||
|
||||
return sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL);
|
||||
return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL);
|
||||
}
|
||||
|
||||
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
|
||||
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
|
||||
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -111,14 +111,14 @@ static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
|
||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
|
||||
}
|
||||
|
||||
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
|
||||
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
|
||||
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -139,12 +139,70 @@ static int _sdmmc_storage_check_status(sdmmc_storage_t *storage)
|
||||
return _sdmmc_storage_get_status(storage, &tmp, 0);
|
||||
}
|
||||
|
||||
int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_62_CMD, arg, SDMMC_RSP_TYPE_1, 1);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
|
||||
return 0;
|
||||
|
||||
u32 resp;
|
||||
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1);
|
||||
|
||||
resp = -1;
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
while (resp != (R1_READY_FOR_DATA | R1_STATE(R1_STATE_TRAN)))
|
||||
{
|
||||
_sdmmc_storage_get_status(storage, &resp, 0);
|
||||
|
||||
if (get_tmr_ms() > timeout)
|
||||
break;
|
||||
}
|
||||
|
||||
return _sdmmc_storage_check_card_status(resp);
|
||||
}
|
||||
|
||||
int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf)
|
||||
{
|
||||
// Request health report.
|
||||
if (!sdmmc_storage_execute_vendor_cmd(storage, MMC_SANDISK_HEALTH_REPORT))
|
||||
return 2;
|
||||
|
||||
u32 tmp = 0;
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_req_t reqbuf;
|
||||
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_63_CMD, 0, SDMMC_RSP_TYPE_1, 0); // similar to CMD17 with arg 0x0.
|
||||
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.blksize = 512;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
u32 blkcnt_out;
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, &blkcnt_out))
|
||||
{
|
||||
sdmmc_stop_transmission(storage->sdmmc, &tmp);
|
||||
_sdmmc_storage_get_status(storage, &tmp, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
||||
{
|
||||
u32 tmp = 0;
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_req_t reqbuf;
|
||||
|
||||
// If SDSC convert block address to byte address.
|
||||
if (!storage->has_sector_access)
|
||||
sector <<= 9;
|
||||
|
||||
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
|
||||
|
||||
reqbuf.buf = buf;
|
||||
@@ -152,7 +210,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
||||
reqbuf.blksize = 512;
|
||||
reqbuf.is_write = is_write;
|
||||
reqbuf.is_multi_block = 1;
|
||||
reqbuf.is_auto_cmd12 = 1;
|
||||
reqbuf.is_auto_stop_trn = 1;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
|
||||
{
|
||||
@@ -288,25 +346,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
|
||||
|
||||
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
|
||||
{
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
|
||||
u32 arg = 0;
|
||||
switch (power)
|
||||
{
|
||||
case SDMMC_POWER_1_8:
|
||||
arg = SD_OCR_CCS | SD_OCR_VDD_18;
|
||||
arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
|
||||
break;
|
||||
|
||||
case SDMMC_POWER_3_3:
|
||||
arg = SD_OCR_CCS | SD_OCR_VDD_27_34;
|
||||
arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
|
||||
@@ -316,15 +374,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
|
||||
{
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
|
||||
while (1)
|
||||
while (true)
|
||||
{
|
||||
u32 cond = 0;
|
||||
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
|
||||
break;
|
||||
|
||||
// Check if power up is done.
|
||||
if (cond & MMC_CARD_BUSY)
|
||||
{
|
||||
if (cond & SD_OCR_CCS)
|
||||
// Check if card is high capacity.
|
||||
if (cond & MMC_CARD_CCS)
|
||||
storage->has_sector_access = 1;
|
||||
|
||||
return 1;
|
||||
@@ -362,7 +422,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
case 3: /* MMC v3.1 - v3.3 */
|
||||
case 4: /* MMC v4 */
|
||||
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
||||
storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2);
|
||||
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
|
||||
storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
|
||||
storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
|
||||
@@ -390,13 +449,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
|
||||
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 *raw_csd = (u32 *)&(storage->raw_csd);
|
||||
u32 *raw_csd = (u32 *)storage->raw_csd;
|
||||
|
||||
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
|
||||
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
|
||||
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
|
||||
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
|
||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||
storage->sec_cnt = storage->csd.capacity;
|
||||
}
|
||||
|
||||
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
||||
@@ -407,16 +467,26 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
||||
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
|
||||
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
|
||||
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
|
||||
storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
||||
storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
|
||||
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
|
||||
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
|
||||
//storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
|
||||
//storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
|
||||
//storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
|
||||
|
||||
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
|
||||
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
|
||||
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
|
||||
|
||||
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
||||
storage->ext_csd.cache_size =
|
||||
buf[EXT_CSD_CACHE_SIZE] |
|
||||
(buf[EXT_CSD_CACHE_SIZE + 1] << 8) |
|
||||
(buf[EXT_CSD_CACHE_SIZE + 2] << 16) |
|
||||
(buf[EXT_CSD_CACHE_SIZE + 3] << 24);
|
||||
storage->ext_csd.max_enh_mult =
|
||||
(buf[EXT_CSD_MAX_ENH_SIZE_MULT] |
|
||||
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) |
|
||||
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) *
|
||||
buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE];
|
||||
|
||||
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
||||
}
|
||||
|
||||
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
||||
@@ -430,7 +500,7 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
@@ -559,19 +629,21 @@ out:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
|
||||
{
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2)))
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK)))
|
||||
return 0;
|
||||
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
}
|
||||
*/
|
||||
|
||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
||||
{
|
||||
memset(storage, 0, sizeof(sdmmc_storage_t));
|
||||
storage->sdmmc = sdmmc;
|
||||
storage->rca = 2; //TODO: this could be a config item.
|
||||
storage->rca = 2; // Set default device address. This could be a config item.
|
||||
|
||||
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
|
||||
return 0;
|
||||
@@ -587,7 +659,7 @@ DPRINTF("[MMC] went to idle state\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] got op cond\n");
|
||||
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
||||
if (!_sdmmc_storage_get_cid(storage))
|
||||
return 0;
|
||||
DPRINTF("[MMC] got cid\n");
|
||||
|
||||
@@ -595,7 +667,7 @@ DPRINTF("[MMC] got cid\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] set relative addr\n");
|
||||
|
||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
||||
if (!_sdmmc_storage_get_csd(storage))
|
||||
return 0;
|
||||
DPRINTF("[MMC] got csd\n");
|
||||
_mmc_storage_parse_csd(storage);
|
||||
@@ -612,13 +684,9 @@ DPRINTF("[MMC] card selected\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] set blocklen to 512\n");
|
||||
|
||||
u32 *csd = (u32 *)storage->raw_csd;
|
||||
//Check system specification version, only version 4.0 and later support below features.
|
||||
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
|
||||
{
|
||||
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
|
||||
// Check system specification version, only version 4.0 and later support below features.
|
||||
if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_mmc_storage_switch_buswidth(storage, bus_width))
|
||||
return 0;
|
||||
@@ -628,21 +696,20 @@ DPRINTF("[MMC] switched buswidth\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] got ext_csd\n");
|
||||
|
||||
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
|
||||
_mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
|
||||
//gfx_hexdump(0, ext_csd, 512);
|
||||
|
||||
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status.
|
||||
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end().
|
||||
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
|
||||
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
|
||||
/*
|
||||
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
|
||||
{
|
||||
_mmc_storage_enable_bkops(storage);
|
||||
DPRINTF("[MMC] BKOPS enabled\n");
|
||||
}
|
||||
*/
|
||||
|
||||
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
|
||||
return 0;
|
||||
DPRINTF("[MMC] succesfully switched to HS mode\n");
|
||||
DPRINTF("[MMC] successfully switched to HS mode\n");
|
||||
|
||||
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
||||
|
||||
@@ -665,16 +732,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
|
||||
}
|
||||
|
||||
/*
|
||||
* SD specific functions.
|
||||
*/
|
||||
* SD specific functions.
|
||||
*/
|
||||
|
||||
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
|
||||
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out)
|
||||
{
|
||||
u32 tmp;
|
||||
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
|
||||
return 0;
|
||||
|
||||
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out);
|
||||
return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out);
|
||||
}
|
||||
|
||||
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
|
||||
@@ -685,67 +752,70 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
|
||||
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
|
||||
}
|
||||
|
||||
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage)
|
||||
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 1; // The SD Card is version 1.X
|
||||
{
|
||||
*is_sdsc = 1; // The SD Card is version 1.X
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Card version is >= 2.0, parse results.
|
||||
// For Card version >= 2.0, parse results.
|
||||
u32 resp = 0;
|
||||
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5))
|
||||
return 2; // Failed.
|
||||
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
|
||||
|
||||
// Check if VHD was accepted and pattern was properly returned.
|
||||
if ((resp & 0xFFF) == vhd_pattern)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
// Failed.
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_uhs_support)
|
||||
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
// Support for Current > 150mA
|
||||
u32 arg = !is_version_1 ? SD_OCR_XPC : 0;
|
||||
u32 arg = !is_sdsc ? SD_OCR_XPC : 0;
|
||||
// Support for handling block-addressed SDHC cards
|
||||
arg |= !is_version_1 ? SD_OCR_CCS : 0;
|
||||
arg |= !is_sdsc ? SD_OCR_CCS : 0;
|
||||
// Support for 1.8V
|
||||
arg |= (bus_uhs_support && !is_version_1) ? SD_OCR_S18R : 0;
|
||||
arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
|
||||
// This is needed for most cards. Do not set bit7 even if 1.8V is supported.
|
||||
arg |= SD_OCR_VDD_32_33;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_version_1 ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
|
||||
}
|
||||
|
||||
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_uhs_support)
|
||||
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
|
||||
{
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
|
||||
while (1)
|
||||
while (true)
|
||||
{
|
||||
u32 cond = 0;
|
||||
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support))
|
||||
if (!_sd_storage_get_op_cond_once(storage, &cond, is_sdsc, bus_uhs_support))
|
||||
break;
|
||||
if (cond & MMC_CARD_BUSY)
|
||||
|
||||
// Check if power up is done.
|
||||
if (cond & SD_OCR_BUSY)
|
||||
{
|
||||
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
|
||||
|
||||
// Check if card is high capacity.
|
||||
if (cond & SD_OCR_CCS)
|
||||
storage->has_sector_access = 1;
|
||||
|
||||
// Check if card supports 1.8V signaling.
|
||||
if (cond & SD_ROCR_S18A && bus_uhs_support)
|
||||
{
|
||||
//The low voltage regulator configuration is valid for SDMMC1 only.
|
||||
if (storage->sdmmc->id == SDMMC_1 &&
|
||||
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
||||
// Switch to 1.8V signaling.
|
||||
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
||||
{
|
||||
if (!sdmmc_enable_low_voltage(storage->sdmmc))
|
||||
return 0;
|
||||
@@ -776,7 +846,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
|
||||
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
|
||||
while (1)
|
||||
while (true)
|
||||
{
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
break;
|
||||
@@ -809,8 +879,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
|
||||
|
||||
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
|
||||
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
|
||||
|
||||
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
|
||||
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
|
||||
/* Check if Physical Layer Spec v3.0 is supported */
|
||||
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
|
||||
if (storage->scr.sda_spec3)
|
||||
storage->scr.cmds = unstuff_bits(resp, 32, 2);
|
||||
@@ -827,7 +898,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
@@ -859,7 +930,7 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
@@ -883,7 +954,7 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
@@ -1064,7 +1135,7 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
|
||||
}
|
||||
|
||||
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
|
||||
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 au_size = storage->ssr.uhs_au_size;
|
||||
|
||||
@@ -1104,39 +1175,24 @@ u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
|
||||
|
||||
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
{
|
||||
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups
|
||||
// unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups.
|
||||
u32 raw_ssr1[4];
|
||||
u32 raw_ssr2[4];
|
||||
|
||||
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12];
|
||||
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8];
|
||||
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
|
||||
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
|
||||
|
||||
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
|
||||
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
|
||||
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
|
||||
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
|
||||
memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
|
||||
memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
|
||||
|
||||
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
|
||||
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
|
||||
|
||||
switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
|
||||
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
|
||||
switch(speed_class)
|
||||
{
|
||||
case 0:
|
||||
storage->ssr.speed_class = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
storage->ssr.speed_class = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
storage->ssr.speed_class = 4;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
storage->ssr.speed_class = 6;
|
||||
storage->ssr.speed_class = speed_class << 1;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
@@ -1144,19 +1200,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
break;
|
||||
|
||||
default:
|
||||
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
|
||||
storage->ssr.speed_class = speed_class;
|
||||
break;
|
||||
}
|
||||
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
|
||||
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
|
||||
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
|
||||
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
||||
|
||||
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
||||
|
||||
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
|
||||
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
|
||||
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
|
||||
}
|
||||
|
||||
static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
|
||||
@@ -1167,11 +1222,11 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
|
||||
{
|
||||
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
||||
DPRINTF("[SD] ssr: Not supported\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1180,14 +1235,16 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
||||
|
||||
u32 tmp = 0;
|
||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||
//Prepare buffer for unstuff_bits
|
||||
for (int i = 0; i < 64; i+=4)
|
||||
|
||||
// Convert buffer to LE.
|
||||
for (int i = 0; i < 64; i += 4)
|
||||
{
|
||||
storage->raw_ssr[i + 3] = buf[i];
|
||||
storage->raw_ssr[i + 2] = buf[i + 1];
|
||||
storage->raw_ssr[i + 1] = buf[i + 2];
|
||||
storage->raw_ssr[i] = buf[i + 3];
|
||||
}
|
||||
|
||||
_sd_storage_parse_ssr(storage);
|
||||
//gfx_hexdump(0, storage->raw_ssr, 64);
|
||||
|
||||
@@ -1198,18 +1255,18 @@ static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 *raw_cid = (u32 *)&(storage->raw_cid);
|
||||
|
||||
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
||||
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
|
||||
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
|
||||
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
|
||||
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
|
||||
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
|
||||
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
|
||||
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
|
||||
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
||||
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
|
||||
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
||||
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
|
||||
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
||||
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
|
||||
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
|
||||
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
|
||||
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
|
||||
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
|
||||
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
|
||||
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
|
||||
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
||||
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
|
||||
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
|
||||
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
||||
}
|
||||
|
||||
static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
@@ -1224,6 +1281,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
{
|
||||
case 0:
|
||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@@ -1231,7 +1289,13 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
storage->csd.capacity = storage->csd.c_size << 10;
|
||||
storage->csd.read_blkbits = 9;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
|
||||
break;
|
||||
}
|
||||
|
||||
storage->sec_cnt = storage->csd.capacity;
|
||||
}
|
||||
|
||||
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
|
||||
@@ -1261,8 +1325,10 @@ void sdmmc_storage_init_wait_sd()
|
||||
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
||||
{
|
||||
int is_version_1 = 0;
|
||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
u32 tmp = 0;
|
||||
int is_sdsc = 0;
|
||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
||||
|
||||
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
|
||||
|
||||
@@ -1282,18 +1348,15 @@ DPRINTF("[SD] after init\n");
|
||||
return 0;
|
||||
DPRINTF("[SD] went to idle state\n");
|
||||
|
||||
is_version_1 = _sd_storage_send_if_cond(storage);
|
||||
if (is_version_1 == 2) // Failed.
|
||||
if (!_sd_storage_send_if_cond(storage, &is_sdsc))
|
||||
return 0;
|
||||
DPRINTF("[SD] after send if cond\n");
|
||||
|
||||
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
||||
|
||||
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support))
|
||||
if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
|
||||
return 0;
|
||||
DPRINTF("[SD] got op cond\n");
|
||||
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
||||
if (!_sdmmc_storage_get_cid(storage))
|
||||
return 0;
|
||||
DPRINTF("[SD] got cid\n");
|
||||
_sd_storage_parse_cid(storage);
|
||||
@@ -1302,30 +1365,16 @@ DPRINTF("[SD] got cid\n");
|
||||
return 0;
|
||||
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
|
||||
|
||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
||||
if (!_sdmmc_storage_get_csd(storage))
|
||||
return 0;
|
||||
DPRINTF("[SD] got csd\n");
|
||||
|
||||
//Parse CSD.
|
||||
_sd_storage_parse_csd(storage);
|
||||
switch (storage->csd.structure)
|
||||
{
|
||||
case 0:
|
||||
storage->sec_cnt = storage->csd.capacity;
|
||||
break;
|
||||
case 1:
|
||||
storage->sec_cnt = storage->csd.c_size << 10;
|
||||
break;
|
||||
default:
|
||||
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!storage->is_low_voltage)
|
||||
{
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
|
||||
return 0;
|
||||
DPRINTF("[SD] after setup clock\n");
|
||||
DPRINTF("[SD] after setup default clock\n");
|
||||
}
|
||||
|
||||
if (!_sdmmc_storage_select_card(storage))
|
||||
@@ -1336,19 +1385,17 @@ DPRINTF("[SD] card selected\n");
|
||||
return 0;
|
||||
DPRINTF("[SD] set blocklen to 512\n");
|
||||
|
||||
u32 tmp = 0;
|
||||
// Disconnect Card Detect resistor from DAT3.
|
||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
|
||||
return 0;
|
||||
DPRINTF("[SD] cleared card detect\n");
|
||||
|
||||
if (!_sd_storage_get_scr(storage, buf))
|
||||
return 0;
|
||||
|
||||
//gfx_hexdump(0, storage->raw_scr, 8);
|
||||
DPRINTF("[SD] got scr\n");
|
||||
|
||||
// Check if card supports a wider bus and if it's not SD Version 1.X
|
||||
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
|
||||
// If card supports a wider bus and if it's not SD Version 1.0 switch bus width.
|
||||
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
|
||||
{
|
||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
|
||||
return 0;
|
||||
@@ -1367,10 +1414,8 @@ DPRINTF("[SD] SD does not support wide bus width\n");
|
||||
if (!_sd_storage_enable_uhs_low_volt(storage, type, buf))
|
||||
return 0;
|
||||
DPRINTF("[SD] enabled UHS\n");
|
||||
|
||||
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
||||
}
|
||||
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF)) // Not default speed and not SD Version 1.x
|
||||
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
|
||||
{
|
||||
if (!_sd_storage_enable_hs_high_volt(storage, buf))
|
||||
return 0;
|
||||
@@ -1389,25 +1434,27 @@ DPRINTF("[SD] enabled HS\n");
|
||||
}
|
||||
|
||||
// Parse additional card info from sd status.
|
||||
if (_sd_storage_get_ssr(storage, buf))
|
||||
if (sd_storage_get_ssr(storage, buf))
|
||||
{
|
||||
DPRINTF("[SD] got sd status\n");
|
||||
}
|
||||
|
||||
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
||||
|
||||
storage->initialized = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gamecard specific functions.
|
||||
*/
|
||||
* Gamecard specific functions.
|
||||
*/
|
||||
|
||||
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
||||
{
|
||||
u32 resp;
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1);
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1);
|
||||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
@@ -1415,7 +1462,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 1;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -30,18 +30,93 @@ typedef enum _sdmmc_type
|
||||
|
||||
EMMC_GPP = 0,
|
||||
EMMC_BOOT0 = 1,
|
||||
EMMC_BOOT1 = 2
|
||||
EMMC_BOOT1 = 2,
|
||||
EMMC_RPMB = 3
|
||||
} sdmmc_type;
|
||||
|
||||
typedef struct _mmc_sandisk_advanced_report_t
|
||||
{
|
||||
u32 power_inits;
|
||||
|
||||
u32 max_erase_cycles_sys;
|
||||
u32 max_erase_cycles_slc;
|
||||
u32 max_erase_cycles_mlc;
|
||||
|
||||
u32 min_erase_cycles_sys;
|
||||
u32 min_erase_cycles_slc;
|
||||
u32 min_erase_cycles_mlc;
|
||||
|
||||
u32 max_erase_cycles_euda;
|
||||
u32 min_erase_cycles_euda;
|
||||
u32 avg_erase_cycles_euda;
|
||||
u32 read_reclaim_cnt_euda;
|
||||
u32 bad_blocks_euda;
|
||||
|
||||
u32 pre_eol_euda;
|
||||
u32 pre_eol_sys;
|
||||
u32 pre_eol_mlc;
|
||||
|
||||
u32 uncorrectable_ecc;
|
||||
|
||||
u32 temperature_now;
|
||||
u32 temperature_min;
|
||||
u32 temperature_max;
|
||||
|
||||
u32 health_pct_euda;
|
||||
u32 health_pct_sys;
|
||||
u32 health_pct_mlc;
|
||||
|
||||
u32 unk0;
|
||||
u32 unk1;
|
||||
u32 unk2;
|
||||
|
||||
u32 reserved[78];
|
||||
} mmc_sandisk_advanced_report_t;
|
||||
|
||||
typedef struct _mmc_sandisk_report_t
|
||||
{
|
||||
u32 avg_erase_cycles_sys;
|
||||
u32 avg_erase_cycles_slc;
|
||||
u32 avg_erase_cycles_mlc;
|
||||
|
||||
u32 read_reclaim_cnt_sys;
|
||||
u32 read_reclaim_cnt_slc;
|
||||
u32 read_reclaim_cnt_mlc;
|
||||
|
||||
u32 bad_blocks_factory;
|
||||
u32 bad_blocks_sys;
|
||||
u32 bad_blocks_slc;
|
||||
u32 bad_blocks_mlc;
|
||||
|
||||
u32 fw_updates_cnt;
|
||||
|
||||
u8 fw_update_date[12];
|
||||
u8 fw_update_time[8];
|
||||
|
||||
u32 total_writes_100mb;
|
||||
u32 vdrops;
|
||||
u32 vdroops;
|
||||
|
||||
u32 vdrops_failed_data_rec;
|
||||
u32 vdrops_data_rec_ops;
|
||||
|
||||
u32 total_writes_slc_100mb;
|
||||
u32 total_writes_mlc_100mb;
|
||||
|
||||
u32 mlc_bigfile_mode_limit_exceeded;
|
||||
u32 avg_erase_cycles_hybrid;
|
||||
|
||||
mmc_sandisk_advanced_report_t advanced;
|
||||
} mmc_sandisk_report_t;
|
||||
|
||||
typedef struct _mmc_cid
|
||||
{
|
||||
u32 manfid;
|
||||
u8 prod_name[8];
|
||||
u8 card_bga;
|
||||
u8 prv;
|
||||
u32 serial;
|
||||
u16 oemid;
|
||||
u16 year;
|
||||
u8 prv;
|
||||
u8 hwrev;
|
||||
u8 fwrev;
|
||||
u8 month;
|
||||
@@ -65,19 +140,20 @@ typedef struct _mmc_csd
|
||||
|
||||
typedef struct _mmc_ext_csd
|
||||
{
|
||||
u32 sectors;
|
||||
int bkops; /* background support bit */
|
||||
int bkops_en; /* manual bkops enable bit */
|
||||
//u8 bkops; /* background support bit */
|
||||
//u8 bkops_en; /* manual bkops enable bit */
|
||||
//u8 bkops_status; /* 246 */
|
||||
u8 rev;
|
||||
u8 ext_struct; /* 194 */
|
||||
u8 card_type; /* 196 */
|
||||
u8 bkops_status; /* 246 */
|
||||
u8 pre_eol_info;
|
||||
u8 dev_life_est_a;
|
||||
u8 dev_life_est_b;
|
||||
u8 boot_mult;
|
||||
u8 rpmb_mult;
|
||||
u16 dev_version;
|
||||
u32 cache_size;
|
||||
u32 max_enh_mult;
|
||||
} mmc_ext_csd_t;
|
||||
|
||||
typedef struct _sd_scr
|
||||
@@ -90,13 +166,13 @@ typedef struct _sd_scr
|
||||
|
||||
typedef struct _sd_ssr
|
||||
{
|
||||
u8 bus_width;
|
||||
u8 speed_class;
|
||||
u8 uhs_grade;
|
||||
u8 video_class;
|
||||
u8 app_class;
|
||||
u8 au_size;
|
||||
u8 uhs_au_size;
|
||||
u8 bus_width;
|
||||
u8 speed_class;
|
||||
u8 uhs_grade;
|
||||
u8 video_class;
|
||||
u8 app_class;
|
||||
u8 au_size;
|
||||
u8 uhs_au_size;
|
||||
u32 protected_size;
|
||||
} sd_ssr_t;
|
||||
|
||||
@@ -130,6 +206,10 @@ void sdmmc_storage_init_wait_sd();
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||
|
||||
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage);
|
||||
int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg);
|
||||
int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf);
|
||||
|
||||
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
|
||||
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
|
||||
*blkcnt_out = blkcnt;
|
||||
|
||||
u32 trnmode = SDHCI_TRNS_DMA;
|
||||
|
||||
// Set mulitblock request.
|
||||
if (req->is_multi_block)
|
||||
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
|
||||
|
||||
// Set request direction.
|
||||
if (!req->is_write)
|
||||
trnmode |= SDHCI_TRNS_READ;
|
||||
if (req->is_auto_cmd12)
|
||||
trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12;
|
||||
|
||||
// Automatic send of stop transmission or set block count cmd.
|
||||
if (req->is_auto_stop_trn)
|
||||
trnmode |= SDHCI_TRNS_AUTO_CMD12;
|
||||
//else if (req->is_auto_set_blkcnt)
|
||||
// trnmode |= SDHCI_TRNS_AUTO_CMD23;
|
||||
|
||||
sdmmc->regs->trnmod = trnmode;
|
||||
|
||||
@@ -1025,12 +1033,10 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
||||
}
|
||||
|
||||
int result = _sdmmc_wait_response(sdmmc);
|
||||
if (!result)
|
||||
{
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
if (!result)
|
||||
EPRINTF("SDMMC: Transfer timeout!");
|
||||
#endif
|
||||
}
|
||||
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
||||
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
|
||||
if (result)
|
||||
@@ -1039,22 +1045,18 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
||||
{
|
||||
sdmmc->expected_rsp_type = cmd->rsp_type;
|
||||
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type);
|
||||
if (!result)
|
||||
{
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
if (!result)
|
||||
EPRINTF("SDMMC: Unknown response type!");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (req && result)
|
||||
{
|
||||
result = _sdmmc_update_dma(sdmmc);
|
||||
if (!result)
|
||||
{
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
if (!result)
|
||||
EPRINTF("SDMMC: DMA Update failed!");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1070,19 +1072,17 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
||||
if (blkcnt_out)
|
||||
*blkcnt_out = blkcnt;
|
||||
|
||||
if (req->is_auto_cmd12)
|
||||
if (req->is_auto_stop_trn)
|
||||
sdmmc->rsp3 = sdmmc->regs->rspreg3;
|
||||
}
|
||||
|
||||
if (cmd->check_busy || req)
|
||||
{
|
||||
result = _sdmmc_wait_card_busy(sdmmc);
|
||||
if (!result)
|
||||
{
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
if (!result)
|
||||
EPRINTF("SDMMC: Busy timeout!");
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1200,8 +1200,8 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
|
||||
usleep(10000);
|
||||
|
||||
// Enable SD card IO power.
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000);
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 1);
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO2, 3300000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, true);
|
||||
usleep(1000);
|
||||
|
||||
// Set pad slew codes to get good quality clock.
|
||||
@@ -1332,19 +1332,6 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p
|
||||
|
||||
void sdmmc1_disable_power()
|
||||
{
|
||||
#if 0
|
||||
// Ensure regulator is into default voltage.
|
||||
if (PMC(APBDEV_PMC_PWR_DET_VAL) & PMC_PWR_DET_SDMMC1_IO_EN)
|
||||
{
|
||||
// Switch to 1.8V and wait for regulator to stabilize.
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
|
||||
usleep(150);
|
||||
|
||||
// Inform IO pads that we switched to 1.8V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN);
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
}
|
||||
#endif
|
||||
// T210B01 WAR: Clear pull down from CLK pad.
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK;
|
||||
|
||||
@@ -1352,7 +1339,7 @@ void sdmmc1_disable_power()
|
||||
_sdmmc_config_sdmmc1_pads(true);
|
||||
|
||||
// Disable SD card IO power regulator.
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 0);
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, false);
|
||||
usleep(4000);
|
||||
|
||||
// Disable SD card IO power pin.
|
||||
@@ -1384,12 +1371,12 @@ void sdmmc_end(sdmmc_t *sdmmc)
|
||||
_sdmmc_sd_clock_disable(sdmmc);
|
||||
// Disable SDMMC power.
|
||||
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
|
||||
_sdmmc_commit_changes(sdmmc);
|
||||
|
||||
// Disable SD card power.
|
||||
if (sdmmc->id == SDMMC_1)
|
||||
sdmmc1_disable_power();
|
||||
|
||||
_sdmmc_commit_changes(sdmmc);
|
||||
clock_sdmmc_disable(sdmmc->id);
|
||||
sdmmc->clock_stopped = 1;
|
||||
}
|
||||
@@ -1441,7 +1428,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
|
||||
_sdmmc_commit_changes(sdmmc);
|
||||
|
||||
// Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed.
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO2, 1800000);
|
||||
usleep(150);
|
||||
|
||||
// Inform IO pads that we switched to 1.8V.
|
||||
|
||||
@@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t
|
||||
u32 num_sectors;
|
||||
int is_write;
|
||||
int is_multi_block;
|
||||
int is_auto_cmd12;
|
||||
int is_auto_stop_trn;
|
||||
} sdmmc_req_t;
|
||||
|
||||
int sdmmc_get_io_power(sdmmc_t *sdmmc);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Fan driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <thermal/fan.h>
|
||||
#include <power/regulator_5v.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <soc/t210.h>
|
||||
@@ -26,11 +27,22 @@
|
||||
void set_fan_duty(u32 duty)
|
||||
{
|
||||
static bool fan_init = false;
|
||||
static u16 curr_duty = -1;
|
||||
static u16 curr_duty = -1;
|
||||
|
||||
if (duty > 236)
|
||||
duty = 236;
|
||||
|
||||
if (curr_duty == duty)
|
||||
return;
|
||||
|
||||
curr_duty = duty;
|
||||
|
||||
//! TODO: Add HOAG/AULA support.
|
||||
u32 hw_type = fuse_read_hw_type();
|
||||
if (hw_type != FUSE_NX_HW_TYPE_ICOSA &&
|
||||
hw_type != FUSE_NX_HW_TYPE_IOWA)
|
||||
return;
|
||||
|
||||
if (!fan_init)
|
||||
{
|
||||
// Fan tachometer.
|
||||
@@ -46,9 +58,6 @@ void set_fan_duty(u32 duty)
|
||||
fan_init = true;
|
||||
}
|
||||
|
||||
if (duty > 236)
|
||||
duty = 236;
|
||||
|
||||
// Inverted polarity.
|
||||
u32 inv_duty = 236 - duty;
|
||||
|
||||
@@ -56,7 +65,7 @@ void set_fan_duty(u32 duty)
|
||||
if (inv_duty == 236)
|
||||
{
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%.
|
||||
regulator_disable_5v(REGULATOR_5V_FAN);
|
||||
regulator_5v_disable(REGULATOR_5V_FAN);
|
||||
|
||||
// Disable fan.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) =
|
||||
@@ -65,29 +74,26 @@ void set_fan_duty(u32 duty)
|
||||
else // Set PWM duty.
|
||||
{
|
||||
// Fan power supply.
|
||||
regulator_enable_5v(REGULATOR_5V_FAN);
|
||||
regulator_5v_enable(REGULATOR_5V_FAN);
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (inv_duty << 16);
|
||||
|
||||
// Enable fan.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1.
|
||||
}
|
||||
|
||||
curr_duty = duty;
|
||||
}
|
||||
|
||||
void get_fan_speed(u32 *duty, u32 *rpm)
|
||||
{
|
||||
if (rpm)
|
||||
{
|
||||
u32 irq_count = 1;
|
||||
u32 irq_count = 0;
|
||||
bool should_read = true;
|
||||
bool irq_val = 0;
|
||||
|
||||
// Poll irqs for 2 seconds.
|
||||
int timer = get_tmr_us() + 1000000;
|
||||
while (timer - get_tmr_us())
|
||||
// Poll irqs for 2 seconds. (5 seconds for accurate count).
|
||||
int timer = get_tmr_us() + 2000000;
|
||||
while ((timer - get_tmr_us()) > 0)
|
||||
{
|
||||
irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
|
||||
bool irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
|
||||
if (irq_val && should_read)
|
||||
{
|
||||
irq_count++;
|
||||
@@ -97,8 +103,11 @@ void get_fan_speed(u32 *duty, u32 *rpm)
|
||||
should_read = true;
|
||||
}
|
||||
|
||||
// Halve the irq count.
|
||||
irq_count /= 2;
|
||||
|
||||
// Calculate rpm based on triggered interrupts.
|
||||
*rpm = 60000000 / ((1000000 * 2) / irq_count);
|
||||
*rpm = irq_count * (60 / 2);
|
||||
}
|
||||
|
||||
if (duty)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
|
||||
*
|
||||
* 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,
|
||||
@@ -16,7 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/t210.h>
|
||||
#include <thermal/tmp451.h>
|
||||
|
||||
u16 tmp451_get_soc_temp(bool intenger)
|
||||
@@ -56,6 +58,20 @@ void tmp451_init()
|
||||
// Disable ALARM and Range to 0 - 127 oC.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80);
|
||||
|
||||
// Set remote sensor offsets based on SoC.
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||
{
|
||||
// Set offset to 0 oC for Erista.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0);
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set offset to -12.5 oC for Mariko.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0xF3); // - 13 oC.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0x80); // + 0.5 oC.
|
||||
}
|
||||
|
||||
// Set conversion rate to 32/s and make a read to update the reg.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9);
|
||||
tmp451_get_soc_temp(false);
|
||||
@@ -63,3 +79,9 @@ void tmp451_init()
|
||||
// Set rate to every 4 seconds.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2);
|
||||
}
|
||||
|
||||
void tmp451_end()
|
||||
{
|
||||
// Place into shutdown mode to conserve power.
|
||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0xC0);
|
||||
}
|
||||
|
||||
@@ -32,11 +32,15 @@
|
||||
#define TMP451_SOC_TMP_DEC_REG 0x10
|
||||
#define TMP451_PCB_TMP_DEC_REG 0x15
|
||||
|
||||
#define TMP451_SOC_TMP_OFH_REG 0x11
|
||||
#define TMP451_SOC_TMP_OFL_REG 0x12
|
||||
|
||||
// If input is false, the return value is packed. MSByte is the integer in oC
|
||||
// and the LSByte is the decimal point truncated to 2 decimal places.
|
||||
// Otherwise it's an integer oC.
|
||||
u16 tmp451_get_soc_temp(bool integer);
|
||||
u16 tmp451_get_pcb_temp(bool integer);
|
||||
void tmp451_init();
|
||||
void tmp451_end();
|
||||
|
||||
#endif /* __TMP451_H_ */
|
||||
|
||||
@@ -309,7 +309,7 @@ static bool _fts_touch_read(touchpad_report_t *rpt)
|
||||
|
||||
static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len)
|
||||
{
|
||||
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED);
|
||||
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED_CMD);
|
||||
if (status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!");
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2003-2008 Alan Stern
|
||||
* Copyright (c) 2009 Samsung Electronics
|
||||
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* 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,
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
#define UMS_SCSI_TRANSFER_512K (0x80000 >> UMS_DISK_LBA_SHIFT)
|
||||
|
||||
#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER >> UMS_DISK_LBA_SHIFT)
|
||||
#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER)
|
||||
|
||||
// Length of a SCSI Command Data Block.
|
||||
#define SCSI_MAX_CMD_SZ 16
|
||||
@@ -109,7 +109,7 @@
|
||||
#define SS_WRITE_ERROR 0x30C02
|
||||
#define SS_WRITE_PROTECTED 0x72700
|
||||
|
||||
#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */
|
||||
#define SK(x) ((u8) ((x) >> 16)) // Sense Key byte, etc.
|
||||
#define ASC(x) ((u8) ((x) >> 8))
|
||||
#define ASCQ(x) ((u8) (x))
|
||||
|
||||
@@ -121,6 +121,15 @@ enum ums_state {
|
||||
UMS_STATE_TERMINATED
|
||||
};
|
||||
|
||||
enum ums_result {
|
||||
UMS_RES_OK = 0,
|
||||
UMS_RES_IO_ERROR = -5,
|
||||
UMS_RES_TIMEOUT = -3,
|
||||
UMS_RES_PROT_FATAL = -4,
|
||||
UMS_RES_INVALID_ARG = -22
|
||||
};
|
||||
|
||||
|
||||
enum data_direction {
|
||||
DATA_DIR_UNKNOWN = 0,
|
||||
DATA_DIR_FROM_HOST,
|
||||
@@ -194,7 +203,7 @@ typedef struct _bulk_ctxt_t {
|
||||
typedef struct _usbd_gadget_ums_t {
|
||||
bulk_ctxt_t bulk_ctxt;
|
||||
|
||||
int cmnd_size;
|
||||
u32 cmnd_size;
|
||||
u8 cmnd[SCSI_MAX_CMD_SZ];
|
||||
|
||||
u32 lun_idx; // lun index
|
||||
@@ -208,6 +217,7 @@ typedef struct _usbd_gadget_ums_t {
|
||||
u32 tag;
|
||||
u32 residue;
|
||||
u32 usb_amount_left;
|
||||
bool cbw_req_queued;
|
||||
|
||||
u32 phase_error;
|
||||
u32 short_packet_received;
|
||||
@@ -283,21 +293,21 @@ static int ums_wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
/* usbd_set_ep_wedge(bulk_ctxt->bulk_in); */
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int ums_set_stall(u32 ep)
|
||||
{
|
||||
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL);
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int ums_clear_stall(u32 ep)
|
||||
{
|
||||
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR);
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static void ums_flush_endpoint(u32 ep)
|
||||
@@ -306,13 +316,13 @@ static void ums_flush_endpoint(u32 ep)
|
||||
usb_ops.usbd_flush_endpoint(ep);
|
||||
}
|
||||
|
||||
static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, bool sync)
|
||||
static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
|
||||
{
|
||||
if (ep == bulk_ctxt->bulk_in)
|
||||
{
|
||||
bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write(
|
||||
bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length,
|
||||
&bulk_ctxt->bulk_in_length_actual, sync);
|
||||
&bulk_ctxt->bulk_in_length_actual, sync_timeout);
|
||||
|
||||
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
@@ -322,14 +332,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED)
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP IN Buffer not aligned!");
|
||||
|
||||
if (sync)
|
||||
if (sync_timeout)
|
||||
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read(
|
||||
bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length,
|
||||
&bulk_ctxt->bulk_out_length_actual, sync);
|
||||
&bulk_ctxt->bulk_out_length_actual, sync_timeout);
|
||||
|
||||
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
@@ -339,7 +349,7 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED)
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP OUT Buffer not aligned!");
|
||||
|
||||
if (sync)
|
||||
if (sync_timeout)
|
||||
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
|
||||
}
|
||||
}
|
||||
@@ -359,12 +369,12 @@ static void _ums_transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk
|
||||
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
|
||||
}
|
||||
|
||||
static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep)
|
||||
static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
|
||||
{
|
||||
if (ep == bulk_ctxt->bulk_in)
|
||||
{
|
||||
bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_writing_finish(
|
||||
&bulk_ctxt->bulk_in_length_actual);
|
||||
&bulk_ctxt->bulk_in_length_actual, sync_timeout);
|
||||
|
||||
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
@@ -377,7 +387,7 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
else
|
||||
{
|
||||
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish(
|
||||
&bulk_ctxt->bulk_out_length_actual, 1000000);
|
||||
&bulk_ctxt->bulk_out_length_actual, sync_timeout);
|
||||
|
||||
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
@@ -446,20 +456,21 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
if (lba_offset >= ums->lun.num_sectors)
|
||||
{
|
||||
ums->set_text(ums->label, "#FF8000 Warn:# Read - Out of range! Host notified.");
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Check that request data size is not 0.
|
||||
u32 amount_left = ums->data_size_from_cmnd >> UMS_DISK_LBA_SHIFT;
|
||||
if (!amount_left)
|
||||
return -5; // I/O error. /* No default reply */
|
||||
return UMS_RES_IO_ERROR; // No default reply.
|
||||
|
||||
// Limit IO transfers based on request for faster concurrent reads.
|
||||
u32 max_io_transfer = (amount_left >= UMS_SCSI_TRANSFER_512K) ?
|
||||
@@ -488,7 +499,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
// Wait for the async USB transfer to finish.
|
||||
if (!first_read)
|
||||
_ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_in);
|
||||
_ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
|
||||
lba_offset += amount;
|
||||
amount_left -= amount;
|
||||
@@ -520,7 +531,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
sdmmc_buf += amount << UMS_DISK_LBA_SHIFT;
|
||||
}
|
||||
|
||||
return -5; // I/O error no default reply here. /* No default reply */
|
||||
return UMS_RES_IO_ERROR; // No default reply.
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -539,9 +550,10 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
if (ums->lun.ro)
|
||||
{
|
||||
ums->set_text(ums->label, "#FF8000 Warn:# Write - Read only! Host notified.");
|
||||
ums->lun.sense_data = SS_WRITE_PROTECTED;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (ums->cmnd[0] == SC_WRITE_6)
|
||||
@@ -555,41 +567,40 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that starting LBA is not past the end sector offset.
|
||||
if (lba_offset >= ums->lun.num_sectors)
|
||||
{
|
||||
ums->set_text(ums->label, "#FF8000 Warn:# Write - Out of range! Host notified.");
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Carry out the file writes */
|
||||
// Carry out the file writes.
|
||||
usb_lba_offset = lba_offset;
|
||||
amount_left_to_req = ums->data_size_from_cmnd;
|
||||
amount_left_to_write = ums->data_size_from_cmnd;
|
||||
|
||||
while (amount_left_to_write > 0)
|
||||
{
|
||||
|
||||
/* Queue a request for more data from the host */
|
||||
if (amount_left_to_req)
|
||||
// Queue a request for more data from the host.
|
||||
if (amount_left_to_req > 0)
|
||||
{
|
||||
|
||||
// Limit write to max supported read from EP OUT.
|
||||
amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER << UMS_DISK_LBA_SHIFT);
|
||||
amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER);
|
||||
|
||||
if (usb_lba_offset >= ums->lun.num_sectors) //////////Check if it works with concurrency
|
||||
if (usb_lba_offset >= ums->lun.num_sectors)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!");
|
||||
amount_left_to_req = 0;
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
ums->lun.sense_data_info = usb_lba_offset;
|
||||
ums->lun.info_valid = 1;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next buffer.
|
||||
@@ -631,12 +642,12 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
*/
|
||||
amount = MIN(amount, bulk_ctxt->bulk_out_length);
|
||||
|
||||
/* Don't write a partial block */
|
||||
// Don't write a partial block.
|
||||
amount -= (amount & 511);
|
||||
if (amount == 0)
|
||||
goto empty_write;
|
||||
|
||||
/* Perform the write */
|
||||
// Perform the write.
|
||||
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
|
||||
amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf))
|
||||
amount = 0;
|
||||
@@ -647,7 +658,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
|
||||
amount_left_to_write -= amount;
|
||||
ums->residue -= amount;
|
||||
|
||||
/* If an error occurred, report it and its position */
|
||||
// If an error occurred, report it and its position.
|
||||
if (!amount)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# SDMMC Write!");
|
||||
@@ -668,7 +679,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
|
||||
}
|
||||
}
|
||||
|
||||
return -5; // I/O error. /* No default reply */
|
||||
return UMS_RES_IO_ERROR; // No default reply.
|
||||
}
|
||||
|
||||
static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -677,9 +688,10 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
u32 lba_offset = get_array_be_to_le32(&ums->cmnd[2]);
|
||||
if (lba_offset >= ums->lun.num_sectors)
|
||||
{
|
||||
ums->set_text(ums->label, "#FF8000 Warn:# Verif - Out of range! Host notified.");
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// We allow DPO but we don't implement it. Check that nothing else is enabled.
|
||||
@@ -687,12 +699,12 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
u32 verification_length = get_array_be_to_le16(&ums->cmnd[7]);
|
||||
if (verification_length == 0)
|
||||
return -5; // I/O error. /* No default reply */
|
||||
return UMS_RES_IO_ERROR; // No default reply.
|
||||
|
||||
u32 amount;
|
||||
while (verification_length > 0)
|
||||
@@ -724,7 +736,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset);
|
||||
lba_offset += amount;
|
||||
verification_length -= amount;
|
||||
}
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -843,7 +855,7 @@ static int _scsi_read_capacity(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
put_array_le_to_be32(ums->lun.num_sectors - 1, &buf[0]); // Max logical block.
|
||||
@@ -866,14 +878,14 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (pc != 1) // Current cumulative values.
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
memset(buf, 0, 8);
|
||||
@@ -915,7 +927,7 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
put_array_le_to_be16(len - 4, &buf0[2]);
|
||||
@@ -938,14 +950,14 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (pc == 3)
|
||||
{
|
||||
ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Write the mode parameter header. Fixed values are: default
|
||||
@@ -995,10 +1007,10 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Store the mode data length */
|
||||
// Store the mode data length.
|
||||
if (ums->cmnd[0] == SC_MODE_SENSE_6)
|
||||
buf0[0] = len - 1;
|
||||
else
|
||||
@@ -1015,14 +1027,14 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
else if ((ums->cmnd[1] & ~0x01) != 0 || // Mask away Immed.
|
||||
(ums->cmnd[4] & ~0x03) != 0) // Mask LoEj, Start.
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
loej = ums->cmnd[4] & 0x02;
|
||||
@@ -1035,10 +1047,10 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
// Check if we are allowed to unload the media.
|
||||
@@ -1047,16 +1059,16 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
|
||||
ums->set_text(ums->label, "#C7EA46 Status:# Unload attempt prevented");
|
||||
ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!loej)
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
|
||||
// Unmount means we exit UMS because of ejection.
|
||||
ums->lun.unmounted = 1;
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
|
||||
@@ -1067,7 +1079,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
prevent = ums->cmnd[4] & 0x01;
|
||||
@@ -1075,17 +1087,16 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Notify for possible unmounting?
|
||||
// Normally we sync here but we do synced writes to SDMMC.
|
||||
if (ums->lun.prevent_medium_removal && !prevent)
|
||||
;
|
||||
if (ums->lun.prevent_medium_removal && !prevent) { /* Do nothing */ }
|
||||
|
||||
ums->lun.prevent_medium_removal = prevent;
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -1105,7 +1116,7 @@ static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bul
|
||||
|
||||
// Check whether the command is properly formed and whether its data size
|
||||
// and direction agree with the values we already have.
|
||||
static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, int cmnd_size,
|
||||
static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, u32 cmnd_size,
|
||||
enum data_direction data_dir, u32 mask, int needs_medium)
|
||||
{
|
||||
//const char dirletter[4] = {'u', 'o', 'i', 'n'};
|
||||
@@ -1132,7 +1143,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
{
|
||||
ums->phase_error = 1;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Cmd length verification.
|
||||
@@ -1146,7 +1157,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
{
|
||||
ums->phase_error = 1;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,7 +1178,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
ums->lun.sense_data = ums->lun.unit_attention_data;
|
||||
ums->lun.unit_attention_data = SS_NO_SENSE;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Check that only command bytes listed in the mask are set.
|
||||
@@ -1178,7 +1189,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1187,16 +1198,16 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
{
|
||||
ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
u32 len;
|
||||
int reply = -22; // Invalid argument.
|
||||
int reply = UMS_RES_INVALID_ARG;
|
||||
|
||||
ums->phase_error = 0;
|
||||
ums->short_packet_received = 0;
|
||||
@@ -1227,7 +1238,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
// We don't support MODE SELECT.
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
reply = -22;
|
||||
reply = UMS_RES_INVALID_ARG;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1238,7 +1249,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
// We don't support MODE SELECT.
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
reply = -22;
|
||||
reply = UMS_RES_INVALID_ARG;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1367,12 +1378,12 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (reply == 0)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
reply = -22; // Invalid argument.
|
||||
reply = UMS_RES_INVALID_ARG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (reply == -22) // Invalid argument.
|
||||
if (reply == UMS_RES_INVALID_ARG)
|
||||
reply = 0; // Error reply length.
|
||||
|
||||
// Set up reply buffer for finish_reply(). Otherwise it's already set.
|
||||
@@ -1384,7 +1395,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
ums->residue -= reply;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -1398,12 +1409,12 @@ static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
u32 nsend = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE);
|
||||
memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep);
|
||||
bulk_ctxt->bulk_in_length = nsend;
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
|
||||
ums->usb_amount_left -= nsend;
|
||||
current_len_to_keep = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -1416,10 +1427,10 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
u32 amount = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE);
|
||||
|
||||
bulk_ctxt->bulk_out_length = amount;
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_DATA);
|
||||
ums->usb_amount_left -= amount;
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
// Throw away the data in a filled buffer.
|
||||
@@ -1431,15 +1442,15 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
bulk_ctxt->bulk_out_status != USB_RES_OK)
|
||||
{
|
||||
raise_exception(ums, UMS_STATE_ABORT_BULK_OUT);
|
||||
return -4; // Interrupted system call
|
||||
return UMS_RES_PROT_FATAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc = UMS_RES_OK;
|
||||
|
||||
switch (ums->data_dir) {
|
||||
case DATA_DIR_NONE:
|
||||
@@ -1463,7 +1474,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
// If there's no residue, simply send the last buffer.
|
||||
if (!ums->residue)
|
||||
{
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
|
||||
|
||||
/* For Bulk-only, if we're allowed to stall then send the
|
||||
* short packet and halt the bulk-in endpoint. If we can't
|
||||
@@ -1471,7 +1482,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
}
|
||||
else if (ums->can_stall)
|
||||
{
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
|
||||
rc = ums_set_stall(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!");
|
||||
}
|
||||
@@ -1491,7 +1502,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (ums->short_packet_received) // Did the host stop sending unexpectedly early?
|
||||
{
|
||||
raise_exception(ums, UMS_STATE_ABORT_BULK_OUT);
|
||||
rc = -4; // Interrupted system call
|
||||
rc = UMS_RES_PROT_FATAL;
|
||||
}
|
||||
else // We can't stall. Read in the excess data and throw it away.
|
||||
rc = throw_away_data(ums, bulk_ctxt);
|
||||
@@ -1531,12 +1542,12 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
/* Was this a real packet? Should it be ignored? */
|
||||
// Was this a real packet? Should it be ignored?
|
||||
if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore || ums->lun.unmounted)
|
||||
{
|
||||
if (bulk_ctxt->bulk_out_status || ums->lun.unmounted)
|
||||
{
|
||||
DPRINTF("USB: EP timeout\n");
|
||||
DPRINTF("USB: EP timeout (%d)\n", bulk_ctxt->bulk_out_status);
|
||||
// In case we disconnected, exit UMS.
|
||||
// Raise timeout if removable and didn't got a unit ready command inside 4s.
|
||||
if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_EP_DISABLED ||
|
||||
@@ -1567,6 +1578,8 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->set_text(ums->label, "#C7EA46 Status:# Medium unmounted");
|
||||
ums->timeouts++;
|
||||
if (!bulk_ctxt->bulk_out_status)
|
||||
ums->timeouts += 3;
|
||||
}
|
||||
|
||||
if (ums->timeouts > 20)
|
||||
@@ -1574,32 +1587,37 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
}
|
||||
|
||||
if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore)
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Is the CBW valid? */
|
||||
// Clear request flag to allow a new one to be queued.
|
||||
ums->cbw_req_queued = false;
|
||||
|
||||
// Is the CBW valid?
|
||||
bulk_recv_pkt_t *cbw = (bulk_recv_pkt_t *)bulk_ctxt->bulk_out_buf;
|
||||
if (bulk_ctxt->bulk_out_length_actual != USB_BULK_CB_WRAP_LEN || cbw->Signature != USB_BULK_CB_SIG)
|
||||
{
|
||||
gfx_printf("USB: invalid CBW: len %X sig 0x%X\n", bulk_ctxt->bulk_out_length_actual, cbw->Signature);
|
||||
|
||||
// The Bulk-only spec says we MUST stall the IN endpoint
|
||||
// (6.6.1), so it's unavoidable. It also says we must
|
||||
// retain this state until the next reset, but there's
|
||||
// no way to tell the controller driver it should ignore
|
||||
// Clear-Feature(HALT) requests.
|
||||
//
|
||||
// We aren't required to halt the OUT endpoint; instead
|
||||
// we can simply accept and discard any data received
|
||||
// until the next reset.
|
||||
/*
|
||||
* The Bulk-only spec says we MUST stall the IN endpoint
|
||||
* (6.6.1), so it's unavoidable. It also says we must
|
||||
* retain this state until the next reset, but there's
|
||||
* no way to tell the controller driver it should ignore
|
||||
* Clear-Feature(HALT) requests.
|
||||
*
|
||||
* We aren't required to halt the OUT endpoint; instead
|
||||
* we can simply accept and discard any data received
|
||||
* until the next reset.
|
||||
*/
|
||||
ums_wedge_bulk_in_endpoint(ums);
|
||||
bulk_ctxt->bulk_out_ignore = 1;
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Is the CBW meaningful? */
|
||||
// Is the CBW meaningful?
|
||||
if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG ||
|
||||
cbw->Length <= 0 || cbw->Length > SCSI_MAX_CMD_SZ)
|
||||
cbw->Length == 0 || cbw->Length > SCSI_MAX_CMD_SZ)
|
||||
{
|
||||
gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n",
|
||||
cbw->Lun, cbw->Flags, cbw->Length);
|
||||
@@ -1613,10 +1631,10 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# CBW unknown - Stalled both EP!");
|
||||
}
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Save the command for later */
|
||||
// Save the command for later.
|
||||
ums->cmnd_size = cbw->Length;
|
||||
memcpy(ums->cmnd, cbw->CDB, ums->cmnd_size);
|
||||
|
||||
@@ -1636,12 +1654,12 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (!ums->lun.unmounted)
|
||||
ums->timeouts = 0;
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc = UMS_RES_OK;
|
||||
|
||||
/* Wait for the next buffer to become available */
|
||||
// while (bulk_ctxt->bulk_out_buf_state != BUF_STATE_EMPTY)
|
||||
@@ -1651,8 +1669,20 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN;
|
||||
|
||||
/* Queue a request to read a Bulk-only CBW */
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED);
|
||||
// Queue a request to read a Bulk-only CBW.
|
||||
if (!ums->cbw_req_queued)
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
|
||||
else
|
||||
_ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
|
||||
|
||||
/*
|
||||
* On XUSB do not allow multiple requests for CBW to be done.
|
||||
* This avoids an issue with some XHCI controllers and OS combos (e.g. ASMedia and Linux/Mac OS)
|
||||
* which confuse that and concatenate an old CBW request with another write request (SCSI Write)
|
||||
* and create a babble error (transmit overflow).
|
||||
*/
|
||||
if (ums->xusb)
|
||||
ums->cbw_req_queued = true;
|
||||
|
||||
/* We will drain the buffer in software, which means we
|
||||
* can reuse it for the next filling. No need to advance
|
||||
@@ -1689,7 +1719,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
SK(sd), ASC(sd), ASCQ(sd), ums->lun.sense_data_info);
|
||||
}
|
||||
|
||||
/* Store and send the Bulk-only CSW */
|
||||
// Store and send the Bulk-only CSW.
|
||||
bulk_send_pkt_t *csw = (bulk_send_pkt_t *)bulk_ctxt->bulk_in_buf;
|
||||
|
||||
csw->Signature = USB_BULK_CS_SIG;
|
||||
@@ -1698,14 +1728,14 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
csw->Status = status;
|
||||
|
||||
bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN;
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_CMD);
|
||||
}
|
||||
|
||||
static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
enum ums_state old_state;
|
||||
|
||||
/* Clear out the controller's fifos */
|
||||
// Clear out the controller's fifos.
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_in);
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_out);
|
||||
|
||||
@@ -1728,7 +1758,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
ums->state = UMS_STATE_NORMAL;
|
||||
|
||||
/* Carry out any extra actions required for the exception */
|
||||
// Carry out any extra actions required for the exception.
|
||||
switch (old_state)
|
||||
{
|
||||
case UMS_STATE_NORMAL:
|
||||
@@ -1750,7 +1780,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
break;
|
||||
|
||||
case UMS_STATE_EXIT:
|
||||
ums->state = UMS_STATE_TERMINATED; /* Stop the thread */
|
||||
ums->state = UMS_STATE_TERMINATED; // Stop the thread.
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1765,16 +1795,16 @@ static inline void _system_maintainance(usbd_gadget_ums_t *ums)
|
||||
|
||||
u32 time = get_tmr_ms();
|
||||
|
||||
if (timer_dram < time)
|
||||
{
|
||||
minerva_periodic_training();
|
||||
timer_dram = get_tmr_ms() + 100;
|
||||
}
|
||||
else if (timer_status_bar < time)
|
||||
if (timer_status_bar < time)
|
||||
{
|
||||
ums->system_maintenance(true);
|
||||
timer_status_bar = get_tmr_ms() + 30000;
|
||||
}
|
||||
else if (timer_dram < time)
|
||||
{
|
||||
minerva_periodic_training();
|
||||
timer_dram = get_tmr_ms() + EMC_PERIODIC_TRAIN_MS;
|
||||
}
|
||||
}
|
||||
|
||||
int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
@@ -1828,6 +1858,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
// Initialize sdmmc.
|
||||
if (usbs->type == MMC_SD)
|
||||
{
|
||||
sd_end();
|
||||
sd_mount();
|
||||
sd_unmount();
|
||||
ums.lun.sdmmc = &sd_sdmmc;
|
||||
@@ -1898,7 +1929,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
send_status(&ums, &ums.bulk_ctxt);
|
||||
} while (ums.state != UMS_STATE_TERMINATED);
|
||||
|
||||
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
|
||||
if (ums.lun.prevent_medium_removal)
|
||||
ums.set_text(ums.label, "#FFDD00 Error:# Disk unsafely ejected");
|
||||
else
|
||||
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
|
||||
goto exit;
|
||||
|
||||
error:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Enhanced & eXtensible USB device (EDCI & XDCI) driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* 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,
|
||||
@@ -198,7 +198,10 @@ typedef struct _t210_usb2d_t
|
||||
#define XUSB_DEV_XHCI_ST 0x34
|
||||
#define XHCI_ST_RC BIT(0)
|
||||
#define XHCI_ST_IP BIT(4)
|
||||
#define XUSB_DEV_XHCI_RT_IMOD 0x38
|
||||
#define XUSB_DEV_XHCI_PORTSC 0x3C
|
||||
#define XHCI_PORTSC_CCS BIT(0)
|
||||
#define XHCI_PORTSC_PED BIT(1)
|
||||
#define XHCI_PORTSC_PR BIT(4)
|
||||
#define XHCI_PORTSC_PLS_MASK (0xF << 5)
|
||||
#define XHCI_PORTSC_PLS_U0 (0 << 5)
|
||||
@@ -225,11 +228,12 @@ typedef struct _t210_usb2d_t
|
||||
#define XUSB_DEV_XHCI_ECPLO 0x40
|
||||
#define XUSB_DEV_XHCI_ECPHI 0x44
|
||||
#define XUSB_DEV_XHCI_EP_HALT 0x50
|
||||
#define XHCI_EP_HALT_DCI BIT(0)
|
||||
#define XHCI_EP_HALT_DCI_EP0_IN BIT(0)
|
||||
#define XUSB_DEV_XHCI_EP_PAUSE 0x54
|
||||
#define XUSB_DEV_XHCI_EP_RELOAD 0x58
|
||||
#define XUSB_DEV_XHCI_EP_STCHG 0x5C
|
||||
#define XUSB_DEV_XHCI_PORTHALT 0x6C
|
||||
#define XUSB_DEV_XHCI_EP_STOPPED 0x78
|
||||
#define XHCI_PORTHALT_HALT_LTSSM BIT(0)
|
||||
#define XHCI_PORTHALT_STCHG_REQ BIT(20)
|
||||
#define XUSB_DEV_XHCI_CFG_DEV_FE 0x85C
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Enhanced USB Device (EDCI) driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* 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,
|
||||
@@ -724,7 +724,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint)
|
||||
return USB_EP_STATUS_IDLE;
|
||||
}
|
||||
|
||||
static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync)
|
||||
static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, u32 sync_timeout)
|
||||
{
|
||||
if (!buf)
|
||||
len = 0;
|
||||
@@ -797,12 +797,12 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync)
|
||||
|
||||
int res = USB_RES_OK;
|
||||
usb_ep_status_t ep_status;
|
||||
if (sync)
|
||||
if (sync_timeout)
|
||||
{
|
||||
ep_status = _usbd_get_ep_status(endpoint);
|
||||
if (ep_status == USB_EP_STATUS_ACTIVE)
|
||||
{
|
||||
u32 retries = 1000000; // Timeout 2s.
|
||||
u32 retries = sync_timeout;
|
||||
while (retries)
|
||||
{
|
||||
ep_status = _usbd_get_ep_status(endpoint);
|
||||
@@ -834,7 +834,7 @@ out:
|
||||
|
||||
static int _usbd_ep_ack(usb_ep_t ep)
|
||||
{
|
||||
return _usbd_ep_operation(ep, NULL, 0, true);
|
||||
return _usbd_ep_operation(ep, NULL, 0, USB_XFER_SYNCED_ENUM);
|
||||
}
|
||||
|
||||
static void _usbd_set_ep0_stall()
|
||||
@@ -1275,7 +1275,7 @@ static int _usbd_handle_ep0_control_transfer()
|
||||
|
||||
if (_wLength < size)
|
||||
size = _wLength;
|
||||
res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, true);
|
||||
res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, USB_XFER_SYNCED_ENUM);
|
||||
if (!res)
|
||||
res = _usbd_ep_ack(USB_EP_CTRL_OUT);
|
||||
}
|
||||
@@ -1402,7 +1402,7 @@ static usb_ep_status_t _usbd_get_ep1_status(usb_dir_t dir)
|
||||
return _usbd_get_ep_status(ep);
|
||||
}
|
||||
|
||||
int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
|
||||
int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_timeout)
|
||||
{
|
||||
if ((u32)buf % USB_EP_BUFFER_ALIGN)
|
||||
return USB2_ERROR_XFER_NOT_ALIGNED;
|
||||
@@ -1410,9 +1410,9 @@ int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
|
||||
int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync);
|
||||
int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync_timeout);
|
||||
|
||||
if (sync && bytes_read)
|
||||
if (sync_timeout && bytes_read)
|
||||
*bytes_read = res ? 0 : len;
|
||||
|
||||
return res;
|
||||
@@ -1435,7 +1435,7 @@ int usb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
|
||||
{
|
||||
u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE);
|
||||
|
||||
res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED);
|
||||
res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
@@ -1455,7 +1455,7 @@ static int _usbd_get_ep1_out_bytes_read()
|
||||
return (usbdaemon->ep_bytes_requested[USB_EP_BULK_OUT] - (usbdaemon->qhs[USB_EP_BULK_OUT].token >> 16));
|
||||
}
|
||||
|
||||
int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
|
||||
int usb_device_ep1_out_reading_finish(u32 *pending_bytes, u32 sync_timeout)
|
||||
{
|
||||
usb_ep_status_t ep_status;
|
||||
do
|
||||
@@ -1480,7 +1480,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
|
||||
return USB_ERROR_XFER_ERROR;
|
||||
}
|
||||
|
||||
int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_timeout)
|
||||
{
|
||||
if ((u32)buf % USB_EP_BUFFER_ALIGN)
|
||||
return USB2_ERROR_XFER_NOT_ALIGNED;
|
||||
@@ -1488,9 +1488,9 @@ int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
|
||||
int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync);
|
||||
int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync_timeout);
|
||||
|
||||
if (sync && bytes_written)
|
||||
if (sync_timeout && bytes_written)
|
||||
*bytes_written = res ? 0 : len;
|
||||
|
||||
return res;
|
||||
@@ -1504,7 +1504,7 @@ static int _usbd_get_ep1_in_bytes_written()
|
||||
return (usbdaemon->ep_bytes_requested[USB_EP_BULK_IN] - (usbdaemon->qhs[USB_EP_BULK_IN].token >> 16));
|
||||
}
|
||||
|
||||
int usb_device_ep1_in_writing_finish(u32 *pending_bytes)
|
||||
int usb_device_ep1_in_writing_finish(u32 *pending_bytes, u32 sync_timeout)
|
||||
{
|
||||
usb_ep_status_t ep_status;
|
||||
do
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Enhanced & eXtensible USB Device (EDCI & XDCI) driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* 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,
|
||||
@@ -30,8 +30,12 @@
|
||||
#define USB_EP_BUFFER_MAX_SIZE (USB_EP_BUFFER_4_TD)
|
||||
#define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE)
|
||||
|
||||
#define USB_XFER_START false
|
||||
#define USB_XFER_SYNCED true
|
||||
#define USB_XFER_START 0
|
||||
#define USB_XFER_SYNCED_ENUM 1000000
|
||||
#define USB_XFER_SYNCED_CMD 1000000
|
||||
#define USB_XFER_SYNCED_DATA 2000000
|
||||
#define USB_XFER_SYNCED_CLASS 5000000
|
||||
#define USB_XFER_SYNCED -1
|
||||
|
||||
typedef enum _usb_hid_type
|
||||
{
|
||||
@@ -144,6 +148,7 @@ typedef enum _usb_error_t
|
||||
XUSB_ERROR_INVALID_EP = USB_ERROR_XFER_ERROR, // From 2.
|
||||
XUSB_ERROR_XFER_BULK_IN_RESIDUE = 7,
|
||||
XUSB_ERROR_INVALID_CYCLE = USB2_ERROR_XFER_EP_DISABLED, // From 8.
|
||||
XUSB_ERROR_BABBLE_DETECTED = 50,
|
||||
XUSB_ERROR_SEQ_NUM = 51,
|
||||
XUSB_ERROR_XFER_DIR = 52,
|
||||
XUSB_ERROR_PORT_CFG = 54
|
||||
@@ -169,11 +174,11 @@ typedef struct _usb_ops_t
|
||||
int (*usb_device_class_send_max_lun)(u8);
|
||||
int (*usb_device_class_send_hid_report)();
|
||||
|
||||
int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, bool);
|
||||
int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32);
|
||||
int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *);
|
||||
int (*usb_device_ep1_out_reading_finish)(u32 *, int);
|
||||
int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, bool);
|
||||
int (*usb_device_ep1_in_writing_finish)(u32 *);
|
||||
int (*usb_device_ep1_out_reading_finish)(u32 *, u32);
|
||||
int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, u32);
|
||||
int (*usb_device_ep1_in_writing_finish)(u32 *, u32);
|
||||
bool (*usb_device_get_suspended)();
|
||||
bool (*usb_device_get_port_in_sleep)();
|
||||
} usb_ops_t;
|
||||
|
||||
296
bdk/usb/xusbd.c
296
bdk/usb/xusbd.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* eXtensible USB Device driver (XDCI) for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2020 CTCaer
|
||||
* Copyright (c) 2020-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -368,7 +368,7 @@ typedef struct _xusbd_controller_t
|
||||
event_trb_t *event_dequeue_ptr;
|
||||
u32 event_ccs;
|
||||
u32 device_state;
|
||||
u32 bytes_remaining[2];
|
||||
u32 tx_bytes[2];
|
||||
u32 tx_count[2];
|
||||
u32 ctrl_seq_num;
|
||||
u32 config_num;
|
||||
@@ -881,7 +881,7 @@ int xusb_device_init()
|
||||
_xusbd_init_device_clocks();
|
||||
|
||||
// Enable AHB redirect for access to IRAM for Event/EP ring buffers.
|
||||
mc_enable_ahb_redirect(); // can be skipped if IRAM is not used/////////////////
|
||||
mc_enable_ahb_redirect(false); // Can be skipped if IRAM is not used.
|
||||
|
||||
// Enable XUSB device IPFS.
|
||||
XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI;
|
||||
@@ -895,14 +895,11 @@ int xusb_device_init()
|
||||
XUSB_DEV_DEV(XUSB_DEV_INTR_MASK) |= DEV_INTR_MASK_IP_INT_MASK;
|
||||
|
||||
// AHB USB performance cfg.
|
||||
//TODO: Doesn't help..
|
||||
/*
|
||||
AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE;
|
||||
AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE;
|
||||
AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3;
|
||||
AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) =
|
||||
MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles.
|
||||
*/
|
||||
|
||||
// Initialize context.
|
||||
usbd_xotg = &usbd_xotg_controller_ctxt;
|
||||
@@ -930,7 +927,7 @@ int xusb_device_init()
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
static int _xusb_queue_trb(int ep_idx, void *trb, bool ring_doorbell)
|
||||
static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||
{
|
||||
int res = USB_RES_OK;
|
||||
data_trb_t *next_trb;
|
||||
@@ -1076,7 +1073,7 @@ static int _xusb_issue_normal_trb(u8 *buf, u32 len, usb_dir_t direction)
|
||||
normal_trb_t trb = {0};
|
||||
|
||||
_xusb_create_normal_trb(&trb, buf, len, direction);
|
||||
int ep_idx = USB_EP_BULK_IN;
|
||||
u32 ep_idx = USB_EP_BULK_IN;
|
||||
if (direction == USB_DIR_OUT)
|
||||
ep_idx = USB_EP_BULK_OUT;
|
||||
int res = _xusb_queue_trb(ep_idx, &trb, EP_RING_DOORBELL);
|
||||
@@ -1103,19 +1100,32 @@ static int _xusb_issue_data_trb(u8 *buf, u32 len, usb_dir_t direction)
|
||||
|
||||
int xusb_set_ep_stall(u32 endpoint, int ep_stall)
|
||||
{
|
||||
int ep_idx = BIT(endpoint);
|
||||
u32 ep_mask = BIT(endpoint);
|
||||
if (ep_stall)
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) |= ep_idx;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) |= ep_mask;
|
||||
else
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~ep_idx;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~ep_mask;
|
||||
|
||||
// Wait for EP status to change.
|
||||
int res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STCHG, ep_idx, ep_idx, 1000);
|
||||
int res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STCHG, ep_mask, ep_mask, 1000);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
// Clear status change.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STCHG) = ep_idx;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STCHG) = ep_mask;
|
||||
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
static int _xusb_wait_ep_stopped(u32 endpoint)
|
||||
{
|
||||
u32 ep_mask = BIT(endpoint);
|
||||
|
||||
// Wait for EP status to change.
|
||||
_xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STOPPED, ep_mask, ep_mask, 1000);
|
||||
|
||||
// Clear status change.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STOPPED) = ep_mask;
|
||||
|
||||
return USB_RES_OK;
|
||||
}
|
||||
@@ -1161,20 +1171,27 @@ static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
|
||||
return _xusb_issue_status_trb(USB_DIR_OUT);
|
||||
else if (usbd_xotg->wait_for_event_trb == XUSB_TRB_STATUS)
|
||||
{
|
||||
if (usbd_xotg->device_state == XUSB_ADDRESSED_STS_WAIT)
|
||||
switch (usbd_xotg->device_state)
|
||||
{
|
||||
case XUSB_ADDRESSED_STS_WAIT:
|
||||
usbd_xotg->device_state = XUSB_ADDRESSED;
|
||||
else if (usbd_xotg->device_state == XUSB_CONFIGURED_STS_WAIT)
|
||||
break;
|
||||
case XUSB_CONFIGURED_STS_WAIT:
|
||||
usbd_xotg->device_state = XUSB_CONFIGURED;
|
||||
else if (usbd_xotg->device_state == XUSB_LUN_CONFIGURED_STS_WAIT)
|
||||
break;
|
||||
case XUSB_LUN_CONFIGURED_STS_WAIT:
|
||||
usbd_xotg->device_state = XUSB_LUN_CONFIGURED;
|
||||
else if (usbd_xotg->device_state == XUSB_HID_CONFIGURED_STS_WAIT)
|
||||
break;
|
||||
case XUSB_HID_CONFIGURED_STS_WAIT:
|
||||
usbd_xotg->device_state = XUSB_HID_CONFIGURED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_EP_BULK_IN:
|
||||
usbd_xotg->bytes_remaining[USB_DIR_IN] -= trb->trb_tx_len;
|
||||
if (usbd_xotg->tx_count[USB_DIR_IN])///////////
|
||||
usbd_xotg->tx_bytes[USB_DIR_IN] -= trb->trb_tx_len;
|
||||
if (usbd_xotg->tx_count[USB_DIR_IN])
|
||||
usbd_xotg->tx_count[USB_DIR_IN]--;
|
||||
|
||||
// If bytes remaining for a Bulk IN transfer, return error.
|
||||
@@ -1184,8 +1201,8 @@ static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
|
||||
|
||||
case USB_EP_BULK_OUT:
|
||||
// If short packet and Bulk OUT, it's not an error because we prime EP for 4KB.
|
||||
usbd_xotg->bytes_remaining[USB_DIR_OUT] -= trb->trb_tx_len;
|
||||
if (usbd_xotg->tx_count[USB_DIR_OUT])///////////
|
||||
usbd_xotg->tx_bytes[USB_DIR_OUT] -= trb->trb_tx_len;
|
||||
if (usbd_xotg->tx_count[USB_DIR_OUT])
|
||||
usbd_xotg->tx_count[USB_DIR_OUT]--;
|
||||
break;
|
||||
}
|
||||
@@ -1199,6 +1216,11 @@ static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
|
||||
xusb_set_ep_stall(trb->ep_id, USB_EP_CFG_STALL);
|
||||
return USB_RES_OK;
|
||||
*/
|
||||
case XUSB_COMP_BABBLE_DETECTED_ERROR:
|
||||
_xusb_wait_ep_stopped(trb->ep_id);
|
||||
xusb_set_ep_stall(trb->ep_id, USB_EP_CFG_STALL);
|
||||
return XUSB_ERROR_BABBLE_DETECTED;
|
||||
|
||||
case XUSB_COMP_CTRL_DIR_ERROR:
|
||||
return XUSB_ERROR_XFER_DIR;
|
||||
|
||||
@@ -1219,11 +1241,52 @@ static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
|
||||
|
||||
static int _xusb_handle_port_change()
|
||||
{
|
||||
u32 res = USB_RES_OK;
|
||||
u32 status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
|
||||
u32 halt = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT);
|
||||
u32 clear_mask = XHCI_PORTSC_CEC | XHCI_PORTSC_PLC | XHCI_PORTSC_PRC | XHCI_PORTSC_WRC | XHCI_PORTSC_CSC;
|
||||
|
||||
// Connect status change (CSC).
|
||||
// Port reset (PR).
|
||||
if (status & XHCI_PORTSC_PR)
|
||||
{
|
||||
//! TODO:
|
||||
// XHCI_PORTSC_PR: device_state = XUSB_RESET
|
||||
|
||||
//_disable_usb_wdt4();
|
||||
}
|
||||
|
||||
// Port Reset Change (PRC).
|
||||
if (status & XHCI_PORTSC_PRC)
|
||||
{
|
||||
// Clear PRC bit.
|
||||
status &= ~clear_mask;
|
||||
status |= XHCI_PORTSC_PRC;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
|
||||
}
|
||||
|
||||
// Warm Port Reset (WPR).
|
||||
if (status & XHCI_PORTSC_WPR)
|
||||
{
|
||||
//_disable_usb_wdt4();
|
||||
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM;
|
||||
(void)XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT);
|
||||
|
||||
//! TODO: XHCI_PORTSC_WPR: device_state = XUSB_RESET
|
||||
}
|
||||
|
||||
// Warm Port Reset Change (WRC).
|
||||
if (status & XHCI_PORTSC_WRC)
|
||||
{
|
||||
// Clear WRC bit.
|
||||
status &= ~clear_mask;
|
||||
status |= XHCI_PORTSC_WRC;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
|
||||
}
|
||||
|
||||
// Reread port status to handle more changes.
|
||||
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
|
||||
|
||||
// Connect Status Change (CSC).
|
||||
if (status & XHCI_PORTSC_CSC)
|
||||
{
|
||||
//! TODO: Check CCS.
|
||||
@@ -1241,90 +1304,64 @@ static int _xusb_handle_port_change()
|
||||
volatile xusb_ep_ctx_t *ep_ctxt = &xusb_evtq->xusb_ep_ctxt[XUSB_EP_CTRL_IN];
|
||||
ep_ctxt->avg_trb_len = 8;
|
||||
ep_ctxt->max_packet_size = 64;
|
||||
//! TODO: If super speed is supported, ep context reload, unpause and unhalt must happen.
|
||||
}
|
||||
|
||||
// Clear CSC bit.
|
||||
status &= ~clear_mask;
|
||||
status |= XHCI_PORTSC_CSC;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
|
||||
}
|
||||
|
||||
// Port reset (PR), Port reset change (PRC).
|
||||
if (status & XHCI_PORTSC_PR || status & XHCI_PORTSC_PRC)
|
||||
{
|
||||
//! TODO:
|
||||
// XHCI_PORTSC_PR: device_state = XUSB_RESET
|
||||
|
||||
//_disable_usb_wdt4();
|
||||
|
||||
//res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_PORTSC, XHCI_PORTSC_PRC, XHCI_PORTSC_PRC, 50000); // unpatched0
|
||||
// if (res) return res;
|
||||
_xusb_xhci_mask_wait(XUSB_DEV_XHCI_PORTSC, XHCI_PORTSC_PRC, XHCI_PORTSC_PRC, 50000); // patched0
|
||||
|
||||
// Clear PRC bit.
|
||||
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) | XHCI_PORTSC_PRC;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_PRC;
|
||||
}
|
||||
|
||||
// Warm Port Reset (WPR), Warm Port Reset Change (WRC).
|
||||
if (status & XHCI_PORTSC_WPR || status & XHCI_PORTSC_WRC)
|
||||
{
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM;
|
||||
(void)XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
|
||||
res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_PORTSC, XHCI_PORTSC_WRC, XHCI_PORTSC_WRC, 1000);
|
||||
|
||||
// Clear WRC bit.
|
||||
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) | XHCI_PORTSC_WRC;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_WRC;
|
||||
|
||||
//! TODO: WPR: device_state = XUSB_RESET
|
||||
}
|
||||
|
||||
// Handle Config Request (STCHG_REQ).
|
||||
if (halt & XHCI_PORTHALT_STCHG_REQ)
|
||||
{
|
||||
// Clear Link Training Status.
|
||||
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) & ~XHCI_PORTHALT_HALT_LTSSM;
|
||||
// Clear Link Training Status and pending request/reject.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM;
|
||||
(void)XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT);
|
||||
}
|
||||
|
||||
// Reread port status to handle more changes.
|
||||
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
|
||||
|
||||
// Port link state change (PLC).
|
||||
if (status & XHCI_PORTSC_PLC)
|
||||
{
|
||||
//! WAR: Sometimes port speed changes without a CSC event. Set again.
|
||||
usbd_xotg->port_speed = (status & XHCI_PORTSC_PS) >> 10;
|
||||
|
||||
// check PLS
|
||||
// if U3
|
||||
// check XHCI_PORTSC_PLS_MASK
|
||||
// if XHCI_PORTSC_PLS_U3
|
||||
// device_state = XUSB_SUSPENDED
|
||||
// else if U0 and XUSB_SUSPENDED
|
||||
// else if XHCI_PORTSC_PLS_U0 and XUSB_SUSPENDED
|
||||
// val = XUSB_DEV_XHCI_EP_PAUSE
|
||||
// XUSB_DEV_XHCI_EP_PAUSE = 0
|
||||
// XUSB_DEV_XHCI_EP_STCHG = val;
|
||||
|
||||
// Clear PLC bit.
|
||||
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) | XHCI_PORTSC_PLC;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_PLC;
|
||||
status &= ~clear_mask;
|
||||
status |= XHCI_PORTSC_PLC;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
|
||||
}
|
||||
|
||||
// Port configuration link error (CEC).
|
||||
if (status & XHCI_PORTSC_CEC)
|
||||
{
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_CEC;
|
||||
res = XUSB_ERROR_PORT_CFG;
|
||||
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
|
||||
status &= ~clear_mask;
|
||||
status |= XHCI_PORTSC_CEC;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
|
||||
|
||||
return XUSB_ERROR_PORT_CFG;
|
||||
}
|
||||
|
||||
return res;
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
static int _xusb_handle_get_ep_status(usb_ctrl_setup_t *ctrl_setup)
|
||||
static int _xusb_handle_get_ep_status(u32 ep_idx)
|
||||
{
|
||||
u32 ep_mask = BIT(ep_idx);
|
||||
static u8 xusb_ep_status_descriptor[2] = {0};
|
||||
|
||||
// Get EP context pointer.
|
||||
volatile xusb_ep_ctx_t *ep_ctxt = (volatile xusb_ep_ctx_t *)(XUSB_DEV_XHCI(XUSB_DEV_XHCI_ECPLO) & 0xFFFFFFF0);
|
||||
ep_ctxt = &ep_ctxt[ctrl_setup->wIndex];
|
||||
|
||||
xusb_ep_status_descriptor[0] = (ep_ctxt->ep_state == EP_HALTED) ? USB_STATUS_EP_HALTED : USB_STATUS_EP_OK;
|
||||
xusb_ep_status_descriptor[0] =
|
||||
(XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) & ep_mask) ? USB_STATUS_EP_HALTED : USB_STATUS_EP_OK;
|
||||
return _xusb_issue_data_trb(xusb_ep_status_descriptor, 2, USB_DIR_IN);
|
||||
}
|
||||
|
||||
@@ -1539,8 +1576,9 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
|
||||
|
||||
//gfx_printf("ctrl: %02X %02X %04X %04X %04X\n", _bmRequestType, _bRequest, _wValue, _wIndex, _wLength);
|
||||
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~XHCI_EP_HALT_DCI;
|
||||
u32 res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_HALT, XHCI_EP_HALT_DCI, 0, 1000);
|
||||
// Unhalt EP0 IN.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~XHCI_EP_HALT_DCI_EP0_IN;
|
||||
u32 res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_HALT, XHCI_EP_HALT_DCI_EP0_IN, 0, 1000);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
@@ -1560,14 +1598,33 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
|
||||
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
|
||||
if ((_wValue & 0xFF) == USB_FEATURE_ENDPOINT_HALT)
|
||||
{
|
||||
if (_bRequest == USB_REQUEST_CLEAR_FEATURE)
|
||||
if (_bRequest == USB_REQUEST_CLEAR_FEATURE || _bRequest == USB_REQUEST_SET_FEATURE)
|
||||
{
|
||||
xusb_set_ep_stall(_wIndex, USB_EP_CFG_CLEAR);
|
||||
return _xusb_issue_status_trb(USB_DIR_IN);
|
||||
}
|
||||
else if (_bRequest == USB_REQUEST_SET_FEATURE)
|
||||
{
|
||||
xusb_set_ep_stall(_wIndex, USB_EP_CFG_STALL);
|
||||
u32 ep = 0;
|
||||
switch (_wIndex) // endpoint
|
||||
{
|
||||
case USB_EP_ADDR_CTRL_OUT:
|
||||
ep = XUSB_EP_CTRL_OUT;
|
||||
break;
|
||||
case USB_EP_ADDR_CTRL_IN:
|
||||
ep = XUSB_EP_CTRL_IN;
|
||||
break;
|
||||
case USB_EP_ADDR_BULK_OUT:
|
||||
ep = USB_EP_BULK_OUT;
|
||||
break;
|
||||
case USB_EP_ADDR_BULK_IN:
|
||||
ep = USB_EP_BULK_IN;
|
||||
break;
|
||||
default:
|
||||
xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL);
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
if (_bRequest == USB_REQUEST_CLEAR_FEATURE)
|
||||
xusb_set_ep_stall(ep, USB_EP_CFG_CLEAR);
|
||||
else if (_bRequest == USB_REQUEST_SET_FEATURE)
|
||||
xusb_set_ep_stall(ep, USB_EP_CFG_STALL);
|
||||
|
||||
return _xusb_issue_status_trb(USB_DIR_IN);
|
||||
}
|
||||
}
|
||||
@@ -1634,7 +1691,28 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
|
||||
|
||||
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
|
||||
if (_bRequest == USB_REQUEST_GET_STATUS)
|
||||
return _xusb_handle_get_ep_status(ctrl_setup);
|
||||
{
|
||||
u32 ep = 0;
|
||||
switch (_wIndex) // endpoint
|
||||
{
|
||||
case USB_EP_ADDR_CTRL_OUT:
|
||||
ep = XUSB_EP_CTRL_OUT;
|
||||
break;
|
||||
case USB_EP_ADDR_CTRL_IN:
|
||||
ep = XUSB_EP_CTRL_IN;
|
||||
break;
|
||||
case USB_EP_ADDR_BULK_OUT:
|
||||
ep = USB_EP_BULK_OUT;
|
||||
break;
|
||||
case USB_EP_ADDR_BULK_IN:
|
||||
ep = USB_EP_BULK_IN;
|
||||
break;
|
||||
default:
|
||||
xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL);
|
||||
return USB_RES_OK;
|
||||
}
|
||||
return _xusb_handle_get_ep_status(ep);
|
||||
}
|
||||
|
||||
ep_stall = true;
|
||||
break;
|
||||
@@ -1771,6 +1849,13 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||
|
||||
usbd_xotg->gadget = gadget;
|
||||
|
||||
/*
|
||||
* Set interrupt moderation to 0us.
|
||||
* This is important because default value creates a 4.62ms latency.
|
||||
* Effectively hurting transfers by having 15% to 96% performance loss.
|
||||
*/
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_RT_IMOD) = 0;
|
||||
|
||||
// Disable Wake events.
|
||||
XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_0) = 0;
|
||||
XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_1) = 0;
|
||||
@@ -1803,7 +1888,7 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||
u32 timer = get_tmr_ms() + 90000;
|
||||
while (true)
|
||||
{
|
||||
int res = _xusb_ep_operation(1000000); // 2s timeout.
|
||||
int res = _xusb_ep_operation(USB_XFER_SYNCED_ENUM); // 2s timeout.
|
||||
if (res && res != USB_ERROR_TIMEOUT)
|
||||
return res;
|
||||
|
||||
@@ -1817,6 +1902,7 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
//! TODO: Do a full deinit.
|
||||
void xusb_end(bool reset_ep, bool only_controller)
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_SS);
|
||||
@@ -1826,7 +1912,7 @@ void xusb_end(bool reset_ep, bool only_controller)
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB);
|
||||
mc_disable_ahb_redirect();///////////////////
|
||||
mc_disable_ahb_redirect(); // Can be skipped if IRAM is not used.
|
||||
}
|
||||
|
||||
int xusb_handle_ep0_ctrl_setup()
|
||||
@@ -1844,24 +1930,24 @@ int xusb_handle_ep0_ctrl_setup()
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
|
||||
int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries)
|
||||
{
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
|
||||
int res = USB_RES_OK;
|
||||
usbd_xotg->tx_count[USB_DIR_OUT] = 0;
|
||||
usbd_xotg->bytes_remaining[USB_DIR_OUT] = len;
|
||||
usbd_xotg->tx_bytes[USB_DIR_OUT] = len;
|
||||
_xusb_issue_normal_trb(buf, len, USB_DIR_OUT);
|
||||
usbd_xotg->tx_count[USB_DIR_OUT]++;
|
||||
|
||||
if (sync)
|
||||
if (sync_tries)
|
||||
{
|
||||
while (!res && usbd_xotg->tx_count[USB_DIR_OUT])
|
||||
res = _xusb_ep_operation(1000000); // 2s timeout.
|
||||
res = _xusb_ep_operation(sync_tries);
|
||||
|
||||
if (bytes_read)
|
||||
*bytes_read = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT];
|
||||
*bytes_read = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_OUT];
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
}
|
||||
@@ -1882,7 +1968,7 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
|
||||
{
|
||||
u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE);
|
||||
|
||||
int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED);
|
||||
int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
@@ -1894,21 +1980,21 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
|
||||
int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, u32 sync_tries)
|
||||
{
|
||||
int res = USB_RES_OK;
|
||||
while (!res && usbd_xotg->tx_count[USB_DIR_OUT])
|
||||
res = _xusb_ep_operation(tries);
|
||||
res = _xusb_ep_operation(sync_tries); // Infinite retries.
|
||||
|
||||
if (pending_bytes)
|
||||
*pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT];
|
||||
*pending_bytes = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_OUT];
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_tries)
|
||||
{
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
@@ -1917,17 +2003,17 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
|
||||
int res = USB_RES_OK;
|
||||
usbd_xotg->tx_count[USB_DIR_IN] = 0;
|
||||
usbd_xotg->bytes_remaining[USB_DIR_IN] = len;
|
||||
usbd_xotg->tx_bytes[USB_DIR_IN] = len;
|
||||
_xusb_issue_normal_trb(buf, len, USB_DIR_IN);
|
||||
usbd_xotg->tx_count[USB_DIR_IN]++;
|
||||
|
||||
if (sync)
|
||||
if (sync_tries)
|
||||
{
|
||||
while (!res && usbd_xotg->tx_count[USB_DIR_IN])
|
||||
res = _xusb_ep_operation(1000000); // 2s timeout.
|
||||
res = _xusb_ep_operation(sync_tries);
|
||||
|
||||
if (bytes_written)
|
||||
*bytes_written = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN];
|
||||
*bytes_written = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_IN];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1943,14 +2029,14 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
return res;
|
||||
}
|
||||
|
||||
int xusb_device_ep1_in_writing_finish(u32 *pending_bytes)
|
||||
int xusb_device_ep1_in_writing_finish(u32 *pending_bytes, u32 sync_tries)
|
||||
{
|
||||
int res = USB_RES_OK;
|
||||
while (!res && usbd_xotg->tx_count[USB_DIR_IN])
|
||||
res = _xusb_ep_operation(1000000); // 2s timeout.
|
||||
res = _xusb_ep_operation(sync_tries); // Infinite retries.
|
||||
|
||||
if (pending_bytes)
|
||||
*pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN];
|
||||
*pending_bytes = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_IN];
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1973,7 +2059,7 @@ bool xusb_device_class_send_max_lun(u8 max_lun)
|
||||
// Wait for request and transfer start.
|
||||
while (usbd_xotg->device_state != XUSB_LUN_CONFIGURED)
|
||||
{
|
||||
_xusb_ep_operation(500000);
|
||||
_xusb_ep_operation(USB_XFER_SYNCED_CLASS);
|
||||
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
return true;
|
||||
}
|
||||
@@ -1991,7 +2077,7 @@ bool xusb_device_class_send_hid_report()
|
||||
// Wait for request and transfer start.
|
||||
while (usbd_xotg->device_state != XUSB_HID_CONFIGURED)
|
||||
{
|
||||
_xusb_ep_operation(500000);
|
||||
_xusb_ep_operation(USB_XFER_SYNCED_CLASS);
|
||||
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
return true;
|
||||
}
|
||||
@@ -2006,7 +2092,7 @@ void xusb_device_get_ops(usb_ops_t *ops)
|
||||
ops->usbd_flush_endpoint = NULL;
|
||||
ops->usbd_set_ep_stall = xusb_set_ep_stall;
|
||||
ops->usbd_handle_ep0_ctrl_setup = xusb_handle_ep0_ctrl_setup;
|
||||
ops->usbd_end = xusb_end;//////////////////
|
||||
ops->usbd_end = xusb_end;
|
||||
ops->usb_device_init = xusb_device_init;
|
||||
ops->usb_device_enumerate = xusb_device_enumerate;
|
||||
ops->usb_device_class_send_max_lun = xusb_device_class_send_max_lun;
|
||||
|
||||
@@ -29,7 +29,7 @@ u8 btn_read()
|
||||
res |= BTN_VOL_DOWN;
|
||||
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
|
||||
res |= BTN_VOL_UP;
|
||||
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & 0x4)
|
||||
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0)
|
||||
res |= BTN_POWER;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -21,16 +21,16 @@
|
||||
#include <mem/heap.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
#define MAX_ENTRIES 64
|
||||
|
||||
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
|
||||
{
|
||||
u8 max_entries = 61;
|
||||
|
||||
int res = 0;
|
||||
u32 i = 0, j = 0, k = 0;
|
||||
DIR dir;
|
||||
FILINFO fno;
|
||||
|
||||
char *dir_entries = (char *)calloc(max_entries, 256);
|
||||
char *dir_entries = (char *)calloc(MAX_ENTRIES, 256);
|
||||
char *temp = (char *)calloc(1, 256);
|
||||
|
||||
if (!pattern && !f_opendir(&dir, directory))
|
||||
@@ -49,7 +49,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
||||
{
|
||||
strcpy(dir_entries + (k * 256), fno.fname);
|
||||
k++;
|
||||
if (k > (max_entries - 1))
|
||||
if (k > (MAX_ENTRIES - 1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
||||
{
|
||||
strcpy(dir_entries + (k * 256), fno.fname);
|
||||
k++;
|
||||
if (k > (max_entries - 1))
|
||||
if (k > (MAX_ENTRIES - 1))
|
||||
break;
|
||||
}
|
||||
res = f_findnext(&dir, &fno);
|
||||
|
||||
@@ -66,14 +66,14 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type
|
||||
|
||||
int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
{
|
||||
FIL fp;
|
||||
u32 lblen;
|
||||
u32 pathlen = strlen(ini_path);
|
||||
u32 k = 0;
|
||||
char lbuf[512];
|
||||
char *filelist = NULL;
|
||||
FIL fp;
|
||||
ini_sec_t *csec = NULL;
|
||||
|
||||
char *lbuf = NULL;
|
||||
char *filelist = NULL;
|
||||
char *filename = (char *)malloc(256);
|
||||
|
||||
strcpy(filename, ini_path);
|
||||
@@ -114,6 +114,8 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
lbuf = malloc(512);
|
||||
|
||||
do
|
||||
{
|
||||
// Fetch one line.
|
||||
@@ -168,6 +170,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
}
|
||||
} while (is_dir);
|
||||
|
||||
free(lbuf);
|
||||
free(filename);
|
||||
free(filelist);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -18,26 +18,18 @@
|
||||
#ifndef _TYPES_H_
|
||||
#define _TYPES_H_
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
#define ALIGN_DOWN(x, a) (((x) - ((a) - 1)) & ~((a) - 1))
|
||||
#define BIT(n) (1U << (n))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
|
||||
#define OFFSET_OF(t, m) ((u32)&((t *)NULL)->m)
|
||||
#define CONTAINER_OF(mp, t, mn) ((t *)((u32)mp - OFFSET_OF(t, mn)))
|
||||
#include <assert.h>
|
||||
|
||||
/* Types */
|
||||
typedef signed char s8;
|
||||
typedef short s16;
|
||||
typedef short SHORT;
|
||||
typedef int s32;
|
||||
typedef int INT;
|
||||
typedef int bool;
|
||||
typedef long LONG;
|
||||
typedef long long int s64;
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short u16;
|
||||
@@ -48,6 +40,7 @@ typedef unsigned int UINT;
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned long long QWORD;
|
||||
typedef unsigned long long int u64;
|
||||
|
||||
typedef volatile unsigned char vu8;
|
||||
typedef volatile unsigned short vu16;
|
||||
typedef volatile unsigned int vu32;
|
||||
@@ -58,24 +51,70 @@ typedef u64 uptr;
|
||||
typedef u32 uptr;
|
||||
#endif
|
||||
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
/* Important */
|
||||
#define false 0
|
||||
#define true 1
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
/* Misc */
|
||||
#define DISABLE 0
|
||||
#define ENABLE 1
|
||||
|
||||
/* Sizes */
|
||||
#define SZ_1K 0x400
|
||||
#define SZ_2K 0x800
|
||||
#define SZ_4K 0x1000
|
||||
#define SZ_8K 0x2000
|
||||
#define SZ_16K 0x4000
|
||||
#define SZ_32K 0x8000
|
||||
#define SZ_64K 0x10000
|
||||
#define SZ_128K 0x20000
|
||||
#define SZ_256K 0x40000
|
||||
#define SZ_512K 0x80000
|
||||
#define SZ_1M 0x100000
|
||||
#define SZ_2M 0x200000
|
||||
#define SZ_4M 0x400000
|
||||
#define SZ_8M 0x800000
|
||||
#define SZ_16M 0x1000000
|
||||
#define SZ_32M 0x2000000
|
||||
#define SZ_64M 0x4000000
|
||||
#define SZ_128M 0x8000000
|
||||
#define SZ_256M 0x10000000
|
||||
#define SZ_512M 0x20000000
|
||||
#define SZ_1G 0x40000000
|
||||
#define SZ_2G 0x80000000
|
||||
#define SZ_PAGE SZ_4K
|
||||
|
||||
/* Macros */
|
||||
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
|
||||
#define BIT(n) (1U << (n))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
|
||||
#define OFFSET_OF(t, m) ((uptr)&((t *)NULL)->m)
|
||||
#define CONTAINER_OF(mp, t, mn) ((t *)((uptr)mp - OFFSET_OF(t, mn)))
|
||||
|
||||
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
|
||||
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
|
||||
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
|
||||
|
||||
|
||||
/* Bootloader/Nyx */
|
||||
#define BOOT_CFG_AUTOBOOT_EN BIT(0)
|
||||
#define BOOT_CFG_FROM_LAUNCH BIT(1)
|
||||
#define BOOT_CFG_FROM_ID BIT(2)
|
||||
#define BOOT_CFG_TO_EMUMMC BIT(3)
|
||||
#define BOOT_CFG_SEPT_RUN BIT(7)
|
||||
|
||||
#define EXTRA_CFG_KEYS BIT(0)
|
||||
#define EXTRA_CFG_PAYLOAD BIT(1)
|
||||
#define EXTRA_CFG_MODULE BIT(2)
|
||||
|
||||
#define EXTRA_CFG_NYX_BIS BIT(4)
|
||||
#define EXTRA_CFG_NYX_UMS BIT(5)
|
||||
#define EXTRA_CFG_NYX_RELOAD BIT(6)
|
||||
#define EXTRA_CFG_NYX_DUMP BIT(7)
|
||||
|
||||
typedef enum _nyx_ums_type
|
||||
{
|
||||
@@ -106,6 +145,8 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||
};
|
||||
} boot_cfg_t;
|
||||
|
||||
static_assert(sizeof(boot_cfg_t) == 0x84, "Boot cfg storage size is wrong!");
|
||||
|
||||
typedef struct __attribute__((__packed__)) _ipl_ver_meta_t
|
||||
{
|
||||
u32 magic;
|
||||
|
||||
104
bdk/utils/util.c
104
bdk/utils/util.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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,
|
||||
@@ -30,6 +30,27 @@
|
||||
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
u8 bit_count(u32 val)
|
||||
{
|
||||
u8 cnt = 0;
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
{
|
||||
if ((val >> i) & 1)
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
u32 bit_count_mask(u8 bits)
|
||||
{
|
||||
u32 val = 0;
|
||||
for (u32 i = 0; i < bits; i++)
|
||||
val |= 1 << i;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 get_tmr_s()
|
||||
{
|
||||
return RTC(APBDEV_RTC_SECONDS);
|
||||
@@ -132,53 +153,58 @@ void panic(u32 val)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
void reboot_normal()
|
||||
void power_set_state(power_state_t state)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
// Unmount and power down sd card.
|
||||
sd_end();
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
panic(0x21); // Bypass fuse programming in package1.
|
||||
}
|
||||
|
||||
void reboot_rcm()
|
||||
{
|
||||
sd_end();
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM;
|
||||
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
|
||||
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
}
|
||||
|
||||
void reboot_full()
|
||||
{
|
||||
sd_end();
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
// Enable soft reset wake event.
|
||||
u8 reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
|
||||
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
|
||||
|
||||
// Do a soft reset.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
|
||||
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
}
|
||||
|
||||
void power_off()
|
||||
{
|
||||
sd_end();
|
||||
// De-initialize and power down various hardware.
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
// Stop the alarm, in case we injected and powered off too fast.
|
||||
max77620_rtc_stop_alarm();
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
// Set power state.
|
||||
switch (state)
|
||||
{
|
||||
case REBOOT_RCM:
|
||||
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; // Enable RCM path.
|
||||
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; // PMC reset.
|
||||
break;
|
||||
|
||||
case REBOOT_BYPASS_FUSES:
|
||||
panic(0x21); // Bypass fuse programming in package1.
|
||||
break;
|
||||
|
||||
case POWER_OFF:
|
||||
// Initiate power down sequence and do not generate a reset (regulators retain state).
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
break;
|
||||
|
||||
case POWER_OFF_RESET:
|
||||
case POWER_OFF_REBOOT:
|
||||
default:
|
||||
// Enable/Disable soft reset wake event.
|
||||
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
|
||||
if (state == POWER_OFF_RESET) // Do not wake up after power off.
|
||||
reg &= ~(MAX77620_ONOFFCNFG2_SFT_RST_WK | MAX77620_ONOFFCNFG2_WK_ALARM1 | MAX77620_ONOFFCNFG2_WK_ALARM2);
|
||||
else // POWER_OFF_REBOOT. Wake up after power off.
|
||||
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
|
||||
|
||||
// Initiate power down sequence and generate a reset (regulators' state resets).
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
|
||||
break;
|
||||
}
|
||||
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
}
|
||||
|
||||
void power_set_state_ex(void *param)
|
||||
{
|
||||
power_state_t *state = (power_state_t *)param;
|
||||
power_set_state(*state);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -25,9 +25,19 @@
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NYX_CFG_BIS = BIT(5),
|
||||
REBOOT_RCM, // PMC reset. Enter RCM mode.
|
||||
REBOOT_BYPASS_FUSES, // PMC reset via watchdog. Enter Normal mode. Bypass fuse programming in package1.
|
||||
|
||||
POWER_OFF, // Power off PMIC. Do not reset regulators.
|
||||
POWER_OFF_RESET, // Power off PMIC. Reset regulators.
|
||||
POWER_OFF_REBOOT, // Power off PMIC. Reset regulators. Power on.
|
||||
} power_state_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NYX_CFG_UMS = BIT(6),
|
||||
NYX_CFG_DUMP = BIT(7),
|
||||
|
||||
NYX_CFG_EXTRA = 0xFF << 24
|
||||
} nyx_cfg_t;
|
||||
|
||||
typedef enum
|
||||
@@ -36,13 +46,11 @@ typedef enum
|
||||
ERR_SYSOLD_NYX = BIT(1),
|
||||
ERR_LIBSYS_MTC = BIT(2),
|
||||
ERR_SD_BOOT_EN = BIT(3),
|
||||
ERR_PANIC_CODE = BIT(4),
|
||||
ERR_L4T_KERNEL = BIT(24),
|
||||
ERR_EXCEPTION = BIT(31),
|
||||
} hekate_errors_t;
|
||||
|
||||
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
|
||||
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
|
||||
|
||||
typedef struct _cfg_op_t
|
||||
{
|
||||
u32 off;
|
||||
@@ -65,23 +73,27 @@ typedef struct _nyx_storage_t
|
||||
u32 cfg;
|
||||
u8 irama[0x8000];
|
||||
u8 hekate[0x30000];
|
||||
u8 rsvd[0x800000 - sizeof(nyx_info_t)];
|
||||
u8 rsvd[SZ_8M - sizeof(nyx_info_t)];
|
||||
nyx_info_t info;
|
||||
mtc_config_t mtc_cfg;
|
||||
emc_table_t mtc_table[10];
|
||||
} nyx_storage_t;
|
||||
|
||||
u32 get_tmr_us();
|
||||
u32 get_tmr_ms();
|
||||
u32 get_tmr_s();
|
||||
void usleep(u32 us);
|
||||
void msleep(u32 ms);
|
||||
void panic(u32 val);
|
||||
void reboot_normal();
|
||||
void reboot_rcm();
|
||||
void reboot_full();
|
||||
void power_off();
|
||||
u8 bit_count(u32 val);
|
||||
u32 bit_count_mask(u8 bits);
|
||||
|
||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
|
||||
|
||||
u32 get_tmr_us();
|
||||
u32 get_tmr_ms();
|
||||
u32 get_tmr_s();
|
||||
void usleep(u32 us);
|
||||
void msleep(u32 ms);
|
||||
|
||||
void panic(u32 val);
|
||||
void power_set_state(power_state_t state);
|
||||
void power_set_state_ex(void *param);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -38,7 +38,6 @@ void set_default_configuration()
|
||||
h_cfg.autoboot = 0;
|
||||
h_cfg.autoboot_list = 0;
|
||||
h_cfg.bootwait = 3;
|
||||
h_cfg.se_keygen_done = 0;
|
||||
h_cfg.backlight = 100;
|
||||
h_cfg.autohosoff = 0;
|
||||
h_cfg.autonogc = 1;
|
||||
@@ -46,8 +45,6 @@ void set_default_configuration()
|
||||
h_cfg.bootprotect = 0;
|
||||
h_cfg.errors = 0;
|
||||
h_cfg.eks = NULL;
|
||||
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
|
||||
h_cfg.aes_slots_new = false;
|
||||
h_cfg.rcm_patched = fuse_check_patched_rcm();
|
||||
h_cfg.emummc_force_disable = false;
|
||||
h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;
|
||||
@@ -58,7 +55,7 @@ int create_config_entry()
|
||||
if (!sd_mount())
|
||||
return 1;
|
||||
|
||||
char lbuf[32];
|
||||
char lbuf[64];
|
||||
FIL fp;
|
||||
bool mainIniFound = false;
|
||||
|
||||
@@ -86,28 +83,36 @@ int create_config_entry()
|
||||
|
||||
if (f_open(&fp, "bootloader/hekate_ipl.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
|
||||
return 1;
|
||||
|
||||
// Add config entry.
|
||||
f_puts("[config]\nautoboot=", &fp);
|
||||
itoa(h_cfg.autoboot, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
|
||||
f_puts("\nautoboot_list=", &fp);
|
||||
itoa(h_cfg.autoboot_list, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
|
||||
f_puts("\nbootwait=", &fp);
|
||||
itoa(h_cfg.bootwait, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
|
||||
f_puts("\nbacklight=", &fp);
|
||||
itoa(h_cfg.backlight, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
|
||||
f_puts("\nautohosoff=", &fp);
|
||||
itoa(h_cfg.autohosoff, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
|
||||
f_puts("\nautonogc=", &fp);
|
||||
itoa(h_cfg.autonogc, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
|
||||
f_puts("\nupdater2p=", &fp);
|
||||
itoa(h_cfg.updater2p, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
|
||||
f_puts("\nbootprotect=", &fp);
|
||||
itoa(h_cfg.bootprotect, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
@@ -158,452 +163,3 @@ int create_config_entry()
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
static void _save_config()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!create_config_entry())
|
||||
gfx_puts("\nConfiguration was saved!\n");
|
||||
else
|
||||
EPRINTF("\nConfiguration saving failed!");
|
||||
gfx_puts("\nPress any key...");
|
||||
}
|
||||
|
||||
static void _config_autoboot_list(void *ent)
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 *temp_autoboot = NULL;
|
||||
|
||||
LIST_INIT(ini_sections);
|
||||
|
||||
u8 max_entries = 30;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
||||
u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries);
|
||||
char *boot_text = (char *)malloc(512 * max_entries);
|
||||
|
||||
for (u32 j = 0; j < max_entries; j++)
|
||||
boot_values[j] = j;
|
||||
|
||||
if (sd_mount())
|
||||
{
|
||||
if (ini_parse(&ini_sections, "bootloader/ini", true))
|
||||
{
|
||||
// Build configuration menu.
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
u32 i = 2;
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
// Skip other ini entries for autoboot.
|
||||
if (ini_sec->type == INI_CHOICE)
|
||||
{
|
||||
if (!strcmp(ini_sec->name, "config"))
|
||||
continue;
|
||||
|
||||
if (strlen(ini_sec->name) > 510)
|
||||
ments[i].caption = ini_sec->name;
|
||||
else
|
||||
{
|
||||
if (h_cfg.autoboot != (i - 1) || !h_cfg.autoboot_list)
|
||||
boot_text[(i - 1) * 512] = ' ';
|
||||
|
||||
else
|
||||
boot_text[(i - 1) * 512] = '*';
|
||||
strcpy(boot_text + (i - 1) * 512 + 1, ini_sec->name);
|
||||
ments[i].caption = &boot_text[(i - 1) * 512];
|
||||
}
|
||||
ments[i].type = ini_sec->type;
|
||||
ments[i].data = &boot_values[i - 1];
|
||||
i++;
|
||||
|
||||
if ((i - 1) > max_entries)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&ments[i], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Select an entry to auto boot", 0, 0};
|
||||
temp_autoboot = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_autoboot != NULL)
|
||||
{
|
||||
h_cfg.autoboot = *(u32 *)temp_autoboot;
|
||||
h_cfg.autoboot_list = 1;
|
||||
_save_config();
|
||||
|
||||
ment_t *tmp = (ment_t *)ent;
|
||||
tmp->data = NULL;
|
||||
}
|
||||
else
|
||||
goto out2;
|
||||
}
|
||||
else
|
||||
{
|
||||
EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!.");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:;
|
||||
btn_wait();
|
||||
out2:;
|
||||
free(ments);
|
||||
free(boot_values);
|
||||
free(boot_text);
|
||||
|
||||
sd_end();
|
||||
}
|
||||
|
||||
void config_autoboot()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 *temp_autoboot = NULL;
|
||||
|
||||
LIST_INIT(ini_sections);
|
||||
|
||||
u8 max_entries = 30;
|
||||
u32 boot_text_size = 512;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 5));
|
||||
u32 *boot_values = (u32 *)malloc(sizeof(u32) * max_entries);
|
||||
char *boot_text = (char *)malloc(boot_text_size * max_entries);
|
||||
|
||||
for (u32 j = 0; j < max_entries; j++)
|
||||
boot_values[j] = j;
|
||||
|
||||
if (sd_mount())
|
||||
{
|
||||
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
||||
{
|
||||
// Build configuration menu.
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
ments[2].type = MENT_DATA;
|
||||
if (!h_cfg.autoboot)
|
||||
ments[2].caption = "*Disable";
|
||||
else
|
||||
ments[2].caption = " Disable";
|
||||
ments[2].data = &boot_values[0];
|
||||
|
||||
ments[3].type = MENT_HDLR_RE;
|
||||
if (h_cfg.autoboot_list)
|
||||
ments[3].caption = "*More configs...";
|
||||
else
|
||||
ments[3].caption = " More configs...";
|
||||
ments[3].handler = _config_autoboot_list;
|
||||
ments[3].data = (void *)0xCAFE;
|
||||
|
||||
ments[4].type = MENT_CHGLINE;
|
||||
|
||||
u32 i = 5;
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
// Skip other ini entries for autoboot.
|
||||
if (ini_sec->type == INI_CHOICE)
|
||||
{
|
||||
if (!strcmp(ini_sec->name, "config"))
|
||||
continue;
|
||||
|
||||
if (strlen(ini_sec->name) > 510)
|
||||
ments[i].caption = ini_sec->name;
|
||||
else
|
||||
{
|
||||
if (h_cfg.autoboot != (i - 4) || h_cfg.autoboot_list)
|
||||
boot_text[(i - 4) * boot_text_size] = ' ';
|
||||
|
||||
else
|
||||
boot_text[(i - 4) * boot_text_size] = '*';
|
||||
strcpy(boot_text + (i - 4) * boot_text_size + 1, ini_sec->name);
|
||||
ments[i].caption = &boot_text[(i - 4) * boot_text_size];
|
||||
}
|
||||
ments[i].type = ini_sec->type;
|
||||
ments[i].data = &boot_values[i - 4];
|
||||
i++;
|
||||
|
||||
if ((i - 4) > max_entries)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 6 && !h_cfg.autoboot_list)
|
||||
{
|
||||
ments[i].type = MENT_CAPTION;
|
||||
ments[i].caption = "No main configurations found...";
|
||||
ments[i].color = 0xFFFFDD00;
|
||||
i++;
|
||||
}
|
||||
|
||||
memset(&ments[i], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Disable or select entry to auto boot", 0, 0};
|
||||
temp_autoboot = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_autoboot != NULL)
|
||||
{
|
||||
h_cfg.autoboot = *(u32 *)temp_autoboot;
|
||||
h_cfg.autoboot_list = 0;
|
||||
_save_config();
|
||||
}
|
||||
else
|
||||
goto out2;
|
||||
}
|
||||
else
|
||||
{
|
||||
EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!.");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:;
|
||||
btn_wait();
|
||||
out2:;
|
||||
free(ments);
|
||||
free(boot_values);
|
||||
free(boot_text);
|
||||
|
||||
sd_end();
|
||||
|
||||
if (temp_autoboot == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
void config_bootdelay()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 delay_entries = 6;
|
||||
u32 delay_text_size = 32;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (delay_entries + 3));
|
||||
u32 *delay_values = (u32 *)malloc(sizeof(u32) * delay_entries);
|
||||
char *delay_text = (char *)malloc(delay_text_size * delay_entries);
|
||||
|
||||
for (u32 j = 0; j < delay_entries; j++)
|
||||
delay_values[j] = j;
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
ments[2].type = MENT_DATA;
|
||||
if (h_cfg.bootwait)
|
||||
ments[2].caption = " 0 seconds (Bootlogo disabled)";
|
||||
else
|
||||
ments[2].caption = "*0 seconds (Bootlogo disabled)";
|
||||
ments[2].data = &delay_values[0];
|
||||
|
||||
u32 i = 0;
|
||||
for (i = 1; i < delay_entries; i++)
|
||||
{
|
||||
if (h_cfg.bootwait != i)
|
||||
delay_text[i * delay_text_size] = ' ';
|
||||
else
|
||||
delay_text[i * delay_text_size] = '*';
|
||||
delay_text[i * delay_text_size + 1] = i + '0';
|
||||
strcpy(delay_text + i * delay_text_size + 2, " seconds");
|
||||
|
||||
ments[i + 2].type = MENT_DATA;
|
||||
ments[i + 2].caption = delay_text + (i * delay_text_size);
|
||||
ments[i + 2].data = &delay_values[i];
|
||||
}
|
||||
|
||||
memset(&ments[i + 2], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Time delay for entering bootloader menu", 0, 0};
|
||||
|
||||
u32 *temp_bootwait = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_bootwait != NULL)
|
||||
{
|
||||
h_cfg.bootwait = *(u32 *)temp_bootwait;
|
||||
_save_config();
|
||||
}
|
||||
|
||||
free(ments);
|
||||
free(delay_values);
|
||||
free(delay_text);
|
||||
|
||||
if (temp_bootwait == NULL)
|
||||
return;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void config_backlight()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 bri_text_size = 8;
|
||||
u32 bri_entries = 11;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (bri_entries + 3));
|
||||
u32 *bri_values = (u32 *)malloc(sizeof(u32) * bri_entries);
|
||||
char *bri_text = (char *)malloc(bri_text_size * bri_entries);
|
||||
|
||||
for (u32 j = 1; j < bri_entries; j++)
|
||||
bri_values[j] = j * 10;
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
u32 i = 0;
|
||||
for (i = 1; i < bri_entries; i++)
|
||||
{
|
||||
if ((h_cfg.backlight / 20) != i)
|
||||
bri_text[i * bri_text_size] = ' ';
|
||||
else
|
||||
bri_text[i * bri_text_size] = '*';
|
||||
|
||||
if (i < 10)
|
||||
{
|
||||
bri_text[i * bri_text_size + 1] = i + '0';
|
||||
strcpy(bri_text + i * bri_text_size + 2, "0%");
|
||||
}
|
||||
else
|
||||
strcpy(bri_text + i * bri_text_size + 1, "100%");
|
||||
|
||||
ments[i + 1].type = MENT_DATA;
|
||||
ments[i + 1].caption = bri_text + (i * bri_text_size);
|
||||
ments[i + 1].data = &bri_values[i];
|
||||
}
|
||||
|
||||
memset(&ments[i + 1], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Backlight brightness", 0, 0};
|
||||
|
||||
u32 *temp_backlight = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_backlight != NULL)
|
||||
{
|
||||
h_cfg.backlight = (*(u32 *)temp_backlight) * 2;
|
||||
_save_config();
|
||||
}
|
||||
|
||||
free(ments);
|
||||
free(bri_values);
|
||||
free(bri_text);
|
||||
|
||||
if (temp_backlight == NULL)
|
||||
return;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void config_auto_hos_poweroff()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6);
|
||||
u32 *hp_values = (u32 *)malloc(sizeof(u32) * 3);
|
||||
|
||||
for (u32 j = 0; j < 3; j++)
|
||||
{
|
||||
hp_values[j] = j;
|
||||
ments[j + 2].type = MENT_DATA;
|
||||
ments[j + 2].data = &hp_values[j];
|
||||
}
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
if (h_cfg.autohosoff == 1)
|
||||
{
|
||||
ments[2].caption = " Disable";
|
||||
ments[3].caption = "*Enable";
|
||||
ments[4].caption = " Enable (No logo)";
|
||||
}
|
||||
else if (h_cfg.autohosoff >= 2)
|
||||
{
|
||||
ments[2].caption = " Disable";
|
||||
ments[3].caption = " Enable";
|
||||
ments[4].caption = "*Enable (No logo)";
|
||||
}
|
||||
else
|
||||
{
|
||||
ments[2].caption = "*Disable";
|
||||
ments[3].caption = " Enable";
|
||||
ments[4].caption = " Enable (No logo)";
|
||||
}
|
||||
|
||||
memset(&ments[5], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "Power off if woke up from HOS", 0, 0};
|
||||
|
||||
u32 *temp_autohosoff = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_autohosoff != NULL)
|
||||
{
|
||||
h_cfg.autohosoff = *(u32 *)temp_autohosoff;
|
||||
_save_config();
|
||||
}
|
||||
|
||||
free(ments);
|
||||
free(hp_values);
|
||||
|
||||
if (temp_autohosoff == NULL)
|
||||
return;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void config_nogc()
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 5);
|
||||
u32 *cb_values = (u32 *)malloc(sizeof(u32) * 2);
|
||||
|
||||
for (u32 j = 0; j < 2; j++)
|
||||
{
|
||||
cb_values[j] = j;
|
||||
ments[j + 2].type = MENT_DATA;
|
||||
ments[j + 2].data = &cb_values[j];
|
||||
}
|
||||
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
if (h_cfg.autonogc)
|
||||
{
|
||||
ments[2].caption = " Disable";
|
||||
ments[3].caption = "*Auto";
|
||||
}
|
||||
else
|
||||
{
|
||||
ments[2].caption = "*Disable";
|
||||
ments[3].caption = " Auto";
|
||||
}
|
||||
|
||||
memset(&ments[4], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "No Gamecard", 0, 0};
|
||||
|
||||
u32 *temp_nogc = (u32 *)tui_do_menu(&menu);
|
||||
if (temp_nogc != NULL)
|
||||
{
|
||||
h_cfg.autonogc = *(u32 *)temp_nogc;
|
||||
_save_config();
|
||||
}
|
||||
|
||||
free(ments);
|
||||
free(cb_values);
|
||||
|
||||
if (temp_nogc == NULL)
|
||||
return;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -33,9 +33,6 @@ typedef struct _hekate_config
|
||||
u32 bootprotect;
|
||||
// Global temporary config.
|
||||
bool t210b01;
|
||||
bool se_keygen_done;
|
||||
bool sept_run;
|
||||
bool aes_slots_new;
|
||||
bool emummc_force_disable;
|
||||
bool rcm_patched;
|
||||
u32 errors;
|
||||
@@ -44,10 +41,5 @@ typedef struct _hekate_config
|
||||
|
||||
void set_default_configuration();
|
||||
int create_config_entry();
|
||||
void config_autoboot();
|
||||
void config_bootdelay();
|
||||
void config_backlight();
|
||||
void config_auto_hos_poweroff();
|
||||
void config_nogc();
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 Rajko Stojadinovic
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
@@ -96,7 +97,7 @@ static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFi
|
||||
|
||||
se_calc_sha256_oneshot(hashEm, bufEm, num << 9);
|
||||
se_calc_sha256_oneshot(hashSd, bufSd, num << 9);
|
||||
res = memcmp(hashEm, hashSd, 0x10);
|
||||
res = memcmp(hashEm, hashSd, SE_SHA_256_SIZE / 2);
|
||||
|
||||
if (res)
|
||||
{
|
||||
@@ -735,7 +736,7 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nFatal error (%d) when reading from SD Card", res);
|
||||
EPRINTF("\nYour device may be in an inoperative state!\n\nPress any key and try again now...\n");
|
||||
EPRINTF("\nThis device may be in an inoperative state!\n\nPress any key and try again now...\n");
|
||||
|
||||
f_close(&fp);
|
||||
return 0;
|
||||
@@ -751,7 +752,7 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTFARGS("\nFailed to write %d blocks @ LBA %08X\nfrom eMMC. Aborting..\n",
|
||||
num, lba_curr);
|
||||
EPRINTF("\nYour device may be in an inoperative state!\n\nPress any key and try again...\n");
|
||||
EPRINTF("\nThis device may be in an inoperative state!\n\nPress any key and try again...\n");
|
||||
|
||||
f_close(&fp);
|
||||
return 0;
|
||||
@@ -797,7 +798,7 @@ static void _restore_emmc_selected(emmcPartType_t restoreType)
|
||||
tui_sbar(true);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
gfx_printf("%kThis may render your device inoperative!\n\n", 0xFFFFDD00);
|
||||
gfx_printf("%kThis may render the device inoperative!\n\n", 0xFFFFDD00);
|
||||
gfx_printf("Are you really sure?\n\n%k", 0xFFCCCCCC);
|
||||
if ((restoreType & PART_BOOT) || (restoreType & PART_GP_ALL))
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "fe_info.h"
|
||||
#include "../config.h"
|
||||
#include <gfx_utils.h>
|
||||
#include "../hos/hos.h"
|
||||
#include "../hos/pkg1.h"
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <mem/smmu.h>
|
||||
#include <power/bq24193.h>
|
||||
#include <power/max17050.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include <sec/tsec.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/i2c.h>
|
||||
@@ -39,6 +41,7 @@
|
||||
#include <utils/btn.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#pragma GCC push_options
|
||||
@@ -46,34 +49,31 @@ extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_st
|
||||
|
||||
void print_fuseinfo()
|
||||
{
|
||||
u32 fuse_size = h_cfg.t210b01 ? 0x368 : 0x300;
|
||||
u32 fuse_address = h_cfg.t210b01 ? 0x7000F898 : 0x7000F900;
|
||||
u32 fuse_array_size = (h_cfg.t210b01 ? 256 : 192) * sizeof(u32);
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 burntFuses = 0;
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
{
|
||||
if ((fuse_read_odm(7) >> i) & 1)
|
||||
burntFuses++;
|
||||
}
|
||||
|
||||
gfx_printf("\nSKU: %X - ", FUSE(FUSE_SKU_INFO));
|
||||
switch (fuse_read_odm(4) & 3)
|
||||
switch (fuse_read_hw_state())
|
||||
{
|
||||
case 0:
|
||||
case FUSE_NX_HW_STATE_PROD:
|
||||
gfx_printf("Retail\n");
|
||||
break;
|
||||
case 3:
|
||||
case FUSE_NX_HW_STATE_DEV:
|
||||
gfx_printf("Dev\n");
|
||||
break;
|
||||
}
|
||||
gfx_printf("Sdram ID: %d\n", (fuse_read_odm(4) >> 3) & 0x1F);
|
||||
gfx_printf("Burnt fuses: %d / 64\n", burntFuses);
|
||||
gfx_printf("Sdram ID: %d\n", fuse_read_dramid(true));
|
||||
gfx_printf("Burnt fuses: %d / 64\n", bit_count(fuse_read_odm(7)));
|
||||
gfx_printf("Secure key: %08X%08X%08X%08X\n\n\n",
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY0)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY1)),
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY2)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY3)));
|
||||
|
||||
gfx_printf("%k(Unlocked) fuse cache:\n\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_hexdump(0x7000F900, (u8 *)0x7000F900, 0x300);
|
||||
gfx_printf("%kFuse cache:\n\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_hexdump(fuse_address, (u8 *)fuse_address, fuse_size);
|
||||
|
||||
gfx_puts("\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
@@ -84,13 +84,13 @@ void print_fuseinfo()
|
||||
{
|
||||
char path[64];
|
||||
emmcsn_path_impl(path, "/dumps", "fuse_cached.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)0x7000F900, 0x300, path))
|
||||
if (!sd_save_to_file((u8 *)fuse_address, fuse_size, path))
|
||||
gfx_puts("\nfuse_cached.bin saved!\n");
|
||||
|
||||
u32 words[192];
|
||||
u32 words[256];
|
||||
fuse_read_array(words);
|
||||
emmcsn_path_impl(path, "/dumps", "fuse_array_raw.bin", NULL);
|
||||
if (!sd_save_to_file((u8 *)words, sizeof(words), path))
|
||||
if (!sd_save_to_file((u8 *)words, fuse_array_size, path))
|
||||
gfx_puts("\nfuse_array_raw.bin saved!\n");
|
||||
|
||||
sd_end();
|
||||
@@ -137,10 +137,7 @@ void print_mmc_info()
|
||||
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
@@ -151,35 +148,34 @@ void print_mmc_info()
|
||||
u32 speed = 0;
|
||||
|
||||
gfx_printf("%kCID:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
switch (storage.csd.mmca_vsn)
|
||||
switch (emmc_storage.csd.mmca_vsn)
|
||||
{
|
||||
case 2: /* MMC v2.0 - v2.2 */
|
||||
case 3: /* MMC v3.1 - v3.3 */
|
||||
case 4: /* MMC v4 */
|
||||
gfx_printf(
|
||||
" Vendor ID: %X\n"
|
||||
" Card/BGA: %X\n"
|
||||
" OEM ID: %02X\n"
|
||||
" Model: %c%c%c%c%c%c\n"
|
||||
" Prd Rev: %X\n"
|
||||
" S/N: %04X\n"
|
||||
" Month/Year: %02d/%04d\n\n",
|
||||
storage.cid.manfid, storage.cid.card_bga, storage.cid.oemid,
|
||||
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2],
|
||||
storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5],
|
||||
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year);
|
||||
emmc_storage.cid.manfid, emmc_storage.cid.oemid,
|
||||
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
|
||||
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
|
||||
emmc_storage.cid.prv, emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (storage.csd.structure == 0)
|
||||
if (emmc_storage.csd.structure == 0)
|
||||
EPRINTF("Unknown CSD structure.");
|
||||
else
|
||||
{
|
||||
gfx_printf("%kExtended CSD V1.%d:%k\n",
|
||||
0xFF00DDFF, storage.ext_csd.ext_struct, 0xFFCCCCCC);
|
||||
card_type = storage.ext_csd.card_type;
|
||||
0xFF00DDFF, emmc_storage.ext_csd.ext_struct, 0xFFCCCCCC);
|
||||
card_type = emmc_storage.ext_csd.card_type;
|
||||
char card_type_support[96];
|
||||
card_type_support[0] = 0;
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
|
||||
@@ -217,16 +213,16 @@ void print_mmc_info()
|
||||
" Max Rate: %d MB/s (%d MHz)\n"
|
||||
" Current Rate: %d MB/s\n"
|
||||
" Type Support: ",
|
||||
storage.csd.mmca_vsn, storage.ext_csd.rev, storage.ext_csd.dev_version, storage.csd.cmdclass,
|
||||
storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
storage.csd.busspeed);
|
||||
emmc_storage.csd.mmca_vsn, emmc_storage.ext_csd.rev, emmc_storage.ext_csd.dev_version, emmc_storage.csd.cmdclass,
|
||||
emmc_storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
emmc_storage.csd.busspeed);
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_printf("%s", card_type_support);
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_printf("\n\n", card_type_support);
|
||||
|
||||
u32 boot_size = storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
|
||||
u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
|
||||
gfx_printf("%keMMC Partitions:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_printf(" 1: %kBOOT0 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF96FF00, 0xFFCCCCCC,
|
||||
boot_size / 1024, boot_size / 512);
|
||||
@@ -238,13 +234,13 @@ void print_mmc_info()
|
||||
rpmb_size / 1024, rpmb_size / 512);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf(" 0: %kGPP (USER) %k\n Size: %5d MiB (LBA Sectors: 0x%07X)\n\n", 0xFF96FF00, 0xFFCCCCCC,
|
||||
storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt);
|
||||
emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf("%kGPP (eMMC USER) partition table:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
int gpp_idx = 0;
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
@@ -258,7 +254,7 @@ void print_mmc_info()
|
||||
}
|
||||
|
||||
out:
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
@@ -270,7 +266,7 @@ void print_sdcard_info()
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (sd_initialize(true))
|
||||
if (sd_initialize(false))
|
||||
{
|
||||
gfx_printf("%kCard IDentification:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_printf(
|
||||
@@ -336,115 +332,6 @@ void print_sdcard_info()
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void print_tsec_key()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 retries = 0;
|
||||
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
// Read package1.
|
||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTF("Unknown pkg1 version.");
|
||||
goto out_wait;
|
||||
}
|
||||
|
||||
u8 keys[0x10 * 2];
|
||||
memset(keys, 0x00, 0x20);
|
||||
|
||||
tsec_ctxt.fw = (u8 *)pkg1 + pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = pkg1;
|
||||
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = pkg1_id->secmon_base;
|
||||
|
||||
if (pkg1_id->kb <= KB_FIRMWARE_VERSION_600)
|
||||
tsec_ctxt.size = 0xF00;
|
||||
else if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
tsec_ctxt.size = 0x2900;
|
||||
else if (pkg1_id->kb == KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
tsec_ctxt.size = 0x3000;
|
||||
// Exit after TSEC key generation.
|
||||
*((vu16 *)((u32)tsec_ctxt.fw + 0x2DB5)) = 0x02F8;
|
||||
}
|
||||
else
|
||||
tsec_ctxt.size = 0x3300;
|
||||
|
||||
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
u8 *tsec_paged = (u8 *)page_alloc(3);
|
||||
memcpy(tsec_paged, (void *)tsec_ctxt.fw, tsec_ctxt.size);
|
||||
tsec_ctxt.fw = tsec_paged;
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
|
||||
while (tsec_query(keys, pkg1_id->kb, &tsec_ctxt) < 0)
|
||||
{
|
||||
memset(keys, 0x00, 0x20);
|
||||
|
||||
retries++;
|
||||
|
||||
if (retries > 3)
|
||||
{
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gfx_printf("%kTSEC key: %k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
if (res >= 0)
|
||||
{
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
gfx_printf("%02X", keys[j]);
|
||||
|
||||
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
gfx_printf("\n%kTSEC root: %k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
gfx_printf("%02X", keys[0x10 + j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
EPRINTFARGS("ERROR %X\n", res);
|
||||
|
||||
gfx_puts("\n\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (sd_mount())
|
||||
{
|
||||
char path[64];
|
||||
emmcsn_path_impl(path, "/dumps", "tsec_keys.bin", NULL);
|
||||
if (!sd_save_to_file(keys, 0x10 * 2, path))
|
||||
gfx_puts("\nDone!\n");
|
||||
sd_end();
|
||||
}
|
||||
}
|
||||
else
|
||||
goto out;
|
||||
|
||||
out_wait:
|
||||
btn_wait();
|
||||
|
||||
out:
|
||||
free(pkg1);
|
||||
}
|
||||
|
||||
void print_fuel_gauge_info()
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -23,7 +23,6 @@ void print_fuseinfo();
|
||||
void print_kfuseinfo();
|
||||
void print_mmc_info();
|
||||
void print_sdcard_info();
|
||||
void print_tsec_key();
|
||||
void print_fuel_gauge_info();
|
||||
void print_battery_charger_info();
|
||||
void print_battery_info();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 Reisyukaku
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -26,11 +26,11 @@
|
||||
#include "../hos/hos.h"
|
||||
#include "../hos/pkg1.h"
|
||||
#include "../hos/pkg2.h"
|
||||
#include "../hos/sept.h"
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
@@ -53,10 +53,10 @@ void dump_packages12()
|
||||
|
||||
char path[64];
|
||||
|
||||
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
|
||||
u8 *warmboot = (u8 *)calloc(1, 0x40000);
|
||||
u8 *secmon = (u8 *)calloc(1, 0x40000);
|
||||
u8 *loader = (u8 *)calloc(1, 0x40000);
|
||||
u8 *pkg1 = (u8 *)calloc(1, SZ_256K);
|
||||
u8 *warmboot = (u8 *)calloc(1, SZ_256K);
|
||||
u8 *secmon = (u8 *)calloc(1, SZ_256K);
|
||||
u8 *loader = (u8 *)calloc(1, SZ_256K);
|
||||
u8 *pkg2 = NULL;
|
||||
u8 kb = 0;
|
||||
|
||||
@@ -65,24 +65,22 @@ void dump_packages12()
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out_free;
|
||||
}
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, SZ_256K / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTF("Unknown pkg1 version for reading\nTSEC firmware.");
|
||||
// Dump package1.
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &storage);
|
||||
if (sd_save_to_file(pkg1, 0x40000, path))
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg1, SZ_256K, path))
|
||||
goto out_free;
|
||||
gfx_puts("\nEnc pkg1 dumped to pkg1_enc.bin\n");
|
||||
|
||||
@@ -91,38 +89,18 @@ void dump_packages12()
|
||||
|
||||
kb = pkg1_id->kb;
|
||||
|
||||
if (!h_cfg.se_keygen_done)
|
||||
{
|
||||
tsec_ctxt.fw = (void *)pkg1 + pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = (void *)pkg1;
|
||||
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = pkg1_id->secmon_base;
|
||||
tsec_ctxt.fw = (void *)pkg1 + pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = (void *)pkg1;
|
||||
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = pkg1_id->secmon_base;
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
|
||||
{
|
||||
b_cfg.autoboot = 0;
|
||||
b_cfg.autoboot_list = 0;
|
||||
// Read keyblob.
|
||||
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
sdmmc_storage_read(&emmc_storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
|
||||
gfx_printf("sept will run to get the keys.\nThen rerun this option.");
|
||||
btn_wait();
|
||||
|
||||
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, kb, NULL))
|
||||
{
|
||||
gfx_printf("Failed to run sept\n");
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
// Read keyblob.
|
||||
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
|
||||
// Decrypt.
|
||||
hos_keygen(keyblob, kb, &tsec_ctxt, NULL);
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
h_cfg.se_keygen_done = 1;
|
||||
free(keyblob);
|
||||
}
|
||||
// Decrypt.
|
||||
hos_keygen(keyblob, kb, &tsec_ctxt, false, false);
|
||||
free(keyblob);
|
||||
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
pkg1_decrypt(pkg1_id, pkg1);
|
||||
@@ -155,35 +133,35 @@ void dump_packages12()
|
||||
gfx_printf("%kWarmboot size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr_pk11->wb_size);
|
||||
|
||||
// Dump package1.1.
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &storage);
|
||||
if (sd_save_to_file(pkg1, 0x40000, path))
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg1, SZ_256K, path))
|
||||
goto out_free;
|
||||
gfx_puts("\npkg1 dumped to pkg1_decr.bin\n");
|
||||
|
||||
// Dump nxbootloader.
|
||||
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &emmc_storage);
|
||||
if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("NX Bootloader dumped to nxloader.bin\n");
|
||||
|
||||
// Dump secmon.
|
||||
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &emmc_storage);
|
||||
if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("Secure Monitor dumped to secmon.bin\n");
|
||||
|
||||
// Dump warmboot.
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &emmc_storage);
|
||||
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("Warmboot dumped to warmboot.bin\n\n\n");
|
||||
}
|
||||
|
||||
// Dump package2.1.
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
// Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
// Find package2 partition.
|
||||
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
|
||||
if (!pkg2_part)
|
||||
@@ -191,17 +169,25 @@ void dump_packages12()
|
||||
|
||||
// Read in package2 header and get package2 real size.
|
||||
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
||||
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
||||
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
|
||||
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
|
||||
free(tmp);
|
||||
// Read in package2.
|
||||
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
|
||||
pkg2 = malloc(pkg2_size_aligned);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
|
||||
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
|
||||
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
|
||||
|
||||
#if 0
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_encr.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg2, pkg2_size_aligned, path))
|
||||
goto out;
|
||||
gfx_puts("\npkg2 dumped to pkg2_encr.bin\n");
|
||||
#endif
|
||||
|
||||
// Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb);
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb, false);
|
||||
if (!pkg2_hdr)
|
||||
{
|
||||
gfx_printf("Pkg2 decryption failed!\n");
|
||||
@@ -213,19 +199,19 @@ void dump_packages12()
|
||||
gfx_printf("%kINI1 size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, pkg2_hdr->sec_size[PKG2_SEC_INI1]);
|
||||
|
||||
// Dump pkg2.1.
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
|
||||
goto out;
|
||||
gfx_puts("\npkg2 dumped to pkg2_decr.bin\n");
|
||||
|
||||
// Dump kernel.
|
||||
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
|
||||
goto out;
|
||||
gfx_puts("Kernel dumped to kernel.bin\n");
|
||||
|
||||
// Dump INI1.
|
||||
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &emmc_storage);
|
||||
u32 ini1_off = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||
u32 ini1_size = pkg2_hdr->sec_size[PKG2_SEC_INI1];
|
||||
if (!ini1_size)
|
||||
@@ -256,7 +242,7 @@ out_free:
|
||||
free(warmboot);
|
||||
free(loader);
|
||||
free(pkg2);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
sd_end();
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
@@ -267,51 +253,43 @@ out_free:
|
||||
|
||||
void _toggle_autorcm(bool enable)
|
||||
{
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
u8 randomXor = 0;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
|
||||
int i, sect = 0;
|
||||
u8 corr_mod_byte0;
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
corr_mod_byte0 = 0xF7;
|
||||
else
|
||||
corr_mod_byte0 = 0x37;
|
||||
u8 corr_mod0, mod1;
|
||||
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&corr_mod0, &mod1);
|
||||
|
||||
// Iterate BCTs.
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
||||
sdmmc_storage_read(&storage, sect, 1, tempbuf);
|
||||
sdmmc_storage_read(&emmc_storage, sect, 1, tempbuf);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (tempbuf[0x11] != mod1)
|
||||
continue;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
do
|
||||
{
|
||||
randomXor = get_tmr_us() & 0xFF; // Bricmii style of bricking.
|
||||
} while (!randomXor); // Avoid the lottery.
|
||||
|
||||
tempbuf[0x10] ^= randomXor;
|
||||
}
|
||||
tempbuf[0x10] = 0;
|
||||
else
|
||||
tempbuf[0x10] = corr_mod_byte0;
|
||||
sdmmc_storage_write(&storage, sect, 1, tempbuf);
|
||||
tempbuf[0x10] = corr_mod0;
|
||||
sdmmc_storage_write(&emmc_storage, sect, 1, tempbuf);
|
||||
}
|
||||
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
if (enable)
|
||||
gfx_printf("%kAutoRCM mode enabled!%k", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
@@ -333,20 +311,16 @@ void menu_autorcm()
|
||||
|
||||
if (h_cfg.rcm_patched)
|
||||
{
|
||||
gfx_printf("%kThis device is RCM patched and\nAutoRCM function is disabled.\n\n"
|
||||
"In case %kAutoRCM%k is enabled\nthis will %kBRICK%k your device PERMANENTLY!!%k",
|
||||
0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFCCCCCC);
|
||||
WPRINTF("This device is RCM patched and the\nfunction is disabled to avoid BRICKS!\n");
|
||||
btn_wait();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Do a simple check on the main BCT.
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
bool disabled = true;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
btn_wait();
|
||||
@@ -354,23 +328,21 @@ void menu_autorcm()
|
||||
return;
|
||||
}
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
u8 mod0, mod1;
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&mod0, &mod1);
|
||||
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
{
|
||||
if (tempbuf[0x10] != 0xF7)
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&emmc_storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (tempbuf[0x11] == mod1)
|
||||
if (tempbuf[0x10] != mod0)
|
||||
disabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tempbuf[0x10] != 0x37)
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
// Create AutoRCM menu.
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6);
|
||||
@@ -400,223 +372,9 @@ void menu_autorcm()
|
||||
ments[4].data = NULL;
|
||||
|
||||
memset(&ments[5], 0, sizeof(ment_t));
|
||||
menu_t menu = {ments, "This corrupts your BOOT0!", 0, 0};
|
||||
menu_t menu = {ments, "This corrupts BOOT0!", 0, 0};
|
||||
|
||||
tui_do_menu(&menu);
|
||||
}
|
||||
|
||||
int _fix_attributes(char *path, u32 *total, u32 hos_folder, u32 check_first_run)
|
||||
{
|
||||
FRESULT res;
|
||||
DIR dir;
|
||||
u32 dirLength = 0;
|
||||
static FILINFO fno;
|
||||
|
||||
if (check_first_run)
|
||||
{
|
||||
// Read file attributes.
|
||||
res = f_stat(path, &fno);
|
||||
if (res != FR_OK)
|
||||
return res;
|
||||
|
||||
// Check if archive bit is set.
|
||||
if (fno.fattrib & AM_ARC)
|
||||
{
|
||||
*(u32 *)total = *(u32 *)total + 1;
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
}
|
||||
}
|
||||
|
||||
// Open directory.
|
||||
res = f_opendir(&dir, path);
|
||||
if (res != FR_OK)
|
||||
return res;
|
||||
|
||||
dirLength = strlen(path);
|
||||
for (;;)
|
||||
{
|
||||
// Clear file or folder path.
|
||||
path[dirLength] = 0;
|
||||
|
||||
// Read a directory item.
|
||||
res = f_readdir(&dir, &fno);
|
||||
|
||||
// Break on error or end of dir.
|
||||
if (res != FR_OK || fno.fname[0] == 0)
|
||||
break;
|
||||
|
||||
// Skip official Nintendo dir if started from root.
|
||||
if (!hos_folder && !strcmp(fno.fname, "Nintendo"))
|
||||
continue;
|
||||
|
||||
// Set new directory or file.
|
||||
memcpy(&path[dirLength], "/", 1);
|
||||
memcpy(&path[dirLength + 1], fno.fname, strlen(fno.fname) + 1);
|
||||
|
||||
// Check if archive bit is set.
|
||||
if (fno.fattrib & AM_ARC)
|
||||
{
|
||||
*total = *total + 1;
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
}
|
||||
|
||||
// Is it a directory?
|
||||
if (fno.fattrib & AM_DIR)
|
||||
{
|
||||
// Set archive bit to NCA folders.
|
||||
if (hos_folder && !strcmp(fno.fname + strlen(fno.fname) - 4, ".nca"))
|
||||
{
|
||||
*total = *total + 1;
|
||||
f_chmod(path, AM_ARC, AM_ARC);
|
||||
}
|
||||
|
||||
// Update status bar.
|
||||
tui_sbar(false);
|
||||
|
||||
// Enter the directory.
|
||||
res = _fix_attributes(path, total, hos_folder, 0);
|
||||
if (res != FR_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f_closedir(&dir);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void _fix_sd_attr(u32 type)
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
char path[256];
|
||||
char label[16];
|
||||
|
||||
u32 total = 0;
|
||||
if (sd_mount())
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
strcpy(path, "/");
|
||||
strcpy(label, "SD Card");
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
strcpy(path, "/Nintendo");
|
||||
strcpy(label, "Nintendo folder");
|
||||
break;
|
||||
}
|
||||
|
||||
gfx_printf("Traversing all %s files!\nThis may take some time...\n\n", label);
|
||||
_fix_attributes(path, &total, type, type);
|
||||
gfx_printf("%kTotal archive bits cleared: %d!%k\n\nDone! Press any key...", 0xFF96FF00, total, 0xFFCCCCCC);
|
||||
sd_end();
|
||||
}
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void fix_sd_all_attr() { _fix_sd_attr(0); }
|
||||
void fix_sd_nin_attr() { _fix_sd_attr(1); }
|
||||
|
||||
/* void fix_fuel_gauge_configuration()
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
int battVoltage, avgCurrent;
|
||||
|
||||
max17050_get_property(MAX17050_VCELL, &battVoltage);
|
||||
max17050_get_property(MAX17050_AvgCurrent, &avgCurrent);
|
||||
|
||||
// Check if still charging. If not, check if battery is >= 95% (4.1V).
|
||||
if (avgCurrent < 0 && battVoltage > 4100)
|
||||
{
|
||||
if ((avgCurrent / 1000) < -10)
|
||||
EPRINTF("You need to be connected to a wall adapter,\nto apply this fix!");
|
||||
else
|
||||
{
|
||||
gfx_printf("%kAre you really sure?\nThis will reset your fuel gauge completely!\n", 0xFFFFDD00);
|
||||
gfx_printf("Additionally this will power off your console.\n%k", 0xFFCCCCCC);
|
||||
|
||||
gfx_puts("\nPress POWER to Continue.\nPress VOL to go to the menu.\n\n\n");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
max17050_fix_configuration();
|
||||
msleep(1000);
|
||||
gfx_con_getpos(&gfx_con.savedx, &gfx_con.savedy);
|
||||
u16 value = 0;
|
||||
gfx_printf("%kThe console will power off in 45 seconds.\n%k", 0xFFFFDD00, 0xFFCCCCCC);
|
||||
while (value < 46)
|
||||
{
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("%2ds elapsed", value);
|
||||
msleep(1000);
|
||||
value++;
|
||||
}
|
||||
msleep(2000);
|
||||
|
||||
power_off();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
EPRINTF("You need a fully charged battery\nand connected to a wall adapter,\nto apply this fix!");
|
||||
|
||||
msleep(500);
|
||||
btn_wait();
|
||||
} */
|
||||
|
||||
/*void reset_pmic_fuel_gauge_charger_config()
|
||||
{
|
||||
int avgCurrent;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
gfx_printf("%k\nThis will wipe your battery stats completely!\n"
|
||||
"%kAnd it may not power on without physically\nremoving and re-inserting the battery.\n%k"
|
||||
"\nAre you really sure?%k\n", 0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFCCCCCC);
|
||||
|
||||
gfx_puts("\nPress POWER to Continue.\nPress VOL to go to the menu.\n\n\n");
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
gfx_printf("%kKeep the USB cable connected!%k\n\n", 0xFFFFDD00, 0xFFCCCCCC);
|
||||
gfx_con_getpos(&gfx_con.savedx, &gfx_con.savedy);
|
||||
|
||||
u8 value = 30;
|
||||
while (value > 0)
|
||||
{
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
gfx_printf("%kWait... (%ds) %k", 0xFF888888, value, 0xFFCCCCCC);
|
||||
msleep(1000);
|
||||
value--;
|
||||
}
|
||||
gfx_con_setpos(gfx_con.savedx, gfx_con.savedy);
|
||||
|
||||
//Check if still connected.
|
||||
max17050_get_property(MAX17050_AvgCurrent, &avgCurrent);
|
||||
if ((avgCurrent / 1000) < -10)
|
||||
EPRINTF("You need to be connected to a wall adapter\nor PC to apply this fix!");
|
||||
else
|
||||
{
|
||||
// Apply fix.
|
||||
bq24193_fake_battery_removal();
|
||||
gfx_printf("Done! \n"
|
||||
"%k1. Remove the USB cable\n"
|
||||
"2. Press POWER for 15s.\n"
|
||||
"3. Reconnect the USB to power-on!%k\n", 0xFFFFDD00, 0xFFCCCCCC);
|
||||
}
|
||||
msleep(500);
|
||||
btn_wait();
|
||||
}
|
||||
}*/
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -19,9 +19,6 @@
|
||||
#define _FE_TOOLS_H_
|
||||
|
||||
void dump_packages12();
|
||||
void fix_sd_all_attr();
|
||||
void fix_sd_nin_attr();
|
||||
void fix_battery_desync();
|
||||
void menu_autorcm();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -23,6 +23,8 @@
|
||||
gfx_ctxt_t gfx_ctxt;
|
||||
gfx_con_t gfx_con;
|
||||
|
||||
static bool gfx_con_init_done = false;
|
||||
|
||||
static const u8 _gfx_font[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( )
|
||||
0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, // Char 033 (!)
|
||||
@@ -157,6 +159,8 @@ void gfx_con_init()
|
||||
gfx_con.fillbg = 1;
|
||||
gfx_con.bgcol = 0xFF1B1B1B;
|
||||
gfx_con.mute = 0;
|
||||
|
||||
gfx_con_init_done = true;
|
||||
}
|
||||
|
||||
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol)
|
||||
@@ -263,7 +267,7 @@ void gfx_putc(char c)
|
||||
|
||||
void gfx_puts(char *s)
|
||||
{
|
||||
if (!s || gfx_con.mute)
|
||||
if (!s || !gfx_con_init_done || gfx_con.mute)
|
||||
return;
|
||||
|
||||
for (; *s; s++)
|
||||
@@ -319,7 +323,7 @@ void gfx_put_big_sep()
|
||||
|
||||
void gfx_printf(const char *fmt, ...)
|
||||
{
|
||||
if (gfx_con.mute)
|
||||
if (!gfx_con_init_done || gfx_con.mute)
|
||||
return;
|
||||
|
||||
va_list ap;
|
||||
@@ -393,11 +397,13 @@ void gfx_printf(const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
void gfx_hexdump(u32 base, const void *buf, u32 len)
|
||||
{
|
||||
if (gfx_con.mute)
|
||||
if (!gfx_con_init_done || gfx_con.mute)
|
||||
return;
|
||||
|
||||
u8 *buff = (u8 *)buf;
|
||||
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 8;
|
||||
for(u32 i = 0; i < len; i++)
|
||||
@@ -409,7 +415,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
gfx_puts("| ");
|
||||
for(u32 j = 0; j < 0x10; j++)
|
||||
{
|
||||
u8 c = buf[i - 0x10 + j];
|
||||
u8 c = buff[i - 0x10 + j];
|
||||
if(c >= 32 && c <= 126)
|
||||
gfx_putc(c);
|
||||
else
|
||||
@@ -419,7 +425,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
}
|
||||
gfx_printf("%08x: ", base + i);
|
||||
}
|
||||
gfx_printf("%02x ", buf[i]);
|
||||
gfx_printf("%02x ", buff[i]);
|
||||
if (i == len - 1)
|
||||
{
|
||||
int ln = len % 0x10 != 0;
|
||||
@@ -433,7 +439,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
gfx_puts("| ");
|
||||
for(u32 j = 0; j < (ln ? k : k + 1); j++)
|
||||
{
|
||||
u8 c = buf[i - k + j];
|
||||
u8 c = buff[i - k + j];
|
||||
if(c >= 32 && c <= 126)
|
||||
gfx_putc(c);
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 M4xw
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -63,7 +63,7 @@ void gfx_con_setpos(u32 x, u32 y);
|
||||
void gfx_putc(char c);
|
||||
void gfx_puts(char *s);
|
||||
void gfx_printf(const char *fmt, ...);
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
|
||||
void gfx_hexdump(u32 base, const void *buf, u32 len);
|
||||
|
||||
void gfx_set_pixel(u32 x, u32 y, u32 color);
|
||||
void gfx_line(int x0, int y0, int x1, int y1, u32 color);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include "tui.h"
|
||||
#include "../config.h"
|
||||
#include <power/max17050.h>
|
||||
@@ -77,7 +77,7 @@ void tui_pbar(int x, int y, u32 val, u32 fgcol, u32 bgcol)
|
||||
|
||||
x += 7 * gfx_con.fntsz;
|
||||
|
||||
for (int i = 0; i < (gfx_con.fntsz >> 3) * 6; i++)
|
||||
for (u32 i = 0; i < (gfx_con.fntsz >> 3) * 6; i++)
|
||||
{
|
||||
gfx_line(x, y + i + 1, x + 3 * val, y + i + 1, fgcol);
|
||||
gfx_line(x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, bgcol);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Atmosphère Fusée Secondary Storage parser.
|
||||
* Atmosphère Fusée Secondary Storage (Package3) parser.
|
||||
*
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* 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,
|
||||
@@ -51,6 +51,7 @@ extern bool is_ipl_updated(void *buf, char *path, bool force);
|
||||
#define CNT_TYPE_KLD 9 // Kernel Loader.
|
||||
#define CNT_TYPE_KRN 10 // Kernel.
|
||||
#define CNT_TYPE_EXF 11 // Exosphere Mariko fatal payload.
|
||||
#define CNT_TYPE_TKG 12 // Tsec Keygen.
|
||||
|
||||
// FSS0 Content Flags.
|
||||
#define CNT_FLAG0_EXPERIMENTAL BIT(0)
|
||||
@@ -81,15 +82,16 @@ typedef struct _fss_content_t
|
||||
char name[0x10];
|
||||
} fss_content_t;
|
||||
|
||||
static void _update_r2p(const char *path)
|
||||
static void _set_fss_path_and_update_r2p(launch_ctxt_t *ctxt, const char *path)
|
||||
{
|
||||
char *r2p_path = malloc(256);
|
||||
u32 path_len = strlen(path);
|
||||
|
||||
strcpy(r2p_path, path);
|
||||
|
||||
while(path_len)
|
||||
{
|
||||
if ((r2p_path[path_len - 1] == '/') || (r2p_path[path_len - 1] == 0x5C))
|
||||
if ((r2p_path[path_len - 1] == '/') || (r2p_path[path_len - 1] == '\\'))
|
||||
{
|
||||
r2p_path[path_len] = 0;
|
||||
strcat(r2p_path, "reboot_payload.bin");
|
||||
@@ -98,7 +100,11 @@ static void _update_r2p(const char *path)
|
||||
is_ipl_updated(r2p_payload, r2p_path, h_cfg.updater2p ? true : false);
|
||||
|
||||
free(r2p_payload);
|
||||
break;
|
||||
|
||||
// Save FSS0 parent path.
|
||||
r2p_path[path_len] = 0;
|
||||
ctxt->fss0_main_path = r2p_path;
|
||||
return;
|
||||
}
|
||||
path_len--;
|
||||
}
|
||||
@@ -106,40 +112,43 @@ static void _update_r2p(const char *path)
|
||||
free(r2p_path);
|
||||
}
|
||||
|
||||
int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
int parse_fss(launch_ctxt_t *ctxt, const char *path)
|
||||
{
|
||||
FIL fp;
|
||||
|
||||
bool stock = false;
|
||||
int sept_used = 0;
|
||||
bool experimental = false;
|
||||
|
||||
// Skip if stock and Exosphere and warmboot are not needed.
|
||||
if (!sept_ctxt)
|
||||
bool pkg1_old = ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620; // Should check if t210b01?
|
||||
bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable;
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||
{
|
||||
bool pkg1_old = ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620;
|
||||
bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable;
|
||||
if (!strcmp("stock", kv->key))
|
||||
if (kv->val[0] == '1')
|
||||
stock = true;
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||
{
|
||||
if (!strcmp("stock", kv->key))
|
||||
if (kv->val[0] == '1')
|
||||
stock = true;
|
||||
}
|
||||
|
||||
#ifdef HOS_MARIKO_STOCK_SECMON
|
||||
if (stock && emummc_disabled && (pkg1_old || h_cfg.t210b01))
|
||||
#else
|
||||
if (stock && emummc_disabled && pkg1_old)
|
||||
#endif
|
||||
return 1;
|
||||
if (!strcmp("fss0experimental", kv->key))
|
||||
if (kv->val[0] == '1')
|
||||
experimental = true;
|
||||
}
|
||||
|
||||
#ifdef HOS_MARIKO_STOCK_SECMON
|
||||
if (stock && emummc_disabled && (pkg1_old || h_cfg.t210b01))
|
||||
return 1;
|
||||
#else
|
||||
if (stock && emummc_disabled && pkg1_old)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
// Try to open FSS0.
|
||||
if (f_open(&fp, path, FA_READ) != FR_OK)
|
||||
return 0;
|
||||
|
||||
void *fss = malloc(f_size(&fp));
|
||||
|
||||
// Read first 1024 bytes of the fss file.
|
||||
// Read first 1024 bytes of the FSS0 file.
|
||||
f_read(&fp, fss, 1024, NULL);
|
||||
|
||||
// Get FSS0 Meta header offset.
|
||||
@@ -149,30 +158,14 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
// Check if valid FSS0 and parse it.
|
||||
if (fss_meta->magic == FSS0_MAGIC)
|
||||
{
|
||||
bool mariko_not_supported = false;
|
||||
if (h_cfg.t210b01 && (fss_meta->version < FSS0_VERSION_0_17_0))
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
mariko_not_supported = true;
|
||||
}
|
||||
|
||||
gfx_printf("Found FSS0, Atmosphere %d.%d.%d-%08x\n"
|
||||
"Max HOS supported: %d.%d.%d\n"
|
||||
"Unpacking and loading components.. ",
|
||||
gfx_printf("Found FSS/PK3, Atmosphere %d.%d.%d-%08x\n"
|
||||
"Max HOS: %d.%d.%d\n"
|
||||
"Unpacking.. ",
|
||||
fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev,
|
||||
fss_meta->hos_ver >> 24, (fss_meta->hos_ver >> 16) & 0xFF, (fss_meta->hos_ver >> 8) & 0xFF);
|
||||
|
||||
if (mariko_not_supported)
|
||||
{
|
||||
EPRINTF("Mariko not supported on < 0.17.0!");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!sept_ctxt)
|
||||
{
|
||||
ctxt->atmosphere = true;
|
||||
ctxt->fss0_hosver = fss_meta->hos_ver;
|
||||
}
|
||||
ctxt->atmosphere = true;
|
||||
ctxt->fss0_hosver = fss_meta->hos_ver;
|
||||
|
||||
// Parse FSS0 contents.
|
||||
fss_content_t *curr_fss_cnt = (fss_content_t *)(fss + fss_meta->cnt_off);
|
||||
@@ -185,104 +178,66 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
if ((curr_fss_cnt[i].offset + curr_fss_cnt[i].size) > fss_meta->size)
|
||||
continue;
|
||||
|
||||
// If content is experimental and experimental flag is not enabled, skip it.
|
||||
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_experimental)
|
||||
// If content is experimental and experimental config is not enabled, skip it.
|
||||
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !experimental)
|
||||
continue;
|
||||
|
||||
// Parse content.
|
||||
if (!sept_ctxt)
|
||||
// Prepare content.
|
||||
switch (curr_fss_cnt[i].type)
|
||||
{
|
||||
// Prepare content context.
|
||||
switch (curr_fss_cnt[i].type)
|
||||
{
|
||||
case CNT_TYPE_KIP:
|
||||
if (stock)
|
||||
continue;
|
||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||
mkip1->kip1 = content;
|
||||
list_append(&ctxt->kip1_list, &mkip1->link);
|
||||
DPRINTF("Loaded %s.kip1 from FSS0 (size %08X)\n", curr_fss_cnt[i].name, curr_fss_cnt[i].size);
|
||||
break;
|
||||
|
||||
case CNT_TYPE_KRN:
|
||||
if (stock)
|
||||
continue;
|
||||
ctxt->kernel_size = curr_fss_cnt[i].size;
|
||||
ctxt->kernel = content;
|
||||
break;
|
||||
|
||||
case CNT_TYPE_EXO:
|
||||
ctxt->secmon_size = curr_fss_cnt[i].size;
|
||||
ctxt->secmon = content;
|
||||
break;
|
||||
|
||||
case CNT_TYPE_EXF:
|
||||
ctxt->exofatal_size = curr_fss_cnt[i].size;
|
||||
ctxt->exofatal = content;
|
||||
break;
|
||||
|
||||
case CNT_TYPE_WBT:
|
||||
if (h_cfg.t210b01)
|
||||
continue;
|
||||
ctxt->warmboot_size = curr_fss_cnt[i].size;
|
||||
ctxt->warmboot = content;
|
||||
break;
|
||||
|
||||
default:
|
||||
case CNT_TYPE_KIP:
|
||||
if (stock)
|
||||
continue;
|
||||
}
|
||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||
mkip1->kip1 = content;
|
||||
list_append(&ctxt->kip1_list, &mkip1->link);
|
||||
DPRINTF("Loaded %s.kip1 from FSS0 (size %08X)\n", curr_fss_cnt[i].name, curr_fss_cnt[i].size);
|
||||
break;
|
||||
|
||||
// Load content to launch context.
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, content, curr_fss_cnt[i].size, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load sept content directly to launch context.
|
||||
switch (curr_fss_cnt[i].type)
|
||||
{
|
||||
case CNT_TYPE_SP1:
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, sept_ctxt->sept_primary, curr_fss_cnt[i].size, NULL);
|
||||
break;
|
||||
case CNT_TYPE_SP2:
|
||||
if (!memcmp(curr_fss_cnt[i].name, (sept_ctxt->kb < KB_FIRMWARE_VERSION_810) ? "septsecondary00" : "septsecondary01", 15))
|
||||
{
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, sept_ctxt->sept_secondary, curr_fss_cnt[i].size, NULL);
|
||||
sept_used = 1;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case CNT_TYPE_KRN:
|
||||
if (stock)
|
||||
continue;
|
||||
ctxt->kernel_size = curr_fss_cnt[i].size;
|
||||
ctxt->kernel = content;
|
||||
break;
|
||||
|
||||
case CNT_TYPE_EXO:
|
||||
ctxt->secmon_size = curr_fss_cnt[i].size;
|
||||
ctxt->secmon = content;
|
||||
break;
|
||||
|
||||
case CNT_TYPE_EXF:
|
||||
ctxt->exofatal_size = curr_fss_cnt[i].size;
|
||||
ctxt->exofatal = content;
|
||||
break;
|
||||
|
||||
case CNT_TYPE_WBT:
|
||||
if (h_cfg.t210b01)
|
||||
continue;
|
||||
ctxt->warmboot_size = curr_fss_cnt[i].size;
|
||||
ctxt->warmboot = content;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load content to launch context.
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, content, curr_fss_cnt[i].size, NULL);
|
||||
}
|
||||
|
||||
out:
|
||||
gfx_printf("Done!\n");
|
||||
f_close(&fp);
|
||||
|
||||
_update_r2p(path);
|
||||
// Set FSS0 path and update r2p if needed.
|
||||
_set_fss_path_and_update_r2p(ctxt, path);
|
||||
|
||||
return (!sept_ctxt ? 1 : sept_used);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fail:
|
||||
f_close(&fp);
|
||||
free(fss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_sept_from_ffs0(fss0_sept_t *sept_ctxt)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &sept_ctxt->cfg_sec->kvs, link)
|
||||
{
|
||||
if (!strcmp("fss0", kv->key))
|
||||
return parse_fss(NULL, kv->val, sept_ctxt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* 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,
|
||||
@@ -19,16 +19,6 @@
|
||||
|
||||
#include "hos.h"
|
||||
|
||||
typedef struct _fss0_sept_t
|
||||
{
|
||||
u32 kb;
|
||||
ini_sec_t *cfg_sec;
|
||||
void *sept_primary;
|
||||
void *sept_secondary;
|
||||
|
||||
} fss0_sept_t;
|
||||
|
||||
int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt);
|
||||
int load_sept_from_ffs0(fss0_sept_t *sept_ctxt);
|
||||
int parse_fss(launch_ctxt_t *ctxt, const char *path);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -20,66 +20,59 @@
|
||||
|
||||
#include "pkg1.h"
|
||||
#include "pkg2.h"
|
||||
#include <sec/se_t210.h>
|
||||
#include <utils/types.h>
|
||||
#include <utils/ini.h>
|
||||
#include <sec/tsec.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define KB_FIRMWARE_VERSION_100_200 0
|
||||
#define KB_FIRMWARE_VERSION_300 1
|
||||
#define KB_FIRMWARE_VERSION_301 2
|
||||
#define KB_FIRMWARE_VERSION_400 3
|
||||
#define KB_FIRMWARE_VERSION_500 4
|
||||
#define KB_FIRMWARE_VERSION_600 5
|
||||
#define KB_FIRMWARE_VERSION_620 6
|
||||
#define KB_FIRMWARE_VERSION_700 7
|
||||
#define KB_FIRMWARE_VERSION_810 8
|
||||
#define KB_FIRMWARE_VERSION_900 9
|
||||
#define KB_FIRMWARE_VERSION_910 10
|
||||
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_910
|
||||
#define KB_FIRMWARE_VERSION_100 0
|
||||
#define KB_FIRMWARE_VERSION_300 1
|
||||
#define KB_FIRMWARE_VERSION_301 2
|
||||
#define KB_FIRMWARE_VERSION_400 3
|
||||
#define KB_FIRMWARE_VERSION_500 4
|
||||
#define KB_FIRMWARE_VERSION_600 5
|
||||
#define KB_FIRMWARE_VERSION_620 6
|
||||
#define KB_FIRMWARE_VERSION_700 7
|
||||
#define KB_FIRMWARE_VERSION_810 8
|
||||
#define KB_FIRMWARE_VERSION_900 9
|
||||
#define KB_FIRMWARE_VERSION_910 10
|
||||
#define KB_FIRMWARE_VERSION_1210 11
|
||||
#define KB_FIRMWARE_VERSION_1300 12
|
||||
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_1300 //!TODO: Update on mkey changes.
|
||||
|
||||
#define HOS_PKG11_MAGIC 0x31314B50
|
||||
#define HOS_EKS_MAGIC 0x30534B45
|
||||
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
|
||||
|
||||
// Use official Mariko secmon when in stock.
|
||||
#define HOS_PKG11_MAGIC 0x31314B50
|
||||
#define HOS_EKS_MAGIC 0x31534B45 // EKS1.
|
||||
#define HOS_EKS_TSEC_VER (KB_FIRMWARE_VERSION_700 + HOS_TSEC_VERSION)
|
||||
|
||||
// Use official Mariko secmon when in stock. Needs access to TZRAM.
|
||||
//#define HOS_MARIKO_STOCK_SECMON
|
||||
|
||||
typedef struct _exo_ctxt_t
|
||||
{
|
||||
bool fs_is_510;
|
||||
u32 hos_revision;
|
||||
bool no_user_exceptions;
|
||||
bool user_pmu;
|
||||
bool *usb3_force;
|
||||
bool *cal0_blank;
|
||||
bool *cal0_allow_writes_sys;
|
||||
} exo_ctxt_t;
|
||||
|
||||
typedef struct _hos_eks_keys_t
|
||||
{
|
||||
u8 mkk[0x10];
|
||||
u8 fdk[0x10];
|
||||
} hos_eks_keys_t;
|
||||
|
||||
typedef struct _hos_eks_bis_keys_t
|
||||
{
|
||||
u8 crypt[0x10];
|
||||
u8 tweak[0x10];
|
||||
} hos_eks_bis_keys_t;
|
||||
|
||||
typedef struct _hos_eks_mbr_t
|
||||
{
|
||||
u32 magic;
|
||||
u8 enabled[5];
|
||||
u8 enabled_bis;
|
||||
u8 rsvd[2];
|
||||
u32 enabled;
|
||||
u32 lot0;
|
||||
u8 dkg[0x10];
|
||||
u8 dkk[0x10];
|
||||
hos_eks_keys_t keys[5];
|
||||
hos_eks_bis_keys_t bis_keys[3];
|
||||
u32 rsvd;
|
||||
u8 tsec[SE_KEY_128_SIZE];
|
||||
u8 troot[SE_KEY_128_SIZE];
|
||||
u8 troot_dev[SE_KEY_128_SIZE];
|
||||
} hos_eks_mbr_t;
|
||||
|
||||
static_assert(sizeof(hos_eks_mbr_t) == 304, "HOS EKS size is wrong!");
|
||||
static_assert(sizeof(hos_eks_mbr_t) == 64, "HOS EKS size is wrong!");
|
||||
|
||||
typedef struct _launch_ctxt_t
|
||||
{
|
||||
@@ -106,14 +99,15 @@ typedef struct _launch_ctxt_t
|
||||
link_t kip1_list;
|
||||
char* kip1_patches;
|
||||
|
||||
u32 fss0_hosver;
|
||||
bool svcperm;
|
||||
bool debugmode;
|
||||
bool stock;
|
||||
bool atmosphere;
|
||||
bool fss0_experimental;
|
||||
bool emummc_forced;
|
||||
|
||||
char *fss0_main_path;
|
||||
u32 fss0_hosver;
|
||||
bool atmosphere;
|
||||
|
||||
exo_ctxt_t exo_ctx;
|
||||
|
||||
ini_sec_t *cfg;
|
||||
@@ -125,10 +119,8 @@ typedef struct _merge_kip_t
|
||||
link_t link;
|
||||
} merge_kip_t;
|
||||
|
||||
void hos_eks_get();
|
||||
void hos_eks_save(u32 kb);
|
||||
void hos_eks_clear(u32 kb);
|
||||
int hos_launch(ini_sec_t *cfg);
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
|
||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -220,6 +220,19 @@ static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_usb3_force(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_ctx.usb3_force = calloc(sizeof(bool), 1);
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled USB 3.0\n");
|
||||
*ctxt->exo_ctx.usb3_force = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
@@ -249,16 +262,7 @@ static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value
|
||||
|
||||
static int _config_fss(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||
{
|
||||
if (!strcmp("fss0experimental", kv->key))
|
||||
{
|
||||
ctxt->fss0_experimental = *kv->val == '1';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return parse_fss(ctxt, value, NULL);
|
||||
return parse_fss(ctxt, value);
|
||||
}
|
||||
|
||||
static int _config_exo_fatal_payload(launch_ctxt_t *ctxt, const char *value)
|
||||
@@ -291,6 +295,7 @@ static const cfg_handler_t _config_handlers[] = {
|
||||
{ "emummcforce", _config_emummc_forced },
|
||||
{ "nouserexceptions", _config_dis_exo_user_exceptions },
|
||||
{ "userpmu", _config_exo_user_pmu_access },
|
||||
{ "usb3force", _config_exo_usb3_force },
|
||||
{ "cal0blank", _config_exo_cal0_blanking },
|
||||
{ "cal0writesys", _config_exo_cal0_writes_enable },
|
||||
{ NULL, NULL },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <soc/t210.h>
|
||||
#include <storage/nx_sd.h>
|
||||
#include <utils/aarch64_util.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
@@ -77,7 +78,7 @@ PATCHSET_DEF(_secmon_6_patchset,
|
||||
// { 0x1A68 + 0x3A6C, _NOP() } // warmboot UARTA cfg.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_620_patchset,
|
||||
PATCHSET_DEF(_secmon_62_patchset,
|
||||
// Patch package2 signature/hash checks.
|
||||
{ 0xDC8 + 0xC74, _NOP() }
|
||||
// Fix sleep mode for debug.
|
||||
@@ -127,10 +128,6 @@ PATCHSET_DEF(_warmboot_1_patchset,
|
||||
{ 0x4DC, _NOPv7() } // Fuse check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_2_patchset,
|
||||
{ 0x4DC, _NOPv7() } // Fuse check.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_warmboot_3_patchset,
|
||||
{ 0x4DC, _NOPv7() }, // Fuse check.
|
||||
{ 0x4F0, _NOPv7() } // Segment id check.
|
||||
@@ -153,53 +150,60 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO
|
||||
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
|
||||
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
|
||||
|
||||
// ID (Timestamp), KB, Fuses, TSEC, PK11, SECMON, Warmboot.
|
||||
static const pkg1_id_t _pkg1_ids[] = {
|
||||
{ "20161121183008", 0, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset, _warmboot_1_patchset }, // 1.0.0 (Patched relocator).
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset, _warmboot_2_patchset }, // 2.0.0 - 2.3.0.
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.0.
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.1 - 3.0.2.
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_4_patchset, _warmboot_4_patchset }, // 4.0.0 - 4.1.0.
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_5_patchset, _warmboot_4_patchset }, // 5.0.0 - 5.1.0.
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800, _secmon_6_patchset, _warmboot_4_patchset }, // 6.0.0 - 6.1.0.
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800, _secmon_620_patchset, _warmboot_4_patchset }, // 6.2.0.
|
||||
{ "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.0.
|
||||
{ "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.1.
|
||||
{ "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.0.0 - 8.0.1.
|
||||
{ "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.1.0.
|
||||
{ "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.0.0 - 9.0.1.
|
||||
{ "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.1.0.
|
||||
{ "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 10.0.0.
|
||||
{ "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 11.0.0.
|
||||
{ NULL } // End.
|
||||
{ "20161121183008", 0, 1, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset }, // 1.0.0 (Patched relocator).
|
||||
{ "20170210155124", 0, 2, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset }, // 2.0.0 - 2.3.0.
|
||||
{ "20170519101410", 1, 3, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset }, // 3.0.0.
|
||||
{ "20170710161758", 2, 4, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset }, // 3.0.1 - 3.0.2.
|
||||
{ "20170921172629", 3, 5, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_4_patchset }, // 4.0.0 - 4.1.0.
|
||||
{ "20180220163747", 4, 6, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_5_patchset }, // 5.0.0 - 5.1.0.
|
||||
{ "20180802162753", 5, 7, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800, _secmon_6_patchset }, // 6.0.0 - 6.1.0.
|
||||
{ "20181107105733", 6, 8, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800, _secmon_62_patchset}, // 6.2.0.
|
||||
{ "20181218175730", 7, 9, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 7.0.0.
|
||||
{ "20190208150037", 7, 9, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 7.0.1.
|
||||
{ "20190314172056", 7, 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 8.0.0 - 8.0.1.
|
||||
{ "20190531152432", 8, 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 8.1.0 - 8.1.1.
|
||||
{ "20190809135709", 9, 11, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 9.0.0 - 9.0.1.
|
||||
{ "20191021113848", 10, 12, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 9.1.0 - 9.2.0.
|
||||
{ "20200303104606", 10, 13, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 10.0.0 - 10.2.0.
|
||||
{ "20201030110855", 10, 14, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 11.0.0 - 11.0.1.
|
||||
{ "20210129111626", 10, 14, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 12.0.0 - 12.0.1.
|
||||
{ "20210422145837", 10, 15, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 12.0.2 - 12.0.3.
|
||||
{ "20210607122020", 11, 15, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 12.1.0.
|
||||
{ "20210805123738", 12, 15, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 13.0.0+
|
||||
};
|
||||
|
||||
const pkg1_id_t *pkg1_get_latest()
|
||||
{
|
||||
return &_pkg1_ids[ARRAY_SIZE(_pkg1_ids) - 2];
|
||||
return &_pkg1_ids[ARRAY_SIZE(_pkg1_ids) - 1];
|
||||
}
|
||||
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1)
|
||||
{
|
||||
char build_date[15];
|
||||
memcpy(build_date, (char *)(pkg1 + 0x10), 14);
|
||||
pk1_hdr_t *hdr = (pk1_hdr_t *)pkg1;
|
||||
|
||||
memcpy(build_date, hdr->timestamp, 14);
|
||||
build_date[14] = 0;
|
||||
gfx_printf("Found pkg1 ('%s').\n\n", build_date);
|
||||
|
||||
for (u32 i = 0; _pkg1_ids[i].id; i++)
|
||||
if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8))
|
||||
for (int i = ARRAY_SIZE(_pkg1_ids) - 1; i >= 0; i--)
|
||||
if (!memcmp(hdr->timestamp, _pkg1_ids[i].id, 8))
|
||||
return &_pkg1_ids[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
|
||||
{
|
||||
// Decrypt package1.
|
||||
pk11_hdr_t *hdr;
|
||||
u8 *pkg11 = pkg1 + id->pkg11_off;
|
||||
u32 pkg11_size = *(u32 *)pkg11;
|
||||
|
||||
// Decrypt package1.
|
||||
if (!h_cfg.t210b01)
|
||||
{
|
||||
u8 *pkg11 = pkg1 + id->pkg11_off;
|
||||
u32 pkg11_size = *(u32 *)pkg11;
|
||||
hdr = (pk11_hdr_t *)(pkg11 + 0x20);
|
||||
se_aes_crypt_ctr(11, hdr, pkg11_size, hdr, pkg11_size, pkg11 + 0x10);
|
||||
}
|
||||
@@ -210,8 +214,9 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
|
||||
hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
|
||||
|
||||
// Use BEK for T210B01.
|
||||
// Additionally, skip 0x20 bytes from decryption to maintain the header.
|
||||
se_aes_iv_clear(13);
|
||||
se_aes_crypt_cbc(13, 0, pkg1 + 0x20, oem_hdr->size - 0x20, pkg1 + 0x20, oem_hdr->size - 0x20);
|
||||
se_aes_crypt_cbc(13, DECRYPT, pkg1 + 0x20, oem_hdr->size - 0x20, pkg1 + 0x20, oem_hdr->size - 0x20);
|
||||
}
|
||||
|
||||
// Return if header is valid.
|
||||
@@ -227,11 +232,11 @@ const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, con
|
||||
//u32 sec_off[3] = { hdr->wb_off, hdr->ldr_off, hdr->sm_off };
|
||||
|
||||
// Get correct header mapping.
|
||||
if (id->kb == KB_FIRMWARE_VERSION_100_200 && !strcmp(id->id, "20161121183008"))
|
||||
if (id->fuses == 1) // 1.0.0.
|
||||
sec_map = sec_map_100;
|
||||
else if (id->kb >= KB_FIRMWARE_VERSION_100_200 && id->kb <= KB_FIRMWARE_VERSION_301)
|
||||
else if (id->fuses >= 2 && id->fuses <= 4) // 2.0.0 - 3.0.2.
|
||||
sec_map = sec_map_2xx;
|
||||
else
|
||||
else // 4.0.0+
|
||||
sec_map = sec_map_4xx;
|
||||
|
||||
// Copy secmon, warmboot and nx bootloader payloads.
|
||||
@@ -309,9 +314,21 @@ void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01)
|
||||
void pkg1_warmboot_patch(void *hos_ctxt)
|
||||
{
|
||||
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
patch_t *warmboot_patchset;
|
||||
|
||||
// Patch warmboot on T210 to allow downgrading.
|
||||
patch_t *warmboot_patchset = ctxt->pkg1_id->warmboot_patchset;
|
||||
switch (ctxt->pkg1_id->kb)
|
||||
{
|
||||
case 0:
|
||||
warmboot_patchset = _warmboot_1_patchset;
|
||||
break;
|
||||
case 1 ... 2:
|
||||
warmboot_patchset = _warmboot_3_patchset;
|
||||
break;
|
||||
default: // 4.0.0 - 6.2.0.
|
||||
warmboot_patchset = _warmboot_4_patchset;
|
||||
break;
|
||||
}
|
||||
gfx_printf("%kPatching Warmboot%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
for (u32 i = 0; warmboot_patchset[i].off != 0xFFFFFFFF; i++)
|
||||
*(vu32 *)(ctxt->pkg1_id->warmboot_base + warmboot_patchset[i].off) = warmboot_patchset[i].val;
|
||||
@@ -329,9 +346,11 @@ static void _warmboot_filename(char *out, u32 fuses)
|
||||
strcat(out, ".bin");
|
||||
}
|
||||
|
||||
void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base)
|
||||
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
|
||||
{
|
||||
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
u32 kb = ctxt->pkg1_id->kb;
|
||||
int res = 1;
|
||||
|
||||
// Set warmboot address in PMC if required.
|
||||
if (kb <= KB_FIRMWARE_VERSION_301)
|
||||
@@ -340,18 +359,11 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base)
|
||||
if (h_cfg.t210b01)
|
||||
{
|
||||
u32 pa_id;
|
||||
u32 fuses_fw = kb + 2;
|
||||
u32 fuses_max = 32; // Current ODM7 max.
|
||||
u8 burnt_fuses = fuse_count_burnt(fuse_read_odm(7));
|
||||
u32 fuses_fw = ctxt->pkg1_id->fuses;
|
||||
u8 burnt_fuses = bit_count(fuse_read_odm(7));
|
||||
|
||||
// Add one more fuse for high versions.
|
||||
//TODO: Add better checks for 10.0.0 and up in case mkey doesn't change.
|
||||
if (kb > KB_FIRMWARE_VERSION_910 || !memcmp(ctxt->pkg1_id->id, "20200303104606", 8)) // 10.0.0.
|
||||
fuses_fw++;
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20201030110855", 8)) // 11.0.0.
|
||||
fuses_fw += 2;
|
||||
|
||||
// Save current warmboot in storage cache and check if another one is needed.
|
||||
// Save current warmboot in storage cache (MWS) and check if another one is needed.
|
||||
if (!ctxt->warmboot)
|
||||
{
|
||||
char path[128];
|
||||
@@ -361,7 +373,7 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base)
|
||||
if (f_stat(path, NULL))
|
||||
sd_save_to_file((void *)warmboot_base, ctxt->warmboot_size, path);
|
||||
|
||||
// Load warmboot fw from storage if not matched.
|
||||
// Load warmboot fw from storage (MWS) if not matched.
|
||||
if (burnt_fuses > fuses_fw)
|
||||
{
|
||||
u32 tmp_fuses = burnt_fuses;
|
||||
@@ -378,7 +390,13 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base)
|
||||
break;
|
||||
tmp_fuses++;
|
||||
}
|
||||
|
||||
// Check if proper warmboot firmware was found.
|
||||
if (!ctxt->warmboot)
|
||||
res = 0;
|
||||
}
|
||||
else // Replace burnt fuses with higher count.
|
||||
burnt_fuses = fuses_fw;
|
||||
}
|
||||
|
||||
// Configure Warmboot parameters. Anything lower is not supported.
|
||||
@@ -408,4 +426,6 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base)
|
||||
else if (kb == KB_FIRMWARE_VERSION_301)
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id.
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,14 @@
|
||||
#define PK11_SECTION_LD 1
|
||||
#define PK11_SECTION_SM 2
|
||||
|
||||
#define PKG1_BOOTLOADER_SIZE SZ_256K
|
||||
#define PKG1_BOOTLOADER_MAIN_OFFSET 0x100000
|
||||
#define PKG1_BOOTLOADER_BACKUP_OFFSET 0x140000
|
||||
#define PKG1_HOS_KEYBLOBS_OFFSET 0x180000
|
||||
|
||||
#define PKG1_ERISTA_ON_MARIKO_MAGIC 0xE59FD00C // For 4.0.0 Erista and up.
|
||||
#define PKG1_MARIKO_ON_ERISTA_MAGIC 0x40010040 // Mariko pkg1 entrypoint.
|
||||
|
||||
typedef struct _patch_t
|
||||
{
|
||||
u32 off;
|
||||
@@ -39,27 +47,38 @@ typedef struct _patch_t
|
||||
|
||||
typedef struct _bl_hdr_t210b01_t
|
||||
{
|
||||
u8 aes_mac[0x10];
|
||||
u8 rsa_sig[0x100];
|
||||
u8 salt[0x20];
|
||||
u8 sha256[0x20];
|
||||
u32 version;
|
||||
u32 size;
|
||||
u32 load_addr;
|
||||
u32 entrypoint;
|
||||
u8 rsvd[0x10];
|
||||
/* 0x000 */ u8 aes_mac[0x10];
|
||||
/* 0x010 */ u8 rsa_sig[0x100];
|
||||
/* 0x110 */ u8 salt[0x20];
|
||||
/* 0x130 */ u8 sha256[0x20];
|
||||
/* 0x150 */ u32 version;
|
||||
/* 0x154 */ u32 size;
|
||||
/* 0x158 */ u32 load_addr;
|
||||
/* 0x15C */ u32 entrypoint;
|
||||
/* 0x160 */ u8 rsvd[0x10];
|
||||
} bl_hdr_t210b01_t;
|
||||
|
||||
typedef struct _pk1_hdr_t
|
||||
{
|
||||
/* 0x00 */ u32 si_sha256; // Secure Init.
|
||||
/* 0x04 */ u32 sm_sha256; // Secure Monitor.
|
||||
/* 0x08 */ u32 sl_sha256; // Secure Loader.
|
||||
/* 0x0C */ u32 unk; // what's this? It's not warmboot.
|
||||
/* 0x10 */ char timestamp[14];
|
||||
/* 0x1E */ u8 keygen;
|
||||
/* 0x1F */ u8 version;
|
||||
} pk1_hdr_t;
|
||||
|
||||
typedef struct _pkg1_id_t
|
||||
{
|
||||
const char *id;
|
||||
u32 kb;
|
||||
u32 tsec_off;
|
||||
u32 pkg11_off;
|
||||
u16 kb;
|
||||
u16 fuses;
|
||||
u16 tsec_off;
|
||||
u16 pkg11_off;
|
||||
u32 secmon_base;
|
||||
u32 warmboot_base;
|
||||
patch_t *secmon_patchset;
|
||||
patch_t *warmboot_patchset;
|
||||
} pkg1_id_t;
|
||||
|
||||
typedef struct _pk11_hdr_t
|
||||
@@ -80,6 +99,6 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
|
||||
const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
|
||||
void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01);
|
||||
void pkg1_warmboot_patch(void *hos_ctxt);
|
||||
void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base);
|
||||
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018 Atmosphère-NX
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -27,6 +26,7 @@
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include "../storage/emummc.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <utils/aarch64_util.h>
|
||||
@@ -48,403 +48,6 @@ u32 pkg2_newkern_ini1_end;
|
||||
#define DPRINTF(...)
|
||||
#endif
|
||||
|
||||
//TODO: Replace hardcoded AArch64 instructions with instruction macros.
|
||||
//TODO: Reduce hardcoded values without searching kernel for patterns?
|
||||
// The process ID send/receive kernel patches were taken from Atmosphère's kernel patches.
|
||||
// They should only be used when running Atmosphère.
|
||||
#define FREE_CODE_OFF_1ST_100 0x4797C
|
||||
#define FREE_CODE_OFF_1ST_200 0x6486C
|
||||
#define FREE_CODE_OFF_1ST_300 0x494A4
|
||||
#define FREE_CODE_OFF_1ST_302 0x494BC
|
||||
#define FREE_CODE_OFF_1ST_400 0x52890
|
||||
#define FREE_CODE_OFF_1ST_500 0x5C020
|
||||
#define FREE_CODE_OFF_1ST_600 0x5EE00
|
||||
#define FREE_CODE_OFF_1ST_700 0x5FEC0
|
||||
#define FREE_CODE_OFF_1ST_800 0x607F0
|
||||
#define FREE_CODE_OFF_1ST_900 0x65780
|
||||
#define FREE_CODE_OFF_1ST_1000 0x67790
|
||||
#define FREE_CODE_OFF_1ST_1100 0x49EE8
|
||||
|
||||
#define ID_SND_OFF_100 0x23CC0
|
||||
#define ID_SND_OFF_200 0x3F134
|
||||
#define ID_SND_OFF_300 0x26080
|
||||
#define ID_SND_OFF_302 0x26080
|
||||
#define ID_SND_OFF_400 0x2AF64
|
||||
#define ID_SND_OFF_500 0x2AD34
|
||||
#define ID_SND_OFF_600 0x2BB8C
|
||||
#define ID_SND_OFF_700 0x2D044
|
||||
#define ID_SND_OFF_800 0x2F1FC
|
||||
#define ID_SND_OFF_900 0x329A0
|
||||
#define ID_SND_OFF_1000 0x34404
|
||||
#define ID_SND_OFF_1100 0x245B4
|
||||
#define ID_SND_OFF_1101 0x245B8
|
||||
|
||||
#define ID_RCV_OFF_100 0x219F0
|
||||
#define ID_RCV_OFF_200 0x3D1A8
|
||||
#define ID_RCV_OFF_300 0x240F0
|
||||
#define ID_RCV_OFF_302 0x240F0
|
||||
#define ID_RCV_OFF_400 0x28F6C
|
||||
#define ID_RCV_OFF_500 0x28DAC
|
||||
#define ID_RCV_OFF_600 0x29B6C
|
||||
#define ID_RCV_OFF_700 0x2B23C
|
||||
#define ID_RCV_OFF_800 0x2D424
|
||||
#define ID_RCV_OFF_900 0x309B4
|
||||
#define ID_RCV_OFF_1000 0x322F8
|
||||
#define ID_RCV_OFF_1100 0x22B24
|
||||
#define ID_RCV_OFF_1101 0x22B28
|
||||
|
||||
static u32 PRC_ID_SND_100[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
|
||||
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_100 (FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_100[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
|
||||
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_200[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
|
||||
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_200 (FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_200[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148,
|
||||
0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_300[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
|
||||
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_300 (FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_300[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148,
|
||||
0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA
|
||||
};
|
||||
|
||||
#define FREE_CODE_OFF_2ND_302 (FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_300) + sizeof(u32))
|
||||
|
||||
static u32 PRC_ID_SND_400[] =
|
||||
{
|
||||
0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9,
|
||||
0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_400 (FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_400[] =
|
||||
{
|
||||
0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
|
||||
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_500[] =
|
||||
{
|
||||
0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9,
|
||||
0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_500 (FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_500[] =
|
||||
{
|
||||
0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
|
||||
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_600[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_600 (FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_600[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_700[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF9403BEB, 0x2A1903EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_700 (FREE_CODE_OFF_1ST_700 + sizeof(PRC_ID_SND_700) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_700[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
#define FREE_CODE_OFF_2ND_800 (FREE_CODE_OFF_1ST_800 + sizeof(PRC_ID_SND_700) + sizeof(u32))
|
||||
|
||||
static u32 PRC_ID_SND_900[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94037EB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002E8, 0xF9401D08, 0xAA1703E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_900 (FREE_CODE_OFF_1ST_900 + sizeof(PRC_ID_SND_900) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_900[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF9404BEB, 0x2A1703EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_1000[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94063EB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002E8, 0xF9401D08, 0xAA1703E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_1000 (FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_1000[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94067EB, 0x2A1A03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_1100[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94043EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define FREE_CODE_OFF_2ND_1100 (FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_1100[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94073EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
// Include kernel patches here, so we can utilize pkg1 id
|
||||
KERNEL_PATCHSET_DEF(_kernel_1_patchset,
|
||||
{ SVC_VERIFY_DS, 0x3764C, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x44074, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_100, _B(ID_SND_OFF_100, FREE_CODE_OFF_1ST_100), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_100, sizeof(PRC_ID_SND_100) >> 2, PRC_ID_SND_100}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), ID_SND_OFF_100 + sizeof(u32)), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_100, _B(ID_RCV_OFF_100, FREE_CODE_OFF_2ND_100), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_100, sizeof(PRC_ID_RCV_100) >> 2, PRC_ID_RCV_100}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), ID_RCV_OFF_100 + sizeof(u32)), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_2_patchset,
|
||||
{ SVC_VERIFY_DS, 0x54834, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x6086C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_200, _B(ID_SND_OFF_200, FREE_CODE_OFF_1ST_200), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_200, sizeof(PRC_ID_SND_200) >> 2, PRC_ID_SND_200}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), ID_SND_OFF_200 + sizeof(u32)), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_200, _B(ID_RCV_OFF_200, FREE_CODE_OFF_2ND_200), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_200, sizeof(PRC_ID_RCV_200) >> 2, PRC_ID_RCV_200}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), ID_RCV_OFF_200 + sizeof(u32)), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_3_patchset,
|
||||
{ SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x483FC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_300, _B(ID_SND_OFF_300, FREE_CODE_OFF_1ST_300), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_300, sizeof(PRC_ID_SND_300) >> 2, PRC_ID_SND_300}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), ID_SND_OFF_300 + sizeof(u32)), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_300, _B(ID_RCV_OFF_300, FREE_CODE_OFF_2ND_300), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_300, sizeof(PRC_ID_RCV_300) >> 2, PRC_ID_RCV_300}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), ID_RCV_OFF_300 + sizeof(u32)), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_302_patchset,
|
||||
{ SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x48414, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_302, _B(ID_SND_OFF_302, FREE_CODE_OFF_1ST_302), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_302, sizeof(PRC_ID_SND_300) >> 2, PRC_ID_SND_300}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_300), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_300), ID_SND_OFF_302 + sizeof(u32)), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_302, _B(ID_RCV_OFF_302, FREE_CODE_OFF_2ND_302), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_302, sizeof(PRC_ID_RCV_300) >> 2, PRC_ID_RCV_300}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_300), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_300), ID_RCV_OFF_302 + sizeof(u32)), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_4_patchset,
|
||||
{ SVC_VERIFY_DS, 0x41EB4, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x4EBFC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_400, _B(ID_SND_OFF_400, FREE_CODE_OFF_1ST_400), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_400, sizeof(PRC_ID_SND_400) >> 2, PRC_ID_SND_400}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), // Branch back and skip 2 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), ID_SND_OFF_400 + sizeof(u32) * 2), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_400, _B(ID_RCV_OFF_400, FREE_CODE_OFF_2ND_400), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_400, sizeof(PRC_ID_RCV_400) >> 2, PRC_ID_RCV_400}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), // Branch back and skip 1 instruction.
|
||||
_B(FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), ID_RCV_OFF_400 + sizeof(u32)), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_5_patchset,
|
||||
{ SVC_GENERIC, 0x38C2C, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x45E6C, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x5513C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x54E30, _MOVZW(8, 0x1E00, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_500, _B(ID_SND_OFF_500, FREE_CODE_OFF_1ST_500), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_500, sizeof(PRC_ID_SND_500) >> 2, PRC_ID_SND_500}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), // Branch back and skip 2 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), ID_SND_OFF_500 + sizeof(u32) * 2), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_500, _B(ID_RCV_OFF_500, FREE_CODE_OFF_2ND_500), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_500, sizeof(PRC_ID_RCV_500) >> 2, PRC_ID_RCV_500}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), // Branch back and skip 2 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), ID_RCV_OFF_500 + sizeof(u32) * 2), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_6_patchset,
|
||||
{ SVC_GENERIC, 0x3A8CC, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x47EA0, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x57548, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x57330, _MOVZW(8, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_600, _B(ID_SND_OFF_600, FREE_CODE_OFF_1ST_600), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_600, sizeof(PRC_ID_SND_600) >> 2, PRC_ID_SND_600}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600), ID_SND_OFF_600 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_600, _B(ID_RCV_OFF_600, FREE_CODE_OFF_2ND_600), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_600, sizeof(PRC_ID_RCV_600) >> 2, PRC_ID_RCV_600}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_600 + sizeof(PRC_ID_RCV_600), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_600 + sizeof(PRC_ID_RCV_600), ID_RCV_OFF_600 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_7_patchset,
|
||||
{ SVC_GENERIC, 0x3C6E0, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x49E5C, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x581B0, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x57F98, _MOVZW(8, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_700, _B(ID_SND_OFF_700, FREE_CODE_OFF_1ST_700), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_700, sizeof(PRC_ID_SND_700) >> 2, PRC_ID_SND_700}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_700 + sizeof(PRC_ID_SND_700), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_700 + sizeof(PRC_ID_SND_700), ID_SND_OFF_700 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_700, _B(ID_RCV_OFF_700, FREE_CODE_OFF_2ND_700), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_700, sizeof(PRC_ID_RCV_700) >> 2, PRC_ID_RCV_700}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_700 + sizeof(PRC_ID_RCV_700), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_700 + sizeof(PRC_ID_RCV_700), ID_RCV_OFF_700 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_8_patchset,
|
||||
{ SVC_GENERIC, 0x3FAD0, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x4D15C, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x5BFAC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x5F9A4, _MOVZW(19, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_800, _B(ID_SND_OFF_800, FREE_CODE_OFF_1ST_800), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_800, sizeof(PRC_ID_SND_700) >> 2, PRC_ID_SND_700}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_800 + sizeof(PRC_ID_SND_700), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_800 + sizeof(PRC_ID_SND_700), ID_SND_OFF_800 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_800, _B(ID_RCV_OFF_800, FREE_CODE_OFF_2ND_800), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_800, sizeof(PRC_ID_RCV_700) >> 2, PRC_ID_RCV_700}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_800 + sizeof(PRC_ID_RCV_700), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_800 + sizeof(PRC_ID_RCV_700), ID_RCV_OFF_800 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_9_patchset,
|
||||
{ SVC_GENERIC, 0x43DFC, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x50628, _NOP(), NULL }, // Disable SVC verifications
|
||||
{ DEBUG_MODE_EN, 0x609E8, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x6493C, _MOVZW(19, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_900, _B(ID_SND_OFF_900, FREE_CODE_OFF_1ST_900), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_900, sizeof(PRC_ID_SND_900) >> 2, PRC_ID_SND_900}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_900 + sizeof(PRC_ID_SND_900), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_900 + sizeof(PRC_ID_SND_900), ID_SND_OFF_900 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_900, _B(ID_RCV_OFF_900, FREE_CODE_OFF_2ND_900), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_900, sizeof(PRC_ID_RCV_900) >> 2, PRC_ID_RCV_900}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_900 + sizeof(PRC_ID_RCV_900), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_900 + sizeof(PRC_ID_RCV_900), ID_RCV_OFF_900 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_10_patchset,
|
||||
{ SVC_GENERIC, 0x45DAC, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x523E4, _NOP(), NULL }, // Disable SVC verifications.
|
||||
{ DEBUG_MODE_EN, 0x62B14, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch.
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x66950, _MOVZW(19, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_1000, _B(ID_SND_OFF_1000, FREE_CODE_OFF_1ST_1000), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_1000, sizeof(PRC_ID_SND_1000) >> 2, PRC_ID_SND_1000}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000), ID_SND_OFF_1000 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_1000, _B(ID_RCV_OFF_1000, FREE_CODE_OFF_2ND_1000), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_1000, sizeof(PRC_ID_RCV_1000) >> 2, PRC_ID_RCV_1000}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1000 + sizeof(PRC_ID_RCV_1000), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_1000 + sizeof(PRC_ID_RCV_1000), ID_RCV_OFF_1000 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_11_patchset,
|
||||
{ SVC_GENERIC, 0x2FCE0, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x39194, _NOP(), NULL }, // Disable SVC verifications.
|
||||
{ DEBUG_MODE_EN, 0x460C0, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch.
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x490C4, _MOVZW(21, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_1100, _B(ID_SND_OFF_1100, FREE_CODE_OFF_1ST_1100), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_1100, sizeof(PRC_ID_SND_1100) >> 2, PRC_ID_SND_1100}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), ID_SND_OFF_1100 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_1100, _B(ID_RCV_OFF_1100, FREE_CODE_OFF_2ND_1100), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_1100, sizeof(PRC_ID_RCV_1100) >> 2, PRC_ID_RCV_1100}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), ID_RCV_OFF_1100 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_1101_patchset,
|
||||
{ SVC_GENERIC, 0x2FD04, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x39194, _NOP(), NULL }, // Disable SVC verifications.
|
||||
{ DEBUG_MODE_EN, 0x460C0, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch.
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x490C4, _MOVZW(21, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_1101, _B(ID_SND_OFF_1101, FREE_CODE_OFF_1ST_1100), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_1100, sizeof(PRC_ID_SND_1100) >> 2, PRC_ID_SND_1100}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), ID_SND_OFF_1101 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_1101, _B(ID_RCV_OFF_1101, FREE_CODE_OFF_2ND_1100), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_1100, sizeof(PRC_ID_RCV_1100) >> 2, PRC_ID_RCV_1100}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), ID_RCV_OFF_1101 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
// Kernel sha256 hashes.
|
||||
static const pkg2_kernel_id_t _pkg2_kernel_ids[] =
|
||||
{
|
||||
{ "\xb8\xc5\x0c\x68\x25\xa9\xb9\x5b", _kernel_1_patchset }, // 1.0.0
|
||||
{ "\x64\x0b\x51\xff\x28\x01\xb8\x30", _kernel_2_patchset }, // 2.0.0 - 2.3.0
|
||||
{ "\x50\x84\x23\xac\x6f\xa1\x5d\x3b", _kernel_3_patchset }, // 3.0.0 - 3.0.1
|
||||
{ "\x81\x9d\x08\xbe\xe4\x5e\x1f\xbb", _kernel_302_patchset }, // 3.0.2
|
||||
{ "\xe6\xc0\xb7\xe3\x2f\xf9\x44\x51", _kernel_4_patchset }, // 4.0.0 - 4.1.0
|
||||
{ "\xb2\x38\x61\xa8\xe1\xe2\xe4\xe4", _kernel_5_patchset }, // 5.0.0 - 5.1.0
|
||||
{ "\x85\x97\x40\xf6\xc0\x3e\x3d\x44", _kernel_6_patchset }, // 6.0.0 - 6.2.0
|
||||
{ "\xa2\x5e\x47\x0c\x8e\x6d\x2f\xd7", _kernel_7_patchset }, // 7.0.0 - 7.0.1
|
||||
{ "\xf1\x5e\xc8\x34\xfd\x68\xf0\xf0", _kernel_8_patchset }, // 8.0.0 - 8.1.0. Kernel only.
|
||||
{ "\x69\x00\x39\xdf\x21\x56\x70\x6b", _kernel_9_patchset }, // 9.0.0 - 9.1.0. Kernel only.
|
||||
{ "\xa2\xe3\xad\x1c\x98\xd8\x7a\x62", _kernel_9_patchset }, // 9.2.0. Kernel only.
|
||||
{ "\x21\xc1\xd7\x24\x8e\xcd\xbd\xa8", _kernel_10_patchset }, // 10.0.0. Kernel only.
|
||||
{ "\xD5\xD0\xBA\x5D\x52\xB9\x77\x85", _kernel_11_patchset }, // 11.0.0. Kernel only.
|
||||
{ "\xF8\x1E\xE0\x30\x3C\x7A\x08\x04", _kernel_1101_patchset },// 11.0.1. Kernel only.
|
||||
};
|
||||
|
||||
enum kip_offset_section
|
||||
{
|
||||
KIP_TEXT = 0,
|
||||
@@ -462,272 +65,7 @@ enum kip_offset_section
|
||||
#define GET_KIP_PATCH_OFFSET(x) ((x) & KIP_PATCH_OFFSET_MASK)
|
||||
#define KPS(x) ((u32)(x) << KIP_PATCH_SECTION_SHIFT)
|
||||
|
||||
static kip1_patch_t _fs_emummc[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 1, 0, "", "" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_100[] =
|
||||
{
|
||||
{ "nogc", NULL },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_40x[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0xA3458, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
|
||||
{ KPS(KIP_TEXT) | 0xAAB44, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_40x[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_40x },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_410[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0xA34BC, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
|
||||
{ KPS(KIP_TEXT) | 0xAABA8, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_410[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_410 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_50x[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0xCF3C4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ KPS(KIP_TEXT) | 0xD73A0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_50x[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_50x },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_510[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0xCF794, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ KPS(KIP_TEXT) | 0xD7770, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_510[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_510 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_600[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x12CC20, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1538F4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_600_exfat[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x138320, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15EFF4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_600[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_600 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_600_exfat[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_600_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_700[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x134160, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15BF04, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_700_exfat[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x13F710, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1674B4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_700[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_700 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_700_exfat[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_700_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_800[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x136800, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15EB94, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_800_exfat[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x141DB0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x16A144, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_800[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_800 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_800_exfat[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_800_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_900[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x129420, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x143268, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_900[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_900 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_910[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x129430, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x143278, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_910[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_910 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1000[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x13BE90, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x14DE08, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1000[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_1000 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1020[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x13C2F0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x14E268, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1020[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_1020 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1100[] =
|
||||
{
|
||||
{ KPS(KIP_TEXT) | 0x1398B4, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x156EB8, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1100[] =
|
||||
{
|
||||
{ "nogc", _fs_nogc_1100 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
// SHA256 hashes.
|
||||
static kip1_id_t _kip_ids[] =
|
||||
{
|
||||
{ "FS", "\xde\x9f\xdd\xa4\x08\x5d\xd5\xfe", _fs_patches_100 }, // FS 1.0.0
|
||||
{ "FS", "\xfc\x3e\x80\x99\x1d\xca\x17\x96", _fs_patches_100 }, // FS 1.0.0 exfat
|
||||
{ "FS", "\xcd\x7b\xbe\x18\xd6\x13\x0b\x28", _fs_patches_100 }, // FS 2.0.0
|
||||
{ "FS", "\xe7\x66\x92\xdf\xaa\x04\x20\xe9", _fs_patches_100 }, // FS 2.0.0 exfat
|
||||
{ "FS", "\x0d\x70\x05\x62\x7b\x07\x76\x7c", _fs_patches_100 }, // FS 2.1.0
|
||||
{ "FS", "\xdb\xd8\x5f\xca\xcc\x19\x3d\xa8", _fs_patches_100 }, // FS 2.1.0 exfat
|
||||
{ "FS", "\xa8\x6d\xa5\xe8\x7e\xf1\x09\x7b", _fs_patches_100 }, // FS 3.0.0
|
||||
{ "FS", "\x98\x1c\x57\xe7\xf0\x2f\x70\xf7", _fs_patches_100 }, // FS 3.0.0 exfat
|
||||
{ "FS", "\x57\x39\x7c\x06\x3f\x10\xb6\x31", _fs_patches_100 }, // FS 3.0.1
|
||||
{ "FS", "\x07\x30\x99\xd7\xc6\xad\x7d\x89", _fs_patches_100 }, // FS 3.0.1 exfat
|
||||
{ "FS", "\x06\xe9\x07\x19\x59\x5a\x01\x0c", _fs_patches_40x }, // FS 4.0.1
|
||||
{ "FS", "\x54\x9b\x0f\x8d\x6f\x72\xc4\xe9", _fs_patches_40x }, // FS 4.0.1 exfat
|
||||
{ "FS", "\x80\x96\xaf\x7c\x6a\x35\xaa\x82", _fs_patches_410 }, // FS 4.1.0
|
||||
{ "FS", "\x02\xd5\xab\xaa\xfd\x20\xc8\xb0", _fs_patches_410 }, // FS 4.1.0 exfat
|
||||
{ "FS", "\xa6\xf2\x7a\xd9\xac\x7c\x73\xad", _fs_patches_50x }, // FS 5.0.0
|
||||
{ "FS", "\xce\x3e\xcb\xa2\xf2\xf0\x62\xf5", _fs_patches_50x }, // FS 5.0.0 exfat
|
||||
{ "FS", "\x76\xf8\x74\x02\xc9\x38\x7c\x0f", _fs_patches_510 }, // FS 5.1.0
|
||||
{ "FS", "\x10\xb2\xd8\x16\x05\x48\x85\x99", _fs_patches_510 }, // FS 5.1.0 exfat
|
||||
{ "FS", "\x1b\x82\xcb\x22\x18\x67\xcb\x52", _fs_patches_600 }, // FS 6.0.0-4.0
|
||||
{ "FS", "\x96\x6a\xdd\x3d\x20\xb6\x27\x13", _fs_patches_600_exfat }, // FS 6.0.0-4.0 exfat
|
||||
{ "FS", "\x3a\x57\x4d\x43\x61\x86\x19\x1d", _fs_patches_600 }, // FS 6.0.0-5.0
|
||||
{ "FS", "\x33\x05\x53\xf6\xb5\xfb\x55\xc4", _fs_patches_600_exfat }, // FS 6.0.0-5.0 exfat
|
||||
{ "FS", "\x2A\xDB\xE9\x7E\x9B\x5F\x41\x77", _fs_patches_700 }, // FS 7.0.0
|
||||
{ "FS", "\x2C\xCE\x65\x9C\xEC\x53\x6A\x8E", _fs_patches_700_exfat }, // FS 7.0.0 exfat
|
||||
{ "FS", "\xB2\xF5\x17\x6B\x35\x48\x36\x4D", _fs_patches_800 }, // FS 8.0.0
|
||||
{ "FS", "\xDB\xD9\x41\xC0\xC5\x3C\x52\xCC", _fs_patches_800_exfat }, // FS 8.0.0 exfat
|
||||
{ "FS", "\x6B\x09\xB6\x7B\x29\xC0\x20\x24", _fs_patches_800 }, // FS 8.1.0
|
||||
{ "FS", "\xB4\xCA\xE1\xF2\x49\x65\xD9\x2E", _fs_patches_800_exfat }, // FS 8.1.0 exfat
|
||||
{ "FS", "\x46\x87\x40\x76\x1E\x19\x3E\xB7", _fs_patches_900 }, // FS 9.0.0
|
||||
{ "FS", "\x7C\x95\x13\x76\xE5\xC1\x2D\xF8", _fs_patches_900 }, // FS 9.0.0 exfat
|
||||
{ "FS", "\xB5\xE7\xA6\x4C\x6F\x5C\x4F\xE3", _fs_patches_910 }, // FS 9.1.0
|
||||
{ "FS", "\xF1\x96\xD1\x44\xD0\x44\x45\xB6", _fs_patches_910 }, // FS 9.1.0 exfat
|
||||
{ "FS", "\x3E\xEB\xD9\xB7\xBC\xD1\xB5\xE0", _fs_patches_1000 }, // FS 10.0.0
|
||||
{ "FS", "\x81\x7E\xA2\xB0\xB7\x02\xC1\xF3", _fs_patches_1000 }, // FS 10.0.0 exfat
|
||||
{ "FS", "\xA9\x52\xB6\x57\xAD\xF9\xC2\xBA", _fs_patches_1020 }, // FS 10.2.0
|
||||
{ "FS", "\x16\x0D\x3E\x10\x4E\xAD\x61\x76", _fs_patches_1020 }, // FS 10.2.0 exfat
|
||||
{ "FS", "\xE3\x99\x15\x6E\x84\x4E\xB0\xAA", _fs_patches_1100 }, // FS 11.0.0
|
||||
{ "FS", "\x0B\xA1\x5B\xB3\x04\xB5\x05\x63", _fs_patches_1100 }, // FS 11.0.0 exfat
|
||||
};
|
||||
#include "pkg2_patches.inl"
|
||||
|
||||
static kip1_id_t *_kip_id_sets = _kip_ids;
|
||||
static u32 _kip_id_sets_cnt = ARRAY_SIZE(_kip_ids);
|
||||
@@ -1132,7 +470,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
if (numPatches >= MAX_NUM_PATCHES_REQUESTED)
|
||||
return "too_many_patches";
|
||||
}
|
||||
else if (*p >= 'A' && *p <= 'Z')
|
||||
else if (*p >= 'A' && *p <= 'Z') // Convert to lowercase.
|
||||
*p += 0x20;
|
||||
}
|
||||
}
|
||||
@@ -1257,15 +595,15 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
emummc_patch_selected = true;
|
||||
patchesApplied |= appliedMask;
|
||||
|
||||
break;
|
||||
continue; // Patching is done later.
|
||||
}
|
||||
|
||||
if (currPatchset->patches == NULL)
|
||||
{
|
||||
gfx_printf("Patch '%s' not necessary for %s KIP1\n", currPatchset->name, (const char*)ki->kip1->name);
|
||||
DPRINTF("Patch '%s' not necessary for %s KIP1\n", currPatchset->name, (const char*)ki->kip1->name);
|
||||
patchesApplied |= appliedMask;
|
||||
|
||||
break;
|
||||
continue; // Continue in case it's double defined.
|
||||
}
|
||||
|
||||
unsigned char* kipSectData = ki->kip1->data;
|
||||
@@ -1287,7 +625,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
}
|
||||
|
||||
u32 currOffset = GET_KIP_PATCH_OFFSET(currPatch->offset);
|
||||
// If source is does not match and is not already patched, throw an error.
|
||||
// If source does not match and is not already patched, throw an error.
|
||||
if ((memcmp(&kipSectData[currOffset], currPatch->srcData, currPatch->length) != 0) &&
|
||||
(memcmp(&kipSectData[currOffset], currPatch->dstData, currPatch->length) != 0))
|
||||
{
|
||||
@@ -1306,11 +644,12 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
}
|
||||
|
||||
patchesApplied |= appliedMask;
|
||||
break;
|
||||
continue; // Continue in case it's double defined.
|
||||
}
|
||||
currPatchset++;
|
||||
}
|
||||
if (emummc_patch_selected && !strncmp(_kip_id_sets[currKipIdx].name, "FS", 2))
|
||||
|
||||
if (emummc_patch_selected && !strncmp(_kip_id_sets[currKipIdx].name, "FS", sizeof(ki->kip1->name)))
|
||||
{
|
||||
emummc_patch_selected = false;
|
||||
emu_cfg.fs_ver = currKipIdx;
|
||||
@@ -1319,7 +658,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
if (currKipIdx > 17)
|
||||
emu_cfg.fs_ver -= 2;
|
||||
|
||||
gfx_printf("Injecting emuMMC. FS ver: %d\n", emu_cfg.fs_ver);
|
||||
gfx_printf("Injecting emuMMC. FS ID: %d\n", emu_cfg.fs_ver);
|
||||
if (_kipm_inject("/bootloader/sys/emummc.kipm", "FS", ki))
|
||||
return "emummc";
|
||||
}
|
||||
@@ -1335,36 +674,14 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const u8 mkey_vector_8xx[][0x10] =
|
||||
{
|
||||
// Master key 8 encrypted with 9. (8.1.0 with 9.0.0)
|
||||
{ 0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80 },
|
||||
// Master key 9 encrypted with 10. (9.0.0 with 9.1.0)
|
||||
{ 0xB8, 0x96, 0x9E, 0x4A, 0x00, 0x0D, 0xD6, 0x28, 0xB3, 0xD1, 0xDB, 0x68, 0x5F, 0xFB, 0xE1, 0x2A }
|
||||
};
|
||||
|
||||
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
|
||||
{
|
||||
// Decrypt older encrypted mkey.
|
||||
se_aes_crypt_ecb(src_slot, 0, mkey, 0x10, key_seed, 0x10);
|
||||
// Set and unwrap pkg2 key.
|
||||
se_aes_key_clear(9);
|
||||
se_aes_key_set(9, mkey, 0x10);
|
||||
se_aes_unwrap_key(9, 9, package2_keyseed);
|
||||
|
||||
// Decrypt header.
|
||||
se_aes_crypt_ctr(9, tmp_test, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
|
||||
|
||||
// Return if header is valid.
|
||||
return (tmp_test->magic == PKG2_MAGIC);
|
||||
}
|
||||
// Master key 7 encrypted with 8. (7.0.0 with 8.1.0). AES-ECB
|
||||
static const u8 mkey_vector_7xx[SE_KEY_128_SIZE] =
|
||||
{ 0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29 };
|
||||
|
||||
u8 pkg2_keyslot;
|
||||
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
|
||||
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo)
|
||||
{
|
||||
pkg2_hdr_t mkey_test;
|
||||
u8 *pdata = (u8 *)data;
|
||||
pkg2_keyslot = 8;
|
||||
|
||||
// Skip signature.
|
||||
pdata += 0x100;
|
||||
@@ -1374,58 +691,24 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
|
||||
// Skip header.
|
||||
pdata += sizeof(pkg2_hdr_t);
|
||||
|
||||
// Check if we need to decrypt with newer mkeys. Valid for sept for 8.1.0 and up.
|
||||
se_aes_crypt_ctr(8, &mkey_test, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
|
||||
// Set pkg2 key slot to default. If 7.0.0 it will change to 9.
|
||||
pkg2_keyslot = 8;
|
||||
|
||||
if (mkey_test.magic == PKG2_MAGIC)
|
||||
goto key_found;
|
||||
|
||||
// Decrypt older pkg2 via new mkeys.
|
||||
if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX))
|
||||
// Decrypt 7.0.0 pkg2 via 8.1.0 mkey on Erista.
|
||||
if (!h_cfg.t210b01 && kb == KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
u8 tmp_mkey[0x10];
|
||||
u8 decr_slot = !h_cfg.t210b01 ? (!h_cfg.aes_slots_new ? 12 : 13) : 7; // Sept mkey or T210B01 mkey.
|
||||
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / 0x10;
|
||||
u8 mkey_seeds_idx = mkey_seeds_cnt; // Real index + 1.
|
||||
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (KB_FIRMWARE_VERSION_MAX - kb);
|
||||
u8 tmp_mkey[SE_KEY_128_SIZE];
|
||||
|
||||
while (mkey_seeds_cnt)
|
||||
{
|
||||
// Decrypt and validate mkey.
|
||||
int res = _pkg2_key_unwrap_validate(&mkey_test, hdr, decr_slot,
|
||||
tmp_mkey, mkey_vector_8xx[mkey_seeds_idx - 1]);
|
||||
// Decrypt 7.0.0 encrypted mkey.
|
||||
se_aes_crypt_ecb(!is_exo ? 7 : 13, DECRYPT, tmp_mkey, SE_KEY_128_SIZE, mkey_vector_7xx, SE_KEY_128_SIZE);
|
||||
|
||||
if (res)
|
||||
{
|
||||
pkg2_keyslot = 9;
|
||||
goto key_found;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set current mkey in order to decrypt a lower mkey.
|
||||
mkey_seeds_idx--;
|
||||
se_aes_key_clear(9);
|
||||
se_aes_key_set(9, tmp_mkey, 0x10);
|
||||
// Set and unwrap pkg2 key.
|
||||
se_aes_key_set(9, tmp_mkey, SE_KEY_128_SIZE);
|
||||
se_aes_unwrap_key(9, 9, package2_keyseed);
|
||||
|
||||
decr_slot = 9; // Temp key.
|
||||
|
||||
// Check if we tried last key for that pkg2 version.
|
||||
// And start with a lower mkey in case sept is older.
|
||||
if (mkey_seeds_idx == mkey_seeds_min_idx)
|
||||
{
|
||||
mkey_seeds_cnt--;
|
||||
mkey_seeds_idx = mkey_seeds_cnt;
|
||||
decr_slot = !h_cfg.aes_slots_new ? 12 : 13; // Sept mkey.
|
||||
}
|
||||
|
||||
// Out of keys. pkg2 is latest or process failed.
|
||||
if (!mkey_seeds_cnt)
|
||||
se_aes_key_clear(9);
|
||||
}
|
||||
}
|
||||
pkg2_keyslot = 9;
|
||||
}
|
||||
|
||||
key_found:
|
||||
// Decrypt header.
|
||||
se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
|
||||
//gfx_hexdump((u32)hdr, hdr, 0x100);
|
||||
@@ -1433,13 +716,14 @@ key_found:
|
||||
if (hdr->magic != PKG2_MAGIC)
|
||||
return NULL;
|
||||
|
||||
// Decrypt sections.
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
|
||||
if (!hdr->sec_size[i])
|
||||
continue;
|
||||
|
||||
se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
|
||||
se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * SE_AES_IV_SIZE]);
|
||||
//gfx_hexdump((u32)pdata, pdata, 0x100);
|
||||
|
||||
pdata += hdr->sec_size[i];
|
||||
@@ -1452,9 +736,13 @@ static u32 _pkg2_ini1_build(u8 *pdst, pkg2_hdr_t *hdr, link_t *kips_info, bool n
|
||||
{
|
||||
u32 ini1_size = sizeof(pkg2_ini1_t);
|
||||
pkg2_ini1_t *ini1 = (pkg2_ini1_t *)pdst;
|
||||
|
||||
// Set initial header and magic.
|
||||
memset(ini1, 0, sizeof(pkg2_ini1_t));
|
||||
ini1->magic = INI1_MAGIC;
|
||||
pdst += sizeof(pkg2_ini1_t);
|
||||
|
||||
// Merge kips into INI1.
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kips_info, link)
|
||||
{
|
||||
DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->size);
|
||||
@@ -1463,13 +751,17 @@ DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->s
|
||||
ini1_size += ki->size;
|
||||
ini1->num_procs++;
|
||||
}
|
||||
|
||||
// Align size and set it.
|
||||
ini1_size = ALIGN(ini1_size, 4);
|
||||
ini1->size = ini1_size;
|
||||
|
||||
// Encrypt INI1 in its own section if old pkg2. Otherwise it gets embedded into Kernel.
|
||||
if (!new_pkg2)
|
||||
{
|
||||
hdr->sec_size[PKG2_SEC_INI1] = ini1_size;
|
||||
hdr->sec_off[PKG2_SEC_INI1] = 0x14080000;
|
||||
se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * 0x10]);
|
||||
se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * SE_AES_IV_SIZE]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1486,11 +778,20 @@ void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info)
|
||||
launch_ctxt_t * ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
u32 kernel_size = ctxt->kernel_size;
|
||||
bool is_meso = *(u32 *)(ctxt->kernel + 4) == ATM_MESOSPHERE;
|
||||
u8 kb = ctxt->pkg1_id->kb;
|
||||
|
||||
// Force new Package2 if Mesosphere.
|
||||
if (is_meso)
|
||||
ctxt->new_pkg2 = true;
|
||||
|
||||
// Set key version. For Erista 7.0.0, use 8.1.0 because of a bug in Exo2?
|
||||
u8 key_ver = kb ? kb + 1 : 0;
|
||||
if (pkg2_keyslot == 9)
|
||||
{
|
||||
key_ver = KB_FIRMWARE_VERSION_810 + 1;
|
||||
pkg2_keyslot = 8;
|
||||
}
|
||||
|
||||
// Signature.
|
||||
memset(pdst, 0, 0x100);
|
||||
pdst += 0x100;
|
||||
@@ -1526,11 +827,11 @@ DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel
|
||||
hdr->sec_off[PKG2_SEC_KERNEL] = 0x60000;
|
||||
}
|
||||
hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size;
|
||||
se_aes_crypt_ctr(pkg2_keyslot, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * 0x10]);
|
||||
se_aes_crypt_ctr(pkg2_keyslot, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * SE_AES_IV_SIZE]);
|
||||
pdst += kernel_size;
|
||||
DPRINTF("kernel encrypted\n");
|
||||
|
||||
/// Build INI1 for old Package2.
|
||||
// Build INI1 for old Package2.
|
||||
u32 ini1_size = 0;
|
||||
if (!ctxt->new_pkg2)
|
||||
ini1_size = _pkg2_ini1_build(pdst, hdr, kips_info, false);
|
||||
@@ -1544,15 +845,11 @@ DPRINTF("INI1 encrypted\n");
|
||||
se_calc_sha256_oneshot(&hdr->sec_sha256[0x20 * PKG2_SEC_INI1],
|
||||
(void *)pk2_hash_data, hdr->sec_size[PKG2_SEC_INI1]);
|
||||
|
||||
//Encrypt header.
|
||||
u8 key_ver = ctxt->pkg1_id->kb ? ctxt->pkg1_id->kb + 1 : 0;
|
||||
// Encrypt header.
|
||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
hdr->ctr[4] = key_ver;
|
||||
se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
|
||||
memset(hdr->ctr, 0 , 0x10);
|
||||
memset(hdr->ctr, 0 , SE_AES_IV_SIZE);
|
||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
hdr->ctr[4] = key_ver;
|
||||
|
||||
if (pkg2_keyslot != 8)
|
||||
se_aes_key_clear(9);
|
||||
}
|
||||
|
||||
@@ -99,17 +99,17 @@ typedef struct _pkg2_kip1_sec_t
|
||||
|
||||
typedef struct _pkg2_kip1_t
|
||||
{
|
||||
u32 magic;
|
||||
u8 name[12];
|
||||
u64 tid;
|
||||
u32 proc_cat;
|
||||
u8 main_thrd_prio;
|
||||
u8 def_cpu_core;
|
||||
u8 res;
|
||||
u8 flags;
|
||||
pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
|
||||
u32 caps[0x20];
|
||||
u8 data[];
|
||||
/* 0x000 */ u32 magic;
|
||||
/* 0x004*/ u8 name[12];
|
||||
/* 0x010 */ u64 tid;
|
||||
/* 0x018 */ u32 proc_cat;
|
||||
/* 0x01C */ u8 main_thrd_prio;
|
||||
/* 0x01D */ u8 def_cpu_core;
|
||||
/* 0x01E */ u8 res;
|
||||
/* 0x01F */ u8 flags;
|
||||
/* 0x020 */ pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
|
||||
/* 0x080 */ u32 caps[0x20];
|
||||
/* 0x100 */ u8 data[];
|
||||
} pkg2_kip1_t;
|
||||
|
||||
typedef struct _pkg2_kip1_info_t
|
||||
@@ -156,7 +156,7 @@ void pkg2_get_ids(kip1_id_t **ids, u32 *entries);
|
||||
const char* pkg2_patch_kips(link_t *info, char* patchNames);
|
||||
|
||||
const pkg2_kernel_id_t *pkg2_identify(u8 *hash);
|
||||
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb);
|
||||
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo);
|
||||
void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -86,9 +86,9 @@ static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec,
|
||||
|
||||
int ini_patch_parse(link_t *dst, char *ini_path)
|
||||
{
|
||||
FIL fp;
|
||||
u32 lblen;
|
||||
char lbuf[512];
|
||||
FIL fp;
|
||||
ini_kip_sec_t *ksec = NULL;
|
||||
|
||||
// Open ini.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user