├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── ipl ├── ELF.h ├── btn.c ├── btn.h ├── clock.c ├── clock.h ├── cluster.c ├── cluster.h ├── di.c ├── di.h ├── di.inl ├── diskio.c ├── diskio.h ├── emc.h ├── ff.c ├── ff.h ├── ffconf.h ├── ffunicode.c ├── fuse.c ├── fuse.h ├── gfx.c ├── gfx.h ├── gpio.c ├── gpio.h ├── heap.c ├── heap.h ├── hos.c ├── hos.h ├── i2c.c ├── i2c.h ├── ini.c ├── ini.h ├── integer.h ├── kfuse.c ├── kfuse.h ├── link.ld ├── list.h ├── lz.c ├── lz.h ├── main.c ├── max77620.h ├── max7762x.c ├── max7762x.h ├── mc.c ├── mc.h ├── mc_t210.h ├── mmc.h ├── nx_emmc.c ├── nx_emmc.h ├── pinmux.c ├── pinmux.h ├── pkg1.c ├── pkg1.h ├── pkg2.c ├── pkg2.h ├── pmc.h ├── pmc_t210_lp0.h ├── reloc.S ├── sd.h ├── sdmmc.c ├── sdmmc.h ├── sdmmc_driver.c ├── sdmmc_driver.h ├── sdmmc_t210.h ├── sdram.c ├── sdram.h ├── sdram.inl ├── sdram_lp0.c ├── sdram_lz.inl ├── sdram_param_t210.h ├── sdram_param_t210_lp0.h ├── se.c ├── se.h ├── se_t210.h ├── start.S ├── t210.h ├── tsec.c ├── tsec.h ├── tui.c ├── tui.h ├── types.h ├── uart.c ├── uart.h ├── util.c └── util.h └── tools ├── emc.def ├── fix_regs.py └── mc.def /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | .vscode 3 | build_ipl/* 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(strip $(DEVKITARM)),) 2 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 3 | endif 4 | 5 | CC = $(DEVKITARM)/bin/arm-none-eabi-gcc 6 | LD = $(DEVKITARM)/bin/arm-none-eabi-ld 7 | OBJCOPY = $(DEVKITARM)/bin/arm-none-eabi-objcopy 8 | 9 | TARGET := ipl 10 | BUILD := build_ipl 11 | SOURCEDIR := ipl 12 | OBJS = $(addprefix $(BUILD)/, \ 13 | start.o \ 14 | main.o \ 15 | btn.o \ 16 | clock.o \ 17 | cluster.o \ 18 | fuse.o \ 19 | gpio.o \ 20 | heap.o \ 21 | hos.o \ 22 | i2c.o \ 23 | kfuse.o \ 24 | lz.o \ 25 | max7762x.o \ 26 | mc.o \ 27 | nx_emmc.o \ 28 | sdmmc.o \ 29 | sdmmc_driver.o \ 30 | sdram.o \ 31 | sdram_lp0.o \ 32 | tui.o \ 33 | util.o \ 34 | di.o \ 35 | gfx.o \ 36 | pinmux.o \ 37 | pkg1.o \ 38 | pkg2.o \ 39 | se.o \ 40 | tsec.o \ 41 | uart.o \ 42 | ini.o \ 43 | ) 44 | OBJS += $(addprefix $(BUILD)/, diskio.o ff.o ffunicode.o) 45 | 46 | ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork 47 | CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11# -Wall 48 | LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections 49 | 50 | .PHONY: all clean 51 | 52 | all: $(BUILD)/$(TARGET) 53 | 54 | clean: 55 | @rm -rf $(OBJS) 56 | @rm -rf $(BUILD)/$(TARGET).elf 57 | @rm -rf $(BUILD)/$(TARGET) 58 | 59 | $(BUILD)/$(TARGET): $(BUILD)/$(TARGET).elf 60 | $(OBJCOPY) -S -O binary $< $@ 61 | 62 | $(BUILD)/$(TARGET).elf: $(OBJS) 63 | $(CC) $(LDFLAGS) -T ipl/link.ld $^ -o $@ 64 | 65 | $(BUILD)/%.o: $(SOURCEDIR)/%.c 66 | $(CC) $(CFLAGS) -c $< -o $@ 67 | 68 | $(BUILD)/%.o: $(SOURCEDIR)/%.S 69 | $(CC) $(CFLAGS) -c $< -o $@ 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hekate for 4.x 2 | 3 | Original by @nwert, ported from [hekate-ipl-50x](https://github.com/Jan4V/hekate-ipl-50x) 4 | 5 | ![Image of Hekate](https://upload.wikimedia.org/wikipedia/commons/f/fc/H%C3%A9cate_-_Mallarm%C3%A9.png) 6 | 7 | Nintendo Switch bootloader, firmware patcher, and more. 8 | 9 | ## ipl config 10 | 11 | The ipl can be configured via 'hekate_ipl.ini' (if it is present on the SD card). Each ini section represents a boot entry, except for the special section 'config' that controls the global configuration. 12 | 13 | Possible key/value combinations: 14 | 15 | - warmboot={SD path} 16 | - secmon={SD path} 17 | - kernel={SD path} 18 | - kip1={SD path} 19 | -------------------------------------------------------------------------------- /ipl/btn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "btn.h" 18 | #include "i2c.h" 19 | #include "gpio.h" 20 | #include "t210.h" 21 | 22 | u32 btn_read() 23 | { 24 | u32 res = 0; 25 | if (!gpio_read(GPIO_PORT_X, GPIO_PIN_7)) 26 | res |= BTN_VOL_DOWN; 27 | if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6)) 28 | res |= BTN_VOL_UP; 29 | if (i2c_recv_byte(4, 0x3C, 0x15) & 0x4) 30 | res |= BTN_POWER; 31 | return res; 32 | } 33 | 34 | u32 btn_wait() 35 | { 36 | u32 res = 0, btn = btn_read(); 37 | do 38 | { 39 | res = btn_read(); 40 | } while (btn == res); 41 | return res; 42 | } 43 | -------------------------------------------------------------------------------- /ipl/btn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _BTN_H_ 18 | #define _BTN_H_ 19 | 20 | #include "types.h" 21 | 22 | #define BTN_POWER 0x1 23 | #define BTN_VOL_DOWN 0x2 24 | #define BTN_VOL_UP 0x4 25 | 26 | u32 btn_read(); 27 | u32 btn_wait(); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ipl/clock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "clock.h" 18 | #include "t210.h" 19 | #include "util.h" 20 | #include "sdmmc.h" 21 | 22 | static const clock_t _clock_uart[] = { 23 | /* UART A */ { 4, 0x10, 0x178, 6, 0, 0 }, 24 | /* UART B */ { 4, 0x10, 0x17C, 7, 0, 0 }, 25 | /* UART C */ { 8, 0x14, 0x1A0, 0x17, 0, 0 }, 26 | /* UART D */ { 0 }, 27 | /* UART E */ { 0 } 28 | }; 29 | 30 | static const clock_t _clock_i2c[] = { 31 | /* I2C1 */ { 4, 0x10, 0x124, 0xC, 6, 0 }, 32 | /* I2C2 */ { 0 }, 33 | /* I2C3 */ { 0 }, 34 | /* I2C4 */ { 0 }, 35 | /* I2C5 */ { 8, 0x14, 0x128, 0xF, 6, 0 }, 36 | /* I2C6 */ { 0 } 37 | }; 38 | 39 | static clock_t _clock_se = { 0x358, 0x360, 0x42C, 0x1F, 0, 0 }; 40 | 41 | static clock_t _clock_host1x = { 4, 0x10, 0x180, 0x1C, 4, 3 }; 42 | static clock_t _clock_tsec = { 0xC, 0x18, 0x1F4, 0x13, 0, 2 }; 43 | static clock_t _clock_sor_safe = { 0x2A4, 0x298, 0, 0x1E, 0, 0 }; 44 | static clock_t _clock_sor0 = { 0x28C, 0x280, 0, 0x16, 0, 0 }; 45 | static clock_t _clock_sor1 = { 0x28C, 0x280, 0x410, 0x17, 0, 2 }; 46 | static clock_t _clock_kfuse = { 8, 0x14, 0, 8, 0, 0 }; 47 | 48 | static clock_t _clock_cl_dvfs = { 0x35C, 0x364, 0, 0x1B, 0, 0 }; 49 | static clock_t _clock_coresight = { 0xC, 0x18, 0x1D4, 9, 0, 4}; 50 | 51 | void clock_enable(const clock_t *clk) 52 | { 53 | //Put clock into reset. 54 | CLOCK(clk->reset) = CLOCK(clk->reset) & ~(1 << clk->index) | (1 << clk->index); 55 | //Disable. 56 | CLOCK(clk->enable) &= ~(1 << clk->index); 57 | //Configure clock source if required. 58 | if (clk->source) 59 | CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29); 60 | //Enable. 61 | CLOCK(clk->enable) = CLOCK(clk->enable) & ~(1 << clk->index) | (1 << clk->index); 62 | //Take clock off reset. 63 | CLOCK(clk->reset) &= ~(1 << clk->index); 64 | } 65 | 66 | void clock_disable(const clock_t *clk) 67 | { 68 | //Put clock into reset. 69 | CLOCK(clk->reset) = CLOCK(clk->reset) & ~(1 << clk->index) | (1 << clk->index); 70 | //Disable. 71 | CLOCK(clk->enable) &= ~(1 << clk->index); 72 | } 73 | 74 | void clock_enable_fuse(u32 enable) 75 | { 76 | CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF | ((enable & 1) << 28) & 0x10000000; 77 | } 78 | 79 | void clock_enable_uart(u32 idx) 80 | { 81 | clock_enable(&_clock_uart[idx]); 82 | } 83 | 84 | void clock_enable_i2c(u32 idx) 85 | { 86 | clock_enable(&_clock_i2c[idx]); 87 | } 88 | 89 | void clock_enable_se() 90 | { 91 | clock_enable(&_clock_se); 92 | } 93 | 94 | void clock_enable_host1x() 95 | { 96 | clock_enable(&_clock_host1x); 97 | } 98 | 99 | void clock_disable_host1x() 100 | { 101 | clock_disable(&_clock_host1x); 102 | } 103 | 104 | void clock_enable_tsec() 105 | { 106 | clock_enable(&_clock_tsec); 107 | } 108 | 109 | void clock_disable_tsec() 110 | { 111 | clock_disable(&_clock_tsec); 112 | } 113 | 114 | void clock_enable_sor_safe() 115 | { 116 | clock_enable(&_clock_sor_safe); 117 | } 118 | 119 | void clock_disable_sor_safe() 120 | { 121 | clock_disable(&_clock_sor_safe); 122 | } 123 | 124 | void clock_enable_sor0() 125 | { 126 | clock_enable(&_clock_sor0); 127 | } 128 | 129 | void clock_disable_sor0() 130 | { 131 | clock_disable(&_clock_sor0); 132 | } 133 | 134 | void clock_enable_sor1() 135 | { 136 | clock_enable(&_clock_sor1); 137 | } 138 | 139 | void clock_disable_sor1() 140 | { 141 | clock_disable(&_clock_sor1); 142 | } 143 | 144 | void clock_enable_kfuse() 145 | { 146 | //clock_enable(&_clock_kfuse); 147 | CLOCK(0x8) = CLOCK(0x8) & 0xFFFFFEFF | 0x100; 148 | CLOCK(0x14) &= 0xFFFFFEFF; 149 | CLOCK(0x14) = CLOCK(0x14) & 0xFFFFFEFF | 0x100; 150 | sleep(10); 151 | CLOCK(0x8) &= 0xFFFFFEFF; 152 | sleep(20); 153 | } 154 | 155 | void clock_disable_kfuse() 156 | { 157 | clock_disable(&_clock_kfuse); 158 | } 159 | 160 | void clock_enable_cl_dvfs() 161 | { 162 | clock_enable(&_clock_cl_dvfs); 163 | } 164 | 165 | void clock_enable_coresight() 166 | { 167 | clock_enable(&_clock_coresight); 168 | } 169 | 170 | #define L_SWR_SDMMC1_RST (1<<14) 171 | #define L_SWR_SDMMC2_RST (1<<9) 172 | #define L_SWR_SDMMC4_RST (1<<15) 173 | #define U_SWR_SDMMC3_RST (1<<5) 174 | 175 | #define L_CLK_ENB_SDMMC1 (1<<14) 176 | #define L_CLK_ENB_SDMMC2 (1<<9) 177 | #define L_CLK_ENB_SDMMC4 (1<<15) 178 | #define U_CLK_ENB_SDMMC3 (1<<5) 179 | 180 | #define L_SET_SDMMC1_RST (1<<14) 181 | #define L_SET_SDMMC2_RST (1<<9) 182 | #define L_SET_SDMMC4_RST (1<<15) 183 | #define U_SET_SDMMC3_RST (1<<5) 184 | 185 | #define L_CLR_SDMMC1_RST (1<<14) 186 | #define L_CLR_SDMMC2_RST (1<<9) 187 | #define L_CLR_SDMMC4_RST (1<<15) 188 | #define U_CLR_SDMMC3_RST (1<<5) 189 | 190 | #define L_SET_CLK_ENB_SDMMC1 (1<<14) 191 | #define L_SET_CLK_ENB_SDMMC2 (1<<9) 192 | #define L_SET_CLK_ENB_SDMMC4 (1<<15) 193 | #define U_SET_CLK_ENB_SDMMC3 (1<<5) 194 | 195 | #define L_CLR_CLK_ENB_SDMMC1 (1<<14) 196 | #define L_CLR_CLK_ENB_SDMMC2 (1<<9) 197 | #define L_CLR_CLK_ENB_SDMMC4 (1<<15) 198 | #define U_CLR_CLK_ENB_SDMMC3 (1<<5) 199 | 200 | static int _clock_sdmmc_is_reset(u32 id) 201 | { 202 | switch (id) 203 | { 204 | case SDMMC_1: 205 | return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC1_RST; 206 | case SDMMC_2: 207 | return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC2_RST; 208 | case SDMMC_3: 209 | return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & U_SWR_SDMMC3_RST; 210 | case SDMMC_4: 211 | return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC4_RST; 212 | } 213 | return 0; 214 | } 215 | 216 | static void _clock_sdmmc_set_reset(u32 id) 217 | { 218 | switch (id) 219 | { 220 | case SDMMC_1: 221 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC1_RST; 222 | case SDMMC_2: 223 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC2_RST; 224 | case SDMMC_3: 225 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = U_SET_SDMMC3_RST; 226 | case SDMMC_4: 227 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC4_RST; 228 | } 229 | } 230 | 231 | static void _clock_sdmmc_clear_reset(u32 id) 232 | { 233 | switch (id) 234 | { 235 | case SDMMC_1: 236 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC1_RST; 237 | case SDMMC_2: 238 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC2_RST; 239 | case SDMMC_3: 240 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = U_CLR_SDMMC3_RST; 241 | case SDMMC_4: 242 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC4_RST; 243 | } 244 | } 245 | 246 | static int _clock_sdmmc_is_enabled(u32 id) 247 | { 248 | switch (id) 249 | { 250 | case SDMMC_1: 251 | return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC1; 252 | case SDMMC_2: 253 | return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC2; 254 | case SDMMC_3: 255 | return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & U_CLK_ENB_SDMMC3; 256 | case SDMMC_4: 257 | return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC4; 258 | } 259 | return 0; 260 | } 261 | 262 | static int _clock_sdmmc_set_enable(u32 id) 263 | { 264 | switch (id) 265 | { 266 | case SDMMC_1: 267 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC1; 268 | case SDMMC_2: 269 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC2; 270 | case SDMMC_3: 271 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = U_SET_CLK_ENB_SDMMC3; 272 | case SDMMC_4: 273 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC4; 274 | } 275 | } 276 | 277 | static int _clock_sdmmc_clear_enable(u32 id) 278 | { 279 | switch (id) 280 | { 281 | case SDMMC_1: 282 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC1; 283 | case SDMMC_2: 284 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC2; 285 | case SDMMC_3: 286 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = U_CLR_CLK_ENB_SDMMC3; 287 | case SDMMC_4: 288 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC4; 289 | } 290 | } 291 | 292 | static u32 _clock_sdmmc_table[8] = { 0 }; 293 | 294 | static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val) 295 | { 296 | u32 divisor = 0; 297 | u32 source = 0; 298 | 299 | switch (val) 300 | { 301 | case 25000: 302 | *pout = 24728; 303 | divisor = 31; 304 | break; 305 | case 26000: 306 | *pout = 25500; 307 | divisor = 30; 308 | break; 309 | case 40800: 310 | *pout = 40800; 311 | divisor = 18; 312 | break; 313 | case 50000: 314 | *pout = 48000; 315 | divisor = 15; 316 | break; 317 | case 52000: 318 | *pout = 51000; 319 | divisor = 14; 320 | break; 321 | case 100000: 322 | *pout = 90667; 323 | divisor = 7; 324 | break; 325 | case 200000: 326 | *pout = 163200; 327 | divisor = 3; 328 | break; 329 | case 208000: 330 | *pout = 204000; 331 | divisor = 2; 332 | break; 333 | default: 334 | return 0; 335 | } 336 | 337 | _clock_sdmmc_table[2 * id] = val; 338 | _clock_sdmmc_table[2 * id + 1] = *pout; 339 | 340 | switch (id) 341 | { 342 | case SDMMC_1: 343 | CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = source | divisor; 344 | break; 345 | case SDMMC_2: 346 | CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = source | divisor; 347 | break; 348 | case SDMMC_3: 349 | CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = source | divisor; 350 | break; 351 | case SDMMC_4: 352 | CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = source | divisor; 353 | break; 354 | } 355 | 356 | return 1; 357 | } 358 | 359 | void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val) 360 | { 361 | if (_clock_sdmmc_table[2 * id] == val) 362 | { 363 | *pout = _clock_sdmmc_table[2 * id + 1]; 364 | } 365 | else 366 | { 367 | int is_enabled = _clock_sdmmc_is_enabled(id); 368 | if (is_enabled) 369 | _clock_sdmmc_clear_enable(id); 370 | _clock_sdmmc_config_clock_source_inner(pout, id, val); 371 | if (is_enabled) 372 | _clock_sdmmc_set_enable(id); 373 | _clock_sdmmc_is_reset(id); 374 | } 375 | } 376 | 377 | void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type) 378 | { 379 | switch (type) 380 | { 381 | case 0: 382 | *pout = 26000; 383 | *pdivisor = 66; 384 | break; 385 | case 1: 386 | *pout = 26000; 387 | *pdivisor = 1; 388 | break; 389 | case 2: 390 | *pout = 52000; 391 | *pdivisor = 1; 392 | break; 393 | case 3: 394 | case 4: 395 | case 11: 396 | *pout = 200000; 397 | *pdivisor = 1; 398 | break; 399 | case 5: 400 | *pout = 25000; 401 | *pdivisor = 64; 402 | case 6: 403 | case 8: 404 | *pout = 25000; 405 | *pdivisor = 1; 406 | break; 407 | case 7: 408 | *pout = 50000; 409 | *pdivisor = 1; 410 | case 10: 411 | *pout = 100000; 412 | *pdivisor = 1; 413 | case 13: 414 | *pout = 40800; 415 | *pdivisor = 1; 416 | break; 417 | case 14: 418 | *pout = 200000; 419 | *pdivisor = 2; 420 | break; 421 | } 422 | } 423 | 424 | int clock_sdmmc_is_not_reset_and_enabled(u32 id) 425 | { 426 | return !_clock_sdmmc_is_reset(id) && _clock_sdmmc_is_enabled(id); 427 | } 428 | 429 | void clock_sdmmc_enable(u32 id, u32 val) 430 | { 431 | u32 div = 0; 432 | 433 | if (_clock_sdmmc_is_enabled(id)) 434 | _clock_sdmmc_clear_enable(id); 435 | _clock_sdmmc_set_reset(id); 436 | _clock_sdmmc_config_clock_source_inner(&div, id, val); 437 | _clock_sdmmc_set_enable(id); 438 | _clock_sdmmc_is_reset(id); 439 | sleep((100000 + div - 1) / div); 440 | _clock_sdmmc_clear_reset(id); 441 | _clock_sdmmc_is_reset(id); 442 | } 443 | 444 | void clock_sdmmc_disable(u32 id) 445 | { 446 | _clock_sdmmc_set_reset(id); 447 | _clock_sdmmc_clear_enable(id); 448 | _clock_sdmmc_is_reset(id); 449 | } 450 | -------------------------------------------------------------------------------- /ipl/clock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _CLOCK_H_ 18 | #define _CLOCK_H_ 19 | 20 | #include "types.h" 21 | 22 | /*! Clock registers. */ 23 | #define CLK_RST_CONTROLLER_RST_DEVICES_L 0x4 24 | #define CLK_RST_CONTROLLER_RST_DEVICES_U 0xC 25 | #define CLK_RST_CONTROLLER_CLK_OUT_ENB_L 0x10 26 | #define CLK_RST_CONTROLLER_CLK_OUT_ENB_H 0x14 27 | #define CLK_RST_CONTROLLER_CLK_OUT_ENB_U 0x18 28 | #define CLK_RST_CONTROLLER_CCLK_BURST_POLICY 0x20 29 | #define CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER 0x24 30 | #define CLK_RST_CONTROLLER_SCLK_BURST_POLICY 0x28 31 | #define CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2C 32 | #define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 33 | #define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 34 | #define CLK_RST_CONTROLLER_OSC_CTRL 0x50 35 | #define CLK_RST_CONTROLLER_PLLX_BASE 0xE0 36 | #define CLK_RST_CONTROLLER_PLLX_MISC 0xE4 37 | #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 0x150 38 | #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 0x154 39 | #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 0x164 40 | #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 0x1BC 41 | #define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19C 42 | #define CLK_RST_CONTROLLER_CLK_OUT_ENB_X 0x280 43 | #define CLK_RST_CONTROLLER_CLK_ENB_X_SET 0x284 44 | #define CLK_RST_CONTROLLER_CLK_OUT_ENB_Y 0x298 45 | #define CLK_RST_CONTROLLER_CLK_ENB_Y_SET 0x29C 46 | #define CLK_RST_CONTROLLER_RST_DEV_L_SET 0x300 47 | #define CLK_RST_CONTROLLER_RST_DEV_L_CLR 0x304 48 | #define CLK_RST_CONTROLLER_RST_DEV_H_SET 0x308 49 | #define CLK_RST_CONTROLLER_RST_DEV_U_SET 0x310 50 | #define CLK_RST_CONTROLLER_RST_DEV_U_CLR 0x314 51 | #define CLK_RST_CONTROLLER_CLK_ENB_L_SET 0x320 52 | #define CLK_RST_CONTROLLER_CLK_ENB_L_CLR 0x324 53 | #define CLK_RST_CONTROLLER_CLK_ENB_H_SET 0x328 54 | #define CLK_RST_CONTROLLER_CLK_ENB_U_SET 0x330 55 | #define CLK_RST_CONTROLLER_CLK_ENB_U_CLR 0x334 56 | #define CLK_RST_CONTROLLER_RST_DEVICES_V 0x358 57 | #define CLK_RST_CONTROLLER_CLK_OUT_ENB_V 0x360 58 | #define CLK_RST_CONTROLLER_CLK_OUT_ENB_W 0x364 59 | #define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2 0x388 60 | #define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4 61 | #define CLK_RST_CONTROLLER_CLK_ENB_V_SET 0x440 62 | #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR 0x454 63 | #define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518 64 | #define CLK_RST_CONTROLLER_SPARE_REG0 0x55C 65 | #define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8 66 | #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694 67 | 68 | /*! Generic clock descriptor. */ 69 | typedef struct _clock_t 70 | { 71 | u32 reset; 72 | u32 enable; 73 | u32 source; 74 | u8 index; 75 | u8 clk_src; 76 | u8 clk_div; 77 | } clock_t; 78 | 79 | /*! Generic clock enable/disable. */ 80 | void clock_enable(const clock_t *clk); 81 | void clock_disable(const clock_t *clk); 82 | 83 | /*! Clock control for specific hardware portions. */ 84 | void clock_enable_fuse(u32 enable); 85 | void clock_enable_uart(u32 idx); 86 | void clock_enable_i2c(u32 idx); 87 | void clock_enable_se(); 88 | void clock_enable_host1x(); 89 | void clock_disable_host1x(); 90 | void clock_enable_tsec(); 91 | void clock_disable_tsec(); 92 | void clock_enable_sor_safe(); 93 | void clock_disable_sor_safe(); 94 | void clock_enable_sor0(); 95 | void clock_disable_sor0(); 96 | void clock_enable_sor1(); 97 | void clock_disable_sor1(); 98 | void clock_enable_kfuse(); 99 | void clock_disable_kfuse(); 100 | void clock_enable_cl_dvfs(); 101 | void clock_enable_coresight(); 102 | void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val); 103 | void clock_sdmmc_get_params(u32 *pout, u16 *pdivisor, u32 type); 104 | int clock_sdmmc_is_not_reset_and_enabled(u32 id); 105 | void clock_sdmmc_enable(u32 id, u32 val); 106 | void clock_sdmmc_disable(u32 id); 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /ipl/cluster.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "cluster.h" 18 | #include "i2c.h" 19 | #include "clock.h" 20 | #include "util.h" 21 | #include "pmc.h" 22 | #include "t210.h" 23 | #include "max77620.h" 24 | 25 | void _cluster_enable_power() 26 | { 27 | u8 tmp = i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_AME_GPIO); 28 | i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_AME_GPIO, tmp & 0xDF); 29 | i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_GPIO5, 0x09); 30 | 31 | //Enable cores power. 32 | i2c_send_byte(I2C_5, 0x1B, 0x2, 0x20); 33 | i2c_send_byte(I2C_5, 0x1B, 0x3, 0x8D); 34 | i2c_send_byte(I2C_5, 0x1B, 0x0, 0xB7); 35 | i2c_send_byte(I2C_5, 0x1B, 0x1, 0xB7); 36 | } 37 | 38 | int _cluster_pmc_enable_partition(u32 part, u32 toggle) 39 | { 40 | //Check if the partition has already been turned on. 41 | if (PMC(APBDEV_PMC_PWRGATE_STATUS) & part) 42 | return 1; 43 | 44 | u32 i = 5001; 45 | while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100) 46 | { 47 | sleep(1); 48 | i--; 49 | if (i < 1) 50 | return 0; 51 | } 52 | 53 | PMC(APBDEV_PMC_PWRGATE_TOGGLE) = toggle | 0x100; 54 | 55 | i = 5001; 56 | while (i > 0) 57 | { 58 | if (PMC(APBDEV_PMC_PWRGATE_STATUS) & part) 59 | break; 60 | sleep(1); 61 | i--; 62 | } 63 | 64 | return 1; 65 | } 66 | 67 | void cluster_boot_cpu0(u32 entry) 68 | { 69 | //Set ACTIVE_CLUSER to FAST. 70 | FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE; 71 | 72 | _cluster_enable_power(); 73 | 74 | if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) 75 | { 76 | CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; 77 | sleep(2); 78 | CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02; 79 | CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02; 80 | CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF | 0x40000; 81 | CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02; 82 | } 83 | while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000)) 84 | ; 85 | 86 | //Configure MSELECT source and enable clock. 87 | CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00 | 6; 88 | CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & 0xFFFFFFF7 | 8; 89 | 90 | //Configure initial CPU clock frequency and enable clock. 91 | CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; 92 | CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000; 93 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = 1; 94 | 95 | clock_enable_coresight(); 96 | 97 | //CAR2PMC_CPU_ACK_WIDTH should be set to 0. 98 | CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) = CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) & 0xFFFFF000; 99 | 100 | //Enable CPU rail. 101 | _cluster_pmc_enable_partition(1, 0); 102 | //Enable cluster 0 non-CPU. 103 | _cluster_pmc_enable_partition(0x8000, 15); 104 | //Enable CE0. 105 | _cluster_pmc_enable_partition(0x4000, 14); 106 | 107 | //Request and wait for RAM repair. 108 | FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; 109 | while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & 2)) 110 | ; 111 | 112 | EXCP_VEC(0x100) = 0; 113 | 114 | //Set reset vector. 115 | SB(SB_AA64_RESET_LOW) = entry | 1; 116 | SB(SB_AA64_RESET_HIGH) = 0; 117 | //Non-secure reset vector write disable. 118 | SB(SB_CSR) = 2; 119 | (void)SB(SB_CSR); 120 | 121 | //Clear MSELECT reset. 122 | CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= 0xFFFFFFF7; 123 | //Clear NONCPU reset. 124 | CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000; 125 | //Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset. 126 | CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x411F000F; 127 | } 128 | -------------------------------------------------------------------------------- /ipl/cluster.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _CLUSTER_H_ 18 | #define _CLUSTER_H_ 19 | 20 | #include "types.h" 21 | 22 | /*! Flow controller registers. */ 23 | #define FLOW_CTLR_RAM_REPAIR 0x40 24 | #define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98 25 | 26 | void cluster_boot_cpu0(u32 entry); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /ipl/di.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "di.h" 18 | #include "t210.h" 19 | #include "util.h" 20 | #include "i2c.h" 21 | #include "pmc.h" 22 | #include "max77620.h" 23 | 24 | #include "di.inl" 25 | 26 | static u32 _display_ver = 0; 27 | 28 | static void _display_dsi_wait(u32 timeout, u32 off, u32 mask) 29 | { 30 | u32 end = TMR(0x10) + timeout; 31 | while (TMR(0x10) < end && DSI(off) & mask) 32 | ; 33 | sleep(5); 34 | } 35 | 36 | void display_init() 37 | { 38 | //Power on. 39 | i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_LDO0_CFG, 0xD0); //Configure to 1.2V. 40 | i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_GPIO7, 0x09); 41 | 42 | //Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. 43 | CLOCK(0x30C) = 0x1010000; 44 | CLOCK(0x328) = 0x1010000; 45 | CLOCK(0x304) = 0x18000000; 46 | CLOCK(0x320) = 0x18000000; 47 | CLOCK(0x284) = 0x20000; 48 | CLOCK(0x66C) = 0xA; 49 | CLOCK(0x448) = 0x80000; 50 | CLOCK(0x620) = 0xA; 51 | 52 | //DPD idle. 53 | PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000; 54 | PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000; 55 | 56 | //Config pins. 57 | PINMUX_AUX(0x1D0) &= 0xFFFFFFEF; 58 | PINMUX_AUX(0x1D4) &= 0xFFFFFFEF; 59 | PINMUX_AUX(0x1FC) &= 0xFFFFFFEF; 60 | PINMUX_AUX(0x200) &= 0xFFFFFFEF; 61 | PINMUX_AUX(0x204) &= 0xFFFFFFEF; 62 | 63 | GPIO_3(0x00) = GPIO_3(0x00) & 0xFFFFFFFC | 0x3; 64 | GPIO_3(0x10) = GPIO_3(0x10) & 0xFFFFFFFC | 0x3; 65 | GPIO_3(0x20) = GPIO_3(0x20) & 0xFFFFFFFE | 0x1; 66 | 67 | sleep(10000u); 68 | 69 | GPIO_3(0x20) = GPIO_3(0x20) & 0xFFFFFFFD | 0x2; 70 | 71 | sleep(10000); 72 | 73 | GPIO_6(0x04) = GPIO_6(0x04) & 0xFFFFFFF8 | 0x7; 74 | GPIO_6(0x14) = GPIO_6(0x14) & 0xFFFFFFF8 | 0x7; 75 | GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFD | 0x2; 76 | 77 | //Config display interface and display. 78 | MIPI_CAL(0x60) = 0; 79 | 80 | exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4); 81 | exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94); 82 | exec_cfg((u32 *)DSI_BASE, _display_config_3, 60); 83 | 84 | sleep(10000); 85 | 86 | GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFB | 0x4; 87 | 88 | sleep(60000); 89 | 90 | DSI(_DSIREG(DSI_DSI_BTA_TIMING)) = 0x50204; 91 | DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x337; 92 | DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; 93 | _display_dsi_wait(250000, _DSIREG(DSI_DSI_TRIGGER), 3); 94 | 95 | DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x406; 96 | DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; 97 | _display_dsi_wait(250000, _DSIREG(DSI_DSI_TRIGGER), 3); 98 | 99 | DSI(_DSIREG(DSI_HOST_DSI_CONTROL)) = 0x200B; 100 | _display_dsi_wait(150000, _DSIREG(DSI_HOST_DSI_CONTROL), 8); 101 | 102 | sleep(5000); 103 | 104 | _display_ver = DSI(_DSIREG(DSI_DSI_RD_DATA)); 105 | if (_display_ver == 0x10) 106 | exec_cfg((u32 *)DSI_BASE, _display_config_4, 43); 107 | 108 | DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x1105; 109 | DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; 110 | 111 | sleep(180000); 112 | 113 | DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x2905; 114 | DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; 115 | 116 | sleep(20000); 117 | 118 | exec_cfg((u32 *)DSI_BASE, _display_config_5, 21); 119 | exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3); 120 | DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; 121 | exec_cfg((u32 *)DSI_BASE, _display_config_7, 10); 122 | 123 | sleep(10000); 124 | 125 | exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6); 126 | exec_cfg((u32 *)DSI_BASE, _display_config_9, 4); 127 | exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16); 128 | 129 | sleep(10000); 130 | 131 | exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113); 132 | } 133 | 134 | void display_end() 135 | { 136 | GPIO_6(0x24) &= 0xFFFFFFFE; 137 | DSI(_DSIREG(DSI_DSI_VID_MODE_CONTROL)) = 1; 138 | DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x2805; 139 | 140 | u32 end = HOST1X(0x30A4) + 5; 141 | while (HOST1X(0x30A4) < end) 142 | ; 143 | 144 | DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = 5; 145 | DSI(_DSIREG(DSI_DSI_VID_MODE_CONTROL)) = 0; 146 | 147 | exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17); 148 | exec_cfg((u32 *)DSI_BASE, _display_config_13, 16); 149 | 150 | sleep(10000); 151 | 152 | if (_display_ver == 0x10) 153 | exec_cfg((u32 *)DSI_BASE, _display_config_14, 22); 154 | 155 | DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x1005; 156 | DSI(_DSIREG(DSI_DSI_TRIGGER)) = 2; 157 | 158 | sleep(50000); 159 | 160 | GPIO_6(0x24) &= 0xFFFFFFFB; 161 | 162 | sleep(10000); 163 | 164 | GPIO_3(0x20) &= 0xFFFFFFFD; 165 | 166 | sleep(10000); 167 | 168 | GPIO_3(0x20) = (GPIO_3(0x20) >> 1) << 1; 169 | 170 | sleep(10000); 171 | 172 | //Disable clocks. 173 | CLOCK(0x308) = 0x1010000; 174 | CLOCK(0x32C) = 0x1010000; 175 | CLOCK(0x300) = 0x18000000; 176 | CLOCK(0x324) = 0x18000000; 177 | 178 | DSI(_DSIREG(DSI_PAD_CONTROL)) = 0x10F010F; 179 | DSI(_DSIREG(DSI_DSI_POWER_CONTROL)) = 0; 180 | 181 | GPIO_6(0x04) &= 0xFFFFFFFE; 182 | 183 | PINMUX_AUX(0x1FC) = PINMUX_AUX(0x1FC) & 0xFFFFFFEF | 0x10; 184 | PINMUX_AUX(0x1FC) = (PINMUX_AUX(0x1FC) >> 2) << 2 | 1; 185 | } 186 | 187 | void display_color_screen(u32 color) 188 | { 189 | exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8); 190 | 191 | //Configure display to show single color. 192 | DISPLAY_A(_DIREG(DC_WIN_AD_WIN_OPTIONS)) = 0; 193 | DISPLAY_A(_DIREG(DC_WIN_BD_WIN_OPTIONS)) = 0; 194 | DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0; 195 | DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color; 196 | DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE | 1; 197 | 198 | sleep(35000); 199 | 200 | GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFE | 1; 201 | } 202 | 203 | u32 *display_init_framebuffer(u32 *fb) 204 | { 205 | //This configures the framebuffer @ 0xC0000000 with a resolution of 1280x720 (line stride 768). 206 | exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32); 207 | 208 | sleep(35000); 209 | 210 | GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFE | 1; 211 | 212 | return (u32 *)0xC0000000; 213 | } 214 | -------------------------------------------------------------------------------- /ipl/di.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _DI_H_ 18 | #define _DI_H_ 19 | 20 | #include "types.h" 21 | 22 | /*! Display registers. */ 23 | #define _DIREG(reg) ((reg) * 4) 24 | #define DC_CMD_DISPLAY_COMMAND 0x32 25 | #define DC_CMD_STATE_ACCESS 0x40 26 | #define DC_CMD_STATE_CONTROL 0x41 27 | #define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 28 | #define DC_DISP_DISP_WIN_OPTIONS 0x402 29 | #define DC_DISP_DISP_CLOCK_CONTROL 0x42E 30 | #define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 31 | #define DC_WIN_AD_WIN_OPTIONS 0xB80 32 | #define DC_WIN_BD_WIN_OPTIONS 0xD80 33 | #define DC_WIN_CD_WIN_OPTIONS 0xF80 34 | 35 | //The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). 36 | #define DC_X_WIN_XD_WIN_OPTIONS 0x700 37 | #define DC_X_WIN_XD_COLOR_DEPTH 0x703 38 | #define DC_X_WIN_XD_POSITION 0x704 39 | #define DC_X_WIN_XD_SIZE 0x705 40 | #define DC_X_WIN_XD_PRESCALED_SIZE 0x706 41 | #define DC_X_WIN_XD_H_INITIAL_DDA 0x707 42 | #define DC_X_WIN_XD_V_INITIAL_DDA 0x708 43 | #define DC_X_WIN_XD_DDA_INCREMENT 0x709 44 | #define DC_X_WIN_XD_LINE_STRIDE 0x70A 45 | 46 | //The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). 47 | #define DC_X_WINBUF_XD_START_ADDR 0x800 48 | #define DC_X_WINBUF_XD_ADDR_H_OFFSET 0x806 49 | #define DC_X_WINBUF_XD_ADDR_V_OFFSET 0x808 50 | #define DC_X_WINBUF_XD_SURFACE_KIND 0x80B 51 | 52 | /*! Display serial interface registers. */ 53 | #define _DSIREG(reg) ((reg) * 4) 54 | #define DSI_DSI_RD_DATA 0x9 55 | #define DSI_DSI_WR_DATA 0xA 56 | #define DSI_DSI_POWER_CONTROL 0xB 57 | #define DSI_HOST_DSI_CONTROL 0xF 58 | #define DSI_DSI_TRIGGER 0x13 59 | #define DSI_DSI_BTA_TIMING 0x3F 60 | #define DSI_PAD_CONTROL 0x4B 61 | #define DSI_DSI_VID_MODE_CONTROL 0x4E 62 | 63 | void display_init(); 64 | void display_end(); 65 | 66 | /*! Show one single color on the display. */ 67 | void display_color_screen(u32 color); 68 | 69 | /*! Init display in full 1280x720 resolution (32bpp, line stride 768, framebuffer size = 1280*768*4 bytes). */ 70 | u32 *display_init_framebuffer(); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ipl/diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ 3 | /*-----------------------------------------------------------------------*/ 4 | /* If a working storage control module is available, it should be */ 5 | /* attached to the FatFs via a glue function rather than modifying it. */ 6 | /* This is an example of glue functions to attach various exsisting */ 7 | /* storage control modules to the FatFs module with a defined API. */ 8 | /*-----------------------------------------------------------------------*/ 9 | 10 | #include 11 | #include "diskio.h" /* FatFs lower layer API */ 12 | #include "sdmmc.h" 13 | 14 | extern sdmmc_storage_t sd_storage; 15 | 16 | DSTATUS disk_status ( 17 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 18 | ) 19 | { 20 | return 0; 21 | } 22 | 23 | DSTATUS disk_initialize ( 24 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 25 | ) 26 | { 27 | return 0; 28 | } 29 | 30 | DRESULT disk_read ( 31 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 32 | BYTE *buff, /* Data buffer to store read data */ 33 | DWORD sector, /* Start sector in LBA */ 34 | UINT count /* Number of sectors to read */ 35 | ) 36 | { 37 | if ((u32)buff >= 0x90000000) 38 | return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR; 39 | u8 *buf = (u8 *)0x98000000; //TODO: define this somewhere. 40 | if (sdmmc_storage_read(&sd_storage, sector, count, buf)) 41 | { 42 | memcpy(buff, buf, 512 * count); 43 | return RES_OK; 44 | } 45 | return RES_ERROR; 46 | } 47 | 48 | DRESULT disk_write ( 49 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 50 | const BYTE *buff, /* Data to be written */ 51 | DWORD sector, /* Start sector in LBA */ 52 | UINT count /* Number of sectors to write */ 53 | ) 54 | { 55 | if ((u32)buff >= 0x90000000) 56 | return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR; 57 | u8 *buf = (u8 *)0x98000000; //TODO: define this somewhere. 58 | memcpy(buf, buff, 512 * count); 59 | if (sdmmc_storage_write(&sd_storage, sector, count, buf)) 60 | return RES_OK; 61 | return RES_ERROR; 62 | } 63 | 64 | DRESULT disk_ioctl ( 65 | BYTE pdrv, /* Physical drive nmuber (0..) */ 66 | BYTE cmd, /* Control code */ 67 | void *buff /* Buffer to send/receive control data */ 68 | ) 69 | { 70 | return RES_OK; 71 | } 72 | -------------------------------------------------------------------------------- /ipl/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file (C)ChaN, 2014 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #include "integer.h" 13 | 14 | 15 | /* Status of Disk Functions */ 16 | typedef BYTE DSTATUS; 17 | 18 | /* Results of Disk Functions */ 19 | typedef enum { 20 | RES_OK = 0, /* 0: Successful */ 21 | RES_ERROR, /* 1: R/W Error */ 22 | RES_WRPRT, /* 2: Write Protected */ 23 | RES_NOTRDY, /* 3: Not Ready */ 24 | RES_PARERR /* 4: Invalid Parameter */ 25 | } DRESULT; 26 | 27 | 28 | /*---------------------------------------*/ 29 | /* Prototypes for disk control functions */ 30 | 31 | 32 | DSTATUS disk_initialize (BYTE pdrv); 33 | DSTATUS disk_status (BYTE pdrv); 34 | DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 35 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); 36 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 37 | 38 | 39 | /* Disk Status Bits (DSTATUS) */ 40 | 41 | #define STA_NOINIT 0x01 /* Drive not initialized */ 42 | #define STA_NODISK 0x02 /* No medium in the drive */ 43 | #define STA_PROTECT 0x04 /* Write protected */ 44 | 45 | 46 | /* Command code for disk_ioctrl fucntion */ 47 | 48 | /* Generic command (Used by FatFs) */ 49 | #define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ 50 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ 51 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ 52 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ 53 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ 54 | 55 | /* Generic command (Not used by FatFs) */ 56 | #define CTRL_POWER 5 /* Get/Set power status */ 57 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 58 | #define CTRL_EJECT 7 /* Eject media */ 59 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 60 | 61 | /* MMC/SDC specific ioctl command */ 62 | #define MMC_GET_TYPE 10 /* Get card type */ 63 | #define MMC_GET_CSD 11 /* Get CSD */ 64 | #define MMC_GET_CID 12 /* Get CID */ 65 | #define MMC_GET_OCR 13 /* Get OCR */ 66 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 67 | #define ISDIO_READ 55 /* Read data form SD iSDIO register */ 68 | #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ 69 | #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ 70 | 71 | /* ATA/CF specific ioctl command */ 72 | #define ATA_GET_REV 20 /* Get F/W revision */ 73 | #define ATA_GET_MODEL 21 /* Get model name */ 74 | #define ATA_GET_SN 22 /* Get serial number */ 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /ipl/ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - Configuration file 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #define FFCONF_DEF 89352 /* Revision ID */ 6 | 7 | /*---------------------------------------------------------------------------/ 8 | / Function Configurations 9 | /---------------------------------------------------------------------------*/ 10 | 11 | #define FF_FS_READONLY 0 12 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 13 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 14 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 15 | / and optional writing functions as well. */ 16 | 17 | 18 | #define FF_FS_MINIMIZE 3 19 | /* This option defines minimization level to remove some basic API functions. 20 | / 21 | / 0: Basic functions are fully enabled. 22 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() 23 | / are removed. 24 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 25 | / 3: f_lseek() function is removed in addition to 2. */ 26 | 27 | 28 | #define FF_USE_STRFUNC 2 29 | /* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). 30 | / 31 | / 0: Disable string functions. 32 | / 1: Enable without LF-CRLF conversion. 33 | / 2: Enable with LF-CRLF conversion. */ 34 | 35 | 36 | #define FF_USE_FIND 0 37 | /* This option switches filtered directory read functions, f_findfirst() and 38 | / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ 39 | 40 | 41 | #define FF_USE_MKFS 0 42 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 43 | 44 | 45 | #define FF_USE_FASTSEEK 0 46 | /* This option switches fast seek function. (0:Disable or 1:Enable) */ 47 | 48 | 49 | #define FF_USE_EXPAND 0 50 | /* This option switches f_expand function. (0:Disable or 1:Enable) */ 51 | 52 | 53 | #define FF_USE_CHMOD 0 54 | /* This option switches attribute manipulation functions, f_chmod() and f_utime(). 55 | / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ 56 | 57 | 58 | #define FF_USE_LABEL 0 59 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 60 | / (0:Disable or 1:Enable) */ 61 | 62 | 63 | #define FF_USE_FORWARD 0 64 | /* This option switches f_forward() function. (0:Disable or 1:Enable) */ 65 | 66 | 67 | /*---------------------------------------------------------------------------/ 68 | / Locale and Namespace Configurations 69 | /---------------------------------------------------------------------------*/ 70 | 71 | #define FF_CODE_PAGE 850 72 | /* This option specifies the OEM code page to be used on the target system. 73 | / Incorrect code page setting can cause a file open failure. 74 | / 75 | / 437 - U.S. 76 | / 720 - Arabic 77 | / 737 - Greek 78 | / 771 - KBL 79 | / 775 - Baltic 80 | / 850 - Latin 1 81 | / 852 - Latin 2 82 | / 855 - Cyrillic 83 | / 857 - Turkish 84 | / 860 - Portuguese 85 | / 861 - Icelandic 86 | / 862 - Hebrew 87 | / 863 - Canadian French 88 | / 864 - Arabic 89 | / 865 - Nordic 90 | / 866 - Russian 91 | / 869 - Greek 2 92 | / 932 - Japanese (DBCS) 93 | / 936 - Simplified Chinese (DBCS) 94 | / 949 - Korean (DBCS) 95 | / 950 - Traditional Chinese (DBCS) 96 | / 0 - Include all code pages above and configured by f_setcp() 97 | */ 98 | 99 | 100 | #define FF_USE_LFN 1 101 | #define FF_MAX_LFN 255 102 | /* The FF_USE_LFN switches the support for LFN (long file name). 103 | / 104 | / 0: Disable LFN. FF_MAX_LFN has no effect. 105 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 106 | / 2: Enable LFN with dynamic working buffer on the STACK. 107 | / 3: Enable LFN with dynamic working buffer on the HEAP. 108 | / 109 | / To enable the LFN, ffunicode.c needs to be added to the project. The LFN function 110 | / requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and 111 | / additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. 112 | / The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can 113 | / be in range of 12 to 255. It is recommended to be set 255 to fully support LFN 114 | / specification. 115 | / When use stack for the working buffer, take care on stack overflow. When use heap 116 | / memory for the working buffer, memory management functions, ff_memalloc() and 117 | / ff_memfree() in ffsystem.c, need to be added to the project. */ 118 | 119 | 120 | #define FF_LFN_UNICODE 0 121 | /* This option switches the character encoding on the API when LFN is enabled. 122 | / 123 | / 0: ANSI/OEM in current CP (TCHAR = char) 124 | / 1: Unicode in UTF-16 (TCHAR = WCHAR) 125 | / 2: Unicode in UTF-8 (TCHAR = char) 126 | / 127 | / Also behavior of string I/O functions will be affected by this option. 128 | / When LFN is not enabled, this option has no effect. */ 129 | 130 | 131 | #define FF_LFN_BUF 255 132 | #define FF_SFN_BUF 12 133 | /* This set of options defines size of file name members in the FILINFO structure 134 | / which is used to read out directory items. These values should be suffcient for 135 | / the file names to read. The maximum possible length of the read file name depends 136 | / on character encoding. When LFN is not enabled, these options have no effect. */ 137 | 138 | 139 | #define FF_STRF_ENCODE 0 140 | /* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(), 141 | / f_putc(), f_puts and f_printf() convert the character encoding in it. 142 | / This option selects assumption of character encoding ON THE FILE to be 143 | / read/written via those functions. 144 | / 145 | / 0: ANSI/OEM in current CP 146 | / 1: Unicode in UTF-16LE 147 | / 2: Unicode in UTF-16BE 148 | / 3: Unicode in UTF-8 149 | */ 150 | 151 | 152 | #define FF_FS_RPATH 0 153 | /* This option configures support for relative path. 154 | / 155 | / 0: Disable relative path and remove related functions. 156 | / 1: Enable relative path. f_chdir() and f_chdrive() are available. 157 | / 2: f_getcwd() function is available in addition to 1. 158 | */ 159 | 160 | 161 | /*---------------------------------------------------------------------------/ 162 | / Drive/Volume Configurations 163 | /---------------------------------------------------------------------------*/ 164 | 165 | #define FF_VOLUMES 1 166 | /* Number of volumes (logical drives) to be used. (1-10) */ 167 | 168 | 169 | #define FF_STR_VOLUME_ID 0 170 | #define FF_VOLUME_STRS "sd" 171 | /* FF_STR_VOLUME_ID switches string support for volume ID. 172 | / When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive 173 | / number in the path name. FF_VOLUME_STRS defines the drive ID strings for each 174 | / logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for 175 | / the drive ID strings are: A-Z and 0-9. */ 176 | 177 | 178 | #define FF_MULTI_PARTITION 0 179 | /* This option switches support for multiple volumes on the physical drive. 180 | / By default (0), each logical drive number is bound to the same physical drive 181 | / number and only an FAT volume found on the physical drive will be mounted. 182 | / When this function is enabled (1), each logical drive number can be bound to 183 | / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() 184 | / funciton will be available. */ 185 | 186 | 187 | #define FF_MIN_SS 512 188 | #define FF_MAX_SS 512 189 | /* This set of options configures the range of sector size to be supported. (512, 190 | / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and 191 | / harddisk. But a larger value may be required for on-board flash memory and some 192 | / type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured 193 | / for variable sector size mode and disk_ioctl() function needs to implement 194 | / GET_SECTOR_SIZE command. */ 195 | 196 | 197 | #define FF_USE_TRIM 0 198 | /* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) 199 | / To enable Trim function, also CTRL_TRIM command should be implemented to the 200 | / disk_ioctl() function. */ 201 | 202 | 203 | #define FF_FS_NOFSINFO 0 204 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 205 | / option, and f_getfree() function at first time after volume mount will force 206 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 207 | / 208 | / bit0=0: Use free cluster count in the FSINFO if available. 209 | / bit0=1: Do not trust free cluster count in the FSINFO. 210 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 211 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 212 | */ 213 | 214 | 215 | 216 | /*---------------------------------------------------------------------------/ 217 | / System Configurations 218 | /---------------------------------------------------------------------------*/ 219 | 220 | #define FF_FS_TINY 0 221 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 222 | / At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. 223 | / Instead of private sector buffer eliminated from the file object, common sector 224 | / buffer in the filesystem object (FATFS) is used for the file data transfer. */ 225 | 226 | 227 | #define FF_FS_EXFAT 1 228 | /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) 229 | / When enable exFAT, also LFN needs to be enabled. 230 | / Note that enabling exFAT discards ANSI C (C89) compatibility. */ 231 | 232 | 233 | #define FF_FS_NORTC 1 234 | #define FF_NORTC_MON 1 235 | #define FF_NORTC_MDAY 1 236 | #define FF_NORTC_YEAR 2018 237 | /* The option FF_FS_NORTC switches timestamp functiton. If the system does not have 238 | / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable 239 | / the timestamp function. All objects modified by FatFs will have a fixed timestamp 240 | / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. 241 | / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be 242 | / added to the project to read current time form real-time clock. FF_NORTC_MON, 243 | / FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. 244 | / These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ 245 | 246 | 247 | #define FF_FS_LOCK 0 248 | /* The option FF_FS_LOCK switches file lock function to control duplicated file open 249 | / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY 250 | / is 1. 251 | / 252 | / 0: Disable file lock function. To avoid volume corruption, application program 253 | / should avoid illegal open, remove and rename to the open objects. 254 | / >0: Enable file lock function. The value defines how many files/sub-directories 255 | / can be opened simultaneously under file lock control. Note that the file 256 | / lock control is independent of re-entrancy. */ 257 | 258 | 259 | #define FF_FS_REENTRANT 0 260 | #define FF_FS_TIMEOUT 1000 261 | #define FF_SYNC_t HANDLE 262 | /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs 263 | / module itself. Note that regardless of this option, file access to different 264 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 265 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 266 | / to the same volume is under control of this function. 267 | / 268 | / 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. 269 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 270 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 271 | / function, must be added to the project. Samples are available in 272 | / option/syscall.c. 273 | / 274 | / The FF_FS_TIMEOUT defines timeout period in unit of time tick. 275 | / The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, 276 | / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be 277 | / included somewhere in the scope of ff.h. */ 278 | 279 | /* #include // O/S definitions */ 280 | 281 | 282 | 283 | /*--- End of configuration options ---*/ 284 | -------------------------------------------------------------------------------- /ipl/fuse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "fuse.h" 18 | #include "t210.h" 19 | 20 | void fuse_disable_program() 21 | { 22 | FUSE(FUSE_DISABLEREGPROGRAM) = 1; 23 | } 24 | 25 | u32 fuse_read_odm(u32 idx) 26 | { 27 | return FUSE(FUSE_RESERVED_ODMX(idx)); 28 | } 29 | -------------------------------------------------------------------------------- /ipl/fuse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _FUSE_H_ 18 | #define _FUSE_H_ 19 | 20 | #include "types.h" 21 | 22 | /*! Fuse registers. */ 23 | #define FUSE_CTRL 0x0 24 | #define FUSE_ADDR 0x4 25 | #define FUSE_RDATA 0x8 26 | #define FUSE_WDATA 0xC 27 | #define FUSE_TIME_RD1 0x10 28 | #define FUSE_TIME_RD2 0x14 29 | #define FUSE_TIME_PGM1 0x18 30 | #define FUSE_TIME_PGM2 0x1C 31 | #define FUSE_PRIV2INTFC 0x20 32 | #define FUSE_FUSEBYPASS 0x24 33 | #define FUSE_PRIVATEKEYDISABLE 0x28 34 | #define FUSE_DISABLEREGPROGRAM 0x2C 35 | #define FUSE_WRITE_ACCESS_SW 0x30 36 | #define FUSE_PWR_GOOD_SW 0x34 37 | 38 | /*! Fuse cache registers. */ 39 | #define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) 40 | 41 | void fuse_disable_program(); 42 | u32 fuse_read_odm(u32 idx); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /ipl/gfx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | #include "gfx.h" 19 | 20 | static const u8 _gfx_font[] = { 21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, 22 | 0x00, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, 23 | 0x00, 0x18, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x18, 0x10, 0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, 24 | 0x00, 0x3C, 0x66, 0x3C, 0x1C, 0xE6, 0x66, 0xFC, 0x00, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 25 | 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x18, 0x0C, 0x00, 26 | 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 27 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 28 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 29 | 0x00, 0x3C, 0x66, 0x76, 0x6E, 0x66, 0x3C, 0x00, 0x00, 0x18, 0x1C, 0x18, 0x18, 0x18, 0x7E, 0x00, 30 | 0x00, 0x3C, 0x62, 0x30, 0x0C, 0x06, 0x7E, 0x00, 0x00, 0x3C, 0x62, 0x38, 0x60, 0x66, 0x3C, 0x00, 31 | 0x00, 0x6C, 0x6C, 0x66, 0xFE, 0x60, 0x60, 0x00, 0x00, 0x7E, 0x06, 0x7E, 0x60, 0x66, 0x3C, 0x00, 32 | 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x7E, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, 33 | 0x00, 0x3C, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x3C, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x00, 34 | 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x0C, 0x00, 35 | 0x00, 0x70, 0x1C, 0x06, 0x06, 0x1C, 0x70, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, 36 | 0x00, 0x0E, 0x38, 0x60, 0x60, 0x38, 0x0E, 0x00, 0x00, 0x3C, 0x66, 0x30, 0x18, 0x00, 0x18, 0x00, 37 | 0x00, 0x3C, 0x66, 0x76, 0x76, 0x06, 0x46, 0x3C, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, 38 | 0x00, 0x3E, 0x66, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x3C, 0x66, 0x06, 0x06, 0x66, 0x3C, 0x00, 39 | 0x00, 0x1E, 0x36, 0x66, 0x66, 0x36, 0x1E, 0x00, 0x00, 0x7E, 0x06, 0x1E, 0x06, 0x06, 0x7E, 0x00, 40 | 0x00, 0x3E, 0x06, 0x1E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x3C, 0x66, 0x06, 0x76, 0x66, 0x3C, 0x00, 41 | 0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 42 | 0x00, 0x78, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x00, 43 | 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x00, 0x00, 0x46, 0x6E, 0x7E, 0x56, 0x46, 0x46, 0x00, 44 | 0x00, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 45 | 0x00, 0x3E, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x70, 0x00, 46 | 0x00, 0x3E, 0x66, 0x3E, 0x1E, 0x36, 0x66, 0x00, 0x00, 0x3C, 0x66, 0x0C, 0x30, 0x66, 0x3C, 0x00, 47 | 0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 48 | 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x46, 0x46, 0x56, 0x7E, 0x6E, 0x46, 0x00, 49 | 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, 50 | 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x06, 0x7E, 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 51 | 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 52 | 0x00, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 53 | 0x00, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x7C, 0x00, 54 | 0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00, 0x3C, 0x06, 0x06, 0x06, 0x3C, 0x00, 55 | 0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00, 56 | 0x00, 0x38, 0x0C, 0x3E, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x7C, 0x40, 0x3C, 0x00, 57 | 0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x1C, 0x18, 0x18, 0x3C, 0x00, 58 | 0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x1E, 0x00, 0x00, 0x06, 0x06, 0x36, 0x1E, 0x36, 0x66, 0x00, 59 | 0x00, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x66, 0xFE, 0xFE, 0xD6, 0xC6, 0x00, 60 | 0x00, 0x00, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, 61 | 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x00, 62 | 0x00, 0x00, 0x3E, 0x66, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x00, 63 | 0x00, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, 64 | 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0xC6, 0xD6, 0xFE, 0x7C, 0x6C, 0x00, 65 | 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x7C, 0x60, 0x3C, 0x00, 66 | 0x00, 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x7E, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 67 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0C, 0x08, 0x08, 0x10, 0x08, 0x08, 68 | }; 69 | 70 | void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride) 71 | { 72 | ctxt->fb = fb; 73 | ctxt->width = width; 74 | ctxt->height = height; 75 | ctxt->stride = stride; 76 | } 77 | 78 | void gfx_clear(gfx_ctxt_t *ctxt, u32 color) 79 | { 80 | for (u32 i = 0; i < ctxt->height * ctxt->stride; i++) 81 | ctxt->fb[i] = color; 82 | } 83 | 84 | void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt) 85 | { 86 | con->gfx_ctxt = ctxt; 87 | con->x = 0; 88 | con->y = 0; 89 | con->fgcol = 0xFFFFFFFF; 90 | con->fillbg = 0; 91 | con->bgcol = 0xFF000000; 92 | } 93 | 94 | void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol) 95 | { 96 | con->fgcol = fgcol; 97 | con->fillbg = fillbg; 98 | con->bgcol = bgcol; 99 | } 100 | 101 | void gfx_con_getpos(gfx_con_t *con, u32 *x, u32 *y) 102 | { 103 | *x = con->x; 104 | *y = con->y; 105 | } 106 | 107 | void gfx_con_setpos(gfx_con_t *con, u32 x, u32 y) 108 | { 109 | con->x = x; 110 | con->y = y; 111 | } 112 | 113 | void gfx_putc(gfx_con_t *con, char c) 114 | { 115 | if (c >= 32 && c < 128) 116 | { 117 | u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)]; 118 | u32 *fb = con->gfx_ctxt->fb + con->x + con->y * con->gfx_ctxt->stride; 119 | for (u32 i = 0; i < 8; i++) 120 | { 121 | u8 v = *cbuf++; 122 | for (u32 j = 0; j < 8; j++) 123 | { 124 | if (v & 1) 125 | *fb = con->fgcol; 126 | else if (con->fillbg) 127 | *fb = con->bgcol; 128 | v >>= 1; 129 | fb++; 130 | } 131 | fb += con->gfx_ctxt->stride - 8; 132 | } 133 | con->x += 8; 134 | } 135 | else if (c == '\n') 136 | { 137 | con->x = 0; 138 | con->y += 8; 139 | if (con->y > con->gfx_ctxt->height - 8) 140 | con->y = 0; 141 | } 142 | } 143 | 144 | void gfx_puts(gfx_con_t *con, const char *s) 145 | { 146 | if (!s) 147 | return; 148 | 149 | for (; *s; s++) 150 | gfx_putc(con, *s); 151 | } 152 | 153 | static void _gfx_putn(gfx_con_t *con, u32 v, int base, char fill, int fcnt) 154 | { 155 | char buf[65]; 156 | static const char digits[] = "0123456789ABCDEFghijklmnopqrstuvwxyz"; 157 | char *p; 158 | int c = fcnt; 159 | 160 | if (base > 36) 161 | return; 162 | 163 | p = buf + 64; 164 | *p = 0; 165 | do 166 | { 167 | c--; 168 | *--p = digits[v % base]; 169 | v /= base; 170 | } while (v); 171 | 172 | if (fill != 0) 173 | { 174 | while (c > 0) 175 | { 176 | *--p = fill; 177 | c--; 178 | } 179 | } 180 | 181 | gfx_puts(con, p); 182 | } 183 | 184 | void gfx_printf(gfx_con_t *con, const char *fmt, ...) 185 | { 186 | va_list ap; 187 | int fill, fcnt; 188 | 189 | va_start(ap, fmt); 190 | while(*fmt) 191 | { 192 | if(*fmt == '%') 193 | { 194 | fmt++; 195 | fill = 0; 196 | fcnt = 0; 197 | if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') 198 | { 199 | fcnt = *fmt; 200 | fmt++; 201 | if (*fmt >= '0' && *fmt <= '9') 202 | { 203 | fill = fcnt; 204 | fcnt = *fmt - '0'; 205 | fmt++; 206 | } 207 | else 208 | { 209 | fill = ' '; 210 | fcnt -= '0'; 211 | } 212 | } 213 | switch(*fmt) 214 | { 215 | case 'c': 216 | gfx_putc(con, va_arg(ap, u32)); 217 | break; 218 | case 's': 219 | gfx_puts(con, va_arg(ap, char *)); 220 | break; 221 | case 'd': 222 | _gfx_putn(con, va_arg(ap, u32), 10, fill, fcnt); 223 | break; 224 | case 'x': 225 | case 'X': 226 | _gfx_putn(con, va_arg(ap, u32), 16, fill, fcnt); 227 | break; 228 | case 'k': 229 | con->fgcol = va_arg(ap, u32); 230 | break; 231 | case 'K': 232 | con->bgcol = va_arg(ap, u32); 233 | con->fillbg = fcnt; 234 | break; 235 | case '%': 236 | gfx_putc(con, '%'); 237 | break; 238 | case '\0': 239 | goto out; 240 | default: 241 | gfx_putc(con, '%'); 242 | gfx_putc(con, *fmt); 243 | break; 244 | } 245 | } 246 | else 247 | gfx_putc(con, *fmt); 248 | fmt++; 249 | } 250 | 251 | out: 252 | va_end(ap); 253 | } 254 | 255 | void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len) 256 | { 257 | for(u32 i = 0; i < len; i++) 258 | { 259 | if(i % 0x10 == 0) 260 | { 261 | if(i != 0) 262 | { 263 | gfx_puts(con, "| "); 264 | for(u32 j = 0; j < 0x10; j++) 265 | { 266 | u8 c = buf[i - 0x10 + j]; 267 | if(c >= 32 && c < 128) 268 | gfx_putc(con, c); 269 | else 270 | gfx_putc(con, '.'); 271 | } 272 | gfx_putc(con, '\n'); 273 | } 274 | gfx_printf(con, "%08x: ", base + i); 275 | } 276 | gfx_printf(con, "%02x ", buf[i]); 277 | } 278 | gfx_putc(con, '\n'); 279 | } 280 | 281 | static int abs(int x) 282 | { 283 | if (x < 0) 284 | return -x; 285 | return x; 286 | } 287 | 288 | void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color) 289 | { 290 | ctxt->fb[x + y * ctxt->stride] = color; 291 | } 292 | 293 | void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color) 294 | { 295 | int dx = abs(x1-x0), sx = x0 < x1 ? 1 : -1; 296 | int dy = abs(y1-y0), sy = y0 < y1 ? 1 : -1; 297 | int err = (dx > dy ? dx : -dy) / 2, e2; 298 | 299 | while (1) 300 | { 301 | gfx_set_pixel(ctxt, x0, y0, color); 302 | if (x0 == x1 && y0 == y1) 303 | break; 304 | e2 = err; 305 | if (e2 >-dx) { err -= dy; x0 += sx; } 306 | if (e2 < dy) { err += dx; y0 += sy; } 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /ipl/gfx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _GFX_H_ 18 | #define _GFX_H_ 19 | 20 | #include "types.h" 21 | 22 | typedef struct _gfx_ctxt_t 23 | { 24 | u32 *fb; 25 | u32 width; 26 | u32 height; 27 | u32 stride; 28 | } gfx_ctxt_t; 29 | 30 | typedef struct _gfx_con_t 31 | { 32 | gfx_ctxt_t *gfx_ctxt; 33 | u32 x; 34 | u32 y; 35 | u32 fgcol; 36 | int fillbg; 37 | u32 bgcol; 38 | } gfx_con_t; 39 | 40 | void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride); 41 | void gfx_clear(gfx_ctxt_t *ctxt, u32 color); 42 | void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt); 43 | void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol); 44 | void gfx_con_getpos(gfx_con_t *con, u32 *x, u32 *y); 45 | void gfx_con_setpos(gfx_con_t *con, u32 x, u32 y); 46 | void gfx_putc(gfx_con_t *con, char c); 47 | void gfx_puts(gfx_con_t *con, const char *s); 48 | void gfx_printf(gfx_con_t *con, const char *fmt, ...); 49 | void gfx_hexdump(gfx_con_t *con, u32 base, const u8 *buf, u32 len); 50 | 51 | void gfx_set_pixel(gfx_ctxt_t *ctxt, u32 x, u32 y, u32 color); 52 | void gfx_line(gfx_ctxt_t *ctxt, int x0, int y0, int x1, int y1, u32 color); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /ipl/gpio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "gpio.h" 18 | #include "t210.h" 19 | 20 | static const u16 _gpio_cnf[31] = { 21 | 0x000, 0x004, 0x008, 0x00C, 22 | 0x100, 0x104, 0x108, 0x10C, 23 | 0x200, 0x204, 0x208, 0x20C, 24 | 0x300, 0x304, 0x308, 0x30C, 25 | 0x400, 0x404, 0x408, 0x40C, 26 | 0x500, 0x504, 0x508, 0x50C, 27 | 0x600, 0x604, 0x608, 0x60C, 28 | 0x700, 0x704, 0x708 29 | }; 30 | 31 | static const u16 _gpio_oe[31] = { 32 | 0x010, 0x014, 0x018, 0x01C, 33 | 0x110, 0x114, 0x118, 0x11C, 34 | 0x210, 0x214, 0x218, 0x21C, 35 | 0x310, 0x314, 0x318, 0x31C, 36 | 0x410, 0x414, 0x418, 0x41C, 37 | 0x510, 0x514, 0x518, 0x51C, 38 | 0x610, 0x614, 0x618, 0x61C, 39 | 0x710, 0x714, 0x718 40 | }; 41 | 42 | static const u16 _gpio_out[31] = { 43 | 0x020, 0x024, 0x028, 0x02C, 44 | 0x120, 0x124, 0x128, 0x12C, 45 | 0x220, 0x224, 0x228, 0x22C, 46 | 0x320, 0x324, 0x328, 0x32C, 47 | 0x420, 0x424, 0x428, 0x42C, 48 | 0x520, 0x524, 0x528, 0x52C, 49 | 0x620, 0x624, 0x628, 0x62C, 50 | 0x720, 0x724, 0x728 51 | }; 52 | 53 | static const u16 _gpio_in[31] = { 54 | 0x030, 0x034, 0x038, 0x03C, 55 | 0x130, 0x134, 0x138, 0x13C, 56 | 0x230, 0x234, 0x238, 0x23C, 57 | 0x330, 0x334, 0x338, 0x33C, 58 | 0x430, 0x434, 0x438, 0x43C, 59 | 0x530, 0x534, 0x538, 0x53C, 60 | 0x630, 0x634, 0x638, 0x63C, 61 | 0x730, 0x734, 0x738 62 | }; 63 | 64 | void gpio_config(u32 port, u32 pins, int mode) 65 | { 66 | if (mode) 67 | GPIO(_gpio_cnf[port]) |= pins; 68 | else 69 | GPIO(_gpio_cnf[port]) &= ~pins; 70 | (void)GPIO(_gpio_cnf[port]); 71 | } 72 | 73 | void gpio_output_enable(u32 port, u32 pins, int enable) 74 | { 75 | if (enable) 76 | GPIO(_gpio_oe[port]) |= pins; 77 | else 78 | GPIO(_gpio_oe[port]) &= ~pins; 79 | (void)GPIO(_gpio_oe[port]); 80 | } 81 | 82 | void gpio_write(u32 port, u32 pins, int high) 83 | { 84 | if (high) 85 | GPIO(_gpio_out[port]) |= pins; 86 | else 87 | GPIO(_gpio_out[port]) &= ~pins; 88 | (void)GPIO(_gpio_out[port]); 89 | } 90 | 91 | int gpio_read(u32 port, u32 pins) 92 | { 93 | return GPIO(_gpio_in[port]) & pins ? 1 : 0; 94 | } 95 | -------------------------------------------------------------------------------- /ipl/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _GPIO_H_ 18 | #define _GPIO_H_ 19 | 20 | #include "types.h" 21 | 22 | #define GPIO_MODE_SPIO 0 23 | #define GPIO_MODE_GPIO 1 24 | #define GPIO_OUTPUT_DISABLE 0 25 | #define GPIO_OUTPUT_ENABLE 1 26 | #define GPIO_LOW 0 27 | #define GPIO_HIGH 1 28 | 29 | /*! GPIO pins (0-7 for each port). */ 30 | #define GPIO_PIN_0 (1 << 0) 31 | #define GPIO_PIN_1 (1 << 1) 32 | #define GPIO_PIN_2 (1 << 2) 33 | #define GPIO_PIN_3 (1 << 3) 34 | #define GPIO_PIN_4 (1 << 4) 35 | #define GPIO_PIN_5 (1 << 5) 36 | #define GPIO_PIN_6 (1 << 6) 37 | #define GPIO_PIN_7 (1 << 7) 38 | 39 | /*! GPIO ports (A-EE). */ 40 | #define GPIO_PORT_A 0 41 | #define GPIO_PORT_B 1 42 | #define GPIO_PORT_C 2 43 | #define GPIO_PORT_D 3 44 | #define GPIO_PORT_E 4 45 | #define GPIO_PORT_F 5 46 | #define GPIO_PORT_G 6 47 | #define GPIO_PORT_H 7 48 | #define GPIO_PORT_I 8 49 | #define GPIO_PORT_J 9 50 | #define GPIO_PORT_K 10 51 | #define GPIO_PORT_L 11 52 | #define GPIO_PORT_M 12 53 | #define GPIO_PORT_N 13 54 | #define GPIO_PORT_O 14 55 | #define GPIO_PORT_P 15 56 | #define GPIO_PORT_Q 16 57 | #define GPIO_PORT_R 17 58 | #define GPIO_PORT_S 18 59 | #define GPIO_PORT_T 19 60 | #define GPIO_PORT_U 20 61 | #define GPIO_PORT_V 21 62 | #define GPIO_PORT_W 22 63 | #define GPIO_PORT_X 23 64 | #define GPIO_PORT_Y 24 65 | #define GPIO_PORT_Z 25 66 | #define GPIO_PORT_AA 26 67 | #define GPIO_PORT_BB 27 68 | #define GPIO_PORT_CC 28 69 | #define GPIO_PORT_DD 29 70 | #define GPIO_PORT_EE 30 71 | 72 | void gpio_config(u32 port, u32 pins, int mode); 73 | void gpio_output_enable(u32 port, u32 pins, int enable); 74 | void gpio_write(u32 port, u32 pins, int high); 75 | int gpio_read(u32 port, u32 pins); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /ipl/heap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | #include "heap.h" 19 | 20 | typedef struct _hnode 21 | { 22 | int used; 23 | u32 size; 24 | struct _hnode *prev; 25 | struct _hnode *next; 26 | } hnode_t; 27 | 28 | typedef struct _heap 29 | { 30 | u32 start; 31 | hnode_t *first; 32 | } heap_t; 33 | 34 | static void _heap_create(heap_t *heap, u32 start) 35 | { 36 | heap->start = start; 37 | heap->first = NULL; 38 | } 39 | 40 | static u32 _heap_alloc(heap_t *heap, u32 size) 41 | { 42 | hnode_t *node, *new; 43 | int search = 1; 44 | 45 | size = ALIGN(size, 0x10); 46 | 47 | if (!heap->first) 48 | { 49 | node = (hnode_t *)heap->start; 50 | node->used = 1; 51 | node->size = size; 52 | node->prev = NULL; 53 | node->next = NULL; 54 | heap->first = node; 55 | 56 | return (u32)node + sizeof(hnode_t); 57 | } 58 | 59 | node = heap->first; 60 | while (search) 61 | { 62 | if (!node->used && size + sizeof(hnode_t) < node->size) 63 | { 64 | new = (hnode_t *)((u32)node + sizeof(hnode_t) + size); 65 | 66 | new->size = node->size - sizeof(hnode_t) - size; 67 | node->size = size; 68 | node->used = 1; 69 | new->used = 0; 70 | new->next = node->next; 71 | new->prev = node; 72 | node->next = new; 73 | 74 | return (u32)node + sizeof(hnode_t); 75 | } 76 | if (node->next) 77 | node = node->next; 78 | else 79 | search = 0; 80 | } 81 | 82 | new = (hnode_t *)((u32)node + sizeof(hnode_t) + node->size); 83 | new->used = 1; 84 | new->size = size; 85 | new->prev = node; 86 | new->next = NULL; 87 | node->next = new; 88 | 89 | return (u32)new + sizeof(hnode_t); 90 | } 91 | 92 | static void _heap_free(heap_t *heap, u32 addr) 93 | { 94 | hnode_t *node = (hnode_t *)(addr - sizeof(hnode_t)); 95 | node->used = 0; 96 | node = heap->first; 97 | while (node) 98 | { 99 | if (!node->used) 100 | if (node->prev && !node->prev->used) 101 | { 102 | node->prev->size += node->size + sizeof(hnode_t); 103 | node->prev->next = node->next; 104 | if (node->next) 105 | node->next->prev = node->prev; 106 | } 107 | node = node->next; 108 | } 109 | } 110 | 111 | static heap_t _heap; 112 | 113 | void heap_init(u32 base) 114 | { 115 | _heap_create(&_heap, base); 116 | } 117 | 118 | void *malloc(u32 size) 119 | { 120 | return (void *)_heap_alloc(&_heap, size); 121 | } 122 | 123 | void *calloc(u32 num, u32 size) 124 | { 125 | void *res = (void *)_heap_alloc(&_heap, num * size); 126 | memset(res, 0, num * size); 127 | return res; 128 | } 129 | 130 | void free(void *buf) 131 | { 132 | _heap_free(&_heap, (u32)buf); 133 | } 134 | -------------------------------------------------------------------------------- /ipl/heap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _HEAP_H_ 18 | #define _HEAP_H_ 19 | 20 | #include "types.h" 21 | 22 | void heap_init(u32 base); 23 | void *malloc(u32 size); 24 | void *calloc(u32 num, u32 size); 25 | void free(void *buf); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ipl/hos.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _HOS_H_ 18 | #define _HOS_H_ 19 | 20 | #include "types.h" 21 | #include "ini.h" 22 | 23 | int hos_launch(ini_sec_t *cfg); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /ipl/i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | 19 | #include "i2c.h" 20 | #include "util.h" 21 | 22 | static u32 i2c_addrs[] = { 0x7000C000, 0x7000C400, 0x7000C500, 0x7000C700, 0x7000D000, 0x7000D100 }; 23 | 24 | static void _i2c_wait(vu32 *base) 25 | { 26 | base[0x23] = 0x25; 27 | for (u32 i = 0; i < 20; i++) 28 | { 29 | sleep(1); 30 | if (!(base[0x23] & 1)) 31 | break; 32 | } 33 | } 34 | 35 | static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size) 36 | { 37 | if (size > 4) 38 | return 0; 39 | 40 | u32 tmp = 0; 41 | memcpy(&tmp, buf, size); 42 | 43 | vu32 *base = (vu32 *)i2c_addrs[idx]; 44 | base[1] = x << 1; //Set x (send mode). 45 | base[3] = tmp; //Set value. 46 | base[0] = (2 * size - 2) | 0x2800; //Set size and send mode. 47 | _i2c_wait(base); //Kick transaction. 48 | 49 | base[0] = base[0] & 0xFFFFFDFF | 0x200; 50 | while (base[7] & 0x100) 51 | ; 52 | 53 | if (base[7] << 28) 54 | return 0; 55 | 56 | return 1; 57 | } 58 | 59 | static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x) 60 | { 61 | if (size > 4) 62 | return 0; 63 | 64 | vu32 *base = (vu32 *)i2c_addrs[idx]; 65 | base[1] = (x << 1) | 1; //Set x (recv mode). 66 | base[0] = (2 * size - 2) | 0x2840; //Set size and recv mode. 67 | _i2c_wait(base); //Kick transaction. 68 | 69 | base[0] = base[0] & 0xFFFFFDFF | 0x200; 70 | while (base[7] & 0x100) 71 | ; 72 | 73 | if (base[7] << 28) 74 | return 0; 75 | 76 | u32 tmp = base[3]; //Get value. 77 | memcpy(buf, &tmp, size); 78 | 79 | return 1; 80 | } 81 | 82 | void i2c_init(u32 idx) 83 | { 84 | vu32 *base = (vu32 *)i2c_addrs[idx]; 85 | 86 | base[0x1B] = 0x50001; 87 | base[0x21] = 0x90003; 88 | _i2c_wait(base); 89 | 90 | for (u32 i = 0; i < 10; i++) 91 | { 92 | sleep(20000); 93 | if (base[0x1A] & 0x800) 94 | break; 95 | } 96 | 97 | vu32 dummy = base[0x22]; 98 | base[0x1A] = base[0x1A]; 99 | } 100 | 101 | u32 i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size) 102 | { 103 | u8 tmp[4]; 104 | 105 | if (size > 3) 106 | return 0; 107 | 108 | tmp[0] = y; 109 | memcpy(tmp + 1, buf, size); 110 | 111 | _i2c_send_pkt(idx, x, tmp, size + 1); 112 | } 113 | 114 | int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y) 115 | { 116 | int res = _i2c_send_pkt(idx, x, (u8 *)&y, 1); 117 | if (res) 118 | res = _i2c_recv_pkt(idx, buf, size, x); 119 | return res; 120 | } 121 | 122 | u32 i2c_send_byte(u32 idx, u32 x, u32 y, u8 b) 123 | { 124 | i2c_send_buf_small(idx, x, y, &b, 1); 125 | } 126 | 127 | u8 i2c_recv_byte(u32 idx, u32 x, u32 y) 128 | { 129 | u8 tmp; 130 | i2c_recv_buf_small(&tmp, 1, idx, x, y); 131 | return tmp; 132 | } 133 | -------------------------------------------------------------------------------- /ipl/i2c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _I2C_H_ 18 | #define _I2C_H_ 19 | 20 | #include "types.h" 21 | 22 | #define I2C_1 0 23 | #define I2C_2 1 24 | #define I2C_3 2 25 | #define I2C_4 3 26 | #define I2C_5 4 27 | #define I2C_6 5 28 | 29 | void i2c_init(u32 idx); 30 | u32 i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size); 31 | int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y); 32 | u32 i2c_send_byte(u32 idx, u32 x, u32 y, u8 b); 33 | u8 i2c_recv_byte(u32 idx, u32 x, u32 y); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /ipl/ini.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | 19 | #include "ini.h" 20 | #include "ff.h" 21 | #include "heap.h" 22 | 23 | 24 | static char *_strdup(char *str) 25 | { 26 | char *res = malloc(strlen(str) + 1); 27 | strcpy(res, str); 28 | return res; 29 | } 30 | 31 | int ini_parse(link_t *dst, char *ini_path) 32 | { 33 | u32 lblen; 34 | char lbuf[512]; 35 | FIL fp; 36 | ini_sec_t *csec = NULL; 37 | 38 | if (f_open(&fp, ini_path, FA_READ) != FR_OK) 39 | return 0; 40 | 41 | do 42 | { 43 | //Fetch one line. 44 | lbuf[0] = 0; 45 | f_gets(lbuf, 512, &fp); 46 | lblen = strlen(lbuf); 47 | 48 | //Skip empty lines and comments. 49 | if (lblen <= 1 || lbuf[0] == '#') 50 | continue; 51 | 52 | //Remove trailing newline. 53 | if (lbuf[lblen - 1] == '\n') 54 | lbuf[lblen - 1] = 0; 55 | 56 | if (lblen > 2 && lbuf[0] == '[') //Create new section. 57 | { 58 | if (csec) 59 | { 60 | list_append(dst, &csec->link); 61 | csec = NULL; 62 | } 63 | 64 | u32 i; 65 | for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != ']'; i++) 66 | ; 67 | lbuf[i] = 0; 68 | 69 | csec = (ini_sec_t *)malloc(sizeof(ini_sec_t)); 70 | csec->name = _strdup(&lbuf[1]); 71 | list_init(&csec->kvs); 72 | } 73 | else if (csec) //Extract key/value. 74 | { 75 | u32 i; 76 | for (i = 0; i < lblen && lbuf[i] != '\n' && lbuf[i] != '='; i++) 77 | ; 78 | lbuf[i] = 0; 79 | 80 | ini_kv_t *kv = (ini_kv_t *)malloc(sizeof(ini_kv_t)); 81 | kv->key = _strdup(&lbuf[0]); 82 | kv->val = _strdup(&lbuf[i + 1]); 83 | list_append(&csec->kvs, &kv->link); 84 | } 85 | } while (!f_eof(&fp)); 86 | 87 | f_close(&fp); 88 | 89 | if (csec) 90 | list_append(dst, &csec->link); 91 | 92 | return 1; 93 | } 94 | -------------------------------------------------------------------------------- /ipl/ini.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _INI_H_ 18 | #define _INI_H_ 19 | 20 | #include "types.h" 21 | #include "list.h" 22 | 23 | typedef struct _ini_kv_t 24 | { 25 | char *key; 26 | char *val; 27 | link_t link; 28 | } ini_kv_t; 29 | 30 | typedef struct _ini_sec_t 31 | { 32 | char *name; 33 | link_t kvs; 34 | link_t link; 35 | } ini_sec_t; 36 | 37 | int ini_parse(link_t *dst, char *ini_path); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /ipl/integer.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------*/ 2 | /* Integer type definitions for FatFs module */ 3 | /*-------------------------------------------*/ 4 | 5 | #ifndef FF_INTEGER 6 | #define FF_INTEGER 7 | 8 | #ifdef _WIN32 /* FatFs development platform */ 9 | 10 | #include 11 | #include 12 | typedef unsigned __int64 QWORD; 13 | 14 | 15 | #else /* Embedded platform */ 16 | 17 | /* These types MUST be 16-bit or 32-bit */ 18 | typedef int INT; 19 | typedef unsigned int UINT; 20 | 21 | /* This type MUST be 8-bit */ 22 | typedef unsigned char BYTE; 23 | 24 | /* These types MUST be 16-bit */ 25 | typedef short SHORT; 26 | typedef unsigned short WORD; 27 | typedef unsigned short WCHAR; 28 | 29 | /* These types MUST be 32-bit */ 30 | typedef long LONG; 31 | typedef unsigned long DWORD; 32 | 33 | /* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */ 34 | typedef unsigned long long QWORD; 35 | 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /ipl/kfuse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "kfuse.h" 18 | #include "clock.h" 19 | #include "t210.h" 20 | 21 | int kfuse_read(u32 *buf) 22 | { 23 | int res = 0; 24 | 25 | clock_enable_kfuse(); 26 | 27 | while (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_DONE)) 28 | ; 29 | 30 | if (!(KFUSE(KFUSE_STATE) & KFUSE_STATE_CRCPASS)) 31 | goto out; 32 | 33 | KFUSE(KFUSE_KEYADDR) = KFUSE_KEYADDR_AUTOINC; 34 | for (int i = 0; i < KFUSE_NUM_WORDS; i++) 35 | buf[i] = KFUSE(KFUSE_KEYS); 36 | 37 | res = 1; 38 | 39 | out:; 40 | clock_disable_kfuse(); 41 | return res; 42 | } 43 | -------------------------------------------------------------------------------- /ipl/kfuse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _KFUSE_H_ 18 | #define _KFUSE_H_ 19 | 20 | #include "types.h" 21 | 22 | #define KFUSE_STATE_SOFTRESET (1<<31) 23 | #define KFUSE_STATE_STOP (1<<25) 24 | #define KFUSE_STATE_RESTART (1<<24) 25 | #define KFUSE_STATE_CRCPASS (1<<17) 26 | #define KFUSE_STATE_DONE (1<<16) 27 | #define KFUSE_STATE_ERRBLOCK_MASK 0x3F00 28 | #define KFUSE_STATE_ERRBLOCK_SHIFT 8 29 | #define KFUSE_STATE_CURBLOCK_MASK 0x3F 30 | 31 | #define KFUSE_KEYADDR_AUTOINC (1<<16) 32 | 33 | #define KFUSE_STATE 0x80 34 | #define KFUSE_KEYADDR 0x88 35 | #define KFUSE_KEYS 0x8C 36 | 37 | #define KFUSE_NUM_WORDS 144 38 | 39 | int kfuse_read(u32 *buf); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /ipl/link.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS { 4 | PROVIDE(__ipl_start = 0x40003000); 5 | . = __ipl_start; 6 | .text : { 7 | *(.text*); 8 | } 9 | .data : { 10 | *(.data*); 11 | *(.rodata*); 12 | } 13 | . = ALIGN(0x10); 14 | __ipl_end = .; 15 | .bss : { 16 | __bss_start = .; 17 | *(COMMON) 18 | *(.bss*) 19 | __bss_end = .; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ipl/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _LIST_H_ 18 | #define _LIST_H_ 19 | 20 | #include "types.h" 21 | 22 | /*! Initialize list. */ 23 | #define LIST_INIT(name) link_t name = {&name, &name} 24 | 25 | /*! Initialize static list. */ 26 | #define LIST_INIT_STATIC(name) static link_t name = {&name, &name} 27 | 28 | /*! Iterate over all list links. */ 29 | #define LIST_FOREACH(iter, list) \ 30 | for(link_t *iter = (list)->next; iter != (list); iter = iter->next) 31 | 32 | /*! Safely iterate over all list links. */ 33 | #define LIST_FOREACH_SAFE(iter, list) \ 34 | for(link_t *iter = (list)->next, *safe = iter->next; iter != (list); iter = safe, safe = iter->next) 35 | 36 | /*! Iterate over all list members. */ 37 | #define LIST_FOREACH_ENTRY(etype, iter, list, mn) \ 38 | for(etype *iter = CONTAINER_OF((list)->next, etype, mn); &iter->mn != (list); iter = CONTAINER_OF(iter->mn.next, etype, mn)) 39 | 40 | typedef struct _link_t 41 | { 42 | struct _link_t *prev; 43 | struct _link_t *next; 44 | } link_t; 45 | 46 | static inline void link_init(link_t *l) 47 | { 48 | l->prev = NULL; 49 | l->next = NULL; 50 | } 51 | 52 | static inline int link_used(link_t *l) 53 | { 54 | if(l->next == NULL) 55 | return 1; 56 | return 0; 57 | } 58 | 59 | static inline void list_init(link_t *lh) 60 | { 61 | lh->prev = lh; 62 | lh->next = lh; 63 | } 64 | 65 | static inline void list_prepend(link_t *lh, link_t *l) 66 | { 67 | l->next = lh->next; 68 | l->prev = lh; 69 | lh->next->prev = l; 70 | lh->next = l; 71 | } 72 | 73 | static inline void list_append(link_t *lh, link_t *l) 74 | { 75 | l->prev = lh->prev; 76 | l->next = lh; 77 | lh->prev->next = l; 78 | lh->prev = l; 79 | } 80 | 81 | static inline void list_remove(link_t *l) 82 | { 83 | l->next->prev = l->prev; 84 | l->prev->next = l->next; 85 | link_init(l); 86 | } 87 | 88 | static inline int list_empty(link_t *lh) 89 | { 90 | if(lh->next == lh) 91 | return 1; 92 | return 0; 93 | } 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /ipl/lz.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Name: lz.c 3 | * Author: Marcus Geelnard 4 | * Description: LZ77 coder/decoder implementation. 5 | * Reentrant: Yes 6 | * 7 | * The LZ77 compression scheme is a substitutional compression scheme 8 | * proposed by Abraham Lempel and Jakob Ziv in 1977. It is very simple in 9 | * its design, and uses no fancy bit level compression. 10 | * 11 | * This is my first attempt at an implementation of a LZ77 code/decoder. 12 | * 13 | * The principle of the LZ77 compression algorithm is to store repeated 14 | * occurrences of strings as references to previous occurrences of the same 15 | * string. The point is that the reference consumes less space than the 16 | * string itself, provided that the string is long enough (in this 17 | * implementation, the string has to be at least 4 bytes long, since the 18 | * minimum coded reference is 3 bytes long). Also note that the term 19 | * "string" refers to any kind of byte sequence (it does not have to be 20 | * an ASCII string, for instance). 21 | * 22 | * The coder uses a brute force approach to finding string matches in the 23 | * history buffer (or "sliding window", if you wish), which is very, very 24 | * slow. I recon the complexity is somewhere between O(n^2) and O(n^3), 25 | * depending on the input data. 26 | * 27 | * There is also a faster implementation that uses a large working buffer 28 | * in which a "jump table" is stored, which is used to quickly find 29 | * possible string matches (see the source code for LZ_CompressFast() for 30 | * more information). The faster method is an order of magnitude faster, 31 | * but still quite slow compared to other compression methods. 32 | * 33 | * The upside is that decompression is very fast, and the compression ratio 34 | * is often very good. 35 | * 36 | * The reference to a string is coded as a (length,offset) pair, where the 37 | * length indicates the length of the string, and the offset gives the 38 | * offset from the current data position. To distinguish between string 39 | * references and literal strings (uncompressed bytes), a string reference 40 | * is preceded by a marker byte, which is chosen as the least common byte 41 | * symbol in the input data stream (this marker byte is stored in the 42 | * output stream as the first byte). 43 | * 44 | * Occurrences of the marker byte in the stream are encoded as the marker 45 | * byte followed by a zero byte, which means that occurrences of the marker 46 | * byte have to be coded with two bytes. 47 | * 48 | * The lengths and offsets are coded in a variable length fashion, allowing 49 | * values of any magnitude (up to 4294967295 in this implementation). 50 | * 51 | * With this compression scheme, the worst case compression result is 52 | * (257/256)*insize + 1. 53 | * 54 | *------------------------------------------------------------------------- 55 | * Copyright (c) 2003-2006 Marcus Geelnard 56 | * 57 | * This software is provided 'as-is', without any express or implied 58 | * warranty. In no event will the authors be held liable for any damages 59 | * arising from the use of this software. 60 | * 61 | * Permission is granted to anyone to use this software for any purpose, 62 | * including commercial applications, and to alter it and redistribute it 63 | * freely, subject to the following restrictions: 64 | * 65 | * 1. The origin of this software must not be misrepresented; you must not 66 | * claim that you wrote the original software. If you use this software 67 | * in a product, an acknowledgment in the product documentation would 68 | * be appreciated but is not required. 69 | * 70 | * 2. Altered source versions must be plainly marked as such, and must not 71 | * be misrepresented as being the original software. 72 | * 73 | * 3. This notice may not be removed or altered from any source 74 | * distribution. 75 | * 76 | * Marcus Geelnard 77 | * marcus.geelnard at home.se 78 | *************************************************************************/ 79 | 80 | 81 | /************************************************************************* 82 | * INTERNAL FUNCTIONS * 83 | *************************************************************************/ 84 | 85 | 86 | /************************************************************************* 87 | * _LZ_ReadVarSize() - Read unsigned integer with variable number of 88 | * bytes depending on value. 89 | *************************************************************************/ 90 | 91 | static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf ) 92 | { 93 | unsigned int y, b, num_bytes; 94 | 95 | /* Read complete value (stop when byte contains zero in 8:th bit) */ 96 | y = 0; 97 | num_bytes = 0; 98 | do 99 | { 100 | b = (unsigned int) (*buf ++); 101 | y = (y << 7) | (b & 0x0000007f); 102 | ++ num_bytes; 103 | } 104 | while( b & 0x00000080 ); 105 | 106 | /* Store value in x */ 107 | *x = y; 108 | 109 | /* Return number of bytes read */ 110 | return num_bytes; 111 | } 112 | 113 | 114 | 115 | /************************************************************************* 116 | * PUBLIC FUNCTIONS * 117 | *************************************************************************/ 118 | 119 | 120 | /************************************************************************* 121 | * LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder. 122 | * in - Input (compressed) buffer. 123 | * out - Output (uncompressed) buffer. This buffer must be large 124 | * enough to hold the uncompressed data. 125 | * insize - Number of input bytes. 126 | *************************************************************************/ 127 | 128 | void LZ_Uncompress( const unsigned char *in, unsigned char *out, 129 | unsigned int insize ) 130 | { 131 | unsigned char marker, symbol; 132 | unsigned int i, inpos, outpos, length, offset; 133 | 134 | /* Do we have anything to uncompress? */ 135 | if( insize < 1 ) 136 | { 137 | return; 138 | } 139 | 140 | /* Get marker symbol from input stream */ 141 | marker = in[ 0 ]; 142 | inpos = 1; 143 | 144 | /* Main decompression loop */ 145 | outpos = 0; 146 | do 147 | { 148 | symbol = in[ inpos ++ ]; 149 | if( symbol == marker ) 150 | { 151 | /* We had a marker byte */ 152 | if( in[ inpos ] == 0 ) 153 | { 154 | /* It was a single occurrence of the marker byte */ 155 | out[ outpos ++ ] = marker; 156 | ++ inpos; 157 | } 158 | else 159 | { 160 | /* Extract true length and offset */ 161 | inpos += _LZ_ReadVarSize( &length, &in[ inpos ] ); 162 | inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] ); 163 | 164 | /* Copy corresponding data from history window */ 165 | for( i = 0; i < length; ++ i ) 166 | { 167 | out[ outpos ] = out[ outpos - offset ]; 168 | ++ outpos; 169 | } 170 | } 171 | } 172 | else 173 | { 174 | /* No marker, plain copy */ 175 | out[ outpos ++ ] = symbol; 176 | } 177 | } 178 | while( inpos < insize ); 179 | } 180 | -------------------------------------------------------------------------------- /ipl/lz.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Name: lz.h 3 | * Author: Marcus Geelnard 4 | * Description: LZ77 coder/decoder interface. 5 | * Reentrant: Yes 6 | *------------------------------------------------------------------------- 7 | * Copyright (c) 2003-2006 Marcus Geelnard 8 | * 9 | * This software is provided 'as-is', without any express or implied 10 | * warranty. In no event will the authors be held liable for any damages 11 | * arising from the use of this software. 12 | * 13 | * Permission is granted to anyone to use this software for any purpose, 14 | * including commercial applications, and to alter it and redistribute it 15 | * freely, subject to the following restrictions: 16 | * 17 | * 1. The origin of this software must not be misrepresented; you must not 18 | * claim that you wrote the original software. If you use this software 19 | * in a product, an acknowledgment in the product documentation would 20 | * be appreciated but is not required. 21 | * 22 | * 2. Altered source versions must be plainly marked as such, and must not 23 | * be misrepresented as being the original software. 24 | * 25 | * 3. This notice may not be removed or altered from any source 26 | * distribution. 27 | * 28 | * Marcus Geelnard 29 | * marcus.geelnard at home.se 30 | *************************************************************************/ 31 | 32 | #ifndef _lz_h_ 33 | #define _lz_h_ 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | 40 | /************************************************************************* 41 | * Function prototypes 42 | *************************************************************************/ 43 | 44 | void LZ_Uncompress( const unsigned char *in, unsigned char *out, 45 | unsigned int insize ); 46 | 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* _lz_h_ */ 53 | -------------------------------------------------------------------------------- /ipl/max77620.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Defining registers address and its bit definitions of MAX77620 and MAX20024 3 | * 4 | * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms and conditions of the GNU General Public License, 8 | * version 2, as published by the Free Software Foundation. 9 | */ 10 | 11 | #ifndef _MFD_MAX77620_H_ 12 | #define _MFD_MAX77620_H_ 13 | 14 | /* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ 15 | #define MAX77620_REG_CNFGGLBL1 0x00 16 | #define MAX77620_REG_CNFGGLBL2 0x01 17 | #define MAX77620_REG_CNFGGLBL3 0x02 18 | #define MAX77620_REG_CNFG1_32K 0x03 19 | #define MAX77620_REG_CNFGBBC 0x04 20 | #define MAX77620_REG_IRQTOP 0x05 21 | #define MAX77620_REG_INTLBT 0x06 22 | #define MAX77620_REG_IRQSD 0x07 23 | #define MAX77620_REG_IRQ_LVL2_L0_7 0x08 24 | #define MAX77620_REG_IRQ_LVL2_L8 0x09 25 | #define MAX77620_REG_IRQ_LVL2_GPIO 0x0A 26 | #define MAX77620_REG_ONOFFIRQ 0x0B 27 | #define MAX77620_REG_NVERC 0x0C 28 | #define MAX77620_REG_IRQTOPM 0x0D 29 | #define MAX77620_REG_INTENLBT 0x0E 30 | #define MAX77620_REG_IRQMASKSD 0x0F 31 | #define MAX77620_REG_IRQ_MSK_L0_7 0x10 32 | #define MAX77620_REG_IRQ_MSK_L8 0x11 33 | #define MAX77620_REG_ONOFFIRQM 0x12 34 | #define MAX77620_REG_STATLBT 0x13 35 | #define MAX77620_REG_STATSD 0x14 36 | #define MAX77620_REG_ONOFFSTAT 0x15 37 | 38 | /* SD and LDO Registers */ 39 | #define MAX77620_REG_SD0 0x16 40 | #define MAX77620_REG_SD1 0x17 41 | #define MAX77620_REG_SD2 0x18 42 | #define MAX77620_REG_SD3 0x19 43 | #define MAX77620_REG_SD4 0x1A 44 | #define MAX77620_REG_DVSSD0 0x1B 45 | #define MAX77620_REG_DVSSD1 0x1C 46 | #define MAX77620_REG_SD0_CFG 0x1D 47 | #define MAX77620_REG_SD1_CFG 0x1E 48 | #define MAX77620_REG_SD2_CFG 0x1F 49 | #define MAX77620_REG_SD3_CFG 0x20 50 | #define MAX77620_REG_SD4_CFG 0x21 51 | #define MAX77620_REG_SD_CFG2 0x22 52 | #define MAX77620_REG_LDO0_CFG 0x23 53 | #define MAX77620_REG_LDO0_CFG2 0x24 54 | #define MAX77620_REG_LDO1_CFG 0x25 55 | #define MAX77620_REG_LDO1_CFG2 0x26 56 | #define MAX77620_REG_LDO2_CFG 0x27 57 | #define MAX77620_REG_LDO2_CFG2 0x28 58 | #define MAX77620_REG_LDO3_CFG 0x29 59 | #define MAX77620_REG_LDO3_CFG2 0x2A 60 | #define MAX77620_REG_LDO4_CFG 0x2B 61 | #define MAX77620_REG_LDO4_CFG2 0x2C 62 | #define MAX77620_REG_LDO5_CFG 0x2D 63 | #define MAX77620_REG_LDO5_CFG2 0x2E 64 | #define MAX77620_REG_LDO6_CFG 0x2F 65 | #define MAX77620_REG_LDO6_CFG2 0x30 66 | #define MAX77620_REG_LDO7_CFG 0x31 67 | #define MAX77620_REG_LDO7_CFG2 0x32 68 | #define MAX77620_REG_LDO8_CFG 0x33 69 | #define MAX77620_REG_LDO8_CFG2 0x34 70 | #define MAX77620_REG_LDO_CFG3 0x35 71 | 72 | #define MAX77620_LDO_SLEW_RATE_MASK 0x1 73 | 74 | /* LDO Configuration 3 */ 75 | #define MAX77620_TRACK4_MASK (1 << 5) 76 | #define MAX77620_TRACK4_SHIFT 5 77 | 78 | /* Voltage */ 79 | #define MAX77620_SDX_VOLT_MASK 0xFF 80 | #define MAX77620_SD0_VOLT_MASK 0x3F 81 | #define MAX77620_SD1_VOLT_MASK 0x7F 82 | #define MAX77620_LDO_VOLT_MASK 0x3F 83 | 84 | #define MAX77620_REG_GPIO0 0x36 85 | #define MAX77620_REG_GPIO1 0x37 86 | #define MAX77620_REG_GPIO2 0x38 87 | #define MAX77620_REG_GPIO3 0x39 88 | #define MAX77620_REG_GPIO4 0x3A 89 | #define MAX77620_REG_GPIO5 0x3B 90 | #define MAX77620_REG_GPIO6 0x3C 91 | #define MAX77620_REG_GPIO7 0x3D 92 | #define MAX77620_REG_PUE_GPIO 0x3E 93 | #define MAX77620_REG_PDE_GPIO 0x3F 94 | #define MAX77620_REG_AME_GPIO 0x40 95 | #define MAX77620_REG_ONOFFCNFG1 0x41 96 | #define MAX77620_REG_ONOFFCNFG2 0x42 97 | 98 | /* FPS Registers */ 99 | #define MAX77620_REG_FPS_CFG0 0x43 100 | #define MAX77620_REG_FPS_CFG1 0x44 101 | #define MAX77620_REG_FPS_CFG2 0x45 102 | #define MAX77620_REG_FPS_LDO0 0x46 103 | #define MAX77620_REG_FPS_LDO1 0x47 104 | #define MAX77620_REG_FPS_LDO2 0x48 105 | #define MAX77620_REG_FPS_LDO3 0x49 106 | #define MAX77620_REG_FPS_LDO4 0x4A 107 | #define MAX77620_REG_FPS_LDO5 0x4B 108 | #define MAX77620_REG_FPS_LDO6 0x4C 109 | #define MAX77620_REG_FPS_LDO7 0x4D 110 | #define MAX77620_REG_FPS_LDO8 0x4E 111 | #define MAX77620_REG_FPS_SD0 0x4F 112 | #define MAX77620_REG_FPS_SD1 0x50 113 | #define MAX77620_REG_FPS_SD2 0x51 114 | #define MAX77620_REG_FPS_SD3 0x52 115 | #define MAX77620_REG_FPS_SD4 0x53 116 | #define MAX77620_REG_FPS_NONE 0 117 | 118 | #define MAX77620_FPS_SRC_MASK 0xC0 119 | #define MAX77620_FPS_SRC_SHIFT 6 120 | #define MAX77620_FPS_PU_PERIOD_MASK 0x38 121 | #define MAX77620_FPS_PU_PERIOD_SHIFT 3 122 | #define MAX77620_FPS_PD_PERIOD_MASK 0x07 123 | #define MAX77620_FPS_PD_PERIOD_SHIFT 0 124 | #define MAX77620_FPS_TIME_PERIOD_MASK 0x38 125 | #define MAX77620_FPS_TIME_PERIOD_SHIFT 3 126 | #define MAX77620_FPS_EN_SRC_MASK 0x06 127 | #define MAX77620_FPS_EN_SRC_SHIFT 1 128 | #define MAX77620_FPS_ENFPS_SW_MASK 0x01 129 | #define MAX77620_FPS_ENFPS_SW 0x01 130 | 131 | /* Minimum and maximum FPS period time (in microseconds) are 132 | * different for MAX77620 and Max20024. 133 | */ 134 | #define MAX77620_FPS_PERIOD_MIN_US 40 135 | #define MAX20024_FPS_PERIOD_MIN_US 20 136 | 137 | #define MAX77620_FPS_PERIOD_MAX_US 2560 138 | #define MAX20024_FPS_PERIOD_MAX_US 5120 139 | 140 | #define MAX77620_REG_FPS_GPIO1 0x54 141 | #define MAX77620_REG_FPS_GPIO2 0x55 142 | #define MAX77620_REG_FPS_GPIO3 0x56 143 | #define MAX77620_REG_FPS_RSO 0x57 144 | #define MAX77620_REG_CID0 0x58 145 | #define MAX77620_REG_CID1 0x59 146 | #define MAX77620_REG_CID2 0x5A 147 | #define MAX77620_REG_CID3 0x5B 148 | #define MAX77620_REG_CID4 0x5C 149 | #define MAX77620_REG_CID5 0x5D 150 | 151 | #define MAX77620_REG_DVSSD4 0x5E 152 | #define MAX20024_REG_MAX_ADD 0x70 153 | 154 | #define MAX77620_CID_DIDM_MASK 0xF0 155 | #define MAX77620_CID_DIDM_SHIFT 4 156 | 157 | /* CNCG2SD */ 158 | #define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) 159 | #define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) 160 | 161 | /* Device Identification Metal */ 162 | #define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) 163 | /* Device Indentification OTP */ 164 | #define MAX77620_CID5_DIDO(n) ((n) & 0xF) 165 | 166 | /* SD CNFG1 */ 167 | #define MAX77620_SD_SR_MASK 0xC0 168 | #define MAX77620_SD_SR_SHIFT 6 169 | #define MAX77620_SD_POWER_MODE_MASK 0x30 170 | #define MAX77620_SD_POWER_MODE_SHIFT 4 171 | #define MAX77620_SD_CFG1_ADE_MASK (1 << 3) 172 | #define MAX77620_SD_CFG1_ADE_DISABLE 0 173 | #define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) 174 | #define MAX77620_SD_FPWM_MASK 0x04 175 | #define MAX77620_SD_FPWM_SHIFT 2 176 | #define MAX77620_SD_FSRADE_MASK 0x01 177 | #define MAX77620_SD_FSRADE_SHIFT 0 178 | #define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) 179 | #define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 180 | #define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) 181 | #define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) 182 | #define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) 183 | #define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 184 | #define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) 185 | 186 | /* LDO_CNFG2 */ 187 | #define MAX77620_LDO_POWER_MODE_MASK 0xC0 188 | #define MAX77620_LDO_POWER_MODE_SHIFT 6 189 | #define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) 190 | #define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) 191 | #define MAX77620_LDO_CFG2_ADE_DISABLE 0 192 | #define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) 193 | #define MAX77620_LDO_CFG2_SS_MASK (1 << 0) 194 | #define MAX77620_LDO_CFG2_SS_FAST (1 << 0) 195 | #define MAX77620_LDO_CFG2_SS_SLOW 0 196 | 197 | #define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) 198 | #define MAX77620_IRQ_TOP_SD_MASK (1 << 6) 199 | #define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) 200 | #define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) 201 | #define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) 202 | #define MAX77620_IRQ_TOP_32K_MASK (1 << 2) 203 | #define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) 204 | 205 | #define MAX77620_IRQ_LBM_MASK (1 << 3) 206 | #define MAX77620_IRQ_TJALRM1_MASK (1 << 2) 207 | #define MAX77620_IRQ_TJALRM2_MASK (1 << 1) 208 | 209 | #define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) 210 | #define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) 211 | #define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0 212 | #define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) 213 | #define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) 214 | #define MAX77620_CNFG_GPIO_DIR_OUTPUT 0 215 | #define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) 216 | #define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) 217 | #define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) 218 | #define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0 219 | #define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) 220 | #define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) 221 | #define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) 222 | #define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) 223 | #define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) 224 | #define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) 225 | #define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) 226 | #define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) 227 | 228 | #define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) 229 | #define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) 230 | #define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) 231 | #define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) 232 | #define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) 233 | #define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) 234 | #define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) 235 | #define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) 236 | 237 | #define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) 238 | 239 | #define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) 240 | #define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 241 | #define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 242 | #define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) 243 | #define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) 244 | #define MAX20024_ONOFFCNFG1_CLRSE 0x18 245 | 246 | #define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) 247 | #define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) 248 | #define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) 249 | #define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) 250 | #define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) 251 | 252 | #define MAX77620_GLBLM_MASK (1 << 0) 253 | 254 | #define MAX77620_WDTC_MASK 0x3 255 | #define MAX77620_WDTOFFC (1 << 4) 256 | #define MAX77620_WDTSLPC (1 << 3) 257 | #define MAX77620_WDTEN (1 << 2) 258 | 259 | #define MAX77620_TWD_MASK 0x3 260 | #define MAX77620_TWD_2s 0x0 261 | #define MAX77620_TWD_16s 0x1 262 | #define MAX77620_TWD_64s 0x2 263 | #define MAX77620_TWD_128s 0x3 264 | 265 | #define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) 266 | #define MAX77620_CNFGGLBL1_MPPLD (1 << 6) 267 | #define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) 268 | #define MAX77620_CNFGGLBL1_LBDAC 0x0E 269 | #define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) 270 | 271 | /* CNFG BBC registers */ 272 | #define MAX77620_CNFGBBC_ENABLE (1 << 0) 273 | #define MAX77620_CNFGBBC_CURRENT_MASK 0x06 274 | #define MAX77620_CNFGBBC_CURRENT_SHIFT 1 275 | #define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 276 | #define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 277 | #define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) 278 | #define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 279 | #define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 280 | 281 | #define MAX77620_FPS_COUNT 3 282 | 283 | /* Interrupts */ 284 | enum { 285 | MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ 286 | MAX77620_IRQ_TOP_SD, /* SD power fail */ 287 | MAX77620_IRQ_TOP_LDO, /* LDO power fail */ 288 | MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ 289 | MAX77620_IRQ_TOP_RTC, /* RTC */ 290 | MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ 291 | MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ 292 | MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ 293 | MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ 294 | MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ 295 | }; 296 | 297 | /* GPIOs */ 298 | enum { 299 | MAX77620_GPIO0, 300 | MAX77620_GPIO1, 301 | MAX77620_GPIO2, 302 | MAX77620_GPIO3, 303 | MAX77620_GPIO4, 304 | MAX77620_GPIO5, 305 | MAX77620_GPIO6, 306 | MAX77620_GPIO7, 307 | MAX77620_GPIO_NR, 308 | }; 309 | 310 | /* FPS Source */ 311 | enum max77620_fps_src { 312 | MAX77620_FPS_SRC_0, 313 | MAX77620_FPS_SRC_1, 314 | MAX77620_FPS_SRC_2, 315 | MAX77620_FPS_SRC_NONE, 316 | MAX77620_FPS_SRC_DEF, 317 | }; 318 | 319 | enum max77620_chip_id { 320 | MAX77620, 321 | MAX20024, 322 | }; 323 | 324 | #endif /* _MFD_MAX77620_H_ */ 325 | -------------------------------------------------------------------------------- /ipl/max7762x.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "max7762x.h" 18 | #include "max77620.h" 19 | #include "i2c.h" 20 | #include "util.h" 21 | 22 | #include "gfx.h" 23 | extern gfx_ctxt_t gfx_ctxt; 24 | extern gfx_con_t gfx_con; 25 | #define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__) 26 | 27 | #define REGULATOR_SD 0 28 | #define REGULATOR_LDO 1 29 | 30 | typedef struct _max77620_regulator_t 31 | { 32 | u8 type; 33 | const char *name; 34 | u8 reg_sd; 35 | u32 mv_step; 36 | u32 mv_min; 37 | u32 mv_default; 38 | u32 mv_max; 39 | u8 volt_addr; 40 | u8 cfg_addr; 41 | u8 volt_mask; 42 | u8 enable_mask; 43 | u8 enable_shift; 44 | u8 status_mask; 45 | 46 | u8 fps_addr; 47 | u8 fps_src; 48 | u8 pd_period; 49 | u8 pu_period; 50 | } max77620_regulator_t; 51 | 52 | static const max77620_regulator_t _pmic_regulators[] = { 53 | { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, 0x3F, 0x30, 4, 0x80, 0x4F, 1, 7, 1 }, 54 | { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, 0x3F, 0x30, 4, 0x40, 0x50, 0, 1, 5 }, 55 | { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, 0xFF, 0x30, 4, 0x20, 0x51, 1, 5, 2 }, 56 | { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, 0xFF, 0x30, 4, 0x10, 0x52, 0, 3, 3 }, 57 | { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, 0x3F, 0xC0, 6, 0x00, 0x46, 3, 7, 0 }, 58 | { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, 0x3F, 0xC0, 6, 0x00, 0x47, 3, 7, 0 }, 59 | { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, 0x3F, 0xC0, 6, 0x00, 0x48, 3, 7, 0 }, 60 | { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, 0x3F, 0xC0, 6, 0x00, 0x49, 3, 7, 0 }, 61 | { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4A, 0, 7, 1 }, 62 | { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4B, 3, 7, 0 }, 63 | { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4C, 3, 7, 0 }, 64 | { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4D, 1, 4, 3 }, 65 | { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4E, 3, 7, 0 } 66 | }; 67 | 68 | int max77620_regulator_get_status(u32 id) 69 | { 70 | if (id > REGULATOR_MAX) 71 | return 0; 72 | 73 | const max77620_regulator_t *reg = &_pmic_regulators[id]; 74 | 75 | if (reg->type == REGULATOR_SD) 76 | return i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask ? 0 : 1; 77 | return i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8 ? 1 : 0; 78 | } 79 | 80 | int max77620_regulator_config_fps(u32 id) 81 | { 82 | if (id > REGULATOR_MAX) 83 | return 0; 84 | 85 | const max77620_regulator_t *reg = &_pmic_regulators[id]; 86 | 87 | i2c_send_byte(I2C_5, 0x3C, reg->fps_addr, (reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); 88 | 89 | return 1; 90 | } 91 | 92 | int max77620_regulator_set_voltage(u32 id, u32 mv) 93 | { 94 | if (id > REGULATOR_MAX) 95 | return 0; 96 | 97 | const max77620_regulator_t *reg = &_pmic_regulators[id]; 98 | 99 | if (mv < reg->mv_default || mv > reg->mv_max) 100 | return 0; 101 | 102 | u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; 103 | u8 val = i2c_recv_byte(I2C_5, 0x3C, reg->volt_addr); 104 | val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); 105 | i2c_send_byte(I2C_5, 0x3C, reg->volt_addr, val); 106 | sleep(1000); 107 | 108 | return 1; 109 | } 110 | 111 | int max77620_regulator_enable(u32 id, int enable) 112 | { 113 | if (id > REGULATOR_MAX) 114 | return 0; 115 | 116 | const max77620_regulator_t *reg = &_pmic_regulators[id]; 117 | 118 | u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr; 119 | u8 val = i2c_recv_byte(I2C_5, 0x3C, addr); 120 | if (enable) 121 | val = (val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask); 122 | else 123 | val &= ~reg->enable_mask; 124 | i2c_send_byte(I2C_5, 0x3C, addr, val); 125 | sleep(1000); 126 | 127 | return 1; 128 | } 129 | 130 | void max77620_config_default() 131 | { 132 | for (u32 i = 1; i <= REGULATOR_MAX; i++) 133 | { 134 | i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_CID4); 135 | max77620_regulator_config_fps(i); 136 | max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); 137 | if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) 138 | max77620_regulator_enable(i, 1); 139 | } 140 | i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_SD_CFG2, 4); 141 | } 142 | -------------------------------------------------------------------------------- /ipl/max7762x.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _MAX7762X_H_ 18 | #define _MAX7762X_H_ 19 | 20 | #include "types.h" 21 | 22 | /* 23 | * Switch Power domains (max77620): 24 | * Name | Usage | uV step | uV min | uV default | uV max | Init 25 | *-------+---------------+---------+--------+------------+---------+------------------ 26 | * sd0 | core | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1) 27 | * sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1) 28 | * sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv) 29 | * sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 | 30 | * ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1) 31 | * ldo1 | XUSB | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) 32 | * ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 | 33 | * ldo3 | | 50000 | 800000 | 3100000 | 3100000 | 34 | * ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 35 | * ldo5 | | 50000 | 800000 | 1800000 | 1800000 | 36 | * ldo6 | | 50000 | 800000 | 2900000 | 2900000 | 37 | * ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 38 | * ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 | 39 | */ 40 | 41 | /* 42 | * MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode 43 | * MAX77620_REG_GPIOx: 0x9 sets output and enable 44 | */ 45 | 46 | /*! MAX77620 partitions. */ 47 | #define REGULATOR_SD0 0 48 | #define REGULATOR_SD1 1 49 | #define REGULATOR_SD2 2 50 | #define REGULATOR_SD3 3 51 | #define REGULATOR_LDO0 4 52 | #define REGULATOR_LDO1 5 53 | #define REGULATOR_LDO2 6 54 | #define REGULATOR_LDO3 7 55 | #define REGULATOR_LDO4 8 56 | #define REGULATOR_LDO5 9 57 | #define REGULATOR_LDO6 10 58 | #define REGULATOR_LDO7 11 59 | #define REGULATOR_LDO8 12 60 | #define REGULATOR_MAX 12 61 | 62 | int max77620_regulator_get_status(u32 id); 63 | int max77620_regulator_config_fps(u32 id); 64 | int max77620_regulator_set_voltage(u32 id, u32 mv); 65 | int max77620_regulator_enable(u32 id, int enable); 66 | void max77620_config_default(); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /ipl/mc.c: -------------------------------------------------------------------------------- 1 | #include "mc.h" 2 | #include "t210.h" 3 | #include "clock.h" 4 | #include "util.h" 5 | 6 | void mc_config_tsec_carveout(u32 bom, u32 size1mb, int lock) 7 | { 8 | MC(MC_SEC_CARVEOUT_BOM) = bom; 9 | MC(MC_SEC_CARVEOUT_SIZE_MB) = size1mb; 10 | if (lock) 11 | MC(MC_SEC_CARVEOUT_REG_CTRL) = 1; 12 | } 13 | 14 | void mc_config_carveout() 15 | { 16 | *(vu32 *)0x8005FFFC = 0xC0EDBBCC; 17 | MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; 18 | MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; 19 | MC(MC_VIDEO_PROTECT_BOM) = 0; 20 | MC(MC_VIDEO_PROTECT_SIZE_MB) = 0; 21 | MC(MC_VIDEO_PROTECT_REG_CTRL) = 1; 22 | 23 | //Configure TSEC carveout @ 0x90000000, 1MB. 24 | //mc_config_tsec_carveout(0x90000000, 1, 0); 25 | mc_config_tsec_carveout(0, 0, 1); 26 | 27 | MC(MC_MTS_CARVEOUT_BOM) = 0; 28 | MC(MC_MTS_CARVEOUT_SIZE_MB) = 0; 29 | MC(MC_MTS_CARVEOUT_ADR_HI) = 0; 30 | MC(MC_MTS_CARVEOUT_REG_CTRL) = 1; 31 | MC(MC_SECURITY_CARVEOUT1_BOM) = 0; 32 | MC(MC_SECURITY_CARVEOUT1_BOM_HI) = 0; 33 | MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0; 34 | MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0) = 0; 35 | MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1) = 0; 36 | MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0; 37 | MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0; 38 | MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0; 39 | MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; 40 | MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; 41 | MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; 42 | MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; 43 | MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; 44 | MC(MC_SECURITY_CARVEOUT1_CFG0) = 0x4000006; 45 | MC(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000; 46 | MC(MC_SECURITY_CARVEOUT2_BOM_HI) = 0; 47 | MC(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2; 48 | MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0; 49 | MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0; 50 | MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = 0x3000000; 51 | MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0; 52 | MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = 0x300; 53 | MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; 54 | MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; 55 | MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; 56 | MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; 57 | MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; 58 | MC(MC_SECURITY_CARVEOUT2_CFG0) = 0x440167E; 59 | MC(MC_SECURITY_CARVEOUT3_BOM) = 0; 60 | MC(MC_SECURITY_CARVEOUT3_BOM_HI) = 0; 61 | MC(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0; 62 | MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0; 63 | MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0; 64 | MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0x3000000; 65 | MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0; 66 | MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0x300; 67 | MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; 68 | MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; 69 | MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; 70 | MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; 71 | MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; 72 | MC(MC_SECURITY_CARVEOUT3_CFG0) = 0x4401E7E; 73 | MC(MC_SECURITY_CARVEOUT4_BOM) = 0; 74 | MC(MC_SECURITY_CARVEOUT4_BOM_HI) = 0; 75 | MC(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0; 76 | MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0) = 0; 77 | MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1) = 0; 78 | MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = 0; 79 | MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3) = 0; 80 | MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = 0; 81 | MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; 82 | MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; 83 | MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; 84 | MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; 85 | MC(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; 86 | MC(MC_SECURITY_CARVEOUT4_CFG0) = 0x8F; 87 | MC(MC_SECURITY_CARVEOUT5_BOM) = 0; 88 | MC(MC_SECURITY_CARVEOUT5_BOM_HI) = 0; 89 | MC(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0; 90 | MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0) = 0; 91 | MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1) = 0; 92 | MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = 0; 93 | MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3) = 0; 94 | MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4) = 0; 95 | MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; 96 | MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; 97 | MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; 98 | MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; 99 | MC(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; 100 | MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F; 101 | } 102 | 103 | void mc_enable_ahb_redirect() 104 | { 105 | CLOCK(0x3A4) = CLOCK(0x3A4) & 0xFFF7FFFF | 0x80000; 106 | //MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE; 107 | MC(MC_IRAM_BOM) = 0x40000000; 108 | MC(MC_IRAM_TOM) = 0x4003F000; 109 | } 110 | 111 | void mc_disable_ahb_redirect() 112 | { 113 | MC(MC_IRAM_BOM) = 0xFFFFF000; 114 | MC(MC_IRAM_TOM) = 0; 115 | //Disable IRAM_CFG_WRITE_ACCESS (sticky). 116 | //MC(MC_IRAM_REG_CTRL) = MC(MC_IRAM_REG_CTRL) & 0xFFFFFFFE | 1; 117 | CLOCK(0x3A4) &= 0xFFF7FFFF; 118 | } 119 | 120 | void mc_enable() 121 | { 122 | CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF | 0x40000000; 123 | //Enable MIPI CAL clock. 124 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF | 0x2000000; 125 | //Enable MC clock. 126 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE | 1; 127 | //Enable EMC DLL clock. 128 | CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & 0xFFFFBFFF | 0x4000; 129 | CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x2000001; //Clear EMC and MC reset. 130 | sleep(5); 131 | 132 | //#ifdef CONFIG_ENABLE_AHB_REDIRECT 133 | mc_disable_ahb_redirect(); 134 | //mc_enable_ahb_redirect(); 135 | //#endif 136 | } 137 | -------------------------------------------------------------------------------- /ipl/mc.h: -------------------------------------------------------------------------------- 1 | #ifndef _MC_H_ 2 | #define _MC_H_ 3 | 4 | #include "types.h" 5 | #include "mc_t210.h" 6 | 7 | void mc_config_tsec_carveout(u32 bom, u32 size1mb, int lock); 8 | void mc_config_carveout(); 9 | void mc_enable_ahb_redirect(); 10 | void mc_disable_ahb_redirect(); 11 | void mc_enable(); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /ipl/nx_emmc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | #include "nx_emmc.h" 19 | #include "heap.h" 20 | #include "list.h" 21 | 22 | void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage) 23 | { 24 | u8 *buf = (u8 *)malloc(NX_GPT_NUM_BLOCKS * NX_EMMC_BLOCKSIZE); 25 | 26 | sdmmc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, buf); 27 | 28 | gpt_header_t *hdr = (gpt_header_t *)buf; 29 | for (u32 i = 0; i < hdr->num_part_ents; i++) 30 | { 31 | gpt_entry_t *ent = (gpt_entry_t *)(buf + (hdr->part_ent_lba - 1) * NX_EMMC_BLOCKSIZE + i * sizeof(gpt_entry_t)); 32 | emmc_part_t *part = (emmc_part_t *)malloc(sizeof(emmc_part_t)); 33 | part->lba_start = ent->lba_start; 34 | part->lba_end = ent->lba_end; 35 | part->attrs = ent->attrs; 36 | 37 | //HACK 38 | for (u32 i = 0; i < 36; i++) 39 | part->name[i] = ent->name[i]; 40 | part->name[37] = 0; 41 | 42 | list_append(gpt, &part->link); 43 | } 44 | 45 | free(buf); 46 | } 47 | 48 | void nx_emmc_gpt_free(link_t *gpt) 49 | { 50 | LIST_FOREACH_SAFE(iter, gpt) 51 | free(CONTAINER_OF(iter, emmc_part_t, link)); 52 | } 53 | 54 | emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name) 55 | { 56 | LIST_FOREACH_ENTRY(emmc_part_t, part, gpt, link) 57 | if (!strcmp(part->name, name)) 58 | return part; 59 | return NULL; 60 | } 61 | 62 | int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) 63 | { 64 | //The last LBA is inclusive. 65 | if (part->lba_start + sector_off > part->lba_end) 66 | return 0; 67 | return sdmmc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf); 68 | } 69 | 70 | int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) 71 | { 72 | //The last LBA is inclusive. 73 | if (part->lba_start + sector_off > part->lba_end) 74 | return 0; 75 | return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf); 76 | } 77 | -------------------------------------------------------------------------------- /ipl/nx_emmc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _NX_EMMC_H_ 18 | #define _NX_EMMC_H_ 19 | 20 | #include "types.h" 21 | #include "list.h" 22 | #include "sdmmc.h" 23 | 24 | typedef struct _gpt_entry_t 25 | { 26 | u8 type_guid[0x10]; 27 | u8 part_guid[0x10]; 28 | u64 lba_start; 29 | u64 lba_end; 30 | u64 attrs; 31 | u16 name[36]; 32 | } gpt_entry_t; 33 | 34 | typedef struct _gpt_header_t 35 | { 36 | u64 signature; 37 | u32 revision; 38 | u32 size; 39 | u32 crc32; 40 | u32 res1; 41 | u64 my_lba; 42 | u64 alt_lba; 43 | u64 first_use_lba; 44 | u64 last_use_lba; 45 | u8 disk_guid[0x10]; 46 | u64 part_ent_lba; 47 | u32 num_part_ents; 48 | u32 part_ent_size; 49 | u32 part_ents_crc32; 50 | u8 res2[420]; 51 | } gpt_header_t; 52 | 53 | #define NX_GPT_FIRST_LBA 1 54 | #define NX_GPT_NUM_BLOCKS 33 55 | #define NX_EMMC_BLOCKSIZE 512 56 | 57 | typedef struct _emmc_part_t 58 | { 59 | u32 lba_start; 60 | u32 lba_end; 61 | u64 attrs; 62 | u8 name[37]; 63 | link_t link; 64 | } emmc_part_t; 65 | 66 | void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage); 67 | void nx_emmc_gpt_free(link_t *gpt); 68 | emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name); 69 | int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); 70 | int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ipl/pinmux.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "pinmux.h" 18 | #include "t210.h" 19 | 20 | void pinmux_config_uart(u32 idx) 21 | { 22 | PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = 0; 23 | PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0x48; 24 | PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0; 25 | PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = 0x44; 26 | } 27 | 28 | void pinmux_config_i2c(u32 idx) 29 | { 30 | PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = 0x40; 31 | PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = 0x40; 32 | } 33 | -------------------------------------------------------------------------------- /ipl/pinmux.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _PINMUX_H_ 18 | #define _PINMUX_H_ 19 | 20 | #include "types.h" 21 | 22 | /*! APB MISC registers. */ 23 | #define APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL 0x8D4 24 | #define APB_MISC_GP_SDMMC3_CLK_LPBK_CONTROL 0x8D8 25 | #define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98 26 | #define APB_MISC_GP_VGPIO_GPIO_MUX_SEL 0xB74 27 | 28 | /*! Pinmux registers. */ 29 | #define PINMUX_AUX_SDMMC1_CLK 0x00 30 | #define PINMUX_AUX_SDMMC1_CMD 0x04 31 | #define PINMUX_AUX_SDMMC1_DAT3 0x08 32 | #define PINMUX_AUX_SDMMC1_DAT2 0x0C 33 | #define PINMUX_AUX_SDMMC1_DAT1 0x10 34 | #define PINMUX_AUX_SDMMC1_DAT0 0x14 35 | #define PINMUX_AUX_SDMMC3_CLK 0x1C 36 | #define PINMUX_AUX_SDMMC3_CMD 0x20 37 | #define PINMUX_AUX_SDMMC3_DAT0 0x24 38 | #define PINMUX_AUX_SDMMC3_DAT1 0x28 39 | #define PINMUX_AUX_SDMMC3_DAT2 0x2C 40 | #define PINMUX_AUX_SDMMC3_DAT3 0x30 41 | #define PINMUX_AUX_DMIC3_CLK 0xB4 42 | #define PINMUX_AUX_UART2_TX 0xF4 43 | #define PINMUX_AUX_UART3_TX 0x104 44 | #define PINMUX_AUX_GPIO_PE6 0x248 45 | #define PINMUX_AUX_GPIO_PH6 0x250 46 | #define PINMUX_AUX_GPIO_PZ1 0x280 47 | /*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */ 48 | #define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x)) 49 | #define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x)) 50 | #define PINMUX_AUX_UARTX_RTS(x) (0xEC + 0x10 * (x)) 51 | #define PINMUX_AUX_UARTX_CTS(x) (0xF0 + 0x10 * (x)) 52 | /*! 0:GEN1, 1:GEN2, 2:GEN3, 3:CAM, 4:PWR */ 53 | #define PINMUX_AUX_X_I2C_SCL(x) (0xBC + 8 * (x)) 54 | #define PINMUX_AUX_X_I2C_SDA(x) (0xC0 + 8 * (x)) 55 | 56 | void pinmux_config_uart(u32 idx); 57 | void pinmux_config_i2c(u32 idx); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /ipl/pkg1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | #include "pkg1.h" 19 | #include "se.h" 20 | 21 | #define _ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F) 22 | #define _MOVZX(r, i, s) 0xD2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) 23 | #define _MOVKX(r, i, s) 0xF2800000 | (((s) & 0x30) << 17) | (((i) & 0xFFFF) << 5) | ((r) & 0x1F) 24 | #define _BL(a, o) 0x94000000 | (((o) - (a)) >> 2) & 0x3FFFFFF 25 | #define _NOP() 0xD503201F 26 | 27 | PATCHSET_DEF(_secmon_1_patchset, 28 | //Patch the relocator to be able to run from 0x4002D000. 29 | //{ 0x1E0, _ADRP(0, 0x7C013000 - 0x4002D000) } 30 | //Patch package2 decryption and signature/hash checks. 31 | { 0x9F0 + 0xADC, _NOP() }, //Header signature. 32 | { 0x9F0 + 0xB8C, _NOP() }, //Version. 33 | { 0x9F0 + 0xBB0, _NOP() } //Sections SHA2. 34 | ); 35 | 36 | PATCHSET_DEF(_secmon_2_patchset, 37 | //Patch package2 decryption and signature/hash checks. 38 | { 0xAC8 + 0xAAC, _NOP() }, //Header signature. 39 | { 0xAC8 + 0xB3C, _NOP() }, //Version. 40 | { 0xAC8 + 0xB58, _NOP() } //Sections SHA2. 41 | ); 42 | 43 | PATCHSET_DEF(_secmon_5_patchset, 44 | //Patch package2 decryption and signature/hash checks. 45 | { 0x1218 + 0x6E68, _NOP() }, //Header signature. 46 | { 0x1218 + 0x6E74, _NOP() }, //Version. 47 | { 0x1218 + 0x6FE4, _NOP() }, //Sections SHA2. 48 | { 0x1218 + 0x2DC, _NOP() } //Unknown. 49 | ); 50 | 51 | PATCHSET_DEF(_secmon_6_patchset, 52 | //Patch package2 decryption and signature/hash checks. 53 | { 0x12B0 + 0x4D0, _NOP() }, //Header signature. 54 | { 0x12B0 + 0x4DC, _NOP() }, //Version. 55 | { 0x12B0 + 0x794, _NOP() }, //Sections SHA2. 56 | { 0x12B0 + 0xB30, _NOP() } /*,*/ //Unknown. 57 | //{ 0x12B0 + 0xA18 , _NOP() } // BootConfig Retail Check 58 | ); 59 | 60 | /* 61 | * package1.1 header: 62 | * package1.1 layout: 63 | * 1.0: {sm, ldr, wb} { 2, 1, 0 } 64 | * 2.0: {wb, ldr, sm} { 0, 1, 2 } 65 | * 3.0: {wb, ldr, sm} { 0, 1, 2 } 66 | * 3.1: {wb, ldr, sm} { 0, 1, 2 } 67 | * 4.0: {ldr, sm, wb} { 1, 2, 0 } 68 | * 5.0: {ldr, sm, wb} { 1, 2, 0 } 69 | */ 70 | 71 | static const pkg1_id_t _pkg1_ids[] = { 72 | { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, _secmon_1_patchset }, //1.0.0 73 | { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_2_patchset }, //2.0.0 74 | { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.0 75 | { "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.1 76 | { "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_5_patchset }, //4.0.0 77 | { "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_6_patchset }, //5.0.0 78 | { NULL, 0, 0, 0, 0 } //End. 79 | }; 80 | 81 | typedef struct _pk11_hdr_t 82 | { 83 | u32 magic; 84 | u32 wb_size; 85 | u32 wb_off; 86 | u32 pad; 87 | u32 ldr_size; 88 | u32 ldr_off; 89 | u32 sm_size; 90 | u32 sm_off; 91 | } pk11_hdr_t; 92 | 93 | const pkg1_id_t *pkg1_identify(u8 *pkg1) 94 | { 95 | for (u32 i = 0; _pkg1_ids[i].id; i++) 96 | if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 12)) 97 | return &_pkg1_ids[i]; 98 | return NULL; 99 | } 100 | 101 | void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1) 102 | { 103 | //Decrypt package1. 104 | u8 *pkg11 = pkg1 + id->pkg11_off; 105 | u32 pkg11_size = *(u32 *)pkg11; 106 | se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10); 107 | } 108 | 109 | void pkg1_unpack(void *warmboot_dst, void *secmon_dst, const pkg1_id_t *id, u8 *pkg1) 110 | { 111 | pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20); 112 | 113 | u32 sec_size[3] = { hdr->wb_size, hdr->ldr_size, hdr->sm_size }; 114 | //u32 sec_off[3] = { hdr->wb_off, hdr->ldr_off, hdr->sm_off }; 115 | 116 | u8 *pdata = (u8 *)hdr + sizeof(pk11_hdr_t); 117 | for (u32 i = 0; i < 3; i++) 118 | { 119 | if (id->sec_map[i] == 0 && warmboot_dst) 120 | memcpy(warmboot_dst, pdata, sec_size[id->sec_map[i]]); 121 | else if (id->sec_map[i] == 2 && secmon_dst) 122 | memcpy(secmon_dst, pdata, sec_size[id->sec_map[i]]); 123 | pdata += sec_size[id->sec_map[i]]; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /ipl/pkg1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _PKG1_H_ 18 | #define _PKG1_H_ 19 | 20 | #include "types.h" 21 | 22 | #define PATCHSET_DEF(name, ...) \ 23 | patch_t name[] = { \ 24 | __VA_ARGS__, \ 25 | { 0xFFFFFFFF, 0xFFFFFFFF } \ 26 | } 27 | 28 | typedef struct _patch_t 29 | { 30 | u32 off; 31 | u32 val; 32 | } patch_t; 33 | 34 | typedef struct _pkg1_id_t 35 | { 36 | const char *id; 37 | u32 kb; 38 | u32 tsec_off; 39 | u32 pkg11_off; 40 | u32 sec_map[3]; 41 | u32 secmon_base; 42 | patch_t *secmon_patchset; 43 | } pkg1_id_t; 44 | 45 | const pkg1_id_t *pkg1_identify(u8 *pkg1); 46 | void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); 47 | void pkg1_unpack(void *warmboot_dst, void *secmon_dst, const pkg1_id_t *id, u8 *pkg1); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /ipl/pkg2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | #include "pkg2.h" 19 | #include "heap.h" 20 | #include "se.h" 21 | 22 | /*#include "gfx.h" 23 | extern gfx_ctxt_t gfx_ctxt; 24 | extern gfx_con_t gfx_con; 25 | #define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/ 26 | #define DPRINTF(...) 27 | 28 | static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1) 29 | { 30 | u32 size = sizeof(pkg2_kip1_t); 31 | for (u32 j = 0; j < KIP1_NUM_SECTIONS; j++) 32 | size += kip1->sections[j].size_comp; 33 | return size; 34 | } 35 | 36 | void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2) 37 | { 38 | u8 *ptr = pkg2->data + pkg2->sec_size[PKG2_SEC_KERNEL]; 39 | pkg2_ini1_t *ini1 = (pkg2_ini1_t *)ptr; 40 | ptr += sizeof(pkg2_ini1_t); 41 | 42 | for (u32 i = 0; i < ini1->num_procs; i++) 43 | { 44 | pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr; 45 | pkg2_kip1_info_t *ki = (pkg2_kip1_info_t *)malloc(sizeof(pkg2_kip1_info_t)); 46 | ki->kip1 = kip1; 47 | ki->size = _pkg2_calc_kip1_size(kip1); 48 | list_append(info, &ki->link); 49 | ptr += ki->size; 50 | DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size); 51 | } 52 | } 53 | 54 | int pkg2_has_kip(link_t *info, u64 tid) 55 | { 56 | LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link) 57 | if(ki->kip1->tid == tid) 58 | return 1; 59 | return 0; 60 | } 61 | 62 | void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1) 63 | { 64 | LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link) 65 | if (ki->kip1->tid == tid) 66 | { 67 | ki->kip1 = kip1; 68 | ki->size = _pkg2_calc_kip1_size(kip1); 69 | DPRINTF("replaced kip (new size %08X)\n", ki->size); 70 | return; 71 | } 72 | } 73 | 74 | void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1) 75 | { 76 | pkg2_kip1_info_t *ki = (pkg2_kip1_info_t *)malloc(sizeof(pkg2_kip1_info_t)); 77 | ki->kip1 = kip1; 78 | ki->size = _pkg2_calc_kip1_size(kip1); 79 | DPRINTF("added kip (size %08X)\n", ki->size); 80 | list_append(info, &ki->link); 81 | } 82 | 83 | void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1) 84 | { 85 | if (pkg2_has_kip(info, kip1->tid)) 86 | pkg2_replace_kip(info, kip1->tid, kip1); 87 | else 88 | pkg2_add_kip(info, kip1); 89 | } 90 | 91 | pkg2_hdr_t *pkg2_decrypt(void *data) 92 | { 93 | u8 *pdata = (u8 *)data; 94 | 95 | //Skip signature. 96 | pdata += 0x100; 97 | 98 | pkg2_hdr_t *hdr = (pkg2_hdr_t *)pdata; 99 | 100 | //Skip header. 101 | pdata += sizeof(pkg2_hdr_t); 102 | 103 | //Decrypt header. 104 | se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); 105 | //gfx_hexdump(&gfx_con, (u32)hdr, hdr, 0x100); 106 | 107 | if (hdr->magic != PKG2_MAGIC) 108 | return NULL; 109 | 110 | for (u32 i = 0; i < 4; i++) 111 | { 112 | DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]); 113 | if (!hdr->sec_size[i]) 114 | continue; 115 | 116 | se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]); 117 | //gfx_hexdump(&gfx_con, (u32)pdata, pdata, 0x100); 118 | 119 | pdata += hdr->sec_size[i]; 120 | } 121 | 122 | return hdr; 123 | } 124 | 125 | void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info) 126 | { 127 | u8 *pdst = (u8 *)dst; 128 | 129 | //Signature. 130 | memset(pdst, 0, 0x100); 131 | pdst += 0x100; 132 | 133 | //Header. 134 | pkg2_hdr_t *hdr = (pkg2_hdr_t *)pdst; 135 | memset(hdr, 0, sizeof(pkg2_hdr_t)); 136 | pdst += sizeof(pkg2_hdr_t); 137 | hdr->magic = PKG2_MAGIC; 138 | hdr->base = 0x10000000; 139 | DPRINTF("kernel @ %08X (%08X)\n", (u32)kernel, kernel_size); 140 | 141 | //Kernel. 142 | memcpy(pdst, kernel, kernel_size); 143 | hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size; 144 | hdr->sec_off[PKG2_SEC_KERNEL] = 0x10000000; 145 | se_aes_crypt_ctr(8, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * 0x10]); 146 | pdst += kernel_size; 147 | DPRINTF("kernel encrypted\n"); 148 | 149 | //INI1. 150 | u32 ini1_size = sizeof(pkg2_ini1_t); 151 | pkg2_ini1_t *ini1 = (pkg2_ini1_t *)pdst; 152 | memset(ini1, 0, sizeof(pkg2_ini1_t)); 153 | ini1->magic = INI1_MAGIC; 154 | pdst += sizeof(pkg2_ini1_t); 155 | LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kips_info, link) 156 | { 157 | DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->size); 158 | memcpy(pdst, ki->kip1, ki->size); 159 | pdst += ki->size; 160 | ini1_size += ki->size; 161 | ini1->num_procs++; 162 | } 163 | ini1->size = ini1_size; 164 | hdr->sec_size[PKG2_SEC_INI1] = ini1_size; 165 | hdr->sec_off[PKG2_SEC_INI1] = 0x14080000; 166 | se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * 0x10]); 167 | DPRINTF("INI1 encrypted\n"); 168 | 169 | //Encrypt header. 170 | *(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size; 171 | se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); 172 | memset(hdr->ctr, 0 , 0x10); 173 | *(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size; 174 | } 175 | -------------------------------------------------------------------------------- /ipl/pkg2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _PKG2_H_ 18 | #define _PKG2_H_ 19 | 20 | #include "types.h" 21 | #include "list.h" 22 | 23 | #define PKG2_MAGIC 0x31324B50 24 | #define PKG2_SEC_BASE 0x80000000 25 | #define PKG2_SEC_KERNEL 0 26 | #define PKG2_SEC_INI1 1 27 | 28 | #define INI1_MAGIC 0x31494E49 29 | 30 | typedef struct _pkg2_hdr_t 31 | { 32 | u8 ctr[0x10]; 33 | u8 sec_ctr[0x40]; 34 | u32 magic; 35 | u32 base; 36 | u32 pad0; 37 | u16 version; 38 | u16 pad1; 39 | u32 sec_size[4]; 40 | u32 sec_off[4]; 41 | u8 sec_sha256[0x80]; 42 | u8 data[]; 43 | } pkg2_hdr_t; 44 | 45 | typedef struct _pkg2_ini1_t 46 | { 47 | u32 magic; 48 | u32 size; 49 | u32 num_procs; 50 | u32 pad; 51 | } pkg2_ini1_t; 52 | 53 | typedef struct _pkg2_kip1_sec_t 54 | { 55 | u32 offset; 56 | u32 size_decomp; 57 | u32 size_comp; 58 | u32 attrib; 59 | } pkg2_kip1_sec_t; 60 | 61 | #define KIP1_NUM_SECTIONS 6 62 | 63 | typedef struct _pkg2_kip1_t 64 | { 65 | u32 magic; 66 | u8 name[12]; 67 | u64 tid; 68 | u32 proc_cat; 69 | u8 main_thrd_prio; 70 | u8 def_cpu_core; 71 | u8 res; 72 | u8 flags; 73 | pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS]; 74 | u32 caps[0x20]; 75 | u8 data[]; 76 | } pkg2_kip1_t; 77 | 78 | typedef struct _pkg2_kip1_info_t 79 | { 80 | pkg2_kip1_t *kip1; 81 | u32 size; 82 | link_t link; 83 | } pkg2_kip1_info_t; 84 | 85 | void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2); 86 | int pkg2_has_kip(link_t *info, u64 tid); 87 | void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1); 88 | void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1); 89 | void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1); 90 | 91 | pkg2_hdr_t *pkg2_decrypt(void *data); 92 | void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info); 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /ipl/pmc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _PMC_H_ 18 | #define _PMC_H_ 19 | 20 | /*! PMC registers. */ 21 | #define APBDEV_PMC_PWRGATE_TOGGLE 0x30 22 | #define APBDEV_PMC_PWRGATE_STATUS 0x38 23 | #define APBDEV_PMC_NO_IOPOWER 0x44 24 | #define APBDEV_PMC_SCRATCH0 0x50 25 | #define APBDEV_PMC_SCRATCH1 0x54 26 | #define APBDEV_PMC_SCRATCH20 0xA0 27 | #define APBDEV_PMC_PWR_DET_VAL 0xE4 28 | #define APBDEV_PMC_DDR_PWR 0xE8 29 | #define APBDEV_PMC_CRYPTO_OP 0xF4 30 | #define APBDEV_PMC_OSC_EDPD_OVER 0x1A4 31 | #define APBDEV_PMC_IO_DPD_REQ 0x1B8 32 | #define APBDEV_PMC_IO_DPD2_REQ 0x1C0 33 | #define APBDEV_PMC_VDDP_SEL 0x1CC 34 | #define APBDEV_PMC_TSC_MULT 0x2B4 35 | #define APBDEV_PMC_REG_SHORT 0x2CC 36 | #define APBDEV_PMC_WEAK_BIAS 0x2C8 37 | #define APBDEV_PMC_SECURE_SCRATCH21 0x334 38 | #define APBDEV_PMC_CNTRL2 0x440 39 | #define APBDEV_PMC_IO_DPD4_REQ 0x464 40 | #define APBDEV_PMC_DDR_CNTRL 0x4E4 41 | #define APBDEV_PMC_SCRATCH188 0x810 42 | #define APBDEV_PMC_SCRATCH190 0x818 43 | #define APBDEV_PMC_SCRATCH200 0x840 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /ipl/reloc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | /* 18 | * TODO: the placement of the relocator is a bit fragile atm, maybe we 19 | * should include it in start.S and copy it to some known good 20 | * place in IRAM instead. Basically we want it as far back atm 21 | * as it might be overwritten during relocation. 22 | */ 23 | 24 | .section .text.reloc 25 | .arm 26 | 27 | .globl _reloc_ipl 28 | .type _reloc_ipl, %function 29 | _reloc_ipl: 30 | LDMIA R0!, {R4-R7} 31 | STMIA R1!, {R4-R7} 32 | SUBS R2, #0x10 33 | BNE _reloc_ipl 34 | BX R3 35 | -------------------------------------------------------------------------------- /ipl/sd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * include/linux/mmc/sd.h 3 | * 4 | * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or (at 9 | * your option) any later version. 10 | */ 11 | 12 | #ifndef LINUX_MMC_SD_H 13 | #define LINUX_MMC_SD_H 14 | 15 | /* SD commands type argument response */ 16 | /* class 0 */ 17 | /* This is basically the same command as for MMC with some quirks. */ 18 | #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ 19 | #define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ 20 | #define SD_SWITCH_VOLTAGE 11 /* ac R1 */ 21 | 22 | /* class 10 */ 23 | #define SD_SWITCH 6 /* adtc [31:0] See below R1 */ 24 | 25 | /* class 5 */ 26 | #define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ 27 | #define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ 28 | 29 | /* Application commands */ 30 | #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ 31 | #define SD_APP_SD_STATUS 13 /* adtc R1 */ 32 | #define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ 33 | #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ 34 | #define SD_APP_SET_CLR_CARD_DETECT 42 35 | #define SD_APP_SEND_SCR 51 /* adtc R1 */ 36 | 37 | /* OCR bit definitions */ 38 | #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ 39 | #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ 40 | #define SD_OCR_XPC (1 << 28) /* SDXC power control */ 41 | #define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ 42 | 43 | /* 44 | * SD_SWITCH argument format: 45 | * 46 | * [31] Check (0) or switch (1) 47 | * [30:24] Reserved (0) 48 | * [23:20] Function group 6 49 | * [19:16] Function group 5 50 | * [15:12] Function group 4 51 | * [11:8] Function group 3 52 | * [7:4] Function group 2 53 | * [3:0] Function group 1 54 | */ 55 | 56 | /* 57 | * SD_SEND_IF_COND argument format: 58 | * 59 | * [31:12] Reserved (0) 60 | * [11:8] Host Voltage Supply Flags 61 | * [7:0] Check Pattern (0xAA) 62 | */ 63 | 64 | /* 65 | * SCR field definitions 66 | */ 67 | 68 | #define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ 69 | #define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ 70 | #define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ 71 | 72 | /* 73 | * SD bus widths 74 | */ 75 | #define SD_BUS_WIDTH_1 0 76 | #define SD_BUS_WIDTH_4 2 77 | 78 | /* 79 | * SD_SWITCH mode 80 | */ 81 | #define SD_SWITCH_CHECK 0 82 | #define SD_SWITCH_SET 1 83 | 84 | /* 85 | * SD_SWITCH function groups 86 | */ 87 | #define SD_SWITCH_GRP_ACCESS 0 88 | 89 | /* 90 | * SD_SWITCH access modes 91 | */ 92 | #define SD_SWITCH_ACCESS_DEF 0 93 | #define SD_SWITCH_ACCESS_HS 1 94 | 95 | #endif /* LINUX_MMC_SD_H */ 96 | -------------------------------------------------------------------------------- /ipl/sdmmc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _SDMMC_H_ 18 | #define _SDMMC_H_ 19 | 20 | #include "types.h" 21 | #include "sdmmc_driver.h" 22 | 23 | /*! SDMMC storage context. */ 24 | typedef struct _sdmmc_storage_t 25 | { 26 | sdmmc_t *sdmmc; 27 | u32 rca; 28 | int has_sector_access; 29 | u32 sec_cnt; 30 | int is_low_voltage; 31 | u32 partition; 32 | u8 cid[0x10]; 33 | u8 csd[0x10]; 34 | u8 scr[8]; 35 | } sdmmc_storage_t; 36 | 37 | int sdmmc_storage_end(sdmmc_storage_t *storage); 38 | int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); 39 | int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); 40 | int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type); 41 | int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); 42 | int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type); 43 | int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /ipl/sdmmc_driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _SDMMC_DRIVER_H_ 18 | #define _SDMMC_DRIVER_H_ 19 | 20 | #include "types.h" 21 | #include "sdmmc_t210.h" 22 | 23 | /*! SDMMC controller IDs. */ 24 | #define SDMMC_1 0 25 | #define SDMMC_2 1 26 | #define SDMMC_3 2 27 | #define SDMMC_4 3 28 | 29 | /*! SDMMC power types. */ 30 | #define SDMMC_POWER_OFF 0 31 | #define SDMMC_POWER_1_8 1 32 | #define SDMMC_POWER_3_3 2 33 | 34 | /*! SDMMC bus widths. */ 35 | #define SDMMC_BUS_WIDTH_1 0 36 | #define SDMMC_BUS_WIDTH_4 1 37 | #define SDMMC_BUS_WIDTH_8 2 38 | 39 | /*! SDMMC response types. */ 40 | #define SDMMC_RSP_TYPE_0 0 41 | #define SDMMC_RSP_TYPE_1 1 42 | #define SDMMC_RSP_TYPE_2 2 43 | #define SDMMC_RSP_TYPE_3 3 44 | #define SDMMC_RSP_TYPE_4 4 45 | #define SDMMC_RSP_TYPE_5 5 46 | 47 | /*! SDMMC mask interrupt status. */ 48 | #define SDMMC_MASKINT_MASKED 0 49 | #define SDMMC_MASKINT_NOERROR -1 50 | #define SDMMC_MASKINT_ERROR -2 51 | 52 | /*! Helper for SWITCH command argument. */ 53 | #define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8)) 54 | 55 | /*! SDMMC controller context. */ 56 | typedef struct _sdmmc_t 57 | { 58 | t210_sdmmc_t *regs; 59 | u32 id; 60 | u32 divisor; 61 | u32 clock_stopped; 62 | int no_sd; 63 | int sd_clock_enabled; 64 | int venclkctl_set; 65 | u32 venclkctl_tap; 66 | u32 expected_rsp_type; 67 | u32 dma_addr_next; 68 | u32 rsp[4]; 69 | u32 rsp3; 70 | } sdmmc_t; 71 | 72 | /*! SDMMC command. */ 73 | typedef struct _sdmmc_cmd_t 74 | { 75 | u16 cmd; 76 | u32 arg; 77 | u32 rsp_type; 78 | u32 check_busy; 79 | } sdmmc_cmd_t; 80 | 81 | /*! SDMMC request. */ 82 | typedef struct _sdmmc_req_t 83 | { 84 | void *buf; 85 | u32 blksize; 86 | u32 num_sectors; 87 | int is_write; 88 | int is_multi_block; 89 | int is_auto_cmd12; 90 | } sdmmc_req_t; 91 | 92 | int sdmmc_get_voltage(sdmmc_t *sdmmc); 93 | u32 sdmmc_get_bus_width(sdmmc_t *sdmmc); 94 | void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width); 95 | void sdmmc_get_venclkctl(sdmmc_t *sdmmc); 96 | int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type); 97 | void sdmmc_sd_clock_ctrl(sdmmc_t *sdmmc, int no_sd); 98 | int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type); 99 | int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd); 100 | int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp); 101 | int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int no_sd); 102 | void sdmmc_end(sdmmc_t *sdmmc); 103 | void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy); 104 | int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out); 105 | int sdmmc_enable_low_voltage(sdmmc_t *sdmmc); 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /ipl/sdmmc_t210.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _SDMMC_T210_H_ 18 | #define _SDMMC_T210_H_ 19 | 20 | #include "types.h" 21 | 22 | #define TEGRA_MMC_PWRCTL_SD_BUS_POWER 0x1 23 | #define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 0xA 24 | #define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 0xC 25 | #define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 0xE 26 | #define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_MASK 0xF1 27 | 28 | #define TEGRA_MMC_HOSTCTL_1BIT 0x00 29 | #define TEGRA_MMC_HOSTCTL_4BIT 0x02 30 | #define TEGRA_MMC_HOSTCTL_8BIT 0x20 31 | 32 | #define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE 0x1 33 | #define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE 0x2 34 | #define TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE 0x4 35 | #define TEGRA_MMC_CLKCON_CLKGEN_SELECT 0x20 36 | 37 | #define TEGRA_MMC_SWRST_SW_RESET_FOR_ALL 0x1 38 | #define TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE 0x2 39 | #define TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE 0x4 40 | 41 | #define TEGRA_MMC_TRNMOD_DMA_ENABLE 0x1 42 | #define TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE 0x2 43 | #define TEGRA_MMC_TRNMOD_AUTO_CMD12 0x4 44 | #define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_WRITE 0x0 45 | #define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ 0x10 46 | #define TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT 0x20 47 | 48 | #define TEGRA_MMC_TRNMOD_CMD_CRC_CHECK 0x8 49 | #define TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK 0x10 50 | #define TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER 0x20 51 | 52 | #define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_MASK 0x3 53 | #define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE 0x0 54 | #define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136 0x1 55 | #define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48 0x2 56 | #define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY 0x3 57 | 58 | #define TEGRA_MMC_NORINTSTS_CMD_COMPLETE 0x1 59 | #define TEGRA_MMC_NORINTSTS_XFER_COMPLETE 0x2 60 | #define TEGRA_MMC_NORINTSTS_DMA_INTERRUPT 0x8 61 | #define TEGRA_MMC_NORINTSTS_ERR_INTERRUPT 0x8000 62 | #define TEGRA_MMC_NORINTSTS_CMD_TIMEOUT 0x10000 63 | 64 | #define TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY 0x20 65 | 66 | typedef struct _t210_sdmmc_t 67 | { 68 | vu32 sysad; 69 | vu16 blksize; 70 | vu16 blkcnt; 71 | vu32 argument; 72 | vu16 trnmod; 73 | vu16 cmdreg; 74 | vu32 rspreg0; 75 | vu32 rspreg1; 76 | vu32 rspreg2; 77 | vu32 rspreg3; 78 | vu32 bdata; 79 | vu32 prnsts; 80 | vu8 hostctl; 81 | vu8 pwrcon; 82 | vu8 blkgap; 83 | vu8 wakcon; 84 | vu16 clkcon; 85 | vu8 timeoutcon; 86 | vu8 swrst; 87 | vu16 norintsts; 88 | vu16 errintsts; 89 | vu16 norintstsen; 90 | vu16 errintstsen; 91 | vu16 norintsigen; 92 | vu16 errintsigen; 93 | vu16 acmd12errsts; 94 | vu16 hostctl2; 95 | vu32 capareg; 96 | vu32 capareg_1; 97 | vu32 maxcurr; 98 | vu8 res3[4]; 99 | vu16 setacmd12err; 100 | vu16 setinterr; 101 | vu8 admaerr; 102 | vu8 res4[3]; 103 | vu32 admaaddr; 104 | vu32 admaaddr_hi; 105 | vu8 res5[156]; 106 | vu16 slotintstatus; 107 | vu16 hcver; 108 | vu32 venclkctl; 109 | vu32 venspictl; 110 | vu32 venspiintsts; 111 | vu32 venceatactl; 112 | vu32 venbootctl; 113 | vu32 venbootacktout; 114 | vu32 venbootdattout; 115 | vu32 vendebouncecnt; 116 | vu32 venmiscctl; 117 | vu32 res6[34]; 118 | vu32 field_1AC; 119 | vu32 field_1B0; 120 | vu8 res7[8]; 121 | vu32 field_1BC; 122 | vu32 field_1C0; 123 | vu32 field_1C4; 124 | vu8 field_1C8[24]; 125 | vu32 sdmemcmppadctl; 126 | vu32 autocalcfg; 127 | vu32 autocalintval; 128 | vu32 autocalsts; 129 | vu32 field_1F0; 130 | } t210_sdmmc_t; 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /ipl/sdram.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _SDRAM_H_ 18 | #define _SDRAM_H_ 19 | 20 | void sdram_init(); 21 | const void *sdram_get_params(); 22 | void sdram_lp0_save_params(const void *params); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /ipl/sdram_lz.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | static const u8 _dram_cfg_lz[1262] = { 18 | 0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 19 | 0x00, 0x2C, 0x17, 0x04, 0x09, 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, 20 | 0x17, 0x10, 0x10, 0x00, 0x00, 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 21 | 0x00, 0x04, 0xB4, 0x01, 0x70, 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 22 | 0x70, 0x17, 0x10, 0x24, 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 23 | 0x00, 0x00, 0x00, 0x17, 0x04, 0x04, 0x17, 0x09, 0x18, 0xFF, 0xFF, 0x1F, 24 | 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x77, 25 | 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, 0x17, 0x08, 0x08, 0xA6, 0xA6, 26 | 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x04, 0x04, 27 | 0x04, 0x04, 0x17, 0x04, 0x04, 0x17, 0x04, 0x3C, 0x1F, 0x1F, 0x1F, 0x1F, 28 | 0x17, 0x04, 0x04, 0x17, 0x06, 0x06, 0x00, 0x00, 0x04, 0x08, 0x17, 0x06, 29 | 0x46, 0xA1, 0x01, 0x00, 0x00, 0x32, 0x17, 0x0B, 0x64, 0x01, 0x17, 0x04, 30 | 0x7C, 0x17, 0x07, 0x0C, 0x03, 0x17, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1E, 31 | 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13, 32 | 0x17, 0x0B, 0x2C, 0x09, 0x00, 0x00, 0x00, 0x17, 0x05, 0x5D, 0x17, 0x07, 33 | 0x10, 0x0B, 0x17, 0x07, 0x28, 0x08, 0x17, 0x07, 0x0C, 0x17, 0x04, 0x1C, 34 | 0x20, 0x00, 0x00, 0x00, 0x06, 0x17, 0x04, 0x04, 0x17, 0x07, 0x08, 0x17, 35 | 0x04, 0x50, 0x17, 0x04, 0x2C, 0x17, 0x04, 0x1C, 0x17, 0x04, 0x10, 0x17, 36 | 0x08, 0x6C, 0x17, 0x04, 0x10, 0x17, 0x04, 0x38, 0x17, 0x04, 0x40, 0x05, 37 | 0x17, 0x07, 0x1C, 0x17, 0x08, 0x58, 0x17, 0x04, 0x24, 0x17, 0x04, 0x18, 38 | 0x17, 0x08, 0x64, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 39 | 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x09, 0x0C, 0x17, 0x05, 0x82, 40 | 0x58, 0x17, 0x07, 0x61, 0xC1, 0x17, 0x07, 0x50, 0x17, 0x04, 0x04, 0x17, 41 | 0x08, 0x81, 0x48, 0x17, 0x04, 0x04, 0x17, 0x04, 0x28, 0x17, 0x04, 0x60, 42 | 0x17, 0x08, 0x54, 0x27, 0x17, 0x04, 0x04, 0x17, 0x07, 0x14, 0x17, 0x04, 43 | 0x04, 0x04, 0x17, 0x07, 0x81, 0x58, 0x17, 0x0C, 0x0C, 0x1C, 0x03, 0x00, 44 | 0x00, 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x17, 0x04, 0x5A, 0xF3, 0x0C, 45 | 0x04, 0x05, 0x1B, 0x06, 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 46 | 0x08, 0x1D, 0x09, 0x0A, 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 47 | 0x02, 0x1B, 0x1C, 0x23, 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 48 | 0x0A, 0x0B, 0x1D, 0x0D, 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 49 | 0x24, 0x06, 0x07, 0x9A, 0x12, 0x17, 0x05, 0x83, 0x41, 0x00, 0xFF, 0x17, 50 | 0x10, 0x83, 0x6C, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 51 | 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 52 | 0x00, 0x0B, 0x08, 0x72, 0x72, 0x0E, 0x0C, 0x17, 0x04, 0x20, 0x08, 0x08, 53 | 0x0D, 0x0C, 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x17, 0x06, 54 | 0x2C, 0x11, 0x08, 0x17, 0x10, 0x84, 0x67, 0x15, 0x00, 0xCC, 0x00, 0x0A, 55 | 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, 0xFF, 56 | 0x0F, 0xFF, 0x0F, 0x17, 0x08, 0x83, 0x4C, 0x01, 0x03, 0x00, 0x70, 0x00, 57 | 0x0C, 0x00, 0x01, 0x17, 0x04, 0x0C, 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 58 | 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, 0x17, 0x04, 0x10, 0xA0, 0x00, 0x2C, 59 | 0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x80, 0x17, 0x06, 0x48, 0x08, 0x00, 60 | 0x04, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 61 | 0x28, 0x28, 0x17, 0x04, 0x04, 0x11, 0x11, 0x11, 0x11, 0x17, 0x04, 0x04, 62 | 0xBE, 0x00, 0x00, 0x17, 0x05, 0x58, 0x17, 0x08, 0x5C, 0x17, 0x22, 0x85, 63 | 0x6A, 0x17, 0x1A, 0x1A, 0x14, 0x00, 0x12, 0x00, 0x10, 0x17, 0x05, 0x83, 64 | 0x0A, 0x17, 0x16, 0x18, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 65 | 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x17, 0x05, 0x83, 0x0C, 0x17, 66 | 0x04, 0x20, 0x17, 0x18, 0x18, 0x28, 0x00, 0x28, 0x17, 0x04, 0x04, 0x17, 67 | 0x08, 0x08, 0x17, 0x10, 0x10, 0x00, 0x14, 0x17, 0x05, 0x5A, 0x17, 0x04, 68 | 0x5C, 0x17, 0x04, 0x5E, 0x17, 0x04, 0x0E, 0x17, 0x0E, 0x78, 0x17, 0x09, 69 | 0x82, 0x50, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 70 | 0x17, 0x08, 0x18, 0x80, 0x01, 0x00, 0x00, 0x40, 0x17, 0x04, 0x20, 0x03, 71 | 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, 0x11, 0x17, 0x08, 0x82, 0x58, 72 | 0x17, 0x0C, 0x38, 0x17, 0x1B, 0x81, 0x6C, 0x17, 0x08, 0x85, 0x60, 0x17, 73 | 0x08, 0x86, 0x50, 0x17, 0x08, 0x86, 0x60, 0x17, 0x06, 0x83, 0x21, 0x22, 74 | 0x04, 0xFF, 0xFF, 0xAF, 0x4F, 0x17, 0x0C, 0x86, 0x74, 0x17, 0x08, 0x2C, 75 | 0x8B, 0xFF, 0x07, 0x17, 0x06, 0x81, 0x04, 0x32, 0x54, 0x76, 0x10, 0x47, 76 | 0x32, 0x65, 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 77 | 0x64, 0x32, 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 78 | 0x32, 0x67, 0x17, 0x04, 0x24, 0x49, 0x92, 0x24, 0x17, 0x04, 0x04, 0x17, 79 | 0x11, 0x7C, 0x1B, 0x17, 0x04, 0x04, 0x17, 0x13, 0x81, 0x14, 0x2F, 0x41, 80 | 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x17, 0x04, 0x7C, 0xFF, 0xFF, 0xFF, 81 | 0x7F, 0x0B, 0xD7, 0x06, 0x40, 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 82 | 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x17, 0x06, 0x86, 0x59, 83 | 0x17, 0x0F, 0x89, 0x14, 0x37, 0x17, 0x07, 0x82, 0x72, 0x10, 0x17, 0x06, 84 | 0x83, 0x0D, 0x00, 0x11, 0x01, 0x17, 0x05, 0x85, 0x39, 0x17, 0x04, 0x0E, 85 | 0x0A, 0x17, 0x07, 0x89, 0x29, 0x17, 0x04, 0x1B, 0x17, 0x08, 0x86, 0x77, 86 | 0x17, 0x09, 0x12, 0x20, 0x00, 0x00, 0x00, 0x81, 0x10, 0x09, 0x28, 0x93, 87 | 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, 0x17, 0x18, 0x82, 0x2C, 0xFF, 88 | 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0x17, 0x04, 0x04, 0xDC, 0xDC, 89 | 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x17, 0x04, 0x04, 0x17, 0x04, 0x04, 90 | 0x17, 0x05, 0x82, 0x24, 0x03, 0x07, 0x17, 0x04, 0x04, 0x00, 0x00, 0x24, 91 | 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 92 | 0x9C, 0x4B, 0x17, 0x04, 0x64, 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 93 | 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x17, 0x06, 0x85, 0x60, 0x17, 94 | 0x10, 0x82, 0x74, 0x17, 0x08, 0x08, 0x17, 0x08, 0x88, 0x00, 0x17, 0x04, 95 | 0x10, 0x04, 0x17, 0x0B, 0x87, 0x6C, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 96 | 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x17, 0x08, 0x8B, 0x18, 97 | 0x1F, 0x17, 0x09, 0x81, 0x73, 0x00, 0xFF, 0x00, 0xFF, 0x17, 0x05, 0x86, 98 | 0x48, 0x17, 0x04, 0x0C, 0x17, 0x07, 0x86, 0x34, 0x00, 0x00, 0xF0, 0x17, 99 | 0x09, 0x87, 0x54, 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x17, 0x0C, 0x81, 100 | 0x52, 0x17, 0x0A, 0x1C, 0x17, 0x10, 0x81, 0x6C, 0x17, 0x0A, 0x82, 0x21, 101 | 0x17, 0x07, 0x82, 0x4D, 0x17, 0x0A, 0x8A, 0x1B, 0x17, 0x11, 0x2C, 0x76, 102 | 0x0C, 0x17, 0x0A, 0x8A, 0x67, 0x17, 0x0F, 0x84, 0x28, 0x17, 0x06, 0x34, 103 | 0x17, 0x17, 0x3A, 0x7E, 0x16, 0x40, 0x17, 0x0C, 0x8B, 0x1F, 0x17, 0x2A, 104 | 0x38, 0x1E, 0x17, 0x0A, 0x38, 0x17, 0x13, 0x81, 0x28, 0x00, 0xC0, 0x17, 105 | 0x17, 0x55, 0x46, 0x24, 0x17, 0x0A, 0x81, 0x28, 0x17, 0x14, 0x38, 0x17, 106 | 0x18, 0x81, 0x60, 0x46, 0x2C, 0x17, 0x06, 0x38, 0xEC, 0x17, 0x0D, 0x16, 107 | 0x17, 0x0E, 0x82, 0x3C, 0x17, 0x82, 0x0C, 0x8E, 0x68, 0x17, 0x04, 0x24, 108 | 0x17, 0x5C, 0x8E, 0x68, 0x17, 0x07, 0x82, 0x5F, 0x80, 0x17, 0x87, 0x01, 109 | 0x8E, 0x68, 0x02, 0x17, 0x81, 0x4A, 0x8E, 0x68, 0x17, 0x0C, 0x87, 0x78, 110 | 0x17, 0x85, 0x28, 0x8E, 0x68, 0x17, 0x8E, 0x68, 0x9D, 0x50, 0x17, 0x81, 111 | 0x24, 0x8E, 0x68, 0x17, 0x04, 0x2C, 0x17, 0x28, 0x8E, 0x68, 0x17, 0x04, 112 | 0x30, 0x17, 0x85, 0x3C, 0x8E, 0x68, 0x12, 0x17, 0x07, 0x85, 0x70, 0x17, 113 | 0x88, 0x74, 0x8E, 0x68, 0x17, 0x87, 0x3E, 0x9D, 0x50, 0x0C, 0x17, 0x04, 114 | 0x04, 0x17, 0x12, 0x8E, 0x68, 0x18, 0x17, 0x87, 0x12, 0xBB, 0x20, 0x17, 115 | 0x83, 0x04, 0x9D, 0x50, 0x15, 0x17, 0x05, 0x8D, 0x76, 0x17, 0x0F, 0x8B, 116 | 0x49, 0x17, 0x0B, 0x18, 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 117 | 0x34, 0x00, 0x36, 0x00, 0x2F, 0x00, 0x33, 0x17, 0x09, 0x84, 0x0C, 0x17, 118 | 0x18, 0x18, 0x17, 0x20, 0x8E, 0x68, 0x15, 0x17, 0x07, 0x5A, 0x17, 0x06, 119 | 0x5E, 0x16, 0x00, 0x15, 0x17, 0x82, 0x40, 0x9D, 0x50, 0x17, 0x86, 0x5F, 120 | 0xBB, 0x20, 0x3A, 0x00, 0x00, 0x00, 0x1D, 0x17, 0x81, 0x4F, 0xAC, 0x38, 121 | 0x3B, 0x17, 0x04, 0x04, 0x17, 0x86, 0x30, 0x8E, 0x68, 0x17, 0x81, 0x53, 122 | 0xAC, 0x38, 0x07, 0x17, 0x0D, 0x8E, 0x68, 0xA3, 0x72, 0x17, 0x83, 0x10, 123 | 0x8E, 0x68 124 | }; 125 | -------------------------------------------------------------------------------- /ipl/se.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | #include "se.h" 19 | #include "heap.h" 20 | #include "t210.h" 21 | #include "se_t210.h" 22 | 23 | typedef struct _se_ll_t 24 | { 25 | vu32 num; 26 | vu32 addr; 27 | vu32 size; 28 | } se_ll_t; 29 | 30 | static void _gf256_mul_x(void *block) 31 | { 32 | u8 *pdata = (u8 *)block; 33 | u32 carry = 0; 34 | 35 | for (u32 i = 0xF; i >= 0; i--) 36 | { 37 | u8 b = pdata[i]; 38 | pdata[i] = (b << 1) | carry; 39 | carry = b >> 7; 40 | } 41 | 42 | if (carry) 43 | pdata[0xF] ^= 0x87; 44 | } 45 | 46 | static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size) 47 | { 48 | ll->num = 0; 49 | ll->addr = addr; 50 | ll->size = size; 51 | } 52 | 53 | static void _se_ll_set(se_ll_t *dst, se_ll_t *src) 54 | { 55 | SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src; 56 | SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst; 57 | } 58 | 59 | static int _se_wait() 60 | { 61 | while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET))) 62 | ; 63 | if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) || 64 | SE(SE_STATUS_0) & 3 || 65 | SE(SE_ERR_STATUS_0) != 0) 66 | return 0; 67 | return 1; 68 | } 69 | 70 | static int _se_execute(u32 op, void *dst, u32 dst_size, void *src, u32 src_size) 71 | { 72 | se_ll_t *ll_dst = NULL, *ll_src = NULL; 73 | 74 | if (dst) 75 | { 76 | ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t)); 77 | _se_ll_init(ll_dst, (u32)dst, dst_size); 78 | } 79 | 80 | if (src) 81 | { 82 | ll_src = (se_ll_t *)malloc(sizeof(se_ll_t)); 83 | _se_ll_init(ll_src, (u32)src, src_size); 84 | } 85 | 86 | _se_ll_set(ll_dst, ll_src); 87 | 88 | SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0); 89 | SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET); 90 | SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); 91 | 92 | int res = _se_wait(); 93 | 94 | if (src) 95 | free(ll_src); 96 | if (dst) 97 | free(ll_dst); 98 | 99 | return res; 100 | } 101 | 102 | static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, void *src, u32 src_size) 103 | { 104 | u8 *block = (u8 *)malloc(0x10); 105 | memset(block, 0, 0x10); 106 | 107 | SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; 108 | 109 | memcpy(block, src, src_size); 110 | int res = _se_execute(op, block, 0x10, block, 0x10); 111 | memcpy(dst, block, dst_size); 112 | 113 | free(block); 114 | return res; 115 | } 116 | 117 | static void _se_aes_ctr_set(void *ctr) 118 | { 119 | u32 *data = (u32 *)ctr; 120 | for (u32 i = 0; i < 4; i++) 121 | SE(SE_CRYPTO_CTR_REG_OFFSET + 4 * i) = data[i]; 122 | } 123 | 124 | void se_rsa_acc_ctrl(u32 rs, u32 flags) 125 | { 126 | if (flags & 0x7F) 127 | SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = ((flags >> 4) & 4 | flags & 3) ^ 7; 128 | if (flags & 0x80) 129 | SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs); 130 | } 131 | 132 | void se_key_acc_ctrl(u32 ks, u32 flags) 133 | { 134 | if (flags & 0x7F) 135 | SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; 136 | if (flags & 0x80) 137 | SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks); 138 | } 139 | 140 | void se_aes_key_set(u32 ks, void *key, u32 size) 141 | { 142 | u32 *data = (u32 *)key; 143 | for (u32 i = 0; i < size / 4; i++) 144 | { 145 | SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; 146 | SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; 147 | } 148 | } 149 | 150 | void se_aes_key_clear(u32 ks) 151 | { 152 | for (u32 i = 0; i < TEGRA_SE_AES_MAX_KEY_SIZE / 4; i++) 153 | { 154 | SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; 155 | SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; 156 | } 157 | } 158 | 159 | int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, void *input) 160 | { 161 | SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB); 162 | SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); 163 | SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); 164 | return _se_execute(OP_START, NULL, 0, input, 0x10); 165 | } 166 | 167 | int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, void *src) 168 | { 169 | if (enc) 170 | { 171 | SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); 172 | SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); 173 | } 174 | else 175 | { 176 | SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); 177 | SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); 178 | } 179 | SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; 180 | return _se_execute(OP_START, dst, 0x10, src, 0x10); 181 | } 182 | 183 | int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, void *src, u32 src_size, void *ctr) 184 | { 185 | SE(SE_SPARE_0_REG_OFFSET) = 1; 186 | SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); 187 | SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | 188 | SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1); 189 | _se_aes_ctr_set(ctr); 190 | 191 | u32 src_size_aligned = src_size & 0xFFFFFFF0; 192 | u32 src_size_delta = src_size & 0xF; 193 | 194 | if (src_size_aligned) 195 | { 196 | SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; 197 | if (!_se_execute(OP_START, dst, dst_size, src, src_size_aligned)) 198 | return 0; 199 | } 200 | 201 | if (src_size - src_size_aligned && src_size_aligned < dst_size) 202 | return _se_execute_one_block(OP_START, dst + src_size_aligned, 203 | MIN(src_size_delta, dst_size - src_size_aligned), 204 | src + src_size_aligned, src_size_delta); 205 | 206 | return 1; 207 | } 208 | 209 | int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize) 210 | { 211 | int res = 0; 212 | u8 *tweak = (u8 *)malloc(0x10); 213 | u8 *pdst = (u8 *)dst; 214 | u8 *psrc = (u8 *)src; 215 | 216 | //Generate tweak. 217 | for (int i = 0xF; i >= 0; i--) 218 | { 219 | tweak[i] = sec & 0xFF; 220 | sec >>= 8; 221 | } 222 | if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak)) 223 | goto out; 224 | 225 | //We are assuming a 0x10-aligned sector size in this implementation. 226 | for (u32 i = 0; i < secsize / 0x10; i++) 227 | { 228 | for (u32 j = 0; j < 0x10; j++) 229 | pdst[j] = psrc[j] ^ tweak[j]; 230 | if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst)) 231 | goto out; 232 | for (u32 j = 0; j < 0x10; j++) 233 | pdst[j] = pdst[j] ^ tweak[j]; 234 | _gf256_mul_x(tweak); 235 | psrc += 0x10; 236 | pdst += 0x10; 237 | } 238 | 239 | res = 1; 240 | 241 | out:; 242 | free(tweak); 243 | return res; 244 | } 245 | 246 | int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs) 247 | { 248 | u8 *pdst = (u8 *)dst; 249 | u8 *psrc = (u8 *)src; 250 | 251 | for (u32 i = 0; i < num_secs; i++) 252 | if (!se_aes_xts_crypt_sec(ks1, ks2, enc, sec + i, pdst + secsize * i, psrc + secsize * i, secsize)) 253 | return 0; 254 | 255 | return 1; 256 | } 257 | -------------------------------------------------------------------------------- /ipl/se.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _SE_H_ 18 | #define _SE_H_ 19 | 20 | #include "types.h" 21 | 22 | void se_rsa_acc_ctrl(u32 rs, u32 flags); 23 | void se_key_acc_ctrl(u32 ks, u32 flags); 24 | void se_aes_key_set(u32 ks, void *key, u32 size); 25 | void se_aes_key_clear(u32 ks); 26 | int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, void *input); 27 | int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, void *src); 28 | int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, void *src, u32 src_size, void *ctr); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /ipl/se_t210.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Driver for Tegra Security Engine 3 | * 4 | * Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved. 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | * more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef _CRYPTO_TEGRA_SE_H 22 | #define _CRYPTO_TEGRA_SE_H 23 | 24 | #include "types.h" 25 | 26 | #define TEGRA_SE_CRA_PRIORITY 300 27 | #define TEGRA_SE_COMPOSITE_PRIORITY 400 28 | #define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50 29 | #define SE_MAX_SRC_SG_COUNT 50 30 | #define SE_MAX_DST_SG_COUNT 50 31 | 32 | #define TEGRA_SE_KEYSLOT_COUNT 16 33 | #define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF 34 | 35 | /* SE register definitions */ 36 | #define SE_SECURITY_0 0x000 37 | #define SE_KEY_SCHED_READ_SHIFT 3 38 | 39 | #define SE_CONFIG_REG_OFFSET 0x014 40 | #define SE_CONFIG_ENC_ALG_SHIFT 12 41 | #define SE_CONFIG_DEC_ALG_SHIFT 8 42 | #define ALG_AES_ENC 1 43 | #define ALG_RNG 2 44 | #define ALG_SHA 3 45 | #define ALG_RSA 4 46 | #define ALG_NOP 0 47 | #define ALG_AES_DEC 1 48 | #define SE_CONFIG_ENC_ALG(x) (x << SE_CONFIG_ENC_ALG_SHIFT) 49 | #define SE_CONFIG_DEC_ALG(x) (x << SE_CONFIG_DEC_ALG_SHIFT) 50 | #define SE_CONFIG_DST_SHIFT 2 51 | #define DST_MEMORY 0 52 | #define DST_HASHREG 1 53 | #define DST_KEYTAB 2 54 | #define DST_SRK 3 55 | #define DST_RSAREG 4 56 | #define SE_CONFIG_DST(x) (x << SE_CONFIG_DST_SHIFT) 57 | #define SE_CONFIG_ENC_MODE_SHIFT 24 58 | #define SE_CONFIG_DEC_MODE_SHIFT 16 59 | #define MODE_KEY128 0 60 | #define MODE_KEY192 1 61 | #define MODE_KEY256 2 62 | #define MODE_SHA1 0 63 | #define MODE_SHA224 4 64 | #define MODE_SHA256 5 65 | #define MODE_SHA384 6 66 | #define MODE_SHA512 7 67 | #define SE_CONFIG_ENC_MODE(x) (x << SE_CONFIG_ENC_MODE_SHIFT) 68 | #define SE_CONFIG_DEC_MODE(x) (x << SE_CONFIG_DEC_MODE_SHIFT) 69 | 70 | #define SE_RNG_CONFIG_REG_OFFSET 0x340 71 | #define DRBG_MODE_SHIFT 0 72 | #define DRBG_MODE_NORMAL 0 73 | #define DRBG_MODE_FORCE_INSTANTION 1 74 | #define DRBG_MODE_FORCE_RESEED 2 75 | #define SE_RNG_CONFIG_MODE(x) (x << DRBG_MODE_SHIFT) 76 | 77 | #define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344 78 | #define DRBG_RO_ENT_SRC_SHIFT 1 79 | #define DRBG_RO_ENT_SRC_ENABLE 1 80 | #define DRBG_RO_ENT_SRC_DISABLE 0 81 | #define SE_RNG_SRC_CONFIG_RO_ENT_SRC(x) (x << DRBG_RO_ENT_SRC_SHIFT) 82 | #define DRBG_RO_ENT_SRC_LOCK_SHIFT 0 83 | #define DRBG_RO_ENT_SRC_LOCK_ENABLE 1 84 | #define DRBG_RO_ENT_SRC_LOCK_DISABLE 0 85 | #define SE_RNG_SRC_CONFIG_RO_ENT_SRC_LOCK(x) (x << DRBG_RO_ENT_SRC_LOCK_SHIFT) 86 | 87 | #define DRBG_SRC_SHIFT 2 88 | #define DRBG_SRC_NONE 0 89 | #define DRBG_SRC_ENTROPY 1 90 | #define DRBG_SRC_LFSR 2 91 | #define SE_RNG_CONFIG_SRC(x) (x << DRBG_SRC_SHIFT) 92 | 93 | #define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348 94 | 95 | #define SE_KEYTABLE_REG_OFFSET 0x31c 96 | #define SE_KEYTABLE_SLOT_SHIFT 4 97 | #define SE_KEYTABLE_SLOT(x) (x << SE_KEYTABLE_SLOT_SHIFT) 98 | #define SE_KEYTABLE_QUAD_SHIFT 2 99 | #define QUAD_KEYS_128 0 100 | #define QUAD_KEYS_192 1 101 | #define QUAD_KEYS_256 1 102 | #define QUAD_ORG_IV 2 103 | #define QUAD_UPDTD_IV 3 104 | #define SE_KEYTABLE_QUAD(x) (x << SE_KEYTABLE_QUAD_SHIFT) 105 | #define SE_KEYTABLE_OP_TYPE_SHIFT 9 106 | #define OP_READ 0 107 | #define OP_WRITE 1 108 | #define SE_KEYTABLE_OP_TYPE(x) (x << SE_KEYTABLE_OP_TYPE_SHIFT) 109 | #define SE_KEYTABLE_TABLE_SEL_SHIFT 8 110 | #define TABLE_KEYIV 0 111 | #define TABLE_SCHEDULE 1 112 | #define SE_KEYTABLE_TABLE_SEL(x) (x << SE_KEYTABLE_TABLE_SEL_SHIFT) 113 | #define SE_KEYTABLE_PKT_SHIFT 0 114 | #define SE_KEYTABLE_PKT(x) (x << SE_KEYTABLE_PKT_SHIFT) 115 | 116 | #define SE_OP_DONE_SHIFT 4 117 | #define OP_DONE 1 118 | #define SE_OP_DONE(x, y) ((x) && (y << SE_OP_DONE_SHIFT)) 119 | 120 | #define SE_CRYPTO_REG_OFFSET 0x304 121 | #define SE_CRYPTO_HASH_SHIFT 0 122 | #define HASH_DISABLE 0 123 | #define HASH_ENABLE 1 124 | #define SE_CRYPTO_HASH(x) (x << SE_CRYPTO_HASH_SHIFT) 125 | #define SE_CRYPTO_XOR_POS_SHIFT 1 126 | #define XOR_BYPASS 0 127 | #define XOR_TOP 2 128 | #define XOR_BOTTOM 3 129 | #define SE_CRYPTO_XOR_POS(x) (x << SE_CRYPTO_XOR_POS_SHIFT) 130 | #define SE_CRYPTO_INPUT_SEL_SHIFT 3 131 | #define INPUT_AHB 0 132 | #define INPUT_RANDOM 1 133 | #define INPUT_AESOUT 2 134 | #define INPUT_LNR_CTR 3 135 | #define SE_CRYPTO_INPUT_SEL(x) (x << SE_CRYPTO_INPUT_SEL_SHIFT) 136 | #define SE_CRYPTO_VCTRAM_SEL_SHIFT 5 137 | #define VCTRAM_AHB 0 138 | #define VCTRAM_AESOUT 2 139 | #define VCTRAM_PREVAHB 3 140 | #define SE_CRYPTO_VCTRAM_SEL(x) (x << SE_CRYPTO_VCTRAM_SEL_SHIFT) 141 | #define SE_CRYPTO_IV_SEL_SHIFT 7 142 | #define IV_ORIGINAL 0 143 | #define IV_UPDATED 1 144 | #define SE_CRYPTO_IV_SEL(x) (x << SE_CRYPTO_IV_SEL_SHIFT) 145 | #define SE_CRYPTO_CORE_SEL_SHIFT 8 146 | #define CORE_DECRYPT 0 147 | #define CORE_ENCRYPT 1 148 | #define SE_CRYPTO_CORE_SEL(x) (x << SE_CRYPTO_CORE_SEL_SHIFT) 149 | #define SE_CRYPTO_CTR_VAL_SHIFT 11 150 | #define SE_CRYPTO_CTR_VAL(x) (x << SE_CRYPTO_CTR_VAL_SHIFT) 151 | #define SE_CRYPTO_KEY_INDEX_SHIFT 24 152 | #define SE_CRYPTO_KEY_INDEX(x) (x << SE_CRYPTO_KEY_INDEX_SHIFT) 153 | #define SE_CRYPTO_CTR_CNTN_SHIFT 11 154 | #define SE_CRYPTO_CTR_CNTN(x) (x << SE_CRYPTO_CTR_CNTN_SHIFT) 155 | 156 | #define SE_CRYPTO_CTR_REG_COUNT 4 157 | #define SE_CRYPTO_CTR_REG_OFFSET 0x308 158 | 159 | #define SE_OPERATION_REG_OFFSET 0x008 160 | #define SE_OPERATION_SHIFT 0 161 | #define OP_ABORT 0 162 | #define OP_START 1 163 | #define OP_RESTART 2 164 | #define OP_CTX_SAVE 3 165 | #define OP_RESTART_IN 4 166 | #define SE_OPERATION(x) (x << SE_OPERATION_SHIFT) 167 | 168 | #define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070 169 | #define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0 170 | #define KEYS_0_3 0 171 | #define KEYS_4_7 1 172 | #define ORIG_IV 2 173 | #define UPD_IV 3 174 | #define SE_CONTEXT_SAVE_WORD_QUAD(x) (x << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT) 175 | 176 | #define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8 177 | #define SE_CONTEXT_SAVE_KEY_INDEX(x) (x << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT) 178 | 179 | #define SE_CONTEXT_SAVAE_STICKY_WORD_QUAD_SHIFT 24 180 | #define STICKY_0_3 0 181 | #define STICKY_4_7 1 182 | #define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \ 183 | (x << SE_CONTEXT_SAVAE_STICKY_WORD_QUAD_SHIFT) 184 | 185 | #define SE_CONTEXT_SAVE_SRC_SHIFT 29 186 | #define STICKY_BITS 0 187 | #define KEYTABLE 2 188 | #define MEM 4 189 | #define SRK 6 190 | 191 | #define RSA_KEYTABLE 1 192 | #define SE_CONTEXT_SAVE_SRC(x) (x << SE_CONTEXT_SAVE_SRC_SHIFT) 193 | 194 | #define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16 195 | #define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \ 196 | (x << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT) 197 | 198 | #define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12 199 | #define SE_CONTEXT_RSA_WORD_QUAD(x) \ 200 | (x << SE_CONTEXT_RSA_WORD_QUAD_SHIFT) 201 | 202 | #define SE_INT_ENABLE_REG_OFFSET 0x00c 203 | #define SE_INT_STATUS_REG_OFFSET 0x010 204 | #define INT_DISABLE 0 205 | #define INT_ENABLE 1 206 | #define INT_UNSET 0 207 | #define INT_SET 1 208 | #define SE_INT_OP_DONE_SHIFT 4 209 | #define SE_INT_OP_DONE(x) (x << SE_INT_OP_DONE_SHIFT) 210 | #define SE_INT_ERROR_SHIFT 16 211 | #define SE_INT_ERROR(x) (x << SE_INT_ERROR_SHIFT) 212 | #define SE_STATUS_0 0x800 213 | #define SE_ERR_STATUS_0 0x804 214 | 215 | #define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330 216 | #define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0 217 | #define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \ 218 | (x << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT) 219 | 220 | #define SE_KEY_INDEX_SHIFT 8 221 | #define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) (x << SE_KEY_INDEX_SHIFT) 222 | 223 | #define SE_IN_LL_ADDR_REG_OFFSET 0x018 224 | #define SE_OUT_LL_ADDR_REG_OFFSET 0x024 225 | 226 | #define SE_KEYTABLE_DATA0_REG_OFFSET 0x320 227 | #define SE_KEYTABLE_REG_MAX_DATA 16 228 | 229 | #define SE_BLOCK_COUNT_REG_OFFSET 0x318 230 | 231 | #define SE_SPARE_0_REG_OFFSET 0x80c 232 | 233 | #define SE_SHA_CONFIG_REG_OFFSET 0x200 234 | #define SHA_DISABLE 0 235 | #define SHA_ENABLE 1 236 | 237 | #define SE_SHA_MSG_LENGTH_REG_OFFSET 0x204 238 | #define SE_SHA_MSG_LEFT_REG_OFFSET 0x214 239 | 240 | #define SE_HASH_RESULT_REG_COUNT 16 241 | #define SE_HASH_RESULT_REG_OFFSET 0x030 242 | #define TEGRA_SE_KEY_256_SIZE 32 243 | #define TEGRA_SE_KEY_192_SIZE 24 244 | #define TEGRA_SE_KEY_128_SIZE 16 245 | #define TEGRA_SE_AES_BLOCK_SIZE 16 246 | #define TEGRA_SE_AES_MIN_KEY_SIZE 16 247 | #define TEGRA_SE_AES_MAX_KEY_SIZE 32 248 | #define TEGRA_SE_AES_IV_SIZE 16 249 | #define TEGRA_SE_RNG_IV_SIZE 16 250 | #define TEGRA_SE_RNG_DT_SIZE 16 251 | #define TEGRA_SE_RNG_KEY_SIZE 16 252 | #define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \ 253 | TEGRA_SE_RNG_KEY_SIZE + \ 254 | TEGRA_SE_RNG_DT_SIZE) 255 | 256 | #define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16 257 | #define TEGRA_SE_RSA512_DIGEST_SIZE 64 258 | #define TEGRA_SE_RSA1024_DIGEST_SIZE 128 259 | #define TEGRA_SE_RSA1536_DIGEST_SIZE 192 260 | #define TEGRA_SE_RSA2048_DIGEST_SIZE 256 261 | 262 | #define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280 263 | #define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 264 | #define SE_KEY_READ_DISABLE_SHIFT 0 265 | #define SE_KEY_UPDATE_DISABLE_SHIFT 1 266 | 267 | #define SE_CONTEXT_BUFER_SIZE 1072 268 | #define SE_CONTEXT_DRBG_BUFER_SIZE 2112 269 | 270 | #define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0 271 | #define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16 272 | #define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \ 273 | (SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE) 274 | #define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16 275 | 276 | #define SE_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ 277 | SE_CONTEXT_SAVE_STICKY_BITS_SIZE) 278 | #define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ 279 | SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \ 280 | SE_CONTEXT_SAVE_STICKY_BITS_SIZE) 281 | 282 | #define SE_CONTEXT_SAVE_KEY_LENGTH 512 283 | #define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \ 284 | SE_CONTEXT_SAVE_KEY_LENGTH) 285 | #define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \ 286 | SE_CONTEXT_SAVE_KEY_LENGTH) 287 | 288 | #define SE_CONTEXT_ORIGINAL_IV_LENGTH 256 289 | 290 | #define SE_CONTEXT_UPDATED_IV_OFFSET (SE_CONTEXT_ORIGINAL_IV_OFFSET + \ 291 | SE_CONTEXT_ORIGINAL_IV_LENGTH) 292 | #define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \ 293 | SE_CONTEXT_ORIGINAL_IV_LENGTH) 294 | 295 | #define SE_CONTEXT_UPDATED_IV_LENGTH 256 296 | 297 | #define SE_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET (SE_CONTEXT_UPDATED_IV_OFFSET + \ 298 | SE_CONTEXT_UPDATED_IV_LENGTH) 299 | #define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \ 300 | (SE11_CONTEXT_UPDATED_IV_OFFSET + \ 301 | SE_CONTEXT_UPDATED_IV_LENGTH) 302 | 303 | #define SE_CONTEXT_SAVE_RSA_KEYS_OFFSET SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET 304 | 305 | #define SE_CONTEXT_SAVE_RSA_KEY_LENGTH 1024 306 | 307 | #define SE_CONTEXT_SAVE_RSA_KNOWN_PATTERN_OFFSET \ 308 | (SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH) 309 | 310 | #define SE_CONTEXT_KNOWN_PATTERN_SIZE 16 311 | 312 | #define TEGRA_SE_RSA_KEYSLOT_COUNT 2 313 | 314 | #define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C 315 | #define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410 316 | 317 | #define SE_RSA_KEYTABLE_ADDR 0x420 318 | #define SE_RSA_KEYTABLE_DATA 0x424 319 | #define SE_RSA_OUTPUT 0x428 320 | 321 | #define RSA_KEY_READ 0 322 | #define RSA_KEY_WRITE 1 323 | #define SE_RSA_KEY_OP_SHIFT 10 324 | #define SE_RSA_KEY_OP(x) (x << SE_RSA_KEY_OP_SHIFT) 325 | 326 | #define RSA_KEY_INPUT_MODE_REG 0 327 | #define RSA_KEY_INPUT_MODE_DMA 1 328 | #define RSA_KEY_INPUT_MODE_SHIFT 8 329 | #define RSA_KEY_INPUT_MODE(x) (x << RSA_KEY_INPUT_MODE_SHIFT) 330 | 331 | #define RSA_KEY_SLOT_ONE 0 332 | #define RSA_KEY_SLOT_TW0 1 333 | #define RSA_KEY_NUM_SHIFT 7 334 | #define RSA_KEY_NUM(x) (x << RSA_KEY_NUM_SHIFT) 335 | 336 | #define RSA_KEY_TYPE_EXP 0 337 | #define RSA_KEY_TYPE_MOD 1 338 | #define RSA_KEY_TYPE_SHIFT 6 339 | #define RSA_KEY_TYPE(x) (x << RSA_KEY_TYPE_SHIFT) 340 | 341 | #define SE_RSA_KEY_SIZE_REG_OFFSET 0x404 342 | #define SE_RSA_EXP_SIZE_REG_OFFSET 0x408 343 | 344 | #define RSA_KEY_SLOT_SHIFT 24 345 | #define RSA_KEY_SLOT(x) (x << RSA_KEY_SLOT_SHIFT) 346 | #define SE_RSA_CONFIG 0x400 347 | 348 | #define RSA_KEY_PKT_WORD_ADDR_SHIFT 0 349 | #define RSA_KEY_PKT_WORD_ADDR(x) (x << RSA_KEY_PKT_WORD_ADDR_SHIFT) 350 | 351 | #define RSA_KEY_WORD_ADDR_SHIFT 0 352 | #define RSA_KEY_WORD_ADDR(x) (x << RSA_KEY_WORD_ADDR_SHIFT) 353 | 354 | #define SE_RSA_KEYTABLE_PKT_SHIFT 0 355 | #define SE_RSA_KEYTABLE_PKT(x) (x << SE_RSA_KEYTABLE_PKT_SHIFT) 356 | 357 | #endif /* _CRYPTO_TEGRA_SE_H */ 358 | -------------------------------------------------------------------------------- /ipl/start.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | .section .text._start 18 | .arm 19 | 20 | .extern _reloc_ipl 21 | .type _reloc_ipl, %function 22 | 23 | .extern memset 24 | .type memset, %function 25 | 26 | .extern ipl_main 27 | .type ipl_main, %function 28 | 29 | .globl _start 30 | .type _start, %function 31 | _start: 32 | ADR R0, _start 33 | LDR R1, =__ipl_start 34 | CMP R0, R1 35 | BEQ _real_start 36 | 37 | /* If we are not in the right location already, copy a relocator to upper IRAM. */ 38 | ADR R2, _reloc_ipl 39 | LDR R3, =0x4003FF00 40 | MOV R4, #(_real_start - _reloc_ipl) 41 | _copy_loop: 42 | LDMIA R2!, {R5} 43 | STMIA R3!, {R5} 44 | SUBS R4, #4 45 | BNE _copy_loop 46 | 47 | /* Use the relocator to copy ourselves into the right place. */ 48 | LDR R2, =__ipl_end 49 | SUB R2, R2, R1 50 | LDR R3, =_real_start 51 | LDR R4, =0x4003FF00 52 | BX R4 53 | 54 | _reloc_ipl: 55 | LDMIA R0!, {R4-R7} 56 | STMIA R1!, {R4-R7} 57 | SUBS R2, #0x10 58 | BNE _reloc_ipl 59 | /* Jump to the relocated entry. */ 60 | BX R3 61 | 62 | _real_start: 63 | /* Initially, we place our stack in IRAM but will move it to SDRAM later. */ 64 | LDR SP, =0x4003FF00 65 | LDR R0, =__bss_start 66 | EOR R1, R1, R1 67 | LDR R2, =__bss_end 68 | SUB R2, R2, R0 69 | BL memset 70 | BL ipl_main 71 | B . 72 | 73 | .globl pivot_stack 74 | .type pivot_stack, %function 75 | pivot_stack: 76 | MOV SP, R0 77 | BX LR 78 | -------------------------------------------------------------------------------- /ipl/t210.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _T210_H_ 18 | #define _T210_H_ 19 | 20 | #include "types.h" 21 | 22 | #define HOST1X_BASE 0x50000000 23 | #define DISPLAY_A_BASE 0x54200000 24 | #define DSI_BASE 0x54300000 25 | #define VIC_BASE 0x54340000 26 | #define TSEC_BASE 0x54500000 27 | #define SOR1_BASE 0x54580000 28 | #define TMR_BASE 0x60005000 29 | #define CLOCK_BASE 0x60006000 30 | #define FLOW_CTLR_BASE 0x60007000 31 | #define SYSREG_BASE 0x6000C000 32 | #define SB_BASE (SYSREG_BASE + 0x200) 33 | #define GPIO_BASE 0x6000D000 34 | #define GPIO_1_BASE (GPIO_BASE) 35 | #define GPIO_2_BASE (GPIO_BASE + 0x100) 36 | #define GPIO_3_BASE (GPIO_BASE + 0x200) 37 | #define GPIO_4_BASE (GPIO_BASE + 0x300) 38 | #define GPIO_5_BASE (GPIO_BASE + 0x400) 39 | #define GPIO_6_BASE (GPIO_BASE + 0x500) 40 | #define GPIO_7_BASE (GPIO_BASE + 0x600) 41 | #define GPIO_8_BASE (GPIO_BASE + 0x700) 42 | #define EXCP_VEC_BASE 0x6000F000 43 | #define APB_MISC_BASE 0x70000000 44 | #define PINMUX_AUX_BASE 0x70003000 45 | #define UART_BASE 0x70006000 46 | #define PMC_BASE 0x7000E400 47 | #define SYSCTR0_BASE 0x7000F000 48 | #define FUSE_BASE 0x7000F800 49 | #define KFUSE_BASE 0x7000FC00 50 | #define SE_BASE 0x70012000 51 | #define MC_BASE 0x70019000 52 | #define EMC_BASE 0x7001B000 53 | #define MIPI_CAL_BASE 0x700E3000 54 | #define I2S_BASE 0x702D1000 55 | 56 | #define _REG(base, off) *(vu32 *)((base) + (off)) 57 | 58 | #define HOST1X(off) _REG(HOST1X_BASE, off) 59 | #define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off) 60 | #define DSI(off) _REG(DSI_BASE, off) 61 | #define VIC(off) _REG(VIC_BASE, off) 62 | #define TSEC(off) _REG(TSEC_BASE, off) 63 | #define SOR1(off) _REG(SOR1_BASE, off) 64 | #define TMR(off) _REG(TMR_BASE, off) 65 | #define CLOCK(off) _REG(CLOCK_BASE, off) 66 | #define FLOW_CTLR(off) _REG(FLOW_CTLR_BASE, off) 67 | #define SYSREG(off) _REG(SYSREG_BASE, off) 68 | #define SB(off) _REG(SB_BASE, off) 69 | #define GPIO(off) _REG(GPIO_BASE, off) 70 | #define GPIO_1(off) _REG(GPIO_1_BASE, off) 71 | #define GPIO_2(off) _REG(GPIO_2_BASE, off) 72 | #define GPIO_3(off) _REG(GPIO_3_BASE, off) 73 | #define GPIO_4(off) _REG(GPIO_4_BASE, off) 74 | #define GPIO_5(off) _REG(GPIO_5_BASE, off) 75 | #define GPIO_6(off) _REG(GPIO_6_BASE, off) 76 | #define GPIO_7(off) _REG(GPIO_7_BASE, off) 77 | #define GPIO_8(off) _REG(GPIO_8_BASE, off) 78 | #define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off) 79 | #define APB_MISC(off) _REG(APB_MISC_BASE, off) 80 | #define PINMUX_AUX(off) _REG(PINMUX_AUX_BASE, off) 81 | #define PMC(off) _REG(PMC_BASE, off) 82 | #define SYSCTR0(off) _REG(SYSCTR0_BASE, off) 83 | #define FUSE(off) _REG(FUSE_BASE, off) 84 | #define KFUSE(off) _REG(KFUSE_BASE, off) 85 | #define SE(off) _REG(SE_BASE, off) 86 | #define MC(off) _REG(MC_BASE, off) 87 | #define EMC(off) _REG(EMC_BASE, off) 88 | #define MIPI_CAL(off) _REG(MIPI_CAL_BASE, off) 89 | #define I2S(off) _REG(I2S_BASE, off) 90 | 91 | /*! System registers. */ 92 | #define AHB_ARBITRATION_XBAR_CTRL 0xE0 93 | 94 | /*! Secure boot registers. */ 95 | #define SB_CSR 0x0 96 | #define SB_AA64_RESET_LOW 0x30 97 | #define SB_AA64_RESET_HIGH 0x34 98 | 99 | /*! SYSCTR0 registers. */ 100 | #define SYSCTR0_CNTFID0 0x20 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /ipl/tsec.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include 18 | #include "tsec.h" 19 | #include "clock.h" 20 | #include "t210.h" 21 | #include "heap.h" 22 | 23 | static int _tsec_dma_wait_idle() 24 | { 25 | u32 timeout = TMR(0x10) + 10000000; 26 | 27 | while (!(TSEC(0x1118) & 2)) 28 | if (TMR(0x10) > timeout) 29 | return 0; 30 | 31 | return 1; 32 | } 33 | 34 | static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offset) 35 | { 36 | u32 cmd; 37 | 38 | if (not_imem) 39 | cmd = 0x600; // DMA 0x100 bytes 40 | else 41 | cmd = 0x10; // dma imem 42 | 43 | TSEC(0x1114) = i_offset; // tsec_dmatrfmoffs_r 44 | TSEC(0x111C) = pa_offset; // tsec_dmatrffboffs_r 45 | TSEC(0x1118) = cmd; // tsec_dmatrfcmd_r 46 | 47 | return _tsec_dma_wait_idle(); 48 | } 49 | 50 | int tsec_query(u8 *dst, u32 rev, void *fw) 51 | { 52 | int res = 0; 53 | 54 | //Enable clocks. 55 | clock_enable_host1x(); 56 | clock_enable_tsec(); 57 | clock_enable_sor_safe(); 58 | clock_enable_sor0(); 59 | clock_enable_sor1(); 60 | clock_enable_kfuse(); 61 | 62 | //Configure Falcon. 63 | TSEC(0x110C) = 0; // tsec_dmactl_r 64 | TSEC(0x1010) = 0xFFF2; // tsec_irqmset_r 65 | TSEC(0x101C) = 0xFFF0; // tsec_irqdest_r 66 | TSEC(0x1048) = 3; // tsec_itfen_r 67 | if (!_tsec_dma_wait_idle()) 68 | { 69 | res = -1; 70 | goto out; 71 | } 72 | 73 | //Load firmware. 74 | u8 *fwbuf = (u8 *)malloc(0x2000); 75 | u8 *fwbuf_aligned = (u8 *)ALIGN((u32)fwbuf + 0x1000, 0x100); 76 | memcpy(fwbuf_aligned, fw, 0xF00); 77 | TSEC(0x1110) = (u32)fwbuf_aligned >> 8;// tsec_dmatrfbase_r 78 | for (u32 addr = 0; addr < 0xF00; addr += 0x100) 79 | if (!_tsec_dma_pa_to_internal_100(0, addr, addr)) 80 | { 81 | res = -2; 82 | goto out_free; 83 | } 84 | 85 | //Execute firmware. 86 | HOST1X(0x3300) = 0x34C2E1DA; 87 | TSEC(0x1044) = 0; 88 | TSEC(0x1040) = rev; 89 | TSEC(0x1104) = 0; // tsec_bootvec_r 90 | TSEC(0x1100) = 2; // tsec_cpuctl_r 91 | if (!_tsec_dma_wait_idle()) 92 | { 93 | res = -3; 94 | goto out_free; 95 | } 96 | u32 timeout = TMR(0x10) + 2000000; 97 | while (!TSEC(0x1044)) 98 | if (TMR(0x10) > timeout) 99 | { 100 | res = -4; 101 | goto out_free; 102 | } 103 | if (TSEC(0x1044) != 0xB0B0B0B0) 104 | { 105 | res = -5; 106 | goto out_free; 107 | } 108 | 109 | //Fetch result. 110 | HOST1X(0x3300) = 0; 111 | u32 buf[4]; 112 | buf[0] = SOR1(0x1E8); 113 | buf[1] = SOR1(0x21C); 114 | buf[2] = SOR1(0x208); 115 | buf[3] = SOR1(0x20C); 116 | SOR1(0x1E8) = 0; 117 | SOR1(0x21C) = 0; 118 | SOR1(0x208) = 0; 119 | SOR1(0x20C) = 0; 120 | memcpy(dst, &buf, 0x10); 121 | 122 | out_free:; 123 | free(fwbuf); 124 | 125 | out:; 126 | 127 | //Disable clocks. 128 | clock_disable_kfuse(); 129 | clock_disable_sor1(); 130 | clock_disable_sor0(); 131 | clock_disable_sor_safe(); 132 | clock_disable_tsec(); 133 | clock_disable_host1x(); 134 | 135 | return res; 136 | } 137 | -------------------------------------------------------------------------------- /ipl/tsec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _TSEC_H_ 18 | #define _TSEC_H_ 19 | 20 | #include "types.h" 21 | 22 | int tsec_query(u8 *dst, u32 rev, void *fw); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /ipl/tui.c: -------------------------------------------------------------------------------- 1 | /*{ 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "tui.h" 18 | #include "btn.h" 19 | 20 | void tui_pbar(gfx_con_t *con, int x, int y, u32 val) 21 | { 22 | u32 cx, cy; 23 | 24 | gfx_con_getpos(con, &cx, &cy); 25 | 26 | gfx_con_setpos(con, x, y); 27 | 28 | gfx_printf(con, "[%3d%%]", val); 29 | 30 | x += 7 * 8; 31 | 32 | for (int i = 0; i < 6; i++) 33 | { 34 | gfx_line(con->gfx_ctxt, x, y + i + 1, x + 3 * val, y + i + 1, 0xFFFFFFFF); 35 | gfx_line(con->gfx_ctxt, x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, 0xFF888888); 36 | } 37 | 38 | gfx_con_setpos(con, cx, cy); 39 | } 40 | 41 | void *tui_do_menu(gfx_con_t *con, menu_t *menu) 42 | { 43 | int idx = 0, cnt; 44 | 45 | gfx_clear(con->gfx_ctxt, 0xFF000000); 46 | 47 | while (1) 48 | { 49 | gfx_con_setcol(con, 0xFFFFFFFF, 1, 0xFF000000); 50 | gfx_con_setpos(con, menu->x, menu->y); 51 | gfx_printf(con, "[%s]\n\n", menu->caption); 52 | 53 | for (cnt = 0; menu->ents[cnt].type != MENT_END; cnt++) 54 | { 55 | if (cnt == idx) 56 | gfx_con_setcol(con, 0xFF000000, 1, 0xFFCCCCCC); 57 | else 58 | gfx_con_setcol(con, 0xFFFFFFFF, 1, 0xFF000000); 59 | con->x += 8; 60 | gfx_printf(con, "%s", menu->ents[cnt].caption); 61 | if(menu->ents[cnt].type == MENT_MENU) 62 | gfx_printf(con, "%k...", 0xFFEE9900); 63 | gfx_putc(con, '\n'); 64 | } 65 | 66 | gfx_con_setcol(con, 0xFFFFFFFF, 1, 0xFF000000); 67 | gfx_putc(con, '\n'); 68 | 69 | u32 btn = btn_wait(); 70 | 71 | if (btn & BTN_VOL_DOWN && idx < cnt - 1) 72 | idx++; 73 | if (btn & BTN_VOL_UP && idx > 0) 74 | idx--; 75 | if (btn & BTN_POWER) 76 | { 77 | ment_t *ent = &menu->ents[idx]; 78 | switch (ent->type) 79 | { 80 | case MENT_HANDLER: 81 | ent->handler(ent->data); 82 | break; 83 | case MENT_MENU: 84 | return tui_do_menu(con, ent->menu); 85 | break; 86 | case MENT_CHOICE: 87 | return ent->data; 88 | break; 89 | case MENT_BACK: 90 | return NULL; 91 | break; 92 | } 93 | gfx_clear(con->gfx_ctxt, 0xFF000000); 94 | } 95 | } 96 | 97 | return NULL; 98 | } 99 | -------------------------------------------------------------------------------- /ipl/tui.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _TUI_H_ 18 | #define _TUI_H_ 19 | 20 | #include "types.h" 21 | #include "gfx.h" 22 | 23 | #define MENT_END 0 24 | #define MENT_HANDLER 1 25 | #define MENT_MENU 2 26 | #define MENT_CHOICE 3 27 | #define MENT_BACK 4 28 | 29 | typedef struct _ment_t 30 | { 31 | u32 type; 32 | const char *caption; 33 | void *data; 34 | union 35 | { 36 | void(*handler)(void *); 37 | struct _menu_t *menu; 38 | }; 39 | } ment_t; 40 | 41 | typedef struct _menu_t 42 | { 43 | ment_t *ents; 44 | const char *caption; 45 | u32 x; 46 | u32 y; 47 | } menu_t; 48 | 49 | #define MDEF_END() {MENT_END} 50 | #define MDEF_HANDLER(caption, _handler) { MENT_HANDLER, caption, NULL, { .handler = _handler } } 51 | #define MDEF_HANDLER_EX(caption, data, _handler) { MENT_HANDLER, caption, data, { .handler = _handler } } 52 | #define MDEF_MENU(caption, _menu) { MENT_MENU, caption, NULL, { .menu = _menu } } 53 | #define MDEF_BACK() { MENT_BACK, "Back" } 54 | 55 | void tui_pbar(gfx_con_t *con, int x, int y, u32 val); 56 | void *tui_do_menu(gfx_con_t *con, menu_t *menu); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /ipl/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _TYPES_H_ 18 | #define _TYPES_H_ 19 | 20 | #define NULL ((void *)0) 21 | 22 | #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) 23 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 24 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 25 | 26 | #define OFFSET_OF(t, m) ((u32)&((t *)NULL)->m) 27 | #define CONTAINER_OF(mp, t, mn) ((t *)((u32)mp - OFFSET_OF(t, mn))) 28 | 29 | typedef unsigned char u8; 30 | typedef unsigned short u16; 31 | typedef unsigned int u32; 32 | typedef unsigned long long int u64; 33 | typedef volatile unsigned char vu8; 34 | typedef volatile unsigned short vu16; 35 | typedef volatile unsigned int vu32; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ipl/uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "uart.h" 18 | #include "t210.h" 19 | #include "util.h" 20 | 21 | /* UART A, B, C, D and E. */ 22 | static const u32 uart_baseoff[5] = { 0, 0x40, 0x200, 0x300, 0x400 }; 23 | 24 | void uart_init(u32 idx, u32 baud) 25 | { 26 | uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); 27 | 28 | //Set baud rate. 29 | u32 rate = (8 * baud + 408000000) / (16 * baud); 30 | uart->UART_LCR = 0x80; //Enable DLAB. 31 | uart->UART_THR_DLAB = (u8)rate; //Divisor latch LSB. 32 | uart->UART_IER_DLAB = (u8)(rate >> 8); //Divisor latch MSB. 33 | uart->UART_LCR = 0; //Diable DLAB. 34 | 35 | //Setup UART in fifo mode. 36 | uart->UART_IER_DLAB = 0; 37 | uart->UART_IIR_FCR = 7; //Enable and clear TX and RX FIFOs. 38 | (void)uart->UART_LSR; 39 | sleep(3 * ((baud + 999999) / baud)); 40 | uart->UART_LCR = 3; //Set word length 8. 41 | uart->UART_MCR = 0; 42 | uart->UART_MSR = 0; 43 | uart->UART_IRDA_CSR = 0; 44 | uart->UART_RX_FIFO_CFG = 1; 45 | uart->UART_MIE = 0; 46 | uart->UART_ASR = 0; 47 | } 48 | 49 | void uart_wait_idle(u32 idx, u32 which) 50 | { 51 | uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); 52 | while (!(uart->UART_VENDOR_STATUS & which)) 53 | ; 54 | } 55 | 56 | void uart_send(u32 idx, u8 *buf, u32 len) 57 | { 58 | uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); 59 | 60 | for (u32 i = 0; i != len; i++) 61 | { 62 | while (uart->UART_LSR & UART_TX_FIFO_FULL) 63 | ; 64 | uart->UART_THR_DLAB = buf[i]; 65 | }; 66 | } 67 | 68 | void uart_recv(u32 idx, u8 *buf, u32 len) 69 | { 70 | uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); 71 | 72 | for (u32 i = 0; i != len; i++) 73 | { 74 | while (uart->UART_LSR & UART_RX_FIFO_EMPTY) 75 | ; 76 | buf[i] = uart->UART_THR_DLAB; 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /ipl/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _UART_H_ 18 | #define _UART_H_ 19 | 20 | #include "types.h" 21 | 22 | #define UART_A 0 23 | #define UART_B 1 24 | #define UART_C 2 25 | //TODO: define clock inits for those. 26 | /*#define UART_D 3 27 | #define UART_E 4*/ 28 | 29 | #define BAUD_115200 115200 30 | 31 | #define UART_TX_IDLE 0x00000001 32 | #define UART_RX_IDLE 0x00000002 33 | #define UART_TX_FIFO_FULL 0x100 34 | #define UART_RX_FIFO_EMPTY 0x200 35 | 36 | typedef struct _uart_t 37 | { 38 | /* 0x00 */ vu32 UART_THR_DLAB; 39 | /* 0x04 */ vu32 UART_IER_DLAB; 40 | /* 0x08 */ vu32 UART_IIR_FCR; 41 | /* 0x0C */ vu32 UART_LCR; 42 | /* 0x10 */ vu32 UART_MCR; 43 | /* 0x14 */ vu32 UART_LSR; 44 | /* 0x18 */ vu32 UART_MSR; 45 | /* 0x1C */ vu32 UART_SPR; 46 | /* 0x20 */ vu32 UART_IRDA_CSR; 47 | /* 0x24 */ vu32 UART_RX_FIFO_CFG; 48 | /* 0x28 */ vu32 UART_MIE; 49 | /* 0x2C */ vu32 UART_VENDOR_STATUS; 50 | /* 0x30 */ u8 _pad_30[0xC]; 51 | /* 0x3C */ vu32 UART_ASR; 52 | } uart_t; 53 | 54 | void uart_init(u32 idx, u32 baud); 55 | void uart_wait_idle(u32 idx, u32 which); 56 | void uart_send(u32 idx, u8 *buf, u32 len); 57 | void uart_recv(u32 idx, u8 *buf, u32 len); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /ipl/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #include "util.h" 18 | #include "t210.h" 19 | 20 | u32 get_tmr() 21 | { 22 | return TMR(0x10); 23 | } 24 | 25 | void sleep(u32 ticks) 26 | { 27 | u32 start = TMR(0x10); 28 | while (TMR(0x10) - start <= ticks) 29 | ; 30 | } 31 | 32 | void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) 33 | { 34 | for(u32 i = 0; i < num_ops; i++) 35 | base[ops[i].off] = ops[i].val; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /ipl/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 naehrwert 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms and conditions of the GNU General Public License, 6 | * version 2, as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | */ 16 | 17 | #ifndef _UTIL_H_ 18 | #define _UTIL_H_ 19 | 20 | #include "types.h" 21 | 22 | typedef struct _cfg_op_t 23 | { 24 | u32 off; 25 | u32 val; 26 | } cfg_op_t; 27 | 28 | u32 get_tmr(); 29 | void sleep(u32 ticks); 30 | void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /tools/fix_regs.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | def parse_defs(fname): 4 | f = open(fname, "r") 5 | lines = f.readlines() 6 | f.close() 7 | res = {} 8 | for l in lines: 9 | p = [str(_.strip()) for _ in l.strip().split(" ", 1)] 10 | res[int(p[1], 16)] = p[0] 11 | return res 12 | 13 | mc = parse_defs("mc.def") 14 | emc = parse_defs("emc.def") 15 | 16 | f = open(sys.argv[1], "r") 17 | buf = f.read() 18 | f.close() 19 | 20 | def fix(m): 21 | what = m.groups()[0] 22 | off = int(m.groups()[1], 16) 23 | if what == "MC": 24 | if off in mc: 25 | return "MC({0})".format(mc[off]) 26 | elif what == "EMC": 27 | if off in emc: 28 | return "EMC({0})".format(emc[off]) 29 | return "{0}(0x{1:X})".format(what, off) 30 | 31 | buf = re.sub(r'([A-Z]+)\(0x([0-9a-fA-F]+)\)', fix, buf) 32 | 33 | f = open(sys.argv[2], "w") 34 | f.write(buf) 35 | f.close() 36 | --------------------------------------------------------------------------------