cr_pll.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Copyright (c) Intel Corp. 2007.
  3. * All Rights Reserved.
  4. *
  5. * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
  6. * develop this driver.
  7. *
  8. * This file is part of the Carillo Ranch video subsystem driver.
  9. * The Carillo Ranch video subsystem driver is free software;
  10. * you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * The Carillo Ranch video subsystem driver is distributed
  16. * in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this driver; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Authors:
  26. * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
  27. * Alan Hourihane <alanh-at-tungstengraphics-dot-com>
  28. */
  29. #include <linux/module.h>
  30. #include <linux/kernel.h>
  31. #include <linux/pci.h>
  32. #include <linux/errno.h>
  33. #include <linux/fb.h>
  34. #include "vermilion.h"
  35. /* The PLL Clock register sits on Host bridge */
  36. #define CRVML_DEVICE_MCH 0x5001
  37. #define CRVML_REG_MCHBAR 0x44
  38. #define CRVML_REG_MCHEN 0x54
  39. #define CRVML_MCHEN_BIT (1 << 28)
  40. #define CRVML_MCHMAP_SIZE 4096
  41. #define CRVML_REG_CLOCK 0xc3c
  42. #define CRVML_CLOCK_SHIFT 8
  43. #define CRVML_CLOCK_MASK 0x00000f00
  44. static struct pci_dev *mch_dev;
  45. static u32 mch_bar;
  46. static void __iomem *mch_regs_base;
  47. static u32 saved_clock;
  48. static const unsigned crvml_clocks[] = {
  49. 6750,
  50. 13500,
  51. 27000,
  52. 29700,
  53. 37125,
  54. 54000,
  55. 59400,
  56. 74250,
  57. 120000
  58. /*
  59. * There are more clocks, but they are disabled on the CR board.
  60. */
  61. };
  62. static const u32 crvml_clock_bits[] = {
  63. 0x0a,
  64. 0x09,
  65. 0x08,
  66. 0x07,
  67. 0x06,
  68. 0x05,
  69. 0x04,
  70. 0x03,
  71. 0x0b
  72. };
  73. static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks);
  74. static int crvml_sys_restore(struct vml_sys *sys)
  75. {
  76. void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
  77. iowrite32(saved_clock, clock_reg);
  78. ioread32(clock_reg);
  79. return 0;
  80. }
  81. static int crvml_sys_save(struct vml_sys *sys)
  82. {
  83. void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
  84. saved_clock = ioread32(clock_reg);
  85. return 0;
  86. }
  87. static int crvml_nearest_index(const struct vml_sys *sys, int clock)
  88. {
  89. int i;
  90. int cur_index = 0;
  91. int cur_diff;
  92. int diff;
  93. cur_diff = clock - crvml_clocks[0];
  94. cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
  95. for (i = 1; i < crvml_num_clocks; ++i) {
  96. diff = clock - crvml_clocks[i];
  97. diff = (diff < 0) ? -diff : diff;
  98. if (diff < cur_diff) {
  99. cur_index = i;
  100. cur_diff = diff;
  101. }
  102. }
  103. return cur_index;
  104. }
  105. static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
  106. {
  107. return crvml_clocks[crvml_nearest_index(sys, clock)];
  108. }
  109. static int crvml_set_clock(struct vml_sys *sys, int clock)
  110. {
  111. void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
  112. int index;
  113. u32 clock_val;
  114. index = crvml_nearest_index(sys, clock);
  115. if (crvml_clocks[index] != clock)
  116. return -EINVAL;
  117. clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
  118. clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
  119. iowrite32(clock_val, clock_reg);
  120. ioread32(clock_reg);
  121. return 0;
  122. }
  123. static struct vml_sys cr_pll_ops = {
  124. .name = "Carillo Ranch",
  125. .save = crvml_sys_save,
  126. .restore = crvml_sys_restore,
  127. .set_clock = crvml_set_clock,
  128. .nearest_clock = crvml_nearest_clock,
  129. };
  130. static int __init cr_pll_init(void)
  131. {
  132. int err;
  133. u32 dev_en;
  134. mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
  135. CRVML_DEVICE_MCH, NULL);
  136. if (!mch_dev) {
  137. printk(KERN_ERR
  138. "Could not find Carillo Ranch MCH device.\n");
  139. return -ENODEV;
  140. }
  141. pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en);
  142. if (!(dev_en & CRVML_MCHEN_BIT)) {
  143. printk(KERN_ERR
  144. "Carillo Ranch MCH device was not enabled.\n");
  145. pci_dev_put(mch_dev);
  146. return -ENODEV;
  147. }
  148. pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR,
  149. &mch_bar);
  150. mch_regs_base =
  151. ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE);
  152. if (!mch_regs_base) {
  153. printk(KERN_ERR
  154. "Carillo Ranch MCH device was not enabled.\n");
  155. pci_dev_put(mch_dev);
  156. return -ENODEV;
  157. }
  158. err = vmlfb_register_subsys(&cr_pll_ops);
  159. if (err) {
  160. printk(KERN_ERR
  161. "Carillo Ranch failed to initialize vml_sys.\n");
  162. pci_dev_put(mch_dev);
  163. return err;
  164. }
  165. return 0;
  166. }
  167. static void __exit cr_pll_exit(void)
  168. {
  169. vmlfb_unregister_subsys(&cr_pll_ops);
  170. iounmap(mch_regs_base);
  171. pci_dev_put(mch_dev);
  172. }
  173. module_init(cr_pll_init);
  174. module_exit(cr_pll_exit);
  175. MODULE_AUTHOR("Tungsten Graphics Inc.");
  176. MODULE_DESCRIPTION("Carillo Ranch PLL Driver");
  177. MODULE_LICENSE("GPL");