powctl: integrate 13.0.0 changes (aula params not done yet)

This commit is contained in:
Michael Scire 2021-10-15 16:30:27 -07:00
parent c04a262d49
commit 990daec3a2
16 changed files with 241 additions and 154 deletions

View file

@ -21,16 +21,20 @@
namespace ams::powctl { namespace ams::powctl {
/* Battery API. */ /* Battery API. */
Result GetBatterySocRep(float *out_percent, Session &session); Result GetBatteryChargePercentage(float *out_percent, Session &session);
Result GetBatterySocVf(float *out_percent, Session &session); Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, Session &session);
Result GetBatteryFullCapacity(int *out_mah, Session &session); Result GetBatteryFullCapacity(int *out_mah, Session &session);
Result GetBatteryRemainingCapacity(int *out_mah, Session &session); Result GetBatteryRemainingCapacity(int *out_mah, Session &session);
Result SetBatteryPercentageMinimumAlertThreshold(Session &session, float percentage); Result SetBatteryChargePercentageMinimumAlertThreshold(Session &session, float percentage);
Result SetBatteryPercentageMaximumAlertThreshold(Session &session, float percentage); Result SetBatteryChargePercentageMaximumAlertThreshold(Session &session, float percentage);
Result SetBatteryPercentageFullThreshold(Session &session, float percentage);
Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(Session &session, float percentage);
Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(Session &session, float percentage);
Result SetBatteryFullChargeThreshold(Session &session, float percentage);
Result GetBatteryAverageCurrent(int *out_ma, Session &session); Result GetBatteryAverageCurrent(int *out_ma, Session &session);
Result GetBatteryCurrent(int *out_ma, Session &session); Result GetBatteryCurrent(int *out_ma, Session &session);

View file

@ -37,6 +37,10 @@ namespace ams::powctl {
bool has_session; bool has_session;
util::TypedStorage<impl::SessionImpl> impl_storage; util::TypedStorage<impl::SessionImpl> impl_storage;
struct ConstantInitializeTag{};
constexpr Session(ConstantInitializeTag) : has_session(false), impl_storage() { /* ... */ }
Session() : has_session(false) { /* ... */ } Session() : has_session(false) { /* ... */ }
}; };

View file

