Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25218795b4 | ||
|
|
a65ec67128 | ||
|
|
5d753f2384 | ||
|
|
1f2de35f94 | ||
|
|
5c140b4f35 | ||
|
|
362ee3cdb0 | ||
|
|
215f1bc8ee | ||
|
|
4d72c2b37a | ||
|
|
dc4dbe29ae | ||
|
|
72dd25a99e | ||
|
|
39d041466d | ||
|
|
442ebff829 | ||
|
|
7e169bc7df | ||
|
|
00f4e5158f | ||
|
|
0c688189f6 | ||
|
|
7cee36544c | ||
|
|
f9c1d5fc1b | ||
|
|
d95e20952c | ||
|
|
32a90334bb | ||
|
|
f534d3498e | ||
|
|
3ea9f444db | ||
|
|
5672c935ed | ||
|
|
4cc2b5c38a | ||
|
|
00e3d874e3 | ||
|
|
803e91a8c4 | ||
|
|
227a1d938d | ||
|
|
fc7f06dc78 | ||
|
|
6777dd9b38 | ||
|
|
4db212ea7b | ||
|
|
8177a27db9 | ||
|
|
27ff119ba6 | ||
|
|
c20774ff5d | ||
|
|
a9f5b7728b | ||
|
|
08ad48fbf3 | ||
|
|
2d0c881ffe | ||
|
|
c916a7db88 | ||
|
|
a5da286351 | ||
|
|
20a48c3a26 | ||
|
|
5bba0f47ff | ||
|
|
bfc987abcd | ||
|
|
85bf7c86e0 | ||
|
|
2225b86eea | ||
|
|
d09be18359 | ||
|
|
09ab3efddd | ||
|
|
382a0192f9 | ||
|
|
e3b968fa80 | ||
|
|
6f85b11fcc | ||
|
|
e561919a52 |
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
|||||||
[submodule "common/include/boost"]
|
[submodule "common/include/boost"]
|
||||||
path = common/include/boost
|
path = common/include/boost
|
||||||
url = https://github.com/Atmosphere-NX/ext-boost.git
|
url = https://github.com/Atmosphere-NX/ext-boost.git
|
||||||
[submodule "stratosphere/libstratosphere"]
|
|
||||||
path = stratosphere/libstratosphere
|
|
||||||
url = https://github.com/Atmosphere-NX/libstratosphere.git
|
|
||||||
|
|||||||
1
Makefile
1
Makefile
@@ -57,6 +57,7 @@ dist: all
|
|||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000037
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000037
|
||||||
mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors
|
mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors
|
||||||
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
|
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
|
||||||
|
cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin
|
||||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
|
||||||
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
|
||||||
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
|
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
BCT0
|
BCT0
|
||||||
[stage1]
|
[stage1]
|
||||||
stage2_path = atmosphere/fusee-secondary.bin
|
stage2_path = atmosphere/fusee-secondary.bin
|
||||||
|
stage2_mtc_path = atmosphere/fusee-mtc.bin
|
||||||
stage2_addr = 0xF0000000
|
stage2_addr = 0xF0000000
|
||||||
stage2_entrypoint = 0xF0000000
|
stage2_entrypoint = 0xF0000000
|
||||||
|
|
||||||
|
|||||||
@@ -29,3 +29,12 @@ dmnt_always_save_cheat_toggles = u8!0x0
|
|||||||
; NOTE: EXPERIMENTAL
|
; NOTE: EXPERIMENTAL
|
||||||
; If you do not know what you are doing, do not touch this yet.
|
; If you do not know what you are doing, do not touch this yet.
|
||||||
fsmitm_redirect_saves_to_sd = u8!0x0
|
fsmitm_redirect_saves_to_sd = u8!0x0
|
||||||
|
[hbloader]
|
||||||
|
; Controls the size of the homebrew heap when running as applet.
|
||||||
|
; If set to zero, all available applet memory is used as heap.
|
||||||
|
; The default is zero.
|
||||||
|
applet_heap_size = u64!0x0
|
||||||
|
; Controls the amount of memory to reserve when running as applet
|
||||||
|
; for usage by other applets. This setting has no effect if
|
||||||
|
; applet_heap_size is non-zero. The default is zero.
|
||||||
|
applet_heap_reservation_size = u64!0x8000000
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 9
|
#define ATMOSPHERE_RELEASE_VERSION_MINOR 9
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 2
|
#define ATMOSPHERE_RELEASE_VERSION_MICRO 3
|
||||||
|
|
||||||
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 8
|
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 8
|
||||||
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1
|
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1
|
||||||
|
|||||||
@@ -1,4 +1,27 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
## 0.9.3
|
||||||
|
+ Thanks to hexkyz, fusee's boot sequence has been greatly optimized.
|
||||||
|
+ Memory training is now managed by a separate binary (`fusee-mtc`, loaded by fusee-primary before fusee-secondary).
|
||||||
|
+ Unnecessarily long splash screen display times were reduced.
|
||||||
|
+ The end result is that Atmosphere now boots *significantly* faster. :)
|
||||||
|
+ **Note:** This means fusee-primary must be updated for Atmosphere to boot successfully.
|
||||||
|
+ The version string was adjusted, and now informs users whether or not they are using emummc.
|
||||||
|
+ Atmosphere now automatically backs up the user's BIS keys on boot.
|
||||||
|
+ This should prevent a user from corrupting nand without access to a copy of the keys needed to fix it.
|
||||||
|
+ This is especially relevant on ipatched units, where the RCM vulnerability is not an option for addressing bricks.
|
||||||
|
+ The `pm` system module was rewritten as part of Stratosphere's ongoing refactor.
|
||||||
|
+ Support was added for forward-declaring a mitm'd service before a custom user sysmodule is launched.
|
||||||
|
+ This should help resolve dependency issues with service registration times.
|
||||||
|
+ SM is now informed of every process's title id, including built-in system modules.
|
||||||
|
+ The `creport` system module was rewritten as part of Stratosphere's ongoing refactor.
|
||||||
|
+ creport now dumps up to 0x100 of stack from each thread in the target process.
|
||||||
|
+ A few bugs were fixed, including one that caused creport to incorrectly dump process dying messages.
|
||||||
|
+ Defaults were added to `system_settings.ini` for controlling hbloader's memory usage in applet mode.
|
||||||
|
+ These defaults reserve enough memory so that homebrew can launch swkbd while in applet mode.
|
||||||
|
+ The `fatal` system module was rewritten as part of Stratosphere's ongoing refactor.
|
||||||
|
+ Incorrect display output ("2000-0000") has been fixed. Fatal will now correctly show 2162-0002 when this occurs.
|
||||||
|
+ A longstanding bug in how fatal manages the displays has been fixed, and official display init behavior is now matched precisely.
|
||||||
|
+ General system stability improvements to enhance the user's experience.
|
||||||
## 0.9.2
|
## 0.9.2
|
||||||
+ A number of emummc bugfixes were added (all thanks to @m4xw's hard work). The following is a summary of emummc changes:
|
+ A number of emummc bugfixes were added (all thanks to @m4xw's hard work). The following is a summary of emummc changes:
|
||||||
+ Support for file-based emummc instances was fixed.
|
+ Support for file-based emummc instances was fixed.
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ typedef enum {
|
|||||||
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||||
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||||
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||||
CARDEVICE_UNK = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ void bootup_misc_mmio(void) {
|
|||||||
|
|
||||||
if (!g_has_booted_up) {
|
if (!g_has_booted_up) {
|
||||||
/* N doesn't do this, but we should for compatibility. */
|
/* N doesn't do this, but we should for compatibility. */
|
||||||
uart_select(UART_A);
|
uart_config(UART_A);
|
||||||
clkrst_reboot(CARDEVICE_UARTA);
|
clkrst_reboot(CARDEVICE_UARTA);
|
||||||
uart_init(UART_A, 115200);
|
uart_init(UART_A, 115200);
|
||||||
|
|
||||||
|
|||||||
@@ -14,25 +14,56 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
#include "pinmux.h"
|
||||||
|
|
||||||
/* Prototypes for internal commands. */
|
/* Prototypes for internal commands. */
|
||||||
volatile i2c_registers_t *i2c_get_registers_from_id(unsigned int id);
|
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id);
|
||||||
void i2c_load_config(volatile i2c_registers_t *regs);
|
void i2c_load_config(volatile tegra_i2c_t *regs);
|
||||||
|
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||||
|
|
||||||
bool i2c_write(volatile i2c_registers_t *regs, uint8_t device, void *src, size_t src_size);
|
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
|
||||||
bool i2c_read(volatile i2c_registers_t *regs, uint8_t device, void *dst, size_t dst_size);
|
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
|
||||||
|
|
||||||
|
/* Configure I2C pinmux. */
|
||||||
|
void i2c_config(I2CDevice id) {
|
||||||
|
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case I2C_1:
|
||||||
|
pinmux->gen1_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen1_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_2:
|
||||||
|
pinmux->gen2_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen2_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_3:
|
||||||
|
pinmux->gen3_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen3_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_4:
|
||||||
|
pinmux->cam_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->cam_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_5:
|
||||||
|
pinmux->pwr_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->pwr_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_6:
|
||||||
|
/* Unused. */
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize I2C based on registers. */
|
/* Initialize I2C based on registers. */
|
||||||
void i2c_init(unsigned int id) {
|
void i2c_init(I2CDevice id) {
|
||||||
volatile i2c_registers_t *regs = i2c_get_registers_from_id(id);
|
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||||
|
|
||||||
/* Setup divisor, and clear the bus. */
|
/* Setup divisor, and clear the bus. */
|
||||||
regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001;
|
regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001;
|
||||||
@@ -61,16 +92,16 @@ void i2c_init(unsigned int id) {
|
|||||||
void i2c_send_pmic_cpu_shutdown_cmd(void) {
|
void i2c_send_pmic_cpu_shutdown_cmd(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* PMIC == Device 4:3C. */
|
/* PMIC == Device 4:3C. */
|
||||||
i2c_query(4, 0x3C, 0x41, &val, 1);
|
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
|
||||||
val |= 4;
|
val |= 4;
|
||||||
i2c_send(4, 0x3C, 0x41, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Queries the value of TI charger bit over I2C. */
|
/* Queries the value of TI charger bit over I2C. */
|
||||||
bool i2c_query_ti_charger_bit_7(void) {
|
bool i2c_query_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
return (val & 0x80) != 0;
|
return (val & 0x80) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,34 +109,34 @@ bool i2c_query_ti_charger_bit_7(void) {
|
|||||||
void i2c_clear_ti_charger_bit_7(void) {
|
void i2c_clear_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
val &= 0x7F;
|
val &= 0x7F;
|
||||||
i2c_send(0, 0x6B, 0, &val, 1);
|
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets TI charger bit over I2C. */
|
/* Sets TI charger bit over I2C. */
|
||||||
void i2c_set_ti_charger_bit_7(void) {
|
void i2c_set_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
val |= 0x80;
|
val |= 0x80;
|
||||||
i2c_send(0, 0x6B, 0, &val, 1);
|
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get registers pointer based on I2C ID. */
|
/* Get registers pointer based on I2C ID. */
|
||||||
volatile i2c_registers_t *i2c_get_registers_from_id(unsigned int id) {
|
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 0:
|
case I2C_1:
|
||||||
return I2C1_REGS;
|
return I2C1_REGS;
|
||||||
case 1:
|
case I2C_2:
|
||||||
return I2C2_REGS;
|
return I2C2_REGS;
|
||||||
case 2:
|
case I2C_3:
|
||||||
return I2C3_REGS;
|
return I2C3_REGS;
|
||||||
case 3:
|
case I2C_4:
|
||||||
return I2C4_REGS;
|
return I2C4_REGS;
|
||||||
case 4:
|
case I2C_5:
|
||||||
return I2C5_REGS;
|
return I2C5_REGS;
|
||||||
case 5:
|
case I2C_6:
|
||||||
return I2C6_REGS;
|
return I2C6_REGS;
|
||||||
default:
|
default:
|
||||||
generic_panic();
|
generic_panic();
|
||||||
@@ -114,7 +145,7 @@ volatile i2c_registers_t *i2c_get_registers_from_id(unsigned int id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Load hardware config for I2C4. */
|
/* Load hardware config for I2C4. */
|
||||||
void i2c_load_config(volatile i2c_registers_t *regs) {
|
void i2c_load_config(volatile tegra_i2c_t *regs) {
|
||||||
/* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */
|
/* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */
|
||||||
regs->I2C_I2C_CONFIG_LOAD_0 = 0x25;
|
regs->I2C_I2C_CONFIG_LOAD_0 = 0x25;
|
||||||
|
|
||||||
@@ -128,8 +159,8 @@ void i2c_load_config(volatile i2c_registers_t *regs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reads a register from a device over I2C, writes result to output. */
|
/* Reads a register from a device over I2C, writes result to output. */
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
||||||
volatile i2c_registers_t *regs = i2c_get_registers_from_id(id);
|
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||||
uint32_t val = r;
|
uint32_t val = r;
|
||||||
|
|
||||||
/* Write single byte register ID to device. */
|
/* Write single byte register ID to device. */
|
||||||
@@ -145,7 +176,7 @@ bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Writes a value to a register over I2C. */
|
/* Writes a value to a register over I2C. */
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
||||||
uint32_t val = r;
|
uint32_t val = r;
|
||||||
if (src_size == 0) {
|
if (src_size == 0) {
|
||||||
return true;
|
return true;
|
||||||
@@ -158,7 +189,7 @@ bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Writes bytes to device over I2C. */
|
/* Writes bytes to device over I2C. */
|
||||||
bool i2c_write(volatile i2c_registers_t *regs, uint8_t device, void *src, size_t src_size) {
|
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) {
|
||||||
if (src_size > 4) {
|
if (src_size > 4) {
|
||||||
return false;
|
return false;
|
||||||
} else if (src_size == 0) {
|
} else if (src_size == 0) {
|
||||||
@@ -177,8 +208,7 @@ bool i2c_write(volatile i2c_registers_t *regs, uint8_t device, void *src, size_t
|
|||||||
i2c_load_config(regs);
|
i2c_load_config(regs);
|
||||||
|
|
||||||
/* Config |= SEND; */
|
/* Config |= SEND; */
|
||||||
regs->I2C_I2C_CNFG_0 |= 0x200;
|
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
|
||||||
|
|
||||||
|
|
||||||
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
||||||
/* Wait until not busy. */
|
/* Wait until not busy. */
|
||||||
@@ -189,7 +219,7 @@ bool i2c_write(volatile i2c_registers_t *regs, uint8_t device, void *src, size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reads bytes from device over I2C. */
|
/* Reads bytes from device over I2C. */
|
||||||
bool i2c_read(volatile i2c_registers_t *regs, uint8_t device, void *dst, size_t dst_size) {
|
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) {
|
||||||
if (dst_size > 4) {
|
if (dst_size > 4) {
|
||||||
return false;
|
return false;
|
||||||
} else if (dst_size == 0) {
|
} else if (dst_size == 0) {
|
||||||
@@ -205,8 +235,7 @@ bool i2c_read(volatile i2c_registers_t *regs, uint8_t device, void *dst, size_t
|
|||||||
i2c_load_config(regs);
|
i2c_load_config(regs);
|
||||||
|
|
||||||
/* Config |= SEND; */
|
/* Config |= SEND; */
|
||||||
regs->I2C_I2C_CNFG_0 |= 0x200;
|
regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200);
|
||||||
|
|
||||||
|
|
||||||
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
while (regs->I2C_I2C_STATUS_0 & 0x100) {
|
||||||
/* Wait until not busy. */
|
/* Wait until not busy. */
|
||||||
|
|||||||
@@ -19,10 +19,27 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
|
|
||||||
/* Exosphere driver for the Tegra X1 I2C registers. */
|
/* Exosphere driver for the Tegra X1 I2C registers. */
|
||||||
|
|
||||||
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
|
#define MAX77620_PWR_I2C_ADDR 0x3C
|
||||||
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I2C_1 = 0,
|
||||||
|
I2C_2 = 1,
|
||||||
|
I2C_3 = 2,
|
||||||
|
I2C_4 = 3,
|
||||||
|
I2C_5 = 4,
|
||||||
|
I2C_6 = 5,
|
||||||
|
} I2CDevice;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t I2C_I2C_CNFG_0;
|
uint32_t I2C_I2C_CNFG_0;
|
||||||
uint32_t I2C_I2C_CMD_ADDR0_0;
|
uint32_t I2C_I2C_CMD_ADDR0_0;
|
||||||
@@ -65,7 +82,7 @@ typedef struct {
|
|||||||
uint32_t I2C_I2C_INTERFACE_TIMING_1_0;
|
uint32_t I2C_I2C_INTERFACE_TIMING_1_0;
|
||||||
uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0;
|
uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0;
|
||||||
uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0;
|
uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0;
|
||||||
} i2c_registers_t;
|
} tegra_i2c_t;
|
||||||
|
|
||||||
static inline uintptr_t get_i2c_dtv_234_base(void) {
|
static inline uintptr_t get_i2c_dtv_234_base(void) {
|
||||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DTV_I2C234);
|
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DTV_I2C234);
|
||||||
@@ -75,17 +92,20 @@ static inline uintptr_t get_i2c56_spi2b_base(void) {
|
|||||||
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_I2C56_SPI2B);
|
return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_I2C56_SPI2B);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define I2C1_REGS ((volatile i2c_registers_t *)(get_i2c_dtv_234_base() + 0x000))
|
#define I2C1_REGS ((volatile tegra_i2c_t *)(get_i2c_dtv_234_base() + 0x000))
|
||||||
#define I2C2_REGS ((volatile i2c_registers_t *)(get_i2c_dtv_234_base() + 0x400))
|
#define I2C2_REGS ((volatile tegra_i2c_t *)(get_i2c_dtv_234_base() + 0x400))
|
||||||
#define I2C3_REGS ((volatile i2c_registers_t *)(get_i2c_dtv_234_base() + 0x500))
|
#define I2C3_REGS ((volatile tegra_i2c_t *)(get_i2c_dtv_234_base() + 0x500))
|
||||||
#define I2C4_REGS ((volatile i2c_registers_t *)(get_i2c_dtv_234_base() + 0x700))
|
#define I2C4_REGS ((volatile tegra_i2c_t *)(get_i2c_dtv_234_base() + 0x700))
|
||||||
#define I2C5_REGS ((volatile i2c_registers_t *)(get_i2c56_spi2b_base() + 0x000))
|
#define I2C5_REGS ((volatile tegra_i2c_t *)(get_i2c56_spi2b_base() + 0x000))
|
||||||
#define I2C6_REGS ((volatile i2c_registers_t *)(get_i2c56_spi2b_base() + 0x100))
|
#define I2C6_REGS ((volatile tegra_i2c_t *)(get_i2c56_spi2b_base() + 0x100))
|
||||||
|
|
||||||
void i2c_init(unsigned int id);
|
void i2c_config(I2CDevice id);
|
||||||
|
|
||||||
|
void i2c_init(I2CDevice id);
|
||||||
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||||
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||||
|
|
||||||
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
||||||
|
|
||||||
bool i2c_query_ti_charger_bit_7(void);
|
bool i2c_query_ti_charger_bit_7(void);
|
||||||
void i2c_clear_ti_charger_bit_7(void);
|
void i2c_clear_ti_charger_bit_7(void);
|
||||||
void i2c_set_ti_charger_bit_7(void);
|
void i2c_set_ti_charger_bit_7(void);
|
||||||
|
|||||||
@@ -18,26 +18,15 @@
|
|||||||
#define EXOSPHERE_MISC_H
|
#define EXOSPHERE_MISC_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
|
|
||||||
/* Exosphere driver for the Tegra X1 MISC Registers. */
|
/* Exosphere driver for the Tegra X1 MISC Registers. */
|
||||||
|
|
||||||
#define MISC_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MISC))
|
#define MISC_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MISC))
|
||||||
|
|
||||||
#define MAKE_MISC_REG(n) MAKE_REG32(MISC_BASE + n)
|
#define MAKE_MISC_REG(n) MAKE_REG32(MISC_BASE + n)
|
||||||
|
|
||||||
|
|
||||||
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 MAKE_MISC_REG(0x0C00)
|
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 MAKE_MISC_REG(0x0C00)
|
||||||
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 MAKE_MISC_REG(0x0C04)
|
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 MAKE_MISC_REG(0x0C04)
|
||||||
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 MAKE_MISC_REG(0x0C08)
|
#define APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 MAKE_MISC_REG(0x0C08)
|
||||||
|
|
||||||
#define PINMUX_AUX_GEN1_I2C_SCL_0 MAKE_MISC_REG(0x30BC)
|
|
||||||
#define PINMUX_AUX_GEN1_I2C_SDA_0 MAKE_MISC_REG(0x30C0)
|
|
||||||
|
|
||||||
#define PINMUX_AUX_UARTn_TX_0(n) MAKE_MISC_REG(0x30E4 + 0x10 * (n))
|
|
||||||
#define PINMUX_AUX_UARTn_RX_0(n) MAKE_MISC_REG(0x30E8 + 0x10 * (n))
|
|
||||||
#define PINMUX_AUX_UARTn_RTS_0(n) MAKE_MISC_REG(0x30EC + 0x10 * (n))
|
|
||||||
#define PINMUX_AUX_UARTn_CTS_0(n) MAKE_MISC_REG(0x30F0 + 0x10 * (n))
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
214
exosphere/src/pinmux.h
Normal file
214
exosphere/src/pinmux.h
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXOSPHERE_PINMUX_H
|
||||||
|
#define EXOSPHERE_PINMUX_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "memory_map.h"
|
||||||
|
|
||||||
|
#define PINMUX_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_MISC) + 0x3000)
|
||||||
|
#define MAKE_PINMUX_REG(n) MAKE_REG32(PINMUX_BASE + n)
|
||||||
|
|
||||||
|
#define PINMUX_TRISTATE (1 << 4)
|
||||||
|
#define PINMUX_PARKED (1 << 5)
|
||||||
|
#define PINMUX_INPUT (1 << 6)
|
||||||
|
#define PINMUX_PULL_NONE (0 << 2)
|
||||||
|
#define PINMUX_PULL_DOWN (1 << 2)
|
||||||
|
#define PINMUX_PULL_UP (2 << 2)
|
||||||
|
#define PINMUX_SELECT_FUNCTION0 0
|
||||||
|
#define PINMUX_SELECT_FUNCTION1 1
|
||||||
|
#define PINMUX_SELECT_FUNCTION2 2
|
||||||
|
#define PINMUX_SELECT_FUNCTION3 3
|
||||||
|
#define PINMUX_DRIVE_1X (0 << 13)
|
||||||
|
#define PINMUX_DRIVE_2X (1 << 13)
|
||||||
|
#define PINMUX_DRIVE_3X (2 << 13)
|
||||||
|
#define PINMUX_DRIVE_4X (3 << 13)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t sdmmc1_clk;
|
||||||
|
uint32_t sdmmc1_cmd;
|
||||||
|
uint32_t sdmmc1_dat3;
|
||||||
|
uint32_t sdmmc1_dat2;
|
||||||
|
uint32_t sdmmc1_dat1;
|
||||||
|
uint32_t sdmmc1_dat0;
|
||||||
|
uint32_t _r18;
|
||||||
|
uint32_t sdmmc3_clk;
|
||||||
|
uint32_t sdmmc3_cmd;
|
||||||
|
uint32_t sdmmc3_dat0;
|
||||||
|
uint32_t sdmmc3_dat1;
|
||||||
|
uint32_t sdmmc3_dat2;
|
||||||
|
uint32_t sdmmc3_dat3;
|
||||||
|
uint32_t _r34;
|
||||||
|
uint32_t pex_l0_rst_n;
|
||||||
|
uint32_t pex_l0_clkreq_n;
|
||||||
|
uint32_t pex_wake_n;
|
||||||
|
uint32_t pex_l1_rst_n;
|
||||||
|
uint32_t pex_l1_clkreq_n;
|
||||||
|
uint32_t sata_led_active;
|
||||||
|
uint32_t spi1_mosi;
|
||||||
|
uint32_t spi1_miso;
|
||||||
|
uint32_t spi1_sck;
|
||||||
|
uint32_t spi1_cs0;
|
||||||
|
uint32_t spi1_cs1;
|
||||||
|
uint32_t spi2_mosi;
|
||||||
|
uint32_t spi2_miso;
|
||||||
|
uint32_t spi2_sck;
|
||||||
|
uint32_t spi2_cs0;
|
||||||
|
uint32_t spi2_cs1;
|
||||||
|
uint32_t spi4_mosi;
|
||||||
|
uint32_t spi4_miso;
|
||||||
|
uint32_t spi4_sck;
|
||||||
|
uint32_t spi4_cs0;
|
||||||
|
uint32_t qspi_sck;
|
||||||
|
uint32_t qspi_cs_n;
|
||||||
|
uint32_t qspi_io0;
|
||||||
|
uint32_t qspi_io1;
|
||||||
|
uint32_t qspi_io2;
|
||||||
|
uint32_t qspi_io3;
|
||||||
|
uint32_t _ra0;
|
||||||
|
uint32_t dmic1_clk;
|
||||||
|
uint32_t dmic1_dat;
|
||||||
|
uint32_t dmic2_clk;
|
||||||
|
uint32_t dmic2_dat;
|
||||||
|
uint32_t dmic3_clk;
|
||||||
|
uint32_t dmic3_dat;
|
||||||
|
uint32_t gen1_i2c_scl;
|
||||||
|
uint32_t gen1_i2c_sda;
|
||||||
|
uint32_t gen2_i2c_scl;
|
||||||
|
uint32_t gen2_i2c_sda;
|
||||||
|
uint32_t gen3_i2c_scl;
|
||||||
|
uint32_t gen3_i2c_sda;
|
||||||
|
uint32_t cam_i2c_scl;
|
||||||
|
uint32_t cam_i2c_sda;
|
||||||
|
uint32_t pwr_i2c_scl;
|
||||||
|
uint32_t pwr_i2c_sda;
|
||||||
|
uint32_t uart1_tx;
|
||||||
|
uint32_t uart1_rx;
|
||||||
|
uint32_t uart1_rts;
|
||||||
|
uint32_t uart1_cts;
|
||||||
|
uint32_t uart2_tx;
|
||||||
|
uint32_t uart2_rx;
|
||||||
|
uint32_t uart2_rts;
|
||||||
|
uint32_t uart2_cts;
|
||||||
|
uint32_t uart3_tx;
|
||||||
|
uint32_t uart3_rx;
|
||||||
|
uint32_t uart3_rts;
|
||||||
|
uint32_t uart3_cts;
|
||||||
|
uint32_t uart4_tx;
|
||||||
|
uint32_t uart4_rx;
|
||||||
|
uint32_t uart4_rts;
|
||||||
|
uint32_t uart4_cts;
|
||||||
|
uint32_t dap1_fs;
|
||||||
|
uint32_t dap1_din;
|
||||||
|
uint32_t dap1_dout;
|
||||||
|
uint32_t dap1_sclk;
|
||||||
|
uint32_t dap2_fs;
|
||||||
|
uint32_t dap2_din;
|
||||||
|
uint32_t dap2_dout;
|
||||||
|
uint32_t dap2_sclk;
|
||||||
|
uint32_t dap4_fs;
|
||||||
|
uint32_t dap4_din;
|
||||||
|
uint32_t dap4_dout;
|
||||||
|
uint32_t dap4_sclk;
|
||||||
|
uint32_t cam1_mclk;
|
||||||
|
uint32_t cam2_mclk;
|
||||||
|
uint32_t jtag_rtck;
|
||||||
|
uint32_t clk_32k_in;
|
||||||
|
uint32_t clk_32k_out;
|
||||||
|
uint32_t batt_bcl;
|
||||||
|
uint32_t clk_req;
|
||||||
|
uint32_t cpu_pwr_req;
|
||||||
|
uint32_t pwr_int_n;
|
||||||
|
uint32_t shutdown;
|
||||||
|
uint32_t core_pwr_req;
|
||||||
|
uint32_t aud_mclk;
|
||||||
|
uint32_t dvfs_pwm;
|
||||||
|
uint32_t dvfs_clk;
|
||||||
|
uint32_t gpio_x1_aud;
|
||||||
|
uint32_t gpio_x3_aud;
|
||||||
|
uint32_t pcc7;
|
||||||
|
uint32_t hdmi_cec;
|
||||||
|
uint32_t hdmi_int_dp_hpd;
|
||||||
|
uint32_t spdif_out;
|
||||||
|
uint32_t spdif_in;
|
||||||
|
uint32_t usb_vbus_en0;
|
||||||
|
uint32_t usb_vbus_en1;
|
||||||
|
uint32_t dp_hpd0;
|
||||||
|
uint32_t wifi_en;
|
||||||
|
uint32_t wifi_rst;
|
||||||
|
uint32_t wifi_wake_ap;
|
||||||
|
uint32_t ap_wake_bt;
|
||||||
|
uint32_t bt_rst;
|
||||||
|
uint32_t bt_wake_ap;
|
||||||
|
uint32_t ap_wake_nfc;
|
||||||
|
uint32_t nfc_en;
|
||||||
|
uint32_t nfc_int;
|
||||||
|
uint32_t gps_en;
|
||||||
|
uint32_t gps_rst;
|
||||||
|
uint32_t cam_rst;
|
||||||
|
uint32_t cam_af_en;
|
||||||
|
uint32_t cam_flash_en;
|
||||||
|
uint32_t cam1_pwdn;
|
||||||
|
uint32_t cam2_pwdn;
|
||||||
|
uint32_t cam1_strobe;
|
||||||
|
uint32_t lcd_te;
|
||||||
|
uint32_t lcd_bl_pwm;
|
||||||
|
uint32_t lcd_bl_en;
|
||||||
|
uint32_t lcd_rst;
|
||||||
|
uint32_t lcd_gpio1;
|
||||||
|
uint32_t lcd_gpio2;
|
||||||
|
uint32_t ap_ready;
|
||||||
|
uint32_t touch_rst;
|
||||||
|
uint32_t touch_clk;
|
||||||
|
uint32_t modem_wake_ap;
|
||||||
|
uint32_t touch_int;
|
||||||
|
uint32_t motion_int;
|
||||||
|
uint32_t als_prox_int;
|
||||||
|
uint32_t temp_alert;
|
||||||
|
uint32_t button_power_on;
|
||||||
|
uint32_t button_vol_up;
|
||||||
|
uint32_t button_vol_down;
|
||||||
|
uint32_t button_slide_sw;
|
||||||
|
uint32_t button_home;
|
||||||
|
uint32_t pa6;
|
||||||
|
uint32_t pe6;
|
||||||
|
uint32_t pe7;
|
||||||
|
uint32_t ph6;
|
||||||
|
uint32_t pk0;
|
||||||
|
uint32_t pk1;
|
||||||
|
uint32_t pk2;
|
||||||
|
uint32_t pk3;
|
||||||
|
uint32_t pk4;
|
||||||
|
uint32_t pk5;
|
||||||
|
uint32_t pk6;
|
||||||
|
uint32_t pk7;
|
||||||
|
uint32_t pl0;
|
||||||
|
uint32_t pl1;
|
||||||
|
uint32_t pz0;
|
||||||
|
uint32_t pz1;
|
||||||
|
uint32_t pz2;
|
||||||
|
uint32_t pz3;
|
||||||
|
uint32_t pz4;
|
||||||
|
uint32_t pz5;
|
||||||
|
} tegra_pinmux_t;
|
||||||
|
|
||||||
|
static inline volatile tegra_pinmux_t *pinmux_get_regs(void)
|
||||||
|
{
|
||||||
|
return (volatile tegra_pinmux_t *)PINMUX_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -15,66 +15,120 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "timers.h"
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "misc.h"
|
#include "timers.h"
|
||||||
|
#include "pinmux.h"
|
||||||
|
|
||||||
void uart_select(UartDevice dev) {
|
static inline void uart_wait_cycles(uint32_t baud, uint32_t num)
|
||||||
unsigned int id = (unsigned int)dev;
|
{
|
||||||
PINMUX_AUX_UARTn_TX_0(id) = 0; /* UART */
|
wait((num * 1000000 + 16 * baud - 1) / (16 * baud));
|
||||||
PINMUX_AUX_UARTn_RX_0(id) = 0x48; /* UART, enable, pull up */
|
}
|
||||||
PINMUX_AUX_UARTn_RTS_0(id) = 0; /* UART */
|
|
||||||
PINMUX_AUX_UARTn_CTS_0(id) = 0x44; /* UART, enable, pull down */
|
static inline void uart_wait_syms(uint32_t baud, uint32_t num)
|
||||||
|
{
|
||||||
|
wait((num * 1000000 + baud - 1) / baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_config(UartDevice dev) {
|
||||||
|
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||||
|
|
||||||
|
switch (dev) {
|
||||||
|
case UART_A:
|
||||||
|
pinmux->uart1_tx = 0;
|
||||||
|
pinmux->uart1_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
||||||
|
pinmux->uart1_rts = 0;
|
||||||
|
pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||||
|
break;
|
||||||
|
case UART_B:
|
||||||
|
pinmux->uart2_tx = 0;
|
||||||
|
pinmux->uart2_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
||||||
|
pinmux->uart2_rts = 0;
|
||||||
|
pinmux->uart2_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||||
|
break;
|
||||||
|
case UART_C:
|
||||||
|
pinmux->uart3_tx = 0;
|
||||||
|
pinmux->uart3_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
||||||
|
pinmux->uart3_rts = 0;
|
||||||
|
pinmux->uart3_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||||
|
break;
|
||||||
|
case UART_D:
|
||||||
|
pinmux->uart4_tx = 0;
|
||||||
|
pinmux->uart4_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
||||||
|
pinmux->uart4_rts = 0;
|
||||||
|
pinmux->uart4_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||||
|
break;
|
||||||
|
case UART_E:
|
||||||
|
/* Unused. */
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_init(UartDevice dev, uint32_t baud) {
|
void uart_init(UartDevice dev, uint32_t baud) {
|
||||||
volatile uart_t *uart = get_uart_device(dev);
|
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||||
|
|
||||||
/* Set baud rate. */
|
/* Wait for idle state. */
|
||||||
|
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE);
|
||||||
|
|
||||||
|
/* Calculate baud rate, round to nearest. */
|
||||||
uint32_t rate = (8 * baud + 408000000) / (16 * baud);
|
uint32_t rate = (8 * baud + 408000000) / (16 * baud);
|
||||||
uart->UART_LCR = UART_LCR_DLAB; /* Enable DLAB. */
|
|
||||||
uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */
|
|
||||||
uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */
|
|
||||||
uart->UART_LCR = 0; /* Diable DLAB. */
|
|
||||||
|
|
||||||
/* Setup UART in fifo mode. */
|
/* Setup UART in FIFO mode. */
|
||||||
uart->UART_IER_DLAB = 0;
|
uart->UART_IER_DLAB = 0;
|
||||||
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */
|
|
||||||
uart->UART_LSR;
|
|
||||||
wait(3 * ((baud + 999999) / baud));
|
|
||||||
uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */
|
|
||||||
uart->UART_MCR = 0;
|
uart->UART_MCR = 0;
|
||||||
uart->UART_MSR = 0;
|
uart->UART_LCR = (UART_LCR_DLAB | UART_LCR_WD_LENGTH_8); /* Enable DLAB and set word length 8. */
|
||||||
uart->UART_IRDA_CSR = 0;
|
uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */
|
||||||
uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */
|
uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */
|
||||||
uart->UART_MIE = 0;
|
uart->UART_LCR &= ~(UART_LCR_DLAB); /* Disable DLAB. */
|
||||||
uart->UART_ASR = 0;
|
uart->UART_SPR; /* Dummy read. */
|
||||||
|
uart_wait_syms(baud, 3); /* Wait for 3 symbols at the new baudrate. */
|
||||||
|
|
||||||
|
/* Enable FIFO with default settings. */
|
||||||
|
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO;
|
||||||
|
uart->UART_SPR; /* Dummy read as mandated by TRM. */
|
||||||
|
uart_wait_cycles(baud, 3); /* Wait for 3 baud cycles, as mandated by TRM (erratum). */
|
||||||
|
|
||||||
|
/* Flush FIFO. */
|
||||||
|
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE); /* Make sure there's no data being written in TX FIFO (TRM). */
|
||||||
|
uart->UART_IIR_FCR |= UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Clear TX and RX FIFOs. */
|
||||||
|
uart_wait_cycles(baud, 32); /* Wait for 32 baud cycles (TRM, erratum). */
|
||||||
|
/* Wait for idle state (TRM). */
|
||||||
|
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE | UART_VENDOR_STATE_RX_IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function blocks until the UART device (dev) is in the desired state (status). Make sure the desired state can be reached! */
|
/* This function blocks until the UART device is in the desired state. */
|
||||||
void uart_wait_idle(UartDevice dev, UartVendorStatus status) {
|
void uart_wait_idle(UartDevice dev, UartVendorStatus status) {
|
||||||
while (!(get_uart_device(dev)->UART_VENDOR_STATUS & status)) {
|
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||||
/* Wait */
|
|
||||||
|
if (status & UART_VENDOR_STATE_TX_IDLE) {
|
||||||
|
while (!(uart->UART_LSR & UART_LSR_TMTY)) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (status & UART_VENDOR_STATE_RX_IDLE) {
|
||||||
|
while (uart->UART_LSR & UART_LSR_RDR) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_send(UartDevice dev, const void *buf, size_t len) {
|
void uart_send(UartDevice dev, const void *buf, size_t len) {
|
||||||
volatile uart_t *uart = get_uart_device(dev);
|
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL) {
|
while (!(uart->UART_LSR & UART_LSR_THRE)) {
|
||||||
/* Wait until the TX FIFO isn't full */
|
/* Wait until it's possible to send data. */
|
||||||
}
|
}
|
||||||
uart->UART_THR_DLAB = *((const uint8_t *)buf + i);
|
uart->UART_THR_DLAB = *((const uint8_t *)buf + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_recv(UartDevice dev, void *buf, size_t len) {
|
void uart_recv(UartDevice dev, void *buf, size_t len) {
|
||||||
volatile uart_t *uart = get_uart_device(dev);
|
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY) {
|
while (!(uart->UART_LSR & UART_LSR_RDR)) {
|
||||||
/* Wait until the RX FIFO isn't empty */
|
/* Wait until it's possible to receive data. */
|
||||||
}
|
}
|
||||||
*((uint8_t *)buf + i) = uart->UART_THR_DLAB;
|
*((uint8_t *)buf + i) = uart->UART_THR_DLAB;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ static inline uintptr_t get_uart_base(void) {
|
|||||||
|
|
||||||
#define BAUD_115200 115200
|
#define BAUD_115200 115200
|
||||||
|
|
||||||
/* Exosphère: add the clkreset values for UART C,D,E */
|
/* UART devices */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UART_A = 0,
|
UART_A = 0,
|
||||||
UART_B = 1,
|
UART_B = 1,
|
||||||
@@ -148,31 +148,31 @@ typedef enum {
|
|||||||
} UartInterruptIdentification;
|
} UartInterruptIdentification;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x00 */ uint32_t UART_THR_DLAB;
|
uint32_t UART_THR_DLAB;
|
||||||
/* 0x04 */ uint32_t UART_IER_DLAB;
|
uint32_t UART_IER_DLAB;
|
||||||
/* 0x08 */ uint32_t UART_IIR_FCR;
|
uint32_t UART_IIR_FCR;
|
||||||
/* 0x0C */ uint32_t UART_LCR;
|
uint32_t UART_LCR;
|
||||||
/* 0x10 */ uint32_t UART_MCR;
|
uint32_t UART_MCR;
|
||||||
/* 0x14 */ uint32_t UART_LSR;
|
uint32_t UART_LSR;
|
||||||
/* 0x18 */ uint32_t UART_MSR;
|
uint32_t UART_MSR;
|
||||||
/* 0x1C */ uint32_t UART_SPR;
|
uint32_t UART_SPR;
|
||||||
/* 0x20 */ uint32_t UART_IRDA_CSR;
|
uint32_t UART_IRDA_CSR;
|
||||||
/* 0x24 */ uint32_t UART_RX_FIFO_CFG;
|
uint32_t UART_RX_FIFO_CFG;
|
||||||
/* 0x28 */ uint32_t UART_MIE;
|
uint32_t UART_MIE;
|
||||||
/* 0x2C */ uint32_t UART_VENDOR_STATUS;
|
uint32_t UART_VENDOR_STATUS;
|
||||||
/* 0x30 */ uint8_t _pad_30[0x0C];
|
uint8_t _0x30[0x0C];
|
||||||
/* 0x3C */ uint32_t UART_ASR;
|
uint32_t UART_ASR;
|
||||||
} uart_t;
|
} tegra_uart_t;
|
||||||
|
|
||||||
void uart_select(UartDevice dev);
|
void uart_config(UartDevice dev);
|
||||||
void uart_init(UartDevice dev, uint32_t baud);
|
void uart_init(UartDevice dev, uint32_t baud);
|
||||||
void uart_wait_idle(UartDevice dev, UartVendorStatus status);
|
void uart_wait_idle(UartDevice dev, UartVendorStatus status);
|
||||||
void uart_send(UartDevice dev, const void *buf, size_t len);
|
void uart_send(UartDevice dev, const void *buf, size_t len);
|
||||||
void uart_recv(UartDevice dev, void *buf, size_t len);
|
void uart_recv(UartDevice dev, void *buf, size_t len);
|
||||||
|
|
||||||
static inline volatile uart_t *get_uart_device(UartDevice dev) {
|
static inline volatile tegra_uart_t *uart_get_regs(UartDevice dev) {
|
||||||
static const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400};
|
static const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400};
|
||||||
return (volatile uart_t *)(UART_BASE + offsets[dev]);
|
return (volatile tegra_uart_t *)(UART_BASE + offsets[dev]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "bootup.h"
|
#include "bootup.h"
|
||||||
#include "smc_api.h"
|
#include "smc_api.h"
|
||||||
#include "exocfg.h"
|
#include "exocfg.h"
|
||||||
|
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
@@ -32,7 +31,6 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
|
|
||||||
#include "pmc.h"
|
#include "pmc.h"
|
||||||
|
|
||||||
uintptr_t get_warmboot_main_stack_address(void) {
|
uintptr_t get_warmboot_main_stack_address(void) {
|
||||||
@@ -41,8 +39,7 @@ uintptr_t get_warmboot_main_stack_address(void) {
|
|||||||
|
|
||||||
static void warmboot_configure_hiz_mode(void) {
|
static void warmboot_configure_hiz_mode(void) {
|
||||||
/* Enable input to I2C1 */
|
/* Enable input to I2C1 */
|
||||||
PINMUX_AUX_GEN1_I2C_SCL_0 = 0x40;
|
i2c_config(I2C_1);
|
||||||
PINMUX_AUX_GEN1_I2C_SDA_0 = 0x40;
|
|
||||||
|
|
||||||
clkrst_reboot(CARDEVICE_I2C1);
|
clkrst_reboot(CARDEVICE_I2C1);
|
||||||
i2c_init(0);
|
i2c_init(0);
|
||||||
@@ -69,7 +66,7 @@ void __attribute__((noreturn)) warmboot_main(void) {
|
|||||||
if (VIRT_MC_SECURITY_CFG3 == 0) {
|
if (VIRT_MC_SECURITY_CFG3 == 0) {
|
||||||
/* N only does this on dev units, but we will do it unconditionally. */
|
/* N only does this on dev units, but we will do it unconditionally. */
|
||||||
{
|
{
|
||||||
uart_select(UART_A);
|
uart_config(UART_A);
|
||||||
clkrst_reboot(CARDEVICE_UARTA);
|
clkrst_reboot(CARDEVICE_UARTA);
|
||||||
uart_init(UART_A, 115200);
|
uart_init(UART_A, 115200);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SUBFOLDERS := fusee-primary fusee-secondary
|
SUBFOLDERS := fusee-primary fusee-mtc fusee-secondary
|
||||||
|
|
||||||
TOPTARGETS := all clean
|
TOPTARGETS := all clean
|
||||||
|
|
||||||
|
|||||||
163
fusee/fusee-mtc/Makefile
Normal file
163
fusee/fusee-mtc/Makefile
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
TOPDIR ?= $(CURDIR)
|
||||||
|
|
||||||
|
AMS := $(TOPDIR)/../../
|
||||||
|
include $(DEVKITARM)/base_rules
|
||||||
|
|
||||||
|
AMSBRANCH := $(shell git symbolic-ref --short HEAD)
|
||||||
|
AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD)
|
||||||
|
|
||||||
|
ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
|
||||||
|
AMSREV := $(AMSREV)-dirty
|
||||||
|
endif
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# DATA is a list of directories containing data files
|
||||||
|
# INCLUDES is a list of directories containing header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := src src/lib src/display
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||||
|
DEFINES := -D__BPMP__ -DFUSEE_STAGE1_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"
|
||||||
|
|
||||||
|
CFLAGS := \
|
||||||
|
-g \
|
||||||
|
-O2 \
|
||||||
|
-fomit-frame-pointer \
|
||||||
|
-ffunction-sections \
|
||||||
|
-fdata-sections \
|
||||||
|
-std=gnu11 \
|
||||||
|
-Werror \
|
||||||
|
-Wall \
|
||||||
|
-fstrict-volatile-bitfields \
|
||||||
|
$(ARCH) $(DEFINES)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE)
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD)
|
||||||
|
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all : $(OUTPUT).bin
|
||||||
|
|
||||||
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
|
$(OBJCOPY) -S -O binary $< $@
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
%.elf: $(OFILES)
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||||
|
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||||
|
|
||||||
|
$(OFILES_SRC) : $(HFILES_BIN)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o %_bin.h: %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
170
fusee/fusee-mtc/linker.ld
Normal file
170
fusee/fusee-mtc/linker.ld
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
crt0 PT_LOAD;
|
||||||
|
main PT_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
NULL : ORIGIN = 0x00000000, LENGTH = 0x1000
|
||||||
|
main : ORIGIN = 0xF0000000, LENGTH = 0x10000000
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
PROVIDE(__start__ = 0xF0000000);
|
||||||
|
PROVIDE(__stack_bottom__ = 0x90010000);
|
||||||
|
PROVIDE(__stack_top__ = 0x90020000);
|
||||||
|
PROVIDE(__heap_start__ = 0x90020000);
|
||||||
|
PROVIDE(__heap_end__ = 0xA0020000);
|
||||||
|
|
||||||
|
. = __start__;
|
||||||
|
|
||||||
|
.crt0 :
|
||||||
|
{
|
||||||
|
KEEP( *(.text.start) )
|
||||||
|
KEEP( *(.init) )
|
||||||
|
. = ALIGN(32);
|
||||||
|
} >main :crt0
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
. = ALIGN(32);
|
||||||
|
/* .text */
|
||||||
|
*(.text)
|
||||||
|
*(.text.*)
|
||||||
|
*(.glue_7)
|
||||||
|
*(.glue_7t)
|
||||||
|
*(.stub)
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.gnu.linkonce.t*)
|
||||||
|
|
||||||
|
/* .fini */
|
||||||
|
KEEP( *(.fini) )
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >main :main
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
*(.roda)
|
||||||
|
*(.rodata.*)
|
||||||
|
*all.rodata*(*)
|
||||||
|
*(.gnu.linkonce.r*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.init_array ALIGN(4) :
|
||||||
|
{
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
KEEP (*(SORT(.init_array.*)))
|
||||||
|
KEEP (*(.init_array))
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.fini_array ALIGN(4) :
|
||||||
|
{
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
KEEP (*(.fini_array))
|
||||||
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.ctors ALIGN(4) :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.dtors ALIGN(4) :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main
|
||||||
|
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
*(.gnu.linkonce.d*)
|
||||||
|
CONSTRUCTORS
|
||||||
|
. = ALIGN(32);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN(32);
|
||||||
|
PROVIDE (__bss_start__ = ABSOLUTE(.));
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(.gnu.linkonce.b*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(32);
|
||||||
|
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
||||||
|
} >main :NONE
|
||||||
|
__end__ = ABSOLUTE(.) ;
|
||||||
|
|
||||||
|
|
||||||
|
/* ==================
|
||||||
|
==== Metadata ====
|
||||||
|
================== */
|
||||||
|
|
||||||
|
/* Discard sections that difficult post-processing */
|
||||||
|
/DISCARD/ : { *(.group .comment .note) }
|
||||||
|
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
}
|
||||||
7
fusee/fusee-mtc/linker.specs
Normal file
7
fusee/fusee-mtc/linker.specs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
%rename link old_link
|
||||||
|
|
||||||
|
*link:
|
||||||
|
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
|
||||||
|
|
||||||
|
*startfile:
|
||||||
|
crti%O%s crtbegin%O%s
|
||||||
139
fusee/fusee-mtc/src/car.c
Normal file
139
fusee/fusee-mtc/src/car.c
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "car.h"
|
||||||
|
#include "timers.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
|
switch (dev) {
|
||||||
|
case CARDEVICE_UARTA: return 0x178;
|
||||||
|
case CARDEVICE_UARTB: return 0x17C;
|
||||||
|
case CARDEVICE_UARTC: return 0x1A0;
|
||||||
|
case CARDEVICE_I2C1: return 0x124;
|
||||||
|
case CARDEVICE_I2C5: return 0x128;
|
||||||
|
case CARDEVICE_TZRAM: return 0;
|
||||||
|
case CARDEVICE_SE: return 0x42C;
|
||||||
|
case CARDEVICE_HOST1X: return 0x180;
|
||||||
|
case CARDEVICE_TSEC: return 0x1F4;
|
||||||
|
case CARDEVICE_SOR_SAFE: return 0;
|
||||||
|
case CARDEVICE_SOR0: return 0;
|
||||||
|
case CARDEVICE_SOR1: return 0x410;
|
||||||
|
case CARDEVICE_KFUSE: return 0;
|
||||||
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
|
case CARDEVICE_CORESIGHT: return 0x1D4;
|
||||||
|
case CARDEVICE_ACTMON: return 0x3E8;
|
||||||
|
case CARDEVICE_BPMP: return 0;
|
||||||
|
default: generic_panic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||||
|
switch (dev) {
|
||||||
|
case CARDEVICE_UARTA: return 0;
|
||||||
|
case CARDEVICE_UARTB: return 0;
|
||||||
|
case CARDEVICE_UARTC: return 0;
|
||||||
|
case CARDEVICE_I2C1: return 6;
|
||||||
|
case CARDEVICE_I2C5: return 6;
|
||||||
|
case CARDEVICE_TZRAM: return 0;
|
||||||
|
case CARDEVICE_SE: return 0;
|
||||||
|
case CARDEVICE_HOST1X: return 4;
|
||||||
|
case CARDEVICE_TSEC: return 0;
|
||||||
|
case CARDEVICE_SOR_SAFE: return 0;
|
||||||
|
case CARDEVICE_SOR0: return 0;
|
||||||
|
case CARDEVICE_SOR1: return 0;
|
||||||
|
case CARDEVICE_KFUSE: return 0;
|
||||||
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
|
case CARDEVICE_CORESIGHT: return 0;
|
||||||
|
case CARDEVICE_ACTMON: return 6;
|
||||||
|
case CARDEVICE_BPMP: return 0;
|
||||||
|
default: generic_panic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||||
|
switch (dev) {
|
||||||
|
case CARDEVICE_UARTA: return 0;
|
||||||
|
case CARDEVICE_UARTB: return 0;
|
||||||
|
case CARDEVICE_UARTC: return 0;
|
||||||
|
case CARDEVICE_I2C1: return 0;
|
||||||
|
case CARDEVICE_I2C5: return 0;
|
||||||
|
case CARDEVICE_TZRAM: return 0;
|
||||||
|
case CARDEVICE_SE: return 0;
|
||||||
|
case CARDEVICE_HOST1X: return 3;
|
||||||
|
case CARDEVICE_TSEC: return 2;
|
||||||
|
case CARDEVICE_SOR_SAFE: return 0;
|
||||||
|
case CARDEVICE_SOR0: return 0;
|
||||||
|
case CARDEVICE_SOR1: return 2;
|
||||||
|
case CARDEVICE_KFUSE: return 0;
|
||||||
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
|
case CARDEVICE_CORESIGHT: return 4;
|
||||||
|
case CARDEVICE_ACTMON: return 0;
|
||||||
|
case CARDEVICE_BPMP: return 0;
|
||||||
|
default: generic_panic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298};
|
||||||
|
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4};
|
||||||
|
|
||||||
|
void clk_enable(CarDevice dev) {
|
||||||
|
uint32_t clk_source_reg;
|
||||||
|
if ((clk_source_reg = get_clk_source_reg(dev))) {
|
||||||
|
MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev);
|
||||||
|
}
|
||||||
|
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clk_disable(CarDevice dev) {
|
||||||
|
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rst_enable(CarDevice dev) {
|
||||||
|
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rst_disable(CarDevice dev) {
|
||||||
|
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F));
|
||||||
|
}
|
||||||
|
|
||||||
|
void clkrst_enable(CarDevice dev) {
|
||||||
|
clk_enable(dev);
|
||||||
|
rst_disable(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clkrst_disable(CarDevice dev) {
|
||||||
|
rst_enable(dev);
|
||||||
|
clk_disable(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clkrst_reboot(CarDevice dev) {
|
||||||
|
clkrst_disable(dev);
|
||||||
|
if (dev == CARDEVICE_KFUSE) {
|
||||||
|
/* Workaround for KFUSE clock. */
|
||||||
|
clk_enable(dev);
|
||||||
|
udelay(100);
|
||||||
|
rst_disable(dev);
|
||||||
|
udelay(200);
|
||||||
|
} else {
|
||||||
|
clkrst_enable(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clkrst_enable_fuse_regs(bool enable) {
|
||||||
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28));
|
||||||
|
}
|
||||||
505
fusee/fusee-mtc/src/car.h
Normal file
505
fusee/fusee-mtc/src/car.h
Normal file
@@ -0,0 +1,505 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_CAR_H
|
||||||
|
#define FUSEE_CAR_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define CAR_BASE 0x60006000
|
||||||
|
#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n)
|
||||||
|
|
||||||
|
#define CLK_L_SDMMC1 (1 << 14)
|
||||||
|
#define CLK_L_SDMMC2 (1 << 9)
|
||||||
|
#define CLK_U_SDMMC3 (1 << 5)
|
||||||
|
#define CLK_L_SDMMC4 (1 << 15)
|
||||||
|
|
||||||
|
#define CLK_SOURCE_MASK (0b111 << 29)
|
||||||
|
#define CLK_SOURCE_FIRST (0b000 << 29)
|
||||||
|
#define CLK_DIVIDER_MASK (0xff << 0)
|
||||||
|
#define CLK_DIVIDER_UNITY (0x00 << 0)
|
||||||
|
|
||||||
|
#define NUM_CAR_BANKS 7
|
||||||
|
|
||||||
|
/* Clock and reset devices. */
|
||||||
|
typedef enum {
|
||||||
|
CARDEVICE_UARTA = ((0 << 5) | 0x6),
|
||||||
|
CARDEVICE_UARTB = ((0 << 5) | 0x7),
|
||||||
|
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||||
|
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||||
|
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||||
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
|
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
||||||
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
|
||||||
|
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
|
||||||
|
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
|
||||||
|
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
|
||||||
|
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
|
||||||
|
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||||
|
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||||
|
CARDEVICE_BPMP = ((0 << 5) | 0x1)
|
||||||
|
} CarDevice;
|
||||||
|
|
||||||
|
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
|
||||||
|
typedef struct {
|
||||||
|
uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */
|
||||||
|
|
||||||
|
/* _RST_DEVICES_L/H/U_0 0x4-0xc */
|
||||||
|
uint32_t rst_dev_l;
|
||||||
|
uint32_t rst_dev_h;
|
||||||
|
uint32_t rst_dev_u;
|
||||||
|
|
||||||
|
/* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */
|
||||||
|
uint32_t clk_out_enb_l;
|
||||||
|
uint32_t clk_out_enb_h;
|
||||||
|
uint32_t clk_out_enb_u;
|
||||||
|
|
||||||
|
uint32_t _0x1C;
|
||||||
|
uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */
|
||||||
|
uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */
|
||||||
|
uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */
|
||||||
|
uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */
|
||||||
|
uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */
|
||||||
|
uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */
|
||||||
|
uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */
|
||||||
|
uint32_t _0x3C;
|
||||||
|
uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */
|
||||||
|
uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */
|
||||||
|
uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */
|
||||||
|
uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */
|
||||||
|
uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */
|
||||||
|
uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */
|
||||||
|
uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */
|
||||||
|
uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */
|
||||||
|
uint32_t _0x60[2];
|
||||||
|
uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */
|
||||||
|
uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */
|
||||||
|
uint32_t _0x70[4];
|
||||||
|
|
||||||
|
/* PLLC 0x80-0x8c */
|
||||||
|
uint32_t pllc_base;
|
||||||
|
uint32_t pllc_out;
|
||||||
|
uint32_t pllc_misc0;
|
||||||
|
uint32_t pllc_misc1;
|
||||||
|
|
||||||
|
/* PLLM 0x90-0x9c */
|
||||||
|
uint32_t pllm_base;
|
||||||
|
uint32_t pllm_out;
|
||||||
|
uint32_t pllm_misc1;
|
||||||
|
uint32_t pllm_misc2;
|
||||||
|
|
||||||
|
/* PLLP 0xa0-0xac */
|
||||||
|
uint32_t pllp_base;
|
||||||
|
uint32_t pllp_outa;
|
||||||
|
uint32_t pllp_outb;
|
||||||
|
uint32_t pllp_misc;
|
||||||
|
|
||||||
|
/* PLLA 0xb0-0xbc */
|
||||||
|
uint32_t plla_base;
|
||||||
|
uint32_t plla_out;
|
||||||
|
uint32_t plla_misc0;
|
||||||
|
uint32_t plla_misc1;
|
||||||
|
|
||||||
|
/* PLLU 0xc0-0xcc */
|
||||||
|
uint32_t pllu_base;
|
||||||
|
uint32_t pllu_out;
|
||||||
|
uint32_t pllu_misc1;
|
||||||
|
uint32_t pllu_misc2;
|
||||||
|
|
||||||
|
/* PLLD 0xd0-0xdc */
|
||||||
|
uint32_t plld_base;
|
||||||
|
uint32_t plld_out;
|
||||||
|
uint32_t plld_misc1;
|
||||||
|
uint32_t plld_misc2;
|
||||||
|
|
||||||
|
/* PLLX 0xe0-0xe4 */
|
||||||
|
uint32_t pllx_base;
|
||||||
|
uint32_t pllx_misc;
|
||||||
|
|
||||||
|
/* PLLE 0xe8-0xf4 */
|
||||||
|
uint32_t plle_base;
|
||||||
|
uint32_t plle_misc;
|
||||||
|
uint32_t plle_ss_cntl1;
|
||||||
|
uint32_t plle_ss_cntl2;
|
||||||
|
|
||||||
|
uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */
|
||||||
|
uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */
|
||||||
|
|
||||||
|
uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */
|
||||||
|
uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */
|
||||||
|
uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */
|
||||||
|
uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */
|
||||||
|
uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */
|
||||||
|
uint32_t _0x114;
|
||||||
|
uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */
|
||||||
|
uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */
|
||||||
|
uint32_t _0x120;
|
||||||
|
uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */
|
||||||
|
uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */
|
||||||
|
uint32_t _0x12c[2];
|
||||||
|
uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */
|
||||||
|
uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */
|
||||||
|
uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */
|
||||||
|
uint32_t _0x140;
|
||||||
|
uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */
|
||||||
|
uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */
|
||||||
|
uint32_t _0x14c;
|
||||||
|
uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */
|
||||||
|
uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */
|
||||||
|
uint32_t _0x158[3];
|
||||||
|
uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */
|
||||||
|
uint32_t _0x168[4];
|
||||||
|
uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */
|
||||||
|
uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */
|
||||||
|
uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */
|
||||||
|
uint32_t _0x184[5];
|
||||||
|
uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */
|
||||||
|
uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */
|
||||||
|
uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */
|
||||||
|
uint32_t _0x1a4;
|
||||||
|
uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */
|
||||||
|
uint32_t _0x1ac[2];
|
||||||
|
uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */
|
||||||
|
uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */
|
||||||
|
uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */
|
||||||
|
uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */
|
||||||
|
uint32_t _0x1c4[2];
|
||||||
|
uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */
|
||||||
|
uint32_t _0x1d0;
|
||||||
|
uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */
|
||||||
|
uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */
|
||||||
|
uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */
|
||||||
|
uint32_t _0x1e0[5];
|
||||||
|
uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */
|
||||||
|
uint32_t _0x1f8;
|
||||||
|
|
||||||
|
uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */
|
||||||
|
uint32_t _0x200[32];
|
||||||
|
|
||||||
|
uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */
|
||||||
|
uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */
|
||||||
|
uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */
|
||||||
|
|
||||||
|
uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */
|
||||||
|
uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */
|
||||||
|
uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */
|
||||||
|
|
||||||
|
uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */
|
||||||
|
uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */
|
||||||
|
uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */
|
||||||
|
|
||||||
|
uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */
|
||||||
|
uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */
|
||||||
|
uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */
|
||||||
|
|
||||||
|
uint32_t _0x2b0[17];
|
||||||
|
uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */
|
||||||
|
uint32_t _0x2f8[2];
|
||||||
|
|
||||||
|
/* _RST_DEV_L/H/U_SET_0 0x300-0x314 */
|
||||||
|
uint32_t rst_dev_l_set;
|
||||||
|
uint32_t rst_dev_l_clr;
|
||||||
|
uint32_t rst_dev_h_set;
|
||||||
|
uint32_t rst_dev_h_clr;
|
||||||
|
uint32_t rst_dev_u_set;
|
||||||
|
uint32_t rst_dev_u_clr;
|
||||||
|
|
||||||
|
uint32_t _0x318[2];
|
||||||
|
|
||||||
|
/* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */
|
||||||
|
uint32_t clk_enb_l_set;
|
||||||
|
uint32_t clk_enb_l_clr;
|
||||||
|
uint32_t clk_enb_h_set;
|
||||||
|
uint32_t clk_enb_h_clr;
|
||||||
|
uint32_t clk_enb_u_set;
|
||||||
|
uint32_t clk_enb_u_clr;
|
||||||
|
|
||||||
|
uint32_t _0x338;
|
||||||
|
uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */
|
||||||
|
uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */
|
||||||
|
uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */
|
||||||
|
|
||||||
|
/* Additional (T30) registers */
|
||||||
|
uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */
|
||||||
|
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
|
||||||
|
|
||||||
|
uint32_t _0x350[2];
|
||||||
|
uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */
|
||||||
|
uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */
|
||||||
|
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */
|
||||||
|
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */
|
||||||
|
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
|
||||||
|
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */
|
||||||
|
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
|
||||||
|
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
|
||||||
|
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
|
||||||
|
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */
|
||||||
|
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
|
||||||
|
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
|
||||||
|
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
|
||||||
|
uint32_t _0x38c[5];
|
||||||
|
uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */
|
||||||
|
uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */
|
||||||
|
uint32_t _0x3a8[2];
|
||||||
|
|
||||||
|
uint32_t _0x3b0;
|
||||||
|
uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */
|
||||||
|
uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */
|
||||||
|
uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */
|
||||||
|
uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */
|
||||||
|
uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */
|
||||||
|
uint32_t _0x3c8[2];
|
||||||
|
uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */
|
||||||
|
uint32_t _0x3d4[4];
|
||||||
|
uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */
|
||||||
|
uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */
|
||||||
|
uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */
|
||||||
|
uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */
|
||||||
|
uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */
|
||||||
|
uint32_t _0x3f8;
|
||||||
|
uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */
|
||||||
|
uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */
|
||||||
|
uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */
|
||||||
|
uint32_t _0x408[2];
|
||||||
|
uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */
|
||||||
|
uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */
|
||||||
|
uint32_t _0x418[2];
|
||||||
|
uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */
|
||||||
|
uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */
|
||||||
|
uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */
|
||||||
|
uint32_t _0x42c;
|
||||||
|
|
||||||
|
/* _RST_DEV_V/W_SET_0 0x430-0x43c */
|
||||||
|
uint32_t rst_dev_v_set;
|
||||||
|
uint32_t rst_dev_v_clr;
|
||||||
|
uint32_t rst_dev_w_set;
|
||||||
|
uint32_t rst_dev_w_clr;
|
||||||
|
|
||||||
|
/* _CLK_ENB_V/W_CLR_0 0x440-0x44c */
|
||||||
|
uint32_t clk_enb_v_set;
|
||||||
|
uint32_t clk_enb_v_clr;
|
||||||
|
uint32_t clk_enb_w_set;
|
||||||
|
uint32_t clk_enb_w_clr;
|
||||||
|
|
||||||
|
/* Additional (T114+) registers */
|
||||||
|
uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */
|
||||||
|
uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */
|
||||||
|
uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */
|
||||||
|
uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */
|
||||||
|
uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */
|
||||||
|
uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */
|
||||||
|
uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */
|
||||||
|
uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */
|
||||||
|
uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */
|
||||||
|
uint32_t _0x474;
|
||||||
|
uint32_t intstatus; /* _INTSTATUS_0, 0x478 */
|
||||||
|
uint32_t intmask; /* _INTMASK_0, 0x47c */
|
||||||
|
uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */
|
||||||
|
uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */
|
||||||
|
uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */
|
||||||
|
|
||||||
|
uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */
|
||||||
|
uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */
|
||||||
|
uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */
|
||||||
|
uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */
|
||||||
|
|
||||||
|
uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */
|
||||||
|
uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */
|
||||||
|
uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */
|
||||||
|
uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */
|
||||||
|
uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */
|
||||||
|
uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */
|
||||||
|
uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */
|
||||||
|
|
||||||
|
uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */
|
||||||
|
uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */
|
||||||
|
uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */
|
||||||
|
uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */
|
||||||
|
uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */
|
||||||
|
uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */
|
||||||
|
uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */
|
||||||
|
uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */
|
||||||
|
uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */
|
||||||
|
uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */
|
||||||
|
uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */
|
||||||
|
uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */
|
||||||
|
uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */
|
||||||
|
uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */
|
||||||
|
uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */
|
||||||
|
uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */
|
||||||
|
uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */
|
||||||
|
uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */
|
||||||
|
uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */
|
||||||
|
uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */
|
||||||
|
uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */
|
||||||
|
uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */
|
||||||
|
uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */
|
||||||
|
uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */
|
||||||
|
uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */
|
||||||
|
uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */
|
||||||
|
uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */
|
||||||
|
uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */
|
||||||
|
uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */
|
||||||
|
uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */
|
||||||
|
uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */
|
||||||
|
uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */
|
||||||
|
uint32_t _0x538;
|
||||||
|
uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */
|
||||||
|
uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */
|
||||||
|
uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */
|
||||||
|
uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */
|
||||||
|
uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */
|
||||||
|
uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */
|
||||||
|
uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */
|
||||||
|
uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */
|
||||||
|
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */
|
||||||
|
uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */
|
||||||
|
uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */
|
||||||
|
|
||||||
|
uint32_t _0x568[2];
|
||||||
|
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */
|
||||||
|
uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */
|
||||||
|
uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */
|
||||||
|
uint32_t _0x57c[5];
|
||||||
|
|
||||||
|
uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/
|
||||||
|
uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */
|
||||||
|
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
|
||||||
|
uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */
|
||||||
|
uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */
|
||||||
|
uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */
|
||||||
|
uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */
|
||||||
|
uint32_t _0x5ac[6];
|
||||||
|
uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */
|
||||||
|
uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */
|
||||||
|
uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */
|
||||||
|
uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */
|
||||||
|
uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */
|
||||||
|
uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */
|
||||||
|
uint32_t _0x5dc[2];
|
||||||
|
uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */
|
||||||
|
uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */
|
||||||
|
uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */
|
||||||
|
uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */
|
||||||
|
uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */
|
||||||
|
uint32_t _0x5f8[2];
|
||||||
|
|
||||||
|
uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */
|
||||||
|
uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */
|
||||||
|
uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */
|
||||||
|
uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */
|
||||||
|
uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */
|
||||||
|
uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */
|
||||||
|
uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */
|
||||||
|
uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */
|
||||||
|
uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */
|
||||||
|
uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */
|
||||||
|
uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */
|
||||||
|
uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */
|
||||||
|
uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */
|
||||||
|
uint32_t _0x634[3];
|
||||||
|
uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */
|
||||||
|
uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */
|
||||||
|
uint32_t _0x648;
|
||||||
|
uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */
|
||||||
|
uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */
|
||||||
|
uint32_t _0x654;
|
||||||
|
uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */
|
||||||
|
uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */
|
||||||
|
uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */
|
||||||
|
uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */
|
||||||
|
uint32_t _0x668;
|
||||||
|
uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */
|
||||||
|
uint32_t _0x670[2];
|
||||||
|
uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */
|
||||||
|
|
||||||
|
uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */
|
||||||
|
uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */
|
||||||
|
uint32_t _0x684[2];
|
||||||
|
uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */
|
||||||
|
uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */
|
||||||
|
|
||||||
|
uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */
|
||||||
|
uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */
|
||||||
|
uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */
|
||||||
|
uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */
|
||||||
|
|
||||||
|
uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */
|
||||||
|
uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */
|
||||||
|
uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */
|
||||||
|
uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */
|
||||||
|
uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */
|
||||||
|
uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */
|
||||||
|
|
||||||
|
uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */
|
||||||
|
uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */
|
||||||
|
uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */
|
||||||
|
uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */
|
||||||
|
uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */
|
||||||
|
uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */
|
||||||
|
uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */
|
||||||
|
uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */
|
||||||
|
|
||||||
|
uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */
|
||||||
|
uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */
|
||||||
|
uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */
|
||||||
|
|
||||||
|
uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */
|
||||||
|
uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */
|
||||||
|
uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */
|
||||||
|
uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */
|
||||||
|
uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */
|
||||||
|
uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */
|
||||||
|
uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */
|
||||||
|
uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */
|
||||||
|
uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */
|
||||||
|
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
|
||||||
|
|
||||||
|
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
|
||||||
|
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
|
||||||
|
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
|
||||||
|
uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */
|
||||||
|
uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */
|
||||||
|
uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */
|
||||||
|
uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */
|
||||||
|
uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */
|
||||||
|
uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */
|
||||||
|
uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */
|
||||||
|
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
|
||||||
|
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
|
||||||
|
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
|
||||||
|
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
|
||||||
|
} tegra_car_t;
|
||||||
|
|
||||||
|
static inline volatile tegra_car_t *car_get_regs(void) {
|
||||||
|
return (volatile tegra_car_t *)CAR_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clk_enable(CarDevice dev);
|
||||||
|
void clk_disable(CarDevice dev);
|
||||||
|
void rst_enable(CarDevice dev);
|
||||||
|
void rst_disable(CarDevice dev);
|
||||||
|
|
||||||
|
void clkrst_enable(CarDevice dev);
|
||||||
|
void clkrst_disable(CarDevice dev);
|
||||||
|
void clkrst_reboot(CarDevice dev);
|
||||||
|
|
||||||
|
void clkrst_enable_fuse_regs(bool enable);
|
||||||
|
|
||||||
|
#endif
|
||||||
1619
fusee/fusee-mtc/src/display/cfb_console.c
Normal file
1619
fusee/fusee-mtc/src/display/cfb_console.c
Normal file
File diff suppressed because it is too large
Load Diff
57
fusee/fusee-mtc/src/display/video_fb.h
Normal file
57
fusee/fusee-mtc/src/display/video_fb.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* (C) Copyright 1997-2002 ELTEC Elektronik AG
|
||||||
|
* Frank Gottschling <fgottschling@eltec.de>
|
||||||
|
*
|
||||||
|
* See file CREDITS for list of people who contributed to this
|
||||||
|
* project.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _VIDEO_FB_H_
|
||||||
|
#define _VIDEO_FB_H_
|
||||||
|
|
||||||
|
#define CONSOLE_BG_COL 0x00
|
||||||
|
#define CONSOLE_FG_COL 0xa0
|
||||||
|
|
||||||
|
/* Try using the small font */
|
||||||
|
#define CONFIG_VIDEO_FONT_SMALL
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Graphic Data Format (GDF) bits for VIDEO_DATA_FORMAT
|
||||||
|
*/
|
||||||
|
#define GDF__8BIT_INDEX 0
|
||||||
|
#define GDF_15BIT_555RGB 1
|
||||||
|
#define GDF_16BIT_565RGB 2
|
||||||
|
#define GDF_32BIT_X888RGB 3
|
||||||
|
#define GDF_24BIT_888RGB 4
|
||||||
|
#define GDF__8BIT_332RGB 5
|
||||||
|
|
||||||
|
#define CONFIG_VIDEO_FB_LITTLE_ENDIAN
|
||||||
|
#define CONFIG_VIDEO_VISIBLE_COLS 720
|
||||||
|
#define CONFIG_VIDEO_VISIBLE_ROWS 1280
|
||||||
|
#define CONFIG_VIDEO_COLS 768
|
||||||
|
#define CONFIG_VIDEO_PIXEL_SIZE 4
|
||||||
|
#define CONFIG_VIDEO_DATA_FORMAT GDF_32BIT_X888RGB /* BGR actually, but w/e */
|
||||||
|
|
||||||
|
int video_get_col(void);
|
||||||
|
int video_get_row(void);
|
||||||
|
|
||||||
|
int video_init(void *fb);
|
||||||
|
int video_resume(void *fb, int row, int col);
|
||||||
|
void video_puts(const char *s);
|
||||||
|
|
||||||
|
#endif /*_VIDEO_FB_H_ */
|
||||||
6181
fusee/fusee-mtc/src/display/video_font_large.h
Normal file
6181
fusee/fusee-mtc/src/display/video_font_large.h
Normal file
File diff suppressed because it is too large
Load Diff
4630
fusee/fusee-mtc/src/display/video_font_small.h
Normal file
4630
fusee/fusee-mtc/src/display/video_font_small.h
Normal file
File diff suppressed because it is too large
Load Diff
1089
fusee/fusee-mtc/src/emc.h
Normal file
1089
fusee/fusee-mtc/src/emc.h
Normal file
File diff suppressed because it is too large
Load Diff
260
fusee/fusee-mtc/src/fuse.c
Normal file
260
fusee/fusee-mtc/src/fuse.c
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "car.h"
|
||||||
|
#include "fuse.h"
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
|
/* Prototypes for internal commands. */
|
||||||
|
void fuse_make_regs_visible(void);
|
||||||
|
|
||||||
|
void fuse_enable_power(void);
|
||||||
|
void fuse_disable_power(void);
|
||||||
|
void fuse_wait_idle(void);
|
||||||
|
|
||||||
|
/* Initialize the fuse driver */
|
||||||
|
void fuse_init(void) {
|
||||||
|
fuse_make_regs_visible();
|
||||||
|
fuse_secondary_private_key_disable();
|
||||||
|
fuse_disable_programming();
|
||||||
|
|
||||||
|
/* TODO: Overrides (iROM patches) and various reads happen here */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make all fuse registers visible */
|
||||||
|
void fuse_make_regs_visible(void) {
|
||||||
|
clkrst_enable_fuse_regs(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable power to the fuse hardware array */
|
||||||
|
void fuse_enable_power(void) {
|
||||||
|
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||||
|
fuse->FUSE_PWR_GOOD_SW = 1;
|
||||||
|
udelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable power to the fuse hardware array */
|
||||||
|
void fuse_disable_power(void) {
|
||||||
|
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||||
|
fuse->FUSE_PWR_GOOD_SW = 0;
|
||||||
|
udelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for the fuse driver to go idle */
|
||||||
|
void fuse_wait_idle(void) {
|
||||||
|
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||||
|
uint32_t ctrl_val = 0;
|
||||||
|
|
||||||
|
/* Wait for STATE_IDLE */
|
||||||
|
while ((ctrl_val & (0xF0000)) != 0x40000)
|
||||||
|
{
|
||||||
|
udelay(1);
|
||||||
|
ctrl_val = fuse->FUSE_CTRL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a fuse from the hardware array */
|
||||||
|
uint32_t fuse_hw_read(uint32_t addr) {
|
||||||
|
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||||
|
fuse_wait_idle();
|
||||||
|
|
||||||
|
/* Program the target address */
|
||||||
|
fuse->FUSE_REG_ADDR = addr;
|
||||||
|
|
||||||
|
/* Enable read operation in control register */
|
||||||
|
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||||
|
ctrl_val &= ~0x3;
|
||||||
|
ctrl_val |= 0x1; /* Set FUSE_READ command */
|
||||||
|
fuse->FUSE_CTRL = ctrl_val;
|
||||||
|
|
||||||
|
fuse_wait_idle();
|
||||||
|
|
||||||
|
return fuse->FUSE_REG_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a fuse in the hardware array */
|
||||||
|
void fuse_hw_write(uint32_t value, uint32_t addr) {
|
||||||
|
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||||
|
fuse_wait_idle();
|
||||||
|
|
||||||
|
/* Program the target address and value */
|
||||||
|
fuse->FUSE_REG_ADDR = addr;
|
||||||
|
fuse->FUSE_REG_WRITE = value;
|
||||||
|
|
||||||
|
/* Enable write operation in control register */
|
||||||
|
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||||
|
ctrl_val &= ~0x3;
|
||||||
|
ctrl_val |= 0x2; /* Set FUSE_WRITE command */
|
||||||
|
fuse->FUSE_CTRL = ctrl_val;
|
||||||
|
|
||||||
|
fuse_wait_idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sense the fuse hardware array into the shadow cache */
|
||||||
|
void fuse_hw_sense(void) {
|
||||||
|
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||||
|
fuse_wait_idle();
|
||||||
|
|
||||||
|
/* Enable sense operation in control register */
|
||||||
|
uint32_t ctrl_val = fuse->FUSE_CTRL;
|
||||||
|
ctrl_val &= ~0x3;
|
||||||
|
ctrl_val |= 0x3; /* Set FUSE_SENSE command */
|
||||||
|
fuse->FUSE_CTRL = ctrl_val;
|
||||||
|
|
||||||
|
fuse_wait_idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disables all fuse programming. */
|
||||||
|
void fuse_disable_programming(void) {
|
||||||
|
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||||
|
fuse->FUSE_DIS_PGM = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unknown exactly what this does, but it alters the contents read from the fuse cache. */
|
||||||
|
void fuse_secondary_private_key_disable(void) {
|
||||||
|
volatile tegra_fuse_t *fuse = fuse_get_regs();
|
||||||
|
fuse->FUSE_PRIVATEKEYDISABLE = 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read the SKU info register from the shadow cache */
|
||||||
|
uint32_t fuse_get_sku_info(void) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
return fuse_chip->FUSE_SKU_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the bootrom patch version from a register in the shadow cache */
|
||||||
|
uint32_t fuse_get_bootrom_patch_version(void) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
return fuse_chip->FUSE_SOC_SPEEDO_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a spare bit register from the shadow cache */
|
||||||
|
uint32_t fuse_get_spare_bit(uint32_t idx) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
|
||||||
|
if (idx >= 32) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fuse_chip->FUSE_SPARE_BIT[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a reserved ODM register from the shadow cache */
|
||||||
|
uint32_t fuse_get_reserved_odm(uint32_t idx) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
|
||||||
|
if (idx >= 8) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fuse_chip->FUSE_RESERVED_ODM[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Derive the Device ID using values in the shadow cache */
|
||||||
|
uint64_t fuse_get_device_id(void) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
|
||||||
|
uint64_t device_id = 0;
|
||||||
|
uint64_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF;
|
||||||
|
uint64_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF;
|
||||||
|
uint64_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F;
|
||||||
|
uint32_t lot_code = fuse_chip->FUSE_LOT_CODE_0;
|
||||||
|
uint64_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F;
|
||||||
|
uint64_t derived_lot_code = 0;
|
||||||
|
for (unsigned int i = 0; i < 5; i++) {
|
||||||
|
derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F);
|
||||||
|
}
|
||||||
|
derived_lot_code &= 0x03FFFFFF;
|
||||||
|
|
||||||
|
device_id |= y_coord << 0;
|
||||||
|
device_id |= x_coord << 9;
|
||||||
|
device_id |= wafer_id << 18;
|
||||||
|
device_id |= derived_lot_code << 24;
|
||||||
|
device_id |= fab_code << 50;
|
||||||
|
return device_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the DRAM ID using values in the shadow cache */
|
||||||
|
uint32_t fuse_get_dram_id(void) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
return (fuse_chip->FUSE_RESERVED_ODM[4] >> 3) & 0x7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Derive the Hardware Type using values in the shadow cache */
|
||||||
|
uint32_t fuse_get_hardware_type(void) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
|
||||||
|
/* This function is very different between 4.x and < 4.x */
|
||||||
|
uint32_t hardware_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((fuse_chip->FUSE_RESERVED_ODM[4] >> 2) & 1);
|
||||||
|
|
||||||
|
/* TODO: choose; if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT) {
|
||||||
|
static const uint32_t types[] = {0,1,4,3};
|
||||||
|
|
||||||
|
hardware_type |= (fuse_chip->FUSE_RESERVED_ODM[4] >> 14) & 0x3C;
|
||||||
|
hardware_type--;
|
||||||
|
return hardware_type > 3 ? 4 : types[hardware_type];
|
||||||
|
} else {*/
|
||||||
|
if (hardware_type >= 1) {
|
||||||
|
return hardware_type > 2 ? 3 : hardware_type - 1;
|
||||||
|
} else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Derive the Retail Type using values in the shadow cache */
|
||||||
|
uint32_t fuse_get_retail_type(void) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
|
||||||
|
/* Retail type = IS_RETAIL | UNIT_TYPE */
|
||||||
|
uint32_t retail_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 4) | (fuse_chip->FUSE_RESERVED_ODM[4] & 3);
|
||||||
|
if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */
|
||||||
|
return 1;
|
||||||
|
} else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 2; /* IS_RETAIL | DEV_UNIT */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */
|
||||||
|
void fuse_get_hardware_info(void *dst) {
|
||||||
|
volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs();
|
||||||
|
uint32_t hw_info[0x4];
|
||||||
|
|
||||||
|
uint32_t unk_hw_fuse = fuse_chip->_0x120 & 0x3F;
|
||||||
|
uint32_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF;
|
||||||
|
uint32_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF;
|
||||||
|
uint32_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F;
|
||||||
|
uint32_t lot_code_0 = fuse_chip->FUSE_LOT_CODE_0;
|
||||||
|
uint32_t lot_code_1 = fuse_chip->FUSE_LOT_CODE_1 & 0x0FFFFFFF;
|
||||||
|
uint32_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F;
|
||||||
|
uint32_t vendor_code = fuse_chip->FUSE_VENDOR_CODE & 0xF;
|
||||||
|
|
||||||
|
/* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */
|
||||||
|
hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse));
|
||||||
|
hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2));
|
||||||
|
hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6));
|
||||||
|
hw_info[3] = (uint32_t)(vendor_code);
|
||||||
|
|
||||||
|
memcpy(dst, hw_info, 0x10);
|
||||||
|
}
|
||||||
213
fusee/fusee-mtc/src/fuse.h
Normal file
213
fusee/fusee-mtc/src/fuse.h
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_FUSE_H
|
||||||
|
#define FUSEE_FUSE_H
|
||||||
|
|
||||||
|
#define FUSE_BASE 0x7000F800
|
||||||
|
#define FUSE_CHIP_BASE (FUSE_BASE + 0x100)
|
||||||
|
#define MAKE_FUSE_REG(n) MAKE_REG32(FUSE_BASE + n)
|
||||||
|
#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t FUSE_CTRL;
|
||||||
|
uint32_t FUSE_REG_ADDR;
|
||||||
|
uint32_t FUSE_REG_READ;
|
||||||
|
uint32_t FUSE_REG_WRITE;
|
||||||
|
uint32_t FUSE_TIME_RD1;
|
||||||
|
uint32_t FUSE_TIME_RD2;
|
||||||
|
uint32_t FUSE_TIME_PGM1;
|
||||||
|
uint32_t FUSE_TIME_PGM2;
|
||||||
|
uint32_t FUSE_PRIV2INTFC;
|
||||||
|
uint32_t FUSE_FUSEBYPASS;
|
||||||
|
uint32_t FUSE_PRIVATEKEYDISABLE;
|
||||||
|
uint32_t FUSE_DIS_PGM;
|
||||||
|
uint32_t FUSE_WRITE_ACCESS;
|
||||||
|
uint32_t FUSE_PWR_GOOD_SW;
|
||||||
|
uint32_t _0x38[0x32];
|
||||||
|
} tegra_fuse_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t FUSE_PRODUCTION_MODE;
|
||||||
|
uint32_t _0x4;
|
||||||
|
uint32_t _0x8;
|
||||||
|
uint32_t _0xC;
|
||||||
|
uint32_t FUSE_SKU_INFO;
|
||||||
|
uint32_t FUSE_CPU_SPEEDO_0;
|
||||||
|
uint32_t FUSE_CPU_IDDQ;
|
||||||
|
uint32_t _0x1C;
|
||||||
|
uint32_t _0x20;
|
||||||
|
uint32_t _0x24;
|
||||||
|
uint32_t FUSE_FT_REV;
|
||||||
|
uint32_t FUSE_CPU_SPEEDO_1;
|
||||||
|
uint32_t FUSE_CPU_SPEEDO_2;
|
||||||
|
uint32_t FUSE_SOC_SPEEDO_0;
|
||||||
|
uint32_t FUSE_SOC_SPEEDO_1;
|
||||||
|
uint32_t FUSE_SOC_SPEEDO_2;
|
||||||
|
uint32_t FUSE_SOC_IDDQ;
|
||||||
|
uint32_t _0x44;
|
||||||
|
uint32_t FUSE_FA;
|
||||||
|
uint32_t _0x4C;
|
||||||
|
uint32_t _0x50;
|
||||||
|
uint32_t _0x54;
|
||||||
|
uint32_t _0x58;
|
||||||
|
uint32_t _0x5C;
|
||||||
|
uint32_t _0x60;
|
||||||
|
uint32_t FUSE_PUBLIC_KEY[0x8];
|
||||||
|
uint32_t FUSE_TSENSOR_1;
|
||||||
|
uint32_t FUSE_TSENSOR_2;
|
||||||
|
uint32_t _0x8C;
|
||||||
|
uint32_t FUSE_CP_REV;
|
||||||
|
uint32_t _0x94;
|
||||||
|
uint32_t FUSE_TSENSOR_0;
|
||||||
|
uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG;
|
||||||
|
uint32_t FUSE_SECURITY_MODE;
|
||||||
|
uint32_t FUSE_PRIVATE_KEY[0x4];
|
||||||
|
uint32_t FUSE_DEVICE_KEY;
|
||||||
|
uint32_t _0xB8;
|
||||||
|
uint32_t _0xBC;
|
||||||
|
uint32_t FUSE_RESERVED_SW;
|
||||||
|
uint32_t FUSE_VP8_ENABLE;
|
||||||
|
uint32_t FUSE_RESERVED_ODM[0x8];
|
||||||
|
uint32_t _0xE8;
|
||||||
|
uint32_t _0xEC;
|
||||||
|
uint32_t FUSE_SKU_USB_CALIB;
|
||||||
|
uint32_t FUSE_SKU_DIRECT_CONFIG;
|
||||||
|
uint32_t _0xF8;
|
||||||
|
uint32_t _0xFC;
|
||||||
|
uint32_t FUSE_VENDOR_CODE;
|
||||||
|
uint32_t FUSE_FAB_CODE;
|
||||||
|
uint32_t FUSE_LOT_CODE_0;
|
||||||
|
uint32_t FUSE_LOT_CODE_1;
|
||||||
|
uint32_t FUSE_WAFER_ID;
|
||||||
|
uint32_t FUSE_X_COORDINATE;
|
||||||
|
uint32_t FUSE_Y_COORDINATE;
|
||||||
|
uint32_t _0x11C;
|
||||||
|
uint32_t _0x120;
|
||||||
|
uint32_t FUSE_SATA_CALIB;
|
||||||
|
uint32_t FUSE_GPU_IDDQ;
|
||||||
|
uint32_t FUSE_TSENSOR_3;
|
||||||
|
uint32_t _0x130;
|
||||||
|
uint32_t _0x134;
|
||||||
|
uint32_t _0x138;
|
||||||
|
uint32_t _0x13C;
|
||||||
|
uint32_t _0x140;
|
||||||
|
uint32_t _0x144;
|
||||||
|
uint32_t FUSE_OPT_SUBREVISION;
|
||||||
|
uint32_t _0x14C;
|
||||||
|
uint32_t _0x150;
|
||||||
|
uint32_t FUSE_TSENSOR_4;
|
||||||
|
uint32_t FUSE_TSENSOR_5;
|
||||||
|
uint32_t FUSE_TSENSOR_6;
|
||||||
|
uint32_t FUSE_TSENSOR_7;
|
||||||
|
uint32_t FUSE_OPT_PRIV_SEC_DIS;
|
||||||
|
uint32_t FUSE_PKC_DISABLE;
|
||||||
|
uint32_t _0x16C;
|
||||||
|
uint32_t _0x170;
|
||||||
|
uint32_t _0x174;
|
||||||
|
uint32_t _0x178;
|
||||||
|
uint32_t _0x17C;
|
||||||
|
uint32_t FUSE_TSENSOR_COMMON;
|
||||||
|
uint32_t _0x184;
|
||||||
|
uint32_t _0x188;
|
||||||
|
uint32_t _0x18C;
|
||||||
|
uint32_t _0x190;
|
||||||
|
uint32_t _0x194;
|
||||||
|
uint32_t _0x198;
|
||||||
|
uint32_t FUSE_DEBUG_AUTH_OVERRIDE;
|
||||||
|
uint32_t _0x1A0;
|
||||||
|
uint32_t _0x1A4;
|
||||||
|
uint32_t _0x1A8;
|
||||||
|
uint32_t _0x1AC;
|
||||||
|
uint32_t _0x1B0;
|
||||||
|
uint32_t _0x1B4;
|
||||||
|
uint32_t _0x1B8;
|
||||||
|
uint32_t _0x1BC;
|
||||||
|
uint32_t _0x1D0;
|
||||||
|
uint32_t FUSE_TSENSOR_8;
|
||||||
|
uint32_t _0x1D8;
|
||||||
|
uint32_t _0x1DC;
|
||||||
|
uint32_t _0x1E0;
|
||||||
|
uint32_t _0x1E4;
|
||||||
|
uint32_t _0x1E8;
|
||||||
|
uint32_t _0x1EC;
|
||||||
|
uint32_t _0x1F0;
|
||||||
|
uint32_t _0x1F4;
|
||||||
|
uint32_t _0x1F8;
|
||||||
|
uint32_t _0x1FC;
|
||||||
|
uint32_t _0x200;
|
||||||
|
uint32_t FUSE_RESERVED_CALIB;
|
||||||
|
uint32_t _0x208;
|
||||||
|
uint32_t _0x20C;
|
||||||
|
uint32_t _0x210;
|
||||||
|
uint32_t _0x214;
|
||||||
|
uint32_t _0x218;
|
||||||
|
uint32_t FUSE_TSENSOR_9;
|
||||||
|
uint32_t _0x220;
|
||||||
|
uint32_t _0x224;
|
||||||
|
uint32_t _0x228;
|
||||||
|
uint32_t _0x22C;
|
||||||
|
uint32_t _0x230;
|
||||||
|
uint32_t _0x234;
|
||||||
|
uint32_t _0x238;
|
||||||
|
uint32_t _0x23C;
|
||||||
|
uint32_t _0x240;
|
||||||
|
uint32_t _0x244;
|
||||||
|
uint32_t _0x248;
|
||||||
|
uint32_t _0x24C;
|
||||||
|
uint32_t FUSE_USB_CALIB_EXT;
|
||||||
|
uint32_t _0x254;
|
||||||
|
uint32_t _0x258;
|
||||||
|
uint32_t _0x25C;
|
||||||
|
uint32_t _0x260;
|
||||||
|
uint32_t _0x264;
|
||||||
|
uint32_t _0x268;
|
||||||
|
uint32_t _0x26C;
|
||||||
|
uint32_t _0x270;
|
||||||
|
uint32_t _0x274;
|
||||||
|
uint32_t _0x278;
|
||||||
|
uint32_t _0x27C;
|
||||||
|
uint32_t FUSE_SPARE_BIT[0x20];
|
||||||
|
} tegra_fuse_chip_t;
|
||||||
|
|
||||||
|
static inline volatile tegra_fuse_t *fuse_get_regs(void) {
|
||||||
|
return (volatile tegra_fuse_t *)FUSE_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) {
|
||||||
|
return (volatile tegra_fuse_chip_t *)FUSE_CHIP_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fuse_init(void);
|
||||||
|
|
||||||
|
uint32_t fuse_hw_read(uint32_t addr);
|
||||||
|
void fuse_hw_write(uint32_t value, uint32_t addr);
|
||||||
|
void fuse_hw_sense(void);
|
||||||
|
void fuse_disable_programming(void);
|
||||||
|
void fuse_secondary_private_key_disable(void);
|
||||||
|
|
||||||
|
uint32_t fuse_get_sku_info(void);
|
||||||
|
uint32_t fuse_get_spare_bit(uint32_t idx);
|
||||||
|
uint32_t fuse_get_reserved_odm(uint32_t idx);
|
||||||
|
|
||||||
|
uint32_t fuse_get_bootrom_patch_version(void);
|
||||||
|
uint64_t fuse_get_device_id(void);
|
||||||
|
uint32_t fuse_get_dram_id(void);
|
||||||
|
uint32_t fuse_get_hardware_type(void);
|
||||||
|
uint32_t fuse_get_retail_type(void);
|
||||||
|
void fuse_get_hardware_info(void *dst);
|
||||||
|
|
||||||
|
#endif
|
||||||
86
fusee/fusee-mtc/src/init.c
Normal file
86
fusee/fusee-mtc/src/init.c
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <sys/iosupport.h>
|
||||||
|
#include "stage2.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
void __libc_init_array(void);
|
||||||
|
void __libc_fini_array(void);
|
||||||
|
|
||||||
|
extern uint8_t __bss_start__[], __bss_end__[];
|
||||||
|
extern uint8_t __heap_start__[], __heap_end__[];
|
||||||
|
|
||||||
|
extern char *fake_heap_start;
|
||||||
|
extern char *fake_heap_end;
|
||||||
|
|
||||||
|
int __program_argc;
|
||||||
|
void **__program_argv;
|
||||||
|
|
||||||
|
void __program_exit(int rc);
|
||||||
|
static void __program_parse_argc_argv(int argc, char *argdata);
|
||||||
|
static void __program_cleanup_argv(void);
|
||||||
|
|
||||||
|
static void __program_init_heap(void) {
|
||||||
|
fake_heap_start = (char*)__heap_start__;
|
||||||
|
fake_heap_end = (char*)__heap_end__;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __program_init_newlib_hooks(void) {
|
||||||
|
__syscalls.exit = __program_exit; /* For exit, etc. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void __program_init(int argc, char *argdata) {
|
||||||
|
/* Zero-fill the .bss section */
|
||||||
|
memset(__bss_start__, 0, __bss_end__ - __bss_start__);
|
||||||
|
|
||||||
|
__program_init_heap();
|
||||||
|
__program_init_newlib_hooks();
|
||||||
|
__program_parse_argc_argv(argc, argdata);
|
||||||
|
__libc_init_array();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __program_exit(int rc) {
|
||||||
|
__libc_fini_array();
|
||||||
|
__program_cleanup_argv();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __program_parse_argc_argv(int argc, char *argdata) {
|
||||||
|
__program_argc = argc;
|
||||||
|
|
||||||
|
__program_argv = malloc(argc * sizeof(void **));
|
||||||
|
if (__program_argv == NULL) {
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
__program_argv[0] = malloc(sizeof(stage2_mtc_args_t));
|
||||||
|
if (__program_argv[0] == NULL) {
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
memcpy(__program_argv[0], argdata, sizeof(stage2_mtc_args_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __program_cleanup_argv(void) {
|
||||||
|
for (int i = 0; i < __program_argc; i++) {
|
||||||
|
free(__program_argv[i]);
|
||||||
|
__program_argv[i] = NULL;
|
||||||
|
}
|
||||||
|
free(__program_argv);
|
||||||
|
}
|
||||||
127
fusee/fusee-mtc/src/lib/log.c
Normal file
127
fusee/fusee-mtc/src/lib/log.c
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "../display/video_fb.h"
|
||||||
|
#include "vsprintf.h"
|
||||||
|
|
||||||
|
/* default log level for screen output */
|
||||||
|
ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_NONE;
|
||||||
|
|
||||||
|
void log_set_log_level(ScreenLogLevel log_level) {
|
||||||
|
g_screen_log_level = log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenLogLevel log_get_log_level() {
|
||||||
|
return g_screen_log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_to_uart(const char *message) {
|
||||||
|
/* TODO: add UART logging */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_to_screen(ScreenLogLevel screen_log_level, char *message) {
|
||||||
|
/* don't print to screen if below log level */
|
||||||
|
if(screen_log_level > g_screen_log_level) return;
|
||||||
|
|
||||||
|
video_puts(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vprintk - logs a message and prints it to screen based on its screen_log_level
|
||||||
|
*
|
||||||
|
* If the level is below g_screen_log_level it will not be shown but logged to UART
|
||||||
|
* This text will not be colored or prefixed
|
||||||
|
* UART is TODO
|
||||||
|
*/
|
||||||
|
void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char buf[PRINT_MESSAGE_MAX_LENGTH];
|
||||||
|
vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args);
|
||||||
|
|
||||||
|
/* we don't need that flag here, but if it gets used, strip it so we print correctly */
|
||||||
|
screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX;
|
||||||
|
|
||||||
|
/* log to UART */
|
||||||
|
log_to_uart(buf);
|
||||||
|
|
||||||
|
print_to_screen(screen_log_level, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) {
|
||||||
|
char typebuf[] = "[%s] %s";
|
||||||
|
|
||||||
|
/* apply prefix and append message format */
|
||||||
|
/* TODO: add coloring to the output */
|
||||||
|
switch(screen_log_level)
|
||||||
|
{
|
||||||
|
case SCREEN_LOG_LEVEL_ERROR:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_WARNING:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_MANDATORY:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_INFO:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt);
|
||||||
|
break;
|
||||||
|
case SCREEN_LOG_LEVEL_DEBUG:
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print - logs a message and prints it to screen based on its screen_log_level
|
||||||
|
*
|
||||||
|
* If the level is below g_screen_log_level it will not be shown but logged to UART
|
||||||
|
* Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added
|
||||||
|
* UART is TODO
|
||||||
|
*/
|
||||||
|
void print(ScreenLogLevel screen_log_level, const char * fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[PRINT_MESSAGE_MAX_LENGTH] = {};
|
||||||
|
char message[PRINT_MESSAGE_MAX_LENGTH] = {};
|
||||||
|
|
||||||
|
/* TODO: make splash disappear if level > MANDATORY */
|
||||||
|
|
||||||
|
/* make prefix free messages with log_level possible */
|
||||||
|
if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) {
|
||||||
|
/* remove the NO_PREFIX flag so the enum can be recognized later on */
|
||||||
|
screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX;
|
||||||
|
|
||||||
|
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
add_prefix(screen_log_level, fmt, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input arguments */
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(message, PRINT_MESSAGE_MAX_LENGTH, buf, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
/* log to UART */
|
||||||
|
log_to_uart(message);
|
||||||
|
|
||||||
|
print_to_screen(screen_log_level, message);
|
||||||
|
}
|
||||||
43
fusee/fusee-mtc/src/lib/log.h
Normal file
43
fusee/fusee-mtc/src/lib/log.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_LOG_H
|
||||||
|
#define FUSEE_LOG_H
|
||||||
|
|
||||||
|
#define PRINT_MESSAGE_MAX_LENGTH 512
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SCREEN_LOG_LEVEL_NONE = 0,
|
||||||
|
SCREEN_LOG_LEVEL_ERROR = 1,
|
||||||
|
SCREEN_LOG_LEVEL_WARNING = 2,
|
||||||
|
SCREEN_LOG_LEVEL_MANDATORY = 3, /* no log prefix */
|
||||||
|
SCREEN_LOG_LEVEL_INFO = 4,
|
||||||
|
SCREEN_LOG_LEVEL_DEBUG = 5,
|
||||||
|
|
||||||
|
SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */
|
||||||
|
} ScreenLogLevel;
|
||||||
|
|
||||||
|
extern ScreenLogLevel g_screen_log_level;
|
||||||
|
|
||||||
|
void log_set_log_level(ScreenLogLevel screen_log_level);
|
||||||
|
ScreenLogLevel log_get_log_level();
|
||||||
|
void log_to_uart(const char *message);
|
||||||
|
void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args);
|
||||||
|
void print(ScreenLogLevel screen_log_level, const char* fmt, ...);
|
||||||
|
|
||||||
|
#endif
|
||||||
1676
fusee/fusee-mtc/src/lib/vsprintf.c
Normal file
1676
fusee/fusee-mtc/src/lib/vsprintf.c
Normal file
File diff suppressed because it is too large
Load Diff
28
fusee/fusee-mtc/src/lib/vsprintf.h
Normal file
28
fusee/fusee-mtc/src/lib/vsprintf.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Andrei Warkentin <andrey.warkentin@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software ; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef VSPRINTF_H
|
||||||
|
#define VSPRINTF_H
|
||||||
|
|
||||||
|
struct va_format {
|
||||||
|
const char *fmt;
|
||||||
|
va_list *va;
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);
|
||||||
|
|
||||||
|
int sprintf(char *buf, const char *fmt, ...);
|
||||||
|
int scnprintf(char *buf, size_t size, const char *fmt, ...);
|
||||||
|
int snprintf(char *buf, size_t size, const char *fmt, ...);
|
||||||
|
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
|
||||||
|
int sscanf(const char *buf, const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif /* VSPRINTF_H */
|
||||||
57
fusee/fusee-mtc/src/main.c
Normal file
57
fusee/fusee-mtc/src/main.c
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "mtc.h"
|
||||||
|
#include "stage2.h"
|
||||||
|
#include "display/video_fb.h"
|
||||||
|
|
||||||
|
static void *g_framebuffer;
|
||||||
|
static __attribute__((__aligned__(0x200))) stage2_mtc_args_t g_mtc_args_store;
|
||||||
|
static stage2_mtc_args_t *g_mtc_args;
|
||||||
|
|
||||||
|
/* Allow for main(int argc, void **argv) signature. */
|
||||||
|
#pragma GCC diagnostic ignored "-Wmain"
|
||||||
|
|
||||||
|
int main(int argc, void **argv) {
|
||||||
|
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_NONE;
|
||||||
|
|
||||||
|
/* Check argc. */
|
||||||
|
if (argc != MTC_ARGC) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract arguments from argv. */
|
||||||
|
g_mtc_args = &g_mtc_args_store;
|
||||||
|
memcpy(g_mtc_args, (stage2_mtc_args_t *)argv[MTC_ARGV_ARGUMENT_STRUCT], sizeof(*g_mtc_args));
|
||||||
|
log_level = g_mtc_args->log_level;
|
||||||
|
|
||||||
|
/* Override the global logging level. */
|
||||||
|
log_set_log_level(log_level);
|
||||||
|
|
||||||
|
if (log_level != SCREEN_LOG_LEVEL_NONE) {
|
||||||
|
/* Set framebuffer address. */
|
||||||
|
g_framebuffer = (void *)0xC0000000;
|
||||||
|
|
||||||
|
/* Zero-fill the framebuffer and register it as printk provider. */
|
||||||
|
video_init(g_framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Train DRAM. */
|
||||||
|
train_dram();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
167
fusee/fusee-mtc/src/mc.c
Normal file
167
fusee/fusee-mtc/src/mc.c
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 naehrwert
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mc.h"
|
||||||
|
#include "car.h"
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
|
void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock)
|
||||||
|
{
|
||||||
|
MAKE_MC_REG(MC_SEC_CARVEOUT_BOM) = bom;
|
||||||
|
MAKE_MC_REG(MC_SEC_CARVEOUT_SIZE_MB) = size1mb;
|
||||||
|
|
||||||
|
if (lock)
|
||||||
|
MAKE_MC_REG(MC_SEC_CARVEOUT_REG_CTRL) = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mc_config_carveout()
|
||||||
|
{
|
||||||
|
*(volatile uint32_t *)0x8005FFFC = 0xC0EDBBCC;
|
||||||
|
|
||||||
|
MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1;
|
||||||
|
MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0;
|
||||||
|
MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0;
|
||||||
|
MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0;
|
||||||
|
MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1;
|
||||||
|
|
||||||
|
mc_config_tsec_carveout(0, 0, true);
|
||||||
|
|
||||||
|
MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = 0;
|
||||||
|
MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0;
|
||||||
|
MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = 0;
|
||||||
|
MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = 1;
|
||||||
|
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM_HI) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CFG0) = 0x4000006;
|
||||||
|
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_BOM) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_BOM_HI) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR));
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2));
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CFG0) = 0x4401E7E;
|
||||||
|
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM_HI) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CFG0) = 0x8F;
|
||||||
|
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM_HI) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mc_config_carveout_finalize()
|
||||||
|
{
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_BOM_HI) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR));
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2));
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
||||||
|
MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CFG0) = 0x440167E;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mc_enable_ahb_redirect()
|
||||||
|
{
|
||||||
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
car->lvl2_clk_gate_ovrd = ((car->lvl2_clk_gate_ovrd & 0xFFF7FFFF) | 0x80000);
|
||||||
|
|
||||||
|
MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000;
|
||||||
|
MAKE_MC_REG(MC_IRAM_TOM) = 0x4003F000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mc_disable_ahb_redirect()
|
||||||
|
{
|
||||||
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
|
||||||
|
MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000;
|
||||||
|
MAKE_MC_REG(MC_IRAM_TOM) = 0;
|
||||||
|
|
||||||
|
car->lvl2_clk_gate_ovrd &= 0xFFF7FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mc_enable()
|
||||||
|
{
|
||||||
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
|
||||||
|
/* Set EMC clock source. */
|
||||||
|
car->clk_source_emc = ((car->clk_source_emc & 0x1FFFFFFF) | 0x40000000);
|
||||||
|
|
||||||
|
/* Enable MIPI CAL clock. */
|
||||||
|
car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFDFFFFFF) | 0x2000000);
|
||||||
|
|
||||||
|
/* Enable MC clock. */
|
||||||
|
car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFFFFFFFE) | 1);
|
||||||
|
|
||||||
|
/* Enable EMC DLL clock. */
|
||||||
|
car->clk_enb_x_set = ((car->clk_enb_x_set & 0xFFFFBFFF) | 0x4000);
|
||||||
|
|
||||||
|
/* Clear EMC and MC reset. */
|
||||||
|
car->rst_dev_h_set = 0x2000001;
|
||||||
|
udelay(5);
|
||||||
|
|
||||||
|
mc_disable_ahb_redirect();
|
||||||
|
}
|
||||||
598
fusee/fusee-mtc/src/mc.h
Normal file
598
fusee/fusee-mtc/src/mc.h
Normal file
@@ -0,0 +1,598 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
|
||||||
|
* Copyright (c) 2018 naehrwert
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_MC_H_
|
||||||
|
#define FUSEE_MC_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define MC_BASE 0x70019000
|
||||||
|
#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n)
|
||||||
|
|
||||||
|
#define MC_INTSTATUS 0x0
|
||||||
|
#define MC_INTMASK 0x4
|
||||||
|
#define MC_ERR_STATUS 0x8
|
||||||
|
#define MC_ERR_ADR 0xc
|
||||||
|
#define MC_SMMU_CONFIG 0x10
|
||||||
|
#define MC_SMMU_TLB_CONFIG 0x14
|
||||||
|
#define MC_SMMU_PTC_CONFIG 0x18
|
||||||
|
#define MC_SMMU_PTB_ASID 0x1c
|
||||||
|
#define MC_SMMU_PTB_DATA 0x20
|
||||||
|
#define MC_SMMU_TLB_FLUSH 0x30
|
||||||
|
#define MC_SMMU_PTC_FLUSH 0x34
|
||||||
|
#define MC_SMMU_ASID_SECURITY 0x38
|
||||||
|
#define MC_SMMU_AFI_ASID 0x238
|
||||||
|
#define MC_SMMU_AVPC_ASID 0x23c
|
||||||
|
#define MC_SMMU_TSEC_ASID 0x294
|
||||||
|
#define MC_SMMU_PPCS1_ASID 0x298
|
||||||
|
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
|
||||||
|
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
|
||||||
|
#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
|
||||||
|
#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
|
||||||
|
#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
|
||||||
|
#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0
|
||||||
|
#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4
|
||||||
|
#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8
|
||||||
|
#define MC_PCFIFO_CLIENT_CONFIG3 0xddc
|
||||||
|
#define MC_PCFIFO_CLIENT_CONFIG4 0xde0
|
||||||
|
#define MC_EMEM_CFG 0x50
|
||||||
|
#define MC_EMEM_ADR_CFG 0x54
|
||||||
|
#define MC_EMEM_ADR_CFG_DEV0 0x58
|
||||||
|
#define MC_EMEM_ADR_CFG_DEV1 0x5c
|
||||||
|
#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60
|
||||||
|
#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64
|
||||||
|
#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68
|
||||||
|
#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c
|
||||||
|
#define MC_SECURITY_CFG0 0x70
|
||||||
|
#define MC_SECURITY_CFG1 0x74
|
||||||
|
#define MC_SECURITY_CFG3 0x9bc
|
||||||
|
#define MC_SECURITY_RSV 0x7c
|
||||||
|
#define MC_EMEM_ARB_CFG 0x90
|
||||||
|
#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94
|
||||||
|
#define MC_EMEM_ARB_TIMING_RCD 0x98
|
||||||
|
#define MC_EMEM_ARB_TIMING_RP 0x9c
|
||||||
|
#define MC_EMEM_ARB_TIMING_RC 0xa0
|
||||||
|
#define MC_EMEM_ARB_TIMING_RAS 0xa4
|
||||||
|
#define MC_EMEM_ARB_TIMING_FAW 0xa8
|
||||||
|
#define MC_EMEM_ARB_TIMING_RRD 0xac
|
||||||
|
#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0
|
||||||
|
#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4
|
||||||
|
#define MC_EMEM_ARB_TIMING_R2R 0xb8
|
||||||
|
#define MC_EMEM_ARB_TIMING_W2W 0xbc
|
||||||
|
#define MC_EMEM_ARB_TIMING_R2W 0xc0
|
||||||
|
#define MC_EMEM_ARB_TIMING_W2R 0xc4
|
||||||
|
#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0
|
||||||
|
#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4
|
||||||
|
#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0
|
||||||
|
#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4
|
||||||
|
#define MC_EMEM_ARB_DA_TURNS 0xd0
|
||||||
|
#define MC_EMEM_ARB_DA_COVERS 0xd4
|
||||||
|
#define MC_EMEM_ARB_MISC0 0xd8
|
||||||
|
#define MC_EMEM_ARB_MISC1 0xdc
|
||||||
|
#define MC_EMEM_ARB_MISC2 0xc8
|
||||||
|
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
|
||||||
|
#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
|
||||||
|
#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0
|
||||||
|
#define MC_EMEM_ARB_OVERRIDE 0xe8
|
||||||
|
#define MC_EMEM_ARB_RSV 0xec
|
||||||
|
#define MC_CLKEN_OVERRIDE 0xf4
|
||||||
|
#define MC_TIMING_CONTROL_DBG 0xf8
|
||||||
|
#define MC_TIMING_CONTROL 0xfc
|
||||||
|
#define MC_STAT_CONTROL 0x100
|
||||||
|
#define MC_STAT_STATUS 0x104
|
||||||
|
#define MC_STAT_EMC_CLOCK_LIMIT 0x108
|
||||||
|
#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c
|
||||||
|
#define MC_STAT_EMC_CLOCKS 0x110
|
||||||
|
#define MC_STAT_EMC_CLOCKS_MSBS 0x114
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134
|
||||||
|
#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174
|
||||||
|
#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c
|
||||||
|
#define MC_STAT_EMC_SET0_COUNT 0x138
|
||||||
|
#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c
|
||||||
|
#define MC_STAT_EMC_SET1_COUNT 0x178
|
||||||
|
#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c
|
||||||
|
#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140
|
||||||
|
#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144
|
||||||
|
#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180
|
||||||
|
#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184
|
||||||
|
#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148
|
||||||
|
#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c
|
||||||
|
#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188
|
||||||
|
#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c
|
||||||
|
#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150
|
||||||
|
#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190
|
||||||
|
#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8
|
||||||
|
#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc
|
||||||
|
#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8
|
||||||
|
#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc
|
||||||
|
#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0
|
||||||
|
#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0
|
||||||
|
#define MC_CLIENT_HOTRESET_CTRL 0x200
|
||||||
|
#define MC_CLIENT_HOTRESET_CTRL_1 0x970
|
||||||
|
#define MC_CLIENT_HOTRESET_STATUS 0x204
|
||||||
|
#define MC_CLIENT_HOTRESET_STATUS_1 0x974
|
||||||
|
#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208
|
||||||
|
#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c
|
||||||
|
#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210
|
||||||
|
#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214
|
||||||
|
#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94
|
||||||
|
#define MC_EMEM_ARB_HYSTERESIS_0 0x218
|
||||||
|
#define MC_EMEM_ARB_HYSTERESIS_1 0x21c
|
||||||
|
#define MC_EMEM_ARB_HYSTERESIS_2 0x220
|
||||||
|
#define MC_EMEM_ARB_HYSTERESIS_3 0x224
|
||||||
|
#define MC_EMEM_ARB_HYSTERESIS_4 0xb84
|
||||||
|
#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0
|
||||||
|
#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4
|
||||||
|
#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8
|
||||||
|
#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc
|
||||||
|
#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0
|
||||||
|
#define MC_EMEM_ARB_DHYST_CTRL 0xbcc
|
||||||
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0
|
||||||
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4
|
||||||
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8
|
||||||
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc
|
||||||
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0
|
||||||
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4
|
||||||
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8
|
||||||
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec
|
||||||
|
#define MC_RESERVED_RSV 0x3fc
|
||||||
|
#define MC_DISB_EXTRA_SNAP_LEVELS 0x408
|
||||||
|
#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4
|
||||||
|
#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0
|
||||||
|
#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18
|
||||||
|
#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08
|
||||||
|
#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10
|
||||||
|
#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c
|
||||||
|
#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40
|
||||||
|
#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414
|
||||||
|
#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc
|
||||||
|
#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c
|
||||||
|
#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14
|
||||||
|
#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0
|
||||||
|
#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac
|
||||||
|
#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c
|
||||||
|
#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48
|
||||||
|
#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8
|
||||||
|
#define MC_USBX_EXTRA_SNAP_LEVELS 0x404
|
||||||
|
#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8
|
||||||
|
#define MC_SD_EXTRA_SNAP_LEVELS 0xa04
|
||||||
|
#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c
|
||||||
|
#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8
|
||||||
|
#define MC_GK_EXTRA_SNAP_LEVELS 0xa00
|
||||||
|
#define MC_VE2_EXTRA_SNAP_LEVELS 0x410
|
||||||
|
#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44
|
||||||
|
#define MC_VIDEO_PROTECT_BOM 0x648
|
||||||
|
#define MC_VIDEO_PROTECT_SIZE_MB 0x64c
|
||||||
|
#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978
|
||||||
|
#define MC_VIDEO_PROTECT_REG_CTRL 0x650
|
||||||
|
#define MC_ERR_VPR_STATUS 0x654
|
||||||
|
#define MC_ERR_VPR_ADR 0x658
|
||||||
|
#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418
|
||||||
|
#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590
|
||||||
|
#define MC_IRAM_BOM 0x65c
|
||||||
|
#define MC_IRAM_TOM 0x660
|
||||||
|
#define MC_IRAM_ADR_HI 0x980
|
||||||
|
#define MC_IRAM_REG_CTRL 0x964
|
||||||
|
#define MC_EMEM_CFG_ACCESS_CTRL 0x664
|
||||||
|
#define MC_TZ_SECURITY_CTRL 0x668
|
||||||
|
#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c
|
||||||
|
#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4
|
||||||
|
#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc
|
||||||
|
#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8
|
||||||
|
#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80
|
||||||
|
#define MC_SEC_CARVEOUT_BOM 0x670
|
||||||
|
#define MC_SEC_CARVEOUT_SIZE_MB 0x674
|
||||||
|
#define MC_SEC_CARVEOUT_ADR_HI 0x9d4
|
||||||
|
#define MC_SEC_CARVEOUT_REG_CTRL 0x678
|
||||||
|
#define MC_ERR_SEC_STATUS 0x67c
|
||||||
|
#define MC_ERR_SEC_ADR 0x680
|
||||||
|
#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684
|
||||||
|
#define MC_STUTTER_CONTROL 0x688
|
||||||
|
#define MC_RESERVED_RSV_1 0x958
|
||||||
|
#define MC_DVFS_PIPE_SELECT 0x95c
|
||||||
|
#define MC_AHB_PTSA_MIN 0x4e0
|
||||||
|
#define MC_AUD_PTSA_MIN 0x54c
|
||||||
|
#define MC_MLL_MPCORER_PTSA_RATE 0x44c
|
||||||
|
#define MC_RING2_PTSA_RATE 0x440
|
||||||
|
#define MC_USBD_PTSA_RATE 0x530
|
||||||
|
#define MC_USBX_PTSA_MIN 0x528
|
||||||
|
#define MC_USBD_PTSA_MIN 0x534
|
||||||
|
#define MC_APB_PTSA_MAX 0x4f0
|
||||||
|
#define MC_JPG_PTSA_RATE 0x584
|
||||||
|
#define MC_DIS_PTSA_MIN 0x420
|
||||||
|
#define MC_AVP_PTSA_MAX 0x4fc
|
||||||
|
#define MC_AVP_PTSA_RATE 0x4f4
|
||||||
|
#define MC_RING1_PTSA_MIN 0x480
|
||||||
|
#define MC_DIS_PTSA_MAX 0x424
|
||||||
|
#define MC_SD_PTSA_MAX 0x4d8
|
||||||
|
#define MC_MSE_PTSA_RATE 0x4c4
|
||||||
|
#define MC_VICPC_PTSA_MIN 0x558
|
||||||
|
#define MC_PCX_PTSA_MAX 0x4b4
|
||||||
|
#define MC_ISP_PTSA_RATE 0x4a0
|
||||||
|
#define MC_A9AVPPC_PTSA_MIN 0x48c
|
||||||
|
#define MC_RING2_PTSA_MAX 0x448
|
||||||
|
#define MC_AUD_PTSA_RATE 0x548
|
||||||
|
#define MC_HOST_PTSA_MIN 0x51c
|
||||||
|
#define MC_MLL_MPCORER_PTSA_MAX 0x454
|
||||||
|
#define MC_SD_PTSA_MIN 0x4d4
|
||||||
|
#define MC_RING1_PTSA_RATE 0x47c
|
||||||
|
#define MC_JPG_PTSA_MIN 0x588
|
||||||
|
#define MC_HDAPC_PTSA_MIN 0x62c
|
||||||
|
#define MC_AVP_PTSA_MIN 0x4f8
|
||||||
|
#define MC_JPG_PTSA_MAX 0x58c
|
||||||
|
#define MC_VE_PTSA_MAX 0x43c
|
||||||
|
#define MC_DFD_PTSA_MAX 0x63c
|
||||||
|
#define MC_VICPC_PTSA_RATE 0x554
|
||||||
|
#define MC_GK_PTSA_MAX 0x544
|
||||||
|
#define MC_VICPC_PTSA_MAX 0x55c
|
||||||
|
#define MC_SDM_PTSA_MAX 0x624
|
||||||
|
#define MC_SAX_PTSA_RATE 0x4b8
|
||||||
|
#define MC_PCX_PTSA_MIN 0x4b0
|
||||||
|
#define MC_APB_PTSA_MIN 0x4ec
|
||||||
|
#define MC_GK2_PTSA_MIN 0x614
|
||||||
|
#define MC_PCX_PTSA_RATE 0x4ac
|
||||||
|
#define MC_RING1_PTSA_MAX 0x484
|
||||||
|
#define MC_HDAPC_PTSA_RATE 0x628
|
||||||
|
#define MC_MLL_MPCORER_PTSA_MIN 0x450
|
||||||
|
#define MC_GK2_PTSA_MAX 0x618
|
||||||
|
#define MC_AUD_PTSA_MAX 0x550
|
||||||
|
#define MC_GK2_PTSA_RATE 0x610
|
||||||
|
#define MC_ISP_PTSA_MAX 0x4a8
|
||||||
|
#define MC_DISB_PTSA_RATE 0x428
|
||||||
|
#define MC_VE2_PTSA_MAX 0x49c
|
||||||
|
#define MC_DFD_PTSA_MIN 0x638
|
||||||
|
#define MC_FTOP_PTSA_RATE 0x50c
|
||||||
|
#define MC_A9AVPPC_PTSA_RATE 0x488
|
||||||
|
#define MC_VE2_PTSA_MIN 0x498
|
||||||
|
#define MC_USBX_PTSA_MAX 0x52c
|
||||||
|
#define MC_DIS_PTSA_RATE 0x41c
|
||||||
|
#define MC_USBD_PTSA_MAX 0x538
|
||||||
|
#define MC_A9AVPPC_PTSA_MAX 0x490
|
||||||
|
#define MC_USBX_PTSA_RATE 0x524
|
||||||
|
#define MC_FTOP_PTSA_MAX 0x514
|
||||||
|
#define MC_HDAPC_PTSA_MAX 0x630
|
||||||
|
#define MC_SD_PTSA_RATE 0x4d0
|
||||||
|
#define MC_DFD_PTSA_RATE 0x634
|
||||||
|
#define MC_FTOP_PTSA_MIN 0x510
|
||||||
|
#define MC_SDM_PTSA_RATE 0x61c
|
||||||
|
#define MC_AHB_PTSA_RATE 0x4dc
|
||||||
|
#define MC_SMMU_SMMU_PTSA_MAX 0x460
|
||||||
|
#define MC_RING2_PTSA_MIN 0x444
|
||||||
|
#define MC_SDM_PTSA_MIN 0x620
|
||||||
|
#define MC_APB_PTSA_RATE 0x4e8
|
||||||
|
#define MC_MSE_PTSA_MIN 0x4c8
|
||||||
|
#define MC_HOST_PTSA_RATE 0x518
|
||||||
|
#define MC_VE_PTSA_RATE 0x434
|
||||||
|
#define MC_AHB_PTSA_MAX 0x4e4
|
||||||
|
#define MC_SAX_PTSA_MIN 0x4bc
|
||||||
|
#define MC_SMMU_SMMU_PTSA_MIN 0x45c
|
||||||
|
#define MC_ISP_PTSA_MIN 0x4a4
|
||||||
|
#define MC_HOST_PTSA_MAX 0x520
|
||||||
|
#define MC_SAX_PTSA_MAX 0x4c0
|
||||||
|
#define MC_VE_PTSA_MIN 0x438
|
||||||
|
#define MC_GK_PTSA_MIN 0x540
|
||||||
|
#define MC_MSE_PTSA_MAX 0x4cc
|
||||||
|
#define MC_DISB_PTSA_MAX 0x430
|
||||||
|
#define MC_DISB_PTSA_MIN 0x42c
|
||||||
|
#define MC_SMMU_SMMU_PTSA_RATE 0x458
|
||||||
|
#define MC_VE2_PTSA_RATE 0x494
|
||||||
|
#define MC_GK_PTSA_RATE 0x53c
|
||||||
|
#define MC_PTSA_GRANT_DECREMENT 0x960
|
||||||
|
#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4
|
||||||
|
#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0
|
||||||
|
#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380
|
||||||
|
#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384
|
||||||
|
#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc
|
||||||
|
#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8
|
||||||
|
#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370
|
||||||
|
#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0
|
||||||
|
#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374
|
||||||
|
#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8
|
||||||
|
#define MC_LATENCY_ALLOWANCE_VIC_0 0x394
|
||||||
|
#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8
|
||||||
|
#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8
|
||||||
|
#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc
|
||||||
|
#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390
|
||||||
|
#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0
|
||||||
|
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694
|
||||||
|
#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348
|
||||||
|
#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c
|
||||||
|
#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344
|
||||||
|
#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0
|
||||||
|
#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0
|
||||||
|
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698
|
||||||
|
#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec
|
||||||
|
#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc
|
||||||
|
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0
|
||||||
|
#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4
|
||||||
|
#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8
|
||||||
|
#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4
|
||||||
|
#define MC_LATENCY_ALLOWANCE_HC_1 0x314
|
||||||
|
#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0
|
||||||
|
#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4
|
||||||
|
#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c
|
||||||
|
#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec
|
||||||
|
#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320
|
||||||
|
#define MC_LATENCY_ALLOWANCE_VI2_0 0x398
|
||||||
|
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c
|
||||||
|
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4
|
||||||
|
#define MC_LATENCY_ALLOWANCE_SATA_0 0x350
|
||||||
|
#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690
|
||||||
|
#define MC_LATENCY_ALLOWANCE_HC_0 0x310
|
||||||
|
#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8
|
||||||
|
#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac
|
||||||
|
#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4
|
||||||
|
#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388
|
||||||
|
#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328
|
||||||
|
#define MC_LATENCY_ALLOWANCE_HDA_0 0x318
|
||||||
|
#define MC_MIN_LENGTH_APE_0 0xb34
|
||||||
|
#define MC_MIN_LENGTH_DCB_2 0x8a8
|
||||||
|
#define MC_MIN_LENGTH_A9AVP_0 0x950
|
||||||
|
#define MC_MIN_LENGTH_TSEC_0 0x93c
|
||||||
|
#define MC_MIN_LENGTH_DC_1 0x898
|
||||||
|
#define MC_MIN_LENGTH_AXIAP_0 0x94c
|
||||||
|
#define MC_MIN_LENGTH_ISP2B_0 0x930
|
||||||
|
#define MC_MIN_LENGTH_VI2_0 0x944
|
||||||
|
#define MC_MIN_LENGTH_DCB_0 0x8a0
|
||||||
|
#define MC_MIN_LENGTH_DCB_1 0x8a4
|
||||||
|
#define MC_MIN_LENGTH_PPCS_1 0x8f4
|
||||||
|
#define MC_MIN_LENGTH_NVJPG_0 0xb3c
|
||||||
|
#define MC_MIN_LENGTH_HDA_0 0x8c4
|
||||||
|
#define MC_MIN_LENGTH_NVENC_0 0x8d4
|
||||||
|
#define MC_MIN_LENGTH_SDMMC_0 0xb18
|
||||||
|
#define MC_MIN_LENGTH_ISP2B_1 0x934
|
||||||
|
#define MC_MIN_LENGTH_HC_1 0x8c0
|
||||||
|
#define MC_MIN_LENGTH_DC_3 0xb20
|
||||||
|
#define MC_MIN_LENGTH_AVPC_0 0x890
|
||||||
|
#define MC_MIN_LENGTH_VIC_0 0x940
|
||||||
|
#define MC_MIN_LENGTH_ISP2_0 0x91c
|
||||||
|
#define MC_MIN_LENGTH_HC_0 0x8bc
|
||||||
|
#define MC_MIN_LENGTH_SE_0 0xb38
|
||||||
|
#define MC_MIN_LENGTH_NVDEC_0 0xb30
|
||||||
|
#define MC_MIN_LENGTH_SATA_0 0x8fc
|
||||||
|
#define MC_MIN_LENGTH_DC_0 0x894
|
||||||
|
#define MC_MIN_LENGTH_XUSB_1 0x92c
|
||||||
|
#define MC_MIN_LENGTH_DC_2 0x89c
|
||||||
|
#define MC_MIN_LENGTH_SDMMCAA_0 0xb14
|
||||||
|
#define MC_MIN_LENGTH_GPU_0 0xb04
|
||||||
|
#define MC_MIN_LENGTH_ETR_0 0xb44
|
||||||
|
#define MC_MIN_LENGTH_AFI_0 0x88c
|
||||||
|
#define MC_MIN_LENGTH_PPCS_0 0x8f0
|
||||||
|
#define MC_MIN_LENGTH_ISP2_1 0x920
|
||||||
|
#define MC_MIN_LENGTH_XUSB_0 0x928
|
||||||
|
#define MC_MIN_LENGTH_MPCORE_0 0x8cc
|
||||||
|
#define MC_MIN_LENGTH_TSECB_0 0xb48
|
||||||
|
#define MC_MIN_LENGTH_SDMMCA_0 0xb10
|
||||||
|
#define MC_MIN_LENGTH_GPU2_0 0xb40
|
||||||
|
#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c
|
||||||
|
#define MC_MIN_LENGTH_PTC_0 0x8f8
|
||||||
|
#define MC_EMEM_ARB_OVERRIDE_1 0x968
|
||||||
|
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984
|
||||||
|
#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988
|
||||||
|
#define MC_EMEM_ARB_STATS_0 0x990
|
||||||
|
#define MC_EMEM_ARB_STATS_1 0x994
|
||||||
|
#define MC_MTS_CARVEOUT_BOM 0x9a0
|
||||||
|
#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4
|
||||||
|
#define MC_MTS_CARVEOUT_ADR_HI 0x9a8
|
||||||
|
#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac
|
||||||
|
#define MC_ERR_MTS_STATUS 0x9b0
|
||||||
|
#define MC_ERR_MTS_ADR 0x9b4
|
||||||
|
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00
|
||||||
|
#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10
|
||||||
|
#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c
|
||||||
|
#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CFG0 0xc58
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CFG0 0xc08
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68
|
||||||
|
#define MC_SECURITY_CARVEOUT3_BOM 0xcac
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CFG0 0xca8
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88
|
||||||
|
#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64
|
||||||
|
#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50
|
||||||
|
#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14
|
||||||
|
#define MC_SECURITY_CARVEOUT1_BOM 0xc0c
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c
|
||||||
|
#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8
|
||||||
|
#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60
|
||||||
|
#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80
|
||||||
|
#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc
|
||||||
|
#define MC_SECURITY_CARVEOUT4_BOM 0xcfc
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CFG0 0xd48
|
||||||
|
#define MC_SECURITY_CARVEOUT2_BOM 0xc5c
|
||||||
|
#define MC_SECURITY_CARVEOUT5_BOM 0xd4c
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24
|
||||||
|
#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c
|
||||||
|
#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0
|
||||||
|
#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20
|
||||||
|
#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c
|
||||||
|
#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c
|
||||||
|
#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08
|
||||||
|
#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
|
||||||
|
#define MC_DA_CONFIG0 0x9dc
|
||||||
|
|
||||||
|
/* Memory Controller clients */
|
||||||
|
#define CLIENT_ACCESS_NUM_CLIENTS 32
|
||||||
|
typedef enum {
|
||||||
|
/* _ACCESS0 */
|
||||||
|
CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)),
|
||||||
|
|
||||||
|
/* _ACCESS1 */
|
||||||
|
CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)),
|
||||||
|
|
||||||
|
/* _ACCESS2 */
|
||||||
|
CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)),
|
||||||
|
|
||||||
|
/* _ACCESS3 */
|
||||||
|
CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)),
|
||||||
|
|
||||||
|
/* _ACCESS4 */
|
||||||
|
CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)),
|
||||||
|
CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4))
|
||||||
|
} McClient;
|
||||||
|
|
||||||
|
void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock);
|
||||||
|
void mc_config_carveout();
|
||||||
|
void mc_config_carveout_finalize();
|
||||||
|
void mc_enable_ahb_redirect();
|
||||||
|
void mc_disable_ahb_redirect();
|
||||||
|
void mc_enable();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3706,7 +3706,7 @@ static int train_one(int z_val, uint32_t next_rate, uint32_t current_rate, tegra
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void train_dram() {
|
void train_dram(void) {
|
||||||
volatile tegra_car_t *car = car_get_regs();
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
|
||||||
tegra_emc_timing_t *timing_tables;
|
tegra_emc_timing_t *timing_tables;
|
||||||
@@ -754,6 +754,6 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Train all possible DRAM sequences. */
|
/* Train all possible DRAM sequences. */
|
||||||
void train_dram();
|
void train_dram(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
29
fusee/fusee-mtc/src/stage2.h
Normal file
29
fusee/fusee-mtc/src/stage2.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_STAGE2_H
|
||||||
|
#define FUSEE_STAGE2_H
|
||||||
|
|
||||||
|
#include "lib/log.h"
|
||||||
|
|
||||||
|
#define MTC_ARGV_ARGUMENT_STRUCT 0
|
||||||
|
#define MTC_ARGC 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ScreenLogLevel log_level;
|
||||||
|
} stage2_mtc_args_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
70
fusee/fusee-mtc/src/start.s
Normal file
70
fusee/fusee-mtc/src/start.s
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.macro CLEAR_GPR_REG_ITER
|
||||||
|
mov r\@, #0
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.section .text.start, "ax", %progbits
|
||||||
|
.arm
|
||||||
|
.align 5
|
||||||
|
.global _start
|
||||||
|
.type _start, %function
|
||||||
|
_start:
|
||||||
|
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||||
|
msr cpsr_cxsf, #0xDF
|
||||||
|
|
||||||
|
/* Backup current stack pointer. */
|
||||||
|
mov r12, sp
|
||||||
|
|
||||||
|
/* Set the stack pointer */
|
||||||
|
ldr sp, =__stack_top__
|
||||||
|
mov fp, #0
|
||||||
|
|
||||||
|
/* Save context */
|
||||||
|
push {r12, lr}
|
||||||
|
|
||||||
|
/* Call init. */
|
||||||
|
bl __program_init
|
||||||
|
|
||||||
|
/* Set r0 to r12 to 0 (for debugging) & call main */
|
||||||
|
.rept 13
|
||||||
|
CLEAR_GPR_REG_ITER
|
||||||
|
.endr
|
||||||
|
ldr r0, =__program_argc
|
||||||
|
ldr r1, =__program_argv
|
||||||
|
ldr r0, [r0]
|
||||||
|
ldr r1, [r1]
|
||||||
|
bl main
|
||||||
|
|
||||||
|
/* Save result. */
|
||||||
|
push {r0}
|
||||||
|
|
||||||
|
/* Exit manually. */
|
||||||
|
bl __program_exit
|
||||||
|
|
||||||
|
/* Restore result. */
|
||||||
|
pop {r0}
|
||||||
|
|
||||||
|
/* Restore context */
|
||||||
|
pop {r12}
|
||||||
|
pop {lr}
|
||||||
|
|
||||||
|
/* Restore previous stack pointer. */
|
||||||
|
mov sp, r12
|
||||||
|
|
||||||
|
/* Return */
|
||||||
|
bx lr
|
||||||
94
fusee/fusee-mtc/src/timers.h
Normal file
94
fusee/fusee-mtc/src/timers.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_TIMERS_H
|
||||||
|
#define FUSEE_TIMERS_H
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define TIMERS_BASE 0x60005000
|
||||||
|
#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n)
|
||||||
|
|
||||||
|
#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10)
|
||||||
|
#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14)
|
||||||
|
#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0)
|
||||||
|
#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4)
|
||||||
|
|
||||||
|
#define RTC_BASE 0x7000E000
|
||||||
|
#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n)
|
||||||
|
|
||||||
|
#define RTC_SECONDS MAKE_RTC_REG(0x08)
|
||||||
|
#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C)
|
||||||
|
#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t CONFIG;
|
||||||
|
uint32_t STATUS;
|
||||||
|
uint32_t COMMAND;
|
||||||
|
uint32_t PATTERN;
|
||||||
|
} watchdog_timers_t;
|
||||||
|
|
||||||
|
#define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n))
|
||||||
|
#define WDT_REBOOT_PATTERN 0xC45A
|
||||||
|
#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n)
|
||||||
|
|
||||||
|
void wait(uint32_t microseconds);
|
||||||
|
|
||||||
|
static inline uint32_t get_time_s(void) {
|
||||||
|
return RTC_SECONDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_time_ms(void) {
|
||||||
|
return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_time_us(void) {
|
||||||
|
return TIMERUS_CNTR_1US_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time in microseconds.
|
||||||
|
*/
|
||||||
|
static inline uint32_t get_time(void) {
|
||||||
|
return get_time_us();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of microseconds that have passed since a given get_time().
|
||||||
|
*/
|
||||||
|
static inline uint32_t get_time_since(uint32_t base) {
|
||||||
|
return get_time_us() - base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delays for a given number of microseconds.
|
||||||
|
*/
|
||||||
|
static inline void udelay(uint32_t usecs) {
|
||||||
|
uint32_t start = get_time_us();
|
||||||
|
while (get_time_us() - start < usecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delays for a given number of milliseconds.
|
||||||
|
*/
|
||||||
|
static inline void mdelay(uint32_t msecs) {
|
||||||
|
uint32_t start = get_time_ms();
|
||||||
|
while (get_time_ms() - start < msecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((noreturn)) void watchdog_reboot(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
40
fusee/fusee-mtc/src/utils.c
Normal file
40
fusee/fusee-mtc/src/utils.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "utils.h"
|
||||||
|
#include "lib/log.h"
|
||||||
|
|
||||||
|
__attribute__ ((noreturn)) void generic_panic(void) {
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR, "Panic raised!");
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
/* Lock. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
||||||
|
va_start(args, fmt);
|
||||||
|
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
/* Lock. */
|
||||||
|
}
|
||||||
|
}
|
||||||
43
fusee/fusee-mtc/src/utils.h
Normal file
43
fusee/fusee-mtc/src/utils.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_UTILS_H
|
||||||
|
#define FUSEE_UTILS_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define BIT(n) (1u << (n))
|
||||||
|
#define BITL(n) (1ull << (n))
|
||||||
|
#define MASK(n) (BIT(n) - 1)
|
||||||
|
#define MASKL(n) (BITL(n) - 1)
|
||||||
|
#define MASK2(a,b) (MASK(a) & ~MASK(b))
|
||||||
|
#define MASK2L(a,b) (MASKL(a) & ~MASKL(b))
|
||||||
|
|
||||||
|
#define MAKE_REG32(a) (*(volatile uint32_t *)(a))
|
||||||
|
|
||||||
|
#define ALIGN(m) __attribute__((aligned(m)))
|
||||||
|
#define PACKED __attribute__((packed))
|
||||||
|
|
||||||
|
#define ALINLINE __attribute__((always_inline))
|
||||||
|
#define NOINLINE __attribute__((noinline))
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void generic_panic(void);
|
||||||
|
__attribute__((noreturn)) void fatal_error(const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -25,7 +25,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0x1A0;
|
case CARDEVICE_UARTC: return 0x1A0;
|
||||||
case CARDEVICE_I2C1: return 0x124;
|
case CARDEVICE_I2C1: return 0x124;
|
||||||
case CARDEVICE_I2C5: return 0x128;
|
case CARDEVICE_I2C5: return 0x128;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0x42C;
|
case CARDEVICE_SE: return 0x42C;
|
||||||
case CARDEVICE_HOST1X: return 0x180;
|
case CARDEVICE_HOST1X: return 0x180;
|
||||||
case CARDEVICE_TSEC: return 0x1F4;
|
case CARDEVICE_TSEC: return 0x1F4;
|
||||||
@@ -48,7 +48,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0;
|
case CARDEVICE_UARTC: return 0;
|
||||||
case CARDEVICE_I2C1: return 6;
|
case CARDEVICE_I2C1: return 6;
|
||||||
case CARDEVICE_I2C5: return 6;
|
case CARDEVICE_I2C5: return 6;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0;
|
case CARDEVICE_SE: return 0;
|
||||||
case CARDEVICE_HOST1X: return 4;
|
case CARDEVICE_HOST1X: return 4;
|
||||||
case CARDEVICE_TSEC: return 0;
|
case CARDEVICE_TSEC: return 0;
|
||||||
@@ -71,7 +71,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0;
|
case CARDEVICE_UARTC: return 0;
|
||||||
case CARDEVICE_I2C1: return 0;
|
case CARDEVICE_I2C1: return 0;
|
||||||
case CARDEVICE_I2C5: return 0;
|
case CARDEVICE_I2C5: return 0;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0;
|
case CARDEVICE_SE: return 0;
|
||||||
case CARDEVICE_HOST1X: return 3;
|
case CARDEVICE_HOST1X: return 3;
|
||||||
case CARDEVICE_TSEC: return 2;
|
case CARDEVICE_TSEC: return 2;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ typedef enum {
|
|||||||
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||||
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||||
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||||
CARDEVICE_UNK = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
|||||||
@@ -21,125 +21,66 @@
|
|||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
/**
|
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin) {
|
||||||
* Returns a GPIO bank object that corresponds to the given GPIO pin,
|
|
||||||
* which can be created using the TEGRA_GPIO macro or passed from the name macro.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO to get the bank for.
|
|
||||||
* @return The GPIO bank object to use for working with the given bank.
|
|
||||||
*/
|
|
||||||
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin)
|
|
||||||
{
|
|
||||||
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
||||||
uint32_t bank_number = pin >> GPIO_BANK_SHIFT;
|
uint32_t bank_number = (pin >> GPIO_BANK_SHIFT);
|
||||||
|
|
||||||
return &gpio->bank[bank_number];
|
return &gpio->bank[bank_number];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static volatile uint32_t gpio_get_port(uint32_t pin) {
|
||||||
* @return the port number for working with the given GPIO.
|
return ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
|
||||||
*/
|
|
||||||
static volatile uint32_t gpio_get_port(uint32_t pin)
|
|
||||||
{
|
|
||||||
return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static volatile uint32_t gpio_get_mask(uint32_t pin) {
|
||||||
* @return a mask to be used to work with the given GPIO
|
uint32_t pin_number = (pin & GPIO_PIN_MASK);
|
||||||
*/
|
|
||||||
static volatile uint32_t gpio_get_mask(uint32_t pin)
|
|
||||||
{
|
|
||||||
uint32_t pin_number = pin & GPIO_PIN_MASK;
|
|
||||||
return (1 << pin_number);
|
return (1 << pin_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset) {
|
||||||
* Performs a simple GPIO configuration operation.
|
/* Retrieve the register set that corresponds to the given pin and offset. */
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
|
||||||
* @param offset The offset into a gpio_bank structure
|
|
||||||
*/
|
|
||||||
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset)
|
|
||||||
{
|
|
||||||
// Retrieve the register set that corresponds to the given pin and offset.
|
|
||||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||||
uint32_t *cluster = (uint32_t *)cluster_addr;
|
uint32_t *cluster = (uint32_t *)cluster_addr;
|
||||||
|
|
||||||
// Figure out the offset into the cluster,
|
/* Figure out the offset into the cluster, and the mask to be used. */
|
||||||
// and the mask to be used.
|
|
||||||
uint32_t port = gpio_get_port(pin);
|
uint32_t port = gpio_get_port(pin);
|
||||||
uint32_t mask = gpio_get_mask(pin);
|
uint32_t mask = gpio_get_mask(pin);
|
||||||
|
|
||||||
// Set or clear the bit, as appropriate.
|
/* Set or clear the bit, as appropriate. */
|
||||||
if (should_be_set)
|
if (should_be_set)
|
||||||
cluster[port] |= mask;
|
cluster[port] |= mask;
|
||||||
else
|
else
|
||||||
cluster[port] &= ~mask;
|
cluster[port] &= ~mask;
|
||||||
|
|
||||||
|
/* Dummy read. */
|
||||||
|
(void)cluster[port];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset) {
|
||||||
* Performs a simple GPIO configuration operation.
|
/* Retrieve the register set that corresponds to the given pin and offset. */
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
|
||||||
* @param offset The offset into a gpio_bank structure
|
|
||||||
*/
|
|
||||||
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset)
|
|
||||||
{
|
|
||||||
// Retrieve the register set that corresponds to the given pin and offset.
|
|
||||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||||
uint32_t *cluster = (uint32_t *)cluster_addr;
|
uint32_t *cluster = (uint32_t *)cluster_addr;
|
||||||
|
|
||||||
// Figure out the offset into the cluster,
|
/* Figure out the offset into the cluster, and the mask to be used. */
|
||||||
// and the mask to be used.
|
|
||||||
uint32_t port = gpio_get_port(pin);
|
uint32_t port = gpio_get_port(pin);
|
||||||
uint32_t mask = gpio_get_mask(pin);
|
uint32_t mask = gpio_get_mask(pin);
|
||||||
|
|
||||||
// Convert the given value to a boolean.
|
/* Convert the given value to a boolean. */
|
||||||
return !!(cluster[port] & mask);
|
return !!(cluster[port] & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_configure_mode(uint32_t pin, uint32_t mode) {
|
||||||
* Configures a given pin as either GPIO or SFIO.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
void gpio_configure_mode(uint32_t pin, uint32_t mode)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_configure_direction(uint32_t pin, uint32_t dir) {
|
||||||
* Configures a given pin as either INPUT or OUPUT.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param direction The relevant direction.
|
|
||||||
*/
|
|
||||||
void gpio_configure_direction(uint32_t pin, uint32_t dir)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_write(uint32_t pin, uint32_t value) {
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
void gpio_write(uint32_t pin, uint32_t value)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
uint32_t gpio_read(uint32_t pin) {
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
uint32_t gpio_read(uint32_t pin)
|
|
||||||
{
|
|
||||||
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ static inline volatile tegra_gpio_t *gpio_get_regs(void)
|
|||||||
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
||||||
|
|
||||||
/* Mode select */
|
/* Mode select */
|
||||||
#define GPIO_MODE_GPIO 0
|
#define GPIO_MODE_SFIO 0
|
||||||
#define GPIO_MODE_SFIO 1
|
#define GPIO_MODE_GPIO 1
|
||||||
|
|
||||||
/* Direction */
|
/* Direction */
|
||||||
#define GPIO_DIRECTION_INPUT 0
|
#define GPIO_DIRECTION_INPUT 0
|
||||||
|
|||||||
@@ -75,14 +75,9 @@ void config_gpios()
|
|||||||
gpio_configure_direction(TEGRA_GPIO(E, 6), GPIO_DIRECTION_INPUT);
|
gpio_configure_direction(TEGRA_GPIO(E, 6), GPIO_DIRECTION_INPUT);
|
||||||
gpio_configure_direction(TEGRA_GPIO(H, 6), GPIO_DIRECTION_INPUT);
|
gpio_configure_direction(TEGRA_GPIO(H, 6), GPIO_DIRECTION_INPUT);
|
||||||
|
|
||||||
pinmux->gen1_i2c_scl = PINMUX_INPUT;
|
i2c_config(I2C_1);
|
||||||
pinmux->gen1_i2c_sda = PINMUX_INPUT;
|
i2c_config(I2C_5);
|
||||||
pinmux->pwr_i2c_scl = PINMUX_INPUT;
|
uart_config(UART_A);
|
||||||
pinmux->pwr_i2c_sda = PINMUX_INPUT;
|
|
||||||
pinmux->uart1_rx = 0;
|
|
||||||
pinmux->uart1_tx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
|
||||||
pinmux->uart1_rts = 0;
|
|
||||||
pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
|
||||||
|
|
||||||
/* Configure volume up/down as inputs. */
|
/* Configure volume up/down as inputs. */
|
||||||
gpio_configure_mode(GPIO_BUTTON_VOL_UP, GPIO_MODE_GPIO);
|
gpio_configure_mode(GPIO_BUTTON_VOL_UP, GPIO_MODE_GPIO);
|
||||||
@@ -236,8 +231,8 @@ void nx_hwinit()
|
|||||||
/* NOTE: [4.0.0+] This was removed. */
|
/* NOTE: [4.0.0+] This was removed. */
|
||||||
/* clkrst_reboot(CARDEVICE_SE); */
|
/* clkrst_reboot(CARDEVICE_SE); */
|
||||||
|
|
||||||
/* Reboot unknown device. */
|
/* Reboot TZRAM. */
|
||||||
clkrst_reboot(CARDEVICE_UNK);
|
clkrst_reboot(CARDEVICE_TZRAM);
|
||||||
|
|
||||||
/* Initialize I2C1. */
|
/* Initialize I2C1. */
|
||||||
/* NOTE: [6.0.0+] This was moved to after the PMIC is configured. */
|
/* NOTE: [6.0.0+] This was moved to after the PMIC is configured. */
|
||||||
|
|||||||
@@ -17,19 +17,52 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
#include "pinmux.h"
|
||||||
|
|
||||||
/* Prototypes for internal commands. */
|
/* Prototypes for internal commands. */
|
||||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id);
|
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id);
|
||||||
void i2c_load_config(volatile tegra_i2c_t *regs);
|
void i2c_load_config(volatile tegra_i2c_t *regs);
|
||||||
|
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||||
|
|
||||||
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
|
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
|
||||||
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
|
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
|
||||||
|
|
||||||
|
/* Configure I2C pinmux. */
|
||||||
|
void i2c_config(I2CDevice id) {
|
||||||
|
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case I2C_1:
|
||||||
|
pinmux->gen1_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen1_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_2:
|
||||||
|
pinmux->gen2_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen2_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_3:
|
||||||
|
pinmux->gen3_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen3_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_4:
|
||||||
|
pinmux->cam_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->cam_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_5:
|
||||||
|
pinmux->pwr_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->pwr_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_6:
|
||||||
|
/* Unused. */
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize I2C based on registers. */
|
/* Initialize I2C based on registers. */
|
||||||
void i2c_init(unsigned int id) {
|
void i2c_init(I2CDevice id) {
|
||||||
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||||
|
|
||||||
/* Setup divisor, and clear the bus. */
|
/* Setup divisor, and clear the bus. */
|
||||||
@@ -91,7 +124,7 @@ void i2c_set_ti_charger_bit_7(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get registers pointer based on I2C ID. */
|
/* Get registers pointer based on I2C ID. */
|
||||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) {
|
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case I2C_1:
|
case I2C_1:
|
||||||
return I2C1_REGS;
|
return I2C1_REGS;
|
||||||
@@ -126,7 +159,7 @@ void i2c_load_config(volatile tegra_i2c_t *regs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reads a register from a device over I2C, writes result to output. */
|
/* Reads a register from a device over I2C, writes result to output. */
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
||||||
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||||
uint32_t val = r;
|
uint32_t val = r;
|
||||||
|
|
||||||
@@ -143,7 +176,7 @@ bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Writes a value to a register over I2C. */
|
/* Writes a value to a register over I2C. */
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
||||||
uint32_t val = r;
|
uint32_t val = r;
|
||||||
if (src_size == 0) {
|
if (src_size == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -24,13 +24,6 @@
|
|||||||
#define I2C1234_BASE 0x7000C000
|
#define I2C1234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
#define I2C_1 0
|
|
||||||
#define I2C_2 1
|
|
||||||
#define I2C_3 2
|
|
||||||
#define I2C_4 3
|
|
||||||
#define I2C_5 4
|
|
||||||
#define I2C_6 5
|
|
||||||
|
|
||||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
#define MAX17050_I2C_ADDR 0x36
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
@@ -38,6 +31,15 @@
|
|||||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
#define BQ24193_I2C_ADDR 0x6B
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I2C_1 = 0,
|
||||||
|
I2C_2 = 1,
|
||||||
|
I2C_3 = 2,
|
||||||
|
I2C_4 = 3,
|
||||||
|
I2C_5 = 4,
|
||||||
|
I2C_6 = 5,
|
||||||
|
} I2CDevice;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t I2C_I2C_CNFG_0;
|
uint32_t I2C_I2C_CNFG_0;
|
||||||
uint32_t I2C_I2C_CMD_ADDR0_0;
|
uint32_t I2C_I2C_CMD_ADDR0_0;
|
||||||
@@ -89,9 +91,11 @@ typedef struct {
|
|||||||
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
||||||
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
||||||
|
|
||||||
void i2c_init(unsigned int id);
|
void i2c_config(I2CDevice id);
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
void i2c_init(I2CDevice id);
|
||||||
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||||
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||||
|
|
||||||
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
||||||
bool i2c_query_ti_charger_bit_7(void);
|
bool i2c_query_ti_charger_bit_7(void);
|
||||||
|
|||||||
@@ -322,3 +322,9 @@ R0.13b (April 07, 2018)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.13c (October 14, 2018)
|
||||||
|
Supported stdint.h for C99 and later. (integer.h was included in ff.h)
|
||||||
|
Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12)
|
||||||
|
Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12)
|
||||||
|
Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FatFs Module Source Files R0.13b
|
FatFs Module Source Files R0.13c
|
||||||
|
|
||||||
|
|
||||||
FILES
|
FILES
|
||||||
@@ -10,7 +10,6 @@ FILES
|
|||||||
ff.h Common include file for FatFs and application module.
|
ff.h Common include file for FatFs and application module.
|
||||||
diskio.h Common include file for FatFs and disk I/O module.
|
diskio.h Common include file for FatFs and disk I/O module.
|
||||||
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
||||||
integer.h Integer type definitions for FatFs.
|
|
||||||
ffunicode.c Optional Unicode utility functions.
|
ffunicode.c Optional Unicode utility functions.
|
||||||
ffsystem.c An example of optional O/S related functions.
|
ffsystem.c An example of optional O/S related functions.
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,11 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "diskio.h" /* FatFs lower layer API */
|
#include "ff.h" /* Obtains integer types */
|
||||||
|
#include "diskio.h" /* Declarations of disk functions */
|
||||||
#include "../../fs_utils.h"
|
#include "../../fs_utils.h"
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Get Drive Status */
|
/* Get Drive Status */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
@@ -63,6 +65,8 @@ DRESULT disk_read (
|
|||||||
/* Write Sector(s) */
|
/* Write Sector(s) */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if FF_FS_READONLY == 0
|
||||||
|
|
||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
const BYTE *buff, /* Data to be written */
|
const BYTE *buff, /* Data to be written */
|
||||||
@@ -78,6 +82,7 @@ DRESULT disk_write (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|||||||
@@ -9,9 +9,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "integer.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Status of Disk Functions */
|
/* Status of Disk Functions */
|
||||||
typedef BYTE DSTATUS;
|
typedef BYTE DSTATUS;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem Module R0.13b /
|
/ FatFs - Generic FAT Filesystem Module R0.13c /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
@@ -31,11 +31,20 @@
|
|||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if FF_DEFINED != 63463 /* Revision ID */
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Limits and boundaries */
|
||||||
|
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
||||||
|
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
||||||
|
#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
||||||
|
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
||||||
|
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
||||||
|
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
||||||
|
|
||||||
|
|
||||||
/* Character code support macros */
|
/* Character code support macros */
|
||||||
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
||||||
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
|
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
|
||||||
@@ -45,18 +54,18 @@
|
|||||||
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
|
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
|
||||||
|
|
||||||
|
|
||||||
/* Additional file attribute bits for internal use */
|
|
||||||
#define AM_VOL 0x08 /* Volume label */
|
|
||||||
#define AM_LFN 0x0F /* LFN entry */
|
|
||||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
|
||||||
|
|
||||||
|
|
||||||
/* Additional file access control and file status flags for internal use */
|
/* Additional file access control and file status flags for internal use */
|
||||||
#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */
|
#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */
|
||||||
#define FA_MODIFIED 0x40 /* File has been modified */
|
#define FA_MODIFIED 0x40 /* File has been modified */
|
||||||
#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
|
#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
|
||||||
|
|
||||||
|
|
||||||
|
/* Additional file attribute bits for internal use */
|
||||||
|
#define AM_VOL 0x08 /* Volume label */
|
||||||
|
#define AM_LFN 0x0F /* LFN entry */
|
||||||
|
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||||
|
|
||||||
|
|
||||||
/* Name status flags in fn[11] */
|
/* Name status flags in fn[11] */
|
||||||
#define NSFLAG 11 /* Index of the name status byte */
|
#define NSFLAG 11 /* Index of the name status byte */
|
||||||
#define NS_LOSS 0x01 /* Out of 8.3 format */
|
#define NS_LOSS 0x01 /* Out of 8.3 format */
|
||||||
@@ -69,13 +78,13 @@
|
|||||||
#define NS_NONAME 0x80 /* Not followed */
|
#define NS_NONAME 0x80 /* Not followed */
|
||||||
|
|
||||||
|
|
||||||
/* Limits and boundaries */
|
/* exFAT directory entry types */
|
||||||
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
#define ET_BITMAP 0x81 /* Allocation bitmap */
|
||||||
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
#define ET_UPCASE 0x82 /* Up-case table */
|
||||||
#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
#define ET_VLABEL 0x83 /* Volume label */
|
||||||
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
#define ET_FILEDIR 0x85 /* File and directory */
|
||||||
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
#define ET_STREAM 0xC0 /* Stream extension */
|
||||||
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
#define ET_FILENAME 0xC1 /* Name extension */
|
||||||
|
|
||||||
|
|
||||||
/* FatFs refers the FAT structure as simple byte array instead of structure member
|
/* FatFs refers the FAT structure as simple byte array instead of structure member
|
||||||
@@ -523,6 +532,7 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */
|
|||||||
#define CODEPAGE CodePage
|
#define CODEPAGE CodePage
|
||||||
static WORD CodePage; /* Current code page */
|
static WORD CodePage; /* Current code page */
|
||||||
static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */
|
static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */
|
||||||
|
|
||||||
static const BYTE Ct437[] = TBL_CT437;
|
static const BYTE Ct437[] = TBL_CT437;
|
||||||
static const BYTE Ct720[] = TBL_CT720;
|
static const BYTE Ct720[] = TBL_CT720;
|
||||||
static const BYTE Ct737[] = TBL_CT737;
|
static const BYTE Ct737[] = TBL_CT737;
|
||||||
@@ -1095,7 +1105,7 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */
|
|||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
|
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
|
||||||
/* Create FSInfo structure */
|
/* Create FSInfo structure */
|
||||||
mem_set(fs->win, 0, SS(fs));
|
mem_set(fs->win, 0, sizeof fs->win);
|
||||||
st_word(fs->win + BS_55AA, 0xAA55);
|
st_word(fs->win + BS_55AA, 0xAA55);
|
||||||
st_dword(fs->win + FSI_LeadSig, 0x41615252);
|
st_dword(fs->win + FSI_LeadSig, 0x41615252);
|
||||||
st_dword(fs->win + FSI_StrucSig, 0x61417272);
|
st_dword(fs->win + FSI_StrucSig, 0x61417272);
|
||||||
@@ -1295,7 +1305,7 @@ static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:D
|
|||||||
if (clst >= fs->n_fatent - 2) clst = 0;
|
if (clst >= fs->n_fatent - 2) clst = 0;
|
||||||
scl = val = clst; ctr = 0;
|
scl = val = clst; ctr = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */
|
if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF;
|
||||||
i = val / 8 % SS(fs); bm = 1 << (val % 8);
|
i = val / 8 % SS(fs); bm = 1 << (val % 8);
|
||||||
do {
|
do {
|
||||||
do {
|
do {
|
||||||
@@ -1333,9 +1343,9 @@ static FRESULT change_bitmap (
|
|||||||
|
|
||||||
|
|
||||||
clst -= 2; /* The first bit corresponds to cluster #2 */
|
clst -= 2; /* The first bit corresponds to cluster #2 */
|
||||||
sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */
|
sect = fs->bitbase + clst / 8 / SS(fs); /* Sector address */
|
||||||
i = clst / 8 % SS(fs); /* Byte offset in the sector */
|
i = clst / 8 % SS(fs); /* Byte offset in the sector */
|
||||||
bm = 1 << (clst % 8); /* Bit mask in the byte */
|
bm = 1 << (clst % 8); /* Bit mask in the byte */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR;
|
if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR;
|
||||||
do {
|
do {
|
||||||
@@ -1408,7 +1418,7 @@ static FRESULT fill_last_frag (
|
|||||||
static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
FFOBJID* obj, /* Corresponding object */
|
FFOBJID* obj, /* Corresponding object */
|
||||||
DWORD clst, /* Cluster to remove a chain from */
|
DWORD clst, /* Cluster to remove a chain from */
|
||||||
DWORD pclst /* Previous cluster of clst (0:entire chain) */
|
DWORD pclst /* Previous cluster of clst (0 if entire chain) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
FRESULT res = FR_OK;
|
FRESULT res = FR_OK;
|
||||||
@@ -1646,7 +1656,7 @@ static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */
|
|||||||
if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */
|
if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */
|
||||||
sect = clst2sect(fs, clst); /* Top of the cluster */
|
sect = clst2sect(fs, clst); /* Top of the cluster */
|
||||||
fs->winsect = sect; /* Set window to top of the cluster */
|
fs->winsect = sect; /* Set window to top of the cluster */
|
||||||
mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */
|
mem_set(fs->win, 0, sizeof fs->win); /* Clear window buffer */
|
||||||
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
|
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
|
||||||
/* Allocate a temporary buffer */
|
/* Allocate a temporary buffer */
|
||||||
for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
|
for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
|
||||||
@@ -1730,7 +1740,8 @@ static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DEN
|
|||||||
|
|
||||||
|
|
||||||
ofs = dp->dptr + SZDIRE; /* Next entry */
|
ofs = dp->dptr + SZDIRE; /* Next entry */
|
||||||
if (dp->sect == 0 || ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) return FR_NO_FILE; /* Report EOT when offset has reached max value */
|
if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0; /* Disable it if the offset reached the max value */
|
||||||
|
if (dp->sect == 0) return FR_NO_FILE; /* Report EOT if it has been disabled */
|
||||||
|
|
||||||
if (ofs % SS(fs) == 0) { /* Sector changed? */
|
if (ofs % SS(fs) == 0) { /* Sector changed? */
|
||||||
dp->sect++; /* Next sector */
|
dp->sect++; /* Next sector */
|
||||||
@@ -1875,7 +1886,7 @@ static int cmp_lfn ( /* 1:matched, 0:not matched */
|
|||||||
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
if (i >= FF_MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */
|
if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */
|
||||||
return 0; /* Not matched */
|
return 0; /* Not matched */
|
||||||
}
|
}
|
||||||
wc = uc;
|
wc = uc;
|
||||||
@@ -1911,15 +1922,15 @@ static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */
|
|||||||
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i++] = wc = uc; /* Store it */
|
lfnbuf[i++] = wc = uc; /* Store it */
|
||||||
} else {
|
} else {
|
||||||
if (uc != 0xFFFF) return 0; /* Check filler */
|
if (uc != 0xFFFF) return 0; /* Check filler */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */
|
if (dir[LDIR_Ord] & LLEF && wc != 0) { /* Put terminator if it is the last LFN part and not terminated */
|
||||||
if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i] = 0;
|
lfnbuf[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2155,33 +2166,33 @@ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */
|
|||||||
BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
|
BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
|
||||||
|
|
||||||
|
|
||||||
/* Load 85 entry */
|
/* Load file-directory entry */
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */
|
||||||
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
|
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
|
||||||
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
|
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
|
||||||
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
|
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
|
||||||
|
|
||||||
/* Load C0 entry */
|
/* Load stream-extension entry */
|
||||||
res = dir_next(dp, 0);
|
res = dir_next(dp, 0);
|
||||||
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */
|
||||||
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
|
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
|
||||||
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
|
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
|
||||||
|
|
||||||
/* Load C1 entries */
|
/* Load file-name entries */
|
||||||
i = 2 * SZDIRE; /* C1 offset to load */
|
i = 2 * SZDIRE; /* Name offset to load */
|
||||||
do {
|
do {
|
||||||
res = dir_next(dp, 0);
|
res = dir_next(dp, 0);
|
||||||
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR; /* Invalid order */
|
||||||
if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
|
if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
|
||||||
} while ((i += SZDIRE) < sz_ent);
|
} while ((i += SZDIRE) < sz_ent);
|
||||||
|
|
||||||
@@ -2286,16 +2297,16 @@ static void create_xdir (
|
|||||||
WCHAR wc;
|
WCHAR wc;
|
||||||
|
|
||||||
|
|
||||||
/* Create 85,C0 entry */
|
/* Create file-directory and stream-extension entry */
|
||||||
mem_set(dirb, 0, 2 * SZDIRE);
|
mem_set(dirb, 0, 2 * SZDIRE);
|
||||||
dirb[0 * SZDIRE + XDIR_Type] = 0x85; /* 85 entry */
|
dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR;
|
||||||
dirb[1 * SZDIRE + XDIR_Type] = 0xC0; /* C0 entry */
|
dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM;
|
||||||
|
|
||||||
/* Create C1 entries */
|
/* Create file-name entries */
|
||||||
i = SZDIRE * 2; /* Top of C1 entries */
|
i = SZDIRE * 2; /* Top of file_name entries */
|
||||||
nlen = nc1 = 0; wc = 1;
|
nlen = nc1 = 0; wc = 1;
|
||||||
do {
|
do {
|
||||||
dirb[i++] = 0xC1; dirb[i++] = 0; /* Entry type C1 */
|
dirb[i++] = ET_FILENAME; dirb[i++] = 0;
|
||||||
do { /* Fill name field */
|
do { /* Fill name field */
|
||||||
if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */
|
if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */
|
||||||
st_word(dirb + i, wc); /* Store it */
|
st_word(dirb + i, wc); /* Store it */
|
||||||
@@ -2319,8 +2330,8 @@ static void create_xdir (
|
|||||||
/* Read an object from the directory */
|
/* Read an object from the directory */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define dir_read_file(dp) dir_read(dp, 0)
|
#define DIR_READ_FILE(dp) dir_read(dp, 0)
|
||||||
#define dir_read_label(dp) dir_read(dp, 1)
|
#define DIR_READ_LABEL(dp) dir_read(dp, 1)
|
||||||
|
|
||||||
static FRESULT dir_read (
|
static FRESULT dir_read (
|
||||||
DIR* dp, /* Pointer to the directory object */
|
DIR* dp, /* Pointer to the directory object */
|
||||||
@@ -2329,7 +2340,7 @@ static FRESULT dir_read (
|
|||||||
{
|
{
|
||||||
FRESULT res = FR_NO_FILE;
|
FRESULT res = FR_NO_FILE;
|
||||||
FATFS *fs = dp->obj.fs;
|
FATFS *fs = dp->obj.fs;
|
||||||
BYTE a, c;
|
BYTE attr, b;
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
BYTE ord = 0xFF, sum = 0xFF;
|
BYTE ord = 0xFF, sum = 0xFF;
|
||||||
#endif
|
#endif
|
||||||
@@ -2337,16 +2348,16 @@ static FRESULT dir_read (
|
|||||||
while (dp->sect) {
|
while (dp->sect) {
|
||||||
res = move_window(fs, dp->sect);
|
res = move_window(fs, dp->sect);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
c = dp->dir[DIR_Name]; /* Test for the entry type */
|
b = dp->dir[DIR_Name]; /* Test for the entry type */
|
||||||
if (c == 0) {
|
if (b == 0) {
|
||||||
res = FR_NO_FILE; break; /* Reached to end of the directory */
|
res = FR_NO_FILE; break; /* Reached to end of the directory */
|
||||||
}
|
}
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
||||||
if (FF_USE_LABEL && vol) {
|
if (FF_USE_LABEL && vol) {
|
||||||
if (c == 0x83) break; /* Volume label entry? */
|
if (b == ET_VLABEL) break; /* Volume label entry? */
|
||||||
} else {
|
} else {
|
||||||
if (c == 0x85) { /* Start of the file entry block? */
|
if (b == ET_FILEDIR) { /* Start of the file entry block? */
|
||||||
dp->blk_ofs = dp->dptr; /* Get location of the block */
|
dp->blk_ofs = dp->dptr; /* Get location of the block */
|
||||||
res = load_xdir(dp); /* Load the entry block */
|
res = load_xdir(dp); /* Load the entry block */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
@@ -2358,19 +2369,19 @@ static FRESULT dir_read (
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{ /* On the FAT/FAT32 volume */
|
{ /* On the FAT/FAT32 volume */
|
||||||
dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
|
dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
|
||||||
#if FF_USE_LFN /* LFN configuration */
|
#if FF_USE_LFN /* LFN configuration */
|
||||||
if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
|
if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
|
||||||
ord = 0xFF;
|
ord = 0xFF;
|
||||||
} else {
|
} else {
|
||||||
if (a == AM_LFN) { /* An LFN entry is found */
|
if (attr == AM_LFN) { /* An LFN entry is found */
|
||||||
if (c & LLEF) { /* Is it start of an LFN sequence? */
|
if (b & LLEF) { /* Is it start of an LFN sequence? */
|
||||||
sum = dp->dir[LDIR_Chksum];
|
sum = dp->dir[LDIR_Chksum];
|
||||||
c &= (BYTE)~LLEF; ord = c;
|
b &= (BYTE)~LLEF; ord = b;
|
||||||
dp->blk_ofs = dp->dptr;
|
dp->blk_ofs = dp->dptr;
|
||||||
}
|
}
|
||||||
/* Check LFN validity and capture it */
|
/* Check LFN validity and capture it */
|
||||||
ord = (c == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
|
ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
|
||||||
} else { /* An SFN entry is found */
|
} else { /* An SFN entry is found */
|
||||||
if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */
|
if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */
|
||||||
dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
|
dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
|
||||||
@@ -2379,7 +2390,7 @@ static FRESULT dir_read (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* Non LFN configuration */
|
#else /* Non LFN configuration */
|
||||||
if (c != DDEM && c != '.' && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */
|
if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2419,7 +2430,7 @@ static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
|
|||||||
UINT di, ni;
|
UINT di, ni;
|
||||||
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
|
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
|
||||||
|
|
||||||
while ((res = dir_read_file(dp)) == FR_OK) { /* Read an item */
|
while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */
|
||||||
#if FF_MAX_LFN < 255
|
#if FF_MAX_LFN < 255
|
||||||
if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */
|
if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */
|
||||||
#endif
|
#endif
|
||||||
@@ -2498,17 +2509,17 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
|
|||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
||||||
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
|
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
|
||||||
res = dir_alloc(dp, nent); /* Allocate entries */
|
res = dir_alloc(dp, nent); /* Allocate directory entries */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
|
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
|
||||||
|
|
||||||
if (dp->obj.stat & 4) { /* Has the directory been stretched? */
|
if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */
|
||||||
dp->obj.stat &= ~4;
|
dp->obj.stat &= ~4;
|
||||||
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
|
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->obj.sclust != 0) { /* Is it a sub directory? */
|
if (dp->obj.sclust != 0) { /* Is it a sub-directory? */
|
||||||
DIR dj;
|
DIR dj;
|
||||||
|
|
||||||
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
|
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
|
||||||
@@ -2640,6 +2651,7 @@ static void get_fileinfo (
|
|||||||
{
|
{
|
||||||
UINT si, di;
|
UINT si, di;
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
|
BYTE lcf;
|
||||||
WCHAR wc, hs;
|
WCHAR wc, hs;
|
||||||
FATFS *fs = dp->obj.fs;
|
FATFS *fs = dp->obj.fs;
|
||||||
#else
|
#else
|
||||||
@@ -2700,9 +2712,10 @@ static void get_fileinfo (
|
|||||||
if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */
|
if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */
|
||||||
fno->fname[di++] = '?';
|
fno->fname[di++] = '?';
|
||||||
} else {
|
} else {
|
||||||
for (si = di = 0; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */
|
for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */
|
||||||
wc = (WCHAR)fno->altname[si];
|
wc = (WCHAR)fno->altname[si];
|
||||||
if (IsUpper(wc) && (dp->dir[DIR_NTres] & ((si >= 9) ? NS_EXT : NS_BODY))) wc += 0x20;
|
if (wc == '.') lcf = NS_EXT;
|
||||||
|
if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20;
|
||||||
fno->fname[di] = (TCHAR)wc;
|
fno->fname[di] = (TCHAR)wc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3256,7 +3269,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|||||||
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
|
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */
|
/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */
|
||||||
bsect = 0;
|
bsect = 0;
|
||||||
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
|
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
|
||||||
if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
|
if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
|
||||||
@@ -3279,6 +3292,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fmt == 1) {
|
if (fmt == 1) {
|
||||||
QWORD maxlba;
|
QWORD maxlba;
|
||||||
|
DWORD so, cv, bcl;
|
||||||
|
|
||||||
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
||||||
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
|
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
|
||||||
@@ -3311,12 +3325,27 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|||||||
if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */
|
if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */
|
||||||
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
||||||
|
|
||||||
/* Check if bitmap location is in assumption (at the first cluster) */
|
/* Get bitmap location and check if it is contiguous (implementation assumption) */
|
||||||
if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR;
|
so = i = 0;
|
||||||
for (i = 0; i < SS(fs); i += SZDIRE) {
|
for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */
|
||||||
if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */
|
if (i == 0) {
|
||||||
|
if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */
|
||||||
|
if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) return FR_DISK_ERR;
|
||||||
|
so++;
|
||||||
|
}
|
||||||
|
if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */
|
||||||
|
i = (i + SZDIRE) % SS(fs); /* Next entry */
|
||||||
}
|
}
|
||||||
if (i == SS(fs)) return FR_NO_FILESYSTEM;
|
bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */
|
||||||
|
if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM;
|
||||||
|
fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */
|
||||||
|
for (;;) { /* Check if bitmap is contiguous */
|
||||||
|
if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR;
|
||||||
|
cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4);
|
||||||
|
if (cv == 0xFFFFFFFF) break; /* Last link? */
|
||||||
|
if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented? */
|
||||||
|
}
|
||||||
|
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
|
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
|
||||||
#endif
|
#endif
|
||||||
@@ -3666,7 +3695,7 @@ FRESULT f_open (
|
|||||||
fp->fptr = 0; /* Set file pointer top of the file */
|
fp->fptr = 0; /* Set file pointer top of the file */
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
#if !FF_FS_TINY
|
#if !FF_FS_TINY
|
||||||
mem_set(fp->buf, 0, FF_MAX_SS); /* Clear sector buffer */
|
mem_set(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */
|
||||||
#endif
|
#endif
|
||||||
if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
|
if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
|
||||||
fp->fptr = fp->obj.objsize; /* Offset to seek */
|
fp->fptr = fp->obj.objsize; /* Offset to seek */
|
||||||
@@ -4137,15 +4166,16 @@ FRESULT f_getcwd (
|
|||||||
TCHAR *tp = buff;
|
TCHAR *tp = buff;
|
||||||
#if FF_VOLUMES >= 2
|
#if FF_VOLUMES >= 2
|
||||||
UINT vl;
|
UINT vl;
|
||||||
#endif
|
|
||||||
#if FF_STR_VOLUME_ID
|
#if FF_STR_VOLUME_ID
|
||||||
const char *vp;
|
const char *vp;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
DEF_NAMBUF
|
DEF_NAMBUF
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive */
|
/* Get logical drive */
|
||||||
|
buff[0] = 0; /* Set null string to get current volume */
|
||||||
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
|
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
dj.obj.fs = fs;
|
dj.obj.fs = fs;
|
||||||
@@ -4164,7 +4194,7 @@ FRESULT f_getcwd (
|
|||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
do { /* Find the entry links to the child directory */
|
do { /* Find the entry links to the child directory */
|
||||||
res = dir_read_file(&dj);
|
res = DIR_READ_FILE(&dj);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */
|
if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */
|
||||||
res = dir_next(&dj, 0);
|
res = dir_next(&dj, 0);
|
||||||
@@ -4496,7 +4526,7 @@ FRESULT f_readdir (
|
|||||||
res = dir_sdi(dp, 0); /* Rewind the directory object */
|
res = dir_sdi(dp, 0); /* Rewind the directory object */
|
||||||
} else {
|
} else {
|
||||||
INIT_NAMBUF(fs);
|
INIT_NAMBUF(fs);
|
||||||
res = dir_read_file(dp); /* Read an item */
|
res = DIR_READ_FILE(dp); /* Read an item */
|
||||||
if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
|
if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
|
||||||
if (res == FR_OK) { /* A valid entry is found */
|
if (res == FR_OK) { /* A valid entry is found */
|
||||||
get_fileinfo(dp, fno); /* Get the object information */
|
get_fileinfo(dp, fno); /* Get the object information */
|
||||||
@@ -4641,7 +4671,7 @@ FRESULT f_getfree (
|
|||||||
UINT b;
|
UINT b;
|
||||||
|
|
||||||
clst = fs->n_fatent - 2; /* Number of clusters */
|
clst = fs->n_fatent - 2; /* Number of clusters */
|
||||||
sect = fs->database; /* Assuming bitmap starts at cluster 2 */
|
sect = fs->bitbase; /* Bitmap sector */
|
||||||
i = 0; /* Offset in the sector */
|
i = 0; /* Offset in the sector */
|
||||||
do { /* Counts numbuer of bits with zero in the bitmap */
|
do { /* Counts numbuer of bits with zero in the bitmap */
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
@@ -4804,7 +4834,7 @@ FRESULT f_unlink (
|
|||||||
#endif
|
#endif
|
||||||
res = dir_sdi(&sdj, 0);
|
res = dir_sdi(&sdj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_file(&sdj); /* Test if the directory is empty */
|
res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */
|
||||||
if (res == FR_OK) res = FR_DENIED; /* Not empty? */
|
if (res == FR_OK) res = FR_DENIED; /* Not empty? */
|
||||||
if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
|
if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
|
||||||
}
|
}
|
||||||
@@ -4842,73 +4872,69 @@ FRESULT f_mkdir (
|
|||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
DIR dj;
|
DIR dj;
|
||||||
|
FFOBJID sobj;
|
||||||
FATFS *fs;
|
FATFS *fs;
|
||||||
BYTE *dir;
|
|
||||||
DWORD dcl, pcl, tm;
|
DWORD dcl, pcl, tm;
|
||||||
DEF_NAMBUF
|
DEF_NAMBUF
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive */
|
res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */
|
||||||
res = find_volume(&path, &fs, FA_WRITE);
|
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
dj.obj.fs = fs;
|
dj.obj.fs = fs;
|
||||||
INIT_NAMBUF(fs);
|
INIT_NAMBUF(fs);
|
||||||
res = follow_path(&dj, path); /* Follow the file path */
|
res = follow_path(&dj, path); /* Follow the file path */
|
||||||
if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */
|
if (res == FR_OK) res = FR_EXIST; /* Name collision? */
|
||||||
if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) {
|
if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */
|
||||||
res = FR_INVALID_NAME;
|
res = FR_INVALID_NAME;
|
||||||
}
|
}
|
||||||
if (res == FR_NO_FILE) { /* Can create a new directory */
|
if (res == FR_NO_FILE) { /* It is clear to create a new directory */
|
||||||
dcl = create_chain(&dj.obj, 0); /* Allocate a cluster for the new directory table */
|
sobj.fs = fs; /* New object id to create a new chain */
|
||||||
dj.obj.objsize = (DWORD)fs->csize * SS(fs);
|
dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */
|
||||||
res = FR_OK;
|
res = FR_OK;
|
||||||
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
|
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */
|
||||||
if (dcl == 1) res = FR_INT_ERR;
|
if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */
|
||||||
if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
|
if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */
|
||||||
if (res == FR_OK) res = sync_window(fs); /* Flush FAT */
|
|
||||||
tm = GET_FATTIME();
|
tm = GET_FATTIME();
|
||||||
if (res == FR_OK) { /* Initialize the new directory table */
|
|
||||||
res = dir_clear(fs, dcl); /* Clean up the new table */
|
|
||||||
if (res == FR_OK && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT)) { /* Create dot entries (FAT only) */
|
|
||||||
dir = fs->win;
|
|
||||||
mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */
|
|
||||||
dir[DIR_Name] = '.';
|
|
||||||
dir[DIR_Attr] = AM_DIR;
|
|
||||||
st_dword(dir + DIR_ModTime, tm);
|
|
||||||
st_clust(fs, dir, dcl);
|
|
||||||
mem_cpy(dir + SZDIRE, dir, SZDIRE); /* Create ".." entry */
|
|
||||||
dir[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
|
|
||||||
st_clust(fs, dir + SZDIRE, pcl);
|
|
||||||
fs->wflag = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_register(&dj); /* Register the object to the directoy */
|
res = dir_clear(fs, dcl); /* Clean up the new table */
|
||||||
|
if (res == FR_OK) {
|
||||||
|
if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */
|
||||||
|
mem_set(fs->win + DIR_Name, ' ', 11); /* Create "." entry */
|
||||||
|
fs->win[DIR_Name] = '.';
|
||||||
|
fs->win[DIR_Attr] = AM_DIR;
|
||||||
|
st_dword(fs->win + DIR_ModTime, tm);
|
||||||
|
st_clust(fs, fs->win, dcl);
|
||||||
|
mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */
|
||||||
|
fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
|
||||||
|
st_clust(fs, fs->win + SZDIRE, pcl);
|
||||||
|
fs->wflag = 1;
|
||||||
|
}
|
||||||
|
res = dir_register(&dj); /* Register the object to the parent directoy */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */
|
if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */
|
||||||
st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */
|
st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */
|
||||||
st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */
|
st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */
|
||||||
st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)dj.obj.objsize); /* File size needs to be valid */
|
st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* File size needs to be valid */
|
||||||
st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)dj.obj.objsize);
|
st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs));
|
||||||
fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */
|
fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */
|
||||||
fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */
|
fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */
|
||||||
res = store_xdir(&dj);
|
res = store_xdir(&dj);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
dir = dj.dir;
|
st_dword(dj.dir + DIR_ModTime, tm); /* Created time */
|
||||||
st_dword(dir + DIR_ModTime, tm); /* Created time */
|
st_clust(fs, dj.dir, dcl); /* Table start cluster */
|
||||||
st_clust(fs, dir, dcl); /* Table start cluster */
|
dj.dir[DIR_Attr] = AM_DIR; /* Attribute */
|
||||||
dir[DIR_Attr] = AM_DIR; /* Attribute */
|
|
||||||
fs->wflag = 1;
|
fs->wflag = 1;
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = sync_fs(fs);
|
res = sync_fs(fs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
remove_chain(&dj.obj, dcl, 0); /* Could not register, remove cluster chain */
|
remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FREE_NAMBUF();
|
FREE_NAMBUF();
|
||||||
@@ -5148,7 +5174,7 @@ FRESULT f_getlabel (
|
|||||||
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_label(&dj); /* Find a volume label entry */
|
res = DIR_READ_LABEL(&dj); /* Find a volume label entry */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) {
|
if (fs->fs_type == FS_EXFAT) {
|
||||||
@@ -5293,7 +5319,7 @@ FRESULT f_setlabel (
|
|||||||
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_label(&dj); /* Get volume label entry */
|
res = DIR_READ_LABEL(&dj); /* Get volume label entry */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
||||||
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
|
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
|
||||||
@@ -5315,7 +5341,7 @@ FRESULT f_setlabel (
|
|||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
|
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
|
||||||
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
||||||
dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */
|
dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */
|
||||||
dj.dir[XDIR_NumLabel] = (BYTE)di;
|
dj.dir[XDIR_NumLabel] = (BYTE)di;
|
||||||
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
|
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
|
||||||
} else {
|
} else {
|
||||||
@@ -5620,7 +5646,7 @@ FRESULT f_mkfs (
|
|||||||
b_fat = b_vol + 32; /* FAT start at offset 32 */
|
b_fat = b_vol + 32; /* FAT start at offset 32 */
|
||||||
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
|
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
|
||||||
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
|
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
|
||||||
if (b_data >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
||||||
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
|
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
|
||||||
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */
|
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */
|
||||||
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
|
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
|
||||||
@@ -5701,11 +5727,11 @@ FRESULT f_mkfs (
|
|||||||
|
|
||||||
/* Initialize the root directory */
|
/* Initialize the root directory */
|
||||||
mem_set(buf, 0, szb_buf);
|
mem_set(buf, 0, szb_buf);
|
||||||
buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */
|
buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry */
|
||||||
buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */
|
buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */
|
||||||
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
|
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
|
||||||
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
|
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
|
||||||
buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */
|
buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */
|
||||||
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
|
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
|
||||||
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
|
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
|
||||||
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
|
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
|
||||||
@@ -6193,8 +6219,7 @@ typedef struct { /* Putchar output buffer and work area */
|
|||||||
} putbuff;
|
} putbuff;
|
||||||
|
|
||||||
|
|
||||||
static
|
static void putc_bfd ( /* Buffered write with code conversion */
|
||||||
void putc_bfd ( /* Buffered write with code conversion */
|
|
||||||
putbuff* pb,
|
putbuff* pb,
|
||||||
TCHAR c
|
TCHAR c
|
||||||
)
|
)
|
||||||
@@ -6305,7 +6330,7 @@ void putc_bfd ( /* Buffered write with code conversion */
|
|||||||
#else /* Write it in ANSI/OEM */
|
#else /* Write it in ANSI/OEM */
|
||||||
if (hs != 0) return;
|
if (hs != 0) return;
|
||||||
wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */
|
wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */
|
||||||
if (wc == 0) return;;
|
if (wc == 0) return;
|
||||||
if (wc >= 0x100) {
|
if (wc >= 0x100) {
|
||||||
pb->buf[i++] = (BYTE)(wc >> 8); nc++;
|
pb->buf[i++] = (BYTE)(wc >> 8); nc++;
|
||||||
}
|
}
|
||||||
@@ -6325,8 +6350,7 @@ void putc_bfd ( /* Buffered write with code conversion */
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static int putc_flush ( /* Flush left characters in the buffer */
|
||||||
int putc_flush ( /* Flush left characters in the buffer */
|
|
||||||
putbuff* pb
|
putbuff* pb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -6339,8 +6363,7 @@ int putc_flush ( /* Flush left characters in the buffer */
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static void putc_init ( /* Initialize write buffer */
|
||||||
void putc_init ( /* Initialize write buffer */
|
|
||||||
putbuff* pb,
|
putbuff* pb,
|
||||||
FIL* fp
|
FIL* fp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem module R0.13b /
|
/ FatFs - Generic FAT Filesystem module R0.13c /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
@@ -20,13 +20,12 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef FF_DEFINED
|
#ifndef FF_DEFINED
|
||||||
#define FF_DEFINED 63463 /* Revision ID */
|
#define FF_DEFINED 86604 /* Revision ID */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "integer.h" /* Basic integer types */
|
|
||||||
#include "ffconf.h" /* FatFs configuration options */
|
#include "ffconf.h" /* FatFs configuration options */
|
||||||
|
|
||||||
#if FF_DEFINED != FFCONF_DEF
|
#if FF_DEFINED != FFCONF_DEF
|
||||||
@@ -34,6 +33,30 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Integer types used for FatFs API */
|
||||||
|
|
||||||
|
#if defined(_WIN32) /* Main development platform */
|
||||||
|
#define FF_INTDEF 2
|
||||||
|
#include <windows.h>
|
||||||
|
typedef unsigned __int64 QWORD;
|
||||||
|
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
|
||||||
|
#define FF_INTDEF 2
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||||
|
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||||
|
typedef uint16_t WORD; /* 16-bit unsigned integer */
|
||||||
|
typedef uint16_t WCHAR; /* 16-bit unsigned integer */
|
||||||
|
typedef uint32_t DWORD; /* 32-bit unsigned integer */
|
||||||
|
typedef uint64_t QWORD; /* 64-bit unsigned integer */
|
||||||
|
#else /* Earlier than C99 */
|
||||||
|
#define FF_INTDEF 1
|
||||||
|
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||||
|
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||||
|
typedef unsigned short WORD; /* 16-bit unsigned integer */
|
||||||
|
typedef unsigned short WCHAR; /* 16-bit unsigned integer */
|
||||||
|
typedef unsigned long DWORD; /* 32-bit unsigned integer */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Definitions of volume management */
|
/* Definitions of volume management */
|
||||||
|
|
||||||
@@ -85,6 +108,9 @@ typedef char TCHAR;
|
|||||||
/* Type of file size variables */
|
/* Type of file size variables */
|
||||||
|
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
|
#if FF_INTDEF != 2
|
||||||
|
#error exFAT feature wants C99 or later
|
||||||
|
#endif
|
||||||
typedef QWORD FSIZE_t;
|
typedef QWORD FSIZE_t;
|
||||||
#else
|
#else
|
||||||
typedef DWORD FSIZE_t;
|
typedef DWORD FSIZE_t;
|
||||||
@@ -95,8 +121,8 @@ typedef DWORD FSIZE_t;
|
|||||||
/* Filesystem object structure (FATFS) */
|
/* Filesystem object structure (FATFS) */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE fs_type; /* Filesystem type (0:N/A) */
|
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||||
BYTE pdrv; /* Physical drive number */
|
BYTE pdrv; /* Associated physical drive */
|
||||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||||
@@ -133,6 +159,9 @@ typedef struct {
|
|||||||
DWORD fatbase; /* FAT base sector */
|
DWORD fatbase; /* FAT base sector */
|
||||||
DWORD dirbase; /* Root directory base sector/cluster */
|
DWORD dirbase; /* Root directory base sector/cluster */
|
||||||
DWORD database; /* Data base sector */
|
DWORD database; /* Data base sector */
|
||||||
|
#if FF_FS_EXFAT
|
||||||
|
DWORD bitbase; /* Allocation bitmap base sector */
|
||||||
|
#endif
|
||||||
DWORD winsect; /* Current sector appearing in the win[] */
|
DWORD winsect; /* Current sector appearing in the win[] */
|
||||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||||
} FATFS;
|
} FATFS;
|
||||||
@@ -145,7 +174,7 @@ typedef struct {
|
|||||||
FATFS* fs; /* Pointer to the hosting volume of this object */
|
FATFS* fs; /* Pointer to the hosting volume of this object */
|
||||||
WORD id; /* Hosting volume mount ID */
|
WORD id; /* Hosting volume mount ID */
|
||||||
BYTE attr; /* Object attribute */
|
BYTE attr; /* Object attribute */
|
||||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */
|
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||||
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
||||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
@@ -276,7 +305,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe
|
|||||||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
||||||
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||||
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||||
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
|
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */
|
||||||
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
||||||
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
|
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
|
||||||
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
|
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - Configuration file
|
/ FatFs Functional Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define FFCONF_DEF 63463 /* Revision ID */
|
#define FFCONF_DEF 86604 /* Revision ID */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ Function Configurations
|
/ Function Configurations
|
||||||
@@ -232,7 +232,7 @@
|
|||||||
|
|
||||||
#define FF_FS_EXFAT 1
|
#define FF_FS_EXFAT 1
|
||||||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
||||||
/ To enable exFAT, also LFN needs to be enabled.
|
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
|
||||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||||
|
|
||||||
|
|
||||||
@@ -262,6 +262,7 @@
|
|||||||
/ lock control is independent of re-entrancy. */
|
/ lock control is independent of re-entrancy. */
|
||||||
|
|
||||||
|
|
||||||
|
/* #include <somertos.h> // O/S definitions */
|
||||||
#define FF_FS_REENTRANT 0
|
#define FF_FS_REENTRANT 0
|
||||||
#define FF_FS_TIMEOUT 1000
|
#define FF_FS_TIMEOUT 1000
|
||||||
#define FF_SYNC_t HANDLE
|
#define FF_SYNC_t HANDLE
|
||||||
@@ -282,8 +283,6 @@
|
|||||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||||
/ included somewhere in the scope of ff.h. */
|
/ included somewhere in the scope of ff.h. */
|
||||||
|
|
||||||
/* #include <windows.h> // O/S definitions */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--- End of configuration options ---*/
|
/*--- End of configuration options ---*/
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Sample Code of OS Dependent Functions for FatFs */
|
/* Sample Code of OS Dependent Functions for FatFs */
|
||||||
/* (C)ChaN, 2017 */
|
/* (C)ChaN, 2018 */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Allocate a memory block */
|
/* Allocate a memory block */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */
|
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||||
UINT msize /* Number of bytes to allocate */
|
UINT msize /* Number of bytes to allocate */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -27,7 +26,7 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on no
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void ff_memfree (
|
void ff_memfree (
|
||||||
void* mblock /* Pointer to the memory block to free (nothing to do for null) */
|
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
free(mblock); /* Free the memory block with POSIX API */
|
free(mblock); /* Free the memory block with POSIX API */
|
||||||
@@ -47,7 +46,7 @@ void ff_memfree (
|
|||||||
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
|
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */
|
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
|
||||||
|
|
||||||
|
|
||||||
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
|
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
|
||||||
@@ -74,7 +73,7 @@ int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object
|
|||||||
// return (int)(*sobj != NULL);
|
// return (int)(*sobj != NULL);
|
||||||
|
|
||||||
/* CMSIS-RTOS */
|
/* CMSIS-RTOS */
|
||||||
// *sobj = osMutexCreate(Mutex + vol);
|
// *sobj = osMutexCreate(&Mutex[vol]);
|
||||||
// return (int)(*sobj != NULL);
|
// return (int)(*sobj != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Unicode handling functions for FatFs R0.13b */
|
/* Unicode handling functions for FatFs R0.13c */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* This module will occupy a huge memory in the .const section when the /
|
/* This module will occupy a huge memory in the .const section when the /
|
||||||
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
||||||
@@ -25,9 +25,9 @@
|
|||||||
|
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
#if FF_USE_LFN /* This module is blanked when non-LFN configuration */
|
#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */
|
||||||
|
|
||||||
#if FF_DEFINED != 63463 /* Revision ID */
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
/*-------------------------------------------*/
|
|
||||||
/* Integer type definitions for FatFs module */
|
|
||||||
/*-------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef FF_INTEGER
|
|
||||||
#define FF_INTEGER
|
|
||||||
|
|
||||||
#ifdef _WIN32 /* FatFs development platform */
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
typedef unsigned __int64 QWORD;
|
|
||||||
|
|
||||||
#else /* Embedded platform */
|
|
||||||
|
|
||||||
/* These types MUST be 16-bit or 32-bit */
|
|
||||||
typedef int INT;
|
|
||||||
typedef unsigned int UINT;
|
|
||||||
|
|
||||||
/* This type MUST be 8-bit */
|
|
||||||
typedef unsigned char BYTE;
|
|
||||||
|
|
||||||
/* These types MUST be 16-bit */
|
|
||||||
typedef short SHORT;
|
|
||||||
typedef unsigned short WORD;
|
|
||||||
typedef unsigned short WCHAR;
|
|
||||||
|
|
||||||
/* These types MUST be 32-bit */
|
|
||||||
typedef long LONG;
|
|
||||||
typedef unsigned long DWORD;
|
|
||||||
|
|
||||||
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
|
|
||||||
typedef unsigned long long QWORD;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -508,7 +508,7 @@ char *uuid_string(char *buf, char *end, const uint8_t *addr,
|
|||||||
if (uc) {
|
if (uc) {
|
||||||
p = uuid;
|
p = uuid;
|
||||||
do {
|
do {
|
||||||
*p = toupper(*p);
|
*p = toupper((unsigned char)*p);
|
||||||
} while (*(++p));
|
} while (*(++p));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1177,7 +1177,7 @@ do { \
|
|||||||
case FORMAT_TYPE_PTR:
|
case FORMAT_TYPE_PTR:
|
||||||
save_arg(void *);
|
save_arg(void *);
|
||||||
/* skip all alphanumeric pointer suffixes */
|
/* skip all alphanumeric pointer suffixes */
|
||||||
while (isalnum(*fmt))
|
while (isalnum((unsigned char)*fmt))
|
||||||
fmt++;
|
fmt++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1340,7 +1340,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const uint32_t *bin_buf
|
|||||||
|
|
||||||
case FORMAT_TYPE_PTR:
|
case FORMAT_TYPE_PTR:
|
||||||
str = pointer(fmt+1, str, end, get_arg(void *), spec);
|
str = pointer(fmt+1, str, end, get_arg(void *), spec);
|
||||||
while (isalnum(*fmt))
|
while (isalnum((unsigned char)*fmt))
|
||||||
fmt++;
|
fmt++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1577,10 +1577,10 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
|
|||||||
digit = *(str + 1);
|
digit = *(str + 1);
|
||||||
|
|
||||||
if (!digit
|
if (!digit
|
||||||
|| (base == 16 && !isxdigit(digit))
|
|| (base == 16 && !isxdigit((unsigned char)digit))
|
||||||
|| (base == 10 && !isdigit(digit))
|
|| (base == 10 && !isdigit((unsigned char)digit))
|
||||||
|| (base == 8 && (!isdigit(digit) || digit > '7'))
|
|| (base == 8 && (!isdigit((unsigned char)digit) || digit > '7'))
|
||||||
|| (base == 0 && !isdigit(digit)))
|
|| (base == 0 && !isdigit((unsigned char)digit)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (qualifier) {
|
switch (qualifier) {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ static char g_bct0_buffer[BCTO_MAX_SIZE];
|
|||||||
"BCT0\n"\
|
"BCT0\n"\
|
||||||
"[stage1]\n"\
|
"[stage1]\n"\
|
||||||
"stage2_path = atmosphere/fusee-secondary.bin\n"\
|
"stage2_path = atmosphere/fusee-secondary.bin\n"\
|
||||||
|
"stage2_mtc_path = atmosphere/fusee-mtc.bin\n"\
|
||||||
"stage2_addr = 0xF0000000\n"\
|
"stage2_addr = 0xF0000000\n"\
|
||||||
"stage2_entrypoint = 0xF0000000\n"
|
"stage2_entrypoint = 0xF0000000\n"
|
||||||
|
|
||||||
@@ -84,12 +85,9 @@ static int config_ini_handler(void *user, const char *section, const char *name,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_env(void) {
|
static void setup_display(void) {
|
||||||
g_framebuffer = (void *)0xC0000000;
|
g_framebuffer = (void *)0xC0000000;
|
||||||
|
|
||||||
/* Initialize hardware. */
|
|
||||||
nx_hwinit();
|
|
||||||
|
|
||||||
/* Zero-fill the framebuffer and register it as printk provider. */
|
/* Zero-fill the framebuffer and register it as printk provider. */
|
||||||
video_init(g_framebuffer);
|
video_init(g_framebuffer);
|
||||||
|
|
||||||
@@ -102,6 +100,19 @@ static void setup_env(void) {
|
|||||||
/* Turn on the backlight after initializing the lfb */
|
/* Turn on the backlight after initializing the lfb */
|
||||||
/* to avoid flickering. */
|
/* to avoid flickering. */
|
||||||
display_backlight(true);
|
display_backlight(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cleanup_display(void) {
|
||||||
|
/* Turn off the backlight. */
|
||||||
|
display_backlight(false);
|
||||||
|
|
||||||
|
/* Terminate the display. */
|
||||||
|
display_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_env(void) {
|
||||||
|
/* Initialize hardware. */
|
||||||
|
nx_hwinit();
|
||||||
|
|
||||||
/* Set up the exception handlers. */
|
/* Set up the exception handlers. */
|
||||||
setup_exception_handlers();
|
setup_exception_handlers();
|
||||||
@@ -113,9 +124,6 @@ static void setup_env(void) {
|
|||||||
static void cleanup_env(void) {
|
static void cleanup_env(void) {
|
||||||
/* Unmount the SD card. */
|
/* Unmount the SD card. */
|
||||||
unmount_sd();
|
unmount_sd();
|
||||||
|
|
||||||
display_backlight(false);
|
|
||||||
display_end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exit_callback(int rc) {
|
static void exit_callback(int rc) {
|
||||||
@@ -128,12 +136,9 @@ int main(void) {
|
|||||||
const char *stage2_path;
|
const char *stage2_path;
|
||||||
stage2_args_t *stage2_args;
|
stage2_args_t *stage2_args;
|
||||||
uint32_t stage2_version = 0;
|
uint32_t stage2_version = 0;
|
||||||
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY;
|
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_NONE;
|
||||||
|
|
||||||
/* Override the global logging level. */
|
/* Initialize the boot environment. */
|
||||||
log_set_log_level(log_level);
|
|
||||||
|
|
||||||
/* Initialize the display, console, etc. */
|
|
||||||
setup_env();
|
setup_env();
|
||||||
|
|
||||||
/* Check for panics. */
|
/* Check for panics. */
|
||||||
@@ -147,8 +152,16 @@ int main(void) {
|
|||||||
fatal_error("Failed to parse BCT.ini!\n");
|
fatal_error("Failed to parse BCT.ini!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Override the global logging level. */
|
||||||
|
log_set_log_level(log_level);
|
||||||
|
|
||||||
|
if (log_level != SCREEN_LOG_LEVEL_NONE) {
|
||||||
|
/* Initialize the display for debugging. */
|
||||||
|
setup_display();
|
||||||
|
}
|
||||||
|
|
||||||
/* Say hello. */
|
/* Say hello. */
|
||||||
print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
|
||||||
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer);
|
||||||
|
|
||||||
/* Load the loader payload into DRAM. */
|
/* Load the loader payload into DRAM. */
|
||||||
@@ -160,16 +173,20 @@ int main(void) {
|
|||||||
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
|
stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */
|
||||||
memcpy(&stage2_args->version, &stage2_version, 4);
|
memcpy(&stage2_args->version, &stage2_version, 4);
|
||||||
memcpy(&stage2_args->log_level, &log_level, sizeof(log_level));
|
memcpy(&stage2_args->log_level, &log_level, sizeof(log_level));
|
||||||
stage2_args->display_initialized = false;
|
|
||||||
strcpy(stage2_args->bct0, bct0);
|
strcpy(stage2_args->bct0, bct0);
|
||||||
g_chainloader_argc = 2;
|
g_chainloader_argc = 2;
|
||||||
|
|
||||||
/* Wait a while. */
|
/* Terminate the boot environment. */
|
||||||
mdelay(1000);
|
|
||||||
|
|
||||||
/* Deinitialize the display, console, etc. */
|
|
||||||
cleanup_env();
|
cleanup_env();
|
||||||
|
|
||||||
|
if (log_level != SCREEN_LOG_LEVEL_NONE) {
|
||||||
|
/* Wait a while for debugging. */
|
||||||
|
mdelay(1000);
|
||||||
|
|
||||||
|
/* Terminate the display for debugging. */
|
||||||
|
cleanup_display();
|
||||||
|
}
|
||||||
|
|
||||||
/* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, jump to Stage2. */
|
/* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, jump to Stage2. */
|
||||||
__program_exit_callback = exit_callback;
|
__program_exit_callback = exit_callback;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
|
#include "display/video_fb.h"
|
||||||
|
|
||||||
static uint32_t g_panic_code = 0;
|
static uint32_t g_panic_code = 0;
|
||||||
|
|
||||||
@@ -56,6 +57,22 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
/* Zero-fill the framebuffer and register it as printk provider. */
|
||||||
|
video_init((void *)0xC0000000);
|
||||||
|
|
||||||
|
/* Initialize the display. */
|
||||||
|
display_init();
|
||||||
|
|
||||||
|
/* Set the framebuffer. */
|
||||||
|
display_init_framebuffer((void *)0xC0000000);
|
||||||
|
|
||||||
|
/* Turn on the backlight after initializing the lfb */
|
||||||
|
/* to avoid flickering. */
|
||||||
|
display_backlight(true);
|
||||||
|
|
||||||
|
/* Override the global logging level. */
|
||||||
|
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
|
||||||
|
|
||||||
/* Copy fatal error context to the stack. */
|
/* Copy fatal error context to the stack. */
|
||||||
atmosphere_fatal_error_ctx ctx = *(ATMOSPHERE_FATAL_ERROR_CONTEXT);
|
atmosphere_fatal_error_ctx ctx = *(ATMOSPHERE_FATAL_ERROR_CONTEXT);
|
||||||
|
|
||||||
@@ -79,6 +96,7 @@ static void _check_and_display_atmosphere_fatal_error(void) {
|
|||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wait for button and reboot. */
|
||||||
wait_for_button_and_reboot();
|
wait_for_button_and_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,11 +105,9 @@ void check_and_display_panic(void) {
|
|||||||
_check_and_display_atmosphere_fatal_error();
|
_check_and_display_atmosphere_fatal_error();
|
||||||
|
|
||||||
/* We also handle our own panics. */
|
/* We also handle our own panics. */
|
||||||
/* In the case of our own panics, we assume that the display has already been initialized. */
|
bool has_panic = ((APBDEV_PMC_RST_STATUS_0 != 0) || (g_panic_code != 0));
|
||||||
bool has_panic = APBDEV_PMC_RST_STATUS_0 != 0 || g_panic_code != 0;
|
uint32_t code = (g_panic_code == 0) ? APBDEV_PMC_SCRATCH200_0 : g_panic_code;
|
||||||
uint32_t code = g_panic_code == 0 ? APBDEV_PMC_SCRATCH200_0 : g_panic_code;
|
has_panic = has_panic && !((APBDEV_PMC_RST_STATUS_0 != 1) && (code == PANIC_CODE_SAFEMODE));
|
||||||
|
|
||||||
has_panic = has_panic && !(APBDEV_PMC_RST_STATUS_0 != 1 && code == PANIC_CODE_SAFEMODE);
|
|
||||||
|
|
||||||
if (has_panic) {
|
if (has_panic) {
|
||||||
uint32_t color;
|
uint32_t color;
|
||||||
@@ -134,11 +150,13 @@ void check_and_display_panic(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_panic_code == 0) {
|
/* Initialize the display. */
|
||||||
display_init();
|
display_init();
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Fill the screen. */
|
||||||
display_color_screen(color);
|
display_color_screen(color);
|
||||||
|
|
||||||
|
/* Wait for button and reboot. */
|
||||||
wait_for_button_and_reboot();
|
wait_for_button_and_reboot();
|
||||||
} else {
|
} else {
|
||||||
g_panic_code = 0;
|
g_panic_code = 0;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#define PANIC_CODE_SAFEMODE 0x00000020
|
#define PANIC_CODE_SAFEMODE 0x00000020
|
||||||
|
|
||||||
|
|
||||||
#define AMS_FATAL_ERROR_MAX_STACKTRACE 0x20
|
#define AMS_FATAL_ERROR_MAX_STACKTRACE 0x20
|
||||||
#define AMS_FATAL_ERROR_MAX_STACKDUMP 0x100
|
#define AMS_FATAL_ERROR_MAX_STACKDUMP 0x100
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ static int stage2_ini_handler(void *user, const char *section, const char *name,
|
|||||||
if (strcmp(name, STAGE2_NAME_KEY) == 0) {
|
if (strcmp(name, STAGE2_NAME_KEY) == 0) {
|
||||||
strncpy(config->path, value, sizeof(config->path) - 1);
|
strncpy(config->path, value, sizeof(config->path) - 1);
|
||||||
config->path[sizeof(config->path) - 1] = '\0';
|
config->path[sizeof(config->path) - 1] = '\0';
|
||||||
|
} else if (strcmp(name, STAGE2_MTC_NAME_KEY) == 0) {
|
||||||
|
strncpy(config->mtc_path, value, sizeof(config->mtc_path) - 1);
|
||||||
|
config->mtc_path[sizeof(config->mtc_path) - 1] = '\0';
|
||||||
} else if (strcmp(name, STAGE2_ADDRESS_KEY) == 0) {
|
} else if (strcmp(name, STAGE2_ADDRESS_KEY) == 0) {
|
||||||
/* Read in load address as a hex string. */
|
/* Read in load address as a hex string. */
|
||||||
sscanf(value, "%x", &x);
|
sscanf(value, "%x", &x);
|
||||||
@@ -52,6 +55,42 @@ static int stage2_ini_handler(void *user, const char *section, const char *name,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool run_mtc(const char *mtc_path, uintptr_t mtc_address) {
|
||||||
|
FILINFO info;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
/* Check if the MTC binary is present. */
|
||||||
|
if (f_stat(mtc_path, &info) != FR_OK) {
|
||||||
|
print(SCREEN_LOG_LEVEL_WARNING, "Stage2's MTC binary not found!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (size_t)info.fsize;
|
||||||
|
|
||||||
|
/* Try to read the MTC binary. */
|
||||||
|
if (read_from_file((void *)mtc_address, size, mtc_path) != size) {
|
||||||
|
print(SCREEN_LOG_LEVEL_WARNING, "Failed to read stage2's MTC binary (%s)!\n", mtc_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenLogLevel mtc_log_level = log_get_log_level();
|
||||||
|
bool mtc_res = false;
|
||||||
|
int mtc_argc = 1;
|
||||||
|
char mtc_arg_data[CHAINLOADER_ARG_DATA_MAX_SIZE] = {0};
|
||||||
|
stage2_mtc_args_t *mtc_args = (stage2_mtc_args_t *)mtc_arg_data;
|
||||||
|
|
||||||
|
/* Setup argument data. */
|
||||||
|
memcpy(&mtc_args->log_level, &mtc_log_level, sizeof(mtc_log_level));
|
||||||
|
|
||||||
|
/* Run the MTC binary. */
|
||||||
|
mtc_res = (((int (*)(int, void *))mtc_address)(mtc_argc, mtc_arg_data) == 0);
|
||||||
|
|
||||||
|
/* Cleanup right away. */
|
||||||
|
memset((void *)mtc_address, 0, size);
|
||||||
|
|
||||||
|
return mtc_res;
|
||||||
|
}
|
||||||
|
|
||||||
void load_stage2(const char *bct0) {
|
void load_stage2(const char *bct0) {
|
||||||
stage2_config_t config = {0};
|
stage2_config_t config = {0};
|
||||||
FILINFO info;
|
FILINFO info;
|
||||||
@@ -80,9 +119,15 @@ void load_stage2(const char *bct0) {
|
|||||||
|
|
||||||
print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n");
|
print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n");
|
||||||
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path);
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path);
|
||||||
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " MTC File Path: %s\n", config.mtc_path);
|
||||||
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address);
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address);
|
||||||
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Entrypoint: 0x%p\n", config.entrypoint);
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Entrypoint: 0x%p\n", config.entrypoint);
|
||||||
|
|
||||||
|
/* Run the MTC binary. */
|
||||||
|
if (!run_mtc(config.mtc_path, config.load_address)) {
|
||||||
|
print(SCREEN_LOG_LEVEL_WARNING, "DRAM training failed! Continuing with untrained DRAM.\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (f_stat(config.path, &info) != FR_OK) {
|
if (f_stat(config.path, &info) != FR_OK) {
|
||||||
fatal_error("Failed to stat stage2 (%s)!\n", config.path);
|
fatal_error("Failed to stat stage2 (%s)!\n", config.path);
|
||||||
}
|
}
|
||||||
@@ -108,6 +153,7 @@ void load_stage2(const char *bct0) {
|
|||||||
tmp_addr = config.load_address;
|
tmp_addr = config.load_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to read stage2. */
|
||||||
if (read_from_file((void *)tmp_addr, size, config.path) != size) {
|
if (read_from_file((void *)tmp_addr, size, config.path) != size) {
|
||||||
fatal_error("Failed to read stage2 (%s)!\n", config.path);
|
fatal_error("Failed to read stage2 (%s)!\n", config.path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,15 @@
|
|||||||
#define STAGE2_ARGC 2
|
#define STAGE2_ARGC 2
|
||||||
|
|
||||||
#define STAGE2_NAME_KEY "stage2_path"
|
#define STAGE2_NAME_KEY "stage2_path"
|
||||||
|
#define STAGE2_MTC_NAME_KEY "stage2_mtc_path"
|
||||||
#define STAGE2_ADDRESS_KEY "stage2_addr"
|
#define STAGE2_ADDRESS_KEY "stage2_addr"
|
||||||
#define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint"
|
#define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint"
|
||||||
|
|
||||||
#define BCTO_MAX_SIZE 0x5800
|
#define BCTO_MAX_SIZE 0x5800
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char path[0x100];
|
char path[0x100];
|
||||||
|
char mtc_path[0x100];
|
||||||
uintptr_t load_address;
|
uintptr_t load_address;
|
||||||
uintptr_t entrypoint;
|
uintptr_t entrypoint;
|
||||||
} stage2_config_t;
|
} stage2_config_t;
|
||||||
@@ -45,10 +48,13 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
ScreenLogLevel log_level;
|
ScreenLogLevel log_level;
|
||||||
bool display_initialized;
|
|
||||||
char bct0[BCTO_MAX_SIZE];
|
char bct0[BCTO_MAX_SIZE];
|
||||||
} stage2_args_t;
|
} stage2_args_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ScreenLogLevel log_level;
|
||||||
|
} stage2_mtc_args_t;
|
||||||
|
|
||||||
const char *stage2_get_program_path(void);
|
const char *stage2_get_program_path(void);
|
||||||
void load_stage2(const char *bct0);
|
void load_stage2(const char *bct0);
|
||||||
|
|
||||||
|
|||||||
@@ -17,35 +17,98 @@
|
|||||||
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
#include "pinmux.h"
|
||||||
|
|
||||||
|
static inline void uart_wait_cycles(uint32_t baud, uint32_t num)
|
||||||
|
{
|
||||||
|
udelay((num * 1000000 + 16 * baud - 1) / (16 * baud));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uart_wait_syms(uint32_t baud, uint32_t num)
|
||||||
|
{
|
||||||
|
udelay((num * 1000000 + baud - 1) / baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_config(UartDevice dev) {
|
||||||
|
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||||
|
|
||||||
|
switch (dev) {
|
||||||
|
case UART_A:
|
||||||
|
pinmux->uart1_tx = 0;
|
||||||
|
pinmux->uart1_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
||||||
|
pinmux->uart1_rts = 0;
|
||||||
|
pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||||
|
break;
|
||||||
|
case UART_B:
|
||||||
|
pinmux->uart2_tx = 0;
|
||||||
|
pinmux->uart2_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
||||||
|
pinmux->uart2_rts = 0;
|
||||||
|
pinmux->uart2_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||||
|
break;
|
||||||
|
case UART_C:
|
||||||
|
pinmux->uart3_tx = 0;
|
||||||
|
pinmux->uart3_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
||||||
|
pinmux->uart3_rts = 0;
|
||||||
|
pinmux->uart3_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||||
|
break;
|
||||||
|
case UART_D:
|
||||||
|
pinmux->uart4_tx = 0;
|
||||||
|
pinmux->uart4_rx = (PINMUX_INPUT | PINMUX_PULL_UP);
|
||||||
|
pinmux->uart4_rts = 0;
|
||||||
|
pinmux->uart4_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||||
|
break;
|
||||||
|
case UART_E:
|
||||||
|
/* Unused. */
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void uart_init(UartDevice dev, uint32_t baud) {
|
void uart_init(UartDevice dev, uint32_t baud) {
|
||||||
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||||
|
|
||||||
/* Set baud rate. */
|
/* Wait for idle state. */
|
||||||
uint32_t rate = (8 * baud + 408000000) / (16 * baud);
|
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE);
|
||||||
uart->UART_LCR = UART_LCR_DLAB; /* Enable DLAB. */
|
|
||||||
uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */
|
|
||||||
uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */
|
|
||||||
uart->UART_LCR = 0; /* Diable DLAB. */
|
|
||||||
|
|
||||||
/* Setup UART in fifo mode. */
|
/* Calculate baud rate, round to nearest. */
|
||||||
|
uint32_t rate = (8 * baud + 408000000) / (16 * baud);
|
||||||
|
|
||||||
|
/* Setup UART in FIFO mode. */
|
||||||
uart->UART_IER_DLAB = 0;
|
uart->UART_IER_DLAB = 0;
|
||||||
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */
|
|
||||||
(void)uart->UART_LSR;
|
|
||||||
udelay(3 * ((baud + 999999) / baud));
|
|
||||||
uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */
|
|
||||||
uart->UART_MCR = 0;
|
uart->UART_MCR = 0;
|
||||||
uart->UART_MSR = 0;
|
uart->UART_LCR = (UART_LCR_DLAB | UART_LCR_WD_LENGTH_8); /* Enable DLAB and set word length 8. */
|
||||||
uart->UART_IRDA_CSR = 0;
|
uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */
|
||||||
uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */
|
uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */
|
||||||
uart->UART_MIE = 0;
|
uart->UART_LCR &= ~(UART_LCR_DLAB); /* Disable DLAB. */
|
||||||
uart->UART_ASR = 0;
|
uart->UART_SPR; /* Dummy read. */
|
||||||
|
uart_wait_syms(baud, 3); /* Wait for 3 symbols at the new baudrate. */
|
||||||
|
|
||||||
|
/* Enable FIFO with default settings. */
|
||||||
|
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO;
|
||||||
|
uart->UART_SPR; /* Dummy read as mandated by TRM. */
|
||||||
|
uart_wait_cycles(baud, 3); /* Wait for 3 baud cycles, as mandated by TRM (erratum). */
|
||||||
|
|
||||||
|
/* Flush FIFO. */
|
||||||
|
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE); /* Make sure there's no data being written in TX FIFO (TRM). */
|
||||||
|
uart->UART_IIR_FCR |= UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Clear TX and RX FIFOs. */
|
||||||
|
uart_wait_cycles(baud, 32); /* Wait for 32 baud cycles (TRM, erratum). */
|
||||||
|
/* Wait for idle state (TRM). */
|
||||||
|
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE | UART_VENDOR_STATE_RX_IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function blocks until the UART device (dev) is in the desired state (status). Make sure the desired state can be reached! */
|
/* This function blocks until the UART device is in the desired state. */
|
||||||
void uart_wait_idle(UartDevice dev, UartVendorStatus status) {
|
void uart_wait_idle(UartDevice dev, UartVendorStatus status) {
|
||||||
while (!(uart_get_regs(dev)->UART_VENDOR_STATUS & status)) {
|
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||||
/* Wait */
|
|
||||||
|
if (status & UART_VENDOR_STATE_TX_IDLE) {
|
||||||
|
while (!(uart->UART_LSR & UART_LSR_TMTY)) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (status & UART_VENDOR_STATE_RX_IDLE) {
|
||||||
|
while (uart->UART_LSR & UART_LSR_RDR) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +116,8 @@ void uart_send(UartDevice dev, const void *buf, size_t len) {
|
|||||||
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL) {
|
while (!(uart->UART_LSR & UART_LSR_THRE)) {
|
||||||
/* Wait until the TX FIFO isn't full */
|
/* Wait until it's possible to send data. */
|
||||||
}
|
}
|
||||||
uart->UART_THR_DLAB = *((const uint8_t *)buf + i);
|
uart->UART_THR_DLAB = *((const uint8_t *)buf + i);
|
||||||
}
|
}
|
||||||
@@ -64,8 +127,8 @@ void uart_recv(UartDevice dev, void *buf, size_t len) {
|
|||||||
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY) {
|
while (!(uart->UART_LSR & UART_LSR_RDR)) {
|
||||||
/* Wait until the RX FIFO isn't empty */
|
/* Wait until it's possible to receive data. */
|
||||||
}
|
}
|
||||||
*((uint8_t *)buf + i) = uart->UART_THR_DLAB;
|
*((uint8_t *)buf + i) = uart->UART_THR_DLAB;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ typedef struct {
|
|||||||
uint32_t UART_ASR;
|
uint32_t UART_ASR;
|
||||||
} tegra_uart_t;
|
} tegra_uart_t;
|
||||||
|
|
||||||
|
void uart_config(UartDevice dev);
|
||||||
void uart_init(UartDevice dev, uint32_t baud);
|
void uart_init(UartDevice dev, uint32_t baud);
|
||||||
void uart_wait_idle(UartDevice dev, UartVendorStatus status);
|
void uart_wait_idle(UartDevice dev, UartVendorStatus status);
|
||||||
void uart_send(UartDevice dev, const void *buf, size_t len);
|
void uart_send(UartDevice dev, const void *buf, size_t len);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "di.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "fuse.h"
|
#include "fuse.h"
|
||||||
#include "pmc.h"
|
#include "pmc.h"
|
||||||
@@ -24,8 +25,8 @@
|
|||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
#include "btn.h"
|
#include "btn.h"
|
||||||
|
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
|
#include "display/video_fb.h"
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
@@ -97,12 +98,34 @@ __attribute__ ((noreturn)) void generic_panic(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
|
||||||
|
/* Forcefully initialize the screen if logging is disabled. */
|
||||||
|
if (log_get_log_level() == SCREEN_LOG_LEVEL_NONE) {
|
||||||
|
/* Zero-fill the framebuffer and register it as printk provider. */
|
||||||
|
video_init((void *)0xC0000000);
|
||||||
|
|
||||||
|
/* Initialize the display. */
|
||||||
|
display_init();
|
||||||
|
|
||||||
|
/* Set the framebuffer. */
|
||||||
|
display_init_framebuffer((void *)0xC0000000);
|
||||||
|
|
||||||
|
/* Turn on the backlight after initializing the lfb */
|
||||||
|
/* to avoid flickering. */
|
||||||
|
display_backlight(true);
|
||||||
|
|
||||||
|
/* Override the global logging level. */
|
||||||
|
log_set_log_level(SCREEN_LOG_LEVEL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display fatal error. */
|
||||||
va_list args;
|
va_list args;
|
||||||
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
|
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n");
|
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n");
|
||||||
|
|
||||||
|
/* Wait for button and reboot. */
|
||||||
wait_for_button_and_reboot();
|
wait_for_button_and_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0x1A0;
|
case CARDEVICE_UARTC: return 0x1A0;
|
||||||
case CARDEVICE_I2C1: return 0x124;
|
case CARDEVICE_I2C1: return 0x124;
|
||||||
case CARDEVICE_I2C5: return 0x128;
|
case CARDEVICE_I2C5: return 0x128;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0x42C;
|
case CARDEVICE_SE: return 0x42C;
|
||||||
case CARDEVICE_HOST1X: return 0x180;
|
case CARDEVICE_HOST1X: return 0x180;
|
||||||
case CARDEVICE_TSEC: return 0x1F4;
|
case CARDEVICE_TSEC: return 0x1F4;
|
||||||
@@ -48,7 +48,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0;
|
case CARDEVICE_UARTC: return 0;
|
||||||
case CARDEVICE_I2C1: return 6;
|
case CARDEVICE_I2C1: return 6;
|
||||||
case CARDEVICE_I2C5: return 6;
|
case CARDEVICE_I2C5: return 6;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0;
|
case CARDEVICE_SE: return 0;
|
||||||
case CARDEVICE_HOST1X: return 4;
|
case CARDEVICE_HOST1X: return 4;
|
||||||
case CARDEVICE_TSEC: return 0;
|
case CARDEVICE_TSEC: return 0;
|
||||||
@@ -71,7 +71,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0;
|
case CARDEVICE_UARTC: return 0;
|
||||||
case CARDEVICE_I2C1: return 0;
|
case CARDEVICE_I2C1: return 0;
|
||||||
case CARDEVICE_I2C5: return 0;
|
case CARDEVICE_I2C5: return 0;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0;
|
case CARDEVICE_SE: return 0;
|
||||||
case CARDEVICE_HOST1X: return 3;
|
case CARDEVICE_HOST1X: return 3;
|
||||||
case CARDEVICE_TSEC: return 2;
|
case CARDEVICE_TSEC: return 2;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ typedef enum {
|
|||||||
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||||
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||||
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||||
CARDEVICE_UNK = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
|||||||
@@ -97,26 +97,23 @@ static ssize_t decode_utf8(uint32_t *out, const uint8_t *in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void console_init_display(void) {
|
static void console_init_display(void) {
|
||||||
if (!g_display_initialized) {
|
/* Initialize the display. */
|
||||||
/* Initialize the display. */
|
display_init();
|
||||||
display_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the framebuffer. */
|
/* Set the framebuffer. */
|
||||||
display_init_framebuffer(g_framebuffer);
|
display_init_framebuffer(g_framebuffer);
|
||||||
|
|
||||||
/* Turn on the backlight after initializing the lfb */
|
/* Turn on the backlight after initializing the lfb */
|
||||||
/* to avoid flickering. */
|
/* to avoid flickering. */
|
||||||
if (!g_display_initialized) {
|
display_backlight(true);
|
||||||
display_backlight(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Display is initialized. */
|
||||||
g_display_initialized = true;
|
g_display_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t console_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
static ssize_t console_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
if (!g_display_initialized) {
|
if (!g_display_initialized && (g_framebuffer != NULL)) {
|
||||||
console_init_display();
|
console_init_display();
|
||||||
}
|
}
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
@@ -138,6 +135,8 @@ static int console_create(void) {
|
|||||||
errno = EEXIST;
|
errno = EEXIST;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate memory for the framebuffer. */
|
||||||
g_framebuffer = memalign(0x1000, CONFIG_VIDEO_VISIBLE_ROWS * CONFIG_VIDEO_COLS * CONFIG_VIDEO_PIXEL_SIZE);
|
g_framebuffer = memalign(0x1000, CONFIG_VIDEO_VISIBLE_ROWS * CONFIG_VIDEO_COLS * CONFIG_VIDEO_PIXEL_SIZE);
|
||||||
|
|
||||||
if (g_framebuffer == NULL) {
|
if (g_framebuffer == NULL) {
|
||||||
@@ -154,9 +153,7 @@ static int console_create(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int console_init(bool display_initialized) {
|
int console_init(void) {
|
||||||
g_display_initialized = display_initialized;
|
|
||||||
|
|
||||||
if (console_create() == -1) {
|
if (console_create() == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -171,15 +168,15 @@ int console_init(bool display_initialized) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *console_get_framebuffer(bool enable_display) {
|
void *console_get_framebuffer(void) {
|
||||||
if (g_framebuffer != NULL && enable_display) {
|
if (!g_display_initialized && (g_framebuffer != NULL)) {
|
||||||
console_init_display();
|
console_init_display();
|
||||||
}
|
}
|
||||||
return g_framebuffer;
|
return g_framebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int console_display(const void *framebuffer) {
|
int console_display(const void *framebuffer) {
|
||||||
if (!g_display_initialized) {
|
if (!g_display_initialized && (g_framebuffer != NULL)) {
|
||||||
console_init_display();
|
console_init_display();
|
||||||
}
|
}
|
||||||
display_init_framebuffer((void *)framebuffer);
|
display_init_framebuffer((void *)framebuffer);
|
||||||
@@ -187,7 +184,7 @@ int console_display(const void *framebuffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int console_resume(void) {
|
int console_resume(void) {
|
||||||
if (!g_display_initialized) {
|
if (!g_display_initialized && (g_framebuffer != NULL)) {
|
||||||
console_init_display();
|
console_init_display();
|
||||||
} else {
|
} else {
|
||||||
display_init_framebuffer(g_framebuffer);
|
display_init_framebuffer(g_framebuffer);
|
||||||
@@ -196,10 +193,15 @@ int console_resume(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int console_end(void) {
|
int console_end(void) {
|
||||||
/* Deinitialize the framebuffer and display */
|
|
||||||
if (g_display_initialized) {
|
if (g_display_initialized) {
|
||||||
|
/* Turn off the backlight. */
|
||||||
display_backlight(false);
|
display_backlight(false);
|
||||||
|
|
||||||
|
/* Terminate the display. */
|
||||||
display_end();
|
display_end();
|
||||||
|
|
||||||
|
/* Display is terminated. */
|
||||||
|
g_display_initialized = false;
|
||||||
}
|
}
|
||||||
free(g_framebuffer);
|
free(g_framebuffer);
|
||||||
g_framebuffer = NULL;
|
g_framebuffer = NULL;
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
|
|
||||||
int console_init(bool display_initialized);
|
int console_init(void);
|
||||||
void *console_get_framebuffer(bool enable_display);
|
void *console_get_framebuffer(void);
|
||||||
int console_display(const void *framebuffer); /* Must be page-aligned */
|
int console_display(const void *framebuffer); /* Must be page-aligned */
|
||||||
int console_resume(void);
|
int console_resume(void);
|
||||||
int console_end(void);
|
int console_end(void);
|
||||||
|
|||||||
@@ -21,125 +21,66 @@
|
|||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
/**
|
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin) {
|
||||||
* Returns a GPIO bank object that corresponds to the given GPIO pin,
|
|
||||||
* which can be created using the TEGRA_GPIO macro or passed from the name macro.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO to get the bank for.
|
|
||||||
* @return The GPIO bank object to use for working with the given bank.
|
|
||||||
*/
|
|
||||||
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin)
|
|
||||||
{
|
|
||||||
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
||||||
uint32_t bank_number = pin >> GPIO_BANK_SHIFT;
|
uint32_t bank_number = (pin >> GPIO_BANK_SHIFT);
|
||||||
|
|
||||||
return &gpio->bank[bank_number];
|
return &gpio->bank[bank_number];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static volatile uint32_t gpio_get_port(uint32_t pin) {
|
||||||
* @return the port number for working with the given GPIO.
|
return ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
|
||||||
*/
|
|
||||||
static volatile uint32_t gpio_get_port(uint32_t pin)
|
|
||||||
{
|
|
||||||
return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static volatile uint32_t gpio_get_mask(uint32_t pin) {
|
||||||
* @return a mask to be used to work with the given GPIO
|
uint32_t pin_number = (pin & GPIO_PIN_MASK);
|
||||||
*/
|
|
||||||
static volatile uint32_t gpio_get_mask(uint32_t pin)
|
|
||||||
{
|
|
||||||
uint32_t pin_number = pin & GPIO_PIN_MASK;
|
|
||||||
return (1 << pin_number);
|
return (1 << pin_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset) {
|
||||||
* Performs a simple GPIO configuration operation.
|
/* Retrieve the register set that corresponds to the given pin and offset. */
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
|
||||||
* @param offset The offset into a gpio_bank structure
|
|
||||||
*/
|
|
||||||
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset)
|
|
||||||
{
|
|
||||||
// Retrieve the register set that corresponds to the given pin and offset.
|
|
||||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||||
uint32_t *cluster = (uint32_t *)cluster_addr;
|
uint32_t *cluster = (uint32_t *)cluster_addr;
|
||||||
|
|
||||||
// Figure out the offset into the cluster,
|
/* Figure out the offset into the cluster, and the mask to be used. */
|
||||||
// and the mask to be used.
|
|
||||||
uint32_t port = gpio_get_port(pin);
|
uint32_t port = gpio_get_port(pin);
|
||||||
uint32_t mask = gpio_get_mask(pin);
|
uint32_t mask = gpio_get_mask(pin);
|
||||||
|
|
||||||
// Set or clear the bit, as appropriate.
|
/* Set or clear the bit, as appropriate. */
|
||||||
if (should_be_set)
|
if (should_be_set)
|
||||||
cluster[port] |= mask;
|
cluster[port] |= mask;
|
||||||
else
|
else
|
||||||
cluster[port] &= ~mask;
|
cluster[port] &= ~mask;
|
||||||
|
|
||||||
|
/* Dummy read. */
|
||||||
|
(void)cluster[port];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset) {
|
||||||
* Performs a simple GPIO configuration operation.
|
/* Retrieve the register set that corresponds to the given pin and offset. */
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
|
||||||
* @param offset The offset into a gpio_bank structure
|
|
||||||
*/
|
|
||||||
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset)
|
|
||||||
{
|
|
||||||
// Retrieve the register set that corresponds to the given pin and offset.
|
|
||||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||||
uint32_t *cluster = (uint32_t *)cluster_addr;
|
uint32_t *cluster = (uint32_t *)cluster_addr;
|
||||||
|
|
||||||
// Figure out the offset into the cluster,
|
/* Figure out the offset into the cluster, and the mask to be used. */
|
||||||
// and the mask to be used.
|
|
||||||
uint32_t port = gpio_get_port(pin);
|
uint32_t port = gpio_get_port(pin);
|
||||||
uint32_t mask = gpio_get_mask(pin);
|
uint32_t mask = gpio_get_mask(pin);
|
||||||
|
|
||||||
// Convert the given value to a boolean.
|
/* Convert the given value to a boolean. */
|
||||||
return !!(cluster[port] & mask);
|
return !!(cluster[port] & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_configure_mode(uint32_t pin, uint32_t mode) {
|
||||||
* Configures a given pin as either GPIO or SFIO.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
void gpio_configure_mode(uint32_t pin, uint32_t mode)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_configure_direction(uint32_t pin, uint32_t dir) {
|
||||||
* Configures a given pin as either INPUT or OUPUT.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param direction The relevant direction.
|
|
||||||
*/
|
|
||||||
void gpio_configure_direction(uint32_t pin, uint32_t dir)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_write(uint32_t pin, uint32_t value) {
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
void gpio_write(uint32_t pin, uint32_t value)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
uint32_t gpio_read(uint32_t pin) {
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
uint32_t gpio_read(uint32_t pin)
|
|
||||||
{
|
|
||||||
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ static inline volatile tegra_gpio_t *gpio_get_regs(void)
|
|||||||
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
||||||
|
|
||||||
/* Mode select */
|
/* Mode select */
|
||||||
#define GPIO_MODE_GPIO 0
|
#define GPIO_MODE_SFIO 0
|
||||||
#define GPIO_MODE_SFIO 1
|
#define GPIO_MODE_GPIO 1
|
||||||
|
|
||||||
/* Direction */
|
/* Direction */
|
||||||
#define GPIO_DIRECTION_INPUT 0
|
#define GPIO_DIRECTION_INPUT 0
|
||||||
|
|||||||
@@ -17,19 +17,52 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
#include "pinmux.h"
|
||||||
|
|
||||||
/* Prototypes for internal commands. */
|
/* Prototypes for internal commands. */
|
||||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id);
|
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id);
|
||||||
void i2c_load_config(volatile tegra_i2c_t *regs);
|
void i2c_load_config(volatile tegra_i2c_t *regs);
|
||||||
|
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||||
|
|
||||||
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
|
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
|
||||||
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
|
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
|
||||||
|
|
||||||
|
/* Configure I2C pinmux. */
|
||||||
|
void i2c_config(I2CDevice id) {
|
||||||
|
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case I2C_1:
|
||||||
|
pinmux->gen1_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen1_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_2:
|
||||||
|
pinmux->gen2_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen2_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_3:
|
||||||
|
pinmux->gen3_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen3_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_4:
|
||||||
|
pinmux->cam_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->cam_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_5:
|
||||||
|
pinmux->pwr_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->pwr_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_6:
|
||||||
|
/* Unused. */
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize I2C based on registers. */
|
/* Initialize I2C based on registers. */
|
||||||
void i2c_init(unsigned int id) {
|
void i2c_init(I2CDevice id) {
|
||||||
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||||
|
|
||||||
/* Setup divisor, and clear the bus. */
|
/* Setup divisor, and clear the bus. */
|
||||||
@@ -91,7 +124,7 @@ void i2c_set_ti_charger_bit_7(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get registers pointer based on I2C ID. */
|
/* Get registers pointer based on I2C ID. */
|
||||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) {
|
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case I2C_1:
|
case I2C_1:
|
||||||
return I2C1_REGS;
|
return I2C1_REGS;
|
||||||
@@ -126,7 +159,7 @@ void i2c_load_config(volatile tegra_i2c_t *regs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reads a register from a device over I2C, writes result to output. */
|
/* Reads a register from a device over I2C, writes result to output. */
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
||||||
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||||
uint32_t val = r;
|
uint32_t val = r;
|
||||||
|
|
||||||
@@ -143,7 +176,7 @@ bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Writes a value to a register over I2C. */
|
/* Writes a value to a register over I2C. */
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
||||||
uint32_t val = r;
|
uint32_t val = r;
|
||||||
if (src_size == 0) {
|
if (src_size == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -24,13 +24,6 @@
|
|||||||
#define I2C1234_BASE 0x7000C000
|
#define I2C1234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
#define I2C_1 0
|
|
||||||
#define I2C_2 1
|
|
||||||
#define I2C_3 2
|
|
||||||
#define I2C_4 3
|
|
||||||
#define I2C_5 4
|
|
||||||
#define I2C_6 5
|
|
||||||
|
|
||||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
#define MAX17050_I2C_ADDR 0x36
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
@@ -38,6 +31,15 @@
|
|||||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
#define BQ24193_I2C_ADDR 0x6B
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I2C_1 = 0,
|
||||||
|
I2C_2 = 1,
|
||||||
|
I2C_3 = 2,
|
||||||
|
I2C_4 = 3,
|
||||||
|
I2C_5 = 4,
|
||||||
|
I2C_6 = 5,
|
||||||
|
} I2CDevice;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t I2C_I2C_CNFG_0;
|
uint32_t I2C_I2C_CNFG_0;
|
||||||
uint32_t I2C_I2C_CMD_ADDR0_0;
|
uint32_t I2C_I2C_CMD_ADDR0_0;
|
||||||
@@ -89,9 +91,11 @@ typedef struct {
|
|||||||
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
||||||
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
||||||
|
|
||||||
void i2c_init(unsigned int id);
|
void i2c_config(I2CDevice id);
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
void i2c_init(I2CDevice id);
|
||||||
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||||
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||||
|
|
||||||
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
||||||
bool i2c_query_ti_charger_bit_7(void);
|
bool i2c_query_ti_charger_bit_7(void);
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ static inline uint8_t hex_nybble_to_u8(const char nybble) {
|
|||||||
static bool name_matches_hash(const char *name, size_t name_len, const void *hash, size_t hash_size) {
|
static bool name_matches_hash(const char *name, size_t name_len, const void *hash, size_t hash_size) {
|
||||||
/* Validate name is hex build id. */
|
/* Validate name is hex build id. */
|
||||||
for (unsigned int i = 0; i < name_len - 4; i++) {
|
for (unsigned int i = 0; i < name_len - 4; i++) {
|
||||||
if (isxdigit(name[i]) == 0) {
|
if (isxdigit((unsigned char)name[i]) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -322,3 +322,9 @@ R0.13b (April 07, 2018)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.13c (October 14, 2018)
|
||||||
|
Supported stdint.h for C99 and later. (integer.h was included in ff.h)
|
||||||
|
Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12)
|
||||||
|
Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12)
|
||||||
|
Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FatFs Module Source Files R0.13b
|
FatFs Module Source Files R0.13c
|
||||||
|
|
||||||
|
|
||||||
FILES
|
FILES
|
||||||
@@ -10,7 +10,6 @@ FILES
|
|||||||
ff.h Common include file for FatFs and application module.
|
ff.h Common include file for FatFs and application module.
|
||||||
diskio.h Common include file for FatFs and disk I/O module.
|
diskio.h Common include file for FatFs and disk I/O module.
|
||||||
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
||||||
integer.h Integer type definitions for FatFs.
|
|
||||||
ffunicode.c Optional Unicode utility functions.
|
ffunicode.c Optional Unicode utility functions.
|
||||||
ffsystem.c An example of optional O/S related functions.
|
ffsystem.c An example of optional O/S related functions.
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "diskio.h" /* FatFs lower layer API */
|
#include "ff.h" /* Obtains integer types */
|
||||||
|
#include "diskio.h" /* Declarations of disk functions */
|
||||||
#include "ffconf.h"
|
#include "ffconf.h"
|
||||||
#include "../../device_partition.h"
|
#include "../../device_partition.h"
|
||||||
|
|
||||||
@@ -21,10 +22,10 @@ extern device_partition_t *g_volume_to_devparts[FF_VOLUMES];
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DSTATUS disk_status (
|
DSTATUS disk_status (
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
if (devpart)
|
if (devpart)
|
||||||
return devpart->initialized ? RES_OK : STA_NOINIT;
|
return devpart->initialized ? RES_OK : STA_NOINIT;
|
||||||
else
|
else
|
||||||
@@ -38,17 +39,17 @@ DSTATUS disk_status (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DSTATUS disk_initialize (
|
DSTATUS disk_initialize (
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
if (!devpart)
|
if (!devpart)
|
||||||
return STA_NODISK;
|
return STA_NODISK;
|
||||||
else if (devpart->initializer)
|
else if (devpart->initializer)
|
||||||
return devpart->initializer(devpart) ? STA_NOINIT : RES_OK;
|
return devpart->initializer(devpart) ? STA_NOINIT : RES_OK;
|
||||||
else
|
else
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -58,20 +59,20 @@ DSTATUS disk_initialize (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DRESULT disk_read (
|
DRESULT disk_read (
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
BYTE *buff, /* Data buffer to store read data */
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
DWORD sector, /* Start sector in LBA */
|
DWORD sector, /* Start sector in LBA */
|
||||||
UINT count /* Number of sectors to read */
|
UINT count /* Number of sectors to read */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
if (!devpart)
|
if (!devpart)
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
else if (devpart->reader)
|
else if (devpart->reader)
|
||||||
return device_partition_read_data(devpart, buff, sector, count) ? RES_ERROR : RES_OK;
|
return device_partition_read_data(devpart, buff, sector, count) ? RES_ERROR : RES_OK;
|
||||||
else
|
else
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,23 +81,26 @@ DRESULT disk_read (
|
|||||||
/* Write Sector(s) */
|
/* Write Sector(s) */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if FF_FS_READONLY == 0
|
||||||
|
|
||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
const BYTE *buff, /* Data to be written */
|
const BYTE *buff, /* Data to be written */
|
||||||
DWORD sector, /* Start sector in LBA */
|
DWORD sector, /* Start sector in LBA */
|
||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
/* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
if (!devpart)
|
if (!devpart)
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
else if (devpart->writer)
|
else if (devpart->writer)
|
||||||
return device_partition_write_data(devpart, buff, sector, count) ? RES_ERROR : RES_OK;
|
return device_partition_write_data(devpart, buff, sector, count) ? RES_ERROR : RES_OK;
|
||||||
else
|
else
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
@@ -104,18 +108,18 @@ DRESULT disk_write (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DRESULT disk_ioctl (
|
DRESULT disk_ioctl (
|
||||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||||
BYTE cmd, /* Control code */
|
BYTE cmd, /* Control code */
|
||||||
void *buff /* Buffer to send/receive control data */
|
void *buff /* Buffer to send/receive control data */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
device_partition_t *devpart = g_volume_to_devparts[pdrv];
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case GET_SECTOR_SIZE:
|
case GET_SECTOR_SIZE:
|
||||||
*(WORD *)buff = devpart ? (WORD)devpart->sector_size : 512;
|
*(WORD *)buff = devpart ? (WORD)devpart->sector_size : 512;
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
default:
|
default:
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "integer.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Status of Disk Functions */
|
/* Status of Disk Functions */
|
||||||
typedef BYTE DSTATUS;
|
typedef BYTE DSTATUS;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem Module R0.13b /
|
/ FatFs - Generic FAT Filesystem Module R0.13c /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
/ by use of this software.
|
/ by use of this software.
|
||||||
/
|
/
|
||||||
/----------------------------------------------------------------------------*/
|
/----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
#pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
|
#pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
|
||||||
@@ -32,11 +31,20 @@
|
|||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if FF_DEFINED != 63463 /* Revision ID */
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Limits and boundaries */
|
||||||
|
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
||||||
|
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
||||||
|
#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
||||||
|
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
||||||
|
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
||||||
|
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
||||||
|
|
||||||
|
|
||||||
/* Character code support macros */
|
/* Character code support macros */
|
||||||
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
||||||
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
|
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
|
||||||
@@ -46,18 +54,18 @@
|
|||||||
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
|
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
|
||||||
|
|
||||||
|
|
||||||
/* Additional file attribute bits for internal use */
|
|
||||||
#define AM_VOL 0x08 /* Volume label */
|
|
||||||
#define AM_LFN 0x0F /* LFN entry */
|
|
||||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
|
||||||
|
|
||||||
|
|
||||||
/* Additional file access control and file status flags for internal use */
|
/* Additional file access control and file status flags for internal use */
|
||||||
#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */
|
#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */
|
||||||
#define FA_MODIFIED 0x40 /* File has been modified */
|
#define FA_MODIFIED 0x40 /* File has been modified */
|
||||||
#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
|
#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
|
||||||
|
|
||||||
|
|
||||||
|
/* Additional file attribute bits for internal use */
|
||||||
|
#define AM_VOL 0x08 /* Volume label */
|
||||||
|
#define AM_LFN 0x0F /* LFN entry */
|
||||||
|
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||||
|
|
||||||
|
|
||||||
/* Name status flags in fn[11] */
|
/* Name status flags in fn[11] */
|
||||||
#define NSFLAG 11 /* Index of the name status byte */
|
#define NSFLAG 11 /* Index of the name status byte */
|
||||||
#define NS_LOSS 0x01 /* Out of 8.3 format */
|
#define NS_LOSS 0x01 /* Out of 8.3 format */
|
||||||
@@ -70,13 +78,13 @@
|
|||||||
#define NS_NONAME 0x80 /* Not followed */
|
#define NS_NONAME 0x80 /* Not followed */
|
||||||
|
|
||||||
|
|
||||||
/* Limits and boundaries */
|
/* exFAT directory entry types */
|
||||||
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
#define ET_BITMAP 0x81 /* Allocation bitmap */
|
||||||
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
#define ET_UPCASE 0x82 /* Up-case table */
|
||||||
#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
#define ET_VLABEL 0x83 /* Volume label */
|
||||||
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
#define ET_FILEDIR 0x85 /* File and directory */
|
||||||
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
#define ET_STREAM 0xC0 /* Stream extension */
|
||||||
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
#define ET_FILENAME 0xC1 /* Name extension */
|
||||||
|
|
||||||
|
|
||||||
/* FatFs refers the FAT structure as simple byte array instead of structure member
|
/* FatFs refers the FAT structure as simple byte array instead of structure member
|
||||||
@@ -524,6 +532,7 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */
|
|||||||
#define CODEPAGE CodePage
|
#define CODEPAGE CodePage
|
||||||
static WORD CodePage; /* Current code page */
|
static WORD CodePage; /* Current code page */
|
||||||
static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */
|
static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */
|
||||||
|
|
||||||
static const BYTE Ct437[] = TBL_CT437;
|
static const BYTE Ct437[] = TBL_CT437;
|
||||||
static const BYTE Ct720[] = TBL_CT720;
|
static const BYTE Ct720[] = TBL_CT720;
|
||||||
static const BYTE Ct737[] = TBL_CT737;
|
static const BYTE Ct737[] = TBL_CT737;
|
||||||
@@ -1096,7 +1105,7 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */
|
|||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
|
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
|
||||||
/* Create FSInfo structure */
|
/* Create FSInfo structure */
|
||||||
mem_set(fs->win, 0, SS(fs));
|
mem_set(fs->win, 0, sizeof fs->win);
|
||||||
st_word(fs->win + BS_55AA, 0xAA55);
|
st_word(fs->win + BS_55AA, 0xAA55);
|
||||||
st_dword(fs->win + FSI_LeadSig, 0x41615252);
|
st_dword(fs->win + FSI_LeadSig, 0x41615252);
|
||||||
st_dword(fs->win + FSI_StrucSig, 0x61417272);
|
st_dword(fs->win + FSI_StrucSig, 0x61417272);
|
||||||
@@ -1296,7 +1305,7 @@ static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:D
|
|||||||
if (clst >= fs->n_fatent - 2) clst = 0;
|
if (clst >= fs->n_fatent - 2) clst = 0;
|
||||||
scl = val = clst; ctr = 0;
|
scl = val = clst; ctr = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */
|
if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF;
|
||||||
i = val / 8 % SS(fs); bm = 1 << (val % 8);
|
i = val / 8 % SS(fs); bm = 1 << (val % 8);
|
||||||
do {
|
do {
|
||||||
do {
|
do {
|
||||||
@@ -1334,9 +1343,9 @@ static FRESULT change_bitmap (
|
|||||||
|
|
||||||
|
|
||||||
clst -= 2; /* The first bit corresponds to cluster #2 */
|
clst -= 2; /* The first bit corresponds to cluster #2 */
|
||||||
sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */
|
sect = fs->bitbase + clst / 8 / SS(fs); /* Sector address */
|
||||||
i = clst / 8 % SS(fs); /* Byte offset in the sector */
|
i = clst / 8 % SS(fs); /* Byte offset in the sector */
|
||||||
bm = 1 << (clst % 8); /* Bit mask in the byte */
|
bm = 1 << (clst % 8); /* Bit mask in the byte */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR;
|
if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR;
|
||||||
do {
|
do {
|
||||||
@@ -1409,7 +1418,7 @@ static FRESULT fill_last_frag (
|
|||||||
static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
FFOBJID* obj, /* Corresponding object */
|
FFOBJID* obj, /* Corresponding object */
|
||||||
DWORD clst, /* Cluster to remove a chain from */
|
DWORD clst, /* Cluster to remove a chain from */
|
||||||
DWORD pclst /* Previous cluster of clst (0:entire chain) */
|
DWORD pclst /* Previous cluster of clst (0 if entire chain) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
FRESULT res = FR_OK;
|
FRESULT res = FR_OK;
|
||||||
@@ -1647,7 +1656,7 @@ static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */
|
|||||||
if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */
|
if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */
|
||||||
sect = clst2sect(fs, clst); /* Top of the cluster */
|
sect = clst2sect(fs, clst); /* Top of the cluster */
|
||||||
fs->winsect = sect; /* Set window to top of the cluster */
|
fs->winsect = sect; /* Set window to top of the cluster */
|
||||||
mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */
|
mem_set(fs->win, 0, sizeof fs->win); /* Clear window buffer */
|
||||||
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
|
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
|
||||||
/* Allocate a temporary buffer */
|
/* Allocate a temporary buffer */
|
||||||
for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
|
for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
|
||||||
@@ -1731,7 +1740,8 @@ static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DEN
|
|||||||
|
|
||||||
|
|
||||||
ofs = dp->dptr + SZDIRE; /* Next entry */
|
ofs = dp->dptr + SZDIRE; /* Next entry */
|
||||||
if (dp->sect == 0 || ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) return FR_NO_FILE; /* Report EOT when offset has reached max value */
|
if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0; /* Disable it if the offset reached the max value */
|
||||||
|
if (dp->sect == 0) return FR_NO_FILE; /* Report EOT if it has been disabled */
|
||||||
|
|
||||||
if (ofs % SS(fs) == 0) { /* Sector changed? */
|
if (ofs % SS(fs) == 0) { /* Sector changed? */
|
||||||
dp->sect++; /* Next sector */
|
dp->sect++; /* Next sector */
|
||||||
@@ -1876,7 +1886,7 @@ static int cmp_lfn ( /* 1:matched, 0:not matched */
|
|||||||
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
if (i >= FF_MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */
|
if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */
|
||||||
return 0; /* Not matched */
|
return 0; /* Not matched */
|
||||||
}
|
}
|
||||||
wc = uc;
|
wc = uc;
|
||||||
@@ -1912,15 +1922,15 @@ static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */
|
|||||||
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i++] = wc = uc; /* Store it */
|
lfnbuf[i++] = wc = uc; /* Store it */
|
||||||
} else {
|
} else {
|
||||||
if (uc != 0xFFFF) return 0; /* Check filler */
|
if (uc != 0xFFFF) return 0; /* Check filler */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */
|
if (dir[LDIR_Ord] & LLEF && wc != 0) { /* Put terminator if it is the last LFN part and not terminated */
|
||||||
if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i] = 0;
|
lfnbuf[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2156,33 +2166,33 @@ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */
|
|||||||
BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
|
BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
|
||||||
|
|
||||||
|
|
||||||
/* Load 85 entry */
|
/* Load file-directory entry */
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */
|
||||||
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
|
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
|
||||||
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
|
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
|
||||||
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
|
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
|
||||||
|
|
||||||
/* Load C0 entry */
|
/* Load stream-extension entry */
|
||||||
res = dir_next(dp, 0);
|
res = dir_next(dp, 0);
|
||||||
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */
|
||||||
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
|
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
|
||||||
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
|
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
|
||||||
|
|
||||||
/* Load C1 entries */
|
/* Load file-name entries */
|
||||||
i = 2 * SZDIRE; /* C1 offset to load */
|
i = 2 * SZDIRE; /* Name offset to load */
|
||||||
do {
|
do {
|
||||||
res = dir_next(dp, 0);
|
res = dir_next(dp, 0);
|
||||||
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR; /* Invalid order */
|
||||||
if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
|
if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
|
||||||
} while ((i += SZDIRE) < sz_ent);
|
} while ((i += SZDIRE) < sz_ent);
|
||||||
|
|
||||||
@@ -2287,16 +2297,16 @@ static void create_xdir (
|
|||||||
WCHAR wc;
|
WCHAR wc;
|
||||||
|
|
||||||
|
|
||||||
/* Create 85,C0 entry */
|
/* Create file-directory and stream-extension entry */
|
||||||
mem_set(dirb, 0, 2 * SZDIRE);
|
mem_set(dirb, 0, 2 * SZDIRE);
|
||||||
dirb[0 * SZDIRE + XDIR_Type] = 0x85; /* 85 entry */
|
dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR;
|
||||||
dirb[1 * SZDIRE + XDIR_Type] = 0xC0; /* C0 entry */
|
dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM;
|
||||||
|
|
||||||
/* Create C1 entries */
|
/* Create file-name entries */
|
||||||
i = SZDIRE * 2; /* Top of C1 entries */
|
i = SZDIRE * 2; /* Top of file_name entries */
|
||||||
nlen = nc1 = 0; wc = 1;
|
nlen = nc1 = 0; wc = 1;
|
||||||
do {
|
do {
|
||||||
dirb[i++] = 0xC1; dirb[i++] = 0; /* Entry type C1 */
|
dirb[i++] = ET_FILENAME; dirb[i++] = 0;
|
||||||
do { /* Fill name field */
|
do { /* Fill name field */
|
||||||
if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */
|
if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */
|
||||||
st_word(dirb + i, wc); /* Store it */
|
st_word(dirb + i, wc); /* Store it */
|
||||||
@@ -2320,8 +2330,8 @@ static void create_xdir (
|
|||||||
/* Read an object from the directory */
|
/* Read an object from the directory */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define dir_read_file(dp) dir_read(dp, 0)
|
#define DIR_READ_FILE(dp) dir_read(dp, 0)
|
||||||
#define dir_read_label(dp) dir_read(dp, 1)
|
#define DIR_READ_LABEL(dp) dir_read(dp, 1)
|
||||||
|
|
||||||
static FRESULT dir_read (
|
static FRESULT dir_read (
|
||||||
DIR* dp, /* Pointer to the directory object */
|
DIR* dp, /* Pointer to the directory object */
|
||||||
@@ -2330,7 +2340,7 @@ static FRESULT dir_read (
|
|||||||
{
|
{
|
||||||
FRESULT res = FR_NO_FILE;
|
FRESULT res = FR_NO_FILE;
|
||||||
FATFS *fs = dp->obj.fs;
|
FATFS *fs = dp->obj.fs;
|
||||||
BYTE a, c;
|
BYTE attr, b;
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
BYTE ord = 0xFF, sum = 0xFF;
|
BYTE ord = 0xFF, sum = 0xFF;
|
||||||
#endif
|
#endif
|
||||||
@@ -2338,16 +2348,16 @@ static FRESULT dir_read (
|
|||||||
while (dp->sect) {
|
while (dp->sect) {
|
||||||
res = move_window(fs, dp->sect);
|
res = move_window(fs, dp->sect);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
c = dp->dir[DIR_Name]; /* Test for the entry type */
|
b = dp->dir[DIR_Name]; /* Test for the entry type */
|
||||||
if (c == 0) {
|
if (b == 0) {
|
||||||
res = FR_NO_FILE; break; /* Reached to end of the directory */
|
res = FR_NO_FILE; break; /* Reached to end of the directory */
|
||||||
}
|
}
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
||||||
if (FF_USE_LABEL && vol) {
|
if (FF_USE_LABEL && vol) {
|
||||||
if (c == 0x83) break; /* Volume label entry? */
|
if (b == ET_VLABEL) break; /* Volume label entry? */
|
||||||
} else {
|
} else {
|
||||||
if (c == 0x85) { /* Start of the file entry block? */
|
if (b == ET_FILEDIR) { /* Start of the file entry block? */
|
||||||
dp->blk_ofs = dp->dptr; /* Get location of the block */
|
dp->blk_ofs = dp->dptr; /* Get location of the block */
|
||||||
res = load_xdir(dp); /* Load the entry block */
|
res = load_xdir(dp); /* Load the entry block */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
@@ -2359,19 +2369,19 @@ static FRESULT dir_read (
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{ /* On the FAT/FAT32 volume */
|
{ /* On the FAT/FAT32 volume */
|
||||||
dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
|
dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
|
||||||
#if FF_USE_LFN /* LFN configuration */
|
#if FF_USE_LFN /* LFN configuration */
|
||||||
if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
|
if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
|
||||||
ord = 0xFF;
|
ord = 0xFF;
|
||||||
} else {
|
} else {
|
||||||
if (a == AM_LFN) { /* An LFN entry is found */
|
if (attr == AM_LFN) { /* An LFN entry is found */
|
||||||
if (c & LLEF) { /* Is it start of an LFN sequence? */
|
if (b & LLEF) { /* Is it start of an LFN sequence? */
|
||||||
sum = dp->dir[LDIR_Chksum];
|
sum = dp->dir[LDIR_Chksum];
|
||||||
c &= (BYTE)~LLEF; ord = c;
|
b &= (BYTE)~LLEF; ord = b;
|
||||||
dp->blk_ofs = dp->dptr;
|
dp->blk_ofs = dp->dptr;
|
||||||
}
|
}
|
||||||
/* Check LFN validity and capture it */
|
/* Check LFN validity and capture it */
|
||||||
ord = (c == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
|
ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
|
||||||
} else { /* An SFN entry is found */
|
} else { /* An SFN entry is found */
|
||||||
if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */
|
if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */
|
||||||
dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
|
dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
|
||||||
@@ -2380,7 +2390,7 @@ static FRESULT dir_read (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* Non LFN configuration */
|
#else /* Non LFN configuration */
|
||||||
if (c != DDEM && c != '.' && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */
|
if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2420,7 +2430,7 @@ static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
|
|||||||
UINT di, ni;
|
UINT di, ni;
|
||||||
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
|
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
|
||||||
|
|
||||||
while ((res = dir_read_file(dp)) == FR_OK) { /* Read an item */
|
while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */
|
||||||
#if FF_MAX_LFN < 255
|
#if FF_MAX_LFN < 255
|
||||||
if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */
|
if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */
|
||||||
#endif
|
#endif
|
||||||
@@ -2499,17 +2509,17 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
|
|||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
||||||
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
|
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
|
||||||
res = dir_alloc(dp, nent); /* Allocate entries */
|
res = dir_alloc(dp, nent); /* Allocate directory entries */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
|
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
|
||||||
|
|
||||||
if (dp->obj.stat & 4) { /* Has the directory been stretched? */
|
if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */
|
||||||
dp->obj.stat &= ~4;
|
dp->obj.stat &= ~4;
|
||||||
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
|
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->obj.sclust != 0) { /* Is it a sub directory? */
|
if (dp->obj.sclust != 0) { /* Is it a sub-directory? */
|
||||||
DIR dj;
|
DIR dj;
|
||||||
|
|
||||||
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
|
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
|
||||||
@@ -2641,6 +2651,7 @@ static void get_fileinfo (
|
|||||||
{
|
{
|
||||||
UINT si, di;
|
UINT si, di;
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
|
BYTE lcf;
|
||||||
WCHAR wc, hs;
|
WCHAR wc, hs;
|
||||||
FATFS *fs = dp->obj.fs;
|
FATFS *fs = dp->obj.fs;
|
||||||
#else
|
#else
|
||||||
@@ -2701,9 +2712,10 @@ static void get_fileinfo (
|
|||||||
if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */
|
if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */
|
||||||
fno->fname[di++] = '?';
|
fno->fname[di++] = '?';
|
||||||
} else {
|
} else {
|
||||||
for (si = di = 0; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */
|
for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */
|
||||||
wc = (WCHAR)fno->altname[si];
|
wc = (WCHAR)fno->altname[si];
|
||||||
if (IsUpper(wc) && (dp->dir[DIR_NTres] & ((si >= 9) ? NS_EXT : NS_BODY))) wc += 0x20;
|
if (wc == '.') lcf = NS_EXT;
|
||||||
|
if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20;
|
||||||
fno->fname[di] = (TCHAR)wc;
|
fno->fname[di] = (TCHAR)wc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3257,7 +3269,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|||||||
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
|
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */
|
/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */
|
||||||
bsect = 0;
|
bsect = 0;
|
||||||
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
|
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
|
||||||
if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
|
if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
|
||||||
@@ -3280,6 +3292,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fmt == 1) {
|
if (fmt == 1) {
|
||||||
QWORD maxlba;
|
QWORD maxlba;
|
||||||
|
DWORD so, cv, bcl;
|
||||||
|
|
||||||
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
||||||
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
|
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
|
||||||
@@ -3312,12 +3325,27 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
|||||||
if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */
|
if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */
|
||||||
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
||||||
|
|
||||||
/* Check if bitmap location is in assumption (at the first cluster) */
|
/* Get bitmap location and check if it is contiguous (implementation assumption) */
|
||||||
if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR;
|
so = i = 0;
|
||||||
for (i = 0; i < SS(fs); i += SZDIRE) {
|
for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */
|
||||||
if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */
|
if (i == 0) {
|
||||||
|
if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */
|
||||||
|
if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) return FR_DISK_ERR;
|
||||||
|
so++;
|
||||||
|
}
|
||||||
|
if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */
|
||||||
|
i = (i + SZDIRE) % SS(fs); /* Next entry */
|
||||||
}
|
}
|
||||||
if (i == SS(fs)) return FR_NO_FILESYSTEM;
|
bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */
|
||||||
|
if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM;
|
||||||
|
fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */
|
||||||
|
for (;;) { /* Check if bitmap is contiguous */
|
||||||
|
if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR;
|
||||||
|
cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4);
|
||||||
|
if (cv == 0xFFFFFFFF) break; /* Last link? */
|
||||||
|
if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented? */
|
||||||
|
}
|
||||||
|
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
|
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
|
||||||
#endif
|
#endif
|
||||||
@@ -3667,7 +3695,7 @@ FRESULT f_open (
|
|||||||
fp->fptr = 0; /* Set file pointer top of the file */
|
fp->fptr = 0; /* Set file pointer top of the file */
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
#if !FF_FS_TINY
|
#if !FF_FS_TINY
|
||||||
mem_set(fp->buf, 0, FF_MAX_SS); /* Clear sector buffer */
|
mem_set(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */
|
||||||
#endif
|
#endif
|
||||||
if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
|
if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
|
||||||
fp->fptr = fp->obj.objsize; /* Offset to seek */
|
fp->fptr = fp->obj.objsize; /* Offset to seek */
|
||||||
@@ -4138,15 +4166,16 @@ FRESULT f_getcwd (
|
|||||||
TCHAR *tp = buff;
|
TCHAR *tp = buff;
|
||||||
#if FF_VOLUMES >= 2
|
#if FF_VOLUMES >= 2
|
||||||
UINT vl;
|
UINT vl;
|
||||||
#endif
|
|
||||||
#if FF_STR_VOLUME_ID
|
#if FF_STR_VOLUME_ID
|
||||||
const char *vp;
|
const char *vp;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
DEF_NAMBUF
|
DEF_NAMBUF
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive */
|
/* Get logical drive */
|
||||||
|
buff[0] = 0; /* Set null string to get current volume */
|
||||||
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
|
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
dj.obj.fs = fs;
|
dj.obj.fs = fs;
|
||||||
@@ -4165,7 +4194,7 @@ FRESULT f_getcwd (
|
|||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
do { /* Find the entry links to the child directory */
|
do { /* Find the entry links to the child directory */
|
||||||
res = dir_read_file(&dj);
|
res = DIR_READ_FILE(&dj);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */
|
if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */
|
||||||
res = dir_next(&dj, 0);
|
res = dir_next(&dj, 0);
|
||||||
@@ -4497,7 +4526,7 @@ FRESULT f_readdir (
|
|||||||
res = dir_sdi(dp, 0); /* Rewind the directory object */
|
res = dir_sdi(dp, 0); /* Rewind the directory object */
|
||||||
} else {
|
} else {
|
||||||
INIT_NAMBUF(fs);
|
INIT_NAMBUF(fs);
|
||||||
res = dir_read_file(dp); /* Read an item */
|
res = DIR_READ_FILE(dp); /* Read an item */
|
||||||
if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
|
if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
|
||||||
if (res == FR_OK) { /* A valid entry is found */
|
if (res == FR_OK) { /* A valid entry is found */
|
||||||
get_fileinfo(dp, fno); /* Get the object information */
|
get_fileinfo(dp, fno); /* Get the object information */
|
||||||
@@ -4642,7 +4671,7 @@ FRESULT f_getfree (
|
|||||||
UINT b;
|
UINT b;
|
||||||
|
|
||||||
clst = fs->n_fatent - 2; /* Number of clusters */
|
clst = fs->n_fatent - 2; /* Number of clusters */
|
||||||
sect = fs->database; /* Assuming bitmap starts at cluster 2 */
|
sect = fs->bitbase; /* Bitmap sector */
|
||||||
i = 0; /* Offset in the sector */
|
i = 0; /* Offset in the sector */
|
||||||
do { /* Counts numbuer of bits with zero in the bitmap */
|
do { /* Counts numbuer of bits with zero in the bitmap */
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
@@ -4805,7 +4834,7 @@ FRESULT f_unlink (
|
|||||||
#endif
|
#endif
|
||||||
res = dir_sdi(&sdj, 0);
|
res = dir_sdi(&sdj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_file(&sdj); /* Test if the directory is empty */
|
res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */
|
||||||
if (res == FR_OK) res = FR_DENIED; /* Not empty? */
|
if (res == FR_OK) res = FR_DENIED; /* Not empty? */
|
||||||
if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
|
if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
|
||||||
}
|
}
|
||||||
@@ -4843,73 +4872,69 @@ FRESULT f_mkdir (
|
|||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
DIR dj;
|
DIR dj;
|
||||||
|
FFOBJID sobj;
|
||||||
FATFS *fs;
|
FATFS *fs;
|
||||||
BYTE *dir;
|
|
||||||
DWORD dcl, pcl, tm;
|
DWORD dcl, pcl, tm;
|
||||||
DEF_NAMBUF
|
DEF_NAMBUF
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive */
|
res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */
|
||||||
res = find_volume(&path, &fs, FA_WRITE);
|
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
dj.obj.fs = fs;
|
dj.obj.fs = fs;
|
||||||
INIT_NAMBUF(fs);
|
INIT_NAMBUF(fs);
|
||||||
res = follow_path(&dj, path); /* Follow the file path */
|
res = follow_path(&dj, path); /* Follow the file path */
|
||||||
if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */
|
if (res == FR_OK) res = FR_EXIST; /* Name collision? */
|
||||||
if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) {
|
if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */
|
||||||
res = FR_INVALID_NAME;
|
res = FR_INVALID_NAME;
|
||||||
}
|
}
|
||||||
if (res == FR_NO_FILE) { /* Can create a new directory */
|
if (res == FR_NO_FILE) { /* It is clear to create a new directory */
|
||||||
dcl = create_chain(&dj.obj, 0); /* Allocate a cluster for the new directory table */
|
sobj.fs = fs; /* New object id to create a new chain */
|
||||||
dj.obj.objsize = (DWORD)fs->csize * SS(fs);
|
dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */
|
||||||
res = FR_OK;
|
res = FR_OK;
|
||||||
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
|
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */
|
||||||
if (dcl == 1) res = FR_INT_ERR;
|
if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */
|
||||||
if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
|
if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */
|
||||||
if (res == FR_OK) res = sync_window(fs); /* Flush FAT */
|
|
||||||
tm = GET_FATTIME();
|
tm = GET_FATTIME();
|
||||||
if (res == FR_OK) { /* Initialize the new directory table */
|
|
||||||
res = dir_clear(fs, dcl); /* Clean up the new table */
|
|
||||||
if (res == FR_OK && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT)) { /* Create dot entries (FAT only) */
|
|
||||||
dir = fs->win;
|
|
||||||
mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */
|
|
||||||
dir[DIR_Name] = '.';
|
|
||||||
dir[DIR_Attr] = AM_DIR;
|
|
||||||
st_dword(dir + DIR_ModTime, tm);
|
|
||||||
st_clust(fs, dir, dcl);
|
|
||||||
mem_cpy(dir + SZDIRE, dir, SZDIRE); /* Create ".." entry */
|
|
||||||
dir[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
|
|
||||||
st_clust(fs, dir + SZDIRE, pcl);
|
|
||||||
fs->wflag = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_register(&dj); /* Register the object to the directoy */
|
res = dir_clear(fs, dcl); /* Clean up the new table */
|
||||||
|
if (res == FR_OK) {
|
||||||
|
if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */
|
||||||
|
mem_set(fs->win + DIR_Name, ' ', 11); /* Create "." entry */
|
||||||
|
fs->win[DIR_Name] = '.';
|
||||||
|
fs->win[DIR_Attr] = AM_DIR;
|
||||||
|
st_dword(fs->win + DIR_ModTime, tm);
|
||||||
|
st_clust(fs, fs->win, dcl);
|
||||||
|
mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */
|
||||||
|
fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
|
||||||
|
st_clust(fs, fs->win + SZDIRE, pcl);
|
||||||
|
fs->wflag = 1;
|
||||||
|
}
|
||||||
|
res = dir_register(&dj); /* Register the object to the parent directoy */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */
|
if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */
|
||||||
st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */
|
st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */
|
||||||
st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */
|
st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */
|
||||||
st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)dj.obj.objsize); /* File size needs to be valid */
|
st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* File size needs to be valid */
|
||||||
st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)dj.obj.objsize);
|
st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs));
|
||||||
fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */
|
fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */
|
||||||
fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */
|
fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */
|
||||||
res = store_xdir(&dj);
|
res = store_xdir(&dj);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
dir = dj.dir;
|
st_dword(dj.dir + DIR_ModTime, tm); /* Created time */
|
||||||
st_dword(dir + DIR_ModTime, tm); /* Created time */
|
st_clust(fs, dj.dir, dcl); /* Table start cluster */
|
||||||
st_clust(fs, dir, dcl); /* Table start cluster */
|
dj.dir[DIR_Attr] = AM_DIR; /* Attribute */
|
||||||
dir[DIR_Attr] = AM_DIR; /* Attribute */
|
|
||||||
fs->wflag = 1;
|
fs->wflag = 1;
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = sync_fs(fs);
|
res = sync_fs(fs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
remove_chain(&dj.obj, dcl, 0); /* Could not register, remove cluster chain */
|
remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FREE_NAMBUF();
|
FREE_NAMBUF();
|
||||||
@@ -5149,7 +5174,7 @@ FRESULT f_getlabel (
|
|||||||
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_label(&dj); /* Find a volume label entry */
|
res = DIR_READ_LABEL(&dj); /* Find a volume label entry */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) {
|
if (fs->fs_type == FS_EXFAT) {
|
||||||
@@ -5294,7 +5319,7 @@ FRESULT f_setlabel (
|
|||||||
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_label(&dj); /* Get volume label entry */
|
res = DIR_READ_LABEL(&dj); /* Get volume label entry */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
||||||
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
|
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
|
||||||
@@ -5316,7 +5341,7 @@ FRESULT f_setlabel (
|
|||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
|
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
|
||||||
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
||||||
dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */
|
dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */
|
||||||
dj.dir[XDIR_NumLabel] = (BYTE)di;
|
dj.dir[XDIR_NumLabel] = (BYTE)di;
|
||||||
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
|
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
|
||||||
} else {
|
} else {
|
||||||
@@ -5621,7 +5646,7 @@ FRESULT f_mkfs (
|
|||||||
b_fat = b_vol + 32; /* FAT start at offset 32 */
|
b_fat = b_vol + 32; /* FAT start at offset 32 */
|
||||||
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
|
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
|
||||||
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
|
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
|
||||||
if (b_data >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
||||||
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
|
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
|
||||||
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */
|
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */
|
||||||
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
|
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
|
||||||
@@ -5702,11 +5727,11 @@ FRESULT f_mkfs (
|
|||||||
|
|
||||||
/* Initialize the root directory */
|
/* Initialize the root directory */
|
||||||
mem_set(buf, 0, szb_buf);
|
mem_set(buf, 0, szb_buf);
|
||||||
buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */
|
buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry */
|
||||||
buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */
|
buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */
|
||||||
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
|
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
|
||||||
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
|
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
|
||||||
buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */
|
buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */
|
||||||
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
|
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
|
||||||
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
|
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
|
||||||
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
|
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
|
||||||
@@ -6194,8 +6219,7 @@ typedef struct { /* Putchar output buffer and work area */
|
|||||||
} putbuff;
|
} putbuff;
|
||||||
|
|
||||||
|
|
||||||
static
|
static void putc_bfd ( /* Buffered write with code conversion */
|
||||||
void putc_bfd ( /* Buffered write with code conversion */
|
|
||||||
putbuff* pb,
|
putbuff* pb,
|
||||||
TCHAR c
|
TCHAR c
|
||||||
)
|
)
|
||||||
@@ -6306,7 +6330,7 @@ void putc_bfd ( /* Buffered write with code conversion */
|
|||||||
#else /* Write it in ANSI/OEM */
|
#else /* Write it in ANSI/OEM */
|
||||||
if (hs != 0) return;
|
if (hs != 0) return;
|
||||||
wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */
|
wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */
|
||||||
if (wc == 0) return;;
|
if (wc == 0) return;
|
||||||
if (wc >= 0x100) {
|
if (wc >= 0x100) {
|
||||||
pb->buf[i++] = (BYTE)(wc >> 8); nc++;
|
pb->buf[i++] = (BYTE)(wc >> 8); nc++;
|
||||||
}
|
}
|
||||||
@@ -6326,8 +6350,7 @@ void putc_bfd ( /* Buffered write with code conversion */
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static int putc_flush ( /* Flush left characters in the buffer */
|
||||||
int putc_flush ( /* Flush left characters in the buffer */
|
|
||||||
putbuff* pb
|
putbuff* pb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -6340,8 +6363,7 @@ int putc_flush ( /* Flush left characters in the buffer */
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static void putc_init ( /* Initialize write buffer */
|
||||||
void putc_init ( /* Initialize write buffer */
|
|
||||||
putbuff* pb,
|
putbuff* pb,
|
||||||
FIL* fp
|
FIL* fp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem module R0.13b /
|
/ FatFs - Generic FAT Filesystem module R0.13c /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
@@ -20,13 +20,12 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef FF_DEFINED
|
#ifndef FF_DEFINED
|
||||||
#define FF_DEFINED 63463 /* Revision ID */
|
#define FF_DEFINED 86604 /* Revision ID */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "integer.h" /* Basic integer types */
|
|
||||||
#include "ffconf.h" /* FatFs configuration options */
|
#include "ffconf.h" /* FatFs configuration options */
|
||||||
|
|
||||||
#if FF_DEFINED != FFCONF_DEF
|
#if FF_DEFINED != FFCONF_DEF
|
||||||
@@ -34,6 +33,30 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Integer types used for FatFs API */
|
||||||
|
|
||||||
|
#if defined(_WIN32) /* Main development platform */
|
||||||
|
#define FF_INTDEF 2
|
||||||
|
#include <windows.h>
|
||||||
|
typedef unsigned __int64 QWORD;
|
||||||
|
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
|
||||||
|
#define FF_INTDEF 2
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||||
|
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||||
|
typedef uint16_t WORD; /* 16-bit unsigned integer */
|
||||||
|
typedef uint16_t WCHAR; /* 16-bit unsigned integer */
|
||||||
|
typedef uint32_t DWORD; /* 32-bit unsigned integer */
|
||||||
|
typedef uint64_t QWORD; /* 64-bit unsigned integer */
|
||||||
|
#else /* Earlier than C99 */
|
||||||
|
#define FF_INTDEF 1
|
||||||
|
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||||
|
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||||
|
typedef unsigned short WORD; /* 16-bit unsigned integer */
|
||||||
|
typedef unsigned short WCHAR; /* 16-bit unsigned integer */
|
||||||
|
typedef unsigned long DWORD; /* 32-bit unsigned integer */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Definitions of volume management */
|
/* Definitions of volume management */
|
||||||
|
|
||||||
@@ -85,6 +108,9 @@ typedef char TCHAR;
|
|||||||
/* Type of file size variables */
|
/* Type of file size variables */
|
||||||
|
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
|
#if FF_INTDEF != 2
|
||||||
|
#error exFAT feature wants C99 or later
|
||||||
|
#endif
|
||||||
typedef QWORD FSIZE_t;
|
typedef QWORD FSIZE_t;
|
||||||
#else
|
#else
|
||||||
typedef DWORD FSIZE_t;
|
typedef DWORD FSIZE_t;
|
||||||
@@ -95,8 +121,8 @@ typedef DWORD FSIZE_t;
|
|||||||
/* Filesystem object structure (FATFS) */
|
/* Filesystem object structure (FATFS) */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE fs_type; /* Filesystem type (0:N/A) */
|
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||||
BYTE pdrv; /* Physical drive number */
|
BYTE pdrv; /* Associated physical drive */
|
||||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||||
@@ -133,6 +159,9 @@ typedef struct {
|
|||||||
DWORD fatbase; /* FAT base sector */
|
DWORD fatbase; /* FAT base sector */
|
||||||
DWORD dirbase; /* Root directory base sector/cluster */
|
DWORD dirbase; /* Root directory base sector/cluster */
|
||||||
DWORD database; /* Data base sector */
|
DWORD database; /* Data base sector */
|
||||||
|
#if FF_FS_EXFAT
|
||||||
|
DWORD bitbase; /* Allocation bitmap base sector */
|
||||||
|
#endif
|
||||||
DWORD winsect; /* Current sector appearing in the win[] */
|
DWORD winsect; /* Current sector appearing in the win[] */
|
||||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||||
} FATFS;
|
} FATFS;
|
||||||
@@ -145,7 +174,7 @@ typedef struct {
|
|||||||
FATFS* fs; /* Pointer to the hosting volume of this object */
|
FATFS* fs; /* Pointer to the hosting volume of this object */
|
||||||
WORD id; /* Hosting volume mount ID */
|
WORD id; /* Hosting volume mount ID */
|
||||||
BYTE attr; /* Object attribute */
|
BYTE attr; /* Object attribute */
|
||||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */
|
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||||
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
||||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
@@ -276,7 +305,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe
|
|||||||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
||||||
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||||
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||||
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
|
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */
|
||||||
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
||||||
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
|
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
|
||||||
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
|
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - Configuration file
|
/ FatFs Functional Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define FFCONF_DEF 63463 /* Revision ID */
|
#define FFCONF_DEF 86604 /* Revision ID */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ Function Configurations
|
/ Function Configurations
|
||||||
@@ -232,7 +232,7 @@
|
|||||||
|
|
||||||
#define FF_FS_EXFAT 1
|
#define FF_FS_EXFAT 1
|
||||||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
||||||
/ To enable exFAT, also LFN needs to be enabled.
|
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
|
||||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||||
|
|
||||||
|
|
||||||
@@ -262,6 +262,7 @@
|
|||||||
/ lock control is independent of re-entrancy. */
|
/ lock control is independent of re-entrancy. */
|
||||||
|
|
||||||
|
|
||||||
|
/* #include <somertos.h> // O/S definitions */
|
||||||
#define FF_FS_REENTRANT 0
|
#define FF_FS_REENTRANT 0
|
||||||
#define FF_FS_TIMEOUT 1000
|
#define FF_FS_TIMEOUT 1000
|
||||||
#define FF_SYNC_t HANDLE
|
#define FF_SYNC_t HANDLE
|
||||||
@@ -282,8 +283,6 @@
|
|||||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||||
/ included somewhere in the scope of ff.h. */
|
/ included somewhere in the scope of ff.h. */
|
||||||
|
|
||||||
/* #include <windows.h> // O/S definitions */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--- End of configuration options ---*/
|
/*--- End of configuration options ---*/
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Sample Code of OS Dependent Functions for FatFs */
|
/* Sample Code of OS Dependent Functions for FatFs */
|
||||||
/* (C)ChaN, 2017 */
|
/* (C)ChaN, 2018 */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Allocate a memory block */
|
/* Allocate a memory block */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */
|
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||||
UINT msize /* Number of bytes to allocate */
|
UINT msize /* Number of bytes to allocate */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -27,7 +26,7 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on no
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void ff_memfree (
|
void ff_memfree (
|
||||||
void* mblock /* Pointer to the memory block to free (nothing to do for null) */
|
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
free(mblock); /* Free the memory block with POSIX API */
|
free(mblock); /* Free the memory block with POSIX API */
|
||||||
@@ -47,7 +46,7 @@ void ff_memfree (
|
|||||||
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
|
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */
|
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
|
||||||
|
|
||||||
|
|
||||||
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
|
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
|
||||||
@@ -74,7 +73,7 @@ int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object
|
|||||||
// return (int)(*sobj != NULL);
|
// return (int)(*sobj != NULL);
|
||||||
|
|
||||||
/* CMSIS-RTOS */
|
/* CMSIS-RTOS */
|
||||||
// *sobj = osMutexCreate(Mutex + vol);
|
// *sobj = osMutexCreate(&Mutex[vol]);
|
||||||
// return (int)(*sobj != NULL);
|
// return (int)(*sobj != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Unicode handling functions for FatFs R0.13b */
|
/* Unicode handling functions for FatFs R0.13c */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* This module will occupy a huge memory in the .const section when the /
|
/* This module will occupy a huge memory in the .const section when the /
|
||||||
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
||||||
@@ -25,9 +25,9 @@
|
|||||||
|
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
#if FF_USE_LFN /* This module is blanked when non-LFN configuration */
|
#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */
|
||||||
|
|
||||||
#if FF_DEFINED != 63463 /* Revision ID */
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
/*-------------------------------------------*/
|
|
||||||
/* Integer type definitions for FatFs module */
|
|
||||||
/*-------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef FF_INTEGER
|
|
||||||
#define FF_INTEGER
|
|
||||||
|
|
||||||
#ifdef _WIN32 /* FatFs development platform */
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
typedef unsigned __int64 QWORD;
|
|
||||||
|
|
||||||
#else /* Embedded platform */
|
|
||||||
|
|
||||||
/* These types MUST be 16-bit or 32-bit */
|
|
||||||
typedef int INT;
|
|
||||||
typedef unsigned int UINT;
|
|
||||||
|
|
||||||
/* This type MUST be 8-bit */
|
|
||||||
typedef unsigned char BYTE;
|
|
||||||
|
|
||||||
/* These types MUST be 16-bit */
|
|
||||||
typedef short SHORT;
|
|
||||||
typedef unsigned short WORD;
|
|
||||||
typedef unsigned short WCHAR;
|
|
||||||
|
|
||||||
/* These types MUST be 32-bit */
|
|
||||||
typedef long LONG;
|
|
||||||
typedef unsigned long DWORD;
|
|
||||||
|
|
||||||
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
|
|
||||||
typedef unsigned long long QWORD;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -26,13 +26,11 @@
|
|||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "chainloader.h"
|
#include "chainloader.h"
|
||||||
#include "stage2.h"
|
#include "stage2.h"
|
||||||
#include "mtc.h"
|
|
||||||
#include "nxboot.h"
|
#include "nxboot.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "nxfs.h"
|
#include "nxfs.h"
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
#include "splash_screen.h"
|
|
||||||
#include "display/video_fb.h"
|
#include "display/video_fb.h"
|
||||||
#include "sdmmc/sdmmc.h"
|
#include "sdmmc/sdmmc.h"
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
@@ -44,8 +42,8 @@ static stage2_args_t *g_stage2_args;
|
|||||||
static bool g_do_nxboot;
|
static bool g_do_nxboot;
|
||||||
|
|
||||||
static void setup_env(void) {
|
static void setup_env(void) {
|
||||||
/* Set the console up. */
|
/* Initialize the display and console. */
|
||||||
if (console_init(g_stage2_args->display_initialized) == -1) {
|
if (console_init() < 0) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,16 +54,11 @@ static void setup_env(void) {
|
|||||||
if (nxfs_init() < 0) {
|
if (nxfs_init() < 0) {
|
||||||
fatal_error("Failed to initialize the file system: %s\n", strerror(errno));
|
fatal_error("Failed to initialize the file system: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Train DRAM. */
|
|
||||||
train_dram();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void cleanup_env(void) {
|
static void cleanup_env(void) {
|
||||||
/* Unmount everything (this causes all open files to be flushed and closed) */
|
/* Terminate the file system. */
|
||||||
nxfs_end();
|
nxfs_end();
|
||||||
//console_end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exit_callback(int rc) {
|
static void exit_callback(int rc) {
|
||||||
@@ -83,6 +76,7 @@ static void exit_callback(int rc) {
|
|||||||
int main(int argc, void **argv) {
|
int main(int argc, void **argv) {
|
||||||
loader_ctx_t *loader_ctx = get_loader_ctx();
|
loader_ctx_t *loader_ctx = get_loader_ctx();
|
||||||
|
|
||||||
|
/* Check argc. */
|
||||||
if (argc != STAGE2_ARGC) {
|
if (argc != STAGE2_ARGC) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -90,6 +84,7 @@ int main(int argc, void **argv) {
|
|||||||
g_stage2_args = &g_stage2_args_store;
|
g_stage2_args = &g_stage2_args_store;
|
||||||
memcpy(g_stage2_args, (stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT], sizeof(*g_stage2_args));
|
memcpy(g_stage2_args, (stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT], sizeof(*g_stage2_args));
|
||||||
|
|
||||||
|
/* Check stage2 version field. */
|
||||||
if (g_stage2_args->version != 0) {
|
if (g_stage2_args->version != 0) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
@@ -97,7 +92,7 @@ int main(int argc, void **argv) {
|
|||||||
/* Override the global logging level. */
|
/* Override the global logging level. */
|
||||||
log_set_log_level(g_stage2_args->log_level);
|
log_set_log_level(g_stage2_args->log_level);
|
||||||
|
|
||||||
/* Initialize the display, console, FS, etc. */
|
/* Initialize the boot environment. */
|
||||||
setup_env();
|
setup_env();
|
||||||
|
|
||||||
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, u8"Welcome to Atmosphère Fusée Stage 2!\n");
|
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, u8"Welcome to Atmosphère Fusée Stage 2!\n");
|
||||||
@@ -114,29 +109,30 @@ int main(int argc, void **argv) {
|
|||||||
|
|
||||||
/* This will load all remaining binaries off of the SD. */
|
/* This will load all remaining binaries off of the SD. */
|
||||||
load_payload(g_stage2_args->bct0);
|
load_payload(g_stage2_args->bct0);
|
||||||
|
|
||||||
print(SCREEN_LOG_LEVEL_INFO, "Loaded payloads!\n");
|
print(SCREEN_LOG_LEVEL_INFO, "Loaded payloads!\n");
|
||||||
|
|
||||||
g_do_nxboot = loader_ctx->chainload_entrypoint == 0;
|
g_do_nxboot = (loader_ctx->chainload_entrypoint == 0);
|
||||||
if (g_do_nxboot) {
|
if (g_do_nxboot) {
|
||||||
print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n");
|
print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n");
|
||||||
|
|
||||||
|
/* Start boot. */
|
||||||
uint32_t boot_memaddr = nxboot_main();
|
uint32_t boot_memaddr = nxboot_main();
|
||||||
/* Wait for the splash screen to have been displayed as long as it should be. */
|
|
||||||
splash_screen_wait_delay();
|
/* Terminate the boot environment. */
|
||||||
/* Cleanup environment. */
|
|
||||||
cleanup_env();
|
cleanup_env();
|
||||||
|
|
||||||
/* Finish boot. */
|
/* Finish boot. */
|
||||||
nxboot_finish(boot_memaddr);
|
nxboot_finish(boot_memaddr);
|
||||||
} else {
|
} else {
|
||||||
/* TODO: What else do we want to do in terms of argc/argv? */
|
/* TODO: What else do we want to do in terms of argc/argv? */
|
||||||
const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint];
|
const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint];
|
||||||
print(SCREEN_LOG_LEVEL_MANDATORY, "Now chainloading.\n");
|
print(SCREEN_LOG_LEVEL_INFO, "Now chainloading.\n");
|
||||||
g_chainloader_argc = 1;
|
g_chainloader_argc = 1;
|
||||||
strcpy(g_chainloader_arg_data, path);
|
strcpy(g_chainloader_arg_data, path);
|
||||||
}
|
|
||||||
|
|
||||||
/* Deinitialize the display, console, FS, etc. */
|
/* Terminate the boot environment. */
|
||||||
cleanup_env();
|
cleanup_env();
|
||||||
|
}
|
||||||
|
|
||||||
/* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, chainload or halt ourselves. */
|
/* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, chainload or halt ourselves. */
|
||||||
__program_exit_callback = exit_callback;
|
__program_exit_callback = exit_callback;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#include "exocfg.h"
|
#include "exocfg.h"
|
||||||
#include "display/video_fb.h"
|
#include "display/video_fb.h"
|
||||||
#include "lib/ini.h"
|
#include "lib/ini.h"
|
||||||
|
#include "lib/log.h"
|
||||||
#include "splash_screen.h"
|
#include "splash_screen.h"
|
||||||
|
|
||||||
#define u8 uint8_t
|
#define u8 uint8_t
|
||||||
@@ -57,7 +58,6 @@
|
|||||||
#include "sept_secondary_01_enc.h"
|
#include "sept_secondary_01_enc.h"
|
||||||
#include "lp0fw_bin.h"
|
#include "lp0fw_bin.h"
|
||||||
#include "emummc_kip.h"
|
#include "emummc_kip.h"
|
||||||
#include "lib/log.h"
|
|
||||||
#undef u8
|
#undef u8
|
||||||
#undef u32
|
#undef u32
|
||||||
|
|
||||||
@@ -650,7 +650,6 @@ uint32_t nxboot_main(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//fatal_error("Ran sept!");
|
|
||||||
/* Display splash screen. */
|
/* Display splash screen. */
|
||||||
display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000);
|
display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000);
|
||||||
|
|
||||||
@@ -716,7 +715,6 @@ uint32_t nxboot_main(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Select the right address for the warmboot firmware. */
|
/* Select the right address for the warmboot firmware. */
|
||||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||||
warmboot_memaddr = (void *)0x8000D000;
|
warmboot_memaddr = (void *)0x8000D000;
|
||||||
@@ -801,8 +799,8 @@ uint32_t nxboot_main(void) {
|
|||||||
|
|
||||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Powering on the CCPLEX...\n");
|
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Powering on the CCPLEX...\n");
|
||||||
|
|
||||||
/* Unmount everything. */
|
/* Wait for the splash screen to have been displayed for as long as it should be. */
|
||||||
nxfs_end();
|
splash_screen_wait_delay();
|
||||||
|
|
||||||
/* Return the memory address for booting CPU0. */
|
/* Return the memory address for booting CPU0. */
|
||||||
return (uint32_t)exosphere_memaddr;
|
return (uint32_t)exosphere_memaddr;
|
||||||
|
|||||||
@@ -24,11 +24,9 @@ static uint32_t g_panic_code = 0;
|
|||||||
|
|
||||||
void check_and_display_panic(void) {
|
void check_and_display_panic(void) {
|
||||||
/* We also handle our own panics. */
|
/* We also handle our own panics. */
|
||||||
/* In the case of our own panics, we assume that the display has already been initialized. */
|
bool has_panic = ((APBDEV_PMC_RST_STATUS_0 != 0) || (g_panic_code != 0));
|
||||||
bool has_panic = APBDEV_PMC_RST_STATUS_0 != 0 || g_panic_code != 0;
|
uint32_t code = (g_panic_code == 0) ? APBDEV_PMC_SCRATCH200_0 : g_panic_code;
|
||||||
uint32_t code = g_panic_code == 0 ? APBDEV_PMC_SCRATCH200_0 : g_panic_code;
|
has_panic = has_panic && !((APBDEV_PMC_RST_STATUS_0 != 1) && (code == PANIC_CODE_SAFEMODE));
|
||||||
|
|
||||||
has_panic = has_panic && !(APBDEV_PMC_RST_STATUS_0 != 1 && code == PANIC_CODE_SAFEMODE);
|
|
||||||
|
|
||||||
if (has_panic) {
|
if (has_panic) {
|
||||||
uint32_t color;
|
uint32_t color;
|
||||||
@@ -71,11 +69,13 @@ void check_and_display_panic(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_panic_code == 0) {
|
/* Initialize the display. */
|
||||||
display_init();
|
display_init();
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Fill the screen. */
|
||||||
display_color_screen(color);
|
display_color_screen(color);
|
||||||
|
|
||||||
|
/* Wait for button and reboot. */
|
||||||
wait_for_button_and_reboot();
|
wait_for_button_and_reboot();
|
||||||
} else {
|
} else {
|
||||||
g_panic_code = 0;
|
g_panic_code = 0;
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
ScreenLogLevel log_level;
|
ScreenLogLevel log_level;
|
||||||
bool display_initialized;
|
|
||||||
char bct0[BCTO_MAX_SIZE];
|
char bct0[BCTO_MAX_SIZE];
|
||||||
} stage2_args_t;
|
} stage2_args_t;
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0x1A0;
|
case CARDEVICE_UARTC: return 0x1A0;
|
||||||
case CARDEVICE_I2C1: return 0x124;
|
case CARDEVICE_I2C1: return 0x124;
|
||||||
case CARDEVICE_I2C5: return 0x128;
|
case CARDEVICE_I2C5: return 0x128;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0x42C;
|
case CARDEVICE_SE: return 0x42C;
|
||||||
case CARDEVICE_HOST1X: return 0x180;
|
case CARDEVICE_HOST1X: return 0x180;
|
||||||
case CARDEVICE_TSEC: return 0x1F4;
|
case CARDEVICE_TSEC: return 0x1F4;
|
||||||
@@ -48,7 +48,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0;
|
case CARDEVICE_UARTC: return 0;
|
||||||
case CARDEVICE_I2C1: return 6;
|
case CARDEVICE_I2C1: return 6;
|
||||||
case CARDEVICE_I2C5: return 6;
|
case CARDEVICE_I2C5: return 6;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0;
|
case CARDEVICE_SE: return 0;
|
||||||
case CARDEVICE_HOST1X: return 4;
|
case CARDEVICE_HOST1X: return 4;
|
||||||
case CARDEVICE_TSEC: return 0;
|
case CARDEVICE_TSEC: return 0;
|
||||||
@@ -71,7 +71,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) {
|
|||||||
case CARDEVICE_UARTC: return 0;
|
case CARDEVICE_UARTC: return 0;
|
||||||
case CARDEVICE_I2C1: return 0;
|
case CARDEVICE_I2C1: return 0;
|
||||||
case CARDEVICE_I2C5: return 0;
|
case CARDEVICE_I2C5: return 0;
|
||||||
case CARDEVICE_UNK: return 0;
|
case CARDEVICE_TZRAM: return 0;
|
||||||
case CARDEVICE_SE: return 0;
|
case CARDEVICE_SE: return 0;
|
||||||
case CARDEVICE_HOST1X: return 3;
|
case CARDEVICE_HOST1X: return 3;
|
||||||
case CARDEVICE_TSEC: return 2;
|
case CARDEVICE_TSEC: return 2;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ typedef enum {
|
|||||||
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
CARDEVICE_UARTC = ((1 << 5) | 0x17),
|
||||||
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
|
||||||
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
|
||||||
CARDEVICE_UNK = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
|||||||
@@ -21,125 +21,66 @@
|
|||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
/**
|
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin) {
|
||||||
* Returns a GPIO bank object that corresponds to the given GPIO pin,
|
|
||||||
* which can be created using the TEGRA_GPIO macro or passed from the name macro.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO to get the bank for.
|
|
||||||
* @return The GPIO bank object to use for working with the given bank.
|
|
||||||
*/
|
|
||||||
static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin)
|
|
||||||
{
|
|
||||||
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
volatile tegra_gpio_t *gpio = gpio_get_regs();
|
||||||
uint32_t bank_number = pin >> GPIO_BANK_SHIFT;
|
uint32_t bank_number = (pin >> GPIO_BANK_SHIFT);
|
||||||
|
|
||||||
return &gpio->bank[bank_number];
|
return &gpio->bank[bank_number];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static volatile uint32_t gpio_get_port(uint32_t pin) {
|
||||||
* @return the port number for working with the given GPIO.
|
return ((pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK);
|
||||||
*/
|
|
||||||
static volatile uint32_t gpio_get_port(uint32_t pin)
|
|
||||||
{
|
|
||||||
return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static volatile uint32_t gpio_get_mask(uint32_t pin) {
|
||||||
* @return a mask to be used to work with the given GPIO
|
uint32_t pin_number = (pin & GPIO_PIN_MASK);
|
||||||
*/
|
|
||||||
static volatile uint32_t gpio_get_mask(uint32_t pin)
|
|
||||||
{
|
|
||||||
uint32_t pin_number = pin & GPIO_PIN_MASK;
|
|
||||||
return (1 << pin_number);
|
return (1 << pin_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset) {
|
||||||
* Performs a simple GPIO configuration operation.
|
/* Retrieve the register set that corresponds to the given pin and offset. */
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
|
||||||
* @param offset The offset into a gpio_bank structure
|
|
||||||
*/
|
|
||||||
static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset)
|
|
||||||
{
|
|
||||||
// Retrieve the register set that corresponds to the given pin and offset.
|
|
||||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||||
uint32_t *cluster = (uint32_t *)cluster_addr;
|
uint32_t *cluster = (uint32_t *)cluster_addr;
|
||||||
|
|
||||||
// Figure out the offset into the cluster,
|
/* Figure out the offset into the cluster, and the mask to be used. */
|
||||||
// and the mask to be used.
|
|
||||||
uint32_t port = gpio_get_port(pin);
|
uint32_t port = gpio_get_port(pin);
|
||||||
uint32_t mask = gpio_get_mask(pin);
|
uint32_t mask = gpio_get_mask(pin);
|
||||||
|
|
||||||
// Set or clear the bit, as appropriate.
|
/* Set or clear the bit, as appropriate. */
|
||||||
if (should_be_set)
|
if (should_be_set)
|
||||||
cluster[port] |= mask;
|
cluster[port] |= mask;
|
||||||
else
|
else
|
||||||
cluster[port] &= ~mask;
|
cluster[port] &= ~mask;
|
||||||
|
|
||||||
|
/* Dummy read. */
|
||||||
|
(void)cluster[port];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset) {
|
||||||
* Performs a simple GPIO configuration operation.
|
/* Retrieve the register set that corresponds to the given pin and offset. */
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param should_be_set True iff the relevant bit should be set; or false if it should be cleared.
|
|
||||||
* @param offset The offset into a gpio_bank structure
|
|
||||||
*/
|
|
||||||
static bool gpio_simple_register_get(uint32_t pin, uint32_t offset)
|
|
||||||
{
|
|
||||||
// Retrieve the register set that corresponds to the given pin and offset.
|
|
||||||
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset;
|
||||||
uint32_t *cluster = (uint32_t *)cluster_addr;
|
uint32_t *cluster = (uint32_t *)cluster_addr;
|
||||||
|
|
||||||
// Figure out the offset into the cluster,
|
/* Figure out the offset into the cluster, and the mask to be used. */
|
||||||
// and the mask to be used.
|
|
||||||
uint32_t port = gpio_get_port(pin);
|
uint32_t port = gpio_get_port(pin);
|
||||||
uint32_t mask = gpio_get_mask(pin);
|
uint32_t mask = gpio_get_mask(pin);
|
||||||
|
|
||||||
// Convert the given value to a boolean.
|
/* Convert the given value to a boolean. */
|
||||||
return !!(cluster[port] & mask);
|
return !!(cluster[port] & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_configure_mode(uint32_t pin, uint32_t mode) {
|
||||||
* Configures a given pin as either GPIO or SFIO.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
void gpio_configure_mode(uint32_t pin, uint32_t mode)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_configure_direction(uint32_t pin, uint32_t dir) {
|
||||||
* Configures a given pin as either INPUT or OUPUT.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param direction The relevant direction.
|
|
||||||
*/
|
|
||||||
void gpio_configure_direction(uint32_t pin, uint32_t dir)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void gpio_write(uint32_t pin, uint32_t value) {
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
void gpio_write(uint32_t pin, uint32_t value)
|
|
||||||
{
|
|
||||||
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
uint32_t gpio_read(uint32_t pin) {
|
||||||
* Drives a relevant GPIO pin as either HIGH or LOW.
|
|
||||||
*
|
|
||||||
* @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO.
|
|
||||||
* @param mode The relevant mode.
|
|
||||||
*/
|
|
||||||
uint32_t gpio_read(uint32_t pin)
|
|
||||||
{
|
|
||||||
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ static inline volatile tegra_gpio_t *gpio_get_regs(void)
|
|||||||
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
((TEGRA_GPIO_PORT_##port * 8) + offset)
|
||||||
|
|
||||||
/* Mode select */
|
/* Mode select */
|
||||||
#define GPIO_MODE_GPIO 0
|
#define GPIO_MODE_SFIO 0
|
||||||
#define GPIO_MODE_SFIO 1
|
#define GPIO_MODE_GPIO 1
|
||||||
|
|
||||||
/* Direction */
|
/* Direction */
|
||||||
#define GPIO_DIRECTION_INPUT 0
|
#define GPIO_DIRECTION_INPUT 0
|
||||||
|
|||||||
@@ -17,19 +17,52 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
#include "pinmux.h"
|
||||||
|
|
||||||
/* Prototypes for internal commands. */
|
/* Prototypes for internal commands. */
|
||||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id);
|
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id);
|
||||||
void i2c_load_config(volatile tegra_i2c_t *regs);
|
void i2c_load_config(volatile tegra_i2c_t *regs);
|
||||||
|
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||||
|
|
||||||
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
|
bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size);
|
||||||
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
|
bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size);
|
||||||
|
|
||||||
|
/* Configure I2C pinmux. */
|
||||||
|
void i2c_config(I2CDevice id) {
|
||||||
|
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case I2C_1:
|
||||||
|
pinmux->gen1_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen1_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_2:
|
||||||
|
pinmux->gen2_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen2_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_3:
|
||||||
|
pinmux->gen3_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->gen3_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_4:
|
||||||
|
pinmux->cam_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->cam_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_5:
|
||||||
|
pinmux->pwr_i2c_scl = PINMUX_INPUT;
|
||||||
|
pinmux->pwr_i2c_sda = PINMUX_INPUT;
|
||||||
|
break;
|
||||||
|
case I2C_6:
|
||||||
|
/* Unused. */
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize I2C based on registers. */
|
/* Initialize I2C based on registers. */
|
||||||
void i2c_init(unsigned int id) {
|
void i2c_init(I2CDevice id) {
|
||||||
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||||
|
|
||||||
/* Setup divisor, and clear the bus. */
|
/* Setup divisor, and clear the bus. */
|
||||||
@@ -91,7 +124,7 @@ void i2c_set_ti_charger_bit_7(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get registers pointer based on I2C ID. */
|
/* Get registers pointer based on I2C ID. */
|
||||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) {
|
volatile tegra_i2c_t *i2c_get_registers_from_id(I2CDevice id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case I2C_1:
|
case I2C_1:
|
||||||
return I2C1_REGS;
|
return I2C1_REGS;
|
||||||
@@ -126,7 +159,7 @@ void i2c_load_config(volatile tegra_i2c_t *regs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reads a register from a device over I2C, writes result to output. */
|
/* Reads a register from a device over I2C, writes result to output. */
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size) {
|
||||||
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id);
|
||||||
uint32_t val = r;
|
uint32_t val = r;
|
||||||
|
|
||||||
@@ -143,7 +176,7 @@ bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Writes a value to a register over I2C. */
|
/* Writes a value to a register over I2C. */
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size) {
|
||||||
uint32_t val = r;
|
uint32_t val = r;
|
||||||
if (src_size == 0) {
|
if (src_size == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -24,13 +24,6 @@
|
|||||||
#define I2C1234_BASE 0x7000C000
|
#define I2C1234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
#define I2C_1 0
|
|
||||||
#define I2C_2 1
|
|
||||||
#define I2C_3 2
|
|
||||||
#define I2C_4 3
|
|
||||||
#define I2C_5 4
|
|
||||||
#define I2C_6 5
|
|
||||||
|
|
||||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
#define MAX17050_I2C_ADDR 0x36
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
@@ -38,6 +31,15 @@
|
|||||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
#define BQ24193_I2C_ADDR 0x6B
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I2C_1 = 0,
|
||||||
|
I2C_2 = 1,
|
||||||
|
I2C_3 = 2,
|
||||||
|
I2C_4 = 3,
|
||||||
|
I2C_5 = 4,
|
||||||
|
I2C_6 = 5,
|
||||||
|
} I2CDevice;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t I2C_I2C_CNFG_0;
|
uint32_t I2C_I2C_CNFG_0;
|
||||||
uint32_t I2C_I2C_CMD_ADDR0_0;
|
uint32_t I2C_I2C_CMD_ADDR0_0;
|
||||||
@@ -89,9 +91,11 @@ typedef struct {
|
|||||||
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000))
|
||||||
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100))
|
||||||
|
|
||||||
void i2c_init(unsigned int id);
|
void i2c_config(I2CDevice id);
|
||||||
bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
|
||||||
bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
void i2c_init(I2CDevice id);
|
||||||
|
bool i2c_query(I2CDevice id, uint8_t device, uint8_t r, void *dst, size_t dst_size);
|
||||||
|
bool i2c_send(I2CDevice id, uint8_t device, uint8_t r, void *src, size_t src_size);
|
||||||
|
|
||||||
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
void i2c_send_pmic_cpu_shutdown_cmd(void);
|
||||||
bool i2c_query_ti_charger_bit_7(void);
|
bool i2c_query_ti_charger_bit_7(void);
|
||||||
|
|||||||
211
sept/sept-primary/src/pinmux.h
Normal file
211
sept/sept-primary/src/pinmux.h
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSEE_PINMUX_H
|
||||||
|
#define FUSEE_PINMUX_H
|
||||||
|
|
||||||
|
#define PINMUX_BASE 0x70003000
|
||||||
|
#define MAKE_PINMUX_REG(n) MAKE_REG32(PINMUX_BASE + n)
|
||||||
|
|
||||||
|
#define PINMUX_TRISTATE (1 << 4)
|
||||||
|
#define PINMUX_PARKED (1 << 5)
|
||||||
|
#define PINMUX_INPUT (1 << 6)
|
||||||
|
#define PINMUX_PULL_NONE (0 << 2)
|
||||||
|
#define PINMUX_PULL_DOWN (1 << 2)
|
||||||
|
#define PINMUX_PULL_UP (2 << 2)
|
||||||
|
#define PINMUX_SELECT_FUNCTION0 0
|
||||||
|
#define PINMUX_SELECT_FUNCTION1 1
|
||||||
|
#define PINMUX_SELECT_FUNCTION2 2
|
||||||
|
#define PINMUX_SELECT_FUNCTION3 3
|
||||||
|
#define PINMUX_DRIVE_1X (0 << 13)
|
||||||
|
#define PINMUX_DRIVE_2X (1 << 13)
|
||||||
|
#define PINMUX_DRIVE_3X (2 << 13)
|
||||||
|
#define PINMUX_DRIVE_4X (3 << 13)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t sdmmc1_clk;
|
||||||
|
uint32_t sdmmc1_cmd;
|
||||||
|
uint32_t sdmmc1_dat3;
|
||||||
|
uint32_t sdmmc1_dat2;
|
||||||
|
uint32_t sdmmc1_dat1;
|
||||||
|
uint32_t sdmmc1_dat0;
|
||||||
|
uint32_t _r18;
|
||||||
|
uint32_t sdmmc3_clk;
|
||||||
|
uint32_t sdmmc3_cmd;
|
||||||
|
uint32_t sdmmc3_dat0;
|
||||||
|
uint32_t sdmmc3_dat1;
|
||||||
|
uint32_t sdmmc3_dat2;
|
||||||
|
uint32_t sdmmc3_dat3;
|
||||||
|
uint32_t _r34;
|
||||||
|
uint32_t pex_l0_rst_n;
|
||||||
|
uint32_t pex_l0_clkreq_n;
|
||||||
|
uint32_t pex_wake_n;
|
||||||
|
uint32_t pex_l1_rst_n;
|
||||||
|
uint32_t pex_l1_clkreq_n;
|
||||||
|
uint32_t sata_led_active;
|
||||||
|
uint32_t spi1_mosi;
|
||||||
|
uint32_t spi1_miso;
|
||||||
|
uint32_t spi1_sck;
|
||||||
|
uint32_t spi1_cs0;
|
||||||
|
uint32_t spi1_cs1;
|
||||||
|
uint32_t spi2_mosi;
|
||||||
|
uint32_t spi2_miso;
|
||||||
|
uint32_t spi2_sck;
|
||||||
|
uint32_t spi2_cs0;
|
||||||
|
uint32_t spi2_cs1;
|
||||||
|
uint32_t spi4_mosi;
|
||||||
|
uint32_t spi4_miso;
|
||||||
|
uint32_t spi4_sck;
|
||||||
|
uint32_t spi4_cs0;
|
||||||
|
uint32_t qspi_sck;
|
||||||
|
uint32_t qspi_cs_n;
|
||||||
|
uint32_t qspi_io0;
|
||||||
|
uint32_t qspi_io1;
|
||||||
|
uint32_t qspi_io2;
|
||||||
|
uint32_t qspi_io3;
|
||||||
|
uint32_t _ra0;
|
||||||
|
uint32_t dmic1_clk;
|
||||||
|
uint32_t dmic1_dat;
|
||||||
|
uint32_t dmic2_clk;
|
||||||
|
uint32_t dmic2_dat;
|
||||||
|
uint32_t dmic3_clk;
|
||||||
|
uint32_t dmic3_dat;
|
||||||
|
uint32_t gen1_i2c_scl;
|
||||||
|
uint32_t gen1_i2c_sda;
|
||||||
|
uint32_t gen2_i2c_scl;
|
||||||
|
uint32_t gen2_i2c_sda;
|
||||||
|
uint32_t gen3_i2c_scl;
|
||||||
|
uint32_t gen3_i2c_sda;
|
||||||
|
uint32_t cam_i2c_scl;
|
||||||
|
uint32_t cam_i2c_sda;
|
||||||
|
uint32_t pwr_i2c_scl;
|
||||||
|
uint32_t pwr_i2c_sda;
|
||||||
|
uint32_t uart1_tx;
|
||||||
|
uint32_t uart1_rx;
|
||||||
|
uint32_t uart1_rts;
|
||||||
|
uint32_t uart1_cts;
|
||||||
|
uint32_t uart2_tx;
|
||||||
|
uint32_t uart2_rx;
|
||||||
|
uint32_t uart2_rts;
|
||||||
|
uint32_t uart2_cts;
|
||||||
|
uint32_t uart3_tx;
|
||||||
|
uint32_t uart3_rx;
|
||||||
|
uint32_t uart3_rts;
|
||||||
|
uint32_t uart3_cts;
|
||||||
|
uint32_t uart4_tx;
|
||||||
|
uint32_t uart4_rx;
|
||||||
|
uint32_t uart4_rts;
|
||||||
|
uint32_t uart4_cts;
|
||||||
|
uint32_t dap1_fs;
|
||||||
|
uint32_t dap1_din;
|
||||||
|
uint32_t dap1_dout;
|
||||||
|
uint32_t dap1_sclk;
|
||||||
|
uint32_t dap2_fs;
|
||||||
|
uint32_t dap2_din;
|
||||||
|
uint32_t dap2_dout;
|
||||||
|
uint32_t dap2_sclk;
|
||||||
|
uint32_t dap4_fs;
|
||||||
|
uint32_t dap4_din;
|
||||||
|
uint32_t dap4_dout;
|
||||||
|
uint32_t dap4_sclk;
|
||||||
|
uint32_t cam1_mclk;
|
||||||
|
uint32_t cam2_mclk;
|
||||||
|
uint32_t jtag_rtck;
|
||||||
|
uint32_t clk_32k_in;
|
||||||
|
uint32_t clk_32k_out;
|
||||||
|
uint32_t batt_bcl;
|
||||||
|
uint32_t clk_req;
|
||||||
|
uint32_t cpu_pwr_req;
|
||||||
|
uint32_t pwr_int_n;
|
||||||
|
uint32_t shutdown;
|
||||||
|
uint32_t core_pwr_req;
|
||||||
|
uint32_t aud_mclk;
|
||||||
|
uint32_t dvfs_pwm;
|
||||||
|
uint32_t dvfs_clk;
|
||||||
|
uint32_t gpio_x1_aud;
|
||||||
|
uint32_t gpio_x3_aud;
|
||||||
|
uint32_t pcc7;
|
||||||
|
uint32_t hdmi_cec;
|
||||||
|
uint32_t hdmi_int_dp_hpd;
|
||||||
|
uint32_t spdif_out;
|
||||||
|
uint32_t spdif_in;
|
||||||
|
uint32_t usb_vbus_en0;
|
||||||
|
uint32_t usb_vbus_en1;
|
||||||
|
uint32_t dp_hpd0;
|
||||||
|
uint32_t wifi_en;
|
||||||
|
uint32_t wifi_rst;
|
||||||
|
uint32_t wifi_wake_ap;
|
||||||
|
uint32_t ap_wake_bt;
|
||||||
|
uint32_t bt_rst;
|
||||||
|
uint32_t bt_wake_ap;
|
||||||
|
uint32_t ap_wake_nfc;
|
||||||
|
uint32_t nfc_en;
|
||||||
|
uint32_t nfc_int;
|
||||||
|
uint32_t gps_en;
|
||||||
|
uint32_t gps_rst;
|
||||||
|
uint32_t cam_rst;
|
||||||
|
uint32_t cam_af_en;
|
||||||
|
uint32_t cam_flash_en;
|
||||||
|
uint32_t cam1_pwdn;
|
||||||
|
uint32_t cam2_pwdn;
|
||||||
|
uint32_t cam1_strobe;
|
||||||
|
uint32_t lcd_te;
|
||||||
|
uint32_t lcd_bl_pwm;
|
||||||
|
uint32_t lcd_bl_en;
|
||||||
|
uint32_t lcd_rst;
|
||||||
|
uint32_t lcd_gpio1;
|
||||||
|
uint32_t lcd_gpio2;
|
||||||
|
uint32_t ap_ready;
|
||||||
|
uint32_t touch_rst;
|
||||||
|
uint32_t touch_clk;
|
||||||
|
uint32_t modem_wake_ap;
|
||||||
|
uint32_t touch_int;
|
||||||
|
uint32_t motion_int;
|
||||||
|
uint32_t als_prox_int;
|
||||||
|
uint32_t temp_alert;
|
||||||
|
uint32_t button_power_on;
|
||||||
|
uint32_t button_vol_up;
|
||||||
|
uint32_t button_vol_down;
|
||||||
|
uint32_t button_slide_sw;
|
||||||
|
uint32_t button_home;
|
||||||
|
uint32_t pa6;
|
||||||
|
uint32_t pe6;
|
||||||
|
uint32_t pe7;
|
||||||
|
uint32_t ph6;
|
||||||
|
uint32_t pk0;
|
||||||
|
uint32_t pk1;
|
||||||
|
uint32_t pk2;
|
||||||
|
uint32_t pk3;
|
||||||
|
uint32_t pk4;
|
||||||
|
uint32_t pk5;
|
||||||
|
uint32_t pk6;
|
||||||
|
uint32_t pk7;
|
||||||
|
uint32_t pl0;
|
||||||
|
uint32_t pl1;
|
||||||
|
uint32_t pz0;
|
||||||
|
uint32_t pz1;
|
||||||
|
uint32_t pz2;
|
||||||
|
uint32_t pz3;
|
||||||
|
uint32_t pz4;
|
||||||
|
uint32_t pz5;
|
||||||
|
} tegra_pinmux_t;
|
||||||
|
|
||||||
|
static inline volatile tegra_pinmux_t *pinmux_get_regs(void)
|
||||||
|
{
|
||||||
|
return (volatile tegra_pinmux_t *)PINMUX_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user