summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0005-Allow-MUX-idle-state-to-be-configured-as-DISCONNECT.patch
blob: ac0995614cb82bc11ef88f618a5a09d6b18ad8eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
From aada39602a21e83d7e8c39c39fb8c5c32122863c Mon Sep 17 00:00:00 2001
From: AKSHAY RAVEENDRAN K <akshay.raveendran.k@intel.com>
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 <akshay.raveendran.k@intel.com>
---
 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<uint64_t> bus = nullptr;
     std::shared_ptr<uint64_t> 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<const nlohmann::json::array_t*>();
         }
+        else if (keyPair.key() == "MuxIdleMode")
+        {
+            idleMode = keyPair.value().get<std::string>();
+        }
+
         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<size_t>(*bus), static_cast<size_t>(*address),
-                *channels);
+        if (channels)
+        {
+            linkMux(name, static_cast<size_t>(*bus),
+                    static_cast<size_t>(*address), *channels);
+        }
+        if (!idleMode.empty())
+        {
+            setIdleMode(name, static_cast<size_t>(*bus),
+                        static_cast<size_t>(*address), idleMode);
+        }
     }
 }
 
-- 
2.17.1