blob: 821324574291d4a2cae62fba7a603e318611c852 [file] [log] [blame]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/*
* Device access interface common functions.
*/
#include "hps/dev.h"
#include <optional>
#include "base/logging.h"
#include <base/strings/stringprintf.h>
#include "hps/hps_reg.h"
#include "hps/utils.h"
namespace hps {
namespace {
class WakeLockNoOpImpl : public WakeLock {
public:
WakeLockNoOpImpl() = default;
~WakeLockNoOpImpl() override = default;
bool supports_power_management() override { return false; }
};
} // namespace
bool DevInterface::Read(uint8_t cmd, uint8_t* data, size_t len) {
if (this->ReadDevice(cmd, data, len)) {
VLOG(2) << base::StringPrintf("Read: cmd: 0x%x len: %zd OK", cmd, len);
return true;
}
VLOG(2) << base::StringPrintf("Read: cmd: 0x%x len: %zd FAILED", cmd, len);
return false;
}
bool DevInterface::Write(uint8_t cmd, const uint8_t* data, size_t len) {
if (this->WriteDevice(cmd, data, len)) {
VLOG(2) << base::StringPrintf("Write: cmd: 0x%x len: %zd OK", cmd, len);
return true;
}
VLOG(2) << base::StringPrintf("Write: cmd: 0x%x len: %zd FAILED", cmd, len);
return false;
}
/*
* Read 1 register.
* Returns value read, or -1 for error.
*/
std::optional<uint16_t> DevInterface::ReadReg(HpsReg r) {
auto reg = HpsRegInfo(r);
uint8_t res[2];
if (this->ReadDevice(I2cReg(r), res, sizeof(res))) {
uint16_t ret = static_cast<uint16_t>(res[0] << 8) | res[1];
VLOG(2) << base::StringPrintf("ReadReg: %s : 0x%.4x OK", reg->name, ret);
return ret;
} else {
VLOG(2) << "ReadReg: " << reg->name << " FAILED";
return std::nullopt;
}
}
std::optional<std::string> DevInterface::ReadStringReg(HpsReg r, size_t len) {
auto reg = HpsRegInfo(r);
std::string ret(len, '\0');
if (this->ReadDevice(I2cReg(r), reinterpret_cast<uint8_t*>(ret.data()),
static_cast<unsigned int>(ret.size()))) {
auto terminator = ret.find('\0');
if (terminator != std::string::npos) {
ret.resize(terminator);
}
VLOG(2) << base::StringPrintf("ReadReg: %s (%zu bytes) OK", reg->name,
ret.size());
return ret;
} else {
VLOG(2) << "ReadStringReg: " << reg->name << " FAILED";
return std::nullopt;
}
}
/*
* Write 1 register.
* Returns false on failure.
*/
bool DevInterface::WriteReg(HpsReg r, uint16_t data) {
auto reg = HpsRegInfo(r);
uint8_t buf[2];
buf[0] = data >> 8;
buf[1] = data & 0xFF;
if (this->WriteDevice(I2cReg(r), buf, sizeof(buf))) {
VLOG(2) << base::StringPrintf("WriteReg: %s : 0x%.4x OK", reg->name, data);
return true;
} else {
VLOG(2) << base::StringPrintf("WriteReg: %s : 0x%.4x FAILED", reg->name,
data);
return false;
}
}
/*
* Return the maximum download block size (in bytes).
* Default is 256 bytes.
*/
size_t DevInterface::BlockSizeBytes() {
return 256;
}
std::unique_ptr<WakeLock> DevInterface::CreateWakeLock() {
return std::make_unique<WakeLockNoOpImpl>();
}
} // namespace hps