pwm: implement driver for boot sysmodule

This commit is contained in:
Michael Scire 2020-11-01 23:04:19 -08:00 committed by SciresM
parent 35552bac2c
commit 3d31837ca1
41 changed files with 2107 additions and 59 deletions

View file

@ -15,7 +15,7 @@
*/
#include <stratosphere.hpp>
namespace ams::clkrst {
namespace ams {
namespace {
@ -47,14 +47,15 @@ namespace ams::clkrst {
constexpr inline const struct {
const ClkRstDefinition *definition;
DeviceCode device_code;
pcv::Module pcv_module;
} ClkRstDefinitionMap[] = {
{ std::addressof(Definitions[0]), i2c::DeviceCode_I2c1 },
{ std::addressof(Definitions[1]), i2c::DeviceCode_I2c2 },
{ std::addressof(Definitions[2]), i2c::DeviceCode_I2c3 },
{ std::addressof(Definitions[3]), i2c::DeviceCode_I2c4 },
{ std::addressof(Definitions[4]), i2c::DeviceCode_I2c5 },
{ std::addressof(Definitions[5]), i2c::DeviceCode_I2c6 },
{ std::addressof(Definitions[6]), pwm::DeviceCode_LcdBacklight },
{ std::addressof(Definitions[0]), i2c::DeviceCode_I2c1, pcv::Module_I2c1 },
{ std::addressof(Definitions[1]), i2c::DeviceCode_I2c2, pcv::Module_I2c2 },
{ std::addressof(Definitions[2]), i2c::DeviceCode_I2c3, pcv::Module_I2c3 },
{ std::addressof(Definitions[3]), i2c::DeviceCode_I2c4, pcv::Module_I2c4 },
{ std::addressof(Definitions[4]), i2c::DeviceCode_I2c5, pcv::Module_I2c5 },
{ std::addressof(Definitions[5]), i2c::DeviceCode_I2c6, pcv::Module_I2c6 },
{ std::addressof(Definitions[6]), pwm::DeviceCode_LcdBacklight, pcv::Module_Pwm },
};
ALWAYS_INLINE const ClkRstDefinition *GetDefinition(DeviceCode device_code) {
@ -71,7 +72,21 @@ namespace ams::clkrst {
return def;
}
ALWAYS_INLINE const ClkRstDefinition &GetDefinition(ClkRstSession *session) {
ALWAYS_INLINE const ClkRstDefinition &GetDefinition(pcv::Module module) {
const ClkRstDefinition *def = nullptr;
for (const auto &entry : ClkRstDefinitionMap) {
if (entry.pcv_module == module) {
def = entry.definition;
break;
}
}
AMS_ABORT_UNLESS(def != nullptr);
return *def;
}
ALWAYS_INLINE const ClkRstDefinition &GetDefinition(clkrst::ClkRstSession *session) {
const ClkRstDefinition *def = nullptr;
for (const auto &entry : ClkRstDefinitionMap) {
@ -85,65 +100,108 @@ namespace ams::clkrst {
return *def;
}
void SetResetEnabled(const ClkRstDefinition &def, bool en) {
/* Set or clear reset. */
reg::ReadWrite(g_clkrst_registers + def.rst_ofs, (en ? 1u : 0u) << def.rst_index, 1u << def.rst_index);
}
void SetClockEnabled(const ClkRstDefinition &def, bool en) {
/* Set or clear reset. */
reg::ReadWrite(g_clkrst_registers + def.clk_en_ofs, (en ? 1u : 0u) << def.clk_en_index, 1u << def.clk_en_index);
}
void SetClockRate(const ClkRstDefinition &def, u32 hz) {
/* Enable clock. */
reg::ReadWrite(g_clkrst_registers + def.clk_en_ofs, 1u << def.clk_en_index, 1u << def.clk_en_index);
/* Set the clock divisor. */
reg::ReadWrite(g_clkrst_registers + def.clk_src_ofs, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_CLK_DIVISOR, def.clk_divisor));
/* Wait for 2us for clock setting to take. */
os::SleepThread(TimeSpan::FromMicroSeconds(2));
/* Set the clock source. */
reg::ReadWrite(g_clkrst_registers + def.clk_src_ofs, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_CLK_SOURCE, def.clk_src));
/* Wait for 2us for clock setting to take. */
os::SleepThread(TimeSpan::FromMicroSeconds(2));
}
}
void Initialize() {
/* ... */
namespace clkrst {
void Initialize() {
/* ... */
}
void Finalize() {
/* ... */
}
Result OpenSession(ClkRstSession *out, DeviceCode device_code) {
/* Get the relevant definition. */
out->_session = const_cast<ClkRstDefinition *>(GetDefinition(device_code));
return ResultSuccess();
}
void CloseSession(ClkRstSession *session) {
/* Clear the session. */
session->_session = nullptr;
}
void SetResetAsserted(ClkRstSession *session) {
/* Assert reset. */
SetResetEnabled(GetDefinition(session), true);
}
void SetResetDeasserted(ClkRstSession *session) {
/* Assert reset. */
SetResetEnabled(GetDefinition(session), false);
}
void SetClockRate(ClkRstSession *session, u32 hz) {
/* Set the clock rate. */
SetClockRate(GetDefinition(session), hz);
}
void SetClockDisabled(ClkRstSession *session) {
AMS_ABORT("SetClockDisabled not implemented for boot system module");
}
}
void Finalize() {
/* ... */
}
namespace pcv {
Result OpenSession(ClkRstSession *out, DeviceCode device_code) {
/* Get the relevant definition. */
out->_session = const_cast<ClkRstDefinition *>(GetDefinition(device_code));
return ResultSuccess();
}
void Initialize() {
/* ... */
}
void CloseSession(ClkRstSession *session) {
/* Clear the session. */
session->_session = nullptr;
}
void Finalize() {
/* ... */
}
void SetResetAsserted(ClkRstSession *session) {
/* Get the definition. */
const auto &def = GetDefinition(session);
Result SetClockEnabled(Module module, bool en) {
/* Set clock. */
SetClockEnabled(GetDefinition(module), en);
/* Assert reset. */
reg::ReadWrite(g_clkrst_registers + def.rst_ofs, 1u << def.rst_index, 1u << def.rst_index);
}
return ResultSuccess();
}
void SetResetDeasserted(ClkRstSession *session) {
/* Get the definition. */
const auto &def = GetDefinition(session);
Result SetClockRate(Module module, ClockHz hz) {
/* Set the clock rate. */
SetClockRate(GetDefinition(module), hz);
/* Clear reset. */
reg::ReadWrite(g_clkrst_registers + def.rst_ofs, 0, 1u << def.rst_index);
}
return ResultSuccess();
}
void SetClockRate(ClkRstSession *session, u32 hz) {
/* Get the definition. */
const auto &def = GetDefinition(session);
Result SetReset(Module module, bool en) {
/* Set reset. */
SetResetEnabled(GetDefinition(module), en);
/* Enable clock. */
reg::ReadWrite(g_clkrst_registers + def.clk_en_ofs, 1u << def.clk_en_index, 1u << def.clk_en_index);
return ResultSuccess();
}
/* Set the clock divisor. */
reg::ReadWrite(g_clkrst_registers + def.clk_src_ofs, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_CLK_DIVISOR, def.clk_divisor));
/* Wait for 2us for clock setting to take. */
os::SleepThread(TimeSpan::FromMicroSeconds(2));
/* Set the clock source. */
reg::ReadWrite(g_clkrst_registers + def.clk_src_ofs, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_CLK_SOURCE, def.clk_src));
/* Wait for 2us for clock setting to take. */
os::SleepThread(TimeSpan::FromMicroSeconds(2));
}
void SetClockDisabled(ClkRstSession *session) {
AMS_ABORT("SetClockDisabled not implemented for boot system module");
}
}

View file

@ -40,13 +40,13 @@ namespace ams::boot {
i2c::driver::Initialize();
/* Initialize the pwm client library with the server manager object. */
/* TODO: pwm::InitializeWith(pwm::server::GetServiceObject()); */
pwm::InitializeWith(pwm::server::GetServiceObject());
/* Initialize the pwm board driver. */
/* TODO: pwm::driver::board::Initialize(); */
pwm::driver::board::Initialize();
/* Initialize the pwm driver library. */
/* TODO: pwm::driver::Initialize(); */
pwm::driver::Initialize();
}
}