new ram timings

This commit is contained in:
souldbminersmwc
2025-08-23 17:04:38 -04:00
parent 96d31c5345
commit 027f2cd06c
7 changed files with 191 additions and 495 deletions

View File

@@ -97,7 +97,7 @@ Overclocking Suite for Nintendo Switch consoles running Atmosphere CFW.
3. Compile Atmosphere loader with devkitpro. 3. Compile Atmosphere loader with devkitpro.
4. When compilation is done, uncompress the kip to make it work with configurator: `hactool -t kip1 Atmosphere/stratosphere/loader/out/nintendo_nx_arm64_armv8a/release/loader.kip --uncompress=./loader.kip` 4. When compilation is done, uncompress the kip to make it work with configurator: `hactool -t kip1 loader.kip --uncompress=loader.kip`
</details> </details>

View File

@@ -1,122 +0,0 @@
# Switch OC Suite
[![License: GPL v2](https://img.shields.io/badge/License-GPL_v2-blue.svg)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![Downloads](https://img.shields.io/github/downloads/hanai3Bi/Switch-OC-Suite/total)](https://github.com/hanai3Bi/Switch-OC-Suite/releases)
이 프로젝트는 매우 위험하며 콘솔을 손상시킬 수 있습니다. 따라서 이 프로젝트를 사용하는걸 권장하지 않습니다. 사용할 경우 모든 책임은 본인에게 있습니다.
닌텐도 스위치 Atmosphere 커스텀 펌웨어 용 오버클럭 스위트
[프로젝트 홈페이지](https://hanai3Bi.github.io/Switch-OC-Suite)
**주의 사항: 사용시 모든 책임은 본인에게 있습니다!**
- 일반적으로 오버클럭 시 일부 하드웨어 구성 요소들의 수명이 단축됩니다. sys-clk-oc 에서 안전하지 않은 주파수 활성화 시 **문제나 고장에 대한 모든 책임은 본인에게 있습니다** . 제한 해제에 관한 이슈 등은 무시되거나 답글 없이 닫힐 수 있습니다.
- HorizonOS 의 구조 때문에, 안전하지 않은 RAM 주파수는 파일시스템 손상을 일으킬 수 있습니다. **메모리 오버클럭을 하기 전 반드시 백업을 하세요**
## 기능
- 구형 스위치 (HAC-001)
- CPU / GPU 오버클럭 (안전한 클럭: 1785 / 921 MHz)
- 안전하지 않은 클럭
- 보드 전력 소모 한계나 전원부 IC 때문
- 2091 / 998 MHz 까지 클럭 해제 가능
- [README for sys-clk-OC](https://github.com/hanai3Bi/Switch-OC-Suite/blob/master/Source/sys-clk-OC/README.md) 참조
- 메모리 오버클럭 (안전한 클럭: 1862.4 MHz)
- 신형 스위치 (HAC-001-01, HDH-001, HEG-001)
- CPU / GPU 오버클럭 (안전한 클럭: 1963 / 998 MHz)
- 안전하지 않은 클럭
- 보드 전력 소모 한계나 전원부 IC 때문
- 2295 / 1267 MHz 까지 클럭 해제 가능
- [README for sys-clk-OC](https://github.com/hanai3Bi/Switch-OC-Suite/blob/master/Source/sys-clk-OC/README.md) 참조
- 메모리 오버클럭 (안전한 클럭: 1996.8 MHz)
- 수정된 sys-clk 와 ReverseNX-RT
- 자동 CPU 부스트
- 게임 로딩 속도 향상 목적
- CPU 코어#3 (시스템 코어)가 과부하시 CPU 부스트 (1785 MHz) 활성화 (주로 I/O 작업).
- 충전기 연결시나 거버너 활성화 했을때만 가능
- 이 기능은 구형 스위치에서, 특히 높은 GPU 주파수나 거버너랑 같이 사용시, 안전하지 않음.
- CPU & GPU 주파수 거버너 (실험적 기능)
- 부하에 따라 주파수를 조정함. 전력 소비를 줄일 수 있지만 렉을 유발할 수 있음. 타이틀 별로 끌 수 있음.
- 신형 스위치에서 프로필의 CPU 주파수를 1020Mhz 보다 높은 값으로 설정 시, 최소 스케일링 주파수는 1020Mhz로 설정됨.
- 충전 전류 (100 mA - 2000 mA) 와 충전 제한 (20% - 100%) 설정
- 충전 제한을 장기간 사용시 배터리 수치가 부정확해 질 수 있음. 완충, 완방 시 재보정에 도움이 될 수 있음. 또는 [battery_desync_fix_nx](https://github.com/CTCaer/battery_desync_fix_nx) 를 사용.
- 글로벌 프로필
- 더미 타이틀 아이디 지정 `0xA111111111111111`.
- 우선 순위: "Temp overrides" > "Application profile" > "Global profile" > "System default".
- ReverseNX 모드 동기화
- ReverseNX (-RT) 에서 모드 변경 후 클럭 변경 불필요
- **[System Settings (옵션)](https://github.com/hanai3Bi/Switch-OC-Suite/blob/master/system_settings.md)**
## 설치 방법
1. 최신 [릴리즈](https://github.com/hanai3Bi/Switch-OC-Suite/releases) 파일을 다운로드 한다.
2. `SdOut` 폴더 안의 모든 파일들을 SD카드의 최상단에 복사한다.
3. Atmosphere 버전에 맞는 `x.x.x_loader.kip` 파일을 `loader.kip` 으로 이름을 변경한 후, `/atmosphere/kips/` 로 이동 시킨다.
4. 맞춤 설정 [온라인 loader configurator](https://hanai3Bi.github.io/Switch-OC-Suite/#config):
<details>
| Defaults | Mariko | Erista |
| ---------- | ------------- | ------------- |
| CPU OC | 2295 MHz Max | 2091 MHz Max |
| CPU Boost | 1785 MHz | N/A |
| CPU Volt | 1235 mV Max | 1235 mV Max |
| GPU OC | 1267 MHz Max | N/A |
| RAM OC | 1996 MHz Max | 1862 MHz Max |
| RAM Volt | Disabled | Disabled |
| RAM Timing | Auto-Adjusted | Auto-Adjusted |
| CPU UV | Disabled | N/A |
| GPU UV | Disabled | N/A |
</details>
5. Hekate 부트로더 전용
- `bootloader/hekate_ipl.ini`을 연 후, boot entry 항목에 `kip1=atmosphere/kips/loader.kip` 를 추가한다.
## AIO 를 통해 업데이트 하기
1. custom_packs.json 파일을 다운로드 한 후 /config/aio-switch-updater/custom_packs.json 에 복사한다.
2. AIO Switch Updater 를 실행한 후 커스텀 다운로드 탭으로 이동한다.
3. Switch-OC-Suite 를 선택한 후 계속하기를 누른다.
## 빌드 방법
<details>
Grab necessary patches from the repo, then compile sys-clk, ReverseNX-RT and Atmosphere loader with devkitpro.
Before compiling Atmosphere loader, run `patch.py` in `Atmosphere/stratosphere/loader/source/` to insert oc module into loader sysmodule.
When compilation is done, uncompress the kip to make it work with configurator: `hactool -t kip1 Atmosphere/stratosphere/loader/out/nintendo_nx_arm64_armv8a/release/loader.kip --uncompress=./loader.kip`
</details>
## 크레딧
- CTCaer for [Hekate-ipl](https://github.com/CTCaer/hekate) bootloader, RE and hardware research
- [devkitPro](https://devkitpro.org/) for All-In-One homebrew toolchains
- masagrator for [ReverseNX-RT](https://github.com/masagrator/ReverseNX-RT) and info on BatteryChargeInfoFields in psm module
- Nvidia for [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual)
- RetroNX team for [sys-clk](https://github.com/retronx-team/sys-clk)
- SciresM and Reswitched Team for the state-of-the-art [Atmosphere](https://github.com/Atmosphere-NX/Atmosphere) CFW of Switch
- Switchbrew [wiki](http://switchbrew.org/wiki/) for Switch in-depth info
- Switchroot for their [modified L4T kernel and device tree](https://gitlab.com/switchroot/kernel)
- ZatchyCatGames for RE and original OC loader patches for Atmosphere
- KazushiMe for [Switch-OC-Suite](https://github.com/KazushiMe/Switch-OC-Suite)

View File

@@ -97,19 +97,46 @@ volatile CustomizeTable C = {
.marikoEmcDvbShift = 0, .marikoEmcDvbShift = 0,
.ramTimingPresetOne = 0, .BL = 16,
.tRFCpb = 140,
.tRFCab = 280,
.tRAS = 42,
.tRPpb = 18,
.tRPab = 21,
.tRC = 60,
.ramTimingPresetTwo = 0, .tDQSCK_min = 1.5,
.tDQSCK_max = 3.5,
.tWPRE = 1.8,
.tRPST = 0.4,
.tDQSS_max = 1.25,
.tDQS2DQ_max = 0.8,
.tDQSQ = 0.18,
.ramTimingPresetThree = 0, .tWTR = 10,
.tRTP = 7.5,
.tWR = 18,
.tR2REF = 25.5,
.ramTimingPresetFour = 0, .tRCD = 18,
.tRRD = 10,
.tREFpb = 488,
.ramTimingPresetFive = 0, .tXP = 10,
.tCMDCKE = 1.75,
.tMRWCKEL = 14,
.tCKELCS = 5,
.tCSCKEH = 1.75,
.tXSR = 287.5,
.tCKE = 7.5,
.ramTimingPresetSix = 0, .tSR = 15,
.tFAW = 40,
.ramTimingPresetSeven = 0, .tCKCKEH = 1.75,
.WL = 14,
.RL = 32,
.marikoGpuVoltArray = {610, 610, 610, 610, 610, 610, 610, 610, 610, 610, 620, 640, 675, 710, 735, 785, 815}, .marikoGpuVoltArray = {610, 610, 610, 610, 610, 610, 610, 610, 610, 610, 620, 640, 675, 710, 735, 785, 815},

View File

@@ -59,14 +59,50 @@ typedef struct CustomizeTable {
u32 commonGpuVoltOffset; u32 commonGpuVoltOffset;
// advanced config // advanced config
u32 marikoEmcDvbShift; u32 marikoEmcDvbShift;
u32 ramTimingPresetOne;
u32 ramTimingPresetTwo;
u32 ramTimingPresetThree;
u32 ramTimingPresetFour;
u32 ramTimingPresetFive;
u32 ramTimingPresetSix;
u32 ramTimingPresetSeven;
// //
const uint32_t BL;
const uint32_t tRFCpb;
const uint32_t tRFCab;
const uint32_t tRAS;
const uint32_t tRPpb;
const uint32_t tRPab;
const uint32_t tRC;
const double tDQSCK_min;
const double tDQSCK_max;
const double tWPRE;
const double tRPST;
const double tDQSS_max;
const double tDQS2DQ_max;
const double tDQSQ;
const uint32_t tWTR;
const double tRTP;
const uint32_t tWR;
const double tR2REF;
const uint32_t tRCD;
const double tRRD;
const uint32_t tREFpb;
const double tXP;
const double tCMDCKE;
const uint32_t tMRWCKEL;
const double tCKELCS;
const double tCSCKEH;
const double tXSR;
const double tCKE;
const uint32_t tSR;
const uint32_t tFAW;
const double tCKCKEH;
const double tCK_avg;
const uint32_t WL;
const uint32_t RL;
u32 marikoGpuVoltArray[17]; u32 marikoGpuVoltArray[17];
CustomizeCpuDvfsTable eristaCpuDvfsTable; CustomizeCpuDvfsTable eristaCpuDvfsTable;
CustomizeCpuDvfsTable marikoCpuDvfsTable; CustomizeCpuDvfsTable marikoCpuDvfsTable;
@@ -85,5 +121,4 @@ extern volatile CustomizeTable C;
//extern volatile EristaMtcTable EristaMtcTablePlaceholder; //extern volatile EristaMtcTable EristaMtcTablePlaceholder;
//extern volatile MarikoMtcTable MarikoMtcTablePlaceholder; //extern volatile MarikoMtcTable MarikoMtcTablePlaceholder;
} }

View File

@@ -23,213 +23,77 @@
#define MAX(A, B) std::max(A, B) #define MAX(A, B) std::max(A, B)
#define MIN(A, B) std::min(A, B) #define MIN(A, B) std::min(A, B)
#define CEIL(A) std::ceil(A) #define CEIL(A) std::ceil(A)
#define FLOOR(A) std::floor(A) #define FLOOR(A) std::floor(A)
const u8 ramtmarker[4] = {'R', 'A', 'M', 'T'};
//Preset One
const std::array<u32, 6> tRCD_values = {18, 17, 16, 15, 14, 13};
const std::array<u32, 6> tRP_values = {18, 17, 16, 15, 14, 13};
const std::array<u32, 6> tRAS_values = {42, 39, 36, 34, 32, 30};
// Preset Two
const std::array<double, 5> tRRD_values = {10, 7.5, 6, 4, 3};
const std::array<double, 5> tFAW_values = {40, 30, 24, 16, 12};
// Preset Three
const std::array<u32, 6> tWR_values = {18, 15, 15, 12, 12, 8};
const std::array<double, 6> tRTP_values = {7.5, 7.5, 6, 6, 4, 4};
// Preset Four
const std::array<u32, 6> tRFC_values = {140, 120, 100, 80, 70, 60};
// Preset Five
const std::array<u32, 6> tWTR_values = {10, 8, 6, 4, 2, 1};
// Preset Six
const std::array<u32, 5> tREFpb_values = {488, 976, 1952, 3256, 9999};
const u32 TIMING_PRESET_ONE = C.ramTimingPresetOne;
const u32 TIMING_PRESET_TWO = C.ramTimingPresetTwo;
const u32 TIMING_PRESET_THREE = C.ramTimingPresetThree;
const u32 TIMING_PRESET_FOUR = C.ramTimingPresetFour;
const u32 TIMING_PRESET_FIVE = C.ramTimingPresetFive;
const u32 TIMING_PRESET_SIX = C.ramTimingPresetSix;
const u32 TIMING_PRESET_SEVEN = C.ramTimingPresetSeven;
// Burst Length
const u32 BL = 16;
// tRFCpb (refresh cycle time per bank) in ns for 8Gb density
const u32 tRFCpb = !TIMING_PRESET_FOUR ? 140 : tRFC_values[TIMING_PRESET_FOUR-1];
// tRFCab (refresh cycle time all banks) in ns for 8Gb density
const u32 tRFCab = !TIMING_PRESET_FOUR ? 280 : 2*tRFCpb;
// tRAS (row active time) in ns
const u32 tRAS = !TIMING_PRESET_ONE ? 42 : tRAS_values[TIMING_PRESET_ONE-1];
// tRPpb (row precharge time per bank) in ns
const u32 tRPpb = !TIMING_PRESET_ONE ? 18 : tRP_values[TIMING_PRESET_ONE-1];
// tRPab (row precharge time all banks) in ns
const u32 tRPab = !TIMING_PRESET_ONE ? 21 : tRPpb + 3;
// tRC (ACTIVATE-ACTIVATE command period same bank) in ns
const u32 tRC = tRPpb + tRAS;
// DQS output access time from CK_t/CK_c
const double tDQSCK_min = 1.5;
// DQS output access time from CK_t/CK_c
const double tDQSCK_max = 3.5;
// Write preamble (tCK)
const double tWPRE = 1.8;
// Read postamble (tCK)
const double tRPST = 0.4;
// WRITE command to first DQS transition(max) (tCK)
const double tDQSS_max = 1.25;
// DQ-to-DQS offset(max) (ns)
const double tDQS2DQ_max = 0.8;
// DQS_t, DQS_c to DQ skew total, per group, per access (DBI Disabled)
const double tDQSQ = 0.18;
// Write-to-Read delay
const u32 tWTR = !TIMING_PRESET_FIVE ? 10 : tWTR_values[TIMING_PRESET_FIVE-1];
// Internal READ-to-PRE-CHARGE command delay in ns
const double tRTP = !TIMING_PRESET_THREE ? 7.5 : tRTP_values[TIMING_PRESET_THREE-1];
// write recovery time
const u32 tWR = !TIMING_PRESET_THREE ? 18 : tWR_values[TIMING_PRESET_THREE-1];
// Read to refresh delay
const u32 tR2REF = tRTP + tRPpb;
// tRCD (RAS-CAS delay) in ns
const u32 tRCD = !TIMING_PRESET_ONE ? 18 : tRCD_values[TIMING_PRESET_ONE-1];
// tRRD (Active bank-A to Active bank-B) in ns
const double tRRD = !TIMING_PRESET_TWO ? 10. : tRRD_values[TIMING_PRESET_TWO-1];
// tREFpb (average refresh interval per bank) in ns for 8Gb density
const u32 tREFpb = !TIMING_PRESET_SIX ? 488 : tREFpb_values[TIMING_PRESET_SIX-1];
// tREFab (average refresh interval all 8 banks) in ns for 8Gb density
// const u32 tREFab = tREFpb * 8;
// tPDEX2WR, tPDEX2RD (timing delay from exiting powerdown mode to a write/read command) in ns
// const u32 tPDEX2 = 10;
// Exit power-down to next valid command delay
const double tXP = 10;
// Delay from valid command to CKE input LOW in ns
const double tCMDCKE = 1.75;
// tACT2PDEN (timing delay from an activate, MRS or EMRS command to power-down entry) in ns
// Valid clock and CS requirement after CKE input LOW after MRW command
const u32 tMRWCKEL = 14;
// Valid CS requirement after CKE input LOW
const double tCKELCS = 5;
// Valid CS requirement before CKE input HIGH
const double tCSCKEH = 1.75;
// tXSR (SELF REFRESH exit to next valid command delay) in ns
const double tXSR = tRFCab + 7.5;
// tCKE (minimum pulse width(HIGH and LOW pulse width)) in ns
const double tCKE = 7.5;
// Minimum self refresh time (entry to exit)
const u32 tSR = 15;
// tFAW (Four-bank Activate Window) in ns
const u32 tFAW = !TIMING_PRESET_TWO ? 40 : tFAW_values[TIMING_PRESET_TWO-1];
// Valid Clock requirement before CKE Input HIGH in ns
const double tCKCKEH = 1.75;
// p78 The first valid data is available RL × t CK + t DQSCK + t DQSQ
//const u32 QUSE = RL + CEIL(tDQSCK_min/tCK_avg + tDQSQ);
namespace pcv::erista { namespace pcv::erista {
// tCK_avg (average clock period) in ns // tCK_avg (average clock period) in ns
const double tCK_avg = 1000'000. / C.eristaEmcMaxClock; const double tCK_avg = 1000'000. / C.eristaEmcMaxClock;
// Write Latency
const u32 WL = 14 - 2*TIMING_PRESET_SEVEN;
// Read Latency
const u32 RL = 32 - 4*TIMING_PRESET_SEVEN;
// minimum number of cycles from any read command to any write command, irrespective of bank // minimum number of cycles from any read command to any write command, irrespective of bank
const u32 R2W = CEIL (RL + CEIL(tDQSCK_max/tCK_avg) + BL/2 - WL + tWPRE + FLOOR(tRPST)) + 6; const u32 R2W = CEIL (C.RL + CEIL(C.tDQSCK_max/tCK_avg) + C.BL/2 - C.WL + C.tWPRE + FLOOR(C.tRPST)) + 6;
// Delay Time From WRITE-to-READ // Delay Time From WRITE-to-READ
const u32 W2R = WL + BL/2 + 1 + CEIL(tWTR/tCK_avg) - 6; const u32 W2R = C.WL + C.BL/2 + 1 + CEIL(C.tWTR/tCK_avg) - 6;
// write-to-precharge time for commands to the same bank in cycles // write-to-precharge time for commands to the same bank in cycles
const u32 WTP = WL + BL/2 + 1 + CEIL(tWR/tCK_avg) - 8; const u32 WTP = C.WL + C.BL/2 + 1 + CEIL(C.tWR/tCK_avg) - 8;
// #_of_rows per die for 8Gb density // #_of_rows per die for 8Gb density
const u32 numOfRows = 65536; const u32 numOfRows = 65536;
// {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%] // {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%]
// emc_clk_period = dram_clk / 2; // emc_clk_period = dram_clk / 2;
// 1600 MHz: 5894, but N' set to 6176 (~4.8% margin) // 1600 MHz: 5894, but N' set to 6176 (~4.8% margin)
const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(tREFpb) * C.eristaEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4); const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(C.tREFpb) * C.eristaEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4);
const u32 REFBW = MIN((u32)65536, REFRESH+64); const u32 REFBW = MIN((u32)65536, REFRESH+64);
// Write With Auto Precharge to to Power-Down Entry // Write With Auto Precharge to to Power-Down Entry
const u32 WTPDEN = WTP + 1 + CEIL(tDQSS_max/tCK_avg) + CEIL(tDQS2DQ_max/tCK_avg) + 6; const u32 WTPDEN = WTP + 1 + CEIL(C.tDQSS_max/tCK_avg) + CEIL(C.tDQS2DQ_max/tCK_avg) + 6;
// Additional time after t XP hasexpired until the MRR commandmay be issued // Additional time after t XP hasexpired until the MRR commandmay be issued
const double tMRRI = tRCD + 3 * tCK_avg; const double tMRRI = C.tRCD + 3 * tCK_avg;
// tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns // tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns
const double tPDEX2MRR = tXP + tMRRI; const double tPDEX2MRR = C.tXP + tMRRI;
} }
namespace pcv::mariko { namespace pcv::mariko {
// tCK_avg (average clock period) in ns // tCK_avg (average clock period) in ns
const double tCK_avg = 1000'000. / C.marikoEmcMaxClock; const double tCK_avg = 1000'000. / C.marikoEmcMaxClock;
// Write Latency
const u32 WL = 14 - 2*TIMING_PRESET_SEVEN;
// Read Latency
const u32 RL = 32 - 4*TIMING_PRESET_SEVEN;
// minimum number of cycles from any read command to any write command, irrespective of bank // minimum number of cycles from any read command to any write command, irrespective of bank
const u32 R2W = CEIL (RL + CEIL(tDQSCK_max/tCK_avg) + BL/2 - WL + tWPRE + FLOOR(tRPST)); const u32 R2W = CEIL (C.RL + CEIL(C.tDQSCK_max/tCK_avg) + C.BL/2 - C.WL + C.tWPRE + FLOOR(C.tRPST));
// Delay Time From WRITE-to-READ // Delay Time From WRITE-to-READ
const u32 W2R = WL + BL/2 + 1 + CEIL(tWTR/tCK_avg); const u32 W2R = C.WL + C.BL/2 + 1 + CEIL(C.tWTR/tCK_avg);
// write-to-precharge time for commands to the same bank in cycles // write-to-precharge time for commands to the same bank in cycles
const u32 WTP = WL + BL/2 + 1 + CEIL(tWR/tCK_avg); const u32 WTP = C.WL + C.BL/2 + 1 + CEIL(C.tWR/tCK_avg);
// Read-To-MRW delay // Read-To-MRW delay
const u32 RTM = RL + BL/2 + CEIL(tDQSCK_max/tCK_avg) + FLOOR(tRPST) + CEIL(7.5/tCK_avg); const u32 RTM = C.RL + C.BL/2 + CEIL(C.tDQSCK_max/tCK_avg) + FLOOR(C.tRPST) + CEIL(7.5/tCK_avg);
// Write-To-MRW/MRR delay // Write-To-MRW/MRR delay
const u32 WTM = WL + 1 + BL/2 + CEIL(7.5/tCK_avg); const u32 WTM = C.WL + 1 + C.BL/2 + CEIL(7.5/tCK_avg);
// Read With AP-To-MRW/MRR delay // Read With AP-To-MRW/MRR delay
const u32 RATM = RTM + CEIL(tRTP/tCK_avg) - 8; const u32 RATM = RTM + CEIL(C.tRTP/tCK_avg) - 8;
// Write With AP-To-MRW/MRR delay // Write With AP-To-MRW/MRR delay
const u32 WATM = WTM + CEIL(tWR/tCK_avg); const u32 WATM = WTM + CEIL(C.tWR/tCK_avg);
// #_of_rows per die for 8Gb density // #_of_rows per die for 8Gb density
const u32 numOfRows = 65536; const u32 numOfRows = 65536;
// {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%] // {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%]
// emc_clk_period = dram_clk / 2; // emc_clk_period = dram_clk / 2;
// 1600 MHz: 5894, but N' set to 6176 (~4.8% margin) // 1600 MHz: 5894, but N' set to 6176 (~4.8% margin)
const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(tREFpb) * C.marikoEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4); const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(C.tREFpb) * C.marikoEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4);
const u32 REFBW = MIN((u32)65536, REFRESH+64); const u32 REFBW = MIN((u32)65536, REFRESH+64);
// Write With Auto Precharge to to Power-Down Entry // Write With Auto Precharge to to Power-Down Entry
const u32 WTPDEN = WTP + 1 + CEIL(tDQSS_max/tCK_avg) + CEIL(tDQS2DQ_max/tCK_avg) + 6; const u32 WTPDEN = WTP + 1 + CEIL(C.tDQSS_max/tCK_avg) + CEIL(C.tDQS2DQ_max/tCK_avg) + 6;
// Additional time after t XP hasexpired until the MRR commandmay be issued // Additional time after t XP hasexpired until the MRR commandmay be issued
const double tMRRI = tRCD + 3 * tCK_avg; const double tMRRI = C.tRCD + 3 * tCK_avg;
// tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns // tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns
const double tPDEX2MRR = tXP + tMRRI; const double tPDEX2MRR = C.tXP + tMRRI;
} }
} }

View File

@@ -18,7 +18,7 @@
#include "pcv.hpp" #include "pcv.hpp"
#include "../mtc_timing_value.hpp" #include "../mtc_timing_value.hpp"
#include "../customize.hpp"
namespace ams::ldr::oc::pcv::erista { namespace ams::ldr::oc::pcv::erista {
Result CpuVoltRange(u32* ptr) { Result CpuVoltRange(u32* ptr) {
@@ -85,57 +85,57 @@ void MemMtcTableAutoAdjust(EristaMtcTable* table) {
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) #define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC)); WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(C.tRC));
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab)); WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(C.tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb)); WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(C.tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS)); WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(C.tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb)); WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(C.tRPpb));
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W); WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP)); WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(C.tRTP));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP); WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD)); WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(C.tRRD));
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH); WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4); WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE_CEIL(tXP)); WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE_CEIL(C.tXP));
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(tXP)); WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(C.tXP));
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(tCMDCKE)); WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(C.tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(tMRWCKEL)); WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(C.tMRWCKEL));
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(tCMDCKE)); WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(C.tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN); WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(tCKELCS)); WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(C.tCKELCS));
WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(tCSCKEH)); WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(C.tCSCKEH));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR)); WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe)); WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe)); WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(tCKE)); WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(C.tCKE));
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR)); WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(C.tSR));
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tCKE)); WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(C.tCKE));
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW)); WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(C.tFAW));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab)); WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(C.tRPab));
WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(tCKCKEH)); WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(C.tCKCKEH));
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tCKE)+8); WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(C.tCKE)+8);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW); WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
#define WRITE_PARAM_BURST_MC_REG(TABLE, PARAM, VALUE) TABLE->burst_mc_regs.PARAM = VALUE; #define WRITE_PARAM_BURST_MC_REG(TABLE, PARAM, VALUE) TABLE->burst_mc_regs.PARAM = VALUE;
constexpr u32 MC_ARB_DIV = 4; constexpr u32 MC_ARB_DIV = 4;
constexpr u32 MC_ARB_SFA = 2; constexpr u32 MC_ARB_SFA = 2;
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2; table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(C.tRCD) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA; table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2; table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(C.tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(C.tRRD) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV); table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(C.tRTP) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV); table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
//table->burst_mc_regs.mc_emem_arb_timing_r2r = CEIL(table->burst_regs.emc_rext / MC_ARB_DIV) - 1 + MC_ARB_SFA; //table->burst_mc_regs.mc_emem_arb_timing_r2r = CEIL(table->burst_regs.emc_rext / MC_ARB_DIV) - 1 + MC_ARB_SFA;
//table->burst_mc_regs.mc_emem_arb_timing_w2w = CEIL(table->burst_regs.emc_wext / MC_ARB_DIV) - 1 + MC_ARB_SFA; //table->burst_mc_regs.mc_emem_arb_timing_w2w = CEIL(table->burst_regs.emc_wext / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA; table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA; table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV); table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(C.tRFCpb) / MC_ARB_DIV);
//table->burst_mc_regs.mc_emem_arb_timing_ccdmw = CEIL(tCCDMW / MC_ARB_DIV) -1 + MC_ARB_SFA; //table->burst_mc_regs.mc_emem_arb_timing_ccdmw = CEIL(tCCDMW / MC_ARB_DIV) -1 + MC_ARB_SFA;
} }
@@ -146,69 +146,18 @@ void MemMtcTableCustomAdjust(EristaMtcTable* table) {
constexpr u32 MC_ARB_DIV = 4; constexpr u32 MC_ARB_DIV = 4;
constexpr u32 MC_ARB_SFA = 2; constexpr u32 MC_ARB_SFA = 2;
if (TIMING_PRESET_ONE) { WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(C.tRC));
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC)); WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(C.tRAS));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS)); WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(C.tRPpb));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb)); WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(C.tRPab));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab)); WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV - 2); table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(C.tRCD) / MC_ARB_DIV - 2);
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV - 1); table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV - 1);
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV - 1 + MC_ARB_SFA); table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV - 1 + MC_ARB_SFA);
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV - 2); table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV - 2);
}
if (TIMING_PRESET_TWO) {
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
}
if (TIMING_PRESET_THREE) {
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
}
if (TIMING_PRESET_FOUR) {
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV);
}
if (TIMING_PRESET_FIVE) {
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
}
if (TIMING_PRESET_SIX) {
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
}
if (TIMING_PRESET_SEVEN) {
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
}
u32 DA_TURNS = 0; u32 DA_TURNS = 0;
DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN

