blob: f6a5dcaa36e44701f1043606400de3013ceaa089 [file] [log] [blame]
// Copyright 2018 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_THERMAL_DRIVERS_MTK_THERMAL_MTK_THERMAL_H_
#define SRC_DEVICES_THERMAL_DRIVERS_MTK_THERMAL_MTK_THERMAL_H_
#include <fuchsia/hardware/platform/device/cpp/banjo.h>
#include <fuchsia/hardware/thermal/c/fidl.h>
#include <lib/device-protocol/platform-device.h>
#include <lib/fidl-utils/bind.h>
#include <lib/mmio/mmio.h>
#include <lib/zx/interrupt.h>
#include <lib/zx/port.h>
#include <threads.h>
#include <ddktl/device.h>
#include <ddktl/protocol/empty-protocol.h>
#include <fbl/mutex.h>
#include "mtk-thermal-reg.h"
namespace thermal {
class MtkThermal;
using DeviceType = ddk::Device<MtkThermal, ddk::Messageable>;
class MtkThermal : public DeviceType, public ddk::EmptyProtocol<ZX_PROTOCOL_THERMAL> {
public:
virtual ~MtkThermal() = default;
static zx_status_t Create(void* ctx, zx_device_t* parent);
void DdkRelease();
zx_status_t DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn);
// Visible for testing.
uint16_t get_dvfs_opp() { return current_op_idx_; }
zx_status_t Init();
zx_status_t GetPort(zx::port* port) { return port_.duplicate(ZX_RIGHT_SAME_RIGHTS, port); }
zx_status_t StartThread();
virtual zx_status_t StopThread();
protected:
// Visible for testing.
MtkThermal(zx_device_t* parent, ddk::MmioBuffer mmio, ddk::MmioBuffer pll_mmio,
ddk::MmioBuffer pmic_mmio, ddk::MmioBuffer infracfg_mmio,
const ddk::PDevProtocolClient& pdev,
const fuchsia_hardware_thermal_ThermalDeviceInfo& thermal_info, zx::port port,
zx::interrupt irq, TempCalibration0 cal0_fuse, TempCalibration1 cal1_fuse,
TempCalibration2 cal2_fuse)
: DeviceType(parent),
mmio_(std::move(mmio)),
pll_mmio_(std::move(pll_mmio)),
pmic_mmio_(std::move(pmic_mmio)),
infracfg_mmio_(std::move(infracfg_mmio)),
pdev_(pdev),
thermal_info_(thermal_info),
port_(std::move(port)),
irq_(std::move(irq)),
cal0_fuse_(cal0_fuse),
cal1_fuse_(cal1_fuse),
cal2_fuse_(cal2_fuse) {}
virtual void PmicWrite(uint16_t data, uint32_t addr);
virtual float ReadTemperatureSensors();
virtual zx_status_t SetDvfsOpp(uint16_t op_idx);
virtual zx_status_t SetTripPoint(size_t trip_pt);
virtual zx_status_t WaitForInterrupt();
int JoinThread() { return thrd_join(thread_, nullptr); }
ddk::MmioBuffer mmio_;
ddk::MmioBuffer pll_mmio_;
ddk::MmioBuffer pmic_mmio_;
ddk::MmioBuffer infracfg_mmio_;
private:
zx_status_t GetInfo(fidl_txn_t* txn);
zx_status_t GetDeviceInfo(fidl_txn_t* txn);
zx_status_t GetDvfsInfo(fuchsia_hardware_thermal_PowerDomain power_domain, fidl_txn_t* txn);
zx_status_t GetTemperatureCelsius(fidl_txn_t* txn);
zx_status_t GetStateChangeEvent(fidl_txn_t* txn);
zx_status_t GetStateChangePort(fidl_txn_t* txn);
zx_status_t SetTripCelsius(uint32_t id, float temp, fidl_txn_t* txn);
zx_status_t GetDvfsOperatingPoint(fuchsia_hardware_thermal_PowerDomain power_domain,
fidl_txn_t* txn);
zx_status_t SetDvfsOperatingPoint(uint16_t op_idx,
fuchsia_hardware_thermal_PowerDomain power_domain,
fidl_txn_t* txn);
zx_status_t GetFanLevel(fidl_txn_t* txn);
zx_status_t SetFanLevel(uint32_t fan_level, fidl_txn_t* txn);
static constexpr fuchsia_hardware_thermal_Device_ops_t fidl_ops = {
.GetTemperatureCelsius =
fidl::Binder<MtkThermal>::BindMember<&MtkThermal::GetTemperatureCelsius>,
.GetInfo = fidl::Binder<MtkThermal>::BindMember<&MtkThermal::GetInfo>,
.GetDeviceInfo = fidl::Binder<MtkThermal>::BindMember<&MtkThermal::GetDeviceInfo>,
.GetDvfsInfo = fidl::Binder<MtkThermal>::BindMember<&MtkThermal::GetDvfsInfo>,
.GetStateChangeEvent = fidl::Binder<MtkThermal>::BindMember<&MtkThermal::GetStateChangeEvent>,
.GetStateChangePort = fidl::Binder<MtkThermal>::BindMember<&MtkThermal::GetStateChangePort>,
.SetTripCelsius = fidl::Binder<MtkThermal>::BindMember<&MtkThermal::SetTripCelsius>,
.GetDvfsOperatingPoint =
fidl::Binder<MtkThermal>::BindMember<&MtkThermal::GetDvfsOperatingPoint>,
.SetDvfsOperatingPoint =
fidl::Binder<MtkThermal>::BindMember<&MtkThermal::SetDvfsOperatingPoint>,
.GetFanLevel = fidl::Binder<MtkThermal>::BindMember<&MtkThermal::GetFanLevel>,
.SetFanLevel = fidl::Binder<MtkThermal>::BindMember<&MtkThermal::SetFanLevel>,
};
float RawToTemperature(uint32_t raw, uint32_t sensor);
uint32_t TemperatureToRaw(float temp, uint32_t sensor);
uint32_t GetRawHot(float temp);
uint32_t GetRawCold(float temp);
int Thread();
ddk::PDevProtocolClient pdev_;
const fuchsia_hardware_thermal_ThermalDeviceInfo thermal_info_;
uint16_t current_op_idx_ = 0;
zx::port port_;
zx::interrupt irq_;
thrd_t thread_;
fbl::Mutex dvfs_lock_;
const TempCalibration0 cal0_fuse_;
const TempCalibration1 cal1_fuse_;
const TempCalibration2 cal2_fuse_;
};
} // namespace thermal
#endif // SRC_DEVICES_THERMAL_DRIVERS_MTK_THERMAL_MTK_THERMAL_H_