blob: ecb21d22f101f8e3b5b0bee7a6727db1cdc0e771 [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.
#ifndef SRC_DEVICES_POWER_DRIVERS_AML_MESON_POWER_AML_POWER_H_
#define SRC_DEVICES_POWER_DRIVERS_AML_MESON_POWER_AML_POWER_H_
#include <lib/device-protocol/pdev.h>
#include <threads.h>
#include <array>
#include <optional>
#include <vector>
#include <ddktl/device.h>
#include <ddktl/protocol/platform/device.h>
#include <ddktl/protocol/powerimpl.h>
#include <ddktl/protocol/pwm.h>
#include <ddktl/protocol/vreg.h>
#include <soc/aml-common/aml-power.h>
#include <soc/aml-s905d2/s905d2-power.h>
#include <soc/aml-s905d3/s905d3-power.h>
#include <soc/aml-t931/t931-power.h>
namespace power {
class AmlPower;
using AmlPowerType = ddk::Device<AmlPower, ddk::Unbindable>;
class AmlPower : public AmlPowerType, public ddk::PowerImplProtocol<AmlPower, ddk::base_protocol> {
private:
static constexpr int kInvalidIndex = -1;
public:
// Constructor for Astro.
AmlPower(zx_device_t* parent, ddk::PwmProtocolClient big_cluster_pwm,
const std::vector<aml_voltage_table_t> voltage_table,
voltage_pwm_period_ns_t pwm_period)
: AmlPowerType(parent),
big_cluster_pwm_(big_cluster_pwm),
big_cluster_vreg_(std::nullopt),
little_cluster_pwm_(std::nullopt),
current_big_cluster_voltage_index_(kInvalidIndex),
current_little_cluster_voltage_index_(kInvalidIndex),
voltage_table_(voltage_table),
pwm_period_(pwm_period),
num_domains_(1) {}
// Constructor for Sherlock.
AmlPower(zx_device_t* parent, ddk::PwmProtocolClient big_cluster_pwm,
ddk::PwmProtocolClient little_cluster_pwm,
const std::vector<aml_voltage_table_t> voltage_table,
voltage_pwm_period_ns_t pwm_period)
: AmlPowerType(parent),
big_cluster_pwm_(big_cluster_pwm),
big_cluster_vreg_(std::nullopt),
little_cluster_pwm_(little_cluster_pwm),
current_big_cluster_voltage_index_(kInvalidIndex),
current_little_cluster_voltage_index_(kInvalidIndex),
voltage_table_(voltage_table),
pwm_period_(pwm_period),
num_domains_(2) {}
AmlPower(zx_device_t* parent, ddk::VregProtocolClient big_cluster_vreg,
ddk::PwmProtocolClient little_cluster_pwm,
const std::vector<aml_voltage_table_t> voltage_table,
voltage_pwm_period_ns_t pwm_period)
: AmlPowerType(parent),
big_cluster_pwm_(std::nullopt),
big_cluster_vreg_(big_cluster_vreg),
little_cluster_pwm_(little_cluster_pwm),
current_big_cluster_voltage_index_(kInvalidIndex),
current_little_cluster_voltage_index_(kInvalidIndex),
voltage_table_(voltage_table),
pwm_period_(pwm_period),
num_domains_(2) {}
AmlPower(const AmlPower&) = delete;
AmlPower(AmlPower&&) = delete;
AmlPower& operator=(const AmlPower&) = delete;
AmlPower& operator=(AmlPower&&) = delete;
virtual ~AmlPower() = default;
static zx_status_t Create(void* ctx, zx_device_t* parent);
// Device protocol implementation
void DdkRelease();
void DdkUnbind(ddk::UnbindTxn txn);
zx_status_t PowerImplGetPowerDomainStatus(uint32_t index, power_domain_status_t* out_status);
zx_status_t PowerImplEnablePowerDomain(uint32_t index);
zx_status_t PowerImplDisablePowerDomain(uint32_t index);
zx_status_t PowerImplGetSupportedVoltageRange(uint32_t index, uint32_t* min_voltage,
uint32_t* max_voltage);
zx_status_t PowerImplRequestVoltage(uint32_t index, uint32_t voltage, uint32_t* actual_voltage);
zx_status_t PowerImplGetCurrentVoltage(uint32_t index, uint32_t* current_voltage);
zx_status_t PowerImplWritePmicCtrlReg(uint32_t index, uint32_t addr, uint32_t value);
zx_status_t PowerImplReadPmicCtrlReg(uint32_t index, uint32_t addr, uint32_t* value);
static constexpr uint32_t kBigClusterDomain = 0;
static constexpr uint32_t kLittleClusterDomain = 1;
static_assert(kBigClusterDomain == static_cast<uint32_t>(S905d2PowerDomains::kArmCore));
static_assert(kBigClusterDomain == static_cast<uint32_t>(S905d3PowerDomains::kArmCore));
static_assert(kBigClusterDomain == static_cast<uint32_t>(T931PowerDomains::kArmCoreBig));
static_assert(kLittleClusterDomain == static_cast<uint32_t>(T931PowerDomains::kArmCoreLittle));
private:
zx_status_t RequestVoltage(const ddk::PwmProtocolClient& pwm, uint32_t u_volts,
int* current_voltage_idx);
zx_status_t SetBigClusterVoltage(uint32_t voltage, uint32_t* actual);
std::optional<ddk::PwmProtocolClient> big_cluster_pwm_;
std::optional<ddk::VregProtocolClient> big_cluster_vreg_;
std::optional<ddk::PwmProtocolClient> little_cluster_pwm_;
int current_big_cluster_voltage_index_;
int current_little_cluster_voltage_index_;
const std::vector<aml_voltage_table_t> voltage_table_;
const voltage_pwm_period_ns_t pwm_period_;
const uint32_t num_domains_;
};
} // namespace power
#endif // SRC_DEVICES_POWER_DRIVERS_AML_MESON_POWER_AML_POWER_H_