mirror of
https://github.com/akuker/RASCSI.git
synced 2024-11-25 20:33:35 +00:00
registers working
This commit is contained in:
parent
68a95794da
commit
f5ee073eaf
@ -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
|
||||
|
48
src/raspberrypi/common.h
Normal file
48
src/raspberrypi/common.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Alejandro Mery <amery@geeks.cl>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _SUNXI_TOOLS_COMMON_H
|
||||
#define _SUNXI_TOOLS_COMMON_H
|
||||
|
||||
#include <stddef.h> /* 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 */
|
@ -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;
|
||||
}
|
||||
|
0
src/raspberrypi/hal/allwinner_hal.cpp
Normal file
0
src/raspberrypi/hal/allwinner_hal.cpp
Normal file
0
src/raspberrypi/hal/allwinner_hal.h
Normal file
0
src/raspberrypi/hal/allwinner_hal.h
Normal file
@ -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;
|
||||
}
|
||||
|
203
src/raspberrypi/hal/sbc_version.cpp
Normal file
203
src/raspberrypi/hal/sbc_version.cpp
Normal file
@ -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 <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
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<std::string, SBC_Version::sbc_version_type> 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
|
68
src/raspberrypi/hal/sbc_version.h
Normal file
68
src/raspberrypi/hal/sbc_version.h
Normal file
@ -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 <string>
|
||||
#include <map>
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// 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<std::string, sbc_version_type> m_proc_device_tree_mapping;
|
||||
|
||||
static const std::string m_device_tree_model_path;
|
||||
|
||||
static DWORD GetDeviceTreeRanges(const char *filename, DWORD offset);
|
||||
|
||||
};
|
@ -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<SysTimer> 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<SysTimer_Raspberry>();
|
||||
private_instance->Init();
|
||||
}
|
||||
else if(SBC_Version::IsBananaPi()){
|
||||
private_instance = std::make_shared<SysTimer_AllWinner>();
|
||||
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) {
|
||||
|
@ -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<SysTimer> private_instance;
|
||||
};
|
||||
|
136
src/raspberrypi/hal/systimer_allwinner.cpp
Normal file
136
src/raspberrypi/hal/systimer_allwinner.cpp
Normal file
@ -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 <sys/mman.h>
|
||||
|
||||
#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<SysTimer_Raspberry>();
|
||||
private_instance->Init();
|
||||
}
|
||||
else if(SBC_Version::IsBananaPi()){
|
||||
private_instance = std::make_shared<SysTimer_AllWinner>();
|
||||
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);
|
||||
}
|
42
src/raspberrypi/hal/systimer_allwinner.h
Normal file
42
src/raspberrypi/hal/systimer_allwinner.h
Normal file
@ -0,0 +1,42 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2022 akuker
|
||||
//
|
||||
// [ High resolution timer ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
||||
};
|
153
src/raspberrypi/hal/systimer_raspberry.cpp
Normal file
153
src/raspberrypi/hal/systimer_raspberry.cpp
Normal file
@ -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 <sys/mman.h>
|
||||
|
||||
#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<SysTimer_Raspberry>();
|
||||
private_instance->Init();
|
||||
}
|
||||
else if(SBC_Version::IsBananaPi()){
|
||||
private_instance = std::make_shared<SysTimer_AllWinner>();
|
||||
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);
|
||||
}
|
45
src/raspberrypi/hal/systimer_raspberry.h
Normal file
45
src/raspberrypi/hal/systimer_raspberry.h
Normal file
@ -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 <stdint.h>
|
||||
#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
|
||||
};
|
BIN
src/raspberrypi/mem-info
Executable file
BIN
src/raspberrypi/mem-info
Executable file
Binary file not shown.
793
src/raspberrypi/mem-info.c
Normal file
793
src/raspberrypi/mem-info.c
Normal file
@ -0,0 +1,793 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Floris Bos <bos@je-eigen-domein.nl>
|
||||
* Copyright (c) 2014 Luc Verhaegen <libv@skynet.be>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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 <asm/arch/dram.h>\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;
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
BIN
src/raspberrypi/registers
Executable file
BIN
src/raspberrypi/registers
Executable file
Binary file not shown.
406
src/raspberrypi/registers.c
Normal file
406
src/raspberrypi/registers.c
Normal file
@ -0,0 +1,406 @@
|
||||
|
||||
// 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#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;
|
||||
// }
|
167
src/raspberrypi/registers.d
Normal file
167
src/raspberrypi/registers.d
Normal file
@ -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:
|
106
src/raspberrypi/registers_raspi.c
Normal file
106
src/raspberrypi/registers_raspi.c
Normal file
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// #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;
|
||||
// }
|
1
src/raspberrypi/version.h
Normal file
1
src/raspberrypi/version.h
Normal file
@ -0,0 +1 @@
|
||||
#define VERSION "0"
|
Loading…
Reference in New Issue
Block a user