mtm.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright(c) 2015 EZchip Technologies.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms and conditions of the GNU General Public License,
  6. * version 2, as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. * more details.
  12. *
  13. * The full GNU General Public License is included in this distribution in
  14. * the file called "COPYING".
  15. */
  16. #include <linux/smp.h>
  17. #include <linux/init.h>
  18. #include <linux/kernel.h>
  19. #include <linux/io.h>
  20. #include <linux/log2.h>
  21. #include <asm/arcregs.h>
  22. #include <plat/mtm.h>
  23. #include <plat/smp.h>
  24. #define MT_HS_CNT_MIN 0x01
  25. #define MT_HS_CNT_MAX 0xFF
  26. #define MT_CTRL_ST_CNT 0xF
  27. #define NPS_NUM_HW_THREADS 0x10
  28. static int mtm_hs_ctr = MT_HS_CNT_MAX;
  29. #ifdef CONFIG_EZNPS_MEM_ERROR_ALIGN
  30. int do_memory_error(unsigned long address, struct pt_regs *regs)
  31. {
  32. die("Invalid Mem Access", regs, address);
  33. return 1;
  34. }
  35. #endif
  36. static void mtm_init_nat(int cpu)
  37. {
  38. struct nps_host_reg_mtm_cfg mtm_cfg;
  39. struct nps_host_reg_aux_udmc udmc;
  40. int log_nat, nat = 0, i, t;
  41. /* Iterate core threads and update nat */
  42. for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
  43. nat += test_bit(t, cpumask_bits(cpu_possible_mask));
  44. log_nat = ilog2(nat);
  45. udmc.value = read_aux_reg(CTOP_AUX_UDMC);
  46. udmc.nat = log_nat;
  47. write_aux_reg(CTOP_AUX_UDMC, udmc.value);
  48. mtm_cfg.value = ioread32be(MTM_CFG(cpu));
  49. mtm_cfg.nat = log_nat;
  50. iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
  51. }
  52. static void mtm_init_thread(int cpu)
  53. {
  54. int i, tries = 5;
  55. struct nps_host_reg_thr_init thr_init;
  56. struct nps_host_reg_thr_init_sts thr_init_sts;
  57. /* Set thread init register */
  58. thr_init.value = 0;
  59. iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
  60. thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
  61. thr_init.str = 1;
  62. iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
  63. /* Poll till thread init is done */
  64. for (i = 0; i < tries; i++) {
  65. thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
  66. if (thr_init_sts.thr_id == thr_init.thr_id) {
  67. if (thr_init_sts.bsy)
  68. continue;
  69. else if (thr_init_sts.err)
  70. pr_warn("Failed to thread init cpu %u\n", cpu);
  71. break;
  72. }
  73. pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
  74. break;
  75. }
  76. if (i == tries)
  77. pr_warn("Got thread init timeout for cpu %u\n", cpu);
  78. }
  79. int mtm_enable_thread(int cpu)
  80. {
  81. struct nps_host_reg_mtm_cfg mtm_cfg;
  82. if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
  83. return 1;
  84. /* Enable thread in mtm */
  85. mtm_cfg.value = ioread32be(MTM_CFG(cpu));
  86. mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
  87. iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
  88. return 0;
  89. }
  90. void mtm_enable_core(unsigned int cpu)
  91. {
  92. int i;
  93. struct nps_host_reg_aux_mt_ctrl mt_ctrl;
  94. struct nps_host_reg_mtm_cfg mtm_cfg;
  95. struct nps_host_reg_aux_dpc dpc;
  96. /*
  97. * Initializing dpc register in each CPU.
  98. * Overwriting the init value of the DPC
  99. * register so that CMEM and FMT virtual address
  100. * spaces are accessible, and Data Plane HW
  101. * facilities are enabled.
  102. */
  103. dpc.ien = 1;
  104. dpc.men = 1;
  105. write_aux_reg(CTOP_AUX_DPC, dpc.value);
  106. if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
  107. return;
  108. /* Initialize Number of Active Threads */
  109. mtm_init_nat(cpu);
  110. /* Initialize mtm_cfg */
  111. mtm_cfg.value = ioread32be(MTM_CFG(cpu));
  112. mtm_cfg.ten = 1;
  113. iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
  114. /* Initialize all other threads in core */
  115. for (i = 1; i < NPS_NUM_HW_THREADS; i++)
  116. mtm_init_thread(cpu + i);
  117. /* Enable HW schedule, stall counter, mtm */
  118. mt_ctrl.value = 0;
  119. mt_ctrl.hsen = 1;
  120. mt_ctrl.hs_cnt = mtm_hs_ctr;
  121. mt_ctrl.mten = 1;
  122. write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
  123. /*
  124. * HW scheduling mechanism will start working
  125. * Only after call to instruction "schd.rw".
  126. * cpu_relax() calls "schd.rw" instruction.
  127. */
  128. cpu_relax();
  129. }
  130. /* Verify and set the value of the mtm hs counter */
  131. static int __init set_mtm_hs_ctr(char *ctr_str)
  132. {
  133. int hs_ctr;
  134. int ret;
  135. ret = kstrtoint(ctr_str, 0, &hs_ctr);
  136. if (ret || hs_ctr > MT_HS_CNT_MAX || hs_ctr < MT_HS_CNT_MIN) {
  137. pr_err("** Invalid @nps_mtm_hs_ctr [%d] needs to be [%d:%d] (incl)\n",
  138. hs_ctr, MT_HS_CNT_MIN, MT_HS_CNT_MAX);
  139. return -EINVAL;
  140. }
  141. mtm_hs_ctr = hs_ctr;
  142. return 0;
  143. }
  144. early_param("nps_mtm_hs_ctr", set_mtm_hs_ctr);