View File

@@ -18,6 +18,7 @@
#include "pcv.hpp" #include "pcv.hpp"
#include "../mtc_timing_value.hpp" #include "../mtc_timing_value.hpp"
#include "../customize.hpp"
namespace ams::ldr::oc::pcv::mariko { namespace ams::ldr::oc::pcv::mariko {
@@ -182,44 +183,44 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) #define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC)); WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(C.tRC));
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab)); WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(C.tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb)); WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(C.tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS)); WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(C.tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb)); WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(C.tRPpb));
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W); WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP)); WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(C.tRTP));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP); WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_trtm, RTM); WRITE_PARAM_ALL_REG(table, emc_trtm, RTM);
WRITE_PARAM_ALL_REG(table, emc_twtm, WTM); WRITE_PARAM_ALL_REG(table, emc_twtm, WTM);
WRITE_PARAM_ALL_REG(table, emc_tratm, RATM); WRITE_PARAM_ALL_REG(table, emc_tratm, RATM);
WRITE_PARAM_ALL_REG(table, emc_twatm, WATM); WRITE_PARAM_ALL_REG(table, emc_twatm, WATM);
//WRITE_PARAM_ALL_REG(table, emc_tr2ref, GET_CYCLE_CEIL(tR2REF)); //WRITE_PARAM_ALL_REG(table, emc_tr2ref, GET_CYCLE_CEIL(C.tR2REF));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD)); WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(C.tRRD));
WRITE_PARAM_ALL_REG(table, emc_rext, 26); WRITE_PARAM_ALL_REG(table, emc_rext, 26);
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH); WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4); WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE_CEIL(tXP)); WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE_CEIL(C.tXP));
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(tXP)); WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(C.tXP));
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(tCMDCKE)); WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(C.tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(tMRWCKEL)); WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(C.tMRWCKEL));
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(tCMDCKE)); WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(C.tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN); WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(tCKELCS)); WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(C.tCKELCS));
//WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(tCSCKEH)); //WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(C.tCSCKEH));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR)); WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe)); WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe)); WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(tCKE) + 1); WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(C.tCKE) + 1);
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR)); WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(C.tSR));
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tCKE)); WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(C.tCKE));
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW)); WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(C.tFAW));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab)); WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(C.tRPab));
//WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(tCKCKEH)); //WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(C.tCKCKEH));
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tCKE) + 8); WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(C.tCKE) + 8);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW); WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
ADJUST_PARAM_ALL_REG(table, emc_dyn_self_ref_control, ref); ADJUST_PARAM_ALL_REG(table, emc_dyn_self_ref_control, ref);
@@ -238,18 +239,18 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
constexpr u32 MC_ARB_SFA = 2; constexpr u32 MC_ARB_SFA = 2;
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_cfg, C.marikoEmcMaxClock / (33.3 * 1000) / MC_ARB_DIV); //CYCLES_PER_UPDATE: The number of mcclk cycles per deadline timer update WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_cfg, C.marikoEmcMaxClock / (33.3 * 1000) / MC_ARB_DIV); //CYCLES_PER_UPDATE: The number of mcclk cycles per deadline timer update
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rcd, CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rcd, CEIL(GET_CYCLE_CEIL(C.tRCD) / MC_ARB_DIV) - 2)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rp, CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rp, CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rc, CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rc, CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_ras, CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_ras, CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV) - 2)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_faw, CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_faw, CEIL(GET_CYCLE_CEIL(C.tFAW) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rrd, CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rrd, CEIL(GET_CYCLE_CEIL(C.tRRD) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rap2pre, CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV)) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rap2pre, CEIL(GET_CYCLE_CEIL(C.tRTP) / MC_ARB_DIV))
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_wap2pre, CEIL((WTP) / MC_ARB_DIV)) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_wap2pre, CEIL((WTP) / MC_ARB_DIV))
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_r2r, CEIL(table->burst_regs.emc_rext / MC_ARB_DIV) - 1 + MC_ARB_SFA) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_r2r, CEIL(table->burst_regs.emc_rext / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_r2w, CEIL((R2W) / MC_ARB_DIV) - 1 + MC_ARB_SFA) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_r2w, CEIL((R2W) / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_w2r, CEIL((W2R) / MC_ARB_DIV) - 1 + MC_ARB_SFA) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_w2r, CEIL((W2R) / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rfcpb, CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV)) WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rfcpb, CEIL(GET_CYCLE_CEIL(C.tRFCpb) / MC_ARB_DIV))
u32 DA_TURNS = 0; u32 DA_TURNS = 0;
DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN
@@ -318,8 +319,8 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
table->pllmb_ss_ctrl1 = 0x0b55fe01; table->pllmb_ss_ctrl1 = 0x0b55fe01;
table->pllmb_ss_ctrl2 = 0x10170b55; table->pllmb_ss_ctrl2 = 0x10170b55;
table->dram_timings.t_rp = tRPpb; table->dram_timings.t_rp = C.tRPpb;
table->dram_timings.t_rfc = tRFCab; table->dram_timings.t_rfc = C.tRFCab;
//table->dram_timings.rl = 32; //table->dram_timings.rl = 32;
table->emc_cfg_2 = 0x0011083d; table->emc_cfg_2 = 0x0011083d;
@@ -332,76 +333,18 @@ void MemMtcTableCustomAdjust(MarikoMtcTable* table) {
constexpr u32 MC_ARB_DIV = 4; constexpr u32 MC_ARB_DIV = 4;
constexpr u32 MC_ARB_SFA = 2; constexpr u32 MC_ARB_SFA = 2;
if (TIMING_PRESET_ONE) { WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(C.tRC));
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC)); WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(C.tRAS));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS)); WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(C.tRPpb));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb)); WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(C.tRPab));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab)); WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_pdex2mrr,GET_CYCLE_CEIL(tPDEX2MRR));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr,GET_CYCLE_CEIL(tPDEX2MRR));
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2; table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(C.tRCD) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA; table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2; table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV) - 2;
}
if (TIMING_PRESET_TWO) {
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
}
if (TIMING_PRESET_THREE) {
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_tratm, RATM);
WRITE_PARAM_ALL_REG(table, emc_twatm, WATM);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
}
if (TIMING_PRESET_FOUR) {
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV);
}
if (TIMING_PRESET_FIVE) {
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
}
if (TIMING_PRESET_SIX) {
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
}
if (TIMING_PRESET_SEVEN) {
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_trtm, RTM);
WRITE_PARAM_ALL_REG(table, emc_twtm, WTM);
WRITE_PARAM_ALL_REG(table, emc_tratm, RATM);
WRITE_PARAM_ALL_REG(table, emc_twatm, WATM);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
}
u32 DA_TURNS = 0; u32 DA_TURNS = 0;
DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN