Initial commit
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
|
||||
LICENSE = "CLOSED"
|
||||
|
||||
SRC_URI += " \
|
||||
file://dimmSpdReader.cpp \
|
||||
file://dimmSpdReader.hpp \
|
||||
file://dimmSpdReaderMain.cpp \
|
||||
file://i3cdev.h \
|
||||
file://meson.build \
|
||||
file://xyz.openbmc_project.dimmspdreader.service \
|
||||
"
|
||||
|
||||
S = "${WORKDIR}"
|
||||
|
||||
inherit pkgconfig meson systemd
|
||||
|
||||
DEPENDS = " \
|
||||
boost \
|
||||
libgpiod \
|
||||
nlohmann-json \
|
||||
phosphor-logging \
|
||||
sdbusplus \
|
||||
"
|
||||
SYSTEMD_PACKAGES = "${PN}"
|
||||
SYSTEMD_SERVICE:${PN} = "xyz.openbmc_project.dimmspdreader.service"
|
||||
|
||||
do_install:append() {
|
||||
install -d ${D}${systemd_unitdir}/system/
|
||||
install -m 0644 ${WORKDIR}/xyz.openbmc_project.dimmspdreader.service ${D}${systemd_unitdir}/system
|
||||
}
|
||||
+1188
File diff suppressed because it is too large
Load Diff
+96
@@ -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;
|
||||
};
|
||||
+190
@@ -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,
|
||||
)
|
||||
+13
@@ -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
|
||||
Reference in New Issue
Block a user