@ -25,21 +25,10 @@ namespace ams::powctl::impl::board::nintendo::nx {
constinit util::optional<BatteryDevice> g_battery_device; constinit util::optional<BatteryDevice> g_battery_device;
constinit util::TypedStorage<Max17050Driver> g_max17050_driver; constinit Max17050Driver g_max17050_driver;
constinit bool g_constructed_max17050_driver;
constinit os::SdkMutex g_max17050_driver_mutex;
Max17050Driver &GetMax17050Driver() { ALWAYS_INLINE Max17050Driver &GetMax17050Driver() {
if (AMS_UNLIKELY(!g_constructed_max17050_driver)) { return g_max17050_driver;
std::scoped_lock lk(g_max17050_driver_mutex);
if (AMS_LIKELY(!g_constructed_max17050_driver)) {
util::ConstructAt(g_max17050_driver);
g_constructed_max17050_driver = true;
}
}
return util::GetReference(g_max17050_driver);
} }
constexpr inline const double SenseResistorValue = 0.005; constexpr inline const double SenseResistorValue = 0.005;
@ -143,28 +132,28 @@ namespace ams::powctl::impl::board::nintendo::nx {
AMS_ABORT(); AMS_ABORT();
} }
Result BatteryDriver::GetBatterySocRep(float *out_percent, IDevice *device) { Result BatteryDriver::GetBatteryChargePercentage(float *out_percent, IDevice *device) {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */ /* Get the value. */
double percent; double percent;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetSocRep(std::addressof(percent))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetChargePercentage(std::addressof(percent)));
/* Set output. */ /* Set output. */
*out_percent = percent; *out_percent = percent;
return ResultSuccess(); return ResultSuccess();
} }
Result BatteryDriver::GetBatterySocVf(float *out_percent, IDevice *device) { Result BatteryDriver::GetBatteryVoltageFuelGaugePercentage(float *out_percent, IDevice *device) {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out_percent != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */ /* Get the value. */
double percent; double percent;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetSocVf(std::addressof(percent))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetVoltageFuelGaugePercentage(std::addressof(percent)));
/* Set output. */ /* Set output. */
*out_percent = percent; *out_percent = percent;
@ -178,7 +167,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the value. */ /* Get the value. */
double mah; double mah;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetFullCapacity(std::addressof(mah), SenseResistorValue)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetFullCapacity(std::addressof(mah), SenseResistorValue));
/* Set output. */ /* Set output. */
*out_mah = mah; *out_mah = mah;
@ -192,36 +181,54 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the value. */ /* Get the value. */
double mah; double mah;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetRemainingCapacity(std::addressof(mah), SenseResistorValue)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetRemainingCapacity(std::addressof(mah), SenseResistorValue));
/* Set output. */ /* Set output. */
*out_mah = mah; *out_mah = mah;
return ResultSuccess(); return ResultSuccess();
} }
Result BatteryDriver::SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) { Result BatteryDriver::SetBatteryChargePercentageMinimumAlertThreshold(IDevice *device, float percentage) {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageMinimumAlertThreshold(percentage)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetChargePercentageMinimumAlertThreshold(percentage));
return ResultSuccess(); return ResultSuccess();
} }
Result BatteryDriver::SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) { Result BatteryDriver::SetBatteryChargePercentageMaximumAlertThreshold(IDevice *device, float percentage) {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageMaximumAlertThreshold(percentage)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetChargePercentageMaximumAlertThreshold(percentage));
return ResultSuccess(); return ResultSuccess();
} }
Result BatteryDriver::SetBatteryPercentageFullThreshold(IDevice *device, float percentage) { Result BatteryDriver::SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(IDevice *device, float percentage) {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetPercentageFullThreshold(percentage)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageFuelGaugePercentageMinimumAlertThreshold(percentage));
return ResultSuccess();
}
Result BatteryDriver::SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(IDevice *device, float percentage) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageFuelGaugePercentageMaximumAlertThreshold(percentage));
return ResultSuccess();
}
Result BatteryDriver::SetBatteryFullChargeThreshold(IDevice *device, float percentage) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetFullChargeThreshold(percentage));
return ResultSuccess(); return ResultSuccess();
} }
@ -233,7 +240,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the value. */ /* Get the value. */
double ma; double ma;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageCurrent(std::addressof(ma), SenseResistorValue)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageCurrent(std::addressof(ma), SenseResistorValue));
/* Set output. */ /* Set output. */
*out_ma = ma; *out_ma = ma;
@ -247,7 +254,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the value. */ /* Get the value. */
double ma; double ma;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetCurrent(std::addressof(ma), SenseResistorValue)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetCurrent(std::addressof(ma), SenseResistorValue));
/* Set output. */ /* Set output. */
*out_ma = ma; *out_ma = ma;
@ -262,7 +269,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(dst_size == sizeof(max17050::InternalState), 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()); R_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(dst), alignof(max17050::InternalState)), powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().ReadInternalState()); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().ReadInternalState());
GetMax17050Driver().GetInternalState(static_cast<max17050::InternalState *>(dst)); GetMax17050Driver().GetInternalState(static_cast<max17050::InternalState *>(dst));
return ResultSuccess(); return ResultSuccess();
@ -276,7 +283,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(src), alignof(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)); GetMax17050Driver().SetInternalState(*static_cast<const max17050::InternalState *>(src));
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().WriteInternalState()); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().WriteInternalState());
return ResultSuccess(); return ResultSuccess();
} }
@ -287,7 +294,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */ /* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetNeedToRestoreParameters(out)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetNeedToRestoreParameters(out));
return ResultSuccess(); return ResultSuccess();
} }
@ -297,7 +304,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Set the value. */ /* Set the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetNeedToRestoreParameters(en)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetNeedToRestoreParameters(en));
return ResultSuccess(); return ResultSuccess();
} }
@ -308,7 +315,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */ /* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().IsI2cShutdownEnabled(out)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().IsI2cShutdownEnabled(out));
return ResultSuccess(); return ResultSuccess();
} }
@ -318,7 +325,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Set the value. */ /* Set the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetI2cShutdownEnabled(en)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetI2cShutdownEnabled(en));
return ResultSuccess(); return ResultSuccess();
} }
@ -330,7 +337,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the battery status. */ /* Get the battery status. */
u16 status; u16 status;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetStatus(std::addressof(status))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetStatus(std::addressof(status)));
/* Set output. */ /* Set output. */
*out = (status & 0x0008) == 0; *out = (status & 0x0008) == 0;
@ -344,7 +351,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the battery cycles. */ /* Get the battery cycles. */
u16 cycles; u16 cycles;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetCycles(std::addressof(cycles))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetCycles(std::addressof(cycles)));
/* Set output. */ /* Set output. */
*out = cycles; *out = cycles;
@ -355,7 +362,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(cycles == 0, powctl::ResultInvalidArgument()); R_UNLESS(cycles == 0, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().ResetCycles()); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().ResetCycles());
return ResultSuccess(); return ResultSuccess();
} }
@ -367,7 +374,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the value. */ /* Get the value. */
double percent; double percent;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAge(std::addressof(percent))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetAge(std::addressof(percent)));
/* Set output. */ /* Set output. */
*out_percent = percent; *out_percent = percent;
@ -381,7 +388,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the value. */ /* Get the value. */
double temp; double temp;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetTemperature(std::addressof(temp))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetTemperature(std::addressof(temp)));
/* Set output. */ /* Set output. */
*out_c = temp; *out_c = temp;
@ -395,7 +402,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the value. */ /* Get the value. */
u8 max_temp; u8 max_temp;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetMaximumTemperature(std::addressof(max_temp))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetMaximumTemperature(std::addressof(max_temp)));
/* Set output. */ /* Set output. */
*out_c = static_cast<float>(max_temp); *out_c = static_cast<float>(max_temp);
@ -406,7 +413,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMinimumAlertThreshold(c)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMinimumAlertThreshold(c));
return ResultSuccess(); return ResultSuccess();
} }
@ -415,7 +422,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMaximumAlertThreshold(c)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetTemperatureMaximumAlertThreshold(c));
return ResultSuccess(); return ResultSuccess();
} }
@ -426,7 +433,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */ /* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetVCell(out_mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetVCell(out_mv));
return ResultSuccess(); return ResultSuccess();
} }
@ -437,7 +444,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */ /* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCell(out_mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCell(out_mv));
return ResultSuccess(); return ResultSuccess();
} }
@ -449,7 +456,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Get the value. */ /* Get the value. */
double ms; double ms;
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCellTime(std::addressof(ms))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetAverageVCellTime(std::addressof(ms)));
/* Set output. */ /* Set output. */
*out = TimeSpan::FromMicroSeconds(static_cast<s64>(ms * 1000.0)); *out = TimeSpan::FromMicroSeconds(static_cast<s64>(ms * 1000.0));
@ -460,7 +467,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMinimumAlertThreshold(mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMinimumAlertThreshold(mv));
return ResultSuccess(); return ResultSuccess();
} }
@ -471,7 +478,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Get the value. */ /* Get the value. */
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().GetOpenCircuitVoltage(out_mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().GetOpenCircuitVoltage(out_mv));
return ResultSuccess(); return ResultSuccess();
} }
@ -480,7 +487,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMaximumAlertThreshold(mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetMax17050Driver().SetVoltageMaximumAlertThreshold(mv));
return ResultSuccess(); return ResultSuccess();
} }

