Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,96 @@
#pragma once
#include <boost/asio/steady_timer.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/container/flat_map.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/bus/match.hpp>
#include <string>
#include <iostream>
#define MAX_CPU_ID 2
#define MAX_DIMM_RANK 12
#define STATUS_TEMP_NUM 3
#define STATUS_PMIC_RAIL_NUM 6
#define STATUS_REG_NUM 8
extern std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_temp_inf;
extern std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_voltage_inf;
extern std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_current_inf;
extern std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_power_inf;
extern std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_statusReg_inf;
enum FieldType {
VOLTAGE,
CURRENT,
POWER,
TEMP,
STATUS
};
struct DimmData
{
uint8_t reg[STATUS_REG_NUM];
double voltage[STATUS_PMIC_RAIL_NUM];
double current[STATUS_PMIC_RAIL_NUM];
double power[STATUS_PMIC_RAIL_NUM];
double temp[STATUS_TEMP_NUM];
};
struct DimmI3CAddr
{
std::string spdAddr;
std::string pmicAddr;
};
enum PMICType {
PMIC5000 = 0,
PMIC5010,
PMIC5100,
PMIC5020,
PMIC5120,
PMIC5200,
PMIC5030
};
struct DIMMSpdReader : std::enable_shared_from_this<DIMMSpdReader>
{
DIMMSpdReader(boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
const float pollRate) : sensorPollMs(static_cast<unsigned int>(pollRate * 1000)),
objectServer(objectServer), waitTimer(io) {};
~DIMMSpdReader()
{
waitTimer.cancel();
};
void init();
void startRead();
void readDimmInfo();
int getDIMMRegsTemp(uint8_t cpuid, uint8_t rank, DimmData& dimmData);
int getDIMMRegsVol(uint8_t cpuid, uint8_t rank, DimmData& dimmData);
int getDIMMRegsCurAndPow(uint8_t cpuid, uint8_t rank, DimmData& dimmData);
void updateDbus();
void updateToDimmInfoFile();
void setupMatches(sdbusplus::bus_t&);
void dimmI3cSwitchMatcher( std::vector<sdbusplus::bus::match_t>& matches,
sdbusplus::bus_t& connection, std::function<void(bool)>&& onMatch);
void getdimmI3cSwitchState(const std::shared_ptr<sdbusplus::asio::connection>& conn, size_t retries = 2);
int getPmicType(uint8_t cpuid, uint8_t rank);
int getPmicStatusRegs(uint8_t cpuid, uint8_t rank, DimmData& dimmData);
private:
std::vector<sdbusplus::bus::match_t> matches;
unsigned int sensorPollMs;
sdbusplus::asio::object_server& objectServer;
boost::asio::steady_timer waitTimer;
PMICType pmicType[MAX_CPU_ID][MAX_DIMM_RANK];
bool gotType[MAX_CPU_ID][MAX_DIMM_RANK];
bool twoByteMode[MAX_CPU_ID][MAX_DIMM_RANK];
int adcDelay[MAX_CPU_ID][MAX_DIMM_RANK];
uint16_t regCounter;
uint16_t pmicCounter;
};
@@ -0,0 +1,190 @@
/*
// Copyright (c) 2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
// #include <math.h>
#include <dimmSpdReader.hpp>
#include <chrono>
#include <functional>
#include <iostream>
#include <limits>
#include <memory>
#include <numeric>
#include <string>
#include <vector>
#include <unordered_map>
std::vector<std::string> dimm_table = {
{"DIMM_CPU0_A"},
{"DIMM_CPU0_B"},
{"DIMM_CPU0_C"},
{"DIMM_CPU0_D"},
{"DIMM_CPU0_E"},
{"DIMM_CPU0_F"},
{"DIMM_CPU0_G"},
{"DIMM_CPU0_H"},
{"DIMM_CPU0_I"},
{"DIMM_CPU0_J"},
{"DIMM_CPU0_K"},
{"DIMM_CPU0_L"},
{"DIMM_CPU1_A"},
{"DIMM_CPU1_B"},
{"DIMM_CPU1_C"},
{"DIMM_CPU1_D"},
{"DIMM_CPU1_E"},
{"DIMM_CPU1_F"},
{"DIMM_CPU1_G"},
{"DIMM_CPU1_H"},
{"DIMM_CPU1_I"},
{"DIMM_CPU1_J"},
{"DIMM_CPU1_K"},
{"DIMM_CPU1_L"}
};
std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_temp_inf;
std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_voltage_inf;
std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_current_inf;
std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_power_inf;
std::unordered_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> dimm_statusReg_inf;
int main()
{
boost::asio::io_context io;
auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
sdbusplus::asio::object_server objectServer(systemBus, true);
std::string unit;
objectServer.add_manager("/xyz/openbmc_project/dimm");
systemBus->request_name("xyz.openbmc_project.DimmSpdReader");
for(auto& dimm : dimm_table) {
std::string interfacePath = "/xyz/openbmc_project/dimm/" + dimm;
dimm_temp_inf[dimm] = objectServer.add_interface(interfacePath,
"xyz.openbmc_project.Dimm.Temperature");
dimm_temp_inf[dimm]->register_property(
"TS0", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_temp_inf[dimm]->register_property(
"TS1", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_temp_inf[dimm]->register_property(
"SPD_TS", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
unit = "DegreesC";
dimm_temp_inf[dimm]->register_property("Unit", unit);
dimm_temp_inf[dimm]->initialize();
dimm_voltage_inf[dimm] = objectServer.add_interface(interfacePath,
"xyz.openbmc_project.Dimm.Voltage");
dimm_voltage_inf[dimm]->register_property(
"SWA", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_voltage_inf[dimm]->register_property(
"SWB", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_voltage_inf[dimm]->register_property(
"SWC", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_voltage_inf[dimm]->register_property(
"SWD", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_voltage_inf[dimm]->register_property(
"SWE", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_voltage_inf[dimm]->register_property(
"SWF", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
unit = "Volts";
dimm_voltage_inf[dimm]->register_property("Unit", unit);
dimm_voltage_inf[dimm]->initialize();
dimm_current_inf[dimm] = objectServer.add_interface(interfacePath,
"xyz.openbmc_project.Dimm.Current");
dimm_current_inf[dimm]->register_property(
"SWA", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_current_inf[dimm]->register_property(
"SWB", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_current_inf[dimm]->register_property(
"SWC", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_current_inf[dimm]->register_property(
"SWD", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_current_inf[dimm]->register_property(
"SWE", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_current_inf[dimm]->register_property(
"SWF", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
unit = "Amperes";
dimm_current_inf[dimm]->register_property("Unit", unit);
dimm_current_inf[dimm]->initialize();
dimm_power_inf[dimm] = objectServer.add_interface(interfacePath,
"xyz.openbmc_project.Dimm.Power");
dimm_power_inf[dimm]->register_property(
"SWA", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_power_inf[dimm]->register_property(
"SWB", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_power_inf[dimm]->register_property(
"SWC", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_power_inf[dimm]->register_property(
"SWD", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_power_inf[dimm]->register_property(
"SWE", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
dimm_power_inf[dimm]->register_property(
"SWF", std::numeric_limits<double>::quiet_NaN(),
sdbusplus::asio::PropertyPermission::readWrite);
unit = "Watts";
dimm_power_inf[dimm]->register_property("Unit", unit);
dimm_power_inf[dimm]->initialize();
dimm_statusReg_inf[dimm] = objectServer.add_interface(interfacePath,
"xyz.openbmc_project.Dimm.StatusReg");
dimm_statusReg_inf[dimm]->register_property(
"0x04", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite);
dimm_statusReg_inf[dimm]->register_property(
"0x05", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite);
dimm_statusReg_inf[dimm]->register_property(
"0x06", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite);
dimm_statusReg_inf[dimm]->register_property(
"0x07", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite);
dimm_statusReg_inf[dimm]->register_property(
"0x08", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite);
dimm_statusReg_inf[dimm]->register_property(
"0x09", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite);
dimm_statusReg_inf[dimm]->register_property(
"0x0a", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite);
dimm_statusReg_inf[dimm]->register_property(
"0x0b", uint8_t(0), sdbusplus::asio::PropertyPermission::readWrite);
dimm_statusReg_inf[dimm]->initialize();
}
double pollRate = 0.1;
auto reader = std::make_shared<DIMMSpdReader>(io, objectServer, pollRate);
reader->init();
reader->getdimmI3cSwitchState(systemBus);
reader->setupMatches(static_cast<sdbusplus::bus_t&>(*systemBus));
io.run();
}
@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Synopsys, Inc. and/or its affiliates.
*
* Author: Vitor Soares <vitor.soares@synopsys.com>
*/
#ifndef _UAPI_I3C_DEV_H_
#define _UAPI_I3C_DEV_H_
#include <linux/types.h>
#include <linux/ioctl.h>
#define VERSION "0.1"
/* IOCTL commands */
#define I3C_DEV_IOC_MAGIC 0x07
/**
* struct i3c_ioc_priv_xfer - I3C SDR ioctl private transfer
* @data: Holds pointer to userspace buffer with transmit data.
* @len: Length of data buffer buffers, in bytes.
* @rnw: encodes the transfer direction. true for a read, false for a write
*/
struct i3c_ioc_priv_xfer {
__u64 data;
__u16 len;
__u8 rnw;
__u8 pad[5];
};
#define I3C_PRIV_XFER_SIZE(N) \
((((sizeof(struct i3c_ioc_priv_xfer)) * (N)) < (1 << _IOC_SIZEBITS)) \
? ((sizeof(struct i3c_ioc_priv_xfer)) * (N)) : 0)
#define I3C_IOC_PRIV_XFER(N) \
_IOC(_IOC_READ|_IOC_WRITE, I3C_DEV_IOC_MAGIC, 30, I3C_PRIV_XFER_SIZE(N))
#endif
@@ -0,0 +1,76 @@
project(
'dimmSpdReader',
'cpp',
default_options: [
'warning_level=3',
'werror=true',
'cpp_std=c++20'
],
license: 'Apache-2.0',
version: '0.1',
meson_version: '>=0.58.0',
)
add_project_arguments(
'-Wno-psabi',
'-Wuninitialized',
'-DBOOST_SYSTEM_NO_DEPRECATED',
'-DBOOST_ASIO_NO_DEPRECATED',
'-DBOOST_ERROR_CODE_HEADER_ONLY',
'-DBOOST_NO_RTTI',
'-DBOOST_NO_TYPEID',
'-DBOOST_ALL_NO_LIB',
'-DBOOST_ASIO_DISABLE_THREADS',
'-DBOOST_ALLOW_DEPRECATED_HEADERS',
'-DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT',
language: 'cpp',
)
cpp = meson.get_compiler('cpp')
gpiodcxx = dependency('libgpiodcxx',
default_options: ['bindings=cxx'],
)
sdbusplus = dependency('sdbusplus', required : true, include_type: 'system')
if not sdbusplus.found()
sdbusplus_proj = subproject('sdbusplus', required: true)
sdbusplus = sdbusplus_proj.get_variable('sdbusplus_dep')
sdbusplus = sdbusplus.as_system('system')
endif
phosphor_logging_dep = dependency('phosphor-logging')
if cpp.has_header('nlohmann/json.hpp')
nlohmann_json = declare_dependency()
else
nlohmann_json = dependency('nlohmann_json')
endif
systemd = dependency('systemd')
boost = dependency('boost',version : '>=1.79.0', required : false, include_type: 'system')
if not boost.found()
subproject('boost', required: false)
boost_inc = include_directories('subprojects/boost_1_79_0/', is_system:true)
boost = declare_dependency(include_directories : boost_inc)
boost = boost.as_system('system')
endif
default_deps = [
boost,
nlohmann_json,
phosphor_logging_dep,
sdbusplus,
gpiodcxx,
]
executable(
'dimmspdreader',
'dimmSpdReader.cpp',
'dimmSpdReaderMain.cpp',
dependencies: [
default_deps,
],
install: true,
)
@@ -0,0 +1,13 @@
[Unit]
Description=DIMM SPD Reader
StopWhenUnneeded=false
Requires=xyz.openbmc_project.EntityManager.service
After=xyz.openbmc_project.EntityManager.service xyz.openbmc_project.Host.Misc.Manager.service
[Service]
Restart=always
RestartSec=5
ExecStart=/usr/bin/dimmspdreader
[Install]
WantedBy=multi-user.target