Support host selector using cpld definitions
Description:
- Support host selector using cpld definitions
Design:
- Because the current structure only supports config defined by GPIO
(Yosemite V2), but there are also have the system (Yosemite V3.5)
gets the host-selector's selection from CPLD.
- So this commit is to extend the current configuration to use CPLD
definitions. Also, support adding event io from the register file
which was exported from the CLD driver.
- For example with config json below:
{
"cpld_definitions": [
{
"name": "HOST_SELECTOR",
"i2c_address": 15,
"i2c_bus": 12,
"register_name": "uart-selection-debug-card",
"max_position": 4
}
]
}
Dependency:
- CLD driver is required (link: https://lore.kernel.org/lkml/20230117094425.19004-1-Delphine_CC_Chiu@Wiwynn.com/)
Test Case:
- When ocp debug card uart button is pressed the position property on
dbus is correct.
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@wiwynn.com>
Change-Id: I6746afa6d905bd3c681e2921c643b3cd4cb9944c
diff --git a/src/cpld.cpp b/src/cpld.cpp
new file mode 100644
index 0000000..af1bbd9
--- /dev/null
+++ b/src/cpld.cpp
@@ -0,0 +1,38 @@
+
+#include "config.h"
+
+#include "button_config.hpp"
+
+#include <error.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <phosphor-logging/lg2.hpp>
+
+const std::string cpldDev = "/sys/bus/i2c/devices/";
+
+std::string getCpldDevPath(const CpldInfo& info)
+{
+ std::stringstream devPath;
+ devPath << cpldDev << info.i2cBus << "-" << std::hex << std::setw(4)
+ << std::setfill('0') << info.i2cAddress << "/" << info.registerName;
+ return devPath.str();
+}
+
+int configCpld(ButtonConfig& buttonIFConfig)
+{
+ std::string devPath = getCpldDevPath(buttonIFConfig.cpld);
+
+ auto fd = ::open(devPath.c_str(), O_RDONLY | O_NONBLOCK);
+
+ if (fd < 0)
+ {
+ lg2::error("Open {PATH} error: {ERROR}", "PATH", devPath, "ERROR",
+ errno);
+ return -1;
+ }
+
+ buttonIFConfig.cpld.cpldMappedFd = fd;
+ buttonIFConfig.fds.push_back(fd);
+ return 0;
+}
diff --git a/src/gpio.cpp b/src/gpio.cpp
index 0a16ce5..a946aa3 100644
--- a/src/gpio.cpp
+++ b/src/gpio.cpp
@@ -16,7 +16,7 @@
#include "config.h"
-#include "gpio.hpp"
+#include "button_config.hpp"
#include <error.h>
#include <fcntl.h>
@@ -83,13 +83,6 @@
: (GpioState::deassert);
return gpioState;
}
-void closeGpio(int fd)
-{
- if (fd > 0)
- {
- ::close(fd);
- }
-}
uint32_t getGpioBase()
{
@@ -134,14 +127,14 @@
return getGpioBase() + offset;
}
-int configGroupGpio(buttonConfig& buttonIFConfig)
+int configGroupGpio(ButtonConfig& buttonIFConfig)
{
int result = 0;
// iterate the list of gpios from the button interface config
// and initialize them
for (auto& gpioCfg : buttonIFConfig.gpios)
{
- result = configGpio(gpioCfg);
+ result = configGpio(gpioCfg, buttonIFConfig);
if (result < 0)
{
lg2::error("{NAME}: Error configuring gpio-{NUM}: {RESULT}", "NAME",
@@ -155,7 +148,7 @@
return result;
}
-int configGpio(gpioInfo& gpioConfig)
+int configGpio(GpioInfo& gpioConfig, ButtonConfig& buttonIFConfig)
{
auto gpioNum = gpioConfig.number;
auto gpioDirection = gpioConfig.direction;
@@ -300,6 +293,7 @@
}
gpioConfig.fd = fd;
+ buttonIFConfig.fds.push_back(fd);
return 0;
}
diff --git a/src/hostSelector_switch.cpp b/src/hostSelector_switch.cpp
index ce168d0..81bd247 100644
--- a/src/hostSelector_switch.cpp
+++ b/src/hostSelector_switch.cpp
@@ -37,38 +37,60 @@
}
return INVALID_INDEX;
}
-void HostSelector::setInitialHostSelectorValue()
+
+char HostSelector::getValueFromFd(int fd)
{
char buf;
- for (size_t index = 0; index < gpioLineCount; index++)
+ auto result = ::lseek(fd, 0, SEEK_SET);
+
+ if (result < 0)
{
- auto result = ::lseek(config.gpios[index].fd, 0, SEEK_SET);
+ throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
+ IOError();
+ }
- if (result < 0)
- {
- lg2::error("{TYPE}: Gpio fd lseek error: {ERROR}", "TYPE",
- getFormFactorType(), "ERROR", errno);
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
- }
+ result = ::read(fd, &buf, sizeof(buf));
+ if (result < 0)
+ {
+ throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
+ IOError();
+ }
+ return buf;
+}
- result = ::read(config.gpios[index].fd, &buf, sizeof(buf));
- if (result < 0)
+void HostSelector::setInitialHostSelectorValue()
+{
+ size_t hsPosMapped = 0;
+
+ try
+ {
+ if (config.type == ConfigType::gpio)
{
- lg2::error("{TYPE}: Gpio fd read error: {ERROR}", "TYPE",
- getFormFactorType(), "ERROR", errno);
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
+ for (size_t index = 0; index < gpioLineCount; index++)
+ {
+ GpioState gpioState =
+ (getValueFromFd(config.gpios[index].fd) == '0')
+ ? (GpioState::deassert)
+ : (GpioState::assert);
+ setHostSelectorValue(config.gpios[index].fd, gpioState);
+ }
+ hsPosMapped = getMappedHSConfig(hostSelectorPosition);
}
- GpioState gpioState = (buf == '0') ? (GpioState::deassert)
- : (GpioState::assert);
- setHostSelectorValue(config.gpios[index].fd, gpioState);
- size_t hsPosMapped = getMappedHSConfig(hostSelectorPosition);
- if (hsPosMapped != INVALID_INDEX)
+ else if (config.type == ConfigType::cpld)
{
- position(hsPosMapped, true);
+ hsPosMapped = getValueFromFd(config.cpld.cpldMappedFd) - '0';
}
}
+ catch (const std::exception& e)
+ {
+ lg2::error("{TYPE}: exception while reading fd : {ERROR}", "TYPE",
+ getFormFactorType(), "ERROR", e.what());
+ }
+
+ if (hsPosMapped != INVALID_INDEX)
+ {
+ position(hsPosMapped, true);
+ }
}
void HostSelector::setHostSelectorValue(int fd, GpioState state)
@@ -98,34 +120,32 @@
void HostSelector::handleEvent(sd_event_source* /* es */, int fd,
uint32_t /* revents */)
{
- int n = -1;
char buf = '0';
-
- n = ::lseek(fd, 0, SEEK_SET);
-
- if (n < 0)
+ try
{
- lg2::error("{TYPE}: Gpio fd lseek error: {ERROR}", "TYPE",
- getFormFactorType(), "ERROR", errno);
+ buf = getValueFromFd(fd);
+ }
+ catch (const std::exception& e)
+ {
+ lg2::error("{TYPE}: exception while reading fd : {ERROR}", "TYPE",
+ getFormFactorType(), "ERROR", e.what());
return;
}
- n = ::read(fd, &buf, sizeof(buf));
- if (n < 0)
+ size_t hsPosMapped = 0;
+ if (config.type == ConfigType::gpio)
{
- lg2::error("{TYPE}: Gpio fd read error: {ERROR}", "TYPE",
- getFormFactorType(), "ERROR", errno);
- throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
- IOError();
+ // read the gpio state for the io event received
+ GpioState gpioState = (buf == '0') ? (GpioState::deassert)
+ : (GpioState::assert);
+
+ setHostSelectorValue(fd, gpioState);
+ hsPosMapped = getMappedHSConfig(hostSelectorPosition);
}
-
- // read the gpio state for the io event received
- GpioState gpioState = (buf == '0') ? (GpioState::deassert)
- : (GpioState::assert);
-
- setHostSelectorValue(fd, gpioState);
-
- size_t hsPosMapped = getMappedHSConfig(hostSelectorPosition);
+ else if (config.type == ConfigType::cpld)
+ {
+ hsPosMapped = buf - '0';
+ }
if (hsPosMapped != INVALID_INDEX)
{
diff --git a/src/main.cpp b/src/main.cpp
index ecb9402..cf38e1f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -14,8 +14,8 @@
// limitations under the License.
*/
+#include "button_config.hpp"
#include "button_factory.hpp"
-#include "gpio.hpp"
#include <nlohmann/json.hpp>
#include <phosphor-logging/elog-errors.hpp>
@@ -24,10 +24,11 @@
#include <fstream>
static constexpr auto gpioDefFile = "/etc/default/obmc/gpio/gpio_defs.json";
-nlohmann::json gpioDefs;
-
int main(void)
{
+ nlohmann::json gpioDefs;
+ nlohmann::json cpldDefs;
+
int ret = 0;
lg2::info("Start Phosphor buttons service...");
@@ -50,8 +51,34 @@
std::vector<std::unique_ptr<ButtonIface>> buttonInterfaces;
std::ifstream gpios{gpioDefFile};
- auto gpioDefJson = nlohmann::json::parse(gpios, nullptr, true);
- gpioDefs = gpioDefJson["gpio_definitions"];
+ auto configDefJson = nlohmann::json::parse(gpios, nullptr, true);
+ gpioDefs = configDefJson["gpio_definitions"];
+ cpldDefs = configDefJson["cpld_definitions"];
+
+ // load cpld config from gpio defs json file and create button interface
+ for (const auto& cpldConfig : cpldDefs)
+ {
+ std::string formFactorName = cpldConfig["name"];
+
+ ButtonConfig buttonCfg;
+ buttonCfg.type = ConfigType::cpld;
+ buttonCfg.formFactorName = formFactorName;
+ buttonCfg.extraJsonInfo = cpldConfig;
+
+ CpldInfo cpldCfg;
+ cpldCfg.registerName = cpldConfig["register_name"];
+
+ cpldCfg.i2cAddress = cpldConfig["i2c_address"].get<int>();
+ cpldCfg.i2cBus = cpldConfig["i2c_bus"].get<int>();
+ buttonCfg.cpld = cpldCfg;
+
+ auto tempButtonIf = ButtonFactory::instance().createInstance(
+ formFactorName, bus, eventP, buttonCfg);
+ if (tempButtonIf)
+ {
+ buttonInterfaces.emplace_back(std::move(tempButtonIf));
+ }
+ }
// load gpio config from gpio defs json file and create button interface
// objects based on the button form factor type
@@ -59,9 +86,10 @@
for (const auto& gpioConfig : gpioDefs)
{
std::string formFactorName = gpioConfig["name"];
- buttonConfig buttonCfg;
+ ButtonConfig buttonCfg;
buttonCfg.formFactorName = formFactorName;
buttonCfg.extraJsonInfo = gpioConfig;
+ buttonCfg.type = ConfigType::gpio;
/* The folloing code checks if the gpio config read
from json file is single gpio config or group gpio config,
@@ -74,7 +102,7 @@
for (const auto& config : groupGpio)
{
- gpioInfo gpioCfg;
+ GpioInfo gpioCfg;
gpioCfg.number = getGpioNum(config["pin"]);
gpioCfg.direction = config["direction"];
gpioCfg.name = config["name"];
@@ -86,7 +114,7 @@
}
else
{
- gpioInfo gpioCfg;
+ GpioInfo gpioCfg;
gpioCfg.number = getGpioNum(gpioConfig["pin"]);
gpioCfg.direction = gpioConfig["direction"];
buttonCfg.gpios.push_back(gpioCfg);
diff --git a/src/serial_uart_mux.cpp b/src/serial_uart_mux.cpp
index 31c2051..ee3d5d5 100644
--- a/src/serial_uart_mux.cpp
+++ b/src/serial_uart_mux.cpp
@@ -62,7 +62,7 @@
for (size_t uartMuxSel = 0; uartMuxSel < gpioLineCount; uartMuxSel++)
{
auto gpioState = GpioState::invalid;
- gpioInfo gpioConfig = config.gpios[uartMuxSel];
+ GpioInfo gpioConfig = config.gpios[uartMuxSel];
if (gpioConfig.name == SERIAL_UART_RX_GPIO)
{