bpmpfw: cleanup makefile and split hpp/cpp

This commit is contained in:
souldbminersmwc committed 2026-08-27 18:57:15 -04:00
1 parent e5240d835f
commit 3352dffc39
15 files changed
+464 -266

No files matched your search

+6 -1
View File
@@ -39,18 +39,23 @@ all: $(BIN_TARGET)
$(BIN_TARGET): $(BUILDDIR)/$(TARGET).elf $(BIN_TARGET): $(BUILDDIR)/$(TARGET).elf
@mkdir -p $(OUTPUTDIR) @mkdir -p $(OUTPUTDIR)
$(OBJCOPY) -S -O binary $< $@ @echo "bpmpfw.bin"
@$(OBJCOPY) -S -O binary $< $@
$(BUILDDIR)/$(TARGET).elf: $(OBJS) $(BUILDDIR)/$(TARGET).elf: $(OBJS)
@echo "linking $(TARGET).elf"
@$(CXX) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@ @$(CXX) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.cpp | $(BUILDDIR) $(BUILDDIR)/%.o: $(SOURCEDIR)/%.cpp | $(BUILDDIR)
@echo "$(notdir $<)"
@$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@ @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@
$(BUILDDIR)/libc/%.o: $(LIBCDIR)/src/%.c | $(BUILDDIR)/libc $(BUILDDIR)/libc/%.o: $(LIBCDIR)/src/%.c | $(BUILDDIR)/libc
@echo "$(notdir $<)"
@$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ @$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.s | $(BUILDDIR) $(BUILDDIR)/%.o: $(SOURCEDIR)/%.s | $(BUILDDIR)
@echo "$(notdir $<)"
@$(CXX) $(ASFLAGS) $(INCLUDE) -c $< -o $@ @$(CXX) $(ASFLAGS) $(INCLUDE) -c $< -o $@
$(BUILDDIR): $(BUILDDIR):
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
*
* 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 "actmon.hpp"
namespace actmon {
u32 DevReg(ActmonDev dev, u32 off) {
return ActmonDevBase + (static_cast<u32>(dev) * ActmonDevSize) + off;
}
void EnableDev(ActmonDev dev, u32 freqKhz, u32 weight) {
MMIO32(DevReg(dev, DevInitAvg)) = freqKhz * ActmonPeriodMs / 2;
MMIO32(DevReg(dev, DevCountWeight)) = weight;
MMIO32(DevReg(dev, DevCtrl)) = ActmonDevCtrlEnb | ActmonDevCtrlEnbPeriodic | ActmonDevCtrlKVal3;
}
void Init() {
const u32 emcFreqKhz = static_cast<u32>(freq::MeasurePtoFreqHz(freq::ClkPtoEmc, 1) / 1000);
if (!(MMIO32(ActmonBase + ActmonGlbStatus) & ActmonMcallMonAct)) {
MMIO32(ActmonBase + ActmonGlbPeriodCtrl) = (ActmonPeriodMs - 1) & 0xFF;
EnableDev(DevMcAll, emcFreqKhz, 256 * 4);
}
if (!(MMIO32(ActmonBase + ActmonGlbStatus) & ActmonMccpuMonAct)) {
EnableDev(DevMcCpu, emcFreqKhz, 256 * 4);
}
}
void Update(HocClkBpmpSharedInfo &info) {
const u32 emcFreqKhz = info.freqMem;
if (emcFreqKhz == 0) {
return;
}
const u32 avgAll = MMIO32(DevReg(DevMcAll, DevAvgCount));
const u32 avgCpu = MMIO32(DevReg(DevMcCpu, DevAvgCount));
// Get 1000 -> 100.0.
info.emcLoadAll = static_cast<u32>((static_cast<u64>(avgAll) * 10 * 100) / (emcFreqKhz * ActmonPeriodMs));
info.emcLoadCpu = static_cast<u32>((static_cast<u64>(avgCpu) * 10 * 100) / (emcFreqKhz * ActmonPeriodMs));
info.emcBwAll = static_cast<u32>((static_cast<u64>(emcFreqKhz) * 16 * info.emcLoadAll) / 1000000);
info.emcBwCpu = static_cast<u32>((static_cast<u64>(emcFreqKhz) * 16 * info.emcLoadCpu) / 1000000);
// Not 100% accurate but should be enough.
info.emcBwGpu = (info.emcBwAll > info.emcBwCpu) ? (info.emcBwAll - info.emcBwCpu) : 0;
}
} // namespace actmon
+4 -39
View File
@@ -53,47 +53,12 @@ namespace actmon {
constexpr u32 DevCountWeight = 0x18; constexpr u32 DevCountWeight = 0x18;
constexpr u32 DevAvgCount = 0x20; constexpr u32 DevAvgCount = 0x20;
inline u32 DevReg(ActmonDev dev, u32 off) { u32 DevReg(ActmonDev dev, u32 off);
return ActmonDevBase + (static_cast<u32>(dev) * ActmonDevSize) + off;
}
inline void EnableDev(ActmonDev dev, u32 freqKhz, u32 weight) { void EnableDev(ActmonDev dev, u32 freqKhz, u32 weight);
MMIO32(DevReg(dev, DevInitAvg)) = freqKhz * ActmonPeriodMs / 2;
MMIO32(DevReg(dev, DevCountWeight)) = weight;
MMIO32(DevReg(dev, DevCtrl)) = ActmonDevCtrlEnb | ActmonDevCtrlEnbPeriodic | ActmonDevCtrlKVal3;
}
inline void Init() { void Init();
const u32 emcFreqKhz = static_cast<u32>(freq::MeasurePtoFreqHz(freq::ClkPtoEmc, 1) / 1000);
if (!(MMIO32(ActmonBase + ActmonGlbStatus) & ActmonMcallMonAct)) { void Update(HocClkBpmpSharedInfo &info);
MMIO32(ActmonBase + ActmonGlbPeriodCtrl) = (ActmonPeriodMs - 1) & 0xFF;
EnableDev(DevMcAll, emcFreqKhz, 256 * 4);
}
if (!(MMIO32(ActmonBase + ActmonGlbStatus) & ActmonMccpuMonAct)) {
EnableDev(DevMcCpu, emcFreqKhz, 256 * 4);
}
}
inline void Update(HocClkBpmpSharedInfo &info) {
const u32 emcFreqKhz = info.freqMem;
if (emcFreqKhz == 0) {
return;
}
const u32 avgAll = MMIO32(DevReg(DevMcAll, DevAvgCount));
const u32 avgCpu = MMIO32(DevReg(DevMcCpu, DevAvgCount));
// Get 1000 -> 100.0.
info.emcLoadAll = static_cast<u32>((static_cast<u64>(avgAll) * 10 * 100) / (emcFreqKhz * ActmonPeriodMs));
info.emcLoadCpu = static_cast<u32>((static_cast<u64>(avgCpu) * 10 * 100) / (emcFreqKhz * ActmonPeriodMs));
info.emcBwAll = static_cast<u32>((static_cast<u64>(emcFreqKhz) * 16 * info.emcLoadAll) / 1000000);
info.emcBwCpu = static_cast<u32>((static_cast<u64>(emcFreqKhz) * 16 * info.emcLoadCpu) / 1000000);
// Not 100% accurate but should be enough.
info.emcBwGpu = (info.emcBwAll > info.emcBwCpu) ? (info.emcBwAll - info.emcBwCpu) : 0;
}
} // namespace actmon } // namespace actmon
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2014 - 2017, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
*
* 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 "aotag.hpp"
namespace aotag {
void Update(HocClkBpmpSharedInfo &info) {
const u32 regval = MMIO32(PmcBase + PmcTsensorStatus1);
if (!(regval & Status1ValidBit)) {
info.tempAO = InvalidSentinel;
return;
}
const u32 abs = (regval >> Status1AbsShift) & Status1AbsMask;
const bool frac = (regval & Status1FracBit) != 0;
const bool negative = (regval & Status1SignBit) != 0;
s32 temp = static_cast<s32>(abs) * 1000 + (frac ? 500 : 0);
if (negative) {
temp = -temp;
}
info.tempAO = temp;
}
} // namespace aotag
+1 -19
View File
@@ -34,24 +34,6 @@ namespace aotag {
constexpr s32 InvalidSentinel = -125; constexpr s32 InvalidSentinel = -125;
inline void Update(HocClkBpmpSharedInfo &info) { void Update(HocClkBpmpSharedInfo &info);
const u32 regval = MMIO32(PmcBase + PmcTsensorStatus1);
if (!(regval & Status1ValidBit)) {
info.tempAO = InvalidSentinel;
return;
}
const u32 abs = (regval >> Status1AbsShift) & Status1AbsMask;
const bool frac = (regval & Status1FracBit) != 0;
const bool negative = (regval & Status1SignBit) != 0;
s32 temp = static_cast<s32>(abs) * 1000 + (frac ? 500 : 0);
if (negative) {
temp = -temp;
}
info.tempAO = temp;
}
} // namespace aotag } // namespace aotag
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2019-2025 CTCaer
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
*
* 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 "bpmp_mmu.hpp"
namespace bpmpMmu {
u32 AlignUp(u32 x, u32 a) {
return (x + a - 1) & ~(a - 1);
}
u32 AlignDown(u32 x, u32 a) {
return x & ~(a - 1);
}
void Maintenance(u32 op, bool force) {
if (!force && !(MMIO32(CacheBase + CacheConfig) & CfgEnableCache)) {
return;
}
MMIO32(CacheBase + IntClear) = IntMaintDone;
// Blocking operation.
MMIO32(CacheBase + MaintReq) = MaintReqWayBitmapAll | op;
while (!(MMIO32(CacheBase + IntRawEvent) & IntMaintDone))
;
MMIO32(CacheBase + IntClear) = MMIO32(CacheBase + IntRawEvent);
}
void SetEntry(u32 idx, const MmuEntry &entry) {
MMIO32(ShadowEntryBase + sizeof(u32) * 4 * idx + 0x0) = AlignUp(entry.startAddr, CacheLineSize);
MMIO32(ShadowEntryBase + sizeof(u32) * 4 * idx + 0x4) = AlignDown(entry.endAddr, CacheLineSize);
MMIO32(ShadowEntryBase + sizeof(u32) * 4 * idx + 0x8) = entry.attr;
MMIO32(CacheBase + MmuShadowCopyMask) |= (1u << idx);
}
void Enable() {
if (MMIO32(CacheBase + CacheConfig) & CfgEnableCache) {
return;
}
// Init BPMP MMU.
MMIO32(CacheBase + MmuCmd) = MmuCmdInit;
MMIO32(CacheBase + MmuFallbackEntry) = MmuEnRead | MmuEnWrite | MmuEnExec; // RWX for non-defined regions.
MMIO32(CacheBase + MmuCfg) = MmuCfgSeqEn | MmuCfgTlbEn | MmuCfgAbortStoreLast;
// Init BPMP MMU entries.
MMIO32(CacheBase + MmuShadowCopyMask) = 0;
for (u32 idx = 0; idx < sizeof(Entries) / sizeof(Entries[0]); idx++) {
SetEntry(idx, Entries[idx]);
}
MMIO32(CacheBase + MmuCmd) = MmuCmdCopyShadow;
// Invalidate cache.
Maintenance(MaintInvalidWay, true);
// Enable cache.
MMIO32(CacheBase + CacheConfig) = CfgEnableCache | CfgForceWriteThrough |
(TagModeParallel << CfgMmuTagModeShift) | CfgTagChkAbrtOnErr;
// HW bug. Invalidate cache again.
Maintenance(MaintInvalidWay, false);
}
void Disable() {
if (!(MMIO32(CacheBase + CacheConfig) & CfgEnableCache)) {
return;
}
// Clean and invalidate cache.
Maintenance(MaintCleanInvalidWay, false);
// Disable cache.
MMIO32(CacheBase + CacheConfig) = 0;
}
} // namespace bpmpMmu
+6 -67
View File
@@ -77,76 +77,15 @@ namespace bpmpMmu {
{ IramBase, IramEnd, MmuEnRead | MmuEnWrite | MmuEnExec | MmuEnCached }, { IramBase, IramEnd, MmuEnRead | MmuEnWrite | MmuEnExec | MmuEnCached },
}; };
inline u32 AlignUp(u32 x, u32 a) { u32 AlignUp(u32 x, u32 a);
return (x + a - 1) & ~(a - 1); u32 AlignDown(u32 x, u32 a);
}
inline u32 AlignDown(u32 x, u32 a) {
return x & ~(a - 1);
}
inline void Maintenance(u32 op, bool force) { void Maintenance(u32 op, bool force);
if (!force && !(MMIO32(CacheBase + CacheConfig) & CfgEnableCache)) {
return;
}
MMIO32(CacheBase + IntClear) = IntMaintDone; void SetEntry(u32 idx, const MmuEntry &entry);
// Blocking operation. void Enable();
MMIO32(CacheBase + MaintReq) = MaintReqWayBitmapAll | op;
while (!(MMIO32(CacheBase + IntRawEvent) & IntMaintDone)) void Disable();
;
MMIO32(CacheBase + IntClear) = MMIO32(CacheBase + IntRawEvent);
}
inline void SetEntry(u32 idx, const MmuEntry &entry) {
MMIO32(ShadowEntryBase + sizeof(u32) * 4 * idx + 0x0) = AlignUp(entry.startAddr, CacheLineSize);
MMIO32(ShadowEntryBase + sizeof(u32) * 4 * idx + 0x4) = AlignDown(entry.endAddr, CacheLineSize);
MMIO32(ShadowEntryBase + sizeof(u32) * 4 * idx + 0x8) = entry.attr;
MMIO32(CacheBase + MmuShadowCopyMask) |= (1u << idx);
}
inline void Enable() {
if (MMIO32(CacheBase + CacheConfig) & CfgEnableCache) {
return;
}
// Init BPMP MMU.
MMIO32(CacheBase + MmuCmd) = MmuCmdInit;
MMIO32(CacheBase + MmuFallbackEntry) = MmuEnRead | MmuEnWrite | MmuEnExec; // RWX for non-defined regions.
MMIO32(CacheBase + MmuCfg) = MmuCfgSeqEn | MmuCfgTlbEn | MmuCfgAbortStoreLast;
// Init BPMP MMU entries.
MMIO32(CacheBase + MmuShadowCopyMask) = 0;
for (u32 idx = 0; idx < sizeof(Entries) / sizeof(Entries[0]); idx++) {
SetEntry(idx, Entries[idx]);
}
MMIO32(CacheBase + MmuCmd) = MmuCmdCopyShadow;
// Invalidate cache.
Maintenance(MaintInvalidWay, true);
// Enable cache.
MMIO32(CacheBase + CacheConfig) = CfgEnableCache | CfgForceWriteThrough |
(TagModeParallel << CfgMmuTagModeShift) | CfgTagChkAbrtOnErr;
// HW bug. Invalidate cache again.
Maintenance(MaintInvalidWay, false);
}
inline void Disable() {
if (!(MMIO32(CacheBase + CacheConfig) & CfgEnableCache)) {
return;
}
// Clean and invalidate cache.
Maintenance(MaintCleanInvalidWay, false);
// Disable cache.
MMIO32(CacheBase + CacheConfig) = 0;
}
} // namespace bpmpMmu } // namespace bpmpMmu
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
*
* 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 "freq.hpp"
namespace freq {
u64 MeasurePtoFreqHz(u32 srcId, u32 multiplier) {
constexpr u32 win = 16;
constexpr u32 osc = 32768;
const u32 val = (srcId << PtoSrcSelShift) | PtoDivSelDiv1 | PtoClkEnable | (win - 1);
MMIO32(CarBase + CarPtoClkCntCntl) = val;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep(2);
MMIO32(CarBase + CarPtoClkCntCntl) = val | PtoCntRst;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep(2);
MMIO32(CarBase + CarPtoClkCntCntl) = val;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep(2);
MMIO32(CarBase + CarPtoClkCntCntl) = val | PtoCntEn;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep((1000000u * win / osc) + 12 + 2); // 502us
while (MMIO32(CarBase + CarPtoClkCntStatus) & PtoClkCntBusy)
;
const u32 cnt = MMIO32(CarBase + CarPtoClkCntStatus) & PtoClkCntMask;
MMIO32(CarBase + CarPtoClkCntCntl) = 0;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep(2);
return (static_cast<u64>(cnt) * multiplier * osc) / win;
}
void Update(HocClkBpmpSharedInfo &info) {
info.freqMem = static_cast<u32>(MeasurePtoFreqHz(ClkPtoEmc, 1) / 1000);
info.freqCpu = static_cast<u32>(MeasurePtoFreqHz(ClkPtoCclkGDiv2, 2) / 1000);
}
} // namespace freq
+2 -37
View File
@@ -37,43 +37,8 @@ namespace freq {
constexpr u32 ClkPtoCclkGDiv2 = 0x13; constexpr u32 ClkPtoCclkGDiv2 = 0x13;
constexpr u32 ClkPtoEmc = 0x24; constexpr u32 ClkPtoEmc = 0x24;
inline u64 MeasurePtoFreqHz(u32 srcId, u32 multiplier) { u64 MeasurePtoFreqHz(u32 srcId, u32 multiplier);
constexpr u32 win = 16;
constexpr u32 osc = 32768;
const u32 val = (srcId << PtoSrcSelShift) | PtoDivSelDiv1 | PtoClkEnable | (win - 1); void Update(HocClkBpmpSharedInfo &info);
MMIO32(CarBase + CarPtoClkCntCntl) = val;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep(2);
MMIO32(CarBase + CarPtoClkCntCntl) = val | PtoCntRst;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep(2);
MMIO32(CarBase + CarPtoClkCntCntl) = val;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep(2);
MMIO32(CarBase + CarPtoClkCntCntl) = val | PtoCntEn;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep((1000000u * win / osc) + 12 + 2); // 502us
while (MMIO32(CarBase + CarPtoClkCntStatus) & PtoClkCntBusy)
;
const u32 cnt = MMIO32(CarBase + CarPtoClkCntStatus) & PtoClkCntMask;
MMIO32(CarBase + CarPtoClkCntCntl) = 0;
(void)MMIO32(CarBase + CarPtoClkCntCntl);
usleep(2);
return (static_cast<u64>(cnt) * multiplier * osc) / win;
}
inline void Update(HocClkBpmpSharedInfo &info) {
info.freqMem = static_cast<u32>(MeasurePtoFreqHz(ClkPtoEmc, 1) / 1000);
info.freqCpu = static_cast<u32>(MeasurePtoFreqHz(ClkPtoCclkGDiv2, 2) / 1000);
}
} // namespace freq } // namespace freq
+84
View File
@@ -0,0 +1,84 @@
/*
* Copyright (c) Souldbminer
* Copyright (c) KazushiMe
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
*
* 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 "pllmb.hpp"
namespace pllmb {
u64 MeasurePtoHz(u32 ptoId, u32 divider, u32 preselReg, u32 preselMask) {
u32 preselOrigBit = 0;
if (preselReg) {
u32 val = MMIO32(freq::CarBase + preselReg);
usleep(10);
preselOrigBit = val & preselMask;
val &= ~preselMask;
val |= preselMask;
MMIO32(freq::CarBase + preselReg) = val;
usleep(10);
}
constexpr u32 cycleCount = 16;
const u32 savedCntl = MMIO32(freq::CarBase + freq::CarPtoClkCntCntl);
u32 val = freq::PtoDivSelDiv1 | freq::PtoClkEnable | (cycleCount - 1);
val |= ptoId << freq::PtoSrcSelShift;
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = val;
usleep(10);
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = val | freq::PtoCntRst;
usleep(10);
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = val;
usleep(10);
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = val | freq::PtoCntEn;
usleep(500);
while (MMIO32(freq::CarBase + freq::CarPtoClkCntStatus) & PtoCyclePeriod)
;
u32 cnt = MMIO32(freq::CarBase + freq::CarPtoClkCntStatus) & freq::PtoClkCntMask;
cnt *= divider;
const u64 rateHz = (static_cast<u64>(cnt) * 32768) / cycleCount;
usleep(10);
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = savedCntl;
usleep(10);
if (preselReg) {
u32 val2 = MMIO32(freq::CarBase + preselReg);
usleep(10);
val2 &= ~preselMask;
val2 |= preselOrigBit;
MMIO32(freq::CarBase + preselReg) = val2;
usleep(10);
}
return rateHz;
}
u64 MeasureRamClockHz() {
const u64 pllmbHz = MeasurePtoHz(PtoPllmb, 2, PllmMisc2, PllmMisc2PllmbBit);
if (pllmbHz != 0) {
return pllmbHz;
}
return MeasurePtoHz(PtoPllm, 2, PllmMisc2, PllmMisc2PllmBit);
}
} // namespace pllmb
+2 -58
View File
@@ -32,64 +32,8 @@ namespace pllmb {
constexpr u32 PtoCyclePeriod = (1u << 31); // PTO_CLK_CNT_STATUS busy bit constexpr u32 PtoCyclePeriod = (1u << 31); // PTO_CLK_CNT_STATUS busy bit
inline u64 MeasurePtoHz(u32 ptoId, u32 divider, u32 preselReg, u32 preselMask) { u64 MeasurePtoHz(u32 ptoId, u32 divider, u32 preselReg, u32 preselMask);
u32 preselOrigBit = 0;
if (preselReg) { u64 MeasureRamClockHz();
u32 val = MMIO32(freq::CarBase + preselReg);
usleep(10);
preselOrigBit = val & preselMask;
val &= ~preselMask;
val |= preselMask;
MMIO32(freq::CarBase + preselReg) = val;
usleep(10);
}
constexpr u32 cycleCount = 16;
const u32 savedCntl = MMIO32(freq::CarBase + freq::CarPtoClkCntCntl);
u32 val = freq::PtoDivSelDiv1 | freq::PtoClkEnable | (cycleCount - 1);
val |= ptoId << freq::PtoSrcSelShift;
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = val;
usleep(10);
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = val | freq::PtoCntRst;
usleep(10);
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = val;
usleep(10);
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = val | freq::PtoCntEn;
usleep(500);
while (MMIO32(freq::CarBase + freq::CarPtoClkCntStatus) & PtoCyclePeriod)
;
u32 cnt = MMIO32(freq::CarBase + freq::CarPtoClkCntStatus) & freq::PtoClkCntMask;
cnt *= divider;
const u64 rateHz = (static_cast<u64>(cnt) * 32768) / cycleCount;
usleep(10);
MMIO32(freq::CarBase + freq::CarPtoClkCntCntl) = savedCntl;
usleep(10);
if (preselReg) {
u32 val2 = MMIO32(freq::CarBase + preselReg);
usleep(10);
val2 &= ~preselMask;
val2 |= preselOrigBit;
MMIO32(freq::CarBase + preselReg) = val2;
usleep(10);
}
return rateHz;
}
inline u64 MeasureRamClockHz() {
const u64 pllmbHz = MeasurePtoHz(PtoPllmb, 2, PllmMisc2, PllmMisc2PllmbBit);
if (pllmbHz != 0) {
return pllmbHz;
}
return MeasurePtoHz(PtoPllm, 2, PllmMisc2, PllmMisc2PllmBit);
}
} // namespace pllmb } // namespace pllmb
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
*
* 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 "regs.hpp"
[[maybe_unused]] void usleep(u32 us) {
while (us) {
const u32 delay = (us > HaltMaxCnt) ? HaltMaxCnt : us;
us -= delay;
MMIO32(FlowCtlrBase + FlowCtlrHaltCopEvents) = HaltModeWaitEvent | HaltUsec | delay;
}
}
[[maybe_unused]] void msleep(u32 ms) {
while (ms) {
const u32 delay = (ms > HaltMaxCnt) ? HaltMaxCnt : ms;
ms -= delay;
MMIO32(FlowCtlrBase + FlowCtlrHaltCopEvents) = HaltModeWaitEvent | HaltMsec | delay;
}
}
void UartPutc(char c) {
while (!(MMIO32(UartBBase + UartLsr) & UartLsrThre))
;
MMIO32(UartBBase + UartThr) = static_cast<u32>(static_cast<u8>(c));
}
void UartFlush() {
while (!(MMIO32(UartBBase + UartLsr) & UartLsrTmty))
;
}
void UartPuts(const char *s) {
while (*s) {
UartPutc(*s++);
}
}
void UartPutHex32(u32 v) {
static const char digits[] = "0123456789ABCDEF";
for (int i = 28; i >= 0; i -= 4) {
UartPutc(digits[(v >> i) & 0xF]);
}
}
+6 -35
View File
@@ -33,20 +33,8 @@ constexpr u32 HaltMsec = (1u << 24);
constexpr u32 HaltUsec = (1u << 25); constexpr u32 HaltUsec = (1u << 25);
constexpr u32 HaltMaxCnt = 0xFF; constexpr u32 HaltMaxCnt = 0xFF;
[[maybe_unused]] inline void usleep(u32 us) { [[maybe_unused]] void usleep(u32 us);
while (us) { [[maybe_unused]] void msleep(u32 ms);
const u32 delay = (us > HaltMaxCnt) ? HaltMaxCnt : us;
us -= delay;
MMIO32(FlowCtlrBase + FlowCtlrHaltCopEvents) = HaltModeWaitEvent | HaltUsec | delay;
}
}
[[maybe_unused]] inline void msleep(u32 ms) {
while (ms) {
const u32 delay = (ms > HaltMaxCnt) ? HaltMaxCnt : ms;
ms -= delay;
MMIO32(FlowCtlrBase + FlowCtlrHaltCopEvents) = HaltModeWaitEvent | HaltMsec | delay;
}
}
constexpr u32 TmrBase = 0x60005000; constexpr u32 TmrBase = 0x60005000;
constexpr u32 TimerUsCntr1Us = 0x10; constexpr u32 TimerUsCntr1Us = 0x10;
@@ -57,27 +45,10 @@ constexpr u32 UartLsr = 0x14;
constexpr u32 UartLsrThre = (1u << 5); constexpr u32 UartLsrThre = (1u << 5);
constexpr u32 UartLsrTmty = (1u << 6); constexpr u32 UartLsrTmty = (1u << 6);
inline void UartPutc(char c) { void UartPutc(char c);
while (!(MMIO32(UartBBase + UartLsr) & UartLsrThre))
;
MMIO32(UartBBase + UartThr) = static_cast<u32>(static_cast<u8>(c));
}
// Waits for the byte to be fully transmitted void UartFlush();
inline void UartFlush() {
while (!(MMIO32(UartBBase + UartLsr) & UartLsrTmty))
;
}
inline void UartPuts(const char *s) { void UartPuts(const char *s);
while (*s) {
UartPutc(*s++);
}
}
inline void UartPutHex32(u32 v) { void UartPutHex32(u32 v);
static const char digits[] = "0123456789ABCDEF";
for (int i = 28; i >= 0; i -= 4) {
UartPutc(digits[(v >> i) & 0xF]);
}
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
*
* 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 "sensors.hpp"
s32 TranslateSocthermTemp(u16 val) {
s32 t = ((val >> 8) & 0xFF) * 1000;
if (val & (1u << 7)) {
t += 500;
}
if (val & (1u << 0)) {
t = -t;
}
return t;
}
+1 -10
View File
@@ -22,13 +22,4 @@ constexpr u32 SocthermBase = 0x700E2000;
constexpr u32 SocthermSensorTemp1 = 0x1C8; constexpr u32 SocthermSensorTemp1 = 0x1C8;
constexpr u32 SocthermSensorTemp2 = 0x1CC; constexpr u32 SocthermSensorTemp2 = 0x1CC;
inline s32 TranslateSocthermTemp(u16 val) { s32 TranslateSocthermTemp(u16 val);
s32 t = ((val >> 8) & 0xFF) * 1000;
if (val & (1u << 7)) {
t += 500;
}
if (val & (1u << 0)) {
t = -t;
}
return t;
}