powctl: add ChargerDriver body (needs impl)

This commit is contained in:
Michael Scire 2020-11-09 17:09:25 -08:00 committed by SciresM
parent d9350d24a9
commit 5bd02f128d
9 changed files with 983 additions and 4 deletions

View file

@ -33,6 +33,7 @@ namespace ams::powctl {
};
enum ChargeCurrentState {
ChargeCurrentState_Unknown = 0x0,
ChargeCurrentState_NotCharging = 0x1,
ChargeCurrentState_ChargingForce20Percent = 0x2,
ChargeCurrentState_Charging = 0x3,

View file

@ -0,0 +1,209 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "powctl_battery_driver.hpp"
namespace ams::powctl::impl::board::nintendo_nx {
/* Generic API. */
void BatteryDriver::InitializeDriver() {
/* TODO */
AMS_ABORT();
}
void BatteryDriver::FinalizeDriver() {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetDeviceSystemEvent(os::SystemEventType **out, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Check that we support event handlers. */
R_UNLESS(this->IsEventHandlerEnabled(), powctl::ResultNotAvailable());
*out = device->SafeCastTo<BatteryDevice>().GetSystemEvent();
return ResultSuccess();
}
Result BatteryDriver::SetDeviceInterruptEnabled(IDevice *device, bool enable) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Set the interrupt enable. */
device->SafeCastTo<BatteryDevice>().SetInterruptEnabled(enable);
return ResultSuccess();
}
Result BatteryDriver::GetDeviceErrorStatus(u32 *out, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetDeviceErrorStatus(IDevice *device, u32 status) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatterySocRep(float *out_percent, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatterySocVf(float *out_percent, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryFullCapacity(int *out_mah, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryRemainingCapacity(int *out_mah, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryPercentageFullThreshold(IDevice *device, float percentage) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryAverageCurrent(int *out_ma, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryCurrent(int *out_ma, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryInternalState(void *dst, size_t *out_size, IDevice *device, size_t dst_size) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryInternalState(IDevice *device, const void *src, size_t src_size) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryNeedToRestoreParameters(bool *out, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryNeedToRestoreParameters(IDevice *device, bool en) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::IsBatteryI2cShutdownEnabled(bool *out, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryI2cShutdownEnabled(IDevice *device, bool en) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::IsBatteryPresent(bool *out, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryCycles(int *out, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryCycles(IDevice *device, int cycles) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryAge(float *out_percent, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryTemperature(float *out_c, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryMaximumTemperature(float *out_c, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryTemperatureMinimumAlertThreshold(IDevice *device, float c) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryTemperatureMaximumAlertThreshold(IDevice *device, float c) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryVCell(int *out_mv, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryAverageVCell(int *out_mv, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryAverageVCellTime(TimeSpan *out, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryVoltageMinimumAlertThreshold(IDevice *device, int mv) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::GetBatteryOpenCircuitVoltage(int *out_mv, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result BatteryDriver::SetBatteryVoltageMaximumAlertThreshold(IDevice *device, int mv) {
/* TODO */
AMS_ABORT();
}
}

View file

@ -0,0 +1,144 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
#include "../../powctl_i_power_control_driver.hpp"
#include "powctl_interrupt_event_handler.hpp"
namespace ams::powctl::impl::board::nintendo_nx {
class BatteryDevice : public powctl::impl::IDevice {
NON_COPYABLE(BatteryDevice);
NON_MOVEABLE(BatteryDevice);
AMS_DDSF_CASTABLE_TRAITS(ams::powctl::impl::board::nintendo_nx::BatteryDevice, ::ams::powctl::impl::IDevice);
private:
bool use_event_handler;
std::optional<BatteryInterruptEventHandler> event_handler;
os::SystemEventType system_event;
public:
BatteryDevice(bool ev);
os::SystemEventType *GetSystemEvent() { return std::addressof(this->system_event); }
void SetInterruptEnabled(bool en) {
if (this->use_event_handler) {
this->event_handler->SetInterruptEnabled(en);
}
}
};
class BatteryDriver : public IPowerControlDriver {
NON_COPYABLE(BatteryDriver);
NON_MOVEABLE(BatteryDriver);
AMS_DDSF_CASTABLE_TRAITS(ams::powctl::impl::board::nintendo_nx::BatteryDriver, ::ams::powctl::impl::IPowerControlDriver);
public:
BatteryDriver(bool ev) : IPowerControlDriver(ev) { /* ... */ }
/* Generic API. */
virtual void InitializeDriver() override;
virtual void FinalizeDriver() override;
virtual Result GetDeviceSystemEvent(os::SystemEventType **out, IDevice *device) override;
virtual Result SetDeviceInterruptEnabled(IDevice *device, bool enable) override;
virtual Result GetDeviceErrorStatus(u32 *out, IDevice *device) override;
virtual Result SetDeviceErrorStatus(IDevice *device, u32 status) override;
/* Battery API. */
virtual Result GetBatterySocRep(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 GetBatteryRemainingCapacity(int *out_mah, IDevice *device) override;
virtual Result SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) override;
virtual Result SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) override;
virtual Result SetBatteryPercentageFullThreshold(IDevice *device, float percentage) override;
virtual Result GetBatteryAverageCurrent(int *out_ma, IDevice *device) override;
virtual Result GetBatteryCurrent(int *out_ma, IDevice *device) override;
virtual Result GetBatteryInternalState(void *dst, size_t *out_size, IDevice *device, size_t dst_size) override;
virtual Result SetBatteryInternalState(IDevice *device, const void *src, size_t src_size) override;
virtual Result GetBatteryNeedToRestoreParameters(bool *out, IDevice *device) override;
virtual Result SetBatteryNeedToRestoreParameters(IDevice *device, bool en) override;
virtual Result IsBatteryI2cShutdownEnabled(bool *out, IDevice *device) override;
virtual Result SetBatteryI2cShutdownEnabled(IDevice *device, bool en) override;
virtual Result IsBatteryPresent(bool *out, IDevice *device) override;
virtual Result GetBatteryCycles(int *out, IDevice *device) override;
virtual Result SetBatteryCycles(IDevice *device, int cycles) override;
virtual Result GetBatteryAge(float *out_percent, IDevice *device) override;
virtual Result GetBatteryTemperature(float *out_c, IDevice *device) override;
virtual Result GetBatteryMaximumTemperature(float *out_c, IDevice *device) override;
virtual Result SetBatteryTemperatureMinimumAlertThreshold(IDevice *device, float c) override;
virtual Result SetBatteryTemperatureMaximumAlertThreshold(IDevice *device, float c) override;
virtual Result GetBatteryVCell(int *out_mv, IDevice *device) override;
virtual Result GetBatteryAverageVCell(int *out_mv, IDevice *device) override;
virtual Result GetBatteryAverageVCellTime(TimeSpan *out, IDevice *device) override;
virtual Result SetBatteryVoltageMinimumAlertThreshold(IDevice *device, int mv) override;
virtual Result GetBatteryOpenCircuitVoltage(int *out_mv, IDevice *device) override;
virtual Result SetBatteryVoltageMaximumAlertThreshold(IDevice *device, int mv) override;
/* Unsupported Charger API. */
virtual Result GetChargerChargeCurrentState(ChargeCurrentState *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerChargeCurrentState(IDevice *device, ChargeCurrentState state) override { return powctl::ResultNotSupported(); }
virtual Result GetChargerFastChargeCurrentLimit(int *out_ma, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerFastChargeCurrentLimit(IDevice *device, int ma) override { return powctl::ResultNotSupported(); }
virtual Result GetChargerChargeVoltageLimit(int *out_mv, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerChargeVoltageLimit(IDevice *device, int mv) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerChargerConfiguration(IDevice *device, ChargerConfiguration cfg) override { return powctl::ResultNotSupported(); }
virtual Result IsChargerHiZEnabled(bool *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerHiZEnabled(IDevice *device, bool en) override { return powctl::ResultNotSupported(); }
virtual Result GetChargerInputCurrentLimit(int *out_ma, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerInputCurrentLimit(IDevice *device, int ma) override { return powctl::ResultNotSupported(); }
virtual Result GetChargerInputVoltageLimit(int *out_mv, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerInputVoltageLimit(IDevice *device, int mv) override { return powctl::ResultNotSupported(); }
virtual Result GetChargerChargerStatus(ChargerStatus *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result IsChargerWatchdogTimerEnabled(bool *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerWatchdogTimerEnabled(IDevice *device, bool en) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerWatchdogTimerTimeout(IDevice *device, TimeSpan timeout) override { return powctl::ResultNotSupported(); }
virtual Result ResetChargerWatchdogTimer(IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetChargerBatteryCompensation(int *out_mo, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerBatteryCompensation(IDevice *device, int mo) override { return powctl::ResultNotSupported(); }
virtual Result GetChargerVoltageClamp(int *out_mv, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetChargerVoltageClamp(IDevice *device, int mv) override { return powctl::ResultNotSupported(); }
};
}

View file

@ -14,13 +14,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "../../powctl_device_management.hpp"
#include "powctl_board_impl.hpp"
#include "powctl_battery_driver.hpp"
#include "powctl_charger_driver.hpp"
namespace ams::powctl::impl::board::nintendo_nx {
namespace {
constinit std::optional<ChargerDriver> g_charger_driver;
constinit std::optional<BatteryDriver> g_battery_driver;
void InitializeChargerDriver(bool use_event_handlers) {
/* Create the charger driver. */
g_charger_driver.emplace(use_event_handlers);
/* Register the driver. */
powctl::impl::RegisterDriver(std::addressof(*g_charger_driver));
}
void InitializeBatteryDriver(bool use_event_handlers) {
/* Create the battery driver. */
g_battery_driver.emplace(use_event_handlers);
/* Register the driver. */
powctl::impl::RegisterDriver(std::addressof(*g_battery_driver));
}
}
void Initialize(bool use_event_handlers) {
/* TODO */
AMS_ABORT();
InitializeChargerDriver(use_event_handlers);
InitializeBatteryDriver(use_event_handlers);
}
void Finalize() {

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::powctl::impl::board::nintendo_nx {
namespace bq24193 {
enum ChargerConfiguration {
ChargerConfiguration_ChargeDisable = 0,
ChargerConfiguration_ChargeBattery = 1,
ChargerConfiguration_Otg = 2,
};
enum ChargerStatus {
ChargerStatus_NotCharging = 0,
ChargerStatus_PreCharge = 1,
ChargerStatus_FastCharging = 2,
ChargerStatus_ChargeTerminationDone = 3,
};
}
class Bq24193Driver {
private:
os::SdkMutex mutex;
int init_count;
i2c::I2cSession i2c_session;
private:
Result InitializeSession();
public:
Bq24193Driver() : mutex(), init_count(0), i2c_session() {
/* ... */
}
void Initialize() {
std::scoped_lock lk(this->mutex);
R_ABORT_UNLESS(this->InitializeSession());
}
Result GetForce20PercentChargeCurrent(bool *out);
Result SetForce20PercentChargeCurrent(bool en);
Result GetFastChargeCurrentLimit(int *out_ma);
Result SetFastChargeCurrentLimit(int ma);
Result GetChargeVoltageLimit(int *out_mv);
Result SetChargeVoltageLimit(int mv);
Result SetChargerConfiguration(bq24193::ChargerConfiguration cfg);
Result IsHiZEnabled(bool *out);
Result SetHiZEnabled(bool en);
Result GetInputCurrentLimit(int *out_ma);
Result SetInputCurrentLimit(int ma);
Result GetInputVoltageLimit(int *out_mv);
Result SetInputVoltageLimit(int mv);
Result GetChargerStatus(bq24193::ChargerStatus *out);
Result ResetWatchdogTimer();
Result SetWatchdogTimerSetting(int seconds);
Result GetBatteryCompensation(int *out_mo);
Result SetBatteryCompensation(int mo);
Result GetVoltageClamp(int *out_mv);
Result SetVoltageClamp(int mv);
};
}

View file

@ -0,0 +1,351 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "../../powctl_device_management.hpp"
#include "powctl_retry_helper.hpp"
#include "powctl_charger_driver.hpp"
#include "powctl_bq24193_driver.hpp"
namespace ams::powctl::impl::board::nintendo_nx {
namespace {
constinit std::optional<ChargerDevice> g_charger_device;
Bq24193Driver &GetBq24193Driver() {
static Bq24193Driver s_bq24193_driver;
return s_bq24193_driver;
}
}
/* Generic API. */
void ChargerDriver::InitializeDriver() {
/* Initialize Bq24193Driver */
GetBq24193Driver().Initialize();
/* Initialize gpio library. */
gpio::Initialize();
/* Create charger device. */
g_charger_device.emplace(this->IsEventHandlerEnabled());
/* Open the device's gpio session. */
R_ABORT_UNLESS(gpio::OpenSession(g_charger_device->GetPadSession(), gpio::DeviceCode_BattChgEnableN));
/* Configure the gpio session as output. */
gpio::SetDirection(g_charger_device->GetPadSession(), gpio::Direction_Output);
/* Register our device. */
this->RegisterDevice(std::addressof(*g_charger_device));
/* Register the charger device's code. */
R_ABORT_UNLESS(powctl::impl::RegisterDeviceCode(powctl::DeviceCode_Bq24193, std::addressof(*g_charger_device)));
}
void ChargerDriver::FinalizeDriver() {
/* Unregister the charger device code. */
powctl::impl::UnregisterDeviceCode(powctl::DeviceCode_Bq24193);
/* Unregister our device. */
this->UnregisterDevice(std::addressof(*g_charger_device));
/* Close the device's gpio session. */
gpio::CloseSession(g_charger_device->GetPadSession());
/* Destroy the charger device. */
g_charger_device = std::nullopt;
}
Result ChargerDriver::GetDeviceSystemEvent(os::SystemEventType **out, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Check that we support event handlers. */
R_UNLESS(this->IsEventHandlerEnabled(), powctl::ResultNotAvailable());
*out = device->SafeCastTo<ChargerDevice>().GetSystemEvent();
return ResultSuccess();
}
Result ChargerDriver::SetDeviceInterruptEnabled(IDevice *device, bool enable) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Set the interrupt enable. */
device->SafeCastTo<ChargerDevice>().SetInterruptEnabled(enable);
return ResultSuccess();
}
Result ChargerDriver::GetDeviceErrorStatus(u32 *out, IDevice *device) {
/* TODO */
AMS_ABORT();
}
Result ChargerDriver::SetDeviceErrorStatus(IDevice *device, u32 status) {
/* TODO */
AMS_ABORT();
}
/* Charger API. */
Result ChargerDriver::GetChargerChargeCurrentState(ChargeCurrentState *out, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
/* Check if we're not charging. */
if (gpio::GetValue(device->SafeCastTo<ChargerDevice>().GetPadSession()) == gpio::GpioValue_High) {
*out = ChargeCurrentState_NotCharging;
} else {
/* Get force 20 percent charge state. */
bool force_20_percent;
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetForce20PercentChargeCurrent(std::addressof(force_20_percent)));
/* Set output appropriately. */
if (force_20_percent) {
*out = ChargeCurrentState_ChargingForce20Percent;
} else {
*out = ChargeCurrentState_Charging;
}
}
return ResultSuccess();
}
Result ChargerDriver::SetChargerChargeCurrentState(IDevice *device, ChargeCurrentState state) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
switch (state) {
case ChargeCurrentState_NotCharging:
gpio::SetValue(device->SafeCastTo<ChargerDevice>().GetPadSession(), gpio::GpioValue_High);
break;
case ChargeCurrentState_ChargingForce20Percent:
case ChargeCurrentState_Charging:
gpio::SetValue(device->SafeCastTo<ChargerDevice>().GetPadSession(), gpio::GpioValue_Low);
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetForce20PercentChargeCurrent(state == ChargeCurrentState_ChargingForce20Percent));
break;
case ChargeCurrentState_Unknown:
return powctl::ResultInvalidArgument();
}
return ResultSuccess();
}
Result ChargerDriver::GetChargerFastChargeCurrentLimit(int *out_ma, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetFastChargeCurrentLimit(out_ma));
return ResultSuccess();
}
Result ChargerDriver::SetChargerFastChargeCurrentLimit(IDevice *device, int ma) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetFastChargeCurrentLimit(ma));
return ResultSuccess();
}
Result ChargerDriver::GetChargerChargeVoltageLimit(int *out_mv, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargeVoltageLimit(out_mv));
return ResultSuccess();
}
Result ChargerDriver::SetChargerChargeVoltageLimit(IDevice *device, int mv) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargeVoltageLimit(mv));
return ResultSuccess();
}
Result ChargerDriver::SetChargerChargerConfiguration(IDevice *device, ChargerConfiguration cfg) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
bq24193::ChargerConfiguration bq_cfg;
switch (cfg) {
case ChargerConfiguration_ChargeDisable: bq_cfg = bq24193::ChargerConfiguration_ChargeDisable; break;
case ChargerConfiguration_ChargeBattery: bq_cfg = bq24193::ChargerConfiguration_ChargeBattery; break;
case ChargerConfiguration_Otg: bq_cfg = bq24193::ChargerConfiguration_Otg; break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetChargerConfiguration(bq_cfg));
return ResultSuccess();
}
Result ChargerDriver::IsChargerHiZEnabled(bool *out, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().IsHiZEnabled(out));
return ResultSuccess();
}
Result ChargerDriver::SetChargerHiZEnabled(IDevice *device, bool en) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetHiZEnabled(en));
return ResultSuccess();
}
Result ChargerDriver::GetChargerInputCurrentLimit(int *out_ma, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out_ma != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetInputCurrentLimit(out_ma));
return ResultSuccess();
}
Result ChargerDriver::SetChargerInputCurrentLimit(IDevice *device, int ma) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputCurrentLimit(ma));
return ResultSuccess();
}
Result ChargerDriver::GetChargerInputVoltageLimit(int *out_mv, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetInputVoltageLimit(out_mv));
return ResultSuccess();
}
Result ChargerDriver::SetChargerInputVoltageLimit(IDevice *device, int mv) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetInputVoltageLimit(mv));
return ResultSuccess();
}
Result ChargerDriver::GetChargerChargerStatus(ChargerStatus *out, IDevice *device) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
bq24193::ChargerStatus bq_status;
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetChargerStatus(std::addressof(bq_status)));
switch (bq_status) {
case bq24193::ChargerStatus_NotCharging:
*out = ChargerStatus_NotCharging;
break;
case bq24193::ChargerStatus_PreCharge:
case bq24193::ChargerStatus_FastCharging:
*out = ChargerStatus_Charging;
break;
case bq24193::ChargerStatus_ChargeTerminationDone:
*out = ChargerStatus_ChargeTerminationDone;
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
return ResultSuccess();
}
Result ChargerDriver::IsChargerWatchdogTimerEnabled(bool *out, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
*out = device->SafeCastTo<ChargerDevice>().IsWatchdogTimerEnabled();
return ResultSuccess();
}
Result ChargerDriver::SetChargerWatchdogTimerEnabled(IDevice *device, bool en) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
auto &charger_device = device->SafeCastTo<ChargerDevice>();
if (en) {
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(charger_device.GetWatchdogTimerTimeout().GetSeconds()));
} else {
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetWatchdogTimerSetting(0));
}
charger_device.SetWatchdogTimerEnabled(en);
return ResultSuccess();
}
Result ChargerDriver::SetChargerWatchdogTimerTimeout(IDevice *device, TimeSpan timeout) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
device->SafeCastTo<ChargerDevice>().SetWatchdogTimerTimeout(timeout);
return ResultSuccess();
}
Result ChargerDriver::ResetChargerWatchdogTimer(IDevice *device) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().ResetWatchdogTimer());
return ResultSuccess();
}
Result ChargerDriver::GetChargerBatteryCompensation(int *out_mo, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out_mo != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetBatteryCompensation(out_mo));
return ResultSuccess();
}
Result ChargerDriver::SetChargerBatteryCompensation(IDevice *device, int mo) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetBatteryCompensation(mo));
return ResultSuccess();
}
Result ChargerDriver::GetChargerVoltageClamp(int *out_mv, IDevice *device) {
/* Validate arguments. */
R_UNLESS(out_mv != nullptr, powctl::ResultInvalidArgument());
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().GetVoltageClamp(out_mv));
return ResultSuccess();
}
Result ChargerDriver::SetChargerVoltageClamp(IDevice *device, int mv) {
/* Validate arguments. */
R_UNLESS(device != nullptr, powctl::ResultInvalidArgument());
AMS_POWCTL_R_TRY_WITH_RETRY(GetBq24193Driver().SetVoltageClamp(mv));
return ResultSuccess();
}
}

