blob: e889819128bc3909b1a6bfa3672010eb78e1a645 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "dev.h"
#include "../dev.h"
#include <ddk/debug.h>
#include <chromiumos-platform-ec/ec_commands.h>
#include <zircon/device/input.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
#include <fbl/ref_ptr.h>
#include <fbl/unique_ptr.h>
#include <stdlib.h>
#include <stdio.h>
#include <acpica/acpi.h>
#include "../errors.h"
zx_status_t AcpiCrOsEc::Create(fbl::RefPtr<AcpiCrOsEc>* out) {
if (!CrOsEc::IsLpc3Supported()) {
return ZX_ERR_NOT_SUPPORTED;
}
fbl::AllocChecker ac;
fbl::RefPtr<AcpiCrOsEc> dev = fbl::AdoptRef(new (&ac) AcpiCrOsEc());
if (!ac.check()) {
return ZX_ERR_NO_MEMORY;
}
size_t actual;
zx_status_t status = CrOsEc::CommandLpc3(EC_CMD_GET_FEATURES, 0, nullptr, 0,
&dev->features_, sizeof(dev->features_), &actual);
if (status != ZX_OK) {
zxlogf(ERROR, "acpi-cros-ec-core: get features failed: %d\n", status);
return status;
}
if (actual != sizeof(dev->features_)) {
zxlogf(ERROR, "acpi-cros-ec-core: get features bad read: %zu vs %zu\n", actual,
sizeof(dev->features_));
return ZX_ERR_IO;
}
*out = fbl::move(dev);
return ZX_OK;
}
zx_status_t AcpiCrOsEc::IssueCommand(uint16_t command, uint8_t command_version,
const void* out, size_t outsize,
void* in, size_t insize, size_t* actual) {
fbl::AutoLock guard(&io_lock_);
return CrOsEc::CommandLpc3(command, command_version, out, outsize, in, insize, actual);
}
AcpiCrOsEc::AcpiCrOsEc() {
}
AcpiCrOsEc::~AcpiCrOsEc() {
}
zx_status_t cros_ec_lpc_init(zx_device_t* parent, ACPI_HANDLE acpi_handle) {
zxlogf(TRACE, "acpi-cros-ec-core: init\n");
fbl::RefPtr<AcpiCrOsEc> ec;
zx_status_t status = AcpiCrOsEc::Create(&ec);
if (status != ZX_OK) {
return status;
}
if (ec->supports_motion_sense()) {
zxlogf(TRACE, "acpi-cros-ec-motion: init\n");
// Set up motion device
fbl::unique_ptr<AcpiCrOsEcMotionDevice> motion_dev;
status = AcpiCrOsEcMotionDevice::Create(ec, parent, acpi_handle, &motion_dev);
if (status == ZX_OK) {
status = motion_dev->DdkAdd("acpi-cros-ec-motion");
if (status != ZX_OK) {
return status;
}
// devmgr is now in charge of the memory for motion_dev
motion_dev.release();
zxlogf(INFO, "acpi-cros-ec-motion: initialized\n");
}
}
zxlogf(INFO, "acpi-cros-ec-core: initialized\n");
return ZX_OK;
}