View file

@ -58,16 +58,19 @@ namespace ams::powctl::impl::board::nintendo::nx {
virtual Result SetDeviceErrorStatus(IDevice *device, u32 status) override; virtual Result SetDeviceErrorStatus(IDevice *device, u32 status) override;
/* Battery API. */ /* Battery API. */
virtual Result GetBatterySocRep(float *out_percent, IDevice *device) override; virtual Result GetBatteryChargePercentage(float *out_percent, IDevice *device) override;
virtual Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, IDevice *device) override;
virtual Result GetBatterySocVf(float *out_percent, IDevice *device) override;
virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) override; virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) override;
virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) override; virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) override;
virtual Result SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) override; virtual Result SetBatteryChargePercentageMinimumAlertThreshold(IDevice *device, float percentage) override;
virtual Result SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) override; virtual Result SetBatteryChargePercentageMaximumAlertThreshold(IDevice *device, float percentage) override;
virtual Result SetBatteryPercentageFullThreshold(IDevice *device, float percentage) override;
virtual Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(IDevice *device, float percentage) override;
virtual Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(IDevice *device, float percentage) override;
virtual Result SetBatteryFullChargeThreshold(IDevice *device, float percentage) override;
virtual Result GetBatteryAverageCurrent(int *out_ma, IDevice *device) override; virtual Result GetBatteryAverageCurrent(int *out_ma, IDevice *device) override;
virtual Result GetBatteryCurrent(int *out_ma, IDevice *device) override; virtual Result GetBatteryCurrent(int *out_ma, IDevice *device) override;

View file

