Add Aspeed PCC driver support
Add support for Aspeed Post Code Capture driver.
In order to fetch post code from Aspeed PCC driver, please set
`snoop-device` and `post-code-bytes` as below.
- snoop-device = aspeed-lpc-pcc
- post-code-bytes = 8
Tested on Harma system.
Change-Id: I5806362d2a54d1ed7b7f821d512f79cbc3effd38
Signed-off-by: Cosmo Chou <cosmo.chou@quantatw.com>
Signed-off-by: Potin Lai <potin.lai@quantatw.com>
diff --git a/main.cpp b/main.cpp
index e977ce0..d84a5aa 100644
--- a/main.cpp
+++ b/main.cpp
@@ -44,6 +44,7 @@
static size_t codeSize = 1; /* Size of each POST code in bytes */
static bool verbose = false;
+static std::function<bool(uint64_t&, ssize_t)> procPostCode;
static void usage(const char* name)
{
@@ -122,6 +123,75 @@
}
/*
+ * Split input code into multiple 2 bytes PCC code, If the PCC code prefix
+ * matches the check code, store each PCC code in aspeedPCCBuffer, or clear
+ * aspeedPCCBuffer if the prefix does not match.
+ *
+ * Each PCC code contains one byte of port number (MSB) and another byte of
+ * partial postcode (LSB). To get a complete postcode, the PCC code should
+ * followed the sequence of 0x40AA, 0x41BB, 0x42CC & 0x43DD. When
+ * aspeedPCCBuffer contains enough PCC codes, the postcode will be assigned as
+ * 0xDDCCBBAA.
+ */
+bool aspeedPCC(uint64_t& code, ssize_t readb)
+{
+ // Size of data coming from the PCC hardware
+ constexpr size_t pccSize = sizeof(uint16_t);
+ // Required PCC count of a full postcode, if codeSize is 8 bytes, it means
+ // it require 4 PCC codes in correct sequence to get a complete postcode.
+ const size_t fullPostPCCCount = codeSize / pccSize;
+ // A PCC buffer for storing PCC code in sequence.
+ static std::vector<uint16_t> aspeedPCCBuffer;
+ constexpr uint16_t firstPCCPortNumber = 0x4000;
+ constexpr uint16_t pccPortNumberMask = 0xFF00;
+ constexpr uint16_t pccPostCodeMask = 0x00FF;
+ constexpr uint8_t byteShift = 8;
+
+ uint16_t* codePtr = reinterpret_cast<uint16_t*>(&code);
+
+ for (size_t i = 0; i < (readb / pccSize); i++)
+ {
+ uint16_t checkCode = firstPCCPortNumber +
+ ((aspeedPCCBuffer.size() % fullPostPCCCount)
+ << byteShift);
+
+ if (checkCode == (codePtr[i] & pccPortNumberMask))
+ {
+ aspeedPCCBuffer.emplace_back(codePtr[i]);
+ }
+ else
+ {
+ aspeedPCCBuffer.clear();
+
+ // keep the PCC code if codePtr[i] matches with 0x40XX as first PCC
+ // code in buffer.
+ if ((codePtr[i] & pccPortNumberMask) == firstPCCPortNumber)
+ {
+ aspeedPCCBuffer.emplace_back(codePtr[i]);
+ }
+ }
+ }
+
+ if (aspeedPCCBuffer.size() < fullPostPCCCount)
+ {
+ // not receive full postcode yet.
+ return false;
+ }
+
+ // Remove the prefix bytes and combine the partial postcodes together.
+ code = 0;
+ for (size_t i = 0; i < fullPostPCCCount; i++)
+ {
+ code |= static_cast<uint64_t>(aspeedPCCBuffer[i] & pccPostCodeMask)
+ << (byteShift * i);
+ }
+ aspeedPCCBuffer.erase(aspeedPCCBuffer.begin(),
+ aspeedPCCBuffer.begin() + fullPostPCCCount);
+
+ return true;
+}
+
+/*
* Callback handling IO event from the POST code fd. i.e. there is new
* POST code available to read.
*/
@@ -133,6 +203,11 @@
while ((readb = read(postFd, &code, codeSize)) > 0)
{
+ if (procPostCode && procPostCode(code, readb) == false)
+ {
+ return;
+ }
+
code = le64toh(code);
if (verbose)
{
@@ -243,6 +318,10 @@
break;
}
case 'd':
+ if (std::string(optarg) == "/dev/aspeed-lpc-pcc")
+ {
+ procPostCode = aspeedPCC;
+ }
postFd = open(optarg, O_NONBLOCK);
if (postFd < 0)