1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-11-23 04:12:02 +00:00

powctl: add battery driver logic (missing impl)

This commit is contained in:
Michael Scire 2020-11-10 01:27:35 -08:00 committed by SciresM
parent 28862f69f8
commit 15c752f52d
3 changed files with 328 additions and 59 deletions

View file

@ -30,6 +30,8 @@ namespace ams::powctl::impl::board::nintendo_nx {
return s_max17050_driver; return s_max17050_driver;
} }
constexpr inline const double SenseResistorValue = 0.005;
} }
/* Generic API. */ /* Generic API. */
@ -115,148 +117,345 @@ namespace ams::powctl::impl::board::nintendo_nx {
} }
Result BatteryDriver::GetBatterySocRep(float *out_percent, IDevice *device) { Result BatteryDriver::GetBatterySocRep(float *out_percent, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double percent;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetSocRep(std::addressof(percent)));
/* Set output. */
*out_percent = percent;
return ResultSuccess();
} }
Result BatteryDriver::GetBatterySocVf(float *out_percent, IDevice *device) { Result BatteryDriver::GetBatterySocVf(float *out_percent, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double percent;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetSocVf(std::addressof(percent)));
/* Set output. */
*out_percent = percent;
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryFullCapacity(int *out_mah, IDevice *device) { Result BatteryDriver::GetBatteryFullCapacity(int *out_mah, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_mah != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double mah;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetFullCapacity(std::addressof(mah), SenseResistorValue));
/* Set output. */
*out_mah = mah;
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryRemainingCapacity(int *out_mah, IDevice *device) { Result BatteryDriver::GetBatteryRemainingCapacity(int *out_mah, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_mah != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double mah;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetRemainingCapacity(std::addressof(mah), SenseResistorValue));
/* Set output. */
*out_mah = mah;
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) { Result BatteryDriver::SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageMinimumAlertThreshold(percentage));
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) { Result BatteryDriver::SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageMaximumAlertThreshold(percentage));
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryPercentageFullThreshold(IDevice *device, float percentage) { Result BatteryDriver::SetBatteryPercentageFullThreshold(IDevice *device, float percentage) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageFullThreshold(percentage));
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryAverageCurrent(int *out_ma, IDevice *device) { Result BatteryDriver::GetBatteryAverageCurrent(int *out_ma, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double ma;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageCurrent(std::addressof(ma), SenseResistorValue));
/* Set output. */
*out_ma = ma;
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryCurrent(int *out_ma, IDevice *device) { Result BatteryDriver::GetBatteryCurrent(int *out_ma, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double ma;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetCurrent(std::addressof(ma), SenseResistorValue));
/* Set output. */
*out_ma = ma;
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryInternalState(void *dst, size_t *out_size, IDevice *device, size_t dst_size) { Result BatteryDriver::GetBatteryInternalState(void *dst, size_t *out_size, IDevice *device, size_t dst_size) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(dst != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(out_size != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(dst_size == sizeof(max17050::InternalState), powctl::ResultInvalidArgument());
R_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(dst), alignof(max17050::InternalState)), powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().ReadInternalState());
GetMax17050Driver().GetInternalState(static_cast<max17050::InternalState *>(dst));
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryInternalState(IDevice *device, const void *src, size_t src_size) { Result BatteryDriver::SetBatteryInternalState(IDevice *device, const void *src, size_t src_size) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(src != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(src_size == sizeof(max17050::InternalState), powctl::ResultInvalidArgument());
R_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(src), alignof(max17050::InternalState)), powctl::ResultInvalidArgument());
GetMax17050Driver().SetInternalState(*static_cast<const max17050::InternalState *>(src));
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().WriteInternalState());
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryNeedToRestoreParameters(bool *out, IDevice *device) { Result BatteryDriver::GetBatteryNeedToRestoreParameters(bool *out, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetNeedToRestoreParameters(out));
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryNeedToRestoreParameters(IDevice *device, bool en) { Result BatteryDriver::SetBatteryNeedToRestoreParameters(IDevice *device, bool en) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Set the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetNeedToRestoreParameters(en));
return ResultSuccess();
} }
Result BatteryDriver::IsBatteryI2cShutdownEnabled(bool *out, IDevice *device) { Result BatteryDriver::IsBatteryI2cShutdownEnabled(bool *out, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().IsI2cShutdownEnabled(out));
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryI2cShutdownEnabled(IDevice *device, bool en) { Result BatteryDriver::SetBatteryI2cShutdownEnabled(IDevice *device, bool en) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Set the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetI2cShutdownEnabled(en));
return ResultSuccess();
} }
Result BatteryDriver::IsBatteryPresent(bool *out, IDevice *device) { Result BatteryDriver::IsBatteryPresent(bool *out, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the battery status. */
u16 status;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetStatus(std::addressof(status)));
/* Set output. */
*out = (status & 0x0008) == 0;
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryCycles(int *out, IDevice *device) { Result BatteryDriver::GetBatteryCycles(int *out, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the battery cycles. */
u16 cycles;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetCycles(std::addressof(cycles)));
/* Set output. */
*out = cycles;
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryCycles(IDevice *device, int cycles) { Result BatteryDriver::SetBatteryCycles(IDevice *device, int cycles) {
/* TODO */ R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_ABORT(); R_UNLESS(cycles == 0, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().ResetCycles());
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryAge(float *out_percent, IDevice *device) { Result BatteryDriver::GetBatteryAge(float *out_percent, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double percent;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAge(std::addressof(percent)));
/* Set output. */
*out_percent = percent;
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryTemperature(float *out_c, IDevice *device) { Result BatteryDriver::GetBatteryTemperature(float *out_c, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_c != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double temp;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetTemperature(std::addressof(temp)));
/* Set output. */
*out_c = temp;
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryMaximumTemperature(float *out_c, IDevice *device) { Result BatteryDriver::GetBatteryMaximumTemperature(float *out_c, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_c != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
u8 max_temp;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetMaximumTemperature(std::addressof(max_temp)));
/* Set output. */
*out_c = static_cast<float>(max_temp);
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryTemperatureMinimumAlertThreshold(IDevice *device, float c) { Result BatteryDriver::SetBatteryTemperatureMinimumAlertThreshold(IDevice *device, float c) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMinimumAlertThreshold(c));
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryTemperatureMaximumAlertThreshold(IDevice *device, float c) { Result BatteryDriver::SetBatteryTemperatureMaximumAlertThreshold(IDevice *device, float c) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMaximumAlertThreshold(c));
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryVCell(int *out_mv, IDevice *device) { Result BatteryDriver::GetBatteryVCell(int *out_mv, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetVCell(out_mv));
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryAverageVCell(int *out_mv, IDevice *device) { Result BatteryDriver::GetBatteryAverageVCell(int *out_mv, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCell(out_mv));
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryAverageVCellTime(TimeSpan *out, IDevice *device) { Result BatteryDriver::GetBatteryAverageVCellTime(TimeSpan *out, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
double ms;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCellTime(std::addressof(ms)));
/* Set output. */
*out = TimeSpan::FromMicroSeconds(static_cast<s64>(ms * 1000.0));
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryVoltageMinimumAlertThreshold(IDevice *device, int mv) { Result BatteryDriver::SetBatteryVoltageMinimumAlertThreshold(IDevice *device, int mv) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMinimumAlertThreshold(mv));
return ResultSuccess();
} }
Result BatteryDriver::GetBatteryOpenCircuitVoltage(int *out_mv, IDevice *device) { Result BatteryDriver::GetBatteryOpenCircuitVoltage(int *out_mv, IDevice *device) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetOpenCircuitVoltage(out_mv));
return ResultSuccess();
} }
Result BatteryDriver::SetBatteryVoltageMaximumAlertThreshold(IDevice *device, int mv) { Result BatteryDriver::SetBatteryVoltageMaximumAlertThreshold(IDevice *device, int mv) {
/* TODO */ /* Validate arguments. */
AMS_ABORT(); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMaximumAlertThreshold(mv));
return ResultSuccess();
} }
} }

View file

@ -156,6 +156,7 @@ namespace ams::powctl::impl::board::nintendo_nx {
} }
} }
} }
} }
@ -417,4 +418,8 @@ namespace ams::powctl::impl::board::nintendo_nx {
return ReadWriteRegister(this->i2c_session, max17050::MiscCfg, 0x8000, en ? 0x8000 : 0); return ReadWriteRegister(this->i2c_session, max17050::MiscCfg, 0x8000, en ? 0x8000 : 0);
} }
Result Max17050Driver::ResetCycles() {
return WriteRegister(this->i2c_session, max17050::Cycles, 0x0060);
}
} }

