ppc_cbe_cpufreq_pervasive.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * pervasive backend for the cbe_cpufreq driver
  3. *
  4. * This driver makes use of the pervasive unit to
  5. * engage the desired frequency.
  6. *
  7. * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
  8. *
  9. * Author: Christian Krafft <krafft@de.ibm.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2, or (at your option)
  14. * any later version.
  15. *
  16. * This program is distributed 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 program; if not, write to the Free Software
  23. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24. */
  25. #include <linux/io.h>
  26. #include <linux/kernel.h>
  27. #include <linux/time.h>
  28. #include <asm/machdep.h>
  29. #include <asm/hw_irq.h>
  30. #include <asm/cell-regs.h>
  31. #include "ppc_cbe_cpufreq.h"
  32. /* to write to MIC register */
  33. static u64 MIC_Slow_Fast_Timer_table[] = {
  34. [0 ... 7] = 0x007fc00000000000ull,
  35. };
  36. /* more values for the MIC */
  37. static u64 MIC_Slow_Next_Timer_table[] = {
  38. 0x0000240000000000ull,
  39. 0x0000268000000000ull,
  40. 0x000029C000000000ull,
  41. 0x00002D0000000000ull,
  42. 0x0000300000000000ull,
  43. 0x0000334000000000ull,
  44. 0x000039C000000000ull,
  45. 0x00003FC000000000ull,
  46. };
  47. int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode)
  48. {
  49. struct cbe_pmd_regs __iomem *pmd_regs;
  50. struct cbe_mic_tm_regs __iomem *mic_tm_regs;
  51. unsigned long flags;
  52. u64 value;
  53. #ifdef DEBUG
  54. long time;
  55. #endif
  56. local_irq_save(flags);
  57. mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
  58. pmd_regs = cbe_get_cpu_pmd_regs(cpu);
  59. #ifdef DEBUG
  60. time = jiffies;
  61. #endif
  62. out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
  63. out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
  64. out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
  65. out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
  66. value = in_be64(&pmd_regs->pmcr);
  67. /* set bits to zero */
  68. value &= 0xFFFFFFFFFFFFFFF8ull;
  69. /* set bits to next pmode */
  70. value |= pmode;
  71. out_be64(&pmd_regs->pmcr, value);
  72. #ifdef DEBUG
  73. /* wait until new pmode appears in status register */
  74. value = in_be64(&pmd_regs->pmsr) & 0x07;
  75. while (value != pmode) {
  76. cpu_relax();
  77. value = in_be64(&pmd_regs->pmsr) & 0x07;
  78. }
  79. time = jiffies - time;
  80. time = jiffies_to_msecs(time);
  81. pr_debug("had to wait %lu ms for a transition using " \
  82. "pervasive unit\n", time);
  83. #endif
  84. local_irq_restore(flags);
  85. return 0;
  86. }
  87. int cbe_cpufreq_get_pmode(int cpu)
  88. {
  89. int ret;
  90. struct cbe_pmd_regs __iomem *pmd_regs;
  91. pmd_regs = cbe_get_cpu_pmd_regs(cpu);
  92. ret = in_be64(&pmd_regs->pmsr) & 0x07;
  93. return ret;
  94. }