xref: /rk3399_rockchip-uboot/arch/arm/mach-mvebu/serdes/a38x/seq_exec.c (revision fe524569d4a7eea66475d5815be75660e59b6ee4)
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