Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nx/include/switch.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extern "C" {
#include "switch/services/gpio.h"
#include "switch/services/bpc.h"
#include "switch/services/pcv.h"
#include "switch/services/clkrst.h"
#include "switch/services/psm.h"
#include "switch/services/spsm.h"
//#include "switch/services/bsd.h" Use switch/runtime/devices/socket.h instead
Expand Down
23 changes: 23 additions & 0 deletions nx/include/switch/services/clkrst.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @file clkrst.h
* @brief Clkrst service IPC wrapper.
* @author p-sam
* @copyright libnx Authors
*/
#pragma once
#include "../types.h"
#include "../services/sm.h"
#include "../services/pcv.h"

typedef struct {
Service s;
} ClkrstSession;

Result clkrstInitialize(void);
void clkrstExit(void);

/// Opens a ClkrstSession for the requested PcvModuleId, unk is set to 3 in official sysmodules.
Result clkrstOpenSession(ClkrstSession* session_out, PcvModuleId module_id, u32 unk);
void clkrstCloseSession(ClkrstSession* session);
Result clkrstSetClockRate(ClkrstSession* session, u32 hz);
Result clkrstGetClockRate(ClkrstSession* session, u32 *out_hz);
88 changes: 87 additions & 1 deletion nx/include/switch/services/pcv.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,97 @@ typedef enum {
PcvModule_Emc = 56,
} PcvModule;

/// Module id returned by [8.0.0+] pcv services
/// See also: https://switchbrew.org/wiki/PCV_services#Modules
typedef enum {
PcvModuleId_CpuBus = 0x40000001,
PcvModuleId_GPU = 0x40000002,
PcvModuleId_I2S1 = 0x40000003,
PcvModuleId_I2S2 = 0x40000004,
PcvModuleId_I2S3 = 0x40000005,
PcvModuleId_PWM = 0x40000006,
PcvModuleId_I2C1 = 0x02000001,
PcvModuleId_I2C2 = 0x02000002,
PcvModuleId_I2C3 = 0x02000003,
PcvModuleId_I2C4 = 0x02000004,
PcvModuleId_I2C5 = 0x02000005,
PcvModuleId_I2C6 = 0x02000006,
PcvModuleId_SPI1 = 0x07000000,
PcvModuleId_SPI2 = 0x07000001,
PcvModuleId_SPI3 = 0x07000002,
PcvModuleId_SPI4 = 0x07000003,
PcvModuleId_DISP1 = 0x40000011,
PcvModuleId_DISP2 = 0x40000012,
PcvModuleId_SDMMC1 = 0x40000015,
PcvModuleId_SDMMC2 = 0x40000016,
PcvModuleId_SDMMC3 = 0x40000017,
PcvModuleId_SDMMC4 = 0x40000018,
PcvModuleId_CSITE = 0x4000001A,
PcvModuleId_TSEC = 0x4000001B,
PcvModuleId_MSELECT = 0x4000001C,
PcvModuleId_HDA2CODEC_2X = 0x4000001D,
PcvModuleId_ACTMON = 0x4000001E,
PcvModuleId_I2C_SLOW = 0x4000001F,
PcvModuleId_SOR1 = 0x40000020,
PcvModuleId_HDA = 0x40000022,
PcvModuleId_XUSB_CORE_HOST = 0x40000023,
PcvModuleId_XUSB_FALCON = 0x40000024,
PcvModuleId_XUSB_FS = 0x40000025,
PcvModuleId_XUSB_CORE_DEV = 0x40000026,
PcvModuleId_XUSB_SS_HOSTDEV = 0x40000027,
PcvModuleId_UARTA = 0x03000001,
PcvModuleId_UARTB = 0x35000405,
PcvModuleId_UARTC = 0x3500040F,
PcvModuleId_UARTD = 0x37000001,
PcvModuleId_HOST1X = 0x4000002C,
PcvModuleId_ENTROPY = 0x4000002D,
PcvModuleId_SOC_THERM = 0x4000002E,
PcvModuleId_VIC = 0x4000002F,
PcvModuleId_NVENC = 0x40000030,
PcvModuleId_NVJPG = 0x40000031,
PcvModuleId_NVDEC = 0x40000032,
PcvModuleId_QSPI = 0x40000033,
PcvModuleId_TSECB = 0x40000035,
PcvModuleId_APE = 0x40000036,
PcvModuleId_ACLK = 0x40000037,
PcvModuleId_UARTAPE = 0x40000038,
PcvModuleId_EMC = 0x40000039,
PcvModuleId_PLLE0_0 = 0x4000003A,
PcvModuleId_PLLE0_1 = 0x4000003B,
PcvModuleId_DSI = 0x4000003C,
PcvModuleId_MAUD = 0x4000003D,
PcvModuleId_DPAUX1 = 0x4000003E,
PcvModuleId_MIPI_CAL = 0x4000003F,
PcvModuleId_UART_FST_MIPI_CAL = 0x40000040,
PcvModuleId_OSC = 0x40000041,
PcvModuleId_SCLK = 0x40000042,
PcvModuleId_SOR_SAFE = 0x40000043,
PcvModuleId_XUSB_SS = 0x40000044,
PcvModuleId_XUSB_HOST = 0x40000045,
PcvModuleId_XUSB_DEV = 0x40000046,
PcvModuleId_EXTPERIPH1 = 0x40000047,
PcvModuleId_AHUB = 0x40000048,
PcvModuleId_HDA2HDMICODEC = 0x40000049,
PcvModuleId_PLLP5 = 0x4000004A,
PcvModuleId_USBD = 0x4000004B,
PcvModuleId_USB2 = 0x4000004C,
PcvModuleId_PCIE = 0x4000004D,
PcvModuleId_AFI = 0x4000004E,
PcvModuleId_PCIEXCLK = 0x4000004F,
PcvModuleId_PEX_USB_UPHY = 0x40000050,
PcvModuleId_XUSB_PADCTL = 0x40000051,
PcvModuleId_APBDMA = 0x40000052,
PcvModuleId_USB2_TRK = 0x40000053,
PcvModuleId_PLLE0_2 = 0x40000054,
PcvModuleId_PLLE0_3 = 0x40000055,
PcvModuleId_CEC = 0x40000056,
PcvModuleId_EXTPERIPH2 = 0x40000057,
} PcvModuleId;

Result pcvInitialize(void);
void pcvExit(void);

Result pcvGetClockRate(PcvModule module, u32 *out_hz);
Result pcvSetClockRate(PcvModule module, u32 hz);
Result pcvSetVoltageEnabled(bool state, u32 voltage);
Result pcvGetVoltageEnabled(bool *isEnabled, u32 voltage);

152 changes: 152 additions & 0 deletions nx/source/services/clkrst.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#include "types.h"
#include "result.h"
#include "arm/atomics.h"
#include "kernel/ipc.h"
#include "services/pcv.h"
#include "runtime/hosversion.h"
#include "services/sm.h"
#include "services/clkrst.h"

static Service g_clkrstSrv;
static u64 g_refCnt;

Result clkrstInitialize(void) {
if(hosversionBefore(8,0,0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}

atomicIncrement64(&g_refCnt);

if (serviceIsActive(&g_clkrstSrv)) {
return 0;
}

Result rc = smGetService(&g_clkrstSrv, "clkrst");

if (R_FAILED(rc)) {
clkrstExit();
}

return rc;
}


void clkrstExit(void) {
if (atomicDecrement64(&g_refCnt) == 0) {
serviceClose(&g_clkrstSrv);
}
}

Result clkrstOpenSession(ClkrstSession* session_out, PcvModuleId module_id, u32 unk) {
IpcCommand c;
ipcInitialize(&c);

struct {
u64 magic;
u64 cmd_id;
u32 module_id;
u32 unk;
} *raw;

raw = ipcPrepareHeader(&c, sizeof(*raw));

raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->module_id = module_id;
raw->unk = unk;

Result rc = serviceIpcDispatch(&g_clkrstSrv);

if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);

struct {
u64 magic;
u64 result;
} *resp = r.Raw;

rc = resp->result;
if (R_SUCCEEDED(rc)) {
serviceCreate(&session_out->s, r.Handles[0]);
}
}

return rc;
}


