diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_mclk.c | 46 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_mclk.h | 13 |
2 files changed, 41 insertions, 18 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_mclk.c b/drivers/gpu/nvgpu/clk/clk_mclk.c index 6ad6c054..06ff9082 100644 --- a/drivers/gpu/nvgpu/clk/clk_mclk.c +++ b/drivers/gpu/nvgpu/clk/clk_mclk.c | |||
@@ -2182,12 +2182,16 @@ int clk_mclkseq_init_mclk_gddr5(struct gk20a *g) | |||
2182 | { | 2182 | { |
2183 | struct clk_mclk_state *mclk; | 2183 | struct clk_mclk_state *mclk; |
2184 | int status; | 2184 | int status; |
2185 | struct clk_set_info *p5_info; | ||
2186 | struct clk_set_info *p0_info; | ||
2187 | |||
2185 | 2188 | ||
2186 | gk20a_dbg_fn(""); | 2189 | gk20a_dbg_fn(""); |
2187 | 2190 | ||
2188 | mclk = &g->clk_pmu.clk_mclk; | 2191 | mclk = &g->clk_pmu.clk_mclk; |
2189 | 2192 | ||
2190 | mutex_init(&mclk->mclk_mutex); | 2193 | mutex_init(&mclk->mclk_lock); |
2194 | mutex_init(&mclk->data_lock); | ||
2191 | 2195 | ||
2192 | /* FBPA gain WAR */ | 2196 | /* FBPA gain WAR */ |
2193 | gk20a_writel(g, fb_fbpa_fbio_iref_byte_rx_ctrl_r(), 0x22222222); | 2197 | gk20a_writel(g, fb_fbpa_fbio_iref_byte_rx_ctrl_r(), 0x22222222); |
@@ -2202,7 +2206,23 @@ int clk_mclkseq_init_mclk_gddr5(struct gk20a *g) | |||
2202 | /* Load RAM pattern */ | 2206 | /* Load RAM pattern */ |
2203 | mclk_memory_load_training_pattern(g); | 2207 | mclk_memory_load_training_pattern(g); |
2204 | 2208 | ||
2205 | mclk->vreg_buf = kzalloc((sizeof(u32) * VREG_COUNT), GFP_KERNEL); | 2209 | p5_info = pstate_get_clk_set_info(g, |
2210 | CTRL_PERF_PSTATE_P5, clkwhich_mclk); | ||
2211 | if (!p5_info) | ||
2212 | return -EINVAL; | ||
2213 | |||
2214 | p0_info = pstate_get_clk_set_info(g, | ||
2215 | CTRL_PERF_PSTATE_P0, clkwhich_mclk); | ||
2216 | if (!p0_info) | ||
2217 | return -EINVAL; | ||
2218 | |||
2219 | |||
2220 | mclk->p5_min = p5_info->min_mhz; | ||
2221 | mclk->p0_min = p0_info->min_mhz; | ||
2222 | |||
2223 | |||
2224 | mclk->vreg_buf = kcalloc(VREG_COUNT, | ||
2225 | sizeof(u32), GFP_KERNEL); | ||
2206 | if (!mclk->vreg_buf) { | 2226 | if (!mclk->vreg_buf) { |
2207 | gk20a_err(dev_from_gk20a(g), | 2227 | gk20a_err(dev_from_gk20a(g), |
2208 | "unable to allocate memory for VREG"); | 2228 | "unable to allocate memory for VREG"); |
@@ -2242,15 +2262,13 @@ int clk_mclkseq_change_mclk_gddr5(struct gk20a *g, u16 val) | |||
2242 | 2262 | ||
2243 | mclk = &g->clk_pmu.clk_mclk; | 2263 | mclk = &g->clk_pmu.clk_mclk; |
2244 | 2264 | ||
2245 | mutex_lock(&mclk->mclk_mutex); | 2265 | mutex_lock(&mclk->mclk_lock); |
2246 | 2266 | ||
2247 | if (!mclk->init) | 2267 | if (!mclk->init) |
2248 | goto exit_status; | 2268 | goto exit_status; |
2249 | 2269 | ||
2250 | /* TODO thia should be done according to VBIOS tables */ | 2270 | speed = (val < mclk->p5_min) ? gk20a_mclk_low_speed : |
2251 | 2271 | (val < mclk->p0_min) ? gk20a_mclk_mid_speed : | |
2252 | speed = (val <= MCLK_LOW_SPEED_LIMIT) ? gk20a_mclk_low_speed : | ||
2253 | (val <= MCLK_MID_SPEED_LIMIT) ? gk20a_mclk_mid_speed : | ||
2254 | gk20a_mclk_high_speed; | 2272 | gk20a_mclk_high_speed; |
2255 | 2273 | ||
2256 | 2274 | ||
@@ -2341,7 +2359,7 @@ int clk_mclkseq_change_mclk_gddr5(struct gk20a *g, u16 val) | |||
2341 | &seq_completion_status, 0); | 2359 | &seq_completion_status, 0); |
2342 | if (seq_completion_status != 0) { | 2360 | if (seq_completion_status != 0) { |
2343 | gk20a_err(dev_from_gk20a(g), | 2361 | gk20a_err(dev_from_gk20a(g), |
2344 | "seq_scrip update failed"); | 2362 | "seq_script update failed"); |
2345 | status = -EBUSY; | 2363 | status = -EBUSY; |
2346 | goto exit_status; | 2364 | goto exit_status; |
2347 | } | 2365 | } |
@@ -2350,6 +2368,8 @@ int clk_mclkseq_change_mclk_gddr5(struct gk20a *g, u16 val) | |||
2350 | 2368 | ||
2351 | #ifdef CONFIG_DEBUG_FS | 2369 | #ifdef CONFIG_DEBUG_FS |
2352 | g->ops.read_ptimer(g, &t1); | 2370 | g->ops.read_ptimer(g, &t1); |
2371 | |||
2372 | mutex_lock(&mclk->data_lock); | ||
2353 | mclk->switch_num++; | 2373 | mclk->switch_num++; |
2354 | 2374 | ||
2355 | if (mclk->switch_num == 1) { | 2375 | if (mclk->switch_num == 1) { |
@@ -2372,10 +2392,11 @@ int clk_mclkseq_change_mclk_gddr5(struct gk20a *g, u16 val) | |||
2372 | mclk->switch_std += | 2392 | mclk->switch_std += |
2373 | (curr - mclk->switch_avg) * (curr - prev_avg); | 2393 | (curr - mclk->switch_avg) * (curr - prev_avg); |
2374 | } | 2394 | } |
2395 | mutex_unlock(&mclk->data_lock); | ||
2375 | #endif | 2396 | #endif |
2376 | exit_status: | 2397 | exit_status: |
2377 | 2398 | ||
2378 | mutex_unlock(&mclk->mclk_mutex); | 2399 | mutex_unlock(&mclk->mclk_lock); |
2379 | return status; | 2400 | return status; |
2380 | } | 2401 | } |
2381 | 2402 | ||
@@ -2387,6 +2408,9 @@ static int mclk_debug_speed_set(void *data, u64 val) | |||
2387 | 2408 | ||
2388 | mclk = &g->clk_pmu.clk_mclk; | 2409 | mclk = &g->clk_pmu.clk_mclk; |
2389 | 2410 | ||
2411 | /* This is problematic because it can interrupt the arbiter | ||
2412 | * and send it to sleep. we need to consider removing this | ||
2413 | */ | ||
2390 | if (mclk->change) | 2414 | if (mclk->change) |
2391 | return mclk->change(g, (u16) val); | 2415 | return mclk->change(g, (u16) val); |
2392 | return 0; | 2416 | return 0; |
@@ -2410,13 +2434,13 @@ static int mclk_switch_stats_show(struct seq_file *s, void *unused) | |||
2410 | mclk = &g->clk_pmu.clk_mclk; | 2434 | mclk = &g->clk_pmu.clk_mclk; |
2411 | 2435 | ||
2412 | /* Make copy of structure to reduce time with lock held */ | 2436 | /* Make copy of structure to reduce time with lock held */ |
2413 | mutex_lock(&mclk->mclk_mutex); | 2437 | mutex_lock(&mclk->data_lock); |
2414 | std = mclk->switch_std; | 2438 | std = mclk->switch_std; |
2415 | avg = mclk->switch_avg; | 2439 | avg = mclk->switch_avg; |
2416 | max = mclk->switch_max; | 2440 | max = mclk->switch_max; |
2417 | min = mclk->switch_min; | 2441 | min = mclk->switch_min; |
2418 | num = mclk->switch_num; | 2442 | num = mclk->switch_num; |
2419 | mutex_unlock(&mclk->mclk_mutex); | 2443 | mutex_unlock(&mclk->data_lock); |
2420 | 2444 | ||
2421 | tmp = std; | 2445 | tmp = std; |
2422 | do_div(tmp, num); | 2446 | do_div(tmp, num); |
diff --git a/drivers/gpu/nvgpu/clk/clk_mclk.h b/drivers/gpu/nvgpu/clk/clk_mclk.h index e3e6c1ee..cb7f0de0 100644 --- a/drivers/gpu/nvgpu/clk/clk_mclk.h +++ b/drivers/gpu/nvgpu/clk/clk_mclk.h | |||
@@ -22,15 +22,14 @@ enum gk20a_mclk_speed { | |||
22 | gk20a_mclk_high_speed, | 22 | gk20a_mclk_high_speed, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | #define MCLK_LOW_SPEED_LIMIT 405 | ||
26 | #define MCLK_MID_SPEED_LIMIT 810 | ||
27 | #define MCLK_HIGH_SPEED_LIMIT 3003 | ||
28 | |||
29 | #define DEFAULT_BOOT_MCLK_SPEED MCLK_HIGH_SPEED_LIMIT | ||
30 | |||
31 | struct clk_mclk_state { | 25 | struct clk_mclk_state { |
32 | enum gk20a_mclk_speed speed; | 26 | enum gk20a_mclk_speed speed; |
33 | struct mutex mclk_mutex; | 27 | struct mutex mclk_lock; |
28 | struct mutex data_lock; | ||
29 | |||
30 | u16 p5_min; | ||
31 | u16 p0_min; | ||
32 | |||
34 | void *vreg_buf; | 33 | void *vreg_buf; |
35 | bool init; | 34 | bool init; |
36 | 35 | ||