@ -84,8 +84,9 @@ namespace ams::powctl::impl::board::nintendo::nx {
constexpr int DecodeChargeVoltageLimit(u8 reg) { constexpr int DecodeChargeVoltageLimit(u8 reg) {
constexpr int Minimum = 3504; constexpr int Minimum = 3504;
constexpr int Maximum = 4400;
return Minimum + (static_cast<u32>(reg & 0xFC) << 2); return std::min<int>(Maximum, Minimum + (static_cast<u32>(reg & 0xFC) << 2));
} }
static_assert(DecodeChargeVoltageLimit(EncodeChargeVoltageLimit(3504)) == 3504); static_assert(DecodeChargeVoltageLimit(EncodeChargeVoltageLimit(3504)) == 3504);

View file

@ -43,7 +43,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
private: private:
Result InitializeSession(); Result InitializeSession();
public: public:
Bq24193Driver() : m_mutex(), m_init_count(0), m_i2c_session() { constexpr Bq24193Driver() : m_mutex(), m_init_count(0), m_i2c_session() {
/* ... */ /* ... */
} }

View file

@ -25,21 +25,10 @@ namespace ams::powctl::impl::board::nintendo::nx {
constinit util::optional<ChargerDevice> g_charger_device; constinit util::optional<ChargerDevice> g_charger_device;
constinit util::TypedStorage<Bq24193Driver> g_bq24193_driver; constinit Bq24193Driver g_bq24193_driver;
constinit bool g_constructed_bq24193_driver;
constinit os::SdkMutex g_bq24193_driver_mutex;
Bq24193Driver &GetBq24193Driver() { ALWAYS_INLINE Bq24193Driver &GetBq24193Driver() {
if (AMS_UNLIKELY(!g_constructed_bq24193_driver)) { return g_bq24193_driver;
std::scoped_lock lk(g_bq24193_driver_mutex);
if (AMS_LIKELY(!g_constructed_bq24193_driver)) {
util::ConstructAt(g_bq24193_driver);
g_constructed_bq24193_driver = true;
}
}
return util::GetReference(g_bq24193_driver);
} }
} }
@ -141,13 +130,15 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(out != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* NOTE: Nintendo doesn't hold the mutex while doing the gpio:: call here, for some reason. */
/* Check if we're not charging. */ /* Check if we're not charging. */
if (gpio::GetValue(device->SafeCastTo<ChargerDevice>().GetPadSession()) == gpio::GpioValue_High) { if (gpio::GetValue(device->SafeCastTo<ChargerDevice>().GetPadSession()) == gpio::GpioValue_High) {
*out = ChargeCurrentState_NotCharging; *out = ChargeCurrentState_NotCharging;
} else { } else {
/* Get force 20 percent charge state. */ /* Get force 20 percent charge state. */
bool force_20_percent; bool force_20_percent;
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetForce20PercentChargeCurrent(std::addressof(force_20_percent))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetForce20PercentChargeCurrent(std::addressof(force_20_percent)));
/* Set output appropriately. */ /* Set output appropriately. */
if (force_20_percent) { if (force_20_percent) {
@ -164,6 +155,8 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
std::scoped_lock lk(this->GetMutex());
switch (state) { switch (state) {
case ChargeCurrentState_NotCharging: case ChargeCurrentState_NotCharging:
gpio::SetValue(device->SafeCastTo<ChargerDevice>().GetPadSession(), gpio::GpioValue_High); gpio::SetValue(device->SafeCastTo<ChargerDevice>().GetPadSession(), gpio::GpioValue_High);
@ -171,7 +164,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
case ChargeCurrentState_ChargingForce20Percent: case ChargeCurrentState_ChargingForce20Percent:
case ChargeCurrentState_Charging: case ChargeCurrentState_Charging:
gpio::SetValue(device->SafeCastTo<ChargerDevice>().GetPadSession(), gpio::GpioValue_Low); gpio::SetValue(device->SafeCastTo<ChargerDevice>().GetPadSession(), gpio::GpioValue_Low);
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetForce20PercentChargeCurrent(state == ChargeCurrentState_ChargingForce20Percent)); AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY(GetBq24193Driver().SetForce20PercentChargeCurrent(state == ChargeCurrentState_ChargingForce20Percent));
break; break;
case ChargeCurrentState_Unknown: case ChargeCurrentState_Unknown:
return powctl::ResultInvalidArgument(); return powctl::ResultInvalidArgument();
@ -185,7 +178,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetFastChargeCurrentLimit(out_ma)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetFastChargeCurrentLimit(out_ma));
return ResultSuccess(); return ResultSuccess();
} }
@ -193,7 +186,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetFastChargeCurrentLimit(ma)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetFastChargeCurrentLimit(ma));
return ResultSuccess(); return ResultSuccess();
} }
@ -202,7 +195,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargeVoltageLimit(out_mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargeVoltageLimit(out_mv));
return ResultSuccess(); return ResultSuccess();
} }
@ -210,7 +203,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargeVoltageLimit(mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargeVoltageLimit(mv));
return ResultSuccess(); return ResultSuccess();
} }
@ -226,7 +219,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
AMS_UNREACHABLE_DEFAULT_CASE(); AMS_UNREACHABLE_DEFAULT_CASE();
} }
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargerConfiguration(bq_cfg)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargerConfiguration(bq_cfg));
return ResultSuccess(); return ResultSuccess();
} }
@ -235,7 +228,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(out != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().IsHiZEnabled(out)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().IsHiZEnabled(out));
return ResultSuccess(); return ResultSuccess();
} }
@ -243,7 +236,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetHiZEnabled(en)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetHiZEnabled(en));
return ResultSuccess(); return ResultSuccess();
} }
@ -252,7 +245,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetInputCurrentLimit(out_ma)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetInputCurrentLimit(out_ma));
return ResultSuccess(); return ResultSuccess();
} }
@ -260,7 +253,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputCurrentLimit(ma)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputCurrentLimit(ma));
return ResultSuccess(); return ResultSuccess();
} }
@ -268,7 +261,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputVoltageLimit(mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputVoltageLimit(mv));
return ResultSuccess(); return ResultSuccess();
} }
@ -276,7 +269,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetBoostModeCurrentLimit(ma)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetBoostModeCurrentLimit(ma));
return ResultSuccess(); return ResultSuccess();
} }
@ -285,7 +278,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
bq24193::ChargerStatus bq_status; bq24193::ChargerStatus bq_status;
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargerStatus(std::addressof(bq_status))); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargerStatus(std::addressof(bq_status)));
switch (bq_status) { switch (bq_status) {
case bq24193::ChargerStatus_NotCharging: case bq24193::ChargerStatus_NotCharging:
@ -320,10 +313,11 @@ namespace ams::powctl::impl::board::nintendo::nx {
auto &charger_device = device->SafeCastTo<ChargerDevice>(); auto &charger_device = device->SafeCastTo<ChargerDevice>();
if (en) { if (en) {
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer()); std::scoped_lock lk(this->GetMutex());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(charger_device.GetWatchdogTimerTimeout().GetSeconds())); AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer());
AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(charger_device.GetWatchdogTimerTimeout().GetSeconds()));
} else { } else {
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(0)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(0));
} }
charger_device.SetWatchdogTimerEnabled(en); charger_device.SetWatchdogTimerEnabled(en);
@ -342,7 +336,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer()); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer());
return ResultSuccess(); return ResultSuccess();
} }
@ -351,7 +345,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(out_mo != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out_mo != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetBatteryCompensation(out_mo)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetBatteryCompensation(out_mo));
return ResultSuccess(); return ResultSuccess();
} }
@ -359,7 +353,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetBatteryCompensation(mo)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetBatteryCompensation(mo));
return ResultSuccess(); return ResultSuccess();
} }
@ -368,7 +362,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetVoltageClamp(out_mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().GetVoltageClamp(out_mv));
return ResultSuccess(); return ResultSuccess();
} }
@ -376,7 +370,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
/* Validate arguments. */ /* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument()); R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetVoltageClamp(mv)); AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(GetBq24193Driver().SetVoltageClamp(mv));
return ResultSuccess(); return ResultSuccess();
} }

View file

@ -105,16 +105,20 @@ namespace ams::powctl::impl::board::nintendo::nx {
virtual Result SetChargerVoltageClamp(IDevice *device, int mv) override; virtual Result SetChargerVoltageClamp(IDevice *device, int mv) override;
/* Unsupported Battery API. */ /* Unsupported Battery API. */
virtual Result GetBatterySocRep(float *out_percent, IDevice *device) override { AMS_UNUSED(out_percent, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryChargePercentage(float *out_percent, IDevice *device) override { AMS_UNUSED(out_percent, device); return powctl::ResultNotSupported(); }
virtual Result GetBatterySocVf(float *out_percent, IDevice *device) override { AMS_UNUSED(out_percent, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, IDevice *device) override { AMS_UNUSED(out_percent, device); return powctl::ResultNotSupported(); }
virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) override { AMS_UNUSED(out_mah, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) override { AMS_UNUSED(out_mah, device); return powctl::ResultNotSupported(); }
virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) override { AMS_UNUSED(out_mah, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) override { AMS_UNUSED(out_mah, device); return powctl::ResultNotSupported(); }
virtual Result SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } virtual Result SetBatteryChargePercentageMinimumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); }
virtual Result SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); } virtual Result SetBatteryChargePercentageMaximumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); }
virtual Result SetBatteryPercentageFullThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); }
virtual Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); }
virtual Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); }
virtual Result SetBatteryFullChargeThreshold(IDevice *device, float percentage) override { AMS_UNUSED(device, percentage); return powctl::ResultNotSupported(); }
virtual Result GetBatteryAverageCurrent(int *out_ma, IDevice *device) override { AMS_UNUSED(out_ma, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryAverageCurrent(int *out_ma, IDevice *device) override { AMS_UNUSED(out_ma, device); return powctl::ResultNotSupported(); }
virtual Result GetBatteryCurrent(int *out_ma, IDevice *device) override { AMS_UNUSED(out_ma, device); return powctl::ResultNotSupported(); } virtual Result GetBatteryCurrent(int *out_ma, IDevice *device) override { AMS_UNUSED(out_ma, device); return powctl::ResultNotSupported(); }

View file

@ -330,11 +330,11 @@ namespace ams::powctl::impl::board::nintendo::nx {
u16 vfsoc, qh; u16 vfsoc, qh;
{ {
R_TRY(ReadRegister(m_i2c_session, max17050::SocVf, std::addressof(vfsoc))); R_TRY(ReadRegister(m_i2c_session, max17050::SocVf, std::addressof(vfsoc)));
R_TRY(this->UnlockVfSoc()); R_TRY(this->UnlockVoltageFuelGauge());
while (!WriteValidateRegister(m_i2c_session, max17050::SocVf0, vfsoc)) { /* ... */ } while (!WriteValidateRegister(m_i2c_session, max17050::SocVf0, vfsoc)) { /* ... */ }
R_TRY(ReadRegister(m_i2c_session, max17050::Qh, std::addressof(qh))); R_TRY(ReadRegister(m_i2c_session, max17050::Qh, std::addressof(qh)));
R_TRY(WriteRegister(m_i2c_session, max17050::Qh0, qh)); R_TRY(WriteRegister(m_i2c_session, max17050::Qh0, qh));
R_TRY(this->LockVfSoc()); R_TRY(this->LockVoltageFuelGauge());
} }
/* Reset cycles. */ /* Reset cycles. */
@ -371,6 +371,14 @@ namespace ams::powctl::impl::board::nintendo::nx {
return WriteRegister(m_i2c_session, max17050::ShdnTimer, 0xE000); return WriteRegister(m_i2c_session, max17050::ShdnTimer, 0xE000);
} }
Result Max17050Driver::SetAlertByChargePercentage() {
return ReadWriteRegister(m_i2c_session, max17050::MiscCfg, 0x0003, 0x0000);
}
Result Max17050Driver::SetAlertByVoltageFuelGaugePercentage() {
return ReadWriteRegister(m_i2c_session, max17050::MiscCfg, 0x0003, 0x0003);
}
bool Max17050Driver::IsPowerOnReset() { bool Max17050Driver::IsPowerOnReset() {
/* Get the register. */ /* Get the register. */
u16 val; u16 val;
@ -380,11 +388,11 @@ namespace ams::powctl::impl::board::nintendo::nx {
return (val & 0x0002) != 0; return (val & 0x0002) != 0;
} }
Result Max17050Driver::LockVfSoc() { Result Max17050Driver::LockVoltageFuelGauge() {
return WriteRegister(m_i2c_session, max17050::SocVfAccess, 0x0000); return WriteRegister(m_i2c_session, max17050::SocVfAccess, 0x0000);
} }
Result Max17050Driver::UnlockVfSoc() { Result Max17050Driver::UnlockVoltageFuelGauge() {
return WriteRegister(m_i2c_session, max17050::SocVfAccess, 0x0080); return WriteRegister(m_i2c_session, max17050::SocVfAccess, 0x0080);
} }
@ -479,7 +487,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
return ResultSuccess(); return ResultSuccess();
} }
Result Max17050Driver::GetSocRep(double *out) { Result Max17050Driver::GetChargePercentage(double *out) {
/* Validate parameters. */ /* Validate parameters. */
AMS_ABORT_UNLESS(out != nullptr); AMS_ABORT_UNLESS(out != nullptr);
@ -492,7 +500,7 @@ namespace ams::powctl::impl::board::nintendo::nx {
return ResultSuccess(); return ResultSuccess();
} }
Result Max17050Driver::GetSocVf(double *out) { Result Max17050Driver::GetVoltageFuelGaugePercentage(double *out) {
/* Validate parameters. */ /* Validate parameters. */
AMS_ABORT_UNLESS(out != nullptr); AMS_ABORT_UNLESS(out != nullptr);
@ -535,15 +543,27 @@ namespace ams::powctl::impl::board::nintendo::nx {
return ResultSuccess(); return ResultSuccess();
} }
Result Max17050Driver::SetPercentageMinimumAlertThreshold(int percentage) { Result Max17050Driver::SetChargePercentageMinimumAlertThreshold(int percentage) {
R_TRY(this->SetAlertByChargePercentage());
return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0x00FF, static_cast<u8>(percentage)); return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0x00FF, static_cast<u8>(percentage));
} }
Result Max17050Driver::SetPercentageMaximumAlertThreshold(int percentage) { Result Max17050Driver::SetChargePercentageMaximumAlertThreshold(int percentage) {
R_TRY(this->SetAlertByChargePercentage());
return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0xFF00, static_cast<u16>(static_cast<u8>(percentage)) << 8); return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0xFF00, static_cast<u16>(static_cast<u8>(percentage)) << 8);
} }
Result Max17050Driver::SetPercentageFullThreshold(double percentage) { Result Max17050Driver::SetVoltageFuelGaugePercentageMinimumAlertThreshold(int percentage) {
R_TRY(this->SetAlertByVoltageFuelGaugePercentage());
return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0x00FF, static_cast<u8>(percentage));
}
Result Max17050Driver::SetVoltageFuelGaugePercentageMaximumAlertThreshold(int percentage) {
R_TRY(this->SetAlertByVoltageFuelGaugePercentage());
return ReadWriteRegister(m_i2c_session, max17050::SocAlrtThreshold, 0xFF00, static_cast<u16>(static_cast<u8>(percentage)) << 8);
}
Result Max17050Driver::SetFullChargeThreshold(double percentage) {
#if defined(ATMOSPHERE_ARCH_ARM64) #if defined(ATMOSPHERE_ARCH_ARM64)
const u16 val = vcvtd_n_s64_f64(percentage, BITSIZEOF(u8)); const u16 val = vcvtd_n_s64_f64(percentage, BITSIZEOF(u8));
#else #else

View file

@ -45,16 +45,19 @@ namespace ams::powctl::impl::board::nintendo::nx {
Result InitializeSession(const char *battery_vendor, u8 battery_version); Result InitializeSession(const char *battery_vendor, u8 battery_version);
Result SetMaximumShutdownTimerThreshold(); Result SetMaximumShutdownTimerThreshold();
Result SetAlertByChargePercentage();
Result SetAlertByVoltageFuelGaugePercentage();
bool IsPowerOnReset(); bool IsPowerOnReset();
Result LockVfSoc(); Result LockVoltageFuelGauge();
Result UnlockVfSoc(); Result UnlockVoltageFuelGauge();
Result LockModelTable(); Result LockModelTable();
Result UnlockModelTable(); Result UnlockModelTable();
bool IsModelTableLocked(); bool IsModelTableLocked();
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() : m_mutex(), m_init_count(0), m_i2c_session(), m_internal_state() { constexpr Max17050Driver() : m_mutex(), m_init_count(0), m_i2c_session(), m_internal_state() {
/* ... */ /* ... */
} }
@ -97,16 +100,19 @@ namespace ams::powctl::impl::board::nintendo::nx {
m_internal_state = src; m_internal_state = src;
} }
Result GetSocRep(double *out); Result GetChargePercentage(double *out);
Result GetSocVf(double *out); Result GetVoltageFuelGaugePercentage(double *out);
Result GetFullCapacity(double *out, double sense_resistor); Result GetFullCapacity(double *out, double sense_resistor);
Result GetRemainingCapacity(double *out, double sense_resistor); Result GetRemainingCapacity(double *out, double sense_resistor);
Result SetPercentageMinimumAlertThreshold(int percentage); Result SetChargePercentageMinimumAlertThreshold(int percentage);
Result SetPercentageMaximumAlertThreshold(int percentage); Result SetChargePercentageMaximumAlertThreshold(int percentage);
Result SetPercentageFullThreshold(double percentage); Result SetVoltageFuelGaugePercentageMinimumAlertThreshold(int percentage);
Result SetVoltageFuelGaugePercentageMaximumAlertThreshold(int percentage);
Result SetFullChargeThreshold(double percentage);
Result GetAverageCurrent(double *out, double sense_resistor); Result GetAverageCurrent(double *out, double sense_resistor);
Result GetCurrent(double *out, double sense_resistor); Result GetCurrent(double *out, double sense_resistor);

View file

@ -21,11 +21,11 @@ namespace ams::powctl::impl {
constexpr inline const TimeSpan PowerControlRetryTimeout = TimeSpan::FromSeconds(10); constexpr inline const TimeSpan PowerControlRetryTimeout = TimeSpan::FromSeconds(10);
constexpr inline const TimeSpan PowerControlRetryInterval = TimeSpan::FromMilliSeconds(20); constexpr inline const TimeSpan PowerControlRetryInterval = TimeSpan::FromMilliSeconds(20);
#define AMS_POWCTL_R_TRY_WITH_RETRY(__EXPR__) \ #define AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY(__EXPR__) \
({ \ ({ \
TimeSpan __powctl_retry_current_time = 0; \ TimeSpan __powctl_retry_current_time = 0; \
while (true) { \ while (true) { \
const Result __powctl_retry_result = (__EXPR__); \ const Result __powctl_retry_result = ( __EXPR__ ); \
if (R_SUCCEEDED(__powctl_retry_result)) { \ if (R_SUCCEEDED(__powctl_retry_result)) { \
break; \ break; \
} \ } \
@ -37,5 +37,6 @@ namespace ams::powctl::impl {
} \ } \
}) })
#define AMS_POWCTL_DRIVER_LOCKED_R_TRY_WITH_RETRY(__EXPR__) AMS_POWCTL_DRIVER_R_TRY_WITH_RETRY( ({ std::scoped_lock lk(this->GetMutex()); ( __EXPR__ ); }) )
} }

View file

@ -33,12 +33,17 @@ namespace ams::powctl::impl {
AMS_DDSF_CASTABLE_TRAITS(ams::powctl::impl::IPowerControlDriver, ::ams::ddsf::IDriver); AMS_DDSF_CASTABLE_TRAITS(ams::powctl::impl::IPowerControlDriver, ::ams::ddsf::IDriver);
private: private:
bool m_event_handler_enabled; bool m_event_handler_enabled;
os::SdkMutex m_mutex;
protected: protected:
constexpr bool IsEventHandlerEnabled() const { constexpr bool IsEventHandlerEnabled() const {
return m_event_handler_enabled; return m_event_handler_enabled;
} }
ALWAYS_INLINE os::SdkMutex &GetMutex() {
return m_mutex;
}
public: public:
IPowerControlDriver(bool ev) : IDriver(), m_event_handler_enabled(ev) { /* ... */ } IPowerControlDriver(bool ev) : IDriver(), m_event_handler_enabled(ev), m_mutex() { /* ... */ }
virtual ~IPowerControlDriver() { /* ... */ } virtual ~IPowerControlDriver() { /* ... */ }
virtual void InitializeDriver() = 0; virtual void InitializeDriver() = 0;
@ -51,16 +56,19 @@ namespace ams::powctl::impl {
virtual Result GetDeviceErrorStatus(u32 *out, IDevice *device) = 0; virtual Result GetDeviceErrorStatus(u32 *out, IDevice *device) = 0;
virtual Result SetDeviceErrorStatus(IDevice *device, u32 status) = 0; virtual Result SetDeviceErrorStatus(IDevice *device, u32 status) = 0;
virtual Result GetBatterySocRep(float *out_percent, IDevice *device) = 0; virtual Result GetBatteryChargePercentage(float *out_percent, IDevice *device) = 0;
virtual Result GetBatterySocVf(float *out_percent, IDevice *device) = 0; virtual Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, IDevice *device) = 0;
virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) = 0; virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) = 0;
virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) = 0; virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) = 0;
virtual Result SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) = 0; virtual Result SetBatteryChargePercentageMinimumAlertThreshold(IDevice *device, float percentage) = 0;
virtual Result SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) = 0; virtual Result SetBatteryChargePercentageMaximumAlertThreshold(IDevice *device, float percentage) = 0;
virtual Result SetBatteryPercentageFullThreshold(IDevice *device, float percentage) = 0; virtual Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(IDevice *device, float percentage) = 0;
virtual Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(IDevice *device, float percentage) = 0;
virtual Result SetBatteryFullChargeThreshold(IDevice *device, float percentage) = 0;
virtual Result GetChargerChargeCurrentState(ChargeCurrentState *out, IDevice *device) = 0; virtual Result GetChargerChargeCurrentState(ChargeCurrentState *out, IDevice *device) = 0;
virtual Result SetChargerChargeCurrentState(IDevice *device, ChargeCurrentState state) = 0; virtual Result SetChargerChargeCurrentState(IDevice *device, ChargeCurrentState state) = 0;

