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