diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index d21d0527..db77d40f 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -2227,18 +2227,45 @@ gk20a_request_firmware(struct gk20a *g, const char *fw_name) | |||
2227 | return fw; | 2227 | return fw; |
2228 | } | 2228 | } |
2229 | 2229 | ||
2230 | 2230 | int gk20a_read_ptimer(struct gk20a *g, u64 *value) | |
2231 | u64 gk20a_read_ptimer(struct gk20a *g) | ||
2232 | { | 2231 | { |
2233 | u32 time_hi0 = gk20a_readl(g, timer_time_1_r()); | 2232 | const unsigned int max_iterations = 3; |
2234 | u32 time_lo = gk20a_readl(g, timer_time_0_r()); | 2233 | unsigned int i = 0; |
2235 | u32 time_hi1 = gk20a_readl(g, timer_time_1_r()); | 2234 | u32 gpu_timestamp_hi_prev = 0; |
2236 | u32 time_hi = (time_lo & (1L << 31)) ? time_hi0 : time_hi1; | ||
2237 | u64 time = ((u64)time_hi << 32) | time_lo; | ||
2238 | 2235 | ||
2239 | return time; | 2236 | if (!value) |
2240 | } | 2237 | return -EINVAL; |
2238 | |||
2239 | /* Note. The GPU nanosecond timer consists of two 32-bit | ||
2240 | * registers (high & low). To detect a possible low register | ||
2241 | * wrap-around between the reads, we need to read the high | ||
2242 | * register before and after low. The wraparound happens | ||
2243 | * approximately once per 4 secs. */ | ||
2244 | |||
2245 | /* get initial gpu_timestamp_hi value */ | ||
2246 | gpu_timestamp_hi_prev = gk20a_readl(g, timer_time_1_r()); | ||
2247 | |||
2248 | for (i = 0; i < max_iterations; ++i) { | ||
2249 | u32 gpu_timestamp_hi = 0; | ||
2250 | u32 gpu_timestamp_lo = 0; | ||
2251 | |||
2252 | gpu_timestamp_lo = gk20a_readl(g, timer_time_0_r()); | ||
2253 | gpu_timestamp_hi = gk20a_readl(g, timer_time_1_r()); | ||
2241 | 2254 | ||
2255 | if (gpu_timestamp_hi == gpu_timestamp_hi_prev) { | ||
2256 | *value = (((u64)gpu_timestamp_hi) << 32) | | ||
2257 | gpu_timestamp_lo; | ||
2258 | return 0; | ||
2259 | } | ||
2260 | |||
2261 | /* wrap-around detected, retry */ | ||
2262 | gpu_timestamp_hi_prev = gpu_timestamp_hi; | ||
2263 | } | ||
2264 | |||
2265 | /* too many iterations, bail out */ | ||
2266 | gk20a_err(dev_from_gk20a(g), "failed to read ptimer"); | ||
2267 | return -EBUSY; | ||
2268 | } | ||
2242 | 2269 | ||
2243 | MODULE_LICENSE("GPL v2"); | 2270 | MODULE_LICENSE("GPL v2"); |
2244 | module_init(gk20a_init); | 2271 | module_init(gk20a_init); |