op_model_bf533.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * File: arch/blackfin/oprofile/op_model_bf533.c
  3. * Based on:
  4. * Author: Anton Blanchard <anton@au.ibm.com>
  5. *
  6. * Created:
  7. * Description:
  8. *
  9. * Modified:
  10. * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
  11. * Copyright 2004-2006 Analog Devices Inc.
  12. *
  13. * Bugs: Enter bugs at http://blackfin.uclinux.org/
  14. *
  15. * This program is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 2 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, see the file COPYING, or write
  27. * to the Free Software Foundation, Inc.,
  28. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  29. */
  30. #include <linux/oprofile.h>
  31. #include <linux/init.h>
  32. #include <linux/smp.h>
  33. #include <linux/interrupt.h>
  34. #include <linux/ptrace.h>
  35. #include <linux/irq.h>
  36. #include <linux/io.h>
  37. #include <asm/system.h>
  38. #include <asm/processor.h>
  39. #include <asm/blackfin.h>
  40. #include "op_blackfin.h"
  41. #define PM_ENABLE 0x01;
  42. #define PM_CTL1_ENABLE 0x18
  43. #define PM_CTL0_ENABLE 0xC000
  44. #define COUNT_EDGE_ONLY 0x3000000
  45. static int oprofile_running;
  46. static unsigned curr_pfctl, curr_count[2];
  47. static int bfin533_reg_setup(struct op_counter_config *ctr)
  48. {
  49. unsigned int pfctl = ctr_read();
  50. unsigned int count[2];
  51. /* set Blackfin perf monitor regs with ctr */
  52. if (ctr[0].enabled) {
  53. pfctl |= (PM_CTL0_ENABLE | ((char)ctr[0].event << 5));
  54. count[0] = 0xFFFFFFFF - ctr[0].count;
  55. curr_count[0] = count[0];
  56. }
  57. if (ctr[1].enabled) {
  58. pfctl |= (PM_CTL1_ENABLE | ((char)ctr[1].event << 16));
  59. count[1] = 0xFFFFFFFF - ctr[1].count;
  60. curr_count[1] = count[1];
  61. }
  62. pr_debug("ctr[0].enabled=%d,ctr[1].enabled=%d,ctr[0].event<<5=0x%x,ctr[1].event<<16=0x%x\n", ctr[0].enabled, ctr[1].enabled, ctr[0].event << 5, ctr[1].event << 16);
  63. pfctl |= COUNT_EDGE_ONLY;
  64. curr_pfctl = pfctl;
  65. pr_debug("write 0x%x to pfctl\n", pfctl);
  66. ctr_write(pfctl);
  67. count_write(count);
  68. return 0;
  69. }
  70. static int bfin533_start(struct op_counter_config *ctr)
  71. {
  72. unsigned int pfctl = ctr_read();
  73. pfctl |= PM_ENABLE;
  74. curr_pfctl = pfctl;
  75. ctr_write(pfctl);
  76. oprofile_running = 1;
  77. pr_debug("start oprofile counter \n");
  78. return 0;
  79. }
  80. static void bfin533_stop(void)
  81. {
  82. int pfctl;
  83. pfctl = ctr_read();
  84. pfctl &= ~PM_ENABLE;
  85. /* freeze counters */
  86. ctr_write(pfctl);
  87. oprofile_running = 0;
  88. pr_debug("stop oprofile counter \n");
  89. }
  90. static int get_kernel(void)
  91. {
  92. int ipend, is_kernel;
  93. ipend = bfin_read_IPEND();
  94. /* test bit 15 */
  95. is_kernel = ((ipend & 0x8000) != 0);
  96. return is_kernel;
  97. }
  98. int pm_overflow_handler(int irq, struct pt_regs *regs)
  99. {
  100. int is_kernel;
  101. int i, cpu;
  102. unsigned int pc, pfctl;
  103. unsigned int count[2];
  104. pr_debug("get interrupt in %s\n", __FUNCTION__);
  105. if (oprofile_running == 0) {
  106. pr_debug("error: entering interrupt when oprofile is stopped.\n\r");
  107. return -1;
  108. }
  109. is_kernel = get_kernel();
  110. cpu = smp_processor_id();
  111. pc = regs->pc;
  112. pfctl = ctr_read();
  113. /* read the two event counter regs */
  114. count_read(count);
  115. /* if the counter overflows, add sample to oprofile buffer */
  116. for (i = 0; i < 2; ++i) {
  117. if (oprofile_running) {
  118. oprofile_add_sample(regs, i);
  119. }
  120. }
  121. /* reset the perfmon counter */
  122. ctr_write(curr_pfctl);
  123. count_write(curr_count);
  124. return 0;
  125. }
  126. struct op_bfin533_model op_model_bfin533 = {
  127. .reg_setup = bfin533_reg_setup,
  128. .start = bfin533_start,
  129. .stop = bfin533_stop,
  130. .num_counters = 2,
  131. .name = "blackfin/bf533"
  132. };