seq_exec.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) Marvell International Ltd. and its affiliates
  4. */
  5. #include <common.h>
  6. #include <spl.h>
  7. #include <asm/io.h>
  8. #include <asm/arch/cpu.h>
  9. #include <asm/arch/soc.h>
  10. #include "seq_exec.h"
  11. #include "high_speed_env_spec.h"
  12. #include "../../../drivers/ddr/marvell/a38x/ddr3_init.h"
  13. #if defined(MV_DEBUG_INIT_FULL) || defined(MV_DEBUG)
  14. #define DB(x) x
  15. #else
  16. #define DB(x)
  17. #endif
  18. /* Array for mapping the operation (write, poll or delay) functions */
  19. op_execute_func_ptr op_execute_func_arr[] = {
  20. write_op_execute,
  21. delay_op_execute,
  22. poll_op_execute
  23. };
  24. int write_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
  25. {
  26. u32 unit_base_reg, unit_offset, data, mask, reg_data, reg_addr;
  27. /* Getting write op params from the input parameter */
  28. data = params->data[data_arr_idx];
  29. mask = params->mask;
  30. /* an empty operation */
  31. if (data == NO_DATA)
  32. return MV_OK;
  33. /* get updated base address since it can be different between Serdes */
  34. CHECK_STATUS(hws_get_ext_base_addr(serdes_num, params->unit_base_reg,
  35. params->unit_offset,
  36. &unit_base_reg, &unit_offset));
  37. /* Address calculation */
  38. reg_addr = unit_base_reg + unit_offset * serdes_num;
  39. #ifdef SEQ_DEBUG
  40. printf("Write: 0x%x: 0x%x (mask 0x%x) - ", reg_addr, data, mask);
  41. #endif
  42. /* Reading old value */
  43. reg_data = reg_read(reg_addr);
  44. reg_data &= (~mask);
  45. /* Writing new data */
  46. data &= mask;
  47. reg_data |= data;
  48. reg_write(reg_addr, reg_data);
  49. #ifdef SEQ_DEBUG
  50. printf(" - 0x%x\n", reg_data);
  51. #endif
  52. return MV_OK;
  53. }
  54. int delay_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
  55. {
  56. u32 delay;
  57. /* Getting delay op params from the input parameter */
  58. delay = params->wait_time;
  59. #ifdef SEQ_DEBUG
  60. printf("Delay: %d\n", delay);
  61. #endif
  62. mdelay(delay);
  63. return MV_OK;
  64. }
  65. int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
  66. {
  67. u32 unit_base_reg, unit_offset, data, mask, num_of_loops, wait_time;
  68. u32 poll_counter = 0;
  69. u32 reg_addr, reg_data;
  70. /* Getting poll op params from the input parameter */
  71. data = params->data[data_arr_idx];
  72. mask = params->mask;
  73. num_of_loops = params->num_of_loops;
  74. wait_time = params->wait_time;
  75. /* an empty operation */
  76. if (data == NO_DATA)
  77. return MV_OK;
  78. /* get updated base address since it can be different between Serdes */
  79. CHECK_STATUS(hws_get_ext_base_addr(serdes_num, params->unit_base_reg,
  80. params->unit_offset,
  81. &unit_base_reg, &unit_offset));
  82. /* Address calculation */
  83. reg_addr = unit_base_reg + unit_offset * serdes_num;
  84. /* Polling */
  85. #ifdef SEQ_DEBUG
  86. printf("Poll: 0x%x: 0x%x (mask 0x%x)\n", reg_addr, data, mask);
  87. #endif
  88. do {
  89. reg_data = reg_read(reg_addr) & mask;
  90. poll_counter++;
  91. udelay(wait_time);
  92. } while ((reg_data != data) && (poll_counter < num_of_loops));
  93. if ((poll_counter >= num_of_loops) && (reg_data != data)) {
  94. DEBUG_INIT_S("poll_op_execute: TIMEOUT\n");
  95. return MV_TIMEOUT;
  96. }
  97. return MV_OK;
  98. }
  99. enum mv_op get_cfg_seq_op(struct op_params *params)
  100. {
  101. if (params->wait_time == 0)
  102. return WRITE_OP;
  103. else if (params->num_of_loops == 0)
  104. return DELAY_OP;
  105. return POLL_OP;
  106. }
  107. int mv_seq_exec(u32 serdes_num, u32 seq_id)
  108. {
  109. u32 seq_idx;
  110. struct op_params *seq_arr;
  111. u32 seq_size;
  112. u32 data_arr_idx;
  113. enum mv_op curr_op;
  114. DB(printf("\n### mv_seq_exec ###\n"));
  115. DB(printf("seq id: %d\n", seq_id));
  116. if (hws_is_serdes_active(serdes_num) != 1) {
  117. printf("mv_seq_exec_ext:Error: SerDes lane %d is not valid\n",
  118. serdes_num);
  119. return MV_BAD_PARAM;
  120. }
  121. seq_arr = serdes_seq_db[seq_id].op_params_ptr;
  122. seq_size = serdes_seq_db[seq_id].cfg_seq_size;
  123. data_arr_idx = serdes_seq_db[seq_id].data_arr_idx;
  124. DB(printf("seq_size: %d\n", seq_size));
  125. DB(printf("data_arr_idx: %d\n", data_arr_idx));
  126. /* Executing the sequence operations */
  127. for (seq_idx = 0; seq_idx < seq_size; seq_idx++) {
  128. curr_op = get_cfg_seq_op(&seq_arr[seq_idx]);
  129. op_execute_func_arr[curr_op](serdes_num, &seq_arr[seq_idx],
  130. data_arr_idx);
  131. }
  132. return MV_OK;
  133. }