nv04_timer.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include "drmP.h"
  2. #include "drm.h"
  3. #include "nouveau_drv.h"
  4. #include "nouveau_drm.h"
  5. #include "nouveau_hw.h"
  6. int
  7. nv04_timer_init(struct drm_device *dev)
  8. {
  9. struct drm_nouveau_private *dev_priv = dev->dev_private;
  10. u32 m, n, d;
  11. nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000);
  12. nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF);
  13. /* aim for 31.25MHz, which gives us nanosecond timestamps */
  14. d = 1000000 / 32;
  15. /* determine base clock for timer source */
  16. if (dev_priv->chipset < 0x40) {
  17. n = nouveau_hw_get_clock(dev, PLL_CORE);
  18. } else
  19. if (dev_priv->chipset == 0x40) {
  20. /*XXX: figure this out */
  21. n = 0;
  22. } else {
  23. n = dev_priv->crystal;
  24. m = 1;
  25. while (n < (d * 2)) {
  26. n += (n / m);
  27. m++;
  28. }
  29. nv_wr32(dev, 0x009220, m - 1);
  30. }
  31. if (!n) {
  32. NV_WARN(dev, "PTIMER: unknown input clock freq\n");
  33. if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
  34. !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
  35. nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1);
  36. nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1);
  37. }
  38. return 0;
  39. }
  40. /* reduce ratio to acceptable values */
  41. while (((n % 5) == 0) && ((d % 5) == 0)) {
  42. n /= 5;
  43. d /= 5;
  44. }
  45. while (((n % 2) == 0) && ((d % 2) == 0)) {
  46. n /= 2;
  47. d /= 2;
  48. }
  49. while (n > 0xffff || d > 0xffff) {
  50. n >>= 1;
  51. d >>= 1;
  52. }
  53. nv_wr32(dev, NV04_PTIMER_NUMERATOR, n);
  54. nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d);
  55. return 0;
  56. }
  57. u64
  58. nv04_timer_read(struct drm_device *dev)
  59. {
  60. u32 hi, lo;
  61. do {
  62. hi = nv_rd32(dev, NV04_PTIMER_TIME_1);
  63. lo = nv_rd32(dev, NV04_PTIMER_TIME_0);
  64. } while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1));
  65. return ((u64)hi << 32 | lo);
  66. }
  67. void
  68. nv04_timer_takedown(struct drm_device *dev)
  69. {
  70. }