void clkrstCloseSession(ClkrstSession* session) {
serviceClose(&session->s);
}

Result clkrstSetClockRate(ClkrstSession* session, u32 hz) {
IpcCommand c;
ipcInitialize(&c);

struct {
u64 magic;
u64 cmd_id;
u32 hz;
} *raw;

raw = serviceIpcPrepareHeader(&session->s, &c, sizeof(*raw));

raw->magic = SFCI_MAGIC;
raw->cmd_id = 7;
raw->hz = hz;

Result rc = serviceIpcDispatch(&session->s);

if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;

serviceIpcParse(&session->s, &r, sizeof(*resp));
resp = r.Raw;

rc = resp->result;
}

return rc;
}

Result clkrstGetClockRate(ClkrstSession* session, u32 *out_hz) {
IpcCommand c;
ipcInitialize(&c);

struct {
u64 magic;
u64 cmd_id;
} *raw;

raw = serviceIpcPrepareHeader(&session->s, &c, sizeof(*raw));

raw->magic = SFCI_MAGIC;
raw->cmd_id = 8;

Result rc = serviceIpcDispatch(&session->s);

if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u32 hz;
} *resp;

serviceIpcParse(&session->s, &r, sizeof(*resp));
resp = r.Raw;

rc = resp->result;

if (R_SUCCEEDED(rc)) {
*out_hz = resp->hz;
}
}

return rc;
}
17 changes: 17 additions & 0 deletions nx/source/services/pcv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "result.h"
#include "arm/atomics.h"
#include "kernel/ipc.h"
#include "runtime/hosversion.h"
#include "services/pcv.h"
#include "services/sm.h"

Expand Down Expand Up @@ -30,6 +31,10 @@ void pcvExit(void) {
}

Result pcvSetClockRate(PcvModule module, u32 hz) {
if(hosversionAtLeast(8,0,0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}

IpcCommand c;
ipcInitialize(&c);

Expand Down Expand Up @@ -66,6 +71,10 @@ Result pcvSetClockRate(PcvModule module, u32 hz) {
}

Result pcvGetClockRate(PcvModule module, u32 *out_hz) {
if(hosversionAtLeast(8,0,0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}

IpcCommand c;
ipcInitialize(&c);

Expand Down Expand Up @@ -105,6 +114,10 @@ Result pcvGetClockRate(PcvModule module, u32 *out_hz) {
}

Result pcvSetVoltageEnabled(bool state, u32 voltage) {
if(hosversionAtLeast(8,0,0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}

IpcCommand c;
ipcInitialize(&c);

Expand Down Expand Up @@ -141,6 +154,10 @@ Result pcvSetVoltageEnabled(bool state, u32 voltage) {
}

Result pcvGetVoltageEnabled(bool *isEnabled, u32 voltage) {
if(hosversionAtLeast(8,0,0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}

IpcCommand c;
ipcInitialize(&c);

Expand Down