blob: a7d6feac3cea4d05458330939f84cd7884d5e1dc [file] [log] [blame]
// Copyright 2020 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 <fidl/fuchsia.hardware.platform.bus/cpp/driver/fidl.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/fidl.h>
#include <lib/ddk/binding.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/device.h>
#include <lib/ddk/metadata.h>
#include <lib/ddk/platform-defs.h>
#include <lib/driver/component/cpp/composite_node_spec.h>
#include <lib/driver/component/cpp/node_add_args.h>
#include <bind/fuchsia/amlogic/platform/cpp/bind.h>
#include <bind/fuchsia/cpp/bind.h>
#include <bind/fuchsia/google/platform/cpp/bind.h>
#include <bind/fuchsia/hardware/pwm/cpp/bind.h>
#include <bind/fuchsia/platform/cpp/bind.h>
#include <bind/fuchsia/power/cpp/bind.h>
#include <ddk/metadata/power.h>
#include <soc/aml-common/aml-power.h>
#include <soc/aml-s905d2/s905d2-pwm.h>
#include "astro-gpios.h"
#include "astro.h"
namespace fdf {
using namespace fuchsia_driver_framework;
} // namespace fdf
namespace astro {
namespace fpbus = fuchsia_hardware_platform_bus;
namespace {
constexpr aml_voltage_table_t kS905D2VoltageTable[] = {
{1'022'000, 0}, {1'011'000, 3}, {1'001'000, 6}, {991'000, 10}, {981'000, 13}, {971'000, 16},
{961'000, 20}, {951'000, 23}, {941'000, 26}, {931'000, 30}, {921'000, 33}, {911'000, 36},
{901'000, 40}, {891'000, 43}, {881'000, 46}, {871'000, 50}, {861'000, 53}, {851'000, 56},
{841'000, 60}, {831'000, 63}, {821'000, 67}, {811'000, 70}, {801'000, 73}, {791'000, 76},
{781'000, 80}, {771'000, 83}, {761'000, 86}, {751'000, 90}, {741'000, 93}, {731'000, 96},
{721'000, 100},
};
constexpr voltage_pwm_period_ns_t kS905d2PwmPeriodNs = 1250;
constexpr power_domain_t domains[] = {
{bind_fuchsia_amlogic_platform::POWER_DOMAIN_ARM_CORE_LITTLE},
};
} // namespace
zx_status_t AddPowerImpl(fdf::WireSyncClient<fuchsia_hardware_platform_bus::PlatformBus>& pbus) {
fpbus::Node dev;
dev.name() = "aml-power-impl-composite";
dev.vid() = bind_fuchsia_google_platform::BIND_PLATFORM_DEV_VID_GOOGLE;
dev.pid() = bind_fuchsia_google_platform::BIND_PLATFORM_DEV_PID_ASTRO;
dev.did() = bind_fuchsia_amlogic_platform::BIND_PLATFORM_DEV_DID_POWER;
dev.metadata() = std::vector<fpbus::Metadata>{
{{
.type = DEVICE_METADATA_AML_VOLTAGE_TABLE,
.data = std::vector<uint8_t>(
reinterpret_cast<const uint8_t*>(&kS905D2VoltageTable),
reinterpret_cast<const uint8_t*>(&kS905D2VoltageTable) + sizeof(kS905D2VoltageTable)),
}},
{{
.type = DEVICE_METADATA_AML_PWM_PERIOD_NS,
.data = std::vector<uint8_t>(
reinterpret_cast<const uint8_t*>(&kS905d2PwmPeriodNs),
reinterpret_cast<const uint8_t*>(&kS905d2PwmPeriodNs) + sizeof(kS905d2PwmPeriodNs)),
}},
};
const std::vector<fuchsia_driver_framework::BindRule> kPwmRules = {
fdf::MakeAcceptBindRule(bind_fuchsia_hardware_pwm::SERVICE,
bind_fuchsia_hardware_pwm::SERVICE_ZIRCONTRANSPORT),
fdf::MakeAcceptBindRule(bind_fuchsia::PWM_ID, static_cast<uint32_t>(S905D2_PWM_AO_D))};
const std::vector<fuchsia_driver_framework::NodeProperty> kPwmProps = {
fdf::MakeProperty(bind_fuchsia_hardware_pwm::SERVICE,
bind_fuchsia_hardware_pwm::SERVICE_ZIRCONTRANSPORT),
fdf::MakeProperty(bind_fuchsia_amlogic_platform::PWM_ID,
bind_fuchsia_amlogic_platform::PWM_ID_AO_D)};
const std::vector<fdf::ParentSpec> kParents = {fdf::ParentSpec{{kPwmRules, kPwmProps}}};
fidl::Arena<> fidl_arena;
fdf::Arena arena('POWR');
fdf::WireUnownedResult result = pbus.buffer(arena)->AddCompositeNodeSpec(
fidl::ToWire(fidl_arena, dev),
fidl::ToWire(fidl_arena, fuchsia_driver_framework::CompositeNodeSpec{
{.name = "aml-power-impl-composite", .parents = kParents}}));
if (!result.ok()) {
zxlogf(ERROR, "Failed to send AddCompositeNodeSpec request: %s", result.status_string());
return result.status();
}
if (result->is_error()) {
zxlogf(ERROR, "Failed to add composite: %s", zx_status_get_string(result->error_value()));
return result->error_value();
}
return ZX_OK;
}
zx_status_t AddPdArmcore(fdf::WireSyncClient<fuchsia_hardware_platform_bus::PlatformBus>& pbus) {
fpbus::Node dev;
dev.name() = "composite-pd-armcore";
dev.vid() = bind_fuchsia_platform::BIND_PLATFORM_DEV_VID_GENERIC;
dev.pid() = bind_fuchsia_platform::BIND_PLATFORM_DEV_PID_GENERIC;
dev.did() = bind_fuchsia_platform::BIND_PLATFORM_DEV_DID_POWER_CORE;
dev.metadata() = std::vector<fpbus::Metadata>{
{{
.type = DEVICE_METADATA_POWER_DOMAINS,
.data =
std::vector<uint8_t>(reinterpret_cast<const uint8_t*>(&domains),
reinterpret_cast<const uint8_t*>(&domains) + sizeof(domains)),
}},
};
const std::vector<fdf::BindRule> kPowerArmcoreRules = std::vector{
fdf::MakeAcceptBindRule(bind_fuchsia::PROTOCOL, bind_fuchsia_power::BIND_PROTOCOL_IMPL),
};
const std::vector<fdf::NodeProperty> kPowerArmcoreProperties = std::vector{
fdf::MakeProperty(bind_fuchsia::PROTOCOL, bind_fuchsia_power::BIND_PROTOCOL_IMPL),
};
const std::vector<fdf::ParentSpec> kParents = {
{
kPowerArmcoreRules,
kPowerArmcoreProperties,
},
};
fidl::Arena<> fidl_arena;
fdf::Arena arena('PDAC');
auto result = pbus.buffer(arena)->AddCompositeNodeSpec(
fidl::ToWire(fidl_arena, dev),
fidl::ToWire(fidl_arena,
fdf::CompositeNodeSpec{{.name = "pd_armcore", .parents = kParents}}));
if (!result.ok()) {
zxlogf(ERROR, "Failed to send AddCompositeNodeSpec request: %s", result.status_string());
return result.status();
}
if (result->is_error()) {
zxlogf(ERROR, "Failed to add composite: %s", zx_status_get_string(result->error_value()));
return result->error_value();
}
return ZX_OK;
}
zx_status_t Astro::PowerInit() {
zx_status_t status = AddPowerImpl(pbus_);
if (status != ZX_OK) {
zxlogf(ERROR, "Failed to add power-impl composite device: %s", zx_status_get_string(status));
return status;
}
status = AddPdArmcore(pbus_);
if (status != ZX_OK) {
zxlogf(ERROR, "Failed to add pd-armcore composite device: %s", zx_status_get_string(status));
return status;
}
return ZX_OK;
}
} // namespace astro