From f5ee073eafa7acc83f2aa3badf23552da30d68ed Mon Sep 17 00:00:00 2001 From: Tony Kuker Date: Sat, 10 Sep 2022 20:30:27 +0000 Subject: [PATCH] registers working --- src/raspberrypi/Makefile | 10 +- src/raspberrypi/common.h | 48 ++ .../controllers/scsi_controller.cpp | 8 +- src/raspberrypi/hal/allwinner_hal.cpp | 0 src/raspberrypi/hal/allwinner_hal.h | 0 src/raspberrypi/hal/gpiobus.cpp | 18 +- src/raspberrypi/hal/sbc_version.cpp | 203 +++++ src/raspberrypi/hal/sbc_version.h | 68 ++ src/raspberrypi/hal/systimer.cpp | 109 +-- src/raspberrypi/hal/systimer.h | 18 +- src/raspberrypi/hal/systimer_allwinner.cpp | 136 +++ src/raspberrypi/hal/systimer_allwinner.h | 42 + src/raspberrypi/hal/systimer_raspberry.cpp | 153 ++++ src/raspberrypi/hal/systimer_raspberry.h | 45 + src/raspberrypi/mem-info | Bin 0 -> 23368 bytes src/raspberrypi/mem-info.c | 793 ++++++++++++++++++ src/raspberrypi/rascsi.cpp | 4 +- src/raspberrypi/rasdump.cpp | 4 +- src/raspberrypi/registers | Bin 0 -> 31972 bytes src/raspberrypi/registers.c | 406 +++++++++ src/raspberrypi/registers.d | 167 ++++ src/raspberrypi/registers_raspi.c | 106 +++ src/raspberrypi/version.h | 1 + 23 files changed, 2212 insertions(+), 127 deletions(-) create mode 100644 src/raspberrypi/common.h create mode 100644 src/raspberrypi/hal/allwinner_hal.cpp create mode 100644 src/raspberrypi/hal/allwinner_hal.h create mode 100644 src/raspberrypi/hal/sbc_version.cpp create mode 100644 src/raspberrypi/hal/sbc_version.h create mode 100644 src/raspberrypi/hal/systimer_allwinner.cpp create mode 100644 src/raspberrypi/hal/systimer_allwinner.h create mode 100644 src/raspberrypi/hal/systimer_raspberry.cpp create mode 100644 src/raspberrypi/hal/systimer_raspberry.h create mode 100755 src/raspberrypi/mem-info create mode 100644 src/raspberrypi/mem-info.c create mode 100755 src/raspberrypi/registers create mode 100644 src/raspberrypi/registers.c create mode 100644 src/raspberrypi/registers.d create mode 100644 src/raspberrypi/registers_raspi.c create mode 100644 src/raspberrypi/version.h diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index ff576344..1195f18c 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -18,11 +18,11 @@ CXX = $(CROSS_COMPILE)g++ DEBUG ?= 0 ifeq ($(DEBUG), 1) # Debug compiler flags - CXXFLAGS += -O0 -g -Wall -DDEBUG + CXXFLAGS += -O0 -g -DDEBUG BUILD_TYPE = Debug else # Release compiler flags - CXXFLAGS += -O3 -Wall -Werror -DNDEBUG + CXXFLAGS += -O0 -g -DDEBUG BUILD_TYPE = Release endif ifeq ("$(shell uname -s)","Linux") @@ -58,6 +58,7 @@ RASCTL = rasctl RASDUMP = rasdump SCSIMON = scsimon RASCSI_TEST = rascsi_test +REGISTERS_TEST = registers SYSTEMD_CONF = /etc/systemd/system/rascsi.service RSYSLOG_CONF = /etc/rsyslog.d/rascsi.conf @@ -204,6 +205,9 @@ $(BINDIR)/$(SCSIMON): $(OBJ_SCSIMON) | $(BINDIR) $(BINDIR)/$(RASCSI_TEST): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCSI_TEST) | $(BINDIR) $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI_CORE) $(OBJ_RASCSI_TEST) -lpthread -lpcap -lprotobuf -lstdc++fs -lgmock -lgtest +$(REGISTERS_TEST): registers.c + $(CXX) $(CXXFLAGS) -o $@ $< + # Phony rules for building individual utilities .PHONY: $(RASCSI) $(RASCTL) $(RASDUMP) $(SCSIMON) @@ -217,7 +221,7 @@ $(SCSIMON) : $(BINDIR)/$(SCSIMON) ## compiler files and executable files .PHONY: clean clean: - rm -rf $(OBJDIR) $(BINDIR) $(GEN_PROTOBUF) $(COVERAGE_DIR) $(COVERAGE_FILE) + rm -rf $(OBJDIR) $(BINDIR) $(GEN_PROTOBUF) $(COVERAGE_DIR) $(COVERAGE_FILE) $(REGISTERS_TEST) ## install : Copies all of the man pages to the correct location ## Copies the binaries to a global install location diff --git a/src/raspberrypi/common.h b/src/raspberrypi/common.h new file mode 100644 index 00000000..52341c3e --- /dev/null +++ b/src/raspberrypi/common.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Alejandro Mery + * + * 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, see . + */ +#ifndef _SUNXI_TOOLS_COMMON_H +#define _SUNXI_TOOLS_COMMON_H + +#include /* offsetof */ + +#include "version.h" /* auto-generated VERSION string */ + +/** flag function argument as unused */ +#ifdef UNUSED +#elif defined(__GNUC__) +# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) +#else +# define UNUSED(x) UNUSED_ ## x +#endif + +/** finds the parent of an struct member */ +#ifndef container_of +#define container_of(P,T,M) (T *)((char *)(P) - offsetof(T, M)) +#endif + +/** calculate number of elements of an array */ +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif + +/** shortcut to "printf to stderr" */ +#define pr_error(...) fprintf(stderr, __VA_ARGS__) +/** like pr_error(), but also exit program */ +#define pr_fatal(...) \ + do { pr_error(__VA_ARGS__); exit(EXIT_FAILURE); } while (0); + +#endif /* _SUNXI_TOOLS_COMMON_H */ \ No newline at end of file diff --git a/src/raspberrypi/controllers/scsi_controller.cpp b/src/raspberrypi/controllers/scsi_controller.cpp index 7864f0c3..dc06e2e5 100644 --- a/src/raspberrypi/controllers/scsi_controller.cpp +++ b/src/raspberrypi/controllers/scsi_controller.cpp @@ -292,7 +292,7 @@ void ScsiController::Execute() // Initialization for data transfer ctrl.offset = 0; ctrl.blocks = 1; - execstart = SysTimer::GetTimerLow(); + execstart = SysTimer::instance().GetTimerLow(); // Discard pending sense data from the previous command if the current command is not REQUEST SENSE if ((scsi_command)ctrl.cmd[0] != scsi_command::eCmdRequestSense) { @@ -356,7 +356,7 @@ void ScsiController::Status() if (execstart > 0) { Sleep(); } else { - SysTimer::SleepUsec(5); + SysTimer::instance().SleepUsec(5); } LOGTRACE("%s Status Phase $%02X",__PRETTY_FUNCTION__, (unsigned int)ctrl.status) @@ -1220,8 +1220,8 @@ int ScsiController::GetEffectiveLun() const void ScsiController::Sleep() { - if (uint32_t time = SysTimer::GetTimerLow() - execstart; time < MIN_EXEC_TIME) { - SysTimer::SleepUsec(MIN_EXEC_TIME - time); + if (uint32_t time = SysTimer::instance().GetTimerLow() - execstart; time < MIN_EXEC_TIME) { + SysTimer::instance().SleepUsec(MIN_EXEC_TIME - time); } execstart = 0; } diff --git a/src/raspberrypi/hal/allwinner_hal.cpp b/src/raspberrypi/hal/allwinner_hal.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/raspberrypi/hal/allwinner_hal.h b/src/raspberrypi/hal/allwinner_hal.h new file mode 100644 index 00000000..e69de29b diff --git a/src/raspberrypi/hal/gpiobus.cpp b/src/raspberrypi/hal/gpiobus.cpp index c558cfb8..ad65b7a6 100644 --- a/src/raspberrypi/hal/gpiobus.cpp +++ b/src/raspberrypi/hal/gpiobus.cpp @@ -705,7 +705,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf) bool ret = WaitSignal(PIN_ACK, TRUE); // Wait until the signal line stabilizes - SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); + SysTimer::instance.SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get data *buf = GetDAT(); @@ -742,7 +742,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf) ret = WaitSignal(PIN_ACK, TRUE); - SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); + SysTimer::instance.SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get the actual SCSI command *buf = GetDAT(); @@ -776,7 +776,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf) ret = WaitSignal(PIN_ACK, TRUE); // Wait until the signal line stabilizes - SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); + SysTimer::instance.SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get data *buf = GetDAT(); @@ -827,7 +827,7 @@ int GPIOBUS::ReceiveHandShake(BYTE *buf, int count) bool ret = WaitSignal(PIN_ACK, TRUE); // Wait until the signal line stabilizes - SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); + SysTimer::instance.SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get data *buf = GetDAT(); @@ -870,7 +870,7 @@ int GPIOBUS::ReceiveHandShake(BYTE *buf, int count) } // Wait until the signal line stabilizes - SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); + SysTimer::instance.SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get data *buf = GetDAT(); @@ -922,7 +922,7 @@ int GPIOBUS::SendHandShake(BYTE *buf, int count, int delay_after_bytes) for (i = 0; i < count; i++) { if(i==delay_after_bytes){ LOGTRACE("%s DELAYING for %dus after %d bytes", __PRETTY_FUNCTION__, SCSI_DELAY_SEND_DATA_DAYNAPORT_US, (int)delay_after_bytes) - SysTimer::SleepUsec(SCSI_DELAY_SEND_DATA_DAYNAPORT_US); + SysTimer::instance.SleepUsec(SCSI_DELAY_SEND_DATA_DAYNAPORT_US); } // Set the DATA signals @@ -965,7 +965,7 @@ int GPIOBUS::SendHandShake(BYTE *buf, int count, int delay_after_bytes) for (i = 0; i < count; i++) { if(i==delay_after_bytes){ LOGTRACE("%s DELAYING for %dus after %d bytes", __PRETTY_FUNCTION__, SCSI_DELAY_SEND_DATA_DAYNAPORT_US, (int)delay_after_bytes) - SysTimer::SleepUsec(SCSI_DELAY_SEND_DATA_DAYNAPORT_US); + SysTimer::instance.SleepUsec(SCSI_DELAY_SEND_DATA_DAYNAPORT_US); } // Set the DATA signals @@ -1366,9 +1366,9 @@ void GPIOBUS::PullConfig(int pin, int mode) } else { pin &= 0x1f; gpio[GPIO_PUD] = mode & 0x3; - SysTimer::SleepUsec(2); + SysTimer::instance.SleepUsec(2); gpio[GPIO_CLK_0] = 0x1 << pin; - SysTimer::SleepUsec(2); + SysTimer::instance.SleepUsec(2); gpio[GPIO_PUD] = 0; gpio[GPIO_CLK_0] = 0; } diff --git a/src/raspberrypi/hal/sbc_version.cpp b/src/raspberrypi/hal/sbc_version.cpp new file mode 100644 index 00000000..eeffb9f3 --- /dev/null +++ b/src/raspberrypi/hal/sbc_version.cpp @@ -0,0 +1,203 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 akuker +// +// [ Hardware version detection routines ] +// +//--------------------------------------------------------------------------- + +#include "sbc_version.h" +#include "log.h" +#include +#include +#include + +SBC_Version::sbc_version_type SBC_Version::m_sbc_version = SBC_Version::sbc_unknown; + +// const std::string SBC_Version::m_str_raspberry_pi_1 = "Raspberry Pi 1"; +// const std::string SBC_Version::m_str_raspberry_pi_2_3 = "Raspberry Pi 2/3"; +// const std::string SBC_Version::m_str_raspberry_pi_4 = "Raspberry Pi 4"; +// const std::string SBC_Version::m_str_bananapi_m2_berry = "Banana Pi M2 Berry/Ultra"; +// const std::string SBC_Version::m_str_bananapi_m2_zero = "Banana Pi M2 Zero"; +// const std::string SBC_Version::m_str_bananapi_m2_plus = "Banana Pi BPI-M2-Plus H3"; +// const std::string SBC_Version::m_str_bananapi_m3 = "Banana Pi M3"; +// const std::string SBC_Version::m_str_bananapi_m4 = "Banana Pi M4"; +// const std::string SBC_Version::m_str_unknown_sbc = "Unknown SBC"; + +// The strings in this table should align with the 'model' embedded +// in the device tree. This can be aquired by running: +// cat /proc/device-tree/model +// Only the first part of the string is checked. Anything following +// will be ignored. For example: +// "Raspberry Pi 4 Model B" will match with both of the following: +// - Raspberry Pi 4 Model B Rev 1.4 +// - Raspberry Pi 4 Model B Rev 1.3 +const std::map SBC_Version::m_proc_device_tree_mapping = { + {"Raspberry Pi 1 Model ", SBC_Version::sbc_raspberry_pi_1}, + {"Raspberry Pi 2 Model ", SBC_Version::sbc_raspberry_pi_2_3}, + {"Raspberry Pi 3 Model ", SBC_Version::sbc_raspberry_pi_2_3}, + {"Raspberry Pi 4 Model ", SBC_Version::sbc_raspberry_pi_4}, + {"Raspberry Pi 400 ", SBC_Version::sbc_raspberry_pi_4}, + {"Raspberry Pi Zero W", SBC_Version::sbc_raspberry_pi_1}, + {"Raspberry Pi Zero", SBC_Version::sbc_raspberry_pi_1}, + {"Banana Pi BPI-M2-Zero ", SBC_Version::sbc_bananapi_m2_zero}, + {"Banana Pi BPI-M2-Ultra ", SBC_Version::sbc_bananapi_m2_berry}, + {"Banana Pi BPI-M2-Plus H3", SBC_Version::sbc_bananapi_m2_plus}, + {"Banana Pi M2 Berry ", SBC_Version::sbc_bananapi_m2_berry}, + // sbc_bananapi_m3, TBD.... + // sbc_bananapi_m4, +}; + +const std::string SBC_Version::m_device_tree_model_path = "/proc/device-tree/model"; + +//--------------------------------------------------------------------------- +// +// Convert the SBC Version to a printable string +// +//--------------------------------------------------------------------------- +const std::string* SBC_Version::GetString(){ + switch(m_sbc_version){ + case sbc_raspberry_pi_1: return &m_str_raspberry_pi_1; + case sbc_raspberry_pi_2_3: return &m_str_raspberry_pi_2_3; + case sbc_raspberry_pi_4: return &m_str_raspberry_pi_4; + case sbc_bananapi_m2_berry: return &m_str_bananapi_m2_berry; + case sbc_bananapi_m2_zero: return &m_str_bananapi_m2_zero; + case sbc_bananapi_m3: return &m_str_bananapi_m3; + case sbc_bananapi_m4: return &m_str_bananapi_m4; + default: + LOGERROR("Unknown type of sbc detected: %d",m_sbc_version); + return &m_str_unknown_sbc; + } +} + +SBC_Version::sbc_version_type SBC_Version::GetSbcVersion(){ + return m_sbc_version; +} + +//--------------------------------------------------------------------------- +// +// Determine which version of single board computer (Pi) is being used +// based upon the device tree model string. +// +//--------------------------------------------------------------------------- +void SBC_Version::Init(){ + + std::string device_tree_model; + + const std::ifstream input_stream(SBC_Version::m_device_tree_model_path); + + if (input_stream.fail()) { + LOGERROR("Failed to open %s. Are you running as root?", SBC_Version::m_device_tree_model_path.c_str()); + throw std::runtime_error("Failed to open /proc/device-tree/model"); + } + + std::stringstream str_buffer; + str_buffer << input_stream.rdbuf(); + device_tree_model = str_buffer.str(); + + for (const auto& [key, value] : m_device_model_map) { + if(device_tree_model.rfind(key,0) == 0){ + m_sbc_version = value; + LOGINFO("Detected device %s", GetString()->c_str()); + return; + } + } + LOGERROR("%s Unable to determine single board computer type. Defaulting to Raspberry Pi 4", __PRETTY_FUNCTION__); + m_sbc_version = sbc_version_type::sbc_raspberry_pi_4; +} + +bool SBC_Version::IsRaspberryPi(){ + switch(m_sbc_version){ + case sbc_raspberry_pi_1: + case sbc_raspberry_pi_2_3: + case sbc_raspberry_pi_4: + return true; + case sbc_bananapi_m2_berry: + case sbc_bananapi_m2_zero: + case sbc_bananapi_m2_plus: + case sbc_bananapi_m3: + case sbc_bananapi_m4: + return false; + default: + return false; + } +} + +bool SBC_Version::IsBananaPi(){ + switch(m_sbc_version){ + case sbc_raspberry_pi_1: + case sbc_raspberry_pi_2_3: + case sbc_raspberry_pi_4: + return false; + case sbc_bananapi_m2_berry: + case sbc_bananapi_m2_zero: + case sbc_bananapi_m2_plus: + case sbc_bananapi_m3: + case sbc_bananapi_m4: + return true; + default: + return false; + } +} + + +//--------------------------------------------------------------------------- +// +// imported from bcm_host.c +// +//--------------------------------------------------------------------------- +DWORD SBC_Version::GetDeviceTreeRanges(const char *filename, DWORD offset) +{ + DWORD address = ~0; + if (FILE *fp = fopen(filename, "rb"); fp) { + fseek(fp, offset, SEEK_SET); + if (BYTE buf[4]; fread(buf, 1, sizeof buf, fp) == sizeof buf) { + address = + buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0; + } + fclose(fp); + } + return address; +} + +#if defined __linux__ +DWORD SBC_Version::GetPeripheralAddress(void) +{ + DWORD address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 4); + if (address == 0) { + address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 8); + } + address = (address == (DWORD)~0) ? 0x20000000 : address; + + printf("Peripheral address : 0x%8x\n", address); + + return address; +} +#elif defined __NetBSD__ +DWORD SBC_Version::GetPeripheralAddress(void) +{ + char buf[1024]; + size_t len = sizeof(buf); + DWORD address; + + if (sysctlbyname("hw.model", buf, &len, NULL, 0) || + strstr(buf, "ARM1176JZ-S") != buf) { + // Failed to get CPU model || Not BCM2835 + // use the address of BCM283[67] + address = 0x3f000000; + } else { + // Use BCM2835 address + address = 0x20000000; + } + printf("Peripheral address : 0x%lx\n", address); + return address; +} +#else +DWORD SBC_Version::GetPeripheralAddress(void) +{ + return 0; +} +#endif \ No newline at end of file diff --git a/src/raspberrypi/hal/sbc_version.h b/src/raspberrypi/hal/sbc_version.h new file mode 100644 index 00000000..791897f8 --- /dev/null +++ b/src/raspberrypi/hal/sbc_version.h @@ -0,0 +1,68 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 akuker +// +// [ Hardware version detection routines ] +// +//--------------------------------------------------------------------------- + +#pragma once +#include "os.h" +#include +#include + +//=========================================================================== +// +// Single Board Computer Versions +// +//=========================================================================== +class SBC_Version +{ +public: + // Type of Single Board Computer + enum sbc_version_type : uint8_t { + sbc_unknown = 0, + sbc_raspberry_pi_1, + sbc_raspberry_pi_2_3, + sbc_raspberry_pi_4, + sbc_bananapi_m2_berry, + sbc_bananapi_m2_zero, + sbc_bananapi_m2_plus, + sbc_bananapi_m3, + sbc_bananapi_m4, + }; + + static void Init(); + + static sbc_version_type GetSbcVersion(); + + static bool IsRaspberryPi(); + static bool IsBananaPi(); + + static const std::string* GetString(); + + static DWORD GetPeripheralAddress(); + +private: + static sbc_version_type m_sbc_version; + + static const std::string m_str_raspberry_pi_1; + static const std::string m_str_raspberry_pi_2_3; + static const std::string m_str_raspberry_pi_4; + static const std::string m_str_bananapi_m2_berry; + static const std::string m_str_bananapi_m2_zero; + static const std::string m_str_bananapi_m2_plus; + static const std::string m_str_bananapi_m3; + static const std::string m_str_bananapi_m4; + static const std::string m_str_unknown_sbc; + + static const std::map m_proc_device_tree_mapping; + + static const std::string m_device_tree_model_path; + + static DWORD GetDeviceTreeRanges(const char *filename, DWORD offset); + +}; \ No newline at end of file diff --git a/src/raspberrypi/hal/systimer.cpp b/src/raspberrypi/hal/systimer.cpp index 6af7dbe6..00bc98e1 100644 --- a/src/raspberrypi/hal/systimer.cpp +++ b/src/raspberrypi/hal/systimer.cpp @@ -20,115 +20,34 @@ #include "config.h" #include "log.h" -//--------------------------------------------------------------------------- -// -// System timer address -// -//--------------------------------------------------------------------------- -volatile DWORD* SysTimer::systaddr; -//--------------------------------------------------------------------------- -// -// ARM timer address -// -//--------------------------------------------------------------------------- -volatile DWORD* SysTimer::armtaddr; + static std::shared_ptr private_instance = nullptr; -//--------------------------------------------------------------------------- -// -// Core frequency -// -//--------------------------------------------------------------------------- -volatile DWORD SysTimer::corefreq; -//--------------------------------------------------------------------------- -// -// Initialize the system timer -// -//--------------------------------------------------------------------------- -void SysTimer::Init(DWORD *syst, DWORD *armt) +ControllerManager& ControllerManager::instance() { - // RPI Mailbox property interface - // Get max clock rate - // Tag: 0x00030004 - // - // Request: Length: 4 - // Value: u32: clock id - // Response: Length: 8 - // Value: u32: clock id, u32: rate (in Hz) - // - // Clock id - // 0x000000004: CORE - DWORD maxclock[32] = { 32, 0, 0x00030004, 8, 0, 4, 0, 0 }; - - // Save the base address - systaddr = syst; - armtaddr = armt; - - // Change the ARM timer to free run mode - armtaddr[ARMT_CTRL] = 0x00000282; - - // Get the core frequency - corefreq = 0; - int fd = open("/dev/vcio", O_RDONLY); - if (fd >= 0) { - ioctl(fd, _IOWR(100, 0, char *), maxclock); - corefreq = maxclock[6] / 1000000; + // If we haven't set up the private instance yet, do that now + if(private_instance == nullptr){ + if(SBC_Version::IsRaspberryPi()){ + private_instance = std::make_shared(); + private_instance->Init(); + } + else if(SBC_Version::IsBananaPi()){ + private_instance = std::make_shared(); + private_instance->Init(); + } } - close(fd); + return private_instance; } -//--------------------------------------------------------------------------- -// -// Get system timer low byte -// -//--------------------------------------------------------------------------- -DWORD SysTimer::GetTimerLow() { - return systaddr[SYST_CLO]; -} -//--------------------------------------------------------------------------- -// -// Get system timer high byte -// -//--------------------------------------------------------------------------- -DWORD SysTimer::GetTimerHigh() { - return systaddr[SYST_CHI]; -} - -//--------------------------------------------------------------------------- -// -// Sleep in nanoseconds -// -//--------------------------------------------------------------------------- -void SysTimer::SleepNsec(DWORD nsec) -{ - // If time is 0, don't do anything - if (nsec == 0) { - return; - } - - // Calculate the timer difference - DWORD diff = corefreq * nsec / 1000; - - // Return if the difference in time is too small - if (diff == 0) { - return; - } - - // Start - DWORD start = armtaddr[ARMT_FREERUN]; - - // Loop until timer has elapsed - while ((armtaddr[ARMT_FREERUN] - start) < diff); -} //--------------------------------------------------------------------------- // // Sleep in microseconds // //--------------------------------------------------------------------------- -void SysTimer::SleepUsec(DWORD usec) +void SysTimer::instance.SleepUsec(DWORD usec) { // If time is 0, don't do anything if (usec == 0) { diff --git a/src/raspberrypi/hal/systimer.h b/src/raspberrypi/hal/systimer.h index 8f4b31d9..91e3fce8 100644 --- a/src/raspberrypi/hal/systimer.h +++ b/src/raspberrypi/hal/systimer.h @@ -26,22 +26,16 @@ class SysTimer { public: - static void Init(uint32_t *syst, uint32_t *armt); - // Initialization - static uint32_t GetTimerLow(); + virtual uint32_t GetTimerLow(); // Get system timer low byte - static uint32_t GetTimerHigh(); + virtual uint32_t GetTimerHigh(); // Get system timer high byte - static void SleepNsec(uint32_t nsec); + virtual void SleepNsec(uint32_t nsec); // Sleep for N nanoseconds - static void SleepUsec(uint32_t usec); + virtual void SleepUsec(uint32_t usec); // Sleep for N microseconds + static SysTimer& instance(); private: - static volatile uint32_t *systaddr; - // System timer address - static volatile uint32_t *armtaddr; - // ARM timer address - static volatile uint32_t corefreq; - // Core frequency + static std::shared_ptr private_instance; }; diff --git a/src/raspberrypi/hal/systimer_allwinner.cpp b/src/raspberrypi/hal/systimer_allwinner.cpp new file mode 100644 index 00000000..d78ff723 --- /dev/null +++ b/src/raspberrypi/hal/systimer_allwinner.cpp @@ -0,0 +1,136 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2020 GIMONS +// Copyright (C) 2022 akuker +// +// [ High resolution timer ] +// +//--------------------------------------------------------------------------- + +#include "hal/systimer.h" +#include + +#include "os.h" +#include "hal/gpiobus.h" + +#include "config.h" +#include "log.h" + + +ControllerManager& ControllerManager::instance() +{ + // If we haven't set up the private instance yet, do that now + if(private_instance == nullptr){ + if(SBC_Version::IsRaspberryPi()){ + private_instance = std::make_shared(); + private_instance->Init(); + } + else if(SBC_Version::IsBananaPi()){ + private_instance = std::make_shared(); + private_instance->Init(); + } + } + return private_instance; +} + +//--------------------------------------------------------------------------- +// +// Initialize the system timer +// +//--------------------------------------------------------------------------- +void SysTimer::Init(DWORD *syst, DWORD *armt) +{ + // RPI Mailbox property interface + // Get max clock rate + // Tag: 0x00030004 + // + // Request: Length: 4 + // Value: u32: clock id + // Response: Length: 8 + // Value: u32: clock id, u32: rate (in Hz) + // + // Clock id + // 0x000000004: CORE + DWORD maxclock[32] = { 32, 0, 0x00030004, 8, 0, 4, 0, 0 }; + + // Save the base address + systaddr = syst; + armtaddr = armt; + + // Change the ARM timer to free run mode + armtaddr[ARMT_CTRL] = 0x00000282; + + // Get the core frequency + corefreq = 0; + int fd = open("/dev/vcio", O_RDONLY); + if (fd >= 0) { + ioctl(fd, _IOWR(100, 0, char *), maxclock); + corefreq = maxclock[6] / 1000000; + } + close(fd); +} + +//--------------------------------------------------------------------------- +// +// Get system timer low byte +// +//--------------------------------------------------------------------------- +DWORD SysTimer::GetTimerLow() { + return systaddr[SYST_CLO]; +} + +//--------------------------------------------------------------------------- +// +// Get system timer high byte +// +//--------------------------------------------------------------------------- +DWORD SysTimer::GetTimerHigh() { + return systaddr[SYST_CHI]; +} + +//--------------------------------------------------------------------------- +// +// Sleep in nanoseconds +// +//--------------------------------------------------------------------------- +void SysTimer::instance.SleepNsec(DWORD nsec) +{ + // If time is 0, don't do anything + if (nsec == 0) { + return; + } + + // Calculate the timer difference + DWORD diff = corefreq * nsec / 1000; + + // Return if the difference in time is too small + if (diff == 0) { + return; + } + + // Start + DWORD start = armtaddr[ARMT_FREERUN]; + + // Loop until timer has elapsed + while ((armtaddr[ARMT_FREERUN] - start) < diff); +} + +//--------------------------------------------------------------------------- +// +// Sleep in microseconds +// +//--------------------------------------------------------------------------- +void SysTimer::instance.SleepUsec(DWORD usec) +{ + // If time is 0, don't do anything + if (usec == 0) { + return; + } + + DWORD now = GetTimerLow(); + while ((GetTimerLow() - now) < usec); +} diff --git a/src/raspberrypi/hal/systimer_allwinner.h b/src/raspberrypi/hal/systimer_allwinner.h new file mode 100644 index 00000000..7c1fd807 --- /dev/null +++ b/src/raspberrypi/hal/systimer_allwinner.h @@ -0,0 +1,42 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Copyright (C) 2022 akuker +// +// [ High resolution timer ] +// +//--------------------------------------------------------------------------- +#pragma once + +#include +#include "systimer.h" + +//=========================================================================== +// +// System timer +// +//=========================================================================== +class SysTimer_AllWinner : SysTimer +{ +public: + override void Init(uint32_t *syst, uint32_t *armt); + // Initialization + override uint32_t GetTimerLow(); + // Get system timer low byte + override uint32_t GetTimerHigh(); + // Get system timer high byte + override void SleepNsec(uint32_t nsec); + // Sleep for N nanoseconds + override void SleepUsec(uint32_t usec); + // Sleep for N microseconds + +private: + static volatile uint32_t *systaddr; + // System timer address + static volatile uint32_t *armtaddr; + // ARM timer address + static volatile uint32_t corefreq; + // Core frequency +}; diff --git a/src/raspberrypi/hal/systimer_raspberry.cpp b/src/raspberrypi/hal/systimer_raspberry.cpp new file mode 100644 index 00000000..0e216d42 --- /dev/null +++ b/src/raspberrypi/hal/systimer_raspberry.cpp @@ -0,0 +1,153 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2020 GIMONS +// Copyright (C) 2022 akuker +// +// [ High resolution timer ] +// +//--------------------------------------------------------------------------- + +#include "hal/systimer.h" +#include + +#include "os.h" +#include "hal/gpiobus.h" + +#include "config.h" +#include "log.h" + + +ControllerManager& ControllerManager::instance() +{ + // If we haven't set up the private instance yet, do that now + if(private_instance == nullptr){ + if(SBC_Version::IsRaspberryPi()){ + private_instance = std::make_shared(); + private_instance->Init(); + } + else if(SBC_Version::IsBananaPi()){ + private_instance = std::make_shared(); + private_instance->Init(); + } + } + return private_instance; +} + +//--------------------------------------------------------------------------- +// +// Initialize the system timer +// +//--------------------------------------------------------------------------- +void SysTimer_Raspberry::Init() +{ + // Get the base address + // auto baseaddr = (DWORD)bcm_host_get_peripheral_address(); + auto baseaddr = SBC_Version::GetPeripheralAddress(); + + // Open /dev/mem + int fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + LOGERROR("Error: Unable to open /dev/mem. Are you running as root?") + return; + } + + // Map peripheral region memory + map = mmap(NULL, 0x1000100, PROT_READ | PROT_WRITE, MAP_SHARED, fd, baseaddr); + if (map == MAP_FAILED) { + LOGERROR("Error: Unable to map memory") + close(fd); + return; + } + + // RPI Mailbox property interface + // Get max clock rate + // Tag: 0x00030004 + // + // Request: Length: 4 + // Value: u32: clock id + // Response: Length: 8 + // Value: u32: clock id, u32: rate (in Hz) + // + // Clock id + // 0x000000004: CORE + DWORD maxclock[32] = { 32, 0, 0x00030004, 8, 0, 4, 0, 0 }; + + // Save the base address + systaddr = (DWORD *)map + SYST_OFFSET / sizeof(DWORD); + armtaddr = (DWORD *)map + ARMT_OFFSET / sizeof(DWORD)); + + // Change the ARM timer to free run mode + armtaddr[ARMT_CTRL] = 0x00000282; + + // Get the core frequency + if (int fd = open("/dev/vcio", O_RDONLY); fd >= 0) { + ioctl(fd, _IOWR(100, 0, char *), maxclock); + corefreq = maxclock[6] / 1000000; + close(fd); + } +} + +//--------------------------------------------------------------------------- +// +// Get system timer low byte +// +//--------------------------------------------------------------------------- +DWORD SysTimer_Raspberry::GetTimerLow() { + return systaddr[SYST_CLO]; +} + +//--------------------------------------------------------------------------- +// +// Get system timer high byte +// +//--------------------------------------------------------------------------- +DWORD SysTimer_Raspberry::GetTimerHigh() { + return systaddr[SYST_CHI]; +} + +//--------------------------------------------------------------------------- +// +// Sleep in nanoseconds +// +//--------------------------------------------------------------------------- +void SysTimer_Raspberry::SleepNsec(DWORD nsec) +{ + // If time is 0, don't do anything + if (nsec == 0) { + return; + } + + // Calculate the timer difference + DWORD diff = corefreq * nsec / 1000; + + // Return if the difference in time is too small + if (diff == 0) { + return; + } + + // Start + DWORD start = armtaddr[ARMT_FREERUN]; + + // Loop until timer has elapsed + while ((armtaddr[ARMT_FREERUN] - start) < diff); +} + +//--------------------------------------------------------------------------- +// +// Sleep in microseconds +// +//--------------------------------------------------------------------------- +void SysTimer_Raspberry::SleepUsec(DWORD usec) +{ + // If time is 0, don't do anything + if (usec == 0) { + return; + } + + DWORD now = GetTimerLow(); + while ((GetTimerLow() - now) < usec); +} diff --git a/src/raspberrypi/hal/systimer_raspberry.h b/src/raspberrypi/hal/systimer_raspberry.h new file mode 100644 index 00000000..21617b1a --- /dev/null +++ b/src/raspberrypi/hal/systimer_raspberry.h @@ -0,0 +1,45 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI Reloaded +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2020 GIMONS +// Copyright (C) 2022 akuker +// +// [ High resolution timer ] +// +//--------------------------------------------------------------------------- + +#pragma once + +#include +#include "systimer.h" + +//=========================================================================== +// +// System timer +// +//=========================================================================== +class SysTimer_Raspberry : SysTimer +{ +public: + override void Init(uint32_t *syst, uint32_t *armt); + // Initialization + override uint32_t GetTimerLow(); + // Get system timer low byte + override uint32_t GetTimerHigh(); + // Get system timer high byte + override void SleepNsec(uint32_t nsec); + // Sleep for N nanoseconds + override void SleepUsec(uint32_t usec); + // Sleep for N microseconds + +private: + static volatile uint32_t *systaddr; + // System timer address + static volatile uint32_t *armtaddr; + // ARM timer address + static volatile uint32_t corefreq = 0; + // Core frequency +}; diff --git a/src/raspberrypi/mem-info b/src/raspberrypi/mem-info new file mode 100755 index 0000000000000000000000000000000000000000..ff85dbdee05bf1e8e7d5e16c2820ca71f23fa145 GIT binary patch literal 23368 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 + * Copyright (c) 2014 Luc Verhaegen + * + * 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +typedef uint32_t u32; + +/* from u-boot code: */ +struct sun4i_dram_para { + u32 baseaddr; + u32 clock; + u32 type; + u32 rank_num; + u32 density; + u32 io_width; + u32 bus_width; + u32 cas; + u32 zq; + u32 odt_en; + u32 size; + u32 tpr0; + u32 tpr1; + u32 tpr2; + u32 tpr3; + u32 tpr4; + u32 tpr5; + u32 emr1; + u32 emr2; + u32 emr3; +}; + +#define DEVMEM_FILE "/dev/mem" +static int devmem_fd; + +enum sunxi_soc_version { + SUNXI_SOC_SUN4I = 0x1623, /* A10 */ + SUNXI_SOC_SUN5I = 0x1625, /* A13, A10s */ + SUNXI_SOC_SUN6I = 0x1633, /* A31 */ + SUNXI_SOC_SUN7I = 0x1651, /* A20 */ + SUNXI_SOC_SUN8I = 0x1650, /* A23 */ + SUNXI_SOC_SUN9I = 0x1667, /* A33 */ + SUNXI_SOC_SUN10I = 0x1635, /* A80 */ + SUNXI_SOC_H3 = 0x1680, /* H3 */ +}; + +static enum sunxi_soc_version soc_version; + +/* + * Libv's favourite register handling calls. + */ +unsigned int +sunxi_io_read(void *base, int offset) +{ + return *(volatile unsigned int*) (base + offset); +} + +void +sunxi_io_write(void *base, int offset, unsigned int value) +{ + *(volatile unsigned int*) (base + offset) = value; +} + +void +sunxi_io_mask(void *base, int offset, unsigned int value, unsigned int mask) +{ + unsigned int tmp = sunxi_io_read(base, offset); + + tmp &= ~mask; + tmp |= value & mask; + + sunxi_io_write(base, offset, tmp); +} + + +/* + * Find out exactly which SoC we are dealing with. + */ +#define SUNXI_IO_SRAM_BASE 0x01C00000 +#define SUNXI_IO_SRAM_SIZE 0x00001000 + +#define SUNXI_IO_SRAM_VERSION 0x24 + +static int +soc_version_read(void) +{ + void *base; + unsigned int restore; + + base = mmap(NULL, SUNXI_IO_SRAM_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, devmem_fd, SUNXI_IO_SRAM_BASE); + if (base == MAP_FAILED) { + fprintf(stderr, "Failed to map sram registers: %s\n", + strerror(errno)); + return errno; + } + + restore = sunxi_io_read(base, SUNXI_IO_SRAM_VERSION); + + sunxi_io_mask(base, SUNXI_IO_SRAM_VERSION, 0x8000, 0x8000); + + soc_version = sunxi_io_read(base, SUNXI_IO_SRAM_VERSION) >> 16; + + sunxi_io_mask(base, SUNXI_IO_SRAM_VERSION, restore, 0x8000); + + munmap(base, SUNXI_IO_SRAM_SIZE); + + return 0; +} + +/* + * Read DRAM clock. + */ +#define SUNXI_IO_CCM_BASE 0x01C20000 +#define SUNXI_IO_CCM_SIZE 0x00001000 + +#define SUNXI_IO_CCM_PLL5_CFG 0x20 + +static int +sunxi_dram_clock_read(unsigned int *clock) +{ + void *base; + unsigned int tmp; + int n, k, m; + + base = mmap(NULL, SUNXI_IO_CCM_SIZE, PROT_READ, + MAP_SHARED, devmem_fd, SUNXI_IO_CCM_BASE); + if (base == MAP_FAILED) { + fprintf(stderr, "Failed to map ccm registers: %s\n", + strerror(errno)); + return errno; + } + + tmp = sunxi_io_read(base, SUNXI_IO_CCM_PLL5_CFG); + + munmap(base, SUNXI_IO_CCM_SIZE); + + n = (tmp >> 8) & 0x1F; + k = ((tmp >> 4) & 0x03) + 1; + m = (tmp & 0x03) + 1; + + switch (soc_version) { + case SUNXI_SOC_SUN6I: + case SUNXI_SOC_SUN8I: + n++; + break; + default: + break; + } + + *clock = (24 * n * k) / m; + + return 0; +} + +struct regs { + int offset; + char *name; +}; + +static int +dram_registers_print(unsigned int address, int size, const struct regs *regs, + const char *description, const char *prefix) +{ + void *base; + int i, j; + + base = mmap(NULL, size, PROT_READ, MAP_SHARED, devmem_fd, address); + if (base == MAP_FAILED) { + fprintf(stderr, "Failed to map %s registers: %s\n", + description, strerror(errno)); + return errno; + } + + printf("/*\n"); + printf(" * %s Registers\n", description); + printf(" */\n"); + + for (i = 0; i < size; i += 4) { + unsigned int reg = sunxi_io_read(base, i); + + for (j = 0; regs[j].name; j++) + if (i == regs[j].offset) { + printf("%s = 0x%08x;\n", regs[j].name, reg); + } + + if (reg && !regs[j].name) + printf("%s_%03X = 0x%08x;\n", prefix, i, reg); + } + + printf("\n"); + + munmap(base, size); + + return 0; +} + +static int +dram_register_range_print(unsigned int address, int size, + const char *description, const char *prefix) +{ + void *base; + int i; + + base = mmap(NULL, size, PROT_READ, MAP_SHARED, devmem_fd, address); + if (base == MAP_FAILED) { + fprintf(stderr, "Failed to map %s registers: %s\n", + description, strerror(errno)); + return errno; + } + + printf("/*\n"); + printf(" * %s Registers\n", description); + printf(" */\n"); + + for (i = 0; i < size; i += 4) { + unsigned int reg = sunxi_io_read(base, i); + + if (reg) + printf("%s_%03X = 0x%08x;\n", prefix, i, reg); + } + + printf("\n"); + + munmap(base, size); + + return 0; +} + +/* + * Read DRAM parameters. + */ +#define SUN4I_IO_DRAM_BASE 0x01C01000 +#define SUN4I_IO_DRAM_SIZE 0x00001000 + +#define SUN4I_IO_DRAM_CCR 0x000 /* controller configuration register */ +#define SUN4I_IO_DRAM_DCR 0x004 /* dram configuration */ +#define SUN4I_IO_DRAM_IOCR 0x008 /* i/o configuration */ + +#define SUN4I_IO_DRAM_TPR0 0x014 /* dram timing parameters register 0 */ +#define SUN4I_IO_DRAM_TPR1 0x018 /* dram timing parameters register 1 */ +#define SUN4I_IO_DRAM_TPR2 0x01C /* dram timing parameters register 2 */ + +#define SUN4I_IO_DRAM_ZQCR0 0x0A8 /* zq control register 0 */ +#define SUN4I_IO_DRAM_ZQCR1 0x0AC /* zq control register 1 */ + +#define SUN4I_IO_DRAM_MR 0x1F0 /* mode register */ +#define SUN4I_IO_DRAM_EMR 0x1F4 /* extended mode register */ +#define SUN4I_IO_DRAM_EMR2 0x1F8 /* extended mode register */ +#define SUN4I_IO_DRAM_EMR3 0x1FC /* extended mode register */ + +#define SUN4I_IO_DRAM_DLLCR0 0x204 /* dll control register 0(byte 0) */ +#define SUN4I_IO_DRAM_DLLCR1 0x208 /* dll control register 1(byte 1) */ +#define SUN4I_IO_DRAM_DLLCR2 0x20C /* dll control register 2(byte 2) */ +#define SUN4I_IO_DRAM_DLLCR3 0x210 /* dll control register 3(byte 3) */ +#define SUN4I_IO_DRAM_DLLCR4 0x214 /* dll control register 4(byte 4) */ + +static int +sun4i_dram_parameters_read(struct sun4i_dram_para *dram_para) +{ + void *base; + unsigned int zqcr0, dcr; + unsigned int dllcr0, dllcr1, dllcr2, dllcr3, dllcr4; + + base = mmap(NULL, SUN4I_IO_DRAM_SIZE, PROT_READ, + MAP_SHARED, devmem_fd, SUN4I_IO_DRAM_BASE); + if (base == MAP_FAILED) { + fprintf(stderr, "Failed to map dram registers: %s\n", + strerror(errno)); + return errno; + } + + dram_para->tpr0 = sunxi_io_read(base, SUN4I_IO_DRAM_TPR0); + dram_para->tpr1 = sunxi_io_read(base, SUN4I_IO_DRAM_TPR1); + dram_para->tpr2 = sunxi_io_read(base, SUN4I_IO_DRAM_TPR2); + + dllcr0 = (sunxi_io_read(base, SUN4I_IO_DRAM_DLLCR0) >> 6) & 0x3F; + dllcr1 = (sunxi_io_read(base, SUN4I_IO_DRAM_DLLCR1) >> 14) & 0x0F; + dllcr2 = (sunxi_io_read(base, SUN4I_IO_DRAM_DLLCR2) >> 14) & 0x0F; + dllcr3 = (sunxi_io_read(base, SUN4I_IO_DRAM_DLLCR3) >> 14) & 0x0F; + dllcr4 = (sunxi_io_read(base, SUN4I_IO_DRAM_DLLCR4) >> 14) & 0x0F; + + dram_para->tpr3 = (dllcr0 << 16) | + (dllcr4 << 12) | (dllcr3 << 8) | (dllcr2 << 4) | dllcr1; + + if (soc_version == SUNXI_SOC_SUN7I) { + if (sunxi_io_read(base, SUN4I_IO_DRAM_CCR) & 0x20) + dram_para->tpr4 |= 0x01; + if (!(sunxi_io_read(base, SUN4I_IO_DRAM_ZQCR1) & 0x01000000)) + dram_para->tpr4 |= 0x02; + } + + dram_para->cas = (sunxi_io_read(base, SUN4I_IO_DRAM_MR) >> 4) & 0x0F; + dram_para->emr1 = sunxi_io_read(base, SUN4I_IO_DRAM_EMR); + dram_para->emr2 = sunxi_io_read(base, SUN4I_IO_DRAM_EMR2); + dram_para->emr3 = sunxi_io_read(base, SUN4I_IO_DRAM_EMR3); + + dram_para->odt_en = sunxi_io_read(base, SUN4I_IO_DRAM_IOCR) & 0x03; + zqcr0 = sunxi_io_read(base, SUN4I_IO_DRAM_ZQCR0); + dram_para->zq = (zqcr0 & 0xf0000000) | + ((zqcr0 >> 20) & 0xff) | + ((zqcr0 & 0xfffff) << 8); + + dcr = sunxi_io_read(base, SUN4I_IO_DRAM_DCR); + if (dcr & 0x01) { + dram_para->cas += 4; + dram_para->type = 3; + } else + dram_para->type = 2; + + dram_para->density = (1 << ((dcr >> 3) & 0x07)) * 256; + dram_para->rank_num = ((dcr >> 10) & 0x03) + 1; + dram_para->io_width = ((dcr >> 1) & 0x03) * 8; + dram_para->bus_width = (((dcr >> 6) & 3) + 1) * 8; + + munmap(base, SUN4I_IO_DRAM_SIZE); + + return 0; +} + +/* + * Print a dram.c that can be stuck immediately into u-boot. + */ +void +sun4i_dram_para_print_uboot(struct sun4i_dram_para *dram_para) +{ + printf("// place this file in board/sunxi/ in u-boot\n"); + printf("/* this file is generated, don't edit it yourself */\n"); + printf("\n"); + printf("#include \"common.h\"\n"); + printf("#include \n"); + printf("\n"); + printf("static struct dram_para dram_para = {\n"); + printf("\t.clock = %d,\n", dram_para->clock); + printf("\t.type = %d,\n", dram_para->type); + printf("\t.rank_num = %d,\n", dram_para->rank_num); + printf("\t.density = %d,\n", dram_para->density); + printf("\t.io_width = %d,\n", dram_para->io_width); + printf("\t.bus_width = %d,\n", dram_para->bus_width); + printf("\t.cas = %d,\n", dram_para->cas); + printf("\t.zq = 0x%02x,\n", dram_para->zq); + printf("\t.odt_en = %d,\n", dram_para->odt_en); + printf("\t.size = !!! FIXME !!!, /* in MiB */\n"); + printf("\t.tpr0 = 0x%08x,\n", dram_para->tpr0); + printf("\t.tpr1 = 0x%04x,\n", dram_para->tpr1); + printf("\t.tpr2 = 0x%05x,\n", dram_para->tpr2); + printf("\t.tpr3 = 0x%02x,\n", dram_para->tpr3); + printf("\t.tpr4 = 0x%02x,\n", dram_para->tpr4); + printf("\t.tpr5 = 0x%02x,\n", dram_para->tpr5); + printf("\t.emr1 = 0x%02x,\n", dram_para->emr1); + printf("\t.emr2 = 0x%02x,\n", dram_para->emr2); + printf("\t.emr3 = 0x%02x,\n", dram_para->emr3); + printf("};\n"); + printf("\n"); + printf("unsigned long sunxi_dram_init(void)\n"); + printf("{\n"); + printf("\treturn dramc_init(&dram_para);\n"); + printf("}\n"); +} + +/* + * Print output matching the .fex output, so it can be stuck in a + * fex file directly. + */ +void +sun4i_dram_para_print_fex(struct sun4i_dram_para *dram_para) +{ + printf("; Insert this section into your .fex file\n"); + printf("[dram_para]\n"); + printf("dram_baseaddr = 0x40000000\n"); + printf("dram_clk = %d\n", dram_para->clock); + printf("dram_type = %d\n", dram_para->type); + printf("dram_rank_num = %d\n", dram_para->rank_num); + printf("dram_chip_density = %d\n", dram_para->density); + printf("dram_io_width = %d\n", dram_para->io_width); + printf("dram_bus_width = %d\n", dram_para->bus_width); + printf("dram_cas = %d\n", dram_para->cas); + printf("dram_zq = 0x%02x\n", dram_para->zq); + printf("dram_odt_en = %d\n", dram_para->odt_en); + printf("dram_size = !!! FIXME !!!\n"); + printf("dram_tpr0 = 0x%08x\n", dram_para->tpr0); + printf("dram_tpr1 = 0x%04x\n", dram_para->tpr1); + printf("dram_tpr2 = 0x%05x\n", dram_para->tpr2); + printf("dram_tpr3 = 0x%02x\n", dram_para->tpr3); + printf("dram_tpr4 = 0x%02x\n", dram_para->tpr4); + printf("dram_tpr5 = 0x%02x\n", dram_para->tpr5); + printf("dram_emr1 = 0x%02x\n", dram_para->emr1); + printf("dram_emr2 = 0x%02x\n", dram_para->emr2); + printf("dram_emr3 = 0x%02x\n", dram_para->emr3); +} + +static int +sun4i_dram_para_print(bool uboot) +{ + struct sun4i_dram_para dram_para = { .baseaddr = 0 }; + int ret; + + ret = sunxi_dram_clock_read(&dram_para.clock); + if (ret) + return ret; + + ret = sun4i_dram_parameters_read(&dram_para); + if (ret) + return ret; + + if (uboot) + sun4i_dram_para_print_uboot(&dram_para); + else + sun4i_dram_para_print_fex(&dram_para); + + return 0; +} + +/* + * + */ +#define SUN6I_IO_DRAMCOM_BASE 0x01C62000 +#define SUN6I_IO_DRAMCOM_SIZE 0x0300 +#define SUN6I_IO_DRAMCTL_BASE 0x01C63000 +#define SUN6I_IO_DRAMCTL_SIZE 0x0400 +#define SUN6I_IO_DRAMPHY_BASE 0x01C65000 +#define SUN6I_IO_DRAMPHY_SIZE 0x0400 + +static struct regs +sun6i_dramcom_regs[] = { + {0x00, "SDR_COM_CR"}, + {0x04, "SDR_COM_CCR"}, + {0x10, "SDR_COM_MFACR"}, + {0x30, "SDR_COM_MSACR"}, + {0x50, "SDR_COM_MBACR"}, + {0, NULL} +}; + +static struct regs +sun6i_dramctl_regs[] = { + {0x004, "SDR_SCTL"}, + {0x008, "SDR_SSTAT"}, + {0x040, "SDR_MCMD"}, + {0x04c, "SDR_CMDSTAT"}, + {0x050, "SDR_CMDSTATEN"}, + {0x060, "SDR_MRRCFG0"}, + {0x064, "SDR_MRRSTAT0"}, + {0x068, "SDR_MRRSTAT1"}, + {0x07c, "SDR_MCFG1"}, + {0x080, "SDR_MCFG"}, + {0x084, "SDR_PPCFG"}, + {0x088, "SDR_MSTAT"}, + {0x08c, "SDR_LP2ZQCFG"}, + {0x094, "SDR_DTUSTAT"}, + {0x098, "SDR_DTUNA"}, + {0x09c, "SDR_DTUNE"}, + {0x0a0, "SDR_DTUPRD0"}, + {0x0a4, "SDR_DTUPRD1"}, + {0x0a8, "SDR_DTUPRD2"}, + {0x0ac, "SDR_DTUPRD3"}, + {0x0b0, "SDR_DTUAWDT"}, + {0x0c0, "SDR_TOGCNT1U"}, + {0x0cc, "SDR_TOGCNT100N"}, + {0x0d0, "SDR_TREFI"}, + {0x0d4, "SDR_TMRD"}, + {0x0d8, "SDR_TRFC"}, + {0x0dc, "SDR_TRP"}, + {0x0e0, "SDR_TRTW"}, + {0x0e4, "SDR_TAL"}, + {0x0e8, "SDR_TCL"}, + {0x0ec, "SDR_TCWL"}, + {0x0f0, "SDR_TRAS"}, + {0x0f4, "SDR_TRC"}, + {0x0f8, "SDR_TRCD"}, + {0x0fc, "SDR_TRRD"}, + {0x100, "SDR_TRTP"}, + {0x104, "SDR_TWR"}, + {0x108, "SDR_TWTR"}, + {0x10c, "SDR_TEXSR"}, + {0x110, "SDR_TXP"}, + {0x114, "SDR_TXPDLL"}, + {0x118, "SDR_TZQCS"}, + {0x11c, "SDR_TZQCSI"}, + {0x120, "SDR_TDQS"}, + {0x124, "SDR_TCKSRE"}, + {0x128, "SDR_TCKSRX"}, + {0x12c, "SDR_TCKE"}, + {0x130, "SDR_TMOD"}, + {0x134, "SDR_TRSTL"}, + {0x138, "SDR_TZQCL"}, + {0x13c, "SDR_TMRR"}, + {0x140, "SDR_TCKESR"}, + {0x144, "SDR_TDPD"}, + {0x200, "SDR_DTUWACTL"}, + {0x204, "SDR_DTURACTL"}, + {0x208, "SDR_DTUCFG"}, + {0x20c, "SDR_DTUECTL"}, + {0x210, "SDR_DTUWD0"}, + {0x214, "SDR_DTUWD1"}, + {0x218, "SDR_DTUWD2"}, + {0x21c, "SDR_DTUWD3"}, + {0x220, "SDR_DTUWDM"}, + {0x224, "SDR_DTURD0"}, + {0x224, "SDR_DTURD1"}, + {0x22c, "SDR_DTURD2"}, + {0x230, "SDR_DTURD3"}, + {0x234, "SDR_DTULFSRWD"}, + {0x238, "SDR_DTULFSRRD"}, + {0x23c, "SDR_DTUEAF"}, + {0x240, "SDR_DFITCTLDLY"}, + {0x244, "SDR_DFIODTCFG"}, + {0x248, "SDR_DFIODTCFG1"}, + {0x24c, "SDR_DFIODTRMAP"}, + {0x250, "SDR_DFITPHYWRD"}, + {0x254, "SDR_DFITPHYWRL"}, + {0x260, "SDR_DFITRDDEN"}, + {0x264, "SDR_DFITPHYRDL"}, + {0x270, "SDR_DFITPHYUPDTYPE0"}, + {0x274, "SDR_DFITPHYUPDTYPE1"}, + {0x278, "SDR_DFITPHYUPDTYPE2"}, + {0x27c, "SDR_DFITPHYUPDTYPE3"}, + {0x280, "SDR_DFITCTRLUPDMIN"}, + {0x284, "SDR_DFITCTRLUPDMAX"}, + {0x288, "SDR_DFITCTRLUPDDLY"}, + {0x290, "SDR_DFIUPDCFG"}, + {0x294, "SDR_DFITREFMSKI"}, + {0x298, "SDR_DFITCRLUPDI"}, + {0x2ac, "SDR_DFITRCFG0"}, + {0x2b0, "SDR_DFITRSTAT0"}, + {0x2b4, "SDR_DFITRWRLVLEN"}, + {0x2b8, "SDR_DFITRRDLVLEN"}, + {0x2bc, "SDR_DFITRRDLVLGATEEN"}, + {0x2c4, "SDR_DFISTCFG0"}, + {0x2c8, "SDR_DFISTCFG1"}, + {0x2d0, "SDR_DFITDRAMCLKEN"}, + {0x2d4, "SDR_DFITDRAMCLKDIS"}, + {0x2f0, "SDR_DFILPCFG0"}, + {0, NULL} +}; + +static struct regs +sun6i_dramphy_regs[] = { + {0x004, "SDR_PIR"}, + {0x008, "SDR_PGCR"}, + {0x00c, "SDR_PGSR"}, + {0x010, "SDR_DLLGCR"}, + {0x014, "SDR_ACDLLCR"}, + {0x018, "SDR_PTR0"}, + {0x01c, "SDR_PTR1"}, + {0x020, "SDR_PTR2"}, + {0x024, "SDR_ACIOCR"}, + {0x028, "SDR_DXCCR"}, + {0x02c, "SDR_DSGCR"}, + {0x030, "SDR_DCR"}, + {0x034, "SDR_DTPR0"}, + {0x038, "SDR_DTPR1"}, + {0x03c, "SDR_DTPR2"}, + {0x040, "SDR_MR0"}, + {0x044, "SDR_MR1"}, + {0x048, "SDR_MR2"}, + {0x04c, "SDR_MR3"}, + {0x050, "SDR_ODTCR"}, + {0x054, "SDR_DTAR"}, + {0x058, "SDR_DTDT0"}, + {0x05c, "SDR_DTDT1"}, + {0x0c0, "SDR_DCUAR"}, + {0x0c4, "SDR_DCUDR"}, + {0x0c8, "SDR_DCURR"}, + {0x0cc, "SDR_DCULR"}, + {0x0d0, "SDR_DCUGCR"}, + {0x0d4, "SDR_DCUTPR"}, + {0x0d8, "SDR_DCUSR0"}, + {0x0dc, "SDR_DCUSR1"}, + {0x100, "SDR_BISTRR"}, + {0x104, "SDR_BISTMSKR0"}, + {0x108, "SDR_BISTMSKR1"}, + {0x10c, "SDR_BISTWCR"}, + {0x110, "SDR_BISTLSR"}, + {0x114, "SDR_BISTAR0"}, + {0x118, "SDR_BISTAR1"}, + {0x11c, "SDR_BISTAR2"}, + {0x120, "SDR_BISTUDPR"}, + {0x124, "SDR_BISTGSR"}, + {0x128, "SDR_BISTWER"}, + {0x12c, "SDR_BISTBER0"}, + {0x130, "SDR_BISTBER1"}, + {0x134, "SDR_BISTBER2"}, + {0x138, "SDR_BISTWCSR"}, + {0x13c, "SDR_BISTFWR0"}, + {0x140, "SDR_BISTFWR1"}, + {0x180, "SDR_ZQ0CR0"}, + {0x184, "SDR_ZQ0CR1"}, + {0x188, "SDR_ZQ0SR0"}, + {0x18c, "SDR_ZQ0SR1"}, + {0x1c0, "SDR_DX0GCR"}, + {0x1c4, "SDR_DX0GSR0"}, + {0x1c8, "SDR_DX0GSR1"}, + {0x1cc, "SDR_DX0DLLCR"}, + {0x1d0, "SDR_DX0DQTR"}, + {0x1d4, "SDR_DX0DQSTR"}, + {0x200, "SDR_DX1GCR"}, + {0x204, "SDR_DX1GSR0"}, + {0x208, "SDR_DX1GSR1"}, + {0x20c, "SDR_DX1DLLCR"}, + {0x210, "SDR_DX1DQTR"}, + {0x214, "SDR_DX1DQSTR"}, + {0x240, "SDR_DX2GCR"}, + {0x244, "SDR_DX2GSR0"}, + {0x248, "SDR_DX2GSR1"}, + {0x24c, "SDR_DX2DLLCR"}, + {0x250, "SDR_DX2DQTR"}, + {0x254, "SDR_DX2DQSTR"}, + {0x280, "SDR_DX3GCR"}, + {0x284, "SDR_DX3GSR0"}, + {0x288, "SDR_DX3GSR1"}, + {0x28c, "SDR_DX3DLLCR"}, + {0x290, "SDR_DX3DQTR"}, + {0x294, "SDR_DX3DQSTR"}, + {0, NULL} +}; + +static int +sun6i_dram_regs_print(void) +{ + unsigned int clock; + int ret; + + ret = sunxi_dram_clock_read(&clock); + if (ret) + return ret; + + printf("DRAM Clock: %dMHz\n", clock); + + ret = dram_registers_print(SUN6I_IO_DRAMCOM_BASE, + SUN6I_IO_DRAMCOM_SIZE, + &sun6i_dramcom_regs[0], + "DRAM COM", "SDR_COM"); + if (ret) + return ret; + + ret = dram_registers_print(SUN6I_IO_DRAMCTL_BASE, + SUN6I_IO_DRAMCTL_SIZE, + &sun6i_dramctl_regs[0], + "DRAM CTL", "SDR_CTL"); + if (ret) + return ret; + + ret = dram_registers_print(SUN6I_IO_DRAMPHY_BASE, + SUN6I_IO_DRAMPHY_SIZE, + &sun6i_dramphy_regs[0], + "DRAM PHY", "SDR_PHY"); + if (ret) + return ret; + + return 0; +} + +/* + * + */ +static int +sun8i_dram_regs_print(void) +{ + unsigned int clock; + int ret; + + ret = sunxi_dram_clock_read(&clock); + if (ret) + return ret; + + printf("DRAM Clock: %dMHz\n", clock); + + ret = dram_register_range_print(SUN6I_IO_DRAMCOM_BASE, + SUN6I_IO_DRAMCOM_SIZE, + "DRAM COM", "SDR_COM"); + if (ret) + return ret; + + + ret = dram_register_range_print(SUN6I_IO_DRAMCTL_BASE, + SUN6I_IO_DRAMCTL_SIZE, + "DRAM CTL", "SDR_CTL"); + if (ret) + return ret; + + ret = dram_register_range_print(SUN6I_IO_DRAMPHY_BASE, + SUN6I_IO_DRAMPHY_SIZE, + "DRAM PHY", "SDR_PHY"); + if (ret) + return ret; + + return 0; +} + +static void +print_usage(const char *name) +{ + puts("sunxi-meminfo " VERSION "\n"); + printf("Utility to retrieve DRAM information from registers on " + "Allwinner SoCs.\n"); + printf("\n"); + printf("This is part of the sunxi-tools package from the sunxi " + "project. "); + printf("For more \ninformation visit " + "http://linux-sunxi.org/Sunxi-tools.\n"); + printf("\n"); + printf("Usage: %s [OPTION]\n", name); + printf("\n"); + printf("Options:\n"); + printf(" -f: print in FEX format (default).\n"); + printf(" -u: print in sunxi U-Boot dram.c file format.\n"); + printf(" -h: print this usage information.\n"); +} + +int +main(int argc, char *argv[]) +{ + bool uboot; + int ret; + + if (argc == 2) { + if (argv[1][0] == '-') { + if (argv[1][1] == 'f') + uboot = false; + else if (argv[1][1] == 'u') + uboot = true; + else if (argv[1][1] == 'h') + goto help; + else if ((argv[1][1] == '-') && (argv[1][2] == 'h')) + goto help; + else + goto usage; + + if (argv[1][2] != 0) + goto usage; + } else + goto usage; + } else if (argc == 1) + uboot = false; + else + goto usage; + + devmem_fd = open(DEVMEM_FILE, O_RDWR); + if (devmem_fd == -1) { + fprintf(stderr, "Error: failed to open %s: %s\n", DEVMEM_FILE, + strerror(errno)); + return errno; + } + + ret = soc_version_read(); + if (ret) + return ret; + switch (soc_version) { + case SUNXI_SOC_SUN4I: + case SUNXI_SOC_SUN5I: + case SUNXI_SOC_SUN7I: + return sun4i_dram_para_print(uboot); + case SUNXI_SOC_SUN6I: + return sun6i_dram_regs_print(); + case SUNXI_SOC_SUN8I: + case SUNXI_SOC_H3: + return sun8i_dram_regs_print(); + default: + fprintf(stderr, "Error: unknown or unhandled Soc: 0x%04X\n", + soc_version); + return -1; + } + + usage: + fprintf(stderr, "Error: wrong argument(s).\n"); + print_usage(argv[0]); + return EINVAL; + help: + print_usage(argv[0]); + return 0; +} \ No newline at end of file diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 2bccfb25..6e1c86f4 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -1489,8 +1489,8 @@ int main(int argc, char* argv[]) // Wait until BSY is released as there is a possibility for the // initiator to assert it while setting the ID (for up to 3 seconds) if (bus->GetBSY()) { - int now = SysTimer::GetTimerLow(); - while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { + int now = SysTimer::instance()->GetTimerLow(); + while ((SysTimer::instance()->GetTimerLow() - now) < 3 * 1000 * 1000) { bus->Acquire(); if (!bus->GetBSY()) { break; diff --git a/src/raspberrypi/rasdump.cpp b/src/raspberrypi/rasdump.cpp index e31fe570..2c7bc58f 100644 --- a/src/raspberrypi/rasdump.cpp +++ b/src/raspberrypi/rasdump.cpp @@ -212,8 +212,8 @@ bool WaitPhase(BUS::phase_t phase) DWORD now; // Timeout (3000ms) - now = SysTimer::GetTimerLow(); - while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { + now = SysTimer::instance()->GetTimerLow(); + while ((SysTimer::instance()->GetTimerLow() - now) < 3 * 1000 * 1000) { bus.Acquire(); if (bus.GetREQ() && bus.GetPhase() == phase) { return true; diff --git a/src/raspberrypi/registers b/src/raspberrypi/registers new file mode 100755 index 0000000000000000000000000000000000000000..465aebecd60a70acff19a7ccaeb8ff1341d165e5 GIT binary patch literal 31972 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

