mtm.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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/io.h>
  18. #include <linux/log2.h>
  19. #include <asm/arcregs.h>
  20. #include <plat/mtm.h>
  21. #include <plat/smp.h>
  22. #define MT_CTRL_HS_CNT 0xFF
  23. #define MT_CTRL_ST_CNT 0xF
  24. #define NPS_NUM_HW_THREADS 0x10
  25. static void mtm_init_nat(int cpu)
  26. {
  27. struct nps_host_reg_mtm_cfg mtm_cfg;
  28. struct nps_host_reg_aux_udmc udmc;
  29. int log_nat, nat = 0, i, t;
  30. /* Iterate core threads and update nat */
  31. for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
  32. nat += test_bit(t, cpumask_bits(cpu_possible_mask));
  33. log_nat = ilog2(nat);
  34. udmc.value = read_aux_reg(CTOP_AUX_UDMC);
  35. udmc.nat = log_nat;
  36. write_aux_reg(CTOP_AUX_UDMC, udmc.value);
  37. mtm_cfg.value = ioread32be(MTM_CFG(cpu));
  38. mtm_cfg.nat = log_nat;
  39. iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
  40. }
  41. static void mtm_init_thread(int cpu)
  42. {
  43. int i, tries = 5;
  44. struct nps_host_reg_thr_init thr_init;
  45. struct nps_host_reg_thr_init_sts thr_init_sts;
  46. /* Set thread init register */
  47. thr_init.value = 0;
  48. iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
  49. thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
  50. thr_init.str = 1;
  51. iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
  52. /* Poll till thread init is done */
  53. for (i = 0; i < tries; i++) {
  54. thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
  55. if (thr_init_sts.thr_id == thr_init.thr_id) {
  56. if (thr_init_sts.bsy)
  57. continue;
  58. else if (thr_init_sts.err)
  59. pr_warn("Failed to thread init cpu %u\n", cpu);
  60. break;
  61. }
  62. pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
  63. break;
  64. }
  65. if (i == tries)
  66. pr_warn("Got thread init timeout for cpu %u\n", cpu);
  67. }
  68. int mtm_enable_thread(int cpu)
  69. {
  70. struct nps_host_reg_mtm_cfg mtm_cfg;
  71. if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
  72. return 1;
  73. /* Enable thread in mtm */
  74. mtm_cfg.value = ioread32be(MTM_CFG(cpu));
  75. mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
  76. iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
  77. return 0;
  78. }
  79. void mtm_enable_core(unsigned int cpu)
  80. {
  81. int i;
  82. struct nps_host_reg_aux_mt_ctrl mt_ctrl;
  83. struct nps_host_reg_mtm_cfg mtm_cfg;
  84. if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
  85. return;
  86. /* Initialize Number of Active Threads */
  87. mtm_init_nat(cpu);
  88. /* Initialize mtm_cfg */
  89. mtm_cfg.value = ioread32be(MTM_CFG(cpu));
  90. mtm_cfg.ten = 1;
  91. iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
  92. /* Initialize all other threads in core */
  93. for (i = 1; i < NPS_NUM_HW_THREADS; i++)
  94. mtm_init_thread(cpu + i);
  95. /* Enable HW schedule, stall counter, mtm */
  96. mt_ctrl.value = 0;
  97. mt_ctrl.hsen = 1;
  98. mt_ctrl.hs_cnt = MT_CTRL_HS_CNT;
  99. mt_ctrl.sten = 1;
  100. mt_ctrl.st_cnt = MT_CTRL_ST_CNT;
  101. mt_ctrl.mten = 1;
  102. write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
  103. /*
  104. * HW scheduling mechanism will start working
  105. * Only after call to instruction "schd.rw".
  106. * cpu_relax() calls "schd.rw" instruction.
  107. */
  108. cpu_relax();
  109. }