Skip to content

Commit

Permalink
smu-tool: Add multiple SMU Support
Browse files Browse the repository at this point in the history
Just found that we have another SMU interface called PwrSMU

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
  • Loading branch information
FlyGoat committed Feb 7, 2019
1 parent 5f0b9cc commit a421eb7
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 29 deletions.
36 changes: 32 additions & 4 deletions smu-tool/inc/nb_smu_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,38 @@ typedef uint64_t u64;

#define AMD_VENDOR_ID 0x1022
#define NB_DEVICE_ID 0x15d0
#define NB_PCI_ID (AMD_VENDOR_ID << 16 | NB_DEVICE_ID)

#define NB_PCI_REG_ADDR_ADDR 0xB8
#define NB_PCI_REG_DATA_ADDR 0xBC

#define C2PMSG_ARGx_ADDR(y, x) (y + 4 * x)

enum SMU_TYPE{
TYPE_MP1,
TYPE_PSMU,
TYPE_COUNT,
};

#define MP1_C2PMSG_MESSAGE_ADDR 0x3B10528
#define MP1_C2PMSG_RESPONSE_ADDR 0x3B10564
#define MP1_C2PMSG_ARG_BASE 0x3B10998
#define MP1_C2PMSG_ARGx_ADDR(x) (MP1_C2PMSG_ARG_BASE + 4 * x)

#define PSMU_C2PMSG_MESSAGE_ADDR 0x3B10a20
#define PSMU_C2PMSG_RESPONSE_ADDR 0x3B10a80
#define PSMU_C2PMSG_ARG_BASE 0x3B10a88

#define REP_MSG_OK 0x1
#define REP_MSG_Failed 0xFF
#define REP_MSG_UnknownCmd 0xFE
#define REP_MSG_CmdRejectedPrereq 0xFD
#define REP_MSG_CmdRejectedBusy 0xFC

/*
* All the SMU have the same TestMessage as for now
* Correct me if they don't
*/
#define SMU_TEST_MSG 0x1

typedef struct {
u32 arg0;
u32 arg1;
Expand All @@ -61,17 +76,30 @@ typedef struct pci_dev *nb_t;
typedef struct pci_access *pci_obj_t;
#endif

typedef struct {
nb_t nb;
u32 msg;
u32 rep;
u32 arg_base;
} smu_t;


pci_obj_t init_pci_obj();

int free_pci_obj(pci_obj_t obj);
void free_pci_obj(pci_obj_t obj);

nb_t get_nb(pci_obj_t obj);

void free_nb(nb_t nb);

u32 nb_reg_read(nb_t nb, u32 addr);

void nb_reg_write(nb_t nb, u32 addr, u32 data);

u32 smu_service_req(nb_t nb ,u32 id ,smu_service_args_t *args);

smu_t *get_smu(nb_t nb, int smu_type);
void free_smu(smu_t *smu);
u32 smu_service_req(smu_t *smu ,u32 id ,smu_service_args_t *args);


#endif
8 changes: 6 additions & 2 deletions smu-tool/libpci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ nb_t get_nb(pci_obj_t obj){
return nb;
}

int free_pci_obj(pci_obj_t obj){
void free_nb(nb_t nb){
pci_free_dev(nb);
}


void free_pci_obj(pci_obj_t obj){
pci_cleanup(obj);
return 0;
}

u32 nb_reg_read(nb_t nb, u32 addr)
Expand Down
35 changes: 30 additions & 5 deletions smu-tool/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@ static const char *const usage[] = {

int main(int argc, const char **argv)
{
pci_obj_t pci_obj;
nb_t nb;
/* Input args */
uint32_t message = 0, iarg0 = 0, iarg1 = 0;
uint32_t iarg2 = 0, iarg3 = 0, iarg4 = 0, iarg5 = 0;
int mp1 = 0, psmu = 0;

/* Objects */
pci_obj_t pci_obj;
nb_t nb;
smu_t *smu;
smu_service_args_t *args;
int err = 0;

struct argparse_option options[] = {
OPT_HELP(),
OPT_GROUP("SMU Type"),
OPT_BOOLEAN('m',"mp1", &mp1, "MP1 SMU"),
OPT_BOOLEAN('p',"psmu", &psmu, "Pwr SMU"),
OPT_GROUP("Arguments"),
OPT_U32('n', "message", &message, "The reqeust message"),
OPT_U32('a', "arg0", &iarg0, "The first argument"),
Expand All @@ -42,18 +50,32 @@ int main(int argc, const char **argv)
argc = argparse_parse(&argparse, argc, argv);

pci_obj = init_pci_obj();
if(!pci_obj){
if (!pci_obj){
printf("Unable to get PCI Obj\n");
return -1;
}

nb = get_nb(pci_obj);
if(!nb){
if (!nb){
printf("Unable to get NB Obj\n");
err = -1;
goto out_free_pci_obj;
}

if (mp1){
smu = get_smu(nb, TYPE_MP1);
} else if (psmu){
smu = get_smu(nb, TYPE_PSMU);
} else {
smu = get_smu(nb, TYPE_MP1);
}

if(!smu){
printf("Unable to get SMU\n");
err = -1;
goto out_free_nb;
}

args = (smu_service_args_t *)malloc(sizeof(*args));
memset(args, 0, sizeof(*args));

Expand All @@ -64,7 +86,7 @@ int main(int argc, const char **argv)
args->arg4 = iarg4;
args->arg5 = iarg5;

switch(smu_service_req(nb, message, args)){
switch(smu_service_req(smu, message, args)){
case REP_MSG_OK:
printf("Service Request OK\n");
break;
Expand Down Expand Up @@ -95,6 +117,9 @@ int main(int argc, const char **argv)
}

free(args);
free_smu(smu);
out_free_nb:
free_nb(nb);
out_free_pci_obj:
free_pci_obj(pci_obj);
return err;
Expand Down
73 changes: 57 additions & 16 deletions smu-tool/nb_smu_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,79 @@

#include "nb_smu_ops.h"

u32 smu_service_req(nb_t nb ,u32 id ,smu_service_args_t *args)
u32 smu_service_req(smu_t *smu ,u32 id ,smu_service_args_t *args)
{
u32 response = 0x0;
DBG("SMU_SERVICE REQ_ID:0x%x\n", id);
DBG("SMU_SERVICE REQ: arg0: 0x%x, arg1:0x%x, arg2:0x%x, arg3:0x%x, arg4: 0x%x, arg5: 0x%x\n", \
args->arg0, args->arg1, args->arg2, args->arg3, args->arg4, args->arg5);

/* Clear the response */
nb_reg_write(nb, MP1_C2PMSG_RESPONSE_ADDR, 0x0);
nb_reg_write(smu->nb, smu->rep, 0x0);
/* Pass arguments */
nb_reg_write(nb, MP1_C2PMSG_ARGx_ADDR(0), args->arg0);
nb_reg_write(nb, MP1_C2PMSG_ARGx_ADDR(1), args->arg1);
nb_reg_write(nb, MP1_C2PMSG_ARGx_ADDR(2), args->arg2);
nb_reg_write(nb, MP1_C2PMSG_ARGx_ADDR(3), args->arg3);
nb_reg_write(nb, MP1_C2PMSG_ARGx_ADDR(4), args->arg4);
nb_reg_write(nb, MP1_C2PMSG_ARGx_ADDR(5), args->arg5);
nb_reg_write(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 0), args->arg0);
nb_reg_write(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 1), args->arg1);
nb_reg_write(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 2), args->arg2);
nb_reg_write(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 3), args->arg3);
nb_reg_write(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 4), args->arg4);
nb_reg_write(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 5), args->arg5);
/* Send message ID */
nb_reg_write(nb, MP1_C2PMSG_MESSAGE_ADDR, id);
nb_reg_write(smu->nb, smu->msg, id);
/* Wait until reponse changed */
while(response == 0x0) {
response = nb_reg_read(nb, MP1_C2PMSG_RESPONSE_ADDR);
response = nb_reg_read(smu->nb, smu->rep);
}
/* Read back arguments */
args->arg0 = nb_reg_read(nb, MP1_C2PMSG_ARGx_ADDR(0));
args->arg1 = nb_reg_read(nb, MP1_C2PMSG_ARGx_ADDR(1));
args->arg2 = nb_reg_read(nb, MP1_C2PMSG_ARGx_ADDR(2));
args->arg3 = nb_reg_read(nb, MP1_C2PMSG_ARGx_ADDR(3));
args->arg4 = nb_reg_read(nb, MP1_C2PMSG_ARGx_ADDR(4));
args->arg5 = nb_reg_read(nb, MP1_C2PMSG_ARGx_ADDR(5));
args->arg0 = nb_reg_read(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 0));
args->arg1 = nb_reg_read(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 1));
args->arg2 = nb_reg_read(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 2));
args->arg3 = nb_reg_read(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 3));
args->arg4 = nb_reg_read(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 4));
args->arg5 = nb_reg_read(smu->nb, C2PMSG_ARGx_ADDR(smu->arg_base, 5));

DBG("SMU_SERVICE REP: REP: 0x%x, arg0: 0x%x, arg1:0x%x, arg2:0x%x, arg3:0x%x, arg4: 0x%x, arg5: 0x%x\n", \
response, args->arg0, args->arg1, args->arg2, args->arg3, args->arg4, args->arg5);

return response;
}

smu_t *get_smu(nb_t nb, int smu_type) {
smu_t *smu;
uint32_t rep; /* REP of test message */
smu_service_args_t arg = {0, 0, 0, 0, 0, 0}; /* Test message shuld have no arguments */

smu = (smu_t *)malloc((sizeof(smu_t)));
smu->nb = nb;
/* Fill SMU information */
switch(smu_type){
case TYPE_MP1:
smu->msg = MP1_C2PMSG_MESSAGE_ADDR;
smu->rep = MP1_C2PMSG_RESPONSE_ADDR;
smu->arg_base = MP1_C2PMSG_ARG_BASE;
break;
case TYPE_PSMU:
smu->msg = PSMU_C2PMSG_MESSAGE_ADDR;
smu->rep = PSMU_C2PMSG_RESPONSE_ADDR;
smu->arg_base = PSMU_C2PMSG_ARG_BASE;
break;
default:
DBG("Failed to get SMU, unknown SMU_TYPE: %s\n", smu_type);
goto err;
break;
}
/* Try to send a test message*/
rep = smu_service_req(smu, SMU_TEST_MSG, &arg);
if(rep == REP_MSG_OK){
return smu;
} else {
DBG("Faild to get SMU: %s, test message REP: %x\n", smu_type, rep);
goto err;
}
err:
free_smu(smu);
return NULL;
}

void free_smu(smu_t *smu) {
free((void *)smu);
}
7 changes: 5 additions & 2 deletions smu-tool/winring0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ nb_t get_nb(pci_obj_t obj){
return &nb_pci_address;
}

int free_pci_obj(pci_obj_t obj){
void free_nb(nb_t){
return;
}

void free_pci_obj(pci_obj_t obj){
DeinitializeOls();
return 0;
}

u32 nb_reg_read(nb_t nb, u32 addr)
Expand Down

0 comments on commit a421eb7

Please sign in to comment.