View file

@ -30,7 +30,7 @@ namespace ams::powctl {
} }
Result GetBatterySocRep(float *out_percent, Session &session) { Result GetBatteryChargePercentage(float *out_percent, Session &session) {
/* Get the session impl. */ /* Get the session impl. */
auto &impl = GetOpenSessionImpl(session); auto &impl = GetOpenSessionImpl(session);
@ -41,10 +41,10 @@ namespace ams::powctl {
auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>(); auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>();
/* Call into the driver. */ /* Call into the driver. */
return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().GetBatterySocRep(out_percent, std::addressof(device)); return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().GetBatteryChargePercentage(out_percent, std::addressof(device));
} }
Result GetBatterySocVf(float *out_percent, Session &session) { Result GetBatteryVoltageFuelGaugePercentage(float *out_percent, Session &session) {
/* Get the session impl. */ /* Get the session impl. */
auto &impl = GetOpenSessionImpl(session); auto &impl = GetOpenSessionImpl(session);
@ -55,7 +55,7 @@ namespace ams::powctl {
auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>(); auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>();
/* Call into the driver. */ /* Call into the driver. */
return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().GetBatterySocVf(out_percent, std::addressof(device)); return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().GetBatteryVoltageFuelGaugePercentage(out_percent, std::addressof(device));
} }
Result GetBatteryFullCapacity(int *out_mah, Session &session) { Result GetBatteryFullCapacity(int *out_mah, Session &session) {
@ -86,7 +86,7 @@ namespace ams::powctl {
return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().GetBatteryRemainingCapacity(out_mah, std::addressof(device)); return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().GetBatteryRemainingCapacity(out_mah, std::addressof(device));
} }
Result SetBatteryPercentageMinimumAlertThreshold(Session &session, float percentage) { Result SetBatteryChargePercentageMinimumAlertThreshold(Session &session, float percentage) {
/* Get the session impl. */ /* Get the session impl. */
auto &impl = GetOpenSessionImpl(session); auto &impl = GetOpenSessionImpl(session);
@ -97,10 +97,10 @@ namespace ams::powctl {
auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>(); auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>();
/* Call into the driver. */ /* Call into the driver. */
return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().SetBatteryPercentageMinimumAlertThreshold(std::addressof(device), percentage); return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().SetBatteryChargePercentageMinimumAlertThreshold(std::addressof(device), percentage);
} }
Result SetBatteryPercentageMaximumAlertThreshold(Session &session, float percentage) { Result SetBatteryChargePercentageMaximumAlertThreshold(Session &session, float percentage) {
/* Get the session impl. */ /* Get the session impl. */
auto &impl = GetOpenSessionImpl(session); auto &impl = GetOpenSessionImpl(session);
@ -111,10 +111,10 @@ namespace ams::powctl {
auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>(); auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>();
/* Call into the driver. */ /* Call into the driver. */
return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().SetBatteryPercentageMaximumAlertThreshold(std::addressof(device), percentage); return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().SetBatteryChargePercentageMaximumAlertThreshold(std::addressof(device), percentage);
} }
Result SetBatteryPercentageFullThreshold(Session &session, float percentage) { Result SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(Session &session, float percentage) {
/* Get the session impl. */ /* Get the session impl. */
auto &impl = GetOpenSessionImpl(session); auto &impl = GetOpenSessionImpl(session);
@ -125,7 +125,35 @@ namespace ams::powctl {
auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>(); auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>();
/* Call into the driver. */ /* Call into the driver. */
return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().SetBatteryPercentageFullThreshold(std::addressof(device), percentage); return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().SetBatteryVoltageFuelGaugePercentageMinimumAlertThreshold(std::addressof(device), percentage);
}
Result SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(Session &session, float percentage) {
/* Get the session impl. */
auto &impl = GetOpenSessionImpl(session);
/* Check the access mode. */
R_UNLESS(impl.CheckAccess(ddsf::AccessMode_Write), ddsf::ResultPermissionDenied());
/* Get the device. */
auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>();
/* Call into the driver. */
return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().SetBatteryVoltageFuelGaugePercentageMaximumAlertThreshold(std::addressof(device), percentage);
}
Result SetBatteryFullChargeThreshold(Session &session, float percentage) {
/* Get the session impl. */
auto &impl = GetOpenSessionImpl(session);
/* Check the access mode. */
R_UNLESS(impl.CheckAccess(ddsf::AccessMode_Write), ddsf::ResultPermissionDenied());
/* Get the device. */
auto &device = impl.GetDevice().SafeCastTo<impl::IDevice>();
/* Call into the driver. */
return device.GetDriver().SafeCastTo<impl::IPowerControlDriver>().SetBatteryFullChargeThreshold(std::addressof(device), percentage);
} }
Result GetBatteryAverageCurrent(int *out_ma, Session &session) { Result GetBatteryAverageCurrent(int *out_ma, Session &session) {

View file

@ -19,55 +19,62 @@
namespace ams::boot { namespace ams::boot {
class BatteryDriver { class BatteryDriver {
NON_COPYABLE(BatteryDriver);
NON_MOVEABLE(BatteryDriver);
private: private:
powctl::Session m_battery_session; static constinit inline powctl::Session s_battery_session{powctl::Session::ConstantInitializeTag{}};
static constinit inline int s_reference_count{0};
public: public:
BatteryDriver() : m_battery_session() { BatteryDriver() {
R_ABORT_UNLESS(powctl::OpenSession(std::addressof(m_battery_session), powctl::DeviceCode_Max17050, ddsf::AccessMode_ReadWrite)); if ((s_reference_count++) == 0) {
R_ABORT_UNLESS(powctl::OpenSession(std::addressof(s_battery_session), powctl::DeviceCode_Max17050, ddsf::AccessMode_ReadWrite));
}
} }
~BatteryDriver() { ~BatteryDriver() {
powctl::CloseSession(m_battery_session); if ((--s_reference_count) == 0) {
powctl::CloseSession(s_battery_session);
}
} }
public: public:
Result IsBatteryRemoved(bool *out) { Result IsBatteryRemoved(bool *out) {
bool present; bool present;
R_TRY(powctl::IsBatteryPresent(std::addressof(present), m_battery_session)); R_TRY(powctl::IsBatteryPresent(std::addressof(present), s_battery_session));
*out = !present; *out = !present;
return ResultSuccess(); return ResultSuccess();
} }
Result GetSocRep(float *out) { Result GetChargePercentage(float *out) {
return powctl::GetBatterySocRep(out, m_battery_session); return powctl::GetBatteryChargePercentage(out, s_battery_session);
} }
Result GetAverageVCell(int *out) { Result GetAverageVCell(int *out) {
return powctl::GetBatteryAverageVCell(out, m_battery_session); return powctl::GetBatteryAverageVCell(out, s_battery_session);
} }
Result GetOpenCircuitVoltage(int *out) { Result GetOpenCircuitVoltage(int *out) {
return powctl::GetBatteryOpenCircuitVoltage(out, m_battery_session); return powctl::GetBatteryOpenCircuitVoltage(out, s_battery_session);
} }
Result GetAverageCurrent(int *out) { Result GetAverageCurrent(int *out) {
return powctl::GetBatteryAverageCurrent(out, m_battery_session); return powctl::GetBatteryAverageCurrent(out, s_battery_session);
} }
Result GetCurrent(int *out) { Result GetCurrent(int *out) {
return powctl::GetBatteryCurrent(out, m_battery_session); return powctl::GetBatteryCurrent(out, s_battery_session);
} }
Result GetTemperature(float *out) { Result GetTemperature(float *out) {
return powctl::GetBatteryTemperature(out, m_battery_session); return powctl::GetBatteryTemperature(out, s_battery_session);
} }
Result IsI2cShutdownEnabled(bool *out) { Result IsI2cShutdownEnabled(bool *out) {
return powctl::IsBatteryI2cShutdownEnabled(out, m_battery_session); return powctl::IsBatteryI2cShutdownEnabled(out, s_battery_session);
} }
Result SetI2cShutdownEnabled(bool en) { Result SetI2cShutdownEnabled(bool en) {
return powctl::SetBatteryI2cShutdownEnabled(m_battery_session, en); return powctl::SetBatteryI2cShutdownEnabled(s_battery_session, en);
} }
}; };

View file

@ -357,7 +357,7 @@ namespace ams::boot {
if (show_charging_display) { if (show_charging_display) {
/* Get the raw battery charge. */ /* Get the raw battery charge. */
float raw_battery_charge; float raw_battery_charge;
if (R_FAILED(m_battery_driver.GetSocRep(std::addressof(raw_battery_charge)))) { if (R_FAILED(m_battery_driver.GetChargePercentage(std::addressof(raw_battery_charge)))) {
return CheckBatteryResult::Shutdown; return CheckBatteryResult::Shutdown;
} }
@ -372,7 +372,7 @@ namespace ams::boot {
while (true) { while (true) {
/* Get the raw battery charge. */ /* Get the raw battery charge. */
float raw_battery_charge; float raw_battery_charge;
if (R_FAILED(m_battery_driver.GetSocRep(std::addressof(raw_battery_charge)))) { if (R_FAILED(m_battery_driver.GetChargePercentage(std::addressof(raw_battery_charge)))) {
return CheckBatteryResult::Shutdown; return CheckBatteryResult::Shutdown;
} }

View file

@ -100,7 +100,7 @@ namespace ams::boot {
bool use_desired_shutdown = true; bool use_desired_shutdown = true;
if (spl::GetHardwareType() == spl::HardwareType::Hoag) { if (spl::GetHardwareType() == spl::HardwareType::Hoag) {
float battery_charge_raw; float battery_charge_raw;
if (R_FAILED(battery_driver.GetSocRep(std::addressof(battery_charge_raw))) || battery_charge_raw >= 80.0) { if (R_FAILED(battery_driver.GetChargePercentage(std::addressof(battery_charge_raw))) || battery_charge_raw >= 80.0) {
use_desired_shutdown = false; use_desired_shutdown = false;
} }
} }