From aada39602a21e83d7e8c39c39fb8c5c32122863c Mon Sep 17 00:00:00 2001 From: AKSHAY RAVEENDRAN K Date: Thu, 2 Sep 2021 11:11:40 +0000 Subject: [PATCH] Allow MUX idle state to be configured as DISCONNECT The existing Linux behavior is to leave the Mux status as it is after an operation. In HSBP and in other places we have more than one MUX parallel in same root bus. The existing behavior will result in reading multiple buses of different MUXes at the same time and causes bad read. In this fix, we can configure "MuxIdleMode" as "Disconnect" in configuration file as shown below { "Address": "0x70", "Bus": "$bus", "ChannelNames": [ "Drive_1", "Drive_2", "Drive_3", "Drive_4" ], "MuxIdleMode": "Disconnect", "Name": "Drive Mux 1", "Type": "PCA9546Mux" Tested: Set the MUX idle mode to Disconnect in MUXes present in HSBP board and only one channel is read at a time. Change-Id: I6d29cd3be350682c386bd3072e76b930a7d45587 Signed-off-by: AKSHAY RAVEENDRAN K --- src/Overlay.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/Overlay.cpp b/src/Overlay.cpp index 4454423..2843c31 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -38,11 +38,46 @@ constexpr const char* outputDir = "/tmp/overlays"; constexpr const char* templateChar = "$"; constexpr const char* i2CDevsDir = "/sys/bus/i2c/devices"; constexpr const char* muxSymlinkDir = "/dev/i2c-mux"; +constexpr const char* idleModeAsIs = "-1"; +constexpr const char* idleModeDisconnect = "-2"; constexpr const bool debug = false; std::regex illegalNameRegex("[^A-Za-z0-9_]"); +void setIdleMode(const std::string& muxName, size_t busIndex, size_t address, + const std::string& idleMode) +{ + std::error_code ec; + + std::ostringstream hexAddress; + hexAddress << std::hex << std::setfill('0') << std::setw(4) << address; + + std::filesystem::path idlePath(i2CDevsDir); + idlePath /= + std::to_string(busIndex) + "-" + hexAddress.str() + "/idle_state"; + + std::string modeData = + (idleMode == "Disconnect") ? idleModeDisconnect : idleModeAsIs; + + if (debug) + { + std::cerr << "Setting " << muxName << " idle state to " << modeData + << " in " << idlePath << "\n"; + } + + std::ofstream idleFile(idlePath); + if (!idleFile.good()) + { + std::cerr << "Can't set idle mode in " << idlePath << " for " << muxName + << "\n"; + } + else + { + idleFile << modeData; + } +} + // helper function to make json types into string std::string jsonToString(const nlohmann::json& in) { @@ -285,6 +320,7 @@ void exportDevice(const std::string& type, std::shared_ptr bus = nullptr; std::shared_ptr address = nullptr; const nlohmann::json::array_t* channels = nullptr; + std::string idleMode; for (auto keyPair = configuration.begin(); keyPair != configuration.end(); keyPair++) @@ -318,6 +354,11 @@ void exportDevice(const std::string& type, channels = keyPair.value().get_ptr(); } + else if (keyPair.key() == "MuxIdleMode") + { + idleMode = keyPair.value().get(); + } + boost::replace_all(parameters, templateChar + keyPair.key(), subsituteString); boost::replace_all(devicePath, templateChar + keyPair.key(), @@ -327,10 +368,18 @@ void exportDevice(const std::string& type, int err = buildDevice(devicePath, parameters, bus, address, constructor, destructor, createsHWMon); - if (!err && boost::ends_with(type, "Mux") && bus && address && channels) + if (!err && boost::ends_with(type, "Mux") && bus && address) { - linkMux(name, static_cast(*bus), static_cast(*address), - *channels); + if (channels) + { + linkMux(name, static_cast(*bus), + static_cast(*address), *channels); + } + if (!idleMode.empty()) + { + setIdleMode(name, static_cast(*bus), + static_cast(*address), idleMode); + } } } -- 2.17.1