View file

@ -0,0 +1,155 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
#include "../../powctl_i_power_control_driver.hpp"
#include "powctl_interrupt_event_handler.hpp"
namespace ams::powctl::impl::board::nintendo_nx {
class ChargerDevice : public powctl::impl::IDevice {
NON_COPYABLE(ChargerDevice);
NON_MOVEABLE(ChargerDevice);
AMS_DDSF_CASTABLE_TRAITS(ams::powctl::impl::board::nintendo_nx::ChargerDevice, ::ams::powctl::impl::IDevice);
private:
gpio::GpioPadSession gpio_pad_session;
bool watchdog_timer_enabled;
TimeSpan watchdog_timer_timeout;
bool use_event_handler;
std::optional<ChargerInterruptEventHandler> event_handler;
os::SystemEventType system_event;
public:
ChargerDevice(bool ev);
bool IsWatchdogTimerEnabled() const { return this->watchdog_timer_enabled; }
void SetWatchdogTimerEnabled(bool en) { this->watchdog_timer_enabled = en; }
TimeSpan GetWatchdogTimerTimeout() const { return this->watchdog_timer_timeout; }
void SetWatchdogTimerTimeout(TimeSpan ts) { this->watchdog_timer_timeout = ts; }
gpio::GpioPadSession *GetPadSession() { return std::addressof(this->gpio_pad_session); }
os::SystemEventType *GetSystemEvent() { return std::addressof(this->system_event); }
void SetInterruptEnabled(bool en) {
if (this->use_event_handler) {
this->event_handler->SetInterruptEnabled(en);
}
}
};
class ChargerDriver : public IPowerControlDriver {
NON_COPYABLE(ChargerDriver);
NON_MOVEABLE(ChargerDriver);
AMS_DDSF_CASTABLE_TRAITS(ams::powctl::impl::board::nintendo_nx::ChargerDriver, ::ams::powctl::impl::IPowerControlDriver);
public:
ChargerDriver(bool ev) : IPowerControlDriver(ev) { /* ... */ }
/* Generic API. */
virtual void InitializeDriver() override;
virtual void FinalizeDriver() override;
virtual Result GetDeviceSystemEvent(os::SystemEventType **out, IDevice *device) override;
virtual Result SetDeviceInterruptEnabled(IDevice *device, bool enable) override;
virtual Result GetDeviceErrorStatus(u32 *out, IDevice *device) override;
virtual Result SetDeviceErrorStatus(IDevice *device, u32 status) override;
/* Charger API. */
virtual Result GetChargerChargeCurrentState(ChargeCurrentState *out, IDevice *device) override;
virtual Result SetChargerChargeCurrentState(IDevice *device, ChargeCurrentState state) override;
virtual Result GetChargerFastChargeCurrentLimit(int *out_ma, IDevice *device) override;
virtual Result SetChargerFastChargeCurrentLimit(IDevice *device, int ma) override;
virtual Result GetChargerChargeVoltageLimit(int *out_mv, IDevice *device) override;
virtual Result SetChargerChargeVoltageLimit(IDevice *device, int mv) override;
virtual Result SetChargerChargerConfiguration(IDevice *device, ChargerConfiguration cfg) override;
virtual Result IsChargerHiZEnabled(bool *out, IDevice *device) override;
virtual Result SetChargerHiZEnabled(IDevice *device, bool en) override;
virtual Result GetChargerInputCurrentLimit(int *out_ma, IDevice *device) override;
virtual Result SetChargerInputCurrentLimit(IDevice *device, int ma) override;
virtual Result GetChargerInputVoltageLimit(int *out_mv, IDevice *device) override;
virtual Result SetChargerInputVoltageLimit(IDevice *device, int mv) override;
virtual Result GetChargerChargerStatus(ChargerStatus *out, IDevice *device) override;
virtual Result IsChargerWatchdogTimerEnabled(bool *out, IDevice *device) override;
virtual Result SetChargerWatchdogTimerEnabled(IDevice *device, bool en) override;
virtual Result SetChargerWatchdogTimerTimeout(IDevice *device, TimeSpan timeout) override;
virtual Result ResetChargerWatchdogTimer(IDevice *device) override;
virtual Result GetChargerBatteryCompensation(int *out_mo, IDevice *device) override;
virtual Result SetChargerBatteryCompensation(IDevice *device, int mo) override;
virtual Result GetChargerVoltageClamp(int *out_mv, IDevice *device) override;
virtual Result SetChargerVoltageClamp(IDevice *device, int mv) override;
/* Unsupported Battery API. */
virtual Result GetBatterySocRep(float *out_percent, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatterySocVf(float *out_percent, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryFullCapacity(int *out_mah, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryRemainingCapacity(int *out_mah, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryPercentageMinimumAlertThreshold(IDevice *device, float percentage) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryPercentageMaximumAlertThreshold(IDevice *device, float percentage) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryPercentageFullThreshold(IDevice *device, float percentage) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryAverageCurrent(int *out_ma, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryCurrent(int *out_ma, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryInternalState(void *dst, size_t *out_size, IDevice *device, size_t dst_size) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryInternalState(IDevice *device, const void *src, size_t src_size) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryNeedToRestoreParameters(bool *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryNeedToRestoreParameters(IDevice *device, bool en) override { return powctl::ResultNotSupported(); }
virtual Result IsBatteryI2cShutdownEnabled(bool *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryI2cShutdownEnabled(IDevice *device, bool en) override { return powctl::ResultNotSupported(); }
virtual Result IsBatteryPresent(bool *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryCycles(int *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryCycles(IDevice *device, int cycles) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryAge(float *out_percent, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryTemperature(float *out_c, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryMaximumTemperature(float *out_c, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryTemperatureMinimumAlertThreshold(IDevice *device, float c) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryTemperatureMaximumAlertThreshold(IDevice *device, float c) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryVCell(int *out_mv, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryAverageVCell(int *out_mv, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryAverageVCellTime(TimeSpan *out, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryVoltageMinimumAlertThreshold(IDevice *device, int mv) override { return powctl::ResultNotSupported(); }
virtual Result GetBatteryOpenCircuitVoltage(int *out_mv, IDevice *device) override { return powctl::ResultNotSupported(); }
virtual Result SetBatteryVoltageMaximumAlertThreshold(IDevice *device, int mv) override { return powctl::ResultNotSupported(); }
};
}

View file

@ -39,6 +39,12 @@ namespace ams::powctl::impl::board::nintendo_nx {
return std::addressof(this->gpio_system_event);
}
void SetInterruptEnabled(bool en) {
std::scoped_lock lk(this->mutex);
gpio::SetInterruptEnable(std::addressof(this->gpio_session), en);
}
virtual void HandleEvent() override final {
/* Acquire exclusive access to ourselves. */
std::scoped_lock lk(this->mutex);
@ -50,7 +56,7 @@ namespace ams::powctl::impl::board::nintendo_nx {
os::ClearSystemEvent(std::addressof(this->gpio_system_event));
/* Signal the event. */
Derived::SignalEvent(this->device);
static_cast<Derived *>(this)->SignalEvent(this->device);
}
};

View file

@ -44,7 +44,7 @@ namespace ams::powctl::impl {
virtual void InitializeDriver() = 0;
virtual void FinalizeDriver() = 0;
virtual Result GetDeviceSystemEvent(IDevice *device) = 0;
virtual Result GetDeviceSystemEvent(os::SystemEventType **out, IDevice *device) = 0;
virtual Result SetDeviceInterruptEnabled(IDevice *device, bool enable) = 0;
/* TODO: Eventually implement proper error status enum? */