PM(AU!fq01! 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 YQ4jH +//https://yhbt.net/lore/all/20140707085858.GG16262@lukather/T/ + + +// +// Access the Raspberry Pi System Timer registers directly. +// +#include +#include +#include +#include +#include +#include + + +#include "common.h" + +typedef uint32_t u32; + +/* from u-boot code: */ +struct sun4i_dram_para { + u32 baseaddr; + u32 clock; + u32 type; + u32 rank_num; + u32 density; + u32 io_width; + u32 bus_width; + u32 cas; + u32 zq; + u32 odt_en; + u32 size; + u32 tpr0; + u32 tpr1; + u32 tpr2; + u32 tpr3; + u32 tpr4; + u32 tpr5; + u32 emr1; + u32 emr2; + u32 emr3; +}; + +#define DEVMEM_FILE "/dev/mem" +static int devmem_fd; + +enum sunxi_soc_version { + SUNXI_SOC_SUN4I = 0x1623, /* A10 */ + SUNXI_SOC_SUN5I = 0x1625, /* A13, A10s */ + SUNXI_SOC_SUN6I = 0x1633, /* A31 */ + SUNXI_SOC_SUN7I = 0x1651, /* A20 */ + SUNXI_SOC_SUN8I = 0x1650, /* A23 */ + SUNXI_SOC_SUN9I = 0x1667, /* A33 */ + SUNXI_SOC_SUN10I = 0x1635, /* A80 */ + SUNXI_SOC_H3 = 0x1680, /* H3 */ +}; + +static enum sunxi_soc_version soc_version; + +// #define PERIPHERAL_BASE 0x20000000 // For Pi 1 and 2 +//#define PERIPHERAL_BASE 0x3F000000 // For Pi 3 +#define PERIPHERAL_BASE 0xfe000000 // For PI 4 +#define SYSTEM_TIMER_OFFSET 0x3000 + +volatile void* hs_timer; +volatile void* system_bus; + +static const uint32_t system_bus_base_address = 0x01C20000; + +static const uint32_t BUS_CLK_GATING_REG0 = 0x60; +static const uint32_t BUS_CLK_GATING_REG1 = 0x64; +static const uint32_t BUS_CLK_GATING_REG2 = 0x68; +static const uint32_t BUS_CLK_GATING_REG3 = 0x6C; +static const uint32_t BUS_CLK_GATING_REG4 = 0x70; + +static const uint32_t BUS_CLK_GATING_REG0_USBOHCI3 =31; +static const uint32_t BUS_CLK_GATING_REG0_USBOHCI2 =30; +static const uint32_t BUS_CLK_GATING_REG0_USBOHCI1 =29; +static const uint32_t BUS_CLK_GATING_REG0_USBOHCI0 =28; +static const uint32_t BUS_CLK_GATING_REG0_USBEHCI3 =27; +static const uint32_t BUS_CLK_GATING_REG0_USBEHCI2 =26; +static const uint32_t BUS_CLK_GATING_REG0_USBEHCI1 =25; +static const uint32_t BUS_CLK_GATING_REG0_USBEHCI0 =24; +static const uint32_t BUS_CLK_GATING_REG0_USB_OTG =23; +static const uint32_t BUS_CLK_GATING_REG0_SPI1 =21; +static const uint32_t BUS_CLK_GATING_REG0_SPI0 =20; +static const uint32_t BUS_CLK_GATING_REG0_HSTMR =19; +static const uint32_t BUS_CLK_GATING_REG0_TS =18; +static const uint32_t BUS_CLK_GATING_REG0_EMAC =17; +static const uint32_t BUS_CLK_GATING_REG0_DRAM =14; +static const uint32_t BUS_CLK_GATING_REG0_NAND =13; +static const uint32_t BUS_CLK_GATING_REG0_MMC2 =10; +static const uint32_t BUS_CLK_GATING_REG0_MMC1 =9; +static const uint32_t BUS_CLK_GATING_REG0_MMC0 =8; +static const uint32_t BUS_CLK_GATING_REG0_DMA =6; +static const uint32_t BUS_CLK_GATING_REG0_CE =5; + + +static const uint32_t BUS_SOFT_RST_REG0 = 0x2C0; +static const uint32_t BUS_SOFT_RST_REG1 = 0x2C4; +static const uint32_t BUS_SOFT_RST_REG2 = 0x2C8; +static const uint32_t BUS_SOFT_RST_REG3 = 0x2D0; +static const uint32_t BUS_SOFT_RST_REG4 = 0x2D8; + + +static const uint32_t BUS_SOFT_RST_REG0_USBOHCI3 =31; +static const uint32_t BUS_SOFT_RST_REG0_USBOHCI2 =30; +static const uint32_t BUS_SOFT_RST_REG0_USBOHCI1 =29; +static const uint32_t BUS_SOFT_RST_REG0_USBOHCI0 =28; +static const uint32_t BUS_SOFT_RST_REG0_USBEHCI3 =27; +static const uint32_t BUS_SOFT_RST_REG0_USBEHCI2 =26; +static const uint32_t BUS_SOFT_RST_REG0_USBEHCI1 =25; +static const uint32_t BUS_SOFT_RST_REG0_USBEHCI0 =24; +static const uint32_t BUS_SOFT_RST_REG0_USB_OTG =23; +static const uint32_t BUS_SOFT_RST_REG0_SPI1 =21; +static const uint32_t BUS_SOFT_RST_REG0_SPI0 =20; +static const uint32_t BUS_SOFT_RST_REG0_HSTMR =19; +static const uint32_t BUS_SOFT_RST_REG0_TS =18; +static const uint32_t BUS_SOFT_RST_REG0_EMAC =17; +static const uint32_t BUS_SOFT_RST_REG0_DRAM =14; +static const uint32_t BUS_SOFT_RST_REG0_NAND =13; +static const uint32_t BUS_SOFT_RST_REG0_MMC2 =10; +static const uint32_t BUS_SOFT_RST_REG0_MMC1 =9; +static const uint32_t BUS_SOFT_RST_REG0_MMC0 =8; +static const uint32_t BUS_SOFT_RST_REG0_DMA =6; +static const uint32_t BUS_SOFT_RST_REG0_CE =5; + + + +/* + * Find out exactly which SoC we are dealing with. + */ +#define SUNXI_IO_SRAM_BASE 0x01C00000 +#define SUNXI_IO_SRAM_SIZE 0x00001000 + +#define SUNXI_IO_SRAM_VERSION 0x24 + + +static const uint32_t hs_timer_base_address = 0x01C60000; + + +static const uint32_t HS_TMR_IRA_EN_EG = 0x00; +static const uint32_t HS_TMR_IRQ_STAT_REG = 0x04; +static const uint32_t HS_TMR_CTRL_REG = 0x10; +static const uint32_t HS_TMR_INTV_LO_REG = 0x14; +static const uint32_t HS_TMR_INTV_HI_REG = 0x18; +static const uint32_t HS_TMR_CURNT_LO_REG = 0x1C; +static const uint32_t HS_TMR_CURNT_HI_REG = 0x20; + + + + +#define ST_BASE (PERIPHERAL_BASE + SYSTEM_TIMER_OFFSET) + +// Sytem Timer Registers layout +typedef struct { + uint32_t control_and_status; + uint32_t counter_low; + uint32_t counter_high; + uint32_t compare_0; + uint32_t compare_1; + uint32_t compare_2; + uint32_t compare_3; +} system_timer_t; + + +inline uint32_t set_bit(uint32_t value, uint32_t bit_num){ + return( value | (1 << bit_num)); +} + +inline uint32_t clear_bit(uint32_t value, uint32_t bit_num){ + return( value & ~(1 << bit_num)); +} + +inline uint32_t get_bit(uint32_t value, uint32_t bit_num){ + return ((value >> bit_num) & 1UL); +} + + +inline uint32_t io_readl(volatile void* base, uint32_t offset){ + return *(volatile uint32_t*) ((uint32_t)base + offset); +} + +inline void io_writel(volatile void* base, uint32_t offset, uint32_t value){ + *(volatile uint32_t*) ((uint32_t)base + offset) = value; +} + +void +inline sunxi_io_mask(void *base, int offset, unsigned int value, unsigned int mask) +{ + unsigned int tmp = io_readl(base, offset); + + tmp &= ~mask; + tmp |= value & mask; + + io_writel(base, offset, tmp); +} + +inline uint32_t sysbus_readl(uint32_t offset) { return io_readl(system_bus, offset); } +inline void sysbus_writel(uint32_t offset, uint32_t value){ io_writel(system_bus, offset, value);} +inline uint32_t hstimer_readl(uint32_t offset) { return io_readl(hs_timer, offset); } +inline void hstimer_writel(uint32_t offset, uint32_t value) { io_writel(hs_timer, offset, value);} + +void dump_sys_bus(){ + + printf("System bus..... %08X\n\r", system_bus_base_address); + printf("Gating Reg: %08X %08X %08X %08X %08X\n\r", + sysbus_readl(BUS_CLK_GATING_REG0), + sysbus_readl(BUS_CLK_GATING_REG1), + sysbus_readl(BUS_CLK_GATING_REG2), + sysbus_readl(BUS_CLK_GATING_REG3), + sysbus_readl(BUS_CLK_GATING_REG4) + ); + printf("Reset Reg: %08X %08X %08X %08X %08X\n\r", + sysbus_readl(BUS_SOFT_RST_REG0), + sysbus_readl(BUS_SOFT_RST_REG1), + sysbus_readl(BUS_SOFT_RST_REG2), + sysbus_readl(BUS_SOFT_RST_REG3), + sysbus_readl(BUS_SOFT_RST_REG4) + ); + +} + + +void dump_hs_timer(){ + + printf("Hs timer..... %08X\n\r", hs_timer_base_address); + printf("HS_TMR_IRA_EN_EG %08X\n\r", hstimer_readl(HS_TMR_IRA_EN_EG)); + printf("HS_TMR_IRQ_STAT_REG %08X\n\r", hstimer_readl(HS_TMR_IRQ_STAT_REG)); + printf("HS_TMR_CTRL_REG %08X\n\r", hstimer_readl(HS_TMR_CTRL_REG)); + printf("HS_TMR_INTV_LO_REG %08X\n\r", hstimer_readl(HS_TMR_INTV_LO_REG)); + printf("HS_TMR_CURNT_LO_REG %08X\n\r", hstimer_readl(HS_TMR_CURNT_LO_REG)); + printf("HS_TMR_CURNT_HI_REG %08X\n\r", hstimer_readl(HS_TMR_CURNT_HI_REG)); + +} + +static int +soc_version_read(void) +{ + void *base; + unsigned int restore; + + base = mmap(NULL, SUNXI_IO_SRAM_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, devmem_fd, SUNXI_IO_SRAM_BASE); + if (base == MAP_FAILED) { + fprintf(stderr, "Failed to map sram registers:"); + // %s\n", + // strerror(errno)); + return -1; + } + + restore = io_readl(base, SUNXI_IO_SRAM_VERSION); + + sunxi_io_mask(base, SUNXI_IO_SRAM_VERSION, 0x8000, 0x8000); + + soc_version = (sunxi_soc_version)(io_readl(base, SUNXI_IO_SRAM_VERSION) >> 16); + + sunxi_io_mask(base, SUNXI_IO_SRAM_VERSION, restore, 0x8000); + + munmap(base, SUNXI_IO_SRAM_SIZE); + + return 0; +} + + + +// Get access to the System Timer registers in user memory space. +void get_hs_timer() { + + int fd; + + if ((fd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) { + printf("1 can't open /dev/mem \n"); + exit(-1); + } + + hs_timer = mmap( + NULL, + 4096, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + // ST_BASE + hs_timer_base_address + ); + + system_bus = mmap( + NULL, + 4096, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + // ST_BASE + system_bus_base_address + ); + + close(fd); + + if (hs_timer == MAP_FAILED) { + printf("mmap error %d\n", (int)hs_timer); // errno also set! + exit(-1); + } +} + +int main(int argc, char **argv) { + devmem_fd = open(DEVMEM_FILE, O_RDWR); + if (devmem_fd == -1) { + fprintf(stderr, "Error: failed to open %s\n", DEVMEM_FILE); + } + + (void)soc_version_read(); + printf("SoC Version: %08X\n\r", (uint32_t)soc_version); + + get_hs_timer(); + + // uint32_t t0, t1 = 0; + + // uint32_t delay = 2; + + dump_sys_bus(); + + + + + +// By default, the HSTimer clock gating is masked. When it is necessary to use +// the HSTimer, its clock gating should be opened in BUS Clock Gating Register 0 +// and then de-assert the software reset in BUS Software Reset Register 0 on the +// CCU module. If it is not needed to use the HSTimer, both the gating bit and +// the software reset bit should be set 0. + + + printf("[Before] CLK GATE: %08X SOFT RST: %08X\n\r", + sysbus_readl(BUS_CLK_GATING_REG0), + sysbus_readl(BUS_SOFT_RST_REG0)); + + sysbus_writel(BUS_CLK_GATING_REG0, set_bit(sysbus_readl(BUS_CLK_GATING_REG0), BUS_CLK_GATING_REG0_HSTMR)); + sysbus_writel(BUS_SOFT_RST_REG0, set_bit(sysbus_readl(BUS_SOFT_RST_REG0), BUS_SOFT_RST_REG0_HSTMR)); + + + printf("[After] CLK GATE: %08X SOFT RST: %08X\n\r", + sysbus_readl(BUS_CLK_GATING_REG0), + sysbus_readl(BUS_SOFT_RST_REG0)); + + +// Make a 1us delay using HSTimer for an instance as follow: +// AHB1CLK will be configured as 100MHz and n_mode, +// Single mode and 2 pre-scale will be selected in this instance + +// Set interval value Hi 0x0 +hstimer_writel(HS_TMR_INTV_HI_REG, 0x0); +// Set interval value Lo 0x32 +hstimer_writel(HS_TMR_INTV_LO_REG, 0x32000000); +// Select n_mode,2 prescale, single mode +hstimer_writel(HS_TMR_CTRL_REG, 0x90); +// Set reload bit +hstimer_writel(HS_TMR_CTRL_REG, hstimer_readl(HS_TMR_CTRL_REG)|(1<<1)); +// Enable HSTimer +hstimer_writel(HS_TMR_CTRL_REG, hstimer_readl(HS_TMR_CTRL_REG)|(1<<0)); +//Wait for HSTimer to generate pending +while (!(hstimer_readl(HS_TMR_IRQ_STAT_REG)&0x1)); +// Clear HSTimer pending +hstimer_writel(HS_TMR_IRQ_STAT_REG, 1); + +dump_hs_timer(); + + + // while (1) { + // t0 = system_timer->counter_low; + // while((system_timer->counter_low - t0) < delay) + // // usleep(100); + // t1 = system_timer->counter_low; + // printf ("Elaspsed = %d\n", t1 - t0); + // printf ("Conter high = %d\n", system_timer->counter_high); + // t0 = t1; + // sleep(1); + // } + return 0; +} + + +// int main(int argc, char **argv) { +// volatile system_timer_t* system_timer = get_system_timer(); +// int32_t t0, t1; + +// while (1) { +// t0 = system_timer->counter_low; +// usleep(100); +// t1 = system_timer->counter_low; +// printf ("Elaspsed = %d\n", t1 - t0); +// printf ("Conter high = %d\n", system_timer->counter_high); +// t0 = t1; +// } +// return 0; +// } \ No newline at end of file diff --git a/src/raspberrypi/registers.d b/src/raspberrypi/registers.d new file mode 100644 index 00000000..550d2519 --- /dev/null +++ b/src/raspberrypi/registers.d @@ -0,0 +1,167 @@ +registers: registers.c /usr/include/stdc-predef.h /usr/include/stdio.h \ + /usr/include/arm-linux-gnueabihf/bits/libc-header-start.h \ + /usr/include/features.h /usr/include/features-time64.h \ + /usr/include/arm-linux-gnueabihf/bits/wordsize.h \ + /usr/include/arm-linux-gnueabihf/bits/timesize.h \ + /usr/include/arm-linux-gnueabihf/sys/cdefs.h \ + /usr/include/arm-linux-gnueabihf/bits/long-double.h \ + /usr/include/arm-linux-gnueabihf/gnu/stubs.h \ + /usr/include/arm-linux-gnueabihf/gnu/stubs-hard.h \ + /usr/lib/gcc/arm-linux-gnueabihf/11/include/stddef.h \ + /usr/lib/gcc/arm-linux-gnueabihf/11/include/stdarg.h \ + /usr/include/arm-linux-gnueabihf/bits/types.h \ + /usr/include/arm-linux-gnueabihf/bits/typesizes.h \ + /usr/include/arm-linux-gnueabihf/bits/time64.h \ + /usr/include/arm-linux-gnueabihf/bits/types/__fpos_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/__mbstate_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/__fpos64_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/__FILE.h \ + /usr/include/arm-linux-gnueabihf/bits/types/FILE.h \ + /usr/include/arm-linux-gnueabihf/bits/types/struct_FILE.h \ + /usr/include/arm-linux-gnueabihf/bits/types/cookie_io_functions_t.h \ + /usr/include/arm-linux-gnueabihf/bits/stdio_lim.h \ + /usr/include/arm-linux-gnueabihf/bits/floatn.h \ + /usr/include/arm-linux-gnueabihf/bits/floatn-common.h \ + /usr/include/c++/11/stdlib.h /usr/include/c++/11/cstdlib \ + /usr/include/arm-linux-gnueabihf/c++/11/bits/c++config.h \ + /usr/include/arm-linux-gnueabihf/c++/11/bits/os_defines.h \ + /usr/include/arm-linux-gnueabihf/c++/11/bits/cpu_defines.h \ + /usr/include/c++/11/pstl/pstl_config.h /usr/include/stdlib.h \ + /usr/include/arm-linux-gnueabihf/bits/waitflags.h \ + /usr/include/arm-linux-gnueabihf/bits/waitstatus.h \ + /usr/include/arm-linux-gnueabihf/bits/types/locale_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/__locale_t.h \ + /usr/include/arm-linux-gnueabihf/sys/types.h \ + /usr/include/arm-linux-gnueabihf/bits/types/clock_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/clockid_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/time_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/timer_t.h \ + /usr/include/arm-linux-gnueabihf/bits/stdint-intn.h \ + /usr/include/endian.h /usr/include/arm-linux-gnueabihf/bits/endian.h \ + /usr/include/arm-linux-gnueabihf/bits/endianness.h \ + /usr/include/arm-linux-gnueabihf/bits/byteswap.h \ + /usr/include/arm-linux-gnueabihf/bits/uintn-identity.h \ + /usr/include/arm-linux-gnueabihf/sys/select.h \ + /usr/include/arm-linux-gnueabihf/bits/select.h \ + /usr/include/arm-linux-gnueabihf/bits/types/sigset_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/__sigset_t.h \ + /usr/include/arm-linux-gnueabihf/bits/types/struct_timeval.h \ + /usr/include/arm-linux-gnueabihf/bits/types/struct_timespec.h \ + /usr/include/arm-linux-gnueabihf/bits/pthreadtypes.h \ + /usr/include/arm-linux-gnueabihf/bits/thread-shared-types.h \ + /usr/include/arm-linux-gnueabihf/bits/pthreadtypes-arch.h \ + /usr/include/arm-linux-gnueabihf/bits/atomic_wide_counter.h \ + /usr/include/arm-linux-gnueabihf/bits/struct_mutex.h \ + /usr/include/arm-linux-gnueabihf/bits/struct_rwlock.h \ + /usr/include/alloca.h \ + /usr/include/arm-linux-gnueabihf/bits/stdlib-float.h \ + /usr/include/c++/11/bits/std_abs.h /usr/include/fcntl.h \ + /usr/include/arm-linux-gnueabihf/bits/fcntl.h \ + /usr/include/arm-linux-gnueabihf/bits/fcntl-linux.h \ + /usr/include/arm-linux-gnueabihf/bits/types/struct_iovec.h \ + /usr/include/linux/falloc.h /usr/include/arm-linux-gnueabihf/bits/stat.h \ + /usr/include/arm-linux-gnueabihf/bits/struct_stat.h \ + /usr/include/arm-linux-gnueabihf/sys/mman.h \ + /usr/include/arm-linux-gnueabihf/bits/mman.h \ + /usr/include/arm-linux-gnueabihf/bits/mman-map-flags-generic.h \ + /usr/include/arm-linux-gnueabihf/bits/mman-linux.h \ + /usr/include/arm-linux-gnueabihf/bits/mman-shared.h \ + /usr/include/unistd.h /usr/include/arm-linux-gnueabihf/bits/posix_opt.h \ + /usr/include/arm-linux-gnueabihf/bits/environments.h \ + /usr/include/arm-linux-gnueabihf/bits/confname.h \ + /usr/include/arm-linux-gnueabihf/bits/getopt_posix.h \ + /usr/include/arm-linux-gnueabihf/bits/getopt_core.h \ + /usr/include/arm-linux-gnueabihf/bits/unistd_ext.h \ + /usr/include/linux/close_range.h \ + /usr/lib/gcc/arm-linux-gnueabihf/11/include/stdint.h \ + /usr/include/stdint.h /usr/include/arm-linux-gnueabihf/bits/wchar.h \ + /usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h common.h version.h +/usr/include/stdc-predef.h: +/usr/include/stdio.h: +/usr/include/arm-linux-gnueabihf/bits/libc-header-start.h: +/usr/include/features.h: +/usr/include/features-time64.h: +/usr/include/arm-linux-gnueabihf/bits/wordsize.h: +/usr/include/arm-linux-gnueabihf/bits/timesize.h: +/usr/include/arm-linux-gnueabihf/sys/cdefs.h: +/usr/include/arm-linux-gnueabihf/bits/long-double.h: +/usr/include/arm-linux-gnueabihf/gnu/stubs.h: +/usr/include/arm-linux-gnueabihf/gnu/stubs-hard.h: +/usr/lib/gcc/arm-linux-gnueabihf/11/include/stddef.h: +/usr/lib/gcc/arm-linux-gnueabihf/11/include/stdarg.h: +/usr/include/arm-linux-gnueabihf/bits/types.h: +/usr/include/arm-linux-gnueabihf/bits/typesizes.h: +/usr/include/arm-linux-gnueabihf/bits/time64.h: +/usr/include/arm-linux-gnueabihf/bits/types/__fpos_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/__mbstate_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/__fpos64_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/__FILE.h: +/usr/include/arm-linux-gnueabihf/bits/types/FILE.h: +/usr/include/arm-linux-gnueabihf/bits/types/struct_FILE.h: +/usr/include/arm-linux-gnueabihf/bits/types/cookie_io_functions_t.h: +/usr/include/arm-linux-gnueabihf/bits/stdio_lim.h: +/usr/include/arm-linux-gnueabihf/bits/floatn.h: +/usr/include/arm-linux-gnueabihf/bits/floatn-common.h: +/usr/include/c++/11/stdlib.h: +/usr/include/c++/11/cstdlib: +/usr/include/arm-linux-gnueabihf/c++/11/bits/c++config.h: +/usr/include/arm-linux-gnueabihf/c++/11/bits/os_defines.h: +/usr/include/arm-linux-gnueabihf/c++/11/bits/cpu_defines.h: +/usr/include/c++/11/pstl/pstl_config.h: +/usr/include/stdlib.h: +/usr/include/arm-linux-gnueabihf/bits/waitflags.h: +/usr/include/arm-linux-gnueabihf/bits/waitstatus.h: +/usr/include/arm-linux-gnueabihf/bits/types/locale_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/__locale_t.h: +/usr/include/arm-linux-gnueabihf/sys/types.h: +/usr/include/arm-linux-gnueabihf/bits/types/clock_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/clockid_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/time_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/timer_t.h: +/usr/include/arm-linux-gnueabihf/bits/stdint-intn.h: +/usr/include/endian.h: +/usr/include/arm-linux-gnueabihf/bits/endian.h: +/usr/include/arm-linux-gnueabihf/bits/endianness.h: +/usr/include/arm-linux-gnueabihf/bits/byteswap.h: +/usr/include/arm-linux-gnueabihf/bits/uintn-identity.h: +/usr/include/arm-linux-gnueabihf/sys/select.h: +/usr/include/arm-linux-gnueabihf/bits/select.h: +/usr/include/arm-linux-gnueabihf/bits/types/sigset_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/__sigset_t.h: +/usr/include/arm-linux-gnueabihf/bits/types/struct_timeval.h: +/usr/include/arm-linux-gnueabihf/bits/types/struct_timespec.h: +/usr/include/arm-linux-gnueabihf/bits/pthreadtypes.h: +/usr/include/arm-linux-gnueabihf/bits/thread-shared-types.h: +/usr/include/arm-linux-gnueabihf/bits/pthreadtypes-arch.h: +/usr/include/arm-linux-gnueabihf/bits/atomic_wide_counter.h: +/usr/include/arm-linux-gnueabihf/bits/struct_mutex.h: +/usr/include/arm-linux-gnueabihf/bits/struct_rwlock.h: +/usr/include/alloca.h: +/usr/include/arm-linux-gnueabihf/bits/stdlib-float.h: +/usr/include/c++/11/bits/std_abs.h: +/usr/include/fcntl.h: +/usr/include/arm-linux-gnueabihf/bits/fcntl.h: +/usr/include/arm-linux-gnueabihf/bits/fcntl-linux.h: +/usr/include/arm-linux-gnueabihf/bits/types/struct_iovec.h: +/usr/include/linux/falloc.h: +/usr/include/arm-linux-gnueabihf/bits/stat.h: +/usr/include/arm-linux-gnueabihf/bits/struct_stat.h: +/usr/include/arm-linux-gnueabihf/sys/mman.h: +/usr/include/arm-linux-gnueabihf/bits/mman.h: +/usr/include/arm-linux-gnueabihf/bits/mman-map-flags-generic.h: +/usr/include/arm-linux-gnueabihf/bits/mman-linux.h: +/usr/include/arm-linux-gnueabihf/bits/mman-shared.h: +/usr/include/unistd.h: +/usr/include/arm-linux-gnueabihf/bits/posix_opt.h: +/usr/include/arm-linux-gnueabihf/bits/environments.h: +/usr/include/arm-linux-gnueabihf/bits/confname.h: +/usr/include/arm-linux-gnueabihf/bits/getopt_posix.h: +/usr/include/arm-linux-gnueabihf/bits/getopt_core.h: +/usr/include/arm-linux-gnueabihf/bits/unistd_ext.h: +/usr/include/linux/close_range.h: +/usr/lib/gcc/arm-linux-gnueabihf/11/include/stdint.h: +/usr/include/stdint.h: +/usr/include/arm-linux-gnueabihf/bits/wchar.h: +/usr/include/arm-linux-gnueabihf/bits/stdint-uintn.h: +common.h: +version.h: diff --git a/src/raspberrypi/registers_raspi.c b/src/raspberrypi/registers_raspi.c new file mode 100644 index 00000000..42fdf7cb --- /dev/null +++ b/src/raspberrypi/registers_raspi.c @@ -0,0 +1,106 @@ + +// Kernel module to access cycle count registers: +// https://matthewarcus.wordpress.com/2018/01/27/using-the-cycle-counter-registers-on-the-raspberry-pi-3/ + + +//https://mindplusplus.wordpress.com/2013/05/21/accessing-the-raspberry-pis-1mhz-timer/ + +// Reading register from user space: +// https://stackoverflow.com/questions/59749160/reading-from-register-of-allwinner-h3-arm-processor + + +// Maybe kernel patch> +//https://yhbt.net/lore/all/20140707085858.GG16262@lukather/T/ + + +// +// Access the Raspberry Pi System Timer registers directly. +// +#include +#include +#include +#include +#include +#include + +// #define PERIPHERAL_BASE 0x20000000 // For Pi 1 and 2 +//#define PERIPHERAL_BASE 0x3F000000 // For Pi 3 +#define PERIPHERAL_BASE 0xfe000000 // For PI 4 +#define SYSTEM_TIMER_OFFSET 0x3000 + + +#define ST_BASE (PERIPHERAL_BASE + SYSTEM_TIMER_OFFSET) + +// Sytem Timer Registers layout +typedef struct { + uint32_t control_and_status; + uint32_t counter_low; + uint32_t counter_high; + uint32_t compare_0; + uint32_t compare_1; + uint32_t compare_2; + uint32_t compare_3; +} system_timer_t; + +// Get access to the System Timer registers in user memory space. +system_timer_t * get_system_timer() { + void *system_timer; + int fd; + + if ((fd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) { + printf("1 can't open /dev/mem \n"); + exit(-1); + } + + system_timer = mmap( + NULL, + 4096, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + ST_BASE + ); + + close(fd); + + if (system_timer == MAP_FAILED) { + printf("mmap error %d\n", (int)system_timer); // errno also set! + exit(-1); + } + return (system_timer_t*)system_timer; +} + +int main(int argc, char **argv) { + volatile system_timer_t* system_timer = get_system_timer(); + uint32_t t0, t1 = 0; + + uint32_t delay = 2; + + while (1) { + t0 = system_timer->counter_low; + while((system_timer->counter_low - t0) < delay) + // usleep(100); + t1 = system_timer->counter_low; + printf ("Elaspsed = %d\n", t1 - t0); + printf ("Conter high = %d\n", system_timer->counter_high); + t0 = t1; + sleep(1); + } + return 0; +} + + +// int main(int argc, char **argv) { +// volatile system_timer_t* system_timer = get_system_timer(); +// int32_t t0, t1; + +// while (1) { +// t0 = system_timer->counter_low; +// usleep(100); +// t1 = system_timer->counter_low; +// printf ("Elaspsed = %d\n", t1 - t0); +// printf ("Conter high = %d\n", system_timer->counter_high); +// t0 = t1; +// } +// return 0; +// } \ No newline at end of file diff --git a/src/raspberrypi/version.h b/src/raspberrypi/version.h new file mode 100644 index 00000000..ffc39266 --- /dev/null +++ b/src/raspberrypi/version.h @@ -0,0 +1 @@ +#define VERSION "0" \ No newline at end of file