seq_exec.c 3.9 KB

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