ppc_cbe_cpufreq_pervasive.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * pervasive backend for the cbe_cpufreq driver
  4. *
  5. * This driver makes use of the pervasive unit to
  6. * engage the desired frequency.
  7. *
  8. * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
  9. *
  10. * Author: Christian Krafft <krafft@de.ibm.com>
  11. */
  12. #include <linux/io.h>
  13. #include <linux/kernel.h>
  14. #include <linux/time.h>
  15. #include <asm/machdep.h>
  16. #include <asm/hw_irq.h>
  17. #include <asm/cell-regs.h>
  18. #include "ppc_cbe_cpufreq.h"
  19. /* to write to MIC register */
  20. static u64 MIC_Slow_Fast_Timer_table[] = {
  21. [0 ... 7] = 0x007fc00000000000ull,
  22. };
  23. /* more values for the MIC */
  24. static u64 MIC_Slow_Next_Timer_table[] = {
  25. 0x0000240000000000ull,
  26. 0x0000268000000000ull,
  27. 0x000029C000000000ull,
  28. 0x00002D0000000000ull,
  29. 0x0000300000000000ull,
  30. 0x0000334000000000ull,
  31. 0x000039C000000000ull,
  32. 0x00003FC000000000ull,
  33. };
  34. int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode)
  35. {
  36. struct cbe_pmd_regs __iomem *pmd_regs;
  37. struct cbe_mic_tm_regs __iomem *mic_tm_regs;
  38. unsigned long flags;
  39. u64 value;
  40. #ifdef DEBUG
  41. long time;
  42. #endif
  43. local_irq_save(flags);
  44. mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
  45. pmd_regs = cbe_get_cpu_pmd_regs(cpu);
  46. #ifdef DEBUG
  47. time = jiffies;
  48. #endif
  49. out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
  50. out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
  51. out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
  52. out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
  53. value = in_be64(&pmd_regs->pmcr);
  54. /* set bits to zero */
  55. value &= 0xFFFFFFFFFFFFFFF8ull;
  56. /* set bits to next pmode */
  57. value |= pmode;
  58. out_be64(&pmd_regs->pmcr, value);
  59. #ifdef DEBUG
  60. /* wait until new pmode appears in status register */
  61. value = in_be64(&pmd_regs->pmsr) & 0x07;
  62. while (value != pmode) {
  63. cpu_relax();
  64. value = in_be64(&pmd_regs->pmsr) & 0x07;
  65. }
  66. time = jiffies - time;
  67. time = jiffies_to_msecs(time);
  68. pr_debug("had to wait %lu ms for a transition using " \
  69. "pervasive unit\n", time);
  70. #endif
  71. local_irq_restore(flags);
  72. return 0;
  73. }
  74. int cbe_cpufreq_get_pmode(int cpu)
  75. {
  76. int ret;
  77. struct cbe_pmd_regs __iomem *pmd_regs;
  78. pmd_regs = cbe_get_cpu_pmd_regs(cpu);
  79. ret = in_be64(&pmd_regs->pmsr) & 0x07;
  80. return ret;
  81. }