View file

@ -20,6 +20,19 @@ namespace ams::powctl::impl::board::nintendo_nx {
namespace max17050 { namespace max17050 {
struct InternalState {
u16 rcomp0;
u16 tempco;
u16 fullcap;
u16 cycles;
u16 fullcapnom;
u16 iavgempty;
u16 qresidual00;
u16 qresidual10;
u16 qresidual20;
u16 qresidual30;
};
} }
class Max17050Driver { class Max17050Driver {
@ -27,6 +40,7 @@ namespace ams::powctl::impl::board::nintendo_nx {
os::SdkMutex mutex; os::SdkMutex mutex;
int init_count; int init_count;
i2c::I2cSession i2c_session; i2c::I2cSession i2c_session;
max17050::InternalState internal_state;
private: private:
Result InitializeSession(const char *battery_vendor, u8 battery_version); Result InitializeSession(const char *battery_vendor, u8 battery_version);
Result SetMaximumShutdownTimerThreshold(); Result SetMaximumShutdownTimerThreshold();
@ -40,7 +54,7 @@ namespace ams::powctl::impl::board::nintendo_nx {
Result SetModelTable(const u16 *model_table); Result SetModelTable(const u16 *model_table);
bool IsModelTableSet(const u16 *model_table); bool IsModelTableSet(const u16 *model_table);
public: public:
Max17050Driver() : mutex(), init_count(0), i2c_session() { Max17050Driver() : mutex(), init_count(0), i2c_session(), internal_state() {
/* ... */ /* ... */
} }
@ -72,8 +86,59 @@ namespace ams::powctl::impl::board::nintendo_nx {
} }
} }
Result ReadInternalState();
Result WriteInternalState();
void GetInternalState(max17050::InternalState *dst) {
*dst = this->internal_state;
}
void SetInternalState(const max17050::InternalState &src) {
this->internal_state = src;
}
Result GetSocRep(double *out);
Result GetSocVf(double *out);
Result GetFullCapacity(double *out, double sense_resistor);
Result GetRemainingCapacity(double *out, double sense_resistor);
Result SetPercentageMinimumAlertThreshold(int percentage);
Result SetPercentageMaximumAlertThreshold(int percentage);
Result SetPercentageFullThreshold(double percentage);
Result GetAverageCurrent(double *out, double sense_resistor);
Result GetCurrent(double *out, double sense_resistor);
Result GetNeedToRestoreParameters(bool *out); Result GetNeedToRestoreParameters(bool *out);
Result SetNeedToRestoreParameters(bool en); Result SetNeedToRestoreParameters(bool en);
Result IsI2cShutdownEnabled(bool *out);
Result SetI2cShutdownEnabled(bool en);
Result GetStatus(u16 *out);
Result GetCycles(u16 *out);
Result ResetCycles();
Result GetAge(double *out);
Result GetTemperature(double *out);
Result GetMaximumTemperature(u8 *out);
Result SetTemperatureMinimumAlertThreshold(int c);
Result SetTemperatureMaximumAlertThreshold(int c);
Result GetVCell(int *out);
Result GetAverageVCell(int *out);
Result GetAverageVCellTime(double *out);
Result GetOpenCircuitVoltage(int *out);
Result SetVoltageMinimumAlertThreshold(int mv);
Result SetVoltageMaximumAlertThreshold(int mv);
}; };
} }