Reinvent x86 power control application
The previous application that was posted here had a TON of timing
issues that made it basically unworkable, and was missing several
features (like power button override, VR timers, ect) that weren't
really possible in the old scheme.
This commit shows a reimagining of power control on the AST2500, and
seems to work much more reliably in testing across several platforms.
The key differentiators here are:
1. It gets rid of the target files. Despite _many_ attempts to make the
target file approach reliable across 1000/10000 reboot cycle testings,
it was clear that the timing differences in the activation times caused
too many hard to fix race conditions. To this end, the power state
machine has been moved into c++, where we can be very explicit about our
IO, and event timings.
2. It implements several features that were not present in the old
implementation, like soft power cycle. These were required to implement
the full Redfish ComputerSystem schema properly.
3. It implements proper handling when collisions occur. For example
when two power off requests come in at the same time. Because of #1 we
can now service both of these requests "correctly" and remove the
possibility of desyncronizing the state machine from the host state.
A majority of this work was accomplished by Jason Bills. The history is
available here, which can be pushed if needed, but I don't beleive it's
wanted.
https://github.com/Intel-BMC/intel-chassis-control/commits/master
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Change-Id: I2eb7fb1dbcab3d374df9d2e8c62407f0277e2583
diff --git a/i2c/src/i2c.cpp b/i2c/src/i2c.cpp
new file mode 100644
index 0000000..dcef067
--- /dev/null
+++ b/i2c/src/i2c.cpp
@@ -0,0 +1,93 @@
+/*
+// Copyright (c) 2018 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 "i2c.hpp"
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <phosphor-logging/elog-errors.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+// TODO Add 16-bit I2C support in the furture
+int i2cSet(uint8_t bus, uint8_t slaveAddr, uint8_t regAddr, uint8_t value)
+{
+ unsigned long funcs = 0;
+ std::string devPath = "/dev/i2c-" + std::to_string(bus);
+
+ int fd = ::open(devPath.c_str(), O_RDWR);
+ if (fd < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Error in open!",
+ phosphor::logging::entry("PATH=%s", devPath.c_str()),
+ phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
+ return -1;
+ }
+
+ if (::ioctl(fd, I2C_FUNCS, &funcs) < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Error in I2C_FUNCS!",
+ phosphor::logging::entry("PATH=%s", devPath.c_str()),
+ phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
+
+ ::close(fd);
+ return -1;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ {
+
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "i2c bus does not support write!",
+ phosphor::logging::entry("PATH=%s", devPath.c_str()),
+ phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
+ ::close(fd);
+ return -1;
+ }
+
+ if (::ioctl(fd, I2C_SLAVE_FORCE, slaveAddr) < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Error in I2C_SLAVE_FORCE!",
+ phosphor::logging::entry("PATH=%s", devPath.c_str()),
+ phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
+ ::close(fd);
+ return -1;
+ }
+
+ if (::i2c_smbus_write_byte_data(fd, regAddr, value) < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Error in i2c write!",
+ phosphor::logging::entry("PATH=%s", devPath.c_str()),
+ phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
+ ::close(fd);
+ return -1;
+ }
+
+ // TODO For testing, will remove the below debug loging in the future
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "i2cset successfully",
+ phosphor::logging::entry("PATH=%s", devPath.c_str()),
+ phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr),
+ phosphor::logging::entry("REGADDR=0x%x", regAddr),
+ phosphor::logging::entry("VALUE=0x%x", value));
+ ::close(fd);
+ return 0;
+}