File drivers/gpu/alga/amd/si/dyn_pm/driver.c changed (mode: 100644) (index 1f21dd9..53742e2) |
37 |
37 |
#include "private.h" |
#include "private.h" |
38 |
38 |
#include "smc_lvl.h" |
#include "smc_lvl.h" |
39 |
39 |
#include "smc_volt.h" |
#include "smc_volt.h" |
|
40 |
|
#include "smc_mc_reg_tbl.h" |
40 |
41 |
|
|
41 |
42 |
static void smc_sw_state_init(struct ctx *ctx, struct smc_sw_state *state) |
static void smc_sw_state_init(struct ctx *ctx, struct smc_sw_state *state) |
42 |
43 |
{ |
{ |
|
... |
... |
err: |
287 |
288 |
return -SI_ERR; |
return -SI_ERR; |
288 |
289 |
} |
} |
289 |
290 |
|
|
|
291 |
|
/* return the *atb* set idx, the smc set idx */ |
|
292 |
|
static u8 atb_mc_reg_set_find(struct ctx *ctx, u32 mem_clk) |
|
293 |
|
{ |
|
294 |
|
u8 mc_reg_set_idx; |
|
295 |
|
|
|
296 |
|
/* select a set of mc regs which can support the pwr lvl mem clk */ |
|
297 |
|
for (mc_reg_set_idx = 0; mc_reg_set_idx < ctx->atb_mc_reg_tbl.sets_n; |
|
298 |
|
++mc_reg_set_idx) { |
|
299 |
|
struct atb_mc_reg_set *mc_reg_set; |
|
300 |
|
|
|
301 |
|
mc_reg_set = &ctx->atb_mc_reg_tbl.sets[mc_reg_set_idx]; |
|
302 |
|
|
|
303 |
|
if (mem_clk <= mc_reg_set->mem_clk_max) |
|
304 |
|
break; |
|
305 |
|
} |
|
306 |
|
|
|
307 |
|
/* |
|
308 |
|
* Not found, then try the last one as a work around which should |
|
309 |
|
* accomodate the highest mem clk. The tbl seems to be sorted |
|
310 |
|
* from lowest mem clk to highest mem clk. |
|
311 |
|
*/ |
|
312 |
|
if (mc_reg_set_idx == ctx->atb_mc_reg_tbl.sets_n) |
|
313 |
|
--mc_reg_set_idx; /* we presume we have at least one set */ |
|
314 |
|
return mc_reg_set_idx; |
|
315 |
|
} |
|
316 |
|
|
|
317 |
|
static void smc_mc_reg_set_init(struct ctx *ctx, u8 smc_set_idx, |
|
318 |
|
struct smc_mc_reg_set *set) |
|
319 |
|
{ |
|
320 |
|
u32 mem_clk; |
|
321 |
|
u8 atb_mc_reg_set_idx; |
|
322 |
|
|
|
323 |
|
mem_clk = ctx->atb_performance.lvls[smc_set_idx].mem_clk; |
|
324 |
|
|
|
325 |
|
atb_mc_reg_set_idx = atb_mc_reg_set_find(ctx, mem_clk); |
|
326 |
|
|
|
327 |
|
smc_mc_reg_set_load(ctx, atb_mc_reg_set_idx, set); |
|
328 |
|
} |
|
329 |
|
|
|
330 |
|
static void smc_mc_reg_sets_init(struct ctx *ctx, struct smc_mc_reg_set *sets) |
|
331 |
|
{ |
|
332 |
|
u8 set_idx; |
|
333 |
|
|
|
334 |
|
for (set_idx = 0; set_idx < ctx->atb_performance.lvls_n; ++set_idx) |
|
335 |
|
smc_mc_reg_set_init(ctx, set_idx, &sets[set_idx]); |
|
336 |
|
} |
290 |
337 |
|
|
291 |
338 |
static long smc_tbls_init(struct ctx *ctx) |
static long smc_tbls_init(struct ctx *ctx) |
292 |
339 |
{ |
{ |
293 |
340 |
struct smc_sw_state *smc_sw_state; |
struct smc_sw_state *smc_sw_state; |
294 |
341 |
struct smc_lvl *smc_lvls; |
struct smc_lvl *smc_lvls; |
|
342 |
|
struct smc_mc_reg_set *smc_mc_reg_sets; |
295 |
343 |
long r; |
long r; |
296 |
344 |
|
|
297 |
345 |
/*--------------------------------------------------------------------*/ |
/*--------------------------------------------------------------------*/ |
|
... |
... |
static long smc_tbls_init(struct ctx *ctx) |
319 |
367 |
|
|
320 |
368 |
/*--------------------------------------------------------------------*/ |
/*--------------------------------------------------------------------*/ |
321 |
369 |
|
|
322 |
|
//TODO:mc_regs, mc_arb... |
|
|
370 |
|
smc_mc_reg_sets = kzalloc(sizeof(*smc_mc_reg_sets) |
|
371 |
|
* ctx->atb_performance.lvls_n, GFP_KERNEL); |
|
372 |
|
if (!smc_mc_reg_sets) { |
|
373 |
|
dev_err(&ctx->dev->dev, "dyn_pm:driver:unable to alloc the smc_mc_reg_sets\n"); |
|
374 |
|
goto err_free_smc_lvls; |
|
375 |
|
} |
|
376 |
|
|
|
377 |
|
smc_mc_reg_sets_init(ctx, smc_mc_reg_sets); |
|
378 |
|
|
|
379 |
|
/*--------------------------------------------------------------------*/ |
|
380 |
|
|
|
381 |
|
//TODO:mc_arb_regs... |
|
382 |
|
|
|
383 |
|
//TODO:cpy in smc sram and dump the tables from smc sram |
323 |
384 |
|
|
|
385 |
|
kfree(smc_mc_reg_sets); |
324 |
386 |
kfree(smc_lvls); |
kfree(smc_lvls); |
325 |
387 |
kfree(smc_sw_state); |
kfree(smc_sw_state); |
326 |
388 |
return 0; |
return 0; |
File drivers/gpu/alga/amd/si/dyn_pm/ulv.c changed (mode: 100644) (index a068ad0..4a7df4c) |
... |
... |
long smc_state_tbl_ulv_init(struct ctx *ctx, struct smc_state_tbl *tbl) |
43 |
43 |
{ |
{ |
44 |
44 |
long r; |
long r; |
45 |
45 |
|
|
46 |
|
LOG("ulv smc table init"); |
|
|
46 |
|
LOG("ultra low voltage smc table init"); |
47 |
47 |
|
|
48 |
48 |
r = smc_lvl_from_atb(ctx, &ctx->atb_ulv.lvls[0], &tbl->ulv_lvl); |
r = smc_lvl_from_atb(ctx, &ctx->atb_ulv.lvls[0], &tbl->ulv_lvl); |
49 |
49 |
if (r == -SI_ERR) { |
if (r == -SI_ERR) { |
|
... |
... |
long smc_state_tbl_ulv_init(struct ctx *ctx, struct smc_state_tbl *tbl) |
68 |
68 |
#define CG_ULV_PARAM_DEFAULT 0x00040035 |
#define CG_ULV_PARAM_DEFAULT 0x00040035 |
69 |
69 |
void ulv_program(struct pci_dev *dev) |
void ulv_program(struct pci_dev *dev) |
70 |
70 |
{ |
{ |
71 |
|
LOG("ulv state program"); |
|
|
71 |
|
LOG("ultra low voltage state program"); |
72 |
72 |
|
|
73 |
73 |
LOG("CG_ULV_CTL=0x%08x", CG_ULV_CTL_DEFAULT); |
LOG("CG_ULV_CTL=0x%08x", CG_ULV_CTL_DEFAULT); |
74 |
74 |
LOG("CG_ULV_PARAM=0x%08x", CG_ULV_PARAM); |
LOG("CG_ULV_PARAM=0x%08x", CG_ULV_PARAM); |
|
... |
... |
void ulv_program(struct pci_dev *dev) |
80 |
80 |
#define ULV_VOLT_CHANGE_DELAY_DEFAULT 1687 |
#define ULV_VOLT_CHANGE_DELAY_DEFAULT 1687 |
81 |
81 |
void smc_sw_regs_ulv_init(struct ctx *ctx) |
void smc_sw_regs_ulv_init(struct ctx *ctx) |
82 |
82 |
{ |
{ |
83 |
|
LOG("ulv smc software registers init"); |
|
|
83 |
|
LOG("ultra low voltage smc software registers init"); |
84 |
84 |
|
|
85 |
85 |
smc_sw_wr32(ctx->dev, ULV_VOLT_CHANGE_DELAY_DEFAULT, |
smc_sw_wr32(ctx->dev, ULV_VOLT_CHANGE_DELAY_DEFAULT, |
86 |
86 |
SMC_SW_ULV_VOLT_CHANGE_DELAY); |
SMC_SW_ULV_VOLT_CHANGE_DELAY); |
|
... |
... |
void smc_sw_regs_ulv_init(struct ctx *ctx) |
88 |
88 |
SMC_SW_NON_ULV_PCIE_LINK_WIDTH); |
SMC_SW_NON_ULV_PCIE_LINK_WIDTH); |
89 |
89 |
} |
} |
90 |
90 |
|
|
91 |
|
#if 0 |
|
92 |
|
this following code may be used somewhere else |
|
93 |
|
static u8 mc_reg_set_find(struct ctx *ctx, u32 mem_clk) |
|
94 |
|
{ |
|
95 |
|
u8 mc_reg_set_idx; |
|
96 |
|
|
|
97 |
|
/* select a set of mc regs which can support the pwr lvl mem clk */ |
|
98 |
|
for (mc_reg_set_idx = 0; mc_reg_set_idx < ctx->atb_mc_reg_tbl.sets_n; |
|
99 |
|
++mc_reg_set_idx) { |
|
100 |
|
struct atb_mc_reg_set *mc_reg_set; |
|
101 |
|
|
|
102 |
|
mc_reg_set = &ctx->atb_mc_reg_tbl.sets[mc_reg_set_idx]; |
|
103 |
|
|
|
104 |
|
if (mem_clk <= mc_reg_set->mem_clk_max) |
|
105 |
|
break; |
|
106 |
|
} |
|
107 |
|
|
|
108 |
|
/* |
|
109 |
|
* Not found, then try the last one as a work around which should |
|
110 |
|
* accomodate the highest mem clk. The tbl seems to be sorted |
|
111 |
|
* from lowest mem clk to highest mem clk. |
|
112 |
|
*/ |
|
113 |
|
if (mc_reg_set_idx == ctx->atb_mc_reg_tbl.sets_n) |
|
114 |
|
--mc_reg_set_idx; /* we presume we have at least one set */ |
|
115 |
|
return mc_reg_set_idx; |
|
116 |
|
} |
|
117 |
|
#endif |
|
118 |
|
|
|
119 |
91 |
void smc_mc_reg_tbl_ulv_init(struct ctx *ctx, |
void smc_mc_reg_tbl_ulv_init(struct ctx *ctx, |
120 |
92 |
struct smc_mc_reg_tbl *smc_mc_reg_tbl) |
struct smc_mc_reg_tbl *smc_mc_reg_tbl) |
121 |
93 |
{ |
{ |
|
... |
... |
long smc_mc_arb_tbl_ulv_init(struct ctx *ctx, |
152 |
124 |
|
|
153 |
125 |
r = smc_mc_arb_tbl_set_compute(ctx, ulv_set, eng_clk, mem_clk); |
r = smc_mc_arb_tbl_set_compute(ctx, ulv_set, eng_clk, mem_clk); |
154 |
126 |
if (r == -SI_ERR) { |
if (r == -SI_ERR) { |
155 |
|
dev_err(&ctx->dev->dev, "dyn_pm:unable to init the memory controller arb register set for the ulv state\n"); |
|
|
127 |
|
dev_err(&ctx->dev->dev, "dyn_pm:unable to init the memory controller arb register set for the ultra low voltage state\n"); |
156 |
128 |
return -SI_ERR; |
return -SI_ERR; |
157 |
129 |
} |
} |
158 |
130 |
return 0; |
return 0; |