123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /*
- * Copyright (C) Marvell International Ltd. and its affiliates
- *
- * SPDX-License-Identifier: GPL-2.0
- */
- #include <common.h>
- #include <spl.h>
- #include <asm/io.h>
- #include <asm/arch/cpu.h>
- #include <asm/arch/soc.h>
- #include "seq_exec.h"
- #include "high_speed_env_spec.h"
- #include "../../../drivers/ddr/marvell/a38x/ddr3_init.h"
- #if defined(MV_DEBUG_INIT_FULL) || defined(MV_DEBUG)
- #define DB(x) x
- #else
- #define DB(x)
- #endif
- /* Array for mapping the operation (write, poll or delay) functions */
- op_execute_func_ptr op_execute_func_arr[] = {
- write_op_execute,
- delay_op_execute,
- poll_op_execute
- };
- int write_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
- {
- u32 unit_base_reg, unit_offset, data, mask, reg_data, reg_addr;
- /* Getting write op params from the input parameter */
- data = params->data[data_arr_idx];
- mask = params->mask;
- /* an empty operation */
- if (data == NO_DATA)
- return MV_OK;
- /* get updated base address since it can be different between Serdes */
- CHECK_STATUS(hws_get_ext_base_addr(serdes_num, params->unit_base_reg,
- params->unit_offset,
- &unit_base_reg, &unit_offset));
- /* Address calculation */
- reg_addr = unit_base_reg + unit_offset * serdes_num;
- #ifdef SEQ_DEBUG
- printf("Write: 0x%x: 0x%x (mask 0x%x) - ", reg_addr, data, mask);
- #endif
- /* Reading old value */
- reg_data = reg_read(reg_addr);
- reg_data &= (~mask);
- /* Writing new data */
- data &= mask;
- reg_data |= data;
- reg_write(reg_addr, reg_data);
- #ifdef SEQ_DEBUG
- printf(" - 0x%x\n", reg_data);
- #endif
- return MV_OK;
- }
- int delay_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
- {
- u32 delay;
- /* Getting delay op params from the input parameter */
- delay = params->wait_time;
- #ifdef SEQ_DEBUG
- printf("Delay: %d\n", delay);
- #endif
- mdelay(delay);
- return MV_OK;
- }
- int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
- {
- u32 unit_base_reg, unit_offset, data, mask, num_of_loops, wait_time;
- u32 poll_counter = 0;
- u32 reg_addr, reg_data;
- /* Getting poll op params from the input parameter */
- data = params->data[data_arr_idx];
- mask = params->mask;
- num_of_loops = params->num_of_loops;
- wait_time = params->wait_time;
- /* an empty operation */
- if (data == NO_DATA)
- return MV_OK;
- /* get updated base address since it can be different between Serdes */
- CHECK_STATUS(hws_get_ext_base_addr(serdes_num, params->unit_base_reg,
- params->unit_offset,
- &unit_base_reg, &unit_offset));
- /* Address calculation */
- reg_addr = unit_base_reg + unit_offset * serdes_num;
- /* Polling */
- #ifdef SEQ_DEBUG
- printf("Poll: 0x%x: 0x%x (mask 0x%x)\n", reg_addr, data, mask);
- #endif
- do {
- reg_data = reg_read(reg_addr) & mask;
- poll_counter++;
- udelay(wait_time);
- } while ((reg_data != data) && (poll_counter < num_of_loops));
- if ((poll_counter >= num_of_loops) && (reg_data != data)) {
- DEBUG_INIT_S("poll_op_execute: TIMEOUT\n");
- return MV_TIMEOUT;
- }
- return MV_OK;
- }
- enum mv_op get_cfg_seq_op(struct op_params *params)
- {
- if (params->wait_time == 0)
- return WRITE_OP;
- else if (params->num_of_loops == 0)
- return DELAY_OP;
- return POLL_OP;
- }
- int mv_seq_exec(u32 serdes_num, u32 seq_id)
- {
- u32 seq_idx;
- struct op_params *seq_arr;
- u32 seq_size;
- u32 data_arr_idx;
- enum mv_op curr_op;
- DB(printf("\n### mv_seq_exec ###\n"));
- DB(printf("seq id: %d\n", seq_id));
- if (hws_is_serdes_active(serdes_num) != 1) {
- printf("mv_seq_exec_ext:Error: SerDes lane %d is not valid\n",
- serdes_num);
- return MV_BAD_PARAM;
- }
- seq_arr = serdes_seq_db[seq_id].op_params_ptr;
- seq_size = serdes_seq_db[seq_id].cfg_seq_size;
- data_arr_idx = serdes_seq_db[seq_id].data_arr_idx;
- DB(printf("seq_size: %d\n", seq_size));
- DB(printf("data_arr_idx: %d\n", data_arr_idx));
- /* Executing the sequence operations */
- for (seq_idx = 0; seq_idx < seq_size; seq_idx++) {
- curr_op = get_cfg_seq_op(&seq_arr[seq_idx]);
- op_execute_func_arr[curr_op](serdes_num, &seq_arr[seq_idx],
- data_arr_idx);
- }
- return MV_OK;
- }
|