blob: 1d6e83a2c70847174355e08ce26a6689ecbfcff2 [file] [log] [blame]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001/*
Marek Vasut6ad74c32019-08-08 16:34:22 +02002 * Copyright (c) 2015-2019, Renesas Electronics Corporation.
3 * All rights reserved.
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include <stdint.h>
9#include <string.h>
10#include <stdio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011
12#include <common/debug.h>
13#include <lib/mmio.h>
14
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020015#include "ddr_regdef.h"
16#include "init_dram_tbl_h3.h"
17#include "init_dram_tbl_m3.h"
18#include "init_dram_tbl_h3ver2.h"
19#include "init_dram_tbl_m3n.h"
20#include "boot_init_dram_regdef.h"
21#include "boot_init_dram.h"
22#include "dram_sub_func.h"
23#include "micro_delay.h"
Marek Vasutd97f6ee2019-08-06 18:58:38 +020024#include "rcar_def.h"
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020025
26#define DDR_BACKUPMODE
27#define FATAL_MSG(x) NOTICE(x)
28
Marek Vasut6a131772019-08-07 19:56:09 +020029/* variables */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020030#ifdef RCAR_DDR_FIXED_LSI_TYPE
31#ifndef RCAR_AUTO
32#define RCAR_AUTO 99
Marek Vasut38dc7562019-08-07 19:17:42 +020033#define RCAR_H3 0
34#define RCAR_M3 1
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020035#define RCAR_M3N 2
Marek Vasut38dc7562019-08-07 19:17:42 +020036#define RCAR_E3 3 /* NON */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020037#define RCAR_H3N 4
38
39#define RCAR_CUT_10 0
40#define RCAR_CUT_11 1
41#define RCAR_CUT_20 10
42#define RCAR_CUT_30 20
43#endif
44#ifndef RCAR_LSI
45#define RCAR_LSI RCAR_AUTO
46#endif
Marek Vasut38dc7562019-08-07 19:17:42 +020047
Marek Vasut80784f92019-08-07 19:02:26 +020048#if (RCAR_LSI == RCAR_AUTO)
Marek Vasut38dc7562019-08-07 19:17:42 +020049static uint32_t prr_product;
50static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020051#else
Marek Vasut80784f92019-08-07 19:02:26 +020052#if (RCAR_LSI == RCAR_H3)
Marek Vasut38dc7562019-08-07 19:17:42 +020053static const uint32_t prr_product = PRR_PRODUCT_H3;
Marek Vasut80784f92019-08-07 19:02:26 +020054#elif(RCAR_LSI == RCAR_M3)
Marek Vasut38dc7562019-08-07 19:17:42 +020055static const uint32_t prr_product = PRR_PRODUCT_M3;
Marek Vasut80784f92019-08-07 19:02:26 +020056#elif(RCAR_LSI == RCAR_M3N)
Marek Vasut38dc7562019-08-07 19:17:42 +020057static const uint32_t prr_product = PRR_PRODUCT_M3N;
Marek Vasut80784f92019-08-07 19:02:26 +020058#elif(RCAR_LSI == RCAR_H3N)
Marek Vasut38dc7562019-08-07 19:17:42 +020059static const uint32_t prr_product = PRR_PRODUCT_H3;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020060#endif /* RCAR_LSI */
61
62#ifndef RCAR_LSI_CUT
Marek Vasut38dc7562019-08-07 19:17:42 +020063static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020064#else /* RCAR_LSI_CUT */
Marek Vasut80784f92019-08-07 19:02:26 +020065#if (RCAR_LSI_CUT == RCAR_CUT_10)
Marek Vasut38dc7562019-08-07 19:17:42 +020066static const uint32_t prr_cut = PRR_PRODUCT_10;
Marek Vasut80784f92019-08-07 19:02:26 +020067#elif(RCAR_LSI_CUT == RCAR_CUT_11)
Marek Vasut38dc7562019-08-07 19:17:42 +020068static const uint32_t prr_cut = PRR_PRODUCT_11;
Marek Vasut80784f92019-08-07 19:02:26 +020069#elif(RCAR_LSI_CUT == RCAR_CUT_20)
Marek Vasut38dc7562019-08-07 19:17:42 +020070static const uint32_t prr_cut = PRR_PRODUCT_20;
Marek Vasut80784f92019-08-07 19:02:26 +020071#elif(RCAR_LSI_CUT == RCAR_CUT_30)
Marek Vasut38dc7562019-08-07 19:17:42 +020072static const uint32_t prr_cut = PRR_PRODUCT_30;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020073#endif /* RCAR_LSI_CUT */
74#endif /* RCAR_LSI_CUT */
75#endif /* RCAR_AUTO_NON */
76#else /* RCAR_DDR_FIXED_LSI_TYPE */
Marek Vasut38dc7562019-08-07 19:17:42 +020077static uint32_t prr_product;
78static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020079#endif /* RCAR_DDR_FIXED_LSI_TYPE */
80
Marek Vasut38dc7562019-08-07 19:17:42 +020081static const uint32_t *p_ddr_regdef_tbl;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020082static uint32_t brd_clk;
83static uint32_t brd_clkdiv;
84static uint32_t brd_clkdiva;
85static uint32_t ddr_mbps;
86static uint32_t ddr_mbpsdiv;
87static uint32_t ddr_tccd;
Marek Vasut6c245a52018-12-12 18:06:39 +010088static uint32_t ddr_phycaslice;
Marek Vasut38dc7562019-08-07 19:17:42 +020089static const struct _boardcnf *board_cnf;
Chiaki Fujii59263ee2019-05-17 10:45:02 +090090static uint32_t ddr_phyvalid;
91static uint32_t ddr_density[DRAM_CH_CNT][CS_CNT];
Marek Vasut6a131772019-08-07 19:56:09 +020092static uint32_t ch_have_this_cs[CS_CNT] __aligned(64);
Chiaki Fujiifd1ec702019-07-08 23:44:56 +090093static uint32_t rdqdm_dly[DRAM_CH_CNT][CSAB_CNT][SLICE_CNT * 2][9];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020094static uint32_t max_density;
95static uint32_t ddr0800_mul;
96static uint32_t ddr_mul;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020097static uint32_t DDR_PHY_SLICE_REGSET_OFS;
98static uint32_t DDR_PHY_ADR_V_REGSET_OFS;
99static uint32_t DDR_PHY_ADR_I_REGSET_OFS;
100static uint32_t DDR_PHY_ADR_G_REGSET_OFS;
101static uint32_t DDR_PI_REGSET_OFS;
102static uint32_t DDR_PHY_SLICE_REGSET_SIZE;
103static uint32_t DDR_PHY_ADR_V_REGSET_SIZE;
104static uint32_t DDR_PHY_ADR_I_REGSET_SIZE;
105static uint32_t DDR_PHY_ADR_G_REGSET_SIZE;
106static uint32_t DDR_PI_REGSET_SIZE;
107static uint32_t DDR_PHY_SLICE_REGSET_NUM;
108static uint32_t DDR_PHY_ADR_V_REGSET_NUM;
109static uint32_t DDR_PHY_ADR_I_REGSET_NUM;
110static uint32_t DDR_PHY_ADR_G_REGSET_NUM;
111static uint32_t DDR_PI_REGSET_NUM;
112static uint32_t DDR_PHY_ADR_I_NUM;
113#define DDR_PHY_REGSET_MAX 128
114#define DDR_PI_REGSET_MAX 320
115static uint32_t _cnf_DDR_PHY_SLICE_REGSET[DDR_PHY_REGSET_MAX];
116static uint32_t _cnf_DDR_PHY_ADR_V_REGSET[DDR_PHY_REGSET_MAX];
117static uint32_t _cnf_DDR_PHY_ADR_I_REGSET[DDR_PHY_REGSET_MAX];
118static uint32_t _cnf_DDR_PHY_ADR_G_REGSET[DDR_PHY_REGSET_MAX];
119static uint32_t _cnf_DDR_PI_REGSET[DDR_PI_REGSET_MAX];
Marek Vasut38dc7562019-08-07 19:17:42 +0200120static uint32_t pll3_mode;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200121static uint32_t loop_max;
122#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +0200123uint32_t ddr_backup;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200124/* #define DDR_BACKUPMODE_HALF //for Half channel(ch0,1 only) */
125#endif
126
127#ifdef ddr_qos_init_setting /* only for non qos_init */
128#define OPERATING_FREQ (400U) /* Mhz */
129#define BASE_SUB_SLOT_NUM (0x6U)
130#define SUB_SLOT_CYCLE (0x7EU) /* 126 */
Marek Vasut6a131772019-08-07 19:56:09 +0200131#define QOSWT_WTSET0_CYCLE \
132 ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / \
133 OPERATING_FREQ) /* unit:ns */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200134
135uint32_t get_refperiod(void)
136{
137 return QOSWT_WTSET0_CYCLE;
138}
139#else /* ddr_qos_init_setting // only for non qos_init */
140extern uint32_t get_refperiod(void);
141#endif /* ddr_qos_init_setting // only for non qos_init */
142
143#define _reg_PHY_RX_CAL_X_NUM 11
144static const uint32_t _reg_PHY_RX_CAL_X[_reg_PHY_RX_CAL_X_NUM] = {
145 _reg_PHY_RX_CAL_DQ0,
146 _reg_PHY_RX_CAL_DQ1,
147 _reg_PHY_RX_CAL_DQ2,
148 _reg_PHY_RX_CAL_DQ3,
149 _reg_PHY_RX_CAL_DQ4,
150 _reg_PHY_RX_CAL_DQ5,
151 _reg_PHY_RX_CAL_DQ6,
152 _reg_PHY_RX_CAL_DQ7,
153 _reg_PHY_RX_CAL_DM,
154 _reg_PHY_RX_CAL_DQS,
155 _reg_PHY_RX_CAL_FDBK
156};
157
158#define _reg_PHY_CLK_WRX_SLAVE_DELAY_NUM 10
Marek Vasut6ad74c32019-08-08 16:34:22 +0200159static const uint32_t _reg_PHY_CLK_WRX_SLAVE_DELAY
160 [_reg_PHY_CLK_WRX_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200161 _reg_PHY_CLK_WRDQ0_SLAVE_DELAY,
162 _reg_PHY_CLK_WRDQ1_SLAVE_DELAY,
163 _reg_PHY_CLK_WRDQ2_SLAVE_DELAY,
164 _reg_PHY_CLK_WRDQ3_SLAVE_DELAY,
165 _reg_PHY_CLK_WRDQ4_SLAVE_DELAY,
166 _reg_PHY_CLK_WRDQ5_SLAVE_DELAY,
167 _reg_PHY_CLK_WRDQ6_SLAVE_DELAY,
168 _reg_PHY_CLK_WRDQ7_SLAVE_DELAY,
169 _reg_PHY_CLK_WRDM_SLAVE_DELAY,
170 _reg_PHY_CLK_WRDQS_SLAVE_DELAY
171};
172
173#define _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM 9
Marek Vasut6ad74c32019-08-08 16:34:22 +0200174static const uint32_t _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY
175 [_reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200176 _reg_PHY_RDDQS_DQ0_FALL_SLAVE_DELAY,
177 _reg_PHY_RDDQS_DQ1_FALL_SLAVE_DELAY,
178 _reg_PHY_RDDQS_DQ2_FALL_SLAVE_DELAY,
179 _reg_PHY_RDDQS_DQ3_FALL_SLAVE_DELAY,
180 _reg_PHY_RDDQS_DQ4_FALL_SLAVE_DELAY,
181 _reg_PHY_RDDQS_DQ5_FALL_SLAVE_DELAY,
182 _reg_PHY_RDDQS_DQ6_FALL_SLAVE_DELAY,
183 _reg_PHY_RDDQS_DQ7_FALL_SLAVE_DELAY,
184 _reg_PHY_RDDQS_DM_FALL_SLAVE_DELAY
185};
186
187#define _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM 9
Marek Vasut6ad74c32019-08-08 16:34:22 +0200188static const uint32_t _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
189 [_reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200190 _reg_PHY_RDDQS_DQ0_RISE_SLAVE_DELAY,
191 _reg_PHY_RDDQS_DQ1_RISE_SLAVE_DELAY,
192 _reg_PHY_RDDQS_DQ2_RISE_SLAVE_DELAY,
193 _reg_PHY_RDDQS_DQ3_RISE_SLAVE_DELAY,
194 _reg_PHY_RDDQS_DQ4_RISE_SLAVE_DELAY,
195 _reg_PHY_RDDQS_DQ5_RISE_SLAVE_DELAY,
196 _reg_PHY_RDDQS_DQ6_RISE_SLAVE_DELAY,
197 _reg_PHY_RDDQS_DQ7_RISE_SLAVE_DELAY,
198 _reg_PHY_RDDQS_DM_RISE_SLAVE_DELAY
199};
200
201#define _reg_PHY_PAD_TERM_X_NUM 8
202static const uint32_t _reg_PHY_PAD_TERM_X[_reg_PHY_PAD_TERM_X_NUM] = {
203 _reg_PHY_PAD_FDBK_TERM,
204 _reg_PHY_PAD_DATA_TERM,
205 _reg_PHY_PAD_DQS_TERM,
206 _reg_PHY_PAD_ADDR_TERM,
207 _reg_PHY_PAD_CLK_TERM,
208 _reg_PHY_PAD_CKE_TERM,
209 _reg_PHY_PAD_RST_TERM,
210 _reg_PHY_PAD_CS_TERM
211};
212
213#define _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM 10
Marek Vasut6ad74c32019-08-08 16:34:22 +0200214static const uint32_t _reg_PHY_CLK_CACS_SLAVE_DELAY_X
215 [_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200216 _reg_PHY_ADR0_CLK_WR_SLAVE_DELAY,
217 _reg_PHY_ADR1_CLK_WR_SLAVE_DELAY,
218 _reg_PHY_ADR2_CLK_WR_SLAVE_DELAY,
219 _reg_PHY_ADR3_CLK_WR_SLAVE_DELAY,
220 _reg_PHY_ADR4_CLK_WR_SLAVE_DELAY,
221 _reg_PHY_ADR5_CLK_WR_SLAVE_DELAY,
222
223 _reg_PHY_GRP_SLAVE_DELAY_0,
224 _reg_PHY_GRP_SLAVE_DELAY_1,
225 _reg_PHY_GRP_SLAVE_DELAY_2,
226 _reg_PHY_GRP_SLAVE_DELAY_3
227};
228
Marek Vasut6a131772019-08-07 19:56:09 +0200229/* Prototypes */
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900230static inline uint32_t vch_nxt(uint32_t pos);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200231static void cpg_write_32(uint32_t a, uint32_t v);
232static void pll3_control(uint32_t high);
233static inline void dsb_sev(void);
234static void wait_dbcmd(void);
235static void send_dbcmd(uint32_t cmd);
236static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd);
237static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata);
238static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata);
239static inline uint32_t ddr_regdef(uint32_t _regdef);
240static inline uint32_t ddr_regdef_adr(uint32_t _regdef);
241static inline uint32_t ddr_regdef_lsb(uint32_t _regdef);
242static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef,
243 uint32_t val);
244static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef);
245static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val);
246static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val);
247static void ddr_setval_ach(uint32_t regdef, uint32_t val);
248static void ddr_setval_ach_as(uint32_t regdef, uint32_t val);
249static uint32_t ddr_getval(uint32_t ch, uint32_t regdef);
Marek Vasut80784f92019-08-07 19:02:26 +0200250static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p);
251static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p);
252static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size);
253static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val);
254static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200255static uint32_t ddrphy_regif_chk(void);
Marek Vasut80784f92019-08-07 19:02:26 +0200256static inline void ddrphy_regif_idle(void);
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +0100257static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200258 uint16_t cyc);
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +0100259static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv,
260 uint16_t *_js2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200261static int16_t _f_scale_adj(int16_t ps);
262static void ddrtbl_load(void);
263static void ddr_config_sub(void);
Marek Vasut80784f92019-08-07 19:02:26 +0200264static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200265static void ddr_config_sub_h3v1x(void);
266static void ddr_config(void);
267static void dbsc_regset(void);
268static void dbsc_regset_post(void);
269static uint32_t dfi_init_start(void);
270static void change_lpddr4_en(uint32_t mode);
271static uint32_t set_term_code(void);
Marek Vasut6c245a52018-12-12 18:06:39 +0100272static void ddr_register_set(void);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200273static inline uint32_t wait_freqchgreq(uint32_t assert);
274static inline void set_freqchgack(uint32_t assert);
275static inline void set_dfifrequency(uint32_t freq);
276static uint32_t pll3_freq(uint32_t on);
277static void update_dly(void);
278static uint32_t pi_training_go(void);
279static uint32_t init_ddr(void);
280static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200281static uint32_t wdqdm_man1(void);
282static uint32_t wdqdm_man(void);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200283static uint32_t rdqdm_man1(void);
284static uint32_t rdqdm_man(void);
285
286static int32_t _find_change(uint64_t val, uint32_t dir);
287static uint32_t _rx_offset_cal_updn(uint32_t code);
288static uint32_t rx_offset_cal(void);
289static uint32_t rx_offset_cal_hw(void);
290static void adjust_rddqs_latency(void);
291static void adjust_wpath_latency(void);
292
Marek Vasut38dc7562019-08-07 19:17:42 +0200293struct ddrt_data {
Marek Vasut6a131772019-08-07 19:56:09 +0200294 int32_t init_temp; /* Initial Temperature (do) */
295 uint32_t init_cal[4]; /* Initial io-code (4 is for H3) */
296 uint32_t tcomp_cal[4]; /* Temp. compensated io-code (4 is for H3) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200297};
Marek Vasut80784f92019-08-07 19:02:26 +0200298
Marek Vasut38dc7562019-08-07 19:17:42 +0200299static struct ddrt_data tcal;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200300
301static void pvtcode_update(void);
302static void pvtcode_update2(void);
303static void ddr_padcal_tcompensate_getinit(uint32_t override);
304
Marek Vasut6a131772019-08-07 19:56:09 +0200305/* load board configuration */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200306#include "boot_init_dram_config.c"
307
Marek Vasut6c245a52018-12-12 18:06:39 +0100308#ifndef DDR_FAST_INIT
309static uint32_t rdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
310static uint32_t rdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
311static uint32_t rdqdm_nw[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
312static uint32_t rdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
313static uint32_t rdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2];
314static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn);
315static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn);
316
317static uint32_t wdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
318static uint32_t wdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
319static uint32_t wdqdm_dly[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
320static uint32_t wdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
321static uint32_t wdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
322static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn);
323static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn);
324#endif/* DDR_FAST_INIT */
325
Marek Vasut6a131772019-08-07 19:56:09 +0200326/* macro for channel selection loop */
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900327static inline uint32_t vch_nxt(uint32_t pos)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200328{
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900329 uint32_t posn;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200330
331 for (posn = pos; posn < DRAM_CH_CNT; posn++) {
332 if (ddr_phyvalid & (1U << posn))
333 break;
334 }
335 return posn;
336}
337
338#define foreach_vch(ch) \
Marek Vasut80784f92019-08-07 19:02:26 +0200339for (ch = vch_nxt(0); ch < DRAM_CH_CNT; ch = vch_nxt(ch + 1))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200340
341#define foreach_ech(ch) \
Marek Vasut80784f92019-08-07 19:02:26 +0200342for (ch = 0; ch < DRAM_CH_CNT; ch++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200343
Marek Vasut6a131772019-08-07 19:56:09 +0200344/* Printing functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200345#define MSG_LF(...)
346
Marek Vasut6a131772019-08-07 19:56:09 +0200347/* clock settings, reset control */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200348static void cpg_write_32(uint32_t a, uint32_t v)
349{
350 mmio_write_32(CPG_CPGWPR, ~v);
351 mmio_write_32(a, v);
352}
353
354static void pll3_control(uint32_t high)
355{
Marek Vasut38dc7562019-08-07 19:17:42 +0200356 uint32_t data_l, data_div, data_mul, tmp_div;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200357
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200358 if (high) {
Marek Vasut38dc7562019-08-07 19:17:42 +0200359 tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) /
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900360 (brd_clk * ddr_mul) / 2;
Chiaki Fujiifd1ec702019-07-08 23:44:56 +0900361 data_mul = ((ddr_mul * tmp_div) - 1) << 24;
Marek Vasut38dc7562019-08-07 19:17:42 +0200362 pll3_mode = 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200363 loop_max = 2;
364 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +0200365 tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) /
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900366 (brd_clk * ddr0800_mul) / 2;
Chiaki Fujiifd1ec702019-07-08 23:44:56 +0900367 data_mul = ((ddr0800_mul * tmp_div) - 1) << 24;
Marek Vasut38dc7562019-08-07 19:17:42 +0200368 pll3_mode = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200369 loop_max = 8;
370 }
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900371
Marek Vasut38dc7562019-08-07 19:17:42 +0200372 switch (tmp_div) {
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900373 case 1:
Marek Vasut38dc7562019-08-07 19:17:42 +0200374 data_div = 0;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900375 break;
376 case 2:
377 case 3:
378 case 4:
Marek Vasut38dc7562019-08-07 19:17:42 +0200379 data_div = tmp_div;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900380 break;
381 default:
Marek Vasut38dc7562019-08-07 19:17:42 +0200382 data_div = 6;
383 data_mul = (data_mul * tmp_div) / 3;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900384 break;
Marek Vasut6c245a52018-12-12 18:06:39 +0100385 }
Marek Vasut38dc7562019-08-07 19:17:42 +0200386 data_mul = data_mul | (brd_clkdiva << 7);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200387
Marek Vasut6c245a52018-12-12 18:06:39 +0100388 /* PLL3 disable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200389 data_l = mmio_read_32(CPG_PLLECR) & ~CPG_PLLECR_PLL3E_BIT;
390 cpg_write_32(CPG_PLLECR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200391 dsb_sev();
392
Marek Vasut38dc7562019-08-07 19:17:42 +0200393 if ((prr_product == PRR_PRODUCT_M3) ||
394 ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_20))) {
Marek Vasut6c245a52018-12-12 18:06:39 +0100395 /* PLL3 DIV resetting(Lowest value:3) */
Marek Vasut38dc7562019-08-07 19:17:42 +0200396 data_l = 0x00030003 | (0xFF80FF80 & mmio_read_32(CPG_FRQCRD));
397 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100398 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200399
Marek Vasut6c245a52018-12-12 18:06:39 +0100400 /* zb3 clk stop */
Marek Vasut38dc7562019-08-07 19:17:42 +0200401 data_l = CPG_ZB3CKCR_ZB3ST_BIT | mmio_read_32(CPG_ZB3CKCR);
402 cpg_write_32(CPG_ZB3CKCR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100403 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200404
Marek Vasut6c245a52018-12-12 18:06:39 +0100405 /* PLL3 enable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200406 data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR);
407 cpg_write_32(CPG_PLLECR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100408 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200409
Marek Vasut6c245a52018-12-12 18:06:39 +0100410 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200411 data_l = mmio_read_32(CPG_PLLECR);
412 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100413 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200414
Marek Vasut6c245a52018-12-12 18:06:39 +0100415 /* PLL3 DIV resetting (Highest value:0) */
Marek Vasut38dc7562019-08-07 19:17:42 +0200416 data_l = (0xFF80FF80 & mmio_read_32(CPG_FRQCRD));
417 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100418 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200419
Marek Vasut6c245a52018-12-12 18:06:39 +0100420 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200421 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
422 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100423 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200424
Marek Vasut6c245a52018-12-12 18:06:39 +0100425 /* PLL3 multiplie set */
Marek Vasut38dc7562019-08-07 19:17:42 +0200426 cpg_write_32(CPG_PLL3CR, data_mul);
Marek Vasut6c245a52018-12-12 18:06:39 +0100427 dsb_sev();
428
429 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200430 data_l = mmio_read_32(CPG_PLLECR);
431 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100432 dsb_sev();
433
434 /* PLL3 DIV resetting(Target value) */
Marek Vasut6a131772019-08-07 19:56:09 +0200435 data_l = (data_div << 16) | data_div |
436 (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80);
Marek Vasut38dc7562019-08-07 19:17:42 +0200437 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100438 dsb_sev();
439
440 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200441 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
442 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100443 dsb_sev();
444
445 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200446 data_l = mmio_read_32(CPG_PLLECR);
447 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100448 dsb_sev();
449
450 /* zb3 clk start */
Marek Vasut38dc7562019-08-07 19:17:42 +0200451 data_l = (~CPG_ZB3CKCR_ZB3ST_BIT) & mmio_read_32(CPG_ZB3CKCR);
452 cpg_write_32(CPG_ZB3CKCR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100453 dsb_sev();
454
455 } else { /* H3Ver.3.0/M3N/V3H */
456
457 /* PLL3 multiplie set */
Marek Vasut38dc7562019-08-07 19:17:42 +0200458 cpg_write_32(CPG_PLL3CR, data_mul);
Marek Vasut6c245a52018-12-12 18:06:39 +0100459 dsb_sev();
460
461 /* PLL3 DIV set(Target value) */
Marek Vasut6a131772019-08-07 19:56:09 +0200462 data_l = (data_div << 16) | data_div |
463 (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80);
Marek Vasut38dc7562019-08-07 19:17:42 +0200464 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100465
466 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200467 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
468 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100469 dsb_sev();
470
471 /* PLL3 enable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200472 data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR);
473 cpg_write_32(CPG_PLLECR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100474 dsb_sev();
475
476 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200477 data_l = mmio_read_32(CPG_PLLECR);
478 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100479 dsb_sev();
480 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200481}
482
Marek Vasut6a131772019-08-07 19:56:09 +0200483/* barrier */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200484static inline void dsb_sev(void)
485{
486 __asm__ __volatile__("dsb sy");
487}
488
Marek Vasut6a131772019-08-07 19:56:09 +0200489/* DDR memory register access */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200490static void wait_dbcmd(void)
491{
Marek Vasut38dc7562019-08-07 19:17:42 +0200492 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200493 /* dummy read */
Marek Vasut38dc7562019-08-07 19:17:42 +0200494 data_l = mmio_read_32(DBSC_DBCMD);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200495 dsb_sev();
496 while (1) {
497 /* wait DBCMD 1=busy, 0=ready */
Marek Vasut38dc7562019-08-07 19:17:42 +0200498 data_l = mmio_read_32(DBSC_DBWAIT);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200499 dsb_sev();
Marek Vasut38dc7562019-08-07 19:17:42 +0200500 if ((data_l & 0x00000001) == 0x00)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200501 break;
502 }
503}
504
505static void send_dbcmd(uint32_t cmd)
506{
507 /* dummy read */
508 wait_dbcmd();
509 mmio_write_32(DBSC_DBCMD, cmd);
510 dsb_sev();
511}
512
Marek Vasut6a131772019-08-07 19:56:09 +0200513/* DDRPHY register access (raw) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200514static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd)
515{
516 uint32_t val;
517 uint32_t loop;
518
519 val = 0;
Marek Vasut6a131772019-08-07 19:56:09 +0200520 if ((prr_product != PRR_PRODUCT_M3N) &&
521 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200522 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
523 dsb_sev();
524
525 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
526 dsb_sev();
527 }
528 dsb_sev();
529
530 for (loop = 0; loop < loop_max; loop++) {
531 val = mmio_read_32(DBSC_DBPDRGD(phyno));
532 dsb_sev();
533 }
534 (void)val;
535 } else {
536 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00004000);
537 dsb_sev();
538 while (mmio_read_32(DBSC_DBPDRGA(phyno)) !=
539 (regadd | 0x0000C000)) {
540 dsb_sev();
541 };
542 val = mmio_read_32(DBSC_DBPDRGA(phyno));
543 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
544 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
545 dsb_sev();
546 };
547 dsb_sev();
548
549 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
550 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
551 dsb_sev();
552 };
553
554 dsb_sev();
555 val = mmio_read_32(DBSC_DBPDRGD(phyno));
556 dsb_sev();
557 (void)val;
558 }
559 return val;
560}
561
562static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata)
563{
564 uint32_t val;
565 uint32_t loop;
566
Marek Vasut6a131772019-08-07 19:56:09 +0200567 if ((prr_product != PRR_PRODUCT_M3N) &&
568 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200569 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
570 dsb_sev();
571 for (loop = 0; loop < loop_max; loop++) {
572 val = mmio_read_32(DBSC_DBPDRGA(phyno));
573 dsb_sev();
574 }
575 mmio_write_32(DBSC_DBPDRGD(phyno), regdata);
576 dsb_sev();
577
578 for (loop = 0; loop < loop_max; loop++) {
579 val = mmio_read_32(DBSC_DBPDRGD(phyno));
580 dsb_sev();
581 }
582 } else {
583 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
584 dsb_sev();
585
586 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
587 dsb_sev();
588 };
589 dsb_sev();
590
591 mmio_write_32(DBSC_DBPDRGD(phyno), regdata);
592 dsb_sev();
593
594 while (mmio_read_32(DBSC_DBPDRGA(phyno)) !=
595 (regadd | 0x00008000)) {
596 dsb_sev();
597 };
598 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
599
600 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
601 dsb_sev();
602 };
603 dsb_sev();
604
605 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
606 }
607 (void)val;
608}
609
610static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata)
611{
612 uint32_t ch;
613 uint32_t val;
614 uint32_t loop;
615
Marek Vasut6a131772019-08-07 19:56:09 +0200616 if ((prr_product != PRR_PRODUCT_M3N) &&
617 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200618 foreach_vch(ch) {
619 mmio_write_32(DBSC_DBPDRGA(ch), regadd);
620 dsb_sev();
621 }
622
623 foreach_vch(ch) {
624 mmio_write_32(DBSC_DBPDRGD(ch), regdata);
625 dsb_sev();
626 }
627
628 for (loop = 0; loop < loop_max; loop++) {
629 val = mmio_read_32(DBSC_DBPDRGD(0));
630 dsb_sev();
631 }
632 (void)val;
633 } else {
634 foreach_vch(ch) {
635 reg_ddrphy_write(ch, regadd, regdata);
636 dsb_sev();
637 }
638 }
639}
640
Marek Vasut80784f92019-08-07 19:02:26 +0200641static inline void ddrphy_regif_idle(void)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200642{
643 uint32_t val;
644
645 val = reg_ddrphy_read(0, ddr_regdef_adr(_reg_PI_INT_STATUS));
646 dsb_sev();
647 (void)val;
648}
649
Marek Vasut6a131772019-08-07 19:56:09 +0200650/* DDRPHY register access (field modify) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200651static inline uint32_t ddr_regdef(uint32_t _regdef)
652{
Marek Vasut38dc7562019-08-07 19:17:42 +0200653 return p_ddr_regdef_tbl[_regdef];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200654}
655
656static inline uint32_t ddr_regdef_adr(uint32_t _regdef)
657{
Marek Vasut38dc7562019-08-07 19:17:42 +0200658 return DDR_REGDEF_ADR(p_ddr_regdef_tbl[_regdef]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200659}
660
661static inline uint32_t ddr_regdef_lsb(uint32_t _regdef)
662{
Marek Vasut38dc7562019-08-07 19:17:42 +0200663 return DDR_REGDEF_LSB(p_ddr_regdef_tbl[_regdef]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200664}
665
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200666static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef,
667 uint32_t val)
668{
669 uint32_t adr;
670 uint32_t lsb;
671 uint32_t len;
672 uint32_t msk;
673 uint32_t tmp;
674 uint32_t regdef;
675
676 regdef = ddr_regdef(_regdef);
677 adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice;
678 len = DDR_REGDEF_LEN(regdef);
679 lsb = DDR_REGDEF_LSB(regdef);
680 if (len == 0x20)
681 msk = 0xffffffff;
682 else
683 msk = ((1U << len) - 1) << lsb;
684
685 tmp = reg_ddrphy_read(ch, adr);
686 tmp = (tmp & (~msk)) | ((val << lsb) & msk);
687 reg_ddrphy_write(ch, adr, tmp);
688}
689
690static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef)
691{
692 uint32_t adr;
693 uint32_t lsb;
694 uint32_t len;
695 uint32_t msk;
696 uint32_t tmp;
697 uint32_t regdef;
698
699 regdef = ddr_regdef(_regdef);
700 adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice;
701 len = DDR_REGDEF_LEN(regdef);
702 lsb = DDR_REGDEF_LSB(regdef);
703 if (len == 0x20)
704 msk = 0xffffffff;
705 else
706 msk = ((1U << len) - 1);
707
708 tmp = reg_ddrphy_read(ch, adr);
709 tmp = (tmp >> lsb) & msk;
710
711 return tmp;
712}
713
714static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val)
715{
716 ddr_setval_s(ch, 0, regdef, val);
717}
718
719static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val)
720{
721 uint32_t ch;
722
723 foreach_vch(ch)
724 ddr_setval_s(ch, slice, regdef, val);
725}
726
727static void ddr_setval_ach(uint32_t regdef, uint32_t val)
728{
729 ddr_setval_ach_s(0, regdef, val);
730}
731
732static void ddr_setval_ach_as(uint32_t regdef, uint32_t val)
733{
734 uint32_t slice;
735
736 for (slice = 0; slice < SLICE_CNT; slice++)
737 ddr_setval_ach_s(slice, regdef, val);
738}
739
740static uint32_t ddr_getval(uint32_t ch, uint32_t regdef)
741{
742 return ddr_getval_s(ch, 0, regdef);
743}
744
Marek Vasut80784f92019-08-07 19:02:26 +0200745static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200746{
747 uint32_t ch;
748
749 foreach_vch(ch)
750 p[ch] = ddr_getval_s(ch, 0, regdef);
751 return p[0];
752}
753
Marek Vasut80784f92019-08-07 19:02:26 +0200754static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200755{
756 uint32_t ch, slice;
757 uint32_t *pp;
758
759 pp = p;
760 foreach_vch(ch)
Marek Vasut6ad74c32019-08-08 16:34:22 +0200761 for (slice = 0; slice < SLICE_CNT; slice++)
762 *pp++ = ddr_getval_s(ch, slice, regdef);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200763 return p[0];
764}
765
Marek Vasut6a131772019-08-07 19:56:09 +0200766/* handling functions for setteing ddrphy value table */
Marek Vasut80784f92019-08-07 19:02:26 +0200767static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200768{
769 uint32_t i;
770
771 for (i = 0; i < size; i++) {
772 to[i] = from[i];
773 }
774}
775
Marek Vasut80784f92019-08-07 19:02:26 +0200776static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200777{
778 uint32_t adr;
779 uint32_t lsb;
780 uint32_t len;
781 uint32_t msk;
782 uint32_t tmp;
783 uint32_t adrmsk;
784 uint32_t regdef;
785
786 regdef = ddr_regdef(_regdef);
787 adr = DDR_REGDEF_ADR(regdef);
788 len = DDR_REGDEF_LEN(regdef);
789 lsb = DDR_REGDEF_LSB(regdef);
790 if (len == 0x20)
791 msk = 0xffffffff;
792 else
793 msk = ((1U << len) - 1) << lsb;
794
795 if (adr < 0x400) {
796 adrmsk = 0xff;
797 } else {
798 adrmsk = 0x7f;
799 }
800
801 tmp = tbl[adr & adrmsk];
802 tmp = (tmp & (~msk)) | ((val << lsb) & msk);
803 tbl[adr & adrmsk] = tmp;
804}
805
Marek Vasut80784f92019-08-07 19:02:26 +0200806static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200807{
808 uint32_t adr;
809 uint32_t lsb;
810 uint32_t len;
811 uint32_t msk;
812 uint32_t tmp;
813 uint32_t adrmsk;
814 uint32_t regdef;
815
816 regdef = ddr_regdef(_regdef);
817 adr = DDR_REGDEF_ADR(regdef);
818 len = DDR_REGDEF_LEN(regdef);
819 lsb = DDR_REGDEF_LSB(regdef);
820 if (len == 0x20)
821 msk = 0xffffffff;
822 else
823 msk = ((1U << len) - 1);
824
825 if (adr < 0x400) {
826 adrmsk = 0xff;
827 } else {
828 adrmsk = 0x7f;
829 }
830
831 tmp = tbl[adr & adrmsk];
832 tmp = (tmp >> lsb) & msk;
833
834 return tmp;
835}
836
Marek Vasut6a131772019-08-07 19:56:09 +0200837/* DDRPHY register access handling */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200838static uint32_t ddrphy_regif_chk(void)
839{
840 uint32_t tmp_ach[DRAM_CH_CNT];
841 uint32_t ch;
842 uint32_t err;
843 uint32_t PI_VERSION_CODE;
844
Marek Vasut6a131772019-08-07 19:56:09 +0200845 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
846 (prr_product == PRR_PRODUCT_M3)) {
847 PI_VERSION_CODE = 0x2041; /* H3 Ver.1.x/M3-W */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200848 } else {
Marek Vasut6a131772019-08-07 19:56:09 +0200849 PI_VERSION_CODE = 0x2040; /* H3 Ver.2.0 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200850 }
851
Marek Vasut80784f92019-08-07 19:02:26 +0200852 ddr_getval_ach(_reg_PI_VERSION, (uint32_t *)tmp_ach);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200853 err = 0;
854 foreach_vch(ch) {
Marek Vasut80784f92019-08-07 19:02:26 +0200855 if (tmp_ach[ch] != PI_VERSION_CODE)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200856 err = 1;
857 }
858 return err;
859}
860
Marek Vasut6a131772019-08-07 19:56:09 +0200861/* functions and parameters for timing setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200862struct _jedec_spec1 {
863 uint16_t fx3;
Marek Vasut38dc7562019-08-07 19:17:42 +0200864 uint8_t rlwodbi;
865 uint8_t rlwdbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200866 uint8_t WL;
Marek Vasut38dc7562019-08-07 19:17:42 +0200867 uint8_t nwr;
868 uint8_t nrtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200869 uint8_t MR1;
870 uint8_t MR2;
871};
Marek Vasut80784f92019-08-07 19:02:26 +0200872
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200873#define JS1_USABLEC_SPEC_LO 2
874#define JS1_USABLEC_SPEC_HI 5
875#define JS1_FREQ_TBL_NUM 8
Marek Vasut80784f92019-08-07 19:02:26 +0200876#define JS1_MR1(f) (0x04 | ((f) << 4))
877#define JS1_MR2(f) (0x00 | ((f) << 3) | (f))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200878const struct _jedec_spec1 js1[JS1_FREQ_TBL_NUM] = {
Marek Vasut6ad74c32019-08-08 16:34:22 +0200879 /* 533.333Mbps */
880 { 800, 6, 6, 4, 6, 8, JS1_MR1(0), JS1_MR2(0) | 0x40 },
881 /* 1066.666Mbps */
882 { 1600, 10, 12, 8, 10, 8, JS1_MR1(1), JS1_MR2(1) | 0x40 },
883 /* 1600.000Mbps */
884 { 2400, 14, 16, 12, 16, 8, JS1_MR1(2), JS1_MR2(2) | 0x40 },
885 /* 2133.333Mbps */
886 { 3200, 20, 22, 10, 20, 8, JS1_MR1(3), JS1_MR2(3) },
887 /* 2666.666Mbps */
888 { 4000, 24, 28, 12, 24, 10, JS1_MR1(4), JS1_MR2(4) },
889 /* 3200.000Mbps */
890 { 4800, 28, 32, 14, 30, 12, JS1_MR1(5), JS1_MR2(5) },
891 /* 3733.333Mbps */
892 { 5600, 32, 36, 16, 34, 14, JS1_MR1(6), JS1_MR2(6) },
893 /* 4266.666Mbps */
894 { 6400, 36, 40, 18, 40, 16, JS1_MR1(7), JS1_MR2(7) }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200895};
896
897struct _jedec_spec2 {
898 uint16_t ps;
899 uint16_t cyc;
900};
901
Marek Vasut38dc7562019-08-07 19:17:42 +0200902#define js2_tsr 0
903#define js2_txp 1
904#define js2_trtp 2
905#define js2_trcd 3
906#define js2_trppb 4
907#define js2_trpab 5
908#define js2_tras 6
909#define js2_twr 7
910#define js2_twtr 8
911#define js2_trrd 9
912#define js2_tppd 10
913#define js2_tfaw 11
914#define js2_tdqsck 12
915#define js2_tckehcmd 13
916#define js2_tckelcmd 14
917#define js2_tckelpd 15
918#define js2_tmrr 16
919#define js2_tmrw 17
920#define js2_tmrd 18
921#define js2_tzqcalns 19
922#define js2_tzqlat 20
923#define js2_tiedly 21
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200924#define JS2_TBLCNT 22
925
Marek Vasut38dc7562019-08-07 19:17:42 +0200926#define js2_trcpb (JS2_TBLCNT)
927#define js2_trcab (JS2_TBLCNT + 1)
928#define js2_trfcab (JS2_TBLCNT + 2)
Marek Vasut80784f92019-08-07 19:02:26 +0200929#define JS2_CNT (JS2_TBLCNT + 3)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200930
931#ifndef JS2_DERATE
932#define JS2_DERATE 0
933#endif
934const struct _jedec_spec2 jedec_spec2[2][JS2_TBLCNT] = {
935 {
936/*tSR */ {15000, 3},
937/*tXP */ {7500, 3},
938/*tRTP */ {7500, 8},
939/*tRCD */ {18000, 4},
940/*tRPpb */ {18000, 3},
941/*tRPab */ {21000, 3},
942/*tRAS */ {42000, 3},
943/*tWR */ {18000, 4},
944/*tWTR */ {10000, 8},
945/*tRRD */ {10000, 4},
946/*tPPD */ {0, 0},
947/*tFAW */ {40000, 0},
948/*tDQSCK*/ {3500, 0},
949/*tCKEHCMD*/ {7500, 3},
950/*tCKELCMD*/ {7500, 3},
951/*tCKELPD*/ {7500, 3},
952/*tMRR*/ {0, 8},
953/*tMRW*/ {10000, 10},
954/*tMRD*/ {14000, 10},
955/*tZQCALns*/ {1000 * 10, 0},
956/*tZQLAT*/ {30000, 10},
957/*tIEdly*/ {12500, 0}
958 }, {
959/*tSR */ {15000, 3},
960/*tXP */ {7500, 3},
961/*tRTP */ {7500, 8},
962/*tRCD */ {19875, 4},
963/*tRPpb */ {19875, 3},
964/*tRPab */ {22875, 3},
965/*tRAS */ {43875, 3},
966/*tWR */ {18000, 4},
967/*tWTR */ {10000, 8},
968/*tRRD */ {11875, 4},
969/*tPPD */ {0, 0},
970/*tFAW */ {40000, 0},
971/*tDQSCK*/ {3600, 0},
972/*tCKEHCMD*/ {7500, 3},
973/*tCKELCMD*/ {7500, 3},
974/*tCKELPD*/ {7500, 3},
975/*tMRR*/ {0, 8},
976/*tMRW*/ {10000, 10},
977/*tMRD*/ {14000, 10},
978/*tZQCALns*/ {1000 * 10, 0},
979/*tZQLAT*/ {30000, 10},
980/*tIEdly*/ {12500, 0}
Marek Vasut80784f92019-08-07 19:02:26 +0200981 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200982};
983
Marek Vasut38dc7562019-08-07 19:17:42 +0200984const uint16_t jedec_spec2_trfc_ab[7] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200985/* 4Gb, 6Gb, 8Gb,12Gb, 16Gb, 24Gb(non), 32Gb(non) */
Marek Vasut6c245a52018-12-12 18:06:39 +0100986 130, 180, 180, 280, 280, 560, 560
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200987};
988
989static uint32_t js1_ind;
990static uint16_t js2[JS2_CNT];
991static uint8_t RL;
992static uint8_t WL;
993
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +0100994static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200995 uint16_t cyc)
996{
997 uint32_t tmp;
998 uint32_t div;
999
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001000 tmp = (((uint32_t)(ps) + 9) / 10) * _ddr_mbps;
1001 div = tmp / (200000 * _ddr_mbpsdiv);
1002 if (tmp != (div * 200000 * _ddr_mbpsdiv))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001003 div = div + 1;
1004
1005 if (div > cyc)
Marek Vasut80784f92019-08-07 19:02:26 +02001006 return (uint16_t)div;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001007 return cyc;
1008}
1009
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001010static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv,
1011 uint16_t *_js2)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001012{
1013 int i;
1014
1015 for (i = 0; i < JS2_TBLCNT; i++) {
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001016 _js2[i] = _f_scale(_ddr_mbps, _ddr_mbpsdiv,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001017 1UL * jedec_spec2[JS2_DERATE][i].ps,
1018 jedec_spec2[JS2_DERATE][i].cyc);
1019 }
1020
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001021 _js2[js2_trcpb] = _js2[js2_tras] + _js2[js2_trppb];
1022 _js2[js2_trcab] = _js2[js2_tras] + _js2[js2_trpab];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001023}
1024
1025/* scaler for DELAY value */
1026static int16_t _f_scale_adj(int16_t ps)
1027{
1028 int32_t tmp;
1029 /*
Marek Vasut6a131772019-08-07 19:56:09 +02001030 * tmp = (int32_t)512 * ps * ddr_mbps /2 / ddr_mbpsdiv / 1000 / 1000;
1031 * = ps * ddr_mbps /2 / ddr_mbpsdiv *512 / 8 / 8 / 125 / 125
1032 * = ps * ddr_mbps / ddr_mbpsdiv *4 / 125 / 125
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001033 */
1034 tmp =
Marek Vasut80784f92019-08-07 19:02:26 +02001035 (int32_t)4 * (int32_t)ps * (int32_t)ddr_mbps /
1036 (int32_t)ddr_mbpsdiv;
1037 tmp = (int32_t)tmp / (int32_t)15625;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001038
Marek Vasut80784f92019-08-07 19:02:26 +02001039 return (int16_t)tmp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001040}
1041
Marek Vasut38dc7562019-08-07 19:17:42 +02001042static const uint32_t reg_pi_mr1_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001043 {
1044 _reg_PI_MR1_DATA_F0_0,
1045 _reg_PI_MR1_DATA_F0_1,
1046 _reg_PI_MR1_DATA_F0_2,
1047 _reg_PI_MR1_DATA_F0_3},
1048 {
1049 _reg_PI_MR1_DATA_F1_0,
1050 _reg_PI_MR1_DATA_F1_1,
1051 _reg_PI_MR1_DATA_F1_2,
1052 _reg_PI_MR1_DATA_F1_3}
1053};
1054
Marek Vasut38dc7562019-08-07 19:17:42 +02001055static const uint32_t reg_pi_mr2_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001056 {
1057 _reg_PI_MR2_DATA_F0_0,
1058 _reg_PI_MR2_DATA_F0_1,
1059 _reg_PI_MR2_DATA_F0_2,
1060 _reg_PI_MR2_DATA_F0_3},
1061 {
1062 _reg_PI_MR2_DATA_F1_0,
1063 _reg_PI_MR2_DATA_F1_1,
1064 _reg_PI_MR2_DATA_F1_2,
1065 _reg_PI_MR2_DATA_F1_3}
1066};
1067
Marek Vasut38dc7562019-08-07 19:17:42 +02001068static const uint32_t reg_pi_mr3_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001069 {
1070 _reg_PI_MR3_DATA_F0_0,
1071 _reg_PI_MR3_DATA_F0_1,
1072 _reg_PI_MR3_DATA_F0_2,
1073 _reg_PI_MR3_DATA_F0_3},
1074 {
1075 _reg_PI_MR3_DATA_F1_0,
1076 _reg_PI_MR3_DATA_F1_1,
1077 _reg_PI_MR3_DATA_F1_2,
1078 _reg_PI_MR3_DATA_F1_3}
1079};
1080
Marek Vasut38dc7562019-08-07 19:17:42 +02001081const uint32_t reg_pi_mr11_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001082 {
1083 _reg_PI_MR11_DATA_F0_0,
1084 _reg_PI_MR11_DATA_F0_1,
1085 _reg_PI_MR11_DATA_F0_2,
1086 _reg_PI_MR11_DATA_F0_3},
1087 {
1088 _reg_PI_MR11_DATA_F1_0,
1089 _reg_PI_MR11_DATA_F1_1,
1090 _reg_PI_MR11_DATA_F1_2,
1091 _reg_PI_MR11_DATA_F1_3}
1092};
1093
Marek Vasut38dc7562019-08-07 19:17:42 +02001094const uint32_t reg_pi_mr12_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001095 {
1096 _reg_PI_MR12_DATA_F0_0,
1097 _reg_PI_MR12_DATA_F0_1,
1098 _reg_PI_MR12_DATA_F0_2,
1099 _reg_PI_MR12_DATA_F0_3},
1100 {
1101 _reg_PI_MR12_DATA_F1_0,
1102 _reg_PI_MR12_DATA_F1_1,
1103 _reg_PI_MR12_DATA_F1_2,
1104 _reg_PI_MR12_DATA_F1_3}
1105};
1106
Marek Vasut38dc7562019-08-07 19:17:42 +02001107const uint32_t reg_pi_mr14_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001108 {
1109 _reg_PI_MR14_DATA_F0_0,
1110 _reg_PI_MR14_DATA_F0_1,
1111 _reg_PI_MR14_DATA_F0_2,
1112 _reg_PI_MR14_DATA_F0_3},
1113 {
1114 _reg_PI_MR14_DATA_F1_0,
1115 _reg_PI_MR14_DATA_F1_1,
1116 _reg_PI_MR14_DATA_F1_2,
1117 _reg_PI_MR14_DATA_F1_3}
1118};
1119
Marek Vasut6a131772019-08-07 19:56:09 +02001120/*
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001121 * regif pll w/a ( REGIF H3 Ver.2.0 or later/M3-N/V3H WA )
Marek Vasut6a131772019-08-07 19:56:09 +02001122 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001123static void regif_pll_wa(void)
1124{
1125 uint32_t ch;
1126
Marek Vasut38dc7562019-08-07 19:17:42 +02001127 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001128 // PLL setting for PHY : H3 Ver.1.x
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001129 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT),
1130 (0x0064U <<
1131 ddr_regdef_lsb(_reg_PHY_PLL_WAIT)));
1132 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL),
1133 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1134 _reg_PHY_PLL_CTRL));
1135
1136 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL),
1137 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1138 _reg_PHY_LP4_BOOT_PLL_CTRL));
1139
1140 } else {
1141 /* PLL setting for PHY : M3-W/M3-N/V3H/H3 Ver.2.0 or later */
1142 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT),
1143 (0x5064U <<
1144 ddr_regdef_lsb(_reg_PHY_PLL_WAIT)));
1145
1146 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL),
1147 (ddrtbl_getval
1148 (_cnf_DDR_PHY_ADR_G_REGSET,
1149 _reg_PHY_PLL_CTRL_TOP) << 16) |
1150 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1151 _reg_PHY_PLL_CTRL));
1152 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL_CA),
1153 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1154 _reg_PHY_PLL_CTRL_CA));
1155
1156 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL),
1157 (ddrtbl_getval
1158 (_cnf_DDR_PHY_ADR_G_REGSET,
1159 _reg_PHY_LP4_BOOT_PLL_CTRL_CA) << 16) |
1160 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1161 _reg_PHY_LP4_BOOT_PLL_CTRL));
1162 reg_ddrphy_write_a(ddr_regdef_adr
1163 (_reg_PHY_LP4_BOOT_TOP_PLL_CTRL),
1164 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
Marek Vasut6a131772019-08-07 19:56:09 +02001165 _reg_PHY_LP4_BOOT_TOP_PLL_CTRL
1166 ));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001167 }
1168
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001169 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LPDDR3_CS),
Marek Vasut6a131772019-08-07 19:56:09 +02001170 _cnf_DDR_PHY_ADR_G_REGSET
1171 [ddr_regdef_adr(_reg_PHY_LPDDR3_CS) -
1172 DDR_PHY_ADR_G_REGSET_OFS]);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001173
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001174 /* protect register interface */
1175 ddrphy_regif_idle();
1176 pll3_control(0);
1177
Marek Vasut38dc7562019-08-07 19:17:42 +02001178 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001179 /* non */
1180 } else {
1181 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_DLL_RST_EN),
1182 (0x01U <<
1183 ddr_regdef_lsb(_reg_PHY_DLL_RST_EN)));
1184 ddrphy_regif_idle();
1185 }
1186
Marek Vasut6a131772019-08-07 19:56:09 +02001187 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001188 /* dbdficnt0:
1189 * dfi_dram_clk_disable=1
1190 * dfi_frequency = 0
1191 * freq_ratio = 01 (2:1)
1192 * init_start =0
1193 */
1194 foreach_vch(ch)
1195 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
1196 dsb_sev();
1197
1198 /* dbdficnt0:
1199 * dfi_dram_clk_disable=1
1200 * dfi_frequency = 0
1201 * freq_ratio = 01 (2:1)
1202 * init_start =1
1203 */
1204 foreach_vch(ch)
1205 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
1206 dsb_sev();
1207
1208 foreach_ech(ch)
Marek Vasut6a131772019-08-07 19:56:09 +02001209 if ((board_cnf->phyvalid) & BIT(ch))
1210 while ((mmio_read_32(DBSC_PLL_LOCK(ch)) & 0x1f) != 0x1f)
1211 ;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001212 dsb_sev();
1213}
1214
Marek Vasut6a131772019-08-07 19:56:09 +02001215/* load table data into DDR registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001216static void ddrtbl_load(void)
1217{
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001218 uint32_t i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001219 uint32_t slice;
1220 uint32_t csab;
1221 uint32_t adr;
Marek Vasut38dc7562019-08-07 19:17:42 +02001222 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001223 uint32_t tmp[3];
1224 uint16_t dataS;
1225
Marek Vasut6a131772019-08-07 19:56:09 +02001226 /* TIMING REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001227 /* search jedec_spec1 index */
1228 for (i = JS1_USABLEC_SPEC_LO; i < JS1_FREQ_TBL_NUM - 1; i++) {
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001229 if (js1[i].fx3 * 2U * ddr_mbpsdiv >= ddr_mbps * 3U)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001230 break;
1231 }
Marek Vasut80784f92019-08-07 19:02:26 +02001232 if (i > JS1_USABLEC_SPEC_HI)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001233 js1_ind = JS1_USABLEC_SPEC_HI;
1234 else
1235 js1_ind = i;
1236
Marek Vasut38dc7562019-08-07 19:17:42 +02001237 if (board_cnf->dbi_en)
1238 RL = js1[js1_ind].rlwdbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001239 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001240 RL = js1[js1_ind].rlwodbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001241
1242 WL = js1[js1_ind].WL;
1243
1244 /* calculate jedec_spec2 */
1245 _f_scale_js2(ddr_mbps, ddr_mbpsdiv, js2);
1246
Marek Vasut6a131772019-08-07 19:56:09 +02001247 /* PREPARE TBL */
Marek Vasut38dc7562019-08-07 19:17:42 +02001248 if (prr_product == PRR_PRODUCT_H3) {
1249 if (prr_cut <= PRR_PRODUCT_11) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001250 /* H3 Ver.1.x */
1251 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1252 DDR_PHY_SLICE_REGSET_H3,
1253 DDR_PHY_SLICE_REGSET_NUM_H3);
1254 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1255 DDR_PHY_ADR_V_REGSET_H3,
1256 DDR_PHY_ADR_V_REGSET_NUM_H3);
1257 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET,
1258 DDR_PHY_ADR_I_REGSET_H3,
1259 DDR_PHY_ADR_I_REGSET_NUM_H3);
1260 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1261 DDR_PHY_ADR_G_REGSET_H3,
1262 DDR_PHY_ADR_G_REGSET_NUM_H3);
1263 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3,
1264 DDR_PI_REGSET_NUM_H3);
1265
1266 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_H3;
1267 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_H3;
1268 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_H3;
1269 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_H3;
1270 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3;
1271 DDR_PHY_SLICE_REGSET_SIZE =
1272 DDR_PHY_SLICE_REGSET_SIZE_H3;
1273 DDR_PHY_ADR_V_REGSET_SIZE =
1274 DDR_PHY_ADR_V_REGSET_SIZE_H3;
1275 DDR_PHY_ADR_I_REGSET_SIZE =
1276 DDR_PHY_ADR_I_REGSET_SIZE_H3;
1277 DDR_PHY_ADR_G_REGSET_SIZE =
1278 DDR_PHY_ADR_G_REGSET_SIZE_H3;
1279 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3;
1280 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_H3;
1281 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_H3;
1282 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_H3;
1283 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_H3;
1284 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3;
1285
1286 DDR_PHY_ADR_I_NUM = 1;
1287 } else {
1288 /* H3 Ver.2.0 or later */
1289 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1290 DDR_PHY_SLICE_REGSET_H3VER2,
1291 DDR_PHY_SLICE_REGSET_NUM_H3VER2);
1292 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1293 DDR_PHY_ADR_V_REGSET_H3VER2,
1294 DDR_PHY_ADR_V_REGSET_NUM_H3VER2);
1295 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1296 DDR_PHY_ADR_G_REGSET_H3VER2,
1297 DDR_PHY_ADR_G_REGSET_NUM_H3VER2);
1298 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3VER2,
1299 DDR_PI_REGSET_NUM_H3VER2);
1300
1301 DDR_PHY_SLICE_REGSET_OFS =
1302 DDR_PHY_SLICE_REGSET_OFS_H3VER2;
1303 DDR_PHY_ADR_V_REGSET_OFS =
1304 DDR_PHY_ADR_V_REGSET_OFS_H3VER2;
1305 DDR_PHY_ADR_G_REGSET_OFS =
1306 DDR_PHY_ADR_G_REGSET_OFS_H3VER2;
1307 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3VER2;
1308 DDR_PHY_SLICE_REGSET_SIZE =
1309 DDR_PHY_SLICE_REGSET_SIZE_H3VER2;
1310 DDR_PHY_ADR_V_REGSET_SIZE =
1311 DDR_PHY_ADR_V_REGSET_SIZE_H3VER2;
1312 DDR_PHY_ADR_G_REGSET_SIZE =
1313 DDR_PHY_ADR_G_REGSET_SIZE_H3VER2;
1314 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3VER2;
1315 DDR_PHY_SLICE_REGSET_NUM =
1316 DDR_PHY_SLICE_REGSET_NUM_H3VER2;
1317 DDR_PHY_ADR_V_REGSET_NUM =
1318 DDR_PHY_ADR_V_REGSET_NUM_H3VER2;
1319 DDR_PHY_ADR_G_REGSET_NUM =
1320 DDR_PHY_ADR_G_REGSET_NUM_H3VER2;
1321 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3VER2;
1322
1323 DDR_PHY_ADR_I_NUM = 0;
1324 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001325 } else if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001326 /* M3-W */
1327 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1328 DDR_PHY_SLICE_REGSET_M3, DDR_PHY_SLICE_REGSET_NUM_M3);
1329 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1330 DDR_PHY_ADR_V_REGSET_M3, DDR_PHY_ADR_V_REGSET_NUM_M3);
1331 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET,
1332 DDR_PHY_ADR_I_REGSET_M3, DDR_PHY_ADR_I_REGSET_NUM_M3);
1333 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1334 DDR_PHY_ADR_G_REGSET_M3, DDR_PHY_ADR_G_REGSET_NUM_M3);
1335 _tblcopy(_cnf_DDR_PI_REGSET,
1336 DDR_PI_REGSET_M3, DDR_PI_REGSET_NUM_M3);
1337
1338 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3;
1339 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3;
1340 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3;
1341 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3;
1342 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3;
1343 DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3;
1344 DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3;
1345 DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3;
1346 DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3;
1347 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3;
1348 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3;
1349 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3;
1350 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3;
1351 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3;
1352 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3;
1353
1354 DDR_PHY_ADR_I_NUM = 2;
1355 } else {
1356 /* M3-N/V3H */
1357 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1358 DDR_PHY_SLICE_REGSET_M3N,
1359 DDR_PHY_SLICE_REGSET_NUM_M3N);
1360 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, DDR_PHY_ADR_V_REGSET_M3N,
1361 DDR_PHY_ADR_V_REGSET_NUM_M3N);
1362 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, DDR_PHY_ADR_I_REGSET_M3N,
1363 DDR_PHY_ADR_I_REGSET_NUM_M3N);
1364 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, DDR_PHY_ADR_G_REGSET_M3N,
1365 DDR_PHY_ADR_G_REGSET_NUM_M3N);
1366 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_M3N,
1367 DDR_PI_REGSET_NUM_M3N);
1368
1369 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3N;
1370 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3N;
1371 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3N;
1372 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3N;
1373 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3N;
1374 DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3N;
1375 DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3N;
1376 DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3N;
1377 DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3N;
1378 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3N;
1379 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3N;
1380 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3N;
1381 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3N;
1382 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3N;
1383 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3N;
1384
1385 DDR_PHY_ADR_I_NUM = 2;
1386 }
1387
Marek Vasut6a131772019-08-07 19:56:09 +02001388 /* PLL CODE CHANGE */
Marek Vasut38dc7562019-08-07 19:17:42 +02001389 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001390 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, _reg_PHY_PLL_CTRL,
1391 0x1142);
1392 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1393 _reg_PHY_LP4_BOOT_PLL_CTRL, 0x1142);
1394 }
1395
Marek Vasut6a131772019-08-07 19:56:09 +02001396 /* on fly gate adjust */
Marek Vasut38dc7562019-08-07 19:17:42 +02001397 if ((prr_product == PRR_PRODUCT_M3) && (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001398 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1399 _reg_ON_FLY_GATE_ADJUST_EN, 0x00);
1400 }
1401
Marek Vasut6a131772019-08-07 19:56:09 +02001402 /* Adjust PI parameters */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001403#ifdef _def_LPDDR4_ODT
Marek Vasut6c245a52018-12-12 18:06:39 +01001404 for (i = 0; i < 2; i++) {
1405 for (csab = 0; csab < CSAB_CNT; csab++) {
1406 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001407 reg_pi_mr11_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001408 _def_LPDDR4_ODT);
1409 }
1410 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001411#endif /* _def_LPDDR4_ODT */
1412
1413#ifdef _def_LPDDR4_VREFCA
Marek Vasut6c245a52018-12-12 18:06:39 +01001414 for (i = 0; i < 2; i++) {
1415 for (csab = 0; csab < CSAB_CNT; csab++) {
1416 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001417 reg_pi_mr12_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001418 _def_LPDDR4_VREFCA);
1419 }
1420 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001421#endif /* _def_LPDDR4_VREFCA */
Marek Vasut6a131772019-08-07 19:56:09 +02001422 if ((prr_product == PRR_PRODUCT_M3N) ||
1423 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001424 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 7000, 0) + 7U;
1425 if (js2[js2_tiedly] > (RL))
1426 js2[js2_tiedly] = RL;
Marek Vasut6a131772019-08-07 19:56:09 +02001427 } else if ((prr_product == PRR_PRODUCT_H3) &&
1428 (prr_cut > PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001429 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 9000, 0) + 4U;
Marek Vasut6a131772019-08-07 19:56:09 +02001430 } else if ((prr_product == PRR_PRODUCT_H3) &&
1431 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001432 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 10000, 0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001433 }
1434
Marek Vasut6a131772019-08-07 19:56:09 +02001435 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
1436 (prr_product == PRR_PRODUCT_M3N) ||
1437 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001438 if ((js2[js2_tiedly]) >= 0x1e)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001439 dataS = 0x1e;
1440 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001441 dataS = js2[js2_tiedly];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001442 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001443 if ((js2[js2_tiedly]) >= 0x0e)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001444 dataS = 0x0e;
1445 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001446 dataS = js2[js2_tiedly];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001447 }
1448
1449 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_DLY, dataS);
1450 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_TSEL_DLY,
1451 (dataS - 2));
Marek Vasut6a131772019-08-07 19:56:09 +02001452 if ((prr_product == PRR_PRODUCT_M3N) ||
1453 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001454 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1455 _reg_PHY_RDDATA_EN_OE_DLY, dataS);
1456 }
1457 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1, RL - dataS);
1458
1459 if (ddrtbl_getval
1460 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001461 data_l = WL - 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001462 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001463 data_l = WL;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001464 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001465 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1, data_l - 2);
1466 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001467
Marek Vasut38dc7562019-08-07 19:17:42 +02001468 if (board_cnf->dbi_en) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001469 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE,
1470 0x01);
1471 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1472 _reg_PHY_WDQLVL_DATADM_MASK, 0x000);
1473 } else {
1474 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE,
1475 0x00);
1476 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1477 _reg_PHY_WDQLVL_DATADM_MASK, 0x100);
1478 }
1479
1480 tmp[0] = js1[js1_ind].MR1;
1481 tmp[1] = js1[js1_ind].MR2;
Marek Vasut38dc7562019-08-07 19:17:42 +02001482 data_l = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_MR3_DATA_F1_0);
1483 if (board_cnf->dbi_en)
1484 tmp[2] = data_l | 0xc0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001485 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001486 tmp[2] = data_l & (~0xc0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001487
1488 for (i = 0; i < 2; i++) {
1489 for (csab = 0; csab < CSAB_CNT; csab++) {
1490 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001491 reg_pi_mr1_data_fx_csx[i][csab], tmp[0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001492 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001493 reg_pi_mr2_data_fx_csx[i][csab], tmp[1]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001494 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001495 reg_pi_mr3_data_fx_csx[i][csab], tmp[2]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001496 }
1497 }
1498
Marek Vasut6a131772019-08-07 19:56:09 +02001499 /* DDRPHY INT START */
Marek Vasut38dc7562019-08-07 19:17:42 +02001500 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001501 /* non */
1502 } else {
1503 regif_pll_wa();
1504 }
1505
Marek Vasut6a131772019-08-07 19:56:09 +02001506 /* FREQ_SEL_MULTICAST & PER_CS_TRAINING_MULTICAST SET (for safety) */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001507 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
Marek Vasut6ad74c32019-08-08 16:34:22 +02001508 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001509 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x01);
1510
Marek Vasut6a131772019-08-07 19:56:09 +02001511 /* SET DATA SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001512 for (slice = 0; slice < SLICE_CNT; slice++) {
1513 adr =
1514 DDR_PHY_SLICE_REGSET_OFS +
1515 DDR_PHY_SLICE_REGSET_SIZE * slice;
1516 for (i = 0; i < DDR_PHY_SLICE_REGSET_NUM; i++) {
1517 reg_ddrphy_write_a(adr + i,
1518 _cnf_DDR_PHY_SLICE_REGSET[i]);
1519 }
1520 }
1521
Marek Vasut6a131772019-08-07 19:56:09 +02001522 /* SET ADR SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001523 adr = DDR_PHY_ADR_V_REGSET_OFS;
1524 for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) {
1525 reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_V_REGSET[i]);
1526 }
1527
Marek Vasut6a131772019-08-07 19:56:09 +02001528 if (((prr_product == PRR_PRODUCT_M3) ||
1529 (prr_product == PRR_PRODUCT_M3N)) &&
Marek Vasut38dc7562019-08-07 19:17:42 +02001530 ((0x00ffffff & (uint32_t)((board_cnf->ch[0].ca_swap) >> 40))
Marek Vasut6c245a52018-12-12 18:06:39 +01001531 != 0x00)) {
1532 adr = DDR_PHY_ADR_I_REGSET_OFS + DDR_PHY_ADR_I_REGSET_SIZE;
1533 for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) {
1534 reg_ddrphy_write_a(adr + i,
1535 _cnf_DDR_PHY_ADR_V_REGSET[i]);
1536 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02001537 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1538 _reg_PHY_ADR_DISABLE, 0x02);
Marek Vasut6c245a52018-12-12 18:06:39 +01001539 DDR_PHY_ADR_I_NUM -= 1;
1540 ddr_phycaslice = 1;
1541
1542#ifndef _def_LPDDR4_ODT
1543 for (i = 0; i < 2; i++) {
1544 for (csab = 0; csab < CSAB_CNT; csab++) {
1545 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001546 reg_pi_mr11_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001547 0x66);
1548 }
1549 }
1550#endif/* _def_LPDDR4_ODT */
1551 } else {
1552 ddr_phycaslice = 0;
1553 }
1554
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001555 if (DDR_PHY_ADR_I_NUM > 0) {
1556 for (slice = 0; slice < DDR_PHY_ADR_I_NUM; slice++) {
1557 adr =
1558 DDR_PHY_ADR_I_REGSET_OFS +
1559 DDR_PHY_ADR_I_REGSET_SIZE * slice;
1560 for (i = 0; i < DDR_PHY_ADR_I_REGSET_NUM; i++) {
1561 reg_ddrphy_write_a(adr + i,
1562 _cnf_DDR_PHY_ADR_I_REGSET
1563 [i]);
1564 }
1565 }
1566 }
1567
Marek Vasut6a131772019-08-07 19:56:09 +02001568 /* SET ADRCTRL SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001569 adr = DDR_PHY_ADR_G_REGSET_OFS;
1570 for (i = 0; i < DDR_PHY_ADR_G_REGSET_NUM; i++) {
1571 reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_G_REGSET[i]);
1572 }
1573
Marek Vasut6a131772019-08-07 19:56:09 +02001574 /* SET PI REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001575 adr = DDR_PI_REGSET_OFS;
1576 for (i = 0; i < DDR_PI_REGSET_NUM; i++) {
1577 reg_ddrphy_write_a(adr + i, _cnf_DDR_PI_REGSET[i]);
1578 }
1579}
1580
Marek Vasut6a131772019-08-07 19:56:09 +02001581/* CONFIGURE DDR REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001582static void ddr_config_sub(void)
1583{
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001584 uint32_t i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001585 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001586 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001587 uint32_t tmp;
1588 uint8_t high_byte[SLICE_CNT];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001589 const uint32_t _par_CALVL_DEVICE_MAP = 1;
Marek Vasut80784f92019-08-07 19:02:26 +02001590
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001591 foreach_vch(ch) {
Marek Vasut6a131772019-08-07 19:56:09 +02001592 /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001593 for (slice = 0; slice < SLICE_CNT; slice++) {
1594 high_byte[slice] =
Marek Vasut38dc7562019-08-07 19:17:42 +02001595 (board_cnf->ch[ch].dqs_swap >> (4 * slice)) % 2;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001596 ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE0,
Marek Vasut38dc7562019-08-07 19:17:42 +02001597 board_cnf->ch[ch].dq_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001598 ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE1,
Marek Vasut38dc7562019-08-07 19:17:42 +02001599 board_cnf->ch[ch].dm_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001600 if (high_byte[slice]) {
1601 /* HIGHER 16 BYTE */
1602 ddr_setval_s(ch, slice,
1603 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1604 0x00);
1605 } else {
1606 /* LOWER 16 BYTE */
1607 ddr_setval_s(ch, slice,
1608 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1609 0x01);
1610 }
1611 }
1612
Marek Vasut6a131772019-08-07 19:56:09 +02001613 /* BOARD SETTINGS (CA,ADDR_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001614 data_l = (0x00ffffff & (uint32_t)(board_cnf->ch[ch].ca_swap)) |
Marek Vasut6c245a52018-12-12 18:06:39 +01001615 0x00888888;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001616
1617 /* --- ADR_CALVL_SWIZZLE --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001618 if (prr_product == PRR_PRODUCT_M3) {
1619 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001620 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0,
1621 0x00000000);
Marek Vasut38dc7562019-08-07 19:17:42 +02001622 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001623 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1,
1624 0x00000000);
1625 ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP,
1626 _par_CALVL_DEVICE_MAP);
1627 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001628 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001629 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1, 0x00000000);
1630 ddr_setval(ch, _reg_PHY_CALVL_DEVICE_MAP,
1631 _par_CALVL_DEVICE_MAP);
1632 }
1633
1634 /* --- ADR_ADDR_SEL --- */
Marek Vasut6a131772019-08-07 19:56:09 +02001635 if ((prr_product == PRR_PRODUCT_H3) &&
1636 (prr_cut > PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001637 data_l = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001638 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001639 data_l = 0;
1640 tmp = board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001641 for (i = 0; i < 6; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001642 data_l |= ((tmp & 0x0f) << (i * 5));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001643 tmp = tmp >> 4;
1644 }
1645 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001646 ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01001647 if (ddr_phycaslice == 1) {
1648 /* ----------- adr slice2 swap ----------- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001649 tmp = (uint32_t)((board_cnf->ch[ch].ca_swap) >> 40);
1650 data_l = (tmp & 0x00ffffff) | 0x00888888;
Marek Vasut6c245a52018-12-12 18:06:39 +01001651
1652 /* --- ADR_CALVL_SWIZZLE --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001653 if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001654 ddr_setval_s(ch, 2,
1655 _reg_PHY_ADR_CALVL_SWIZZLE0_0,
1656 data_l);
1657 ddr_setval_s(ch, 2,
1658 _reg_PHY_ADR_CALVL_SWIZZLE1_0,
Marek Vasut6c245a52018-12-12 18:06:39 +01001659 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001660 ddr_setval_s(ch, 2,
1661 _reg_PHY_ADR_CALVL_SWIZZLE0_1,
1662 data_l);
1663 ddr_setval_s(ch, 2,
1664 _reg_PHY_ADR_CALVL_SWIZZLE1_1,
Marek Vasut6c245a52018-12-12 18:06:39 +01001665 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001666 ddr_setval_s(ch, 2,
1667 _reg_PHY_ADR_CALVL_DEVICE_MAP,
Marek Vasut6c245a52018-12-12 18:06:39 +01001668 _par_CALVL_DEVICE_MAP);
1669 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001670 ddr_setval_s(ch, 2,
1671 _reg_PHY_ADR_CALVL_SWIZZLE0,
1672 data_l);
1673 ddr_setval_s(ch, 2,
1674 _reg_PHY_ADR_CALVL_SWIZZLE1,
Marek Vasut6c245a52018-12-12 18:06:39 +01001675 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001676 ddr_setval_s(ch, 2,
1677 _reg_PHY_CALVL_DEVICE_MAP,
Marek Vasut6c245a52018-12-12 18:06:39 +01001678 _par_CALVL_DEVICE_MAP);
1679 }
1680
1681 /* --- ADR_ADDR_SEL --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001682 data_l = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01001683 for (i = 0; i < 6; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001684 data_l |= ((tmp & 0x0f) << (i * 5));
Marek Vasut6c245a52018-12-12 18:06:39 +01001685 tmp = tmp >> 4;
1686 }
1687
Marek Vasut38dc7562019-08-07 19:17:42 +02001688 ddr_setval_s(ch, 2, _reg_PHY_ADR_ADDR_SEL, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01001689 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001690
Marek Vasut6a131772019-08-07 19:56:09 +02001691 /* BOARD SETTINGS (BYTE_ORDER_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001692 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001693 /* --- DATA_BYTE_SWAP --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001694 data_l = 0;
1695 tmp = board_cnf->ch[ch].dqs_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001696 for (i = 0; i < 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001697 data_l |= ((tmp & 0x03) << (i * 2));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001698 tmp = tmp >> 4;
1699 }
1700 } else {
1701 /* --- DATA_BYTE_SWAP --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001702 data_l = board_cnf->ch[ch].dqs_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001703 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_EN, 0x01);
1704 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE0,
Marek Vasut38dc7562019-08-07 19:17:42 +02001705 (data_l) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001706 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE1,
Marek Vasut38dc7562019-08-07 19:17:42 +02001707 (data_l >> 4 * 1) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001708 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE2,
Marek Vasut38dc7562019-08-07 19:17:42 +02001709 (data_l >> 4 * 2) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001710 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE3,
Marek Vasut38dc7562019-08-07 19:17:42 +02001711 (data_l >> 4 * 3) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001712
1713 ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL_HIGH, 0x00);
1714 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001715 ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001716 }
1717}
1718
Marek Vasut80784f92019-08-07 19:02:26 +02001719static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001720{
1721 uint32_t slice;
1722 uint32_t tmp;
1723 uint32_t tgt;
Marek Vasut80784f92019-08-07 19:02:26 +02001724
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001725 if (ddr_csn / 2) {
1726 tgt = 3;
1727 } else {
1728 tgt = 1;
1729 }
1730
1731 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001732 tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001733 if (tgt == tmp)
1734 break;
1735 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001736 tmp = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001737 if (slice % 2)
1738 tmp |= 0x00888888;
1739 *p_swz = tmp;
1740}
1741
1742static void ddr_config_sub_h3v1x(void)
1743{
1744 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001745 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001746 uint32_t tmp;
1747 uint8_t high_byte[SLICE_CNT];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001748 uint32_t ca_swizzle;
1749 uint32_t ca;
1750 uint32_t csmap;
1751 uint32_t o_inv;
1752 uint32_t inv;
1753 uint32_t bit_soc;
1754 uint32_t bit_mem;
1755 uint32_t j;
1756
1757 const uint8_t o_mr15 = 0x55;
1758 const uint8_t o_mr20 = 0x55;
1759 const uint16_t o_mr32_mr40 = 0x5a3c;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001760
1761 foreach_vch(ch) {
Marek Vasut6a131772019-08-07 19:56:09 +02001762 /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001763 csmap = 0;
1764 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001765 tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) &
1766 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001767 high_byte[slice] = tmp % 2;
1768 if (tmp == 1 && (slice >= 2))
1769 csmap |= 0x05;
1770 if (tmp == 3 && (slice >= 2))
1771 csmap |= 0x50;
1772 ddr_setval_s(ch, slice, _reg_PHY_DQ_SWIZZLING,
Marek Vasut38dc7562019-08-07 19:17:42 +02001773 board_cnf->ch[ch].dq_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001774 if (high_byte[slice]) {
1775 /* HIGHER 16 BYTE */
1776 ddr_setval_s(ch, slice,
1777 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1778 0x00);
1779 } else {
1780 /* LOWER 16 BYTE */
1781 ddr_setval_s(ch, slice,
1782 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1783 0x01);
1784 }
1785 }
Marek Vasut6a131772019-08-07 19:56:09 +02001786 /* BOARD SETTINGS (CA,ADDR_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001787 ca = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001788 ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, ca);
1789 ddr_setval(ch, _reg_PHY_CALVL_CS_MAP, csmap);
1790
1791 get_ca_swizzle(ch, 0, &ca_swizzle);
1792
1793 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, ca_swizzle);
1794 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0, 0x00000000);
1795 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, 0x00000000);
1796 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1, 0x00000000);
1797 ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP, 0x01);
1798
1799 for (slice = 0; slice < SLICE_CNT; slice++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001800 ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_NUM,
1801 0x01);
1802 ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_START,
1803 0x08);
1804
1805 if (high_byte[slice])
1806 o_inv = o_mr20;
1807 else
1808 o_inv = o_mr15;
1809
Marek Vasut38dc7562019-08-07 19:17:42 +02001810 tmp = board_cnf->ch[ch].dq_swap[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001811 inv = 0;
1812 j = 0;
1813 for (bit_soc = 0; bit_soc < 8; bit_soc++) {
1814 bit_mem = (tmp >> (4 * bit_soc)) & 0x0f;
1815 j |= (1U << bit_mem);
1816 if (o_inv & (1U << bit_mem))
1817 inv |= (1U << bit_soc);
1818 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001819 data_l = o_mr32_mr40;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001820 if (!high_byte[slice])
Marek Vasut38dc7562019-08-07 19:17:42 +02001821 data_l |= (inv << 24);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001822 if (high_byte[slice])
Marek Vasut38dc7562019-08-07 19:17:42 +02001823 data_l |= (inv << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001824 ddr_setval_s(ch, slice, _reg_PHY_LP4_RDLVL_PATT8,
Marek Vasut38dc7562019-08-07 19:17:42 +02001825 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001826 }
1827 }
1828}
1829
1830static void ddr_config(void)
1831{
1832 int32_t i;
1833 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001834 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001835 uint32_t tmp;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001836 int8_t _adj;
1837 int16_t adj;
1838 uint32_t dq;
1839 union {
1840 uint32_t ui32[4];
1841 uint8_t ui8[16];
1842 } patt;
1843 uint16_t patm;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001844
Marek Vasut6a131772019-08-07 19:56:09 +02001845 /* configure ddrphy registers */
Marek Vasut38dc7562019-08-07 19:17:42 +02001846 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001847 ddr_config_sub_h3v1x();
Marek Vasut6ad74c32019-08-08 16:34:22 +02001848 } else { /* H3 Ver.2.0 or later/M3-N/V3H is same as M3-W */
1849 ddr_config_sub();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001850 }
1851
Marek Vasut6a131772019-08-07 19:56:09 +02001852 /* WDQ_USER_PATT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001853 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001854 for (slice = 0; slice < SLICE_CNT; slice++) {
1855 patm = 0;
1856 for (i = 0; i < 16; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001857 tmp = board_cnf->ch[ch].wdqlvl_patt[i];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001858 patt.ui8[i] = tmp & 0xff;
1859 if (tmp & 0x100)
1860 patm |= (1U << i);
1861 }
1862 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT0,
1863 patt.ui32[0]);
1864 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT1,
1865 patt.ui32[1]);
1866 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT2,
1867 patt.ui32[2]);
1868 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT3,
1869 patt.ui32[3]);
1870 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT4, patm);
1871 }
1872 }
1873
Marek Vasut6a131772019-08-07 19:56:09 +02001874 /* CACS DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001875 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001876 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
1877 0x00U);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001878 foreach_vch(ch) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001879 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001880 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001881 ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET,
1882 _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001883 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001884 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001885 ddr_regdef_adr
1886 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]),
1887 _cnf_DDR_PHY_ADR_V_REGSET
1888 [ddr_regdef_adr
1889 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001890 DDR_PHY_ADR_V_REGSET_OFS]);
1891 }
1892
1893 for (i = (_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4);
1894 i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001895 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001896 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1897 _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001898 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001899 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001900 ddr_regdef_adr
1901 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]),
1902 _cnf_DDR_PHY_ADR_G_REGSET
1903 [ddr_regdef_adr
1904 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001905 DDR_PHY_ADR_G_REGSET_OFS]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001906 }
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001907
Marek Vasut6c245a52018-12-12 18:06:39 +01001908 if (ddr_phycaslice == 1) {
1909 for (i = 0; i < 6; i++) {
Marek Vasut6a131772019-08-07 19:56:09 +02001910 adj = _f_scale_adj
1911 (board_cnf->ch[ch].cacs_adj
1912 [i +
1913 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001914 ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET,
Marek Vasut6ad74c32019-08-08 16:34:22 +02001915 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
1916 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001917 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001918 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001919 ddr_regdef_adr
1920 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) +
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001921 0x0100,
Marek Vasut6a131772019-08-07 19:56:09 +02001922 _cnf_DDR_PHY_ADR_V_REGSET
1923 [ddr_regdef_adr
1924 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001925 DDR_PHY_ADR_V_REGSET_OFS]);
Marek Vasut6c245a52018-12-12 18:06:39 +01001926 }
1927 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001928 }
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001929
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001930 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
Marek Vasut6ad74c32019-08-08 16:34:22 +02001931 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001932
Marek Vasut6a131772019-08-07 19:56:09 +02001933 /* WDQDM DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001934 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001935 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001936 for (slice = 0; slice < SLICE_CNT; slice++) {
1937 for (i = 0; i <= 8; i++) {
1938 dq = slice * 8 + i;
1939 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02001940 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001941 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001942 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001943 adj = _f_scale_adj(_adj);
1944 ddr_setval_s(ch, slice,
1945 _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001946 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001947 }
1948 }
1949 }
1950
Marek Vasut6a131772019-08-07 19:56:09 +02001951 /* RDQDM DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001952 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001953 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001954 for (slice = 0; slice < SLICE_CNT; slice++) {
1955 for (i = 0; i <= 8; i++) {
1956 dq = slice * 8 + i;
1957 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02001958 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001959 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001960 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001961 adj = _f_scale_adj(_adj);
1962 ddr_setval_s(ch, slice,
1963 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY
Marek Vasut38dc7562019-08-07 19:17:42 +02001964 [i], data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001965 ddr_setval_s(ch, slice,
1966 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
Marek Vasut38dc7562019-08-07 19:17:42 +02001967 [i], data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001968 }
1969 }
1970 }
1971}
1972
Marek Vasut6a131772019-08-07 19:56:09 +02001973/* DBSC register setting functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001974static void dbsc_regset_pre(void)
1975{
1976 uint32_t ch, csab;
Marek Vasut38dc7562019-08-07 19:17:42 +02001977 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001978
Marek Vasut6a131772019-08-07 19:56:09 +02001979 /* PRIMARY SETTINGS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001980 /* LPDDR4, BL=16, DFI interface */
1981 mmio_write_32(DBSC_DBKIND, 0x0000000a);
1982 mmio_write_32(DBSC_DBBL, 0x00000002);
1983 mmio_write_32(DBSC_DBPHYCONF0, 0x00000001);
1984
1985 /* FREQRATIO=2 */
1986 mmio_write_32(DBSC_DBSYSCONF1, 0x00000002);
1987
1988 /* Chanel map (H3 Ver.1.x) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001989 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001990 mmio_write_32(DBSC_DBSCHCNT1, 0x00001010);
1991
1992 /* DRAM SIZE REGISTER:
1993 * set all ranks as density=0(4Gb) for PHY initialization
1994 */
Marek Vasut6ad74c32019-08-08 16:34:22 +02001995 foreach_vch(ch) {
1996 for (csab = 0; csab < 4; csab++) {
1997 mmio_write_32(DBSC_DBMEMCONF(ch, csab),
1998 DBMEMCONF_REGD(0));
1999 }
2000 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002001
Marek Vasut38dc7562019-08-07 19:17:42 +02002002 if (prr_product == PRR_PRODUCT_M3) {
2003 data_l = 0xe4e4e4e4;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002004 foreach_ech(ch) {
2005 if ((ddr_phyvalid & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02002006 data_l = (data_l & (~(0x000000FF << (ch * 8))))
2007 | (((board_cnf->ch[ch].dqs_swap & 0x0003)
2008 | ((board_cnf->ch[ch].dqs_swap & 0x0030)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002009 >> 2)
Marek Vasut38dc7562019-08-07 19:17:42 +02002010 | ((board_cnf->ch[ch].dqs_swap & 0x0300)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002011 >> 4)
Marek Vasut38dc7562019-08-07 19:17:42 +02002012 | ((board_cnf->ch[ch].dqs_swap & 0x3000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002013 >> 6)) << (ch * 8));
2014 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002015 mmio_write_32(DBSC_DBBSWAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002016 }
2017}
2018
2019static void dbsc_regset(void)
2020{
2021 int32_t i;
2022 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002023 uint32_t data_l;
2024 uint32_t data_l2;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002025 uint32_t tmp[4];
2026
2027 /* RFC */
Marek Vasut6a131772019-08-07 19:56:09 +02002028 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_20) &&
2029 (max_density == 0)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002030 js2[js2_trfcab] =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002031 _f_scale(ddr_mbps, ddr_mbpsdiv,
Marek Vasut38dc7562019-08-07 19:17:42 +02002032 1UL * jedec_spec2_trfc_ab[1] * 1000, 0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002033 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002034 js2[js2_trfcab] =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002035 _f_scale(ddr_mbps, ddr_mbpsdiv,
Marek Vasut38dc7562019-08-07 19:17:42 +02002036 1UL * jedec_spec2_trfc_ab[max_density] *
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002037 1000, 0);
2038 }
2039
2040 /* DBTR0.CL : RL */
2041 mmio_write_32(DBSC_DBTR(0), RL);
2042
2043 /* DBTR1.CWL : WL */
2044 mmio_write_32(DBSC_DBTR(1), WL);
2045
2046 /* DBTR2.AL : 0 */
2047 mmio_write_32(DBSC_DBTR(2), 0);
2048
2049 /* DBTR3.TRCD: tRCD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002050 mmio_write_32(DBSC_DBTR(3), js2[js2_trcd]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002051
2052 /* DBTR4.TRPA,TRP: tRPab,tRPpb */
Marek Vasut38dc7562019-08-07 19:17:42 +02002053 mmio_write_32(DBSC_DBTR(4), (js2[js2_trpab] << 16) | js2[js2_trppb]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002054
2055 /* DBTR5.TRC : use tRCpb */
Marek Vasut38dc7562019-08-07 19:17:42 +02002056 mmio_write_32(DBSC_DBTR(5), js2[js2_trcpb]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002057
2058 /* DBTR6.TRAS : tRAS */
Marek Vasut38dc7562019-08-07 19:17:42 +02002059 mmio_write_32(DBSC_DBTR(6), js2[js2_tras]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002060
2061 /* DBTR7.TRRD : tRRD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002062 mmio_write_32(DBSC_DBTR(7), (js2[js2_trrd] << 16) | js2[js2_trrd]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002063
2064 /* DBTR8.TFAW : tFAW */
Marek Vasut38dc7562019-08-07 19:17:42 +02002065 mmio_write_32(DBSC_DBTR(8), js2[js2_tfaw]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002066
2067 /* DBTR9.TRDPR : tRTP */
Marek Vasut38dc7562019-08-07 19:17:42 +02002068 mmio_write_32(DBSC_DBTR(9), js2[js2_trtp]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002069
Marek Vasut38dc7562019-08-07 19:17:42 +02002070 /* DBTR10.TWR : nwr */
2071 mmio_write_32(DBSC_DBTR(10), js1[js1_ind].nwr);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002072
2073 /* DBTR11.TRDWR : RL + tDQSCK + BL/2 + Rounddown(tRPST) - WL + tWPRE */
2074 mmio_write_32(DBSC_DBTR(11),
Marek Vasut38dc7562019-08-07 19:17:42 +02002075 RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002076
2077 /* DBTR12.TWRRD : WL + 1 + BL/2 + tWTR */
Marek Vasut38dc7562019-08-07 19:17:42 +02002078 data_l = WL + 1 + (16 / 2) + js2[js2_twtr];
2079 mmio_write_32(DBSC_DBTR(12), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002080
Marek Vasut6c245a52018-12-12 18:06:39 +01002081 /* DBTR13.TRFCAB : tRFCab */
Marek Vasut38dc7562019-08-07 19:17:42 +02002082 mmio_write_32(DBSC_DBTR(13), (js2[js2_trfcab]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002083
2084 /* DBTR14.TCKEHDLL,tCKEH : tCKEHCMD,tCKEHCMD */
2085 mmio_write_32(DBSC_DBTR(14),
Marek Vasut38dc7562019-08-07 19:17:42 +02002086 (js2[js2_tckehcmd] << 16) | (js2[js2_tckehcmd]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002087
2088 /* DBTR15.TCKESR,TCKEL : tSR,tCKELPD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002089 mmio_write_32(DBSC_DBTR(15), (js2[js2_tsr] << 16) | (js2[js2_tckelpd]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002090
2091 /* DBTR16 */
2092 /* WDQL : tphy_wrlat + tphy_wrdata */
2093 tmp[0] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1);
Marek Vasut3af20052019-02-25 14:57:08 +01002094 /* DQENLTNCY : tphy_wrlat = WL-2 : PHY_WRITE_PATH_LAT_ADD == 0
2095 * tphy_wrlat = WL-3 : PHY_WRITE_PATH_LAT_ADD != 0
2096 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002097 tmp[1] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1);
2098 /* DQL : tphy_rdlat + trdata_en */
2099 /* it is not important for dbsc */
2100 tmp[2] = RL + 16;
2101 /* DQIENLTNCY : trdata_en */
2102 tmp[3] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1) - 1;
2103 mmio_write_32(DBSC_DBTR(16),
2104 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2105
2106 /* DBTR24 */
2107 /* WRCSLAT = WRLAT -5 */
2108 tmp[0] -= 5;
2109 /* WRCSGAP = 5 */
2110 tmp[1] = 5;
2111 /* RDCSLAT = RDLAT_ADJ +2 */
Marek Vasut38dc7562019-08-07 19:17:42 +02002112 if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6c245a52018-12-12 18:06:39 +01002113 tmp[2] = tmp[3];
2114 } else {
2115 tmp[2] = tmp[3] + 2;
2116 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002117 /* RDCSGAP = 6 */
Marek Vasut38dc7562019-08-07 19:17:42 +02002118 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002119 tmp[3] = 4;
2120 } else {
2121 tmp[3] = 6;
2122 }
2123 mmio_write_32(DBSC_DBTR(24),
2124 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2125
2126 /* DBTR17.TMODRD,TMOD,TRDMR: tMRR,tMRD,(0) */
2127 mmio_write_32(DBSC_DBTR(17),
Marek Vasut38dc7562019-08-07 19:17:42 +02002128 (js2[js2_tmrr] << 24) | (js2[js2_tmrd] << 16));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002129
2130 /* DBTR18.RODTL, RODTA, WODTL, WODTA : do not use in LPDDR4 */
2131 mmio_write_32(DBSC_DBTR(18), 0);
2132
2133 /* DBTR19.TZQCL, TZQCS : do not use in LPDDR4 */
2134 mmio_write_32(DBSC_DBTR(19), 0);
2135
2136 /* DBTR20.TXSDLL, TXS : tRFCab+tCKEHCMD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002137 data_l = js2[js2_trfcab] + js2[js2_tckehcmd];
2138 mmio_write_32(DBSC_DBTR(20), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002139
2140 /* DBTR21.TCCD */
2141 /* DBTR23.TCCD */
2142 /* H3 Ver.1.0 cannot use TBTR23 feature */
2143 if (ddr_tccd == 8 &&
Marek Vasut38dc7562019-08-07 19:17:42 +02002144 !((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_10))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002145 ) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002146 data_l = 8;
2147 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002148 mmio_write_32(DBSC_DBTR(23), 0x00000002);
2149 } else if (ddr_tccd <= 11) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002150 data_l = 11;
2151 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002152 mmio_write_32(DBSC_DBTR(23), 0x00000000);
2153 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002154 data_l = ddr_tccd;
2155 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002156 mmio_write_32(DBSC_DBTR(23), 0x00000000);
2157 }
2158
2159 /* DBTR22.ZQLAT : */
Marek Vasut38dc7562019-08-07 19:17:42 +02002160 data_l = js2[js2_tzqcalns] * 100; /* 1000 * 1000 ps */
2161 data_l = (data_l << 16) | (js2[js2_tzqlat] + 24 + 20);
2162 mmio_write_32(DBSC_DBTR(22), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002163
2164 /* DBTR25 : do not use in LPDDR4 */
2165 mmio_write_32(DBSC_DBTR(25), 0);
2166
2167 /* DBRNK : */
2168 /*
2169 * DBSC_DBRNK2 rkrr
2170 * DBSC_DBRNK3 rkrw
2171 * DBSC_DBRNK4 rkwr
2172 * DBSC_DBRNK5 rkww
2173 */
2174#define _par_DBRNK_VAL (0x7007)
2175
2176 for (i = 0; i < 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002177 data_l = (_par_DBRNK_VAL >> (i * 4)) & 0x0f;
Marek Vasut6a131772019-08-07 19:56:09 +02002178 if ((prr_product == PRR_PRODUCT_H3) &&
2179 (prr_cut > PRR_PRODUCT_11) && (i == 0)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002180 data_l += 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002181 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002182 data_l2 = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002183 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002184 data_l2 = data_l2 | (data_l << (4 * ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002185 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002186 mmio_write_32(DBSC_DBRNK(2 + i), data_l2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002187 }
2188 mmio_write_32(DBSC_DBADJ0, 0x00000000);
2189
Marek Vasut6a131772019-08-07 19:56:09 +02002190 /* timing registers for Scheduler */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002191 /* SCFCTST0 */
2192 /* SCFCTST0 ACT-ACT */
Marek Vasut38dc7562019-08-07 19:17:42 +02002193 tmp[3] = 1UL * js2[js2_trcpb] * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002194 /* SCFCTST0 RDA-ACT */
2195 tmp[2] =
Marek Vasut38dc7562019-08-07 19:17:42 +02002196 1UL * ((16 / 2) + js2[js2_trtp] - 8 +
2197 js2[js2_trppb]) * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002198 /* SCFCTST0 WRA-ACT */
2199 tmp[1] =
2200 1UL * (WL + 1 + (16 / 2) +
Marek Vasut38dc7562019-08-07 19:17:42 +02002201 js1[js1_ind].nwr) * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002202 /* SCFCTST0 PRE-ACT */
Marek Vasut38dc7562019-08-07 19:17:42 +02002203 tmp[0] = 1UL * js2[js2_trppb];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002204 mmio_write_32(DBSC_SCFCTST0,
2205 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2206
2207 /* SCFCTST1 */
2208 /* SCFCTST1 RD-WR */
2209 tmp[3] =
2210 1UL * (mmio_read_32(DBSC_DBTR(11)) & 0xff) * 800 * ddr_mbpsdiv /
2211 ddr_mbps;
2212 /* SCFCTST1 WR-RD */
2213 tmp[2] =
2214 1UL * (mmio_read_32(DBSC_DBTR(12)) & 0xff) * 800 * ddr_mbpsdiv /
2215 ddr_mbps;
2216 /* SCFCTST1 ACT-RD/WR */
Marek Vasut38dc7562019-08-07 19:17:42 +02002217 tmp[1] = 1UL * js2[js2_trcd] * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002218 /* SCFCTST1 ASYNCOFS */
2219 tmp[0] = 12;
2220 mmio_write_32(DBSC_SCFCTST1,
2221 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2222
2223 /* DBSCHRW1 */
2224 /* DBSCHRW1 SCTRFCAB */
Marek Vasut38dc7562019-08-07 19:17:42 +02002225 tmp[0] = 1UL * js2[js2_trfcab] * 800 * ddr_mbpsdiv / ddr_mbps;
2226 data_l = (((mmio_read_32(DBSC_DBTR(16)) & 0x00FF0000) >> 16)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002227 + (mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
2228 + (0x28 * 2)) * 400 * 2 * ddr_mbpsdiv / ddr_mbps + 7;
Marek Vasut38dc7562019-08-07 19:17:42 +02002229 if (tmp[0] < data_l)
2230 tmp[0] = data_l;
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002231
Marek Vasut38dc7562019-08-07 19:17:42 +02002232 if ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30)) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002233 mmio_write_32(DBSC_DBSCHRW1, tmp[0]
2234 + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
Marek Vasut6ad74c32019-08-08 16:34:22 +02002235 * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) /
2236 ddr_mbps - 3);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002237 } else {
2238 mmio_write_32(DBSC_DBSCHRW1, tmp[0]
2239 + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
Marek Vasut6ad74c32019-08-08 16:34:22 +02002240 * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) /
2241 ddr_mbps);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002242 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002243
Marek Vasut6a131772019-08-07 19:56:09 +02002244 /* QOS and CAM */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002245#ifdef ddr_qos_init_setting /* only for non qos_init */
2246 /*wbkwait(0004), wbkmdhi(4,2),wbkmdlo(1,8) */
2247 mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218);
2248 /*0(fillunit),8(dirtymax),4(dirtymin) */
2249 mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4);
2250 /*stop_tolerance */
2251 mmio_write_32(DBSC_DBSCHRW0, 0x22421111);
2252 /*rd-wr/wr-rd toggle priority */
2253 mmio_write_32(DBSC_SCFCTST2, 0x012F1123);
2254 mmio_write_32(DBSC_DBSCHSZ0, 0x00000001);
2255 mmio_write_32(DBSC_DBSCHCNT0, 0x000F0037);
2256
2257 /* QoS Settings */
2258 mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00U);
2259 mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00U);
2260 mmio_write_32(DBSC_DBSCHQOS02, 0x00000000U);
2261 mmio_write_32(DBSC_DBSCHQOS03, 0x00000000U);
2262 mmio_write_32(DBSC_DBSCHQOS40, 0x00000300U);
2263 mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0U);
2264 mmio_write_32(DBSC_DBSCHQOS42, 0x00000200U);
2265 mmio_write_32(DBSC_DBSCHQOS43, 0x00000100U);
2266 mmio_write_32(DBSC_DBSCHQOS90, 0x00000100U);
2267 mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0U);
2268 mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0U);
2269 mmio_write_32(DBSC_DBSCHQOS93, 0x00000040U);
2270 mmio_write_32(DBSC_DBSCHQOS120, 0x00000040U);
2271 mmio_write_32(DBSC_DBSCHQOS121, 0x00000030U);
2272 mmio_write_32(DBSC_DBSCHQOS122, 0x00000020U);
2273 mmio_write_32(DBSC_DBSCHQOS123, 0x00000010U);
2274 mmio_write_32(DBSC_DBSCHQOS130, 0x00000100U);
2275 mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0U);
2276 mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0U);
2277 mmio_write_32(DBSC_DBSCHQOS133, 0x00000040U);
2278 mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0U);
2279 mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0U);
2280 mmio_write_32(DBSC_DBSCHQOS142, 0x00000080U);
2281 mmio_write_32(DBSC_DBSCHQOS143, 0x00000040U);
2282 mmio_write_32(DBSC_DBSCHQOS150, 0x00000040U);
2283 mmio_write_32(DBSC_DBSCHQOS151, 0x00000030U);
2284 mmio_write_32(DBSC_DBSCHQOS152, 0x00000020U);
2285 mmio_write_32(DBSC_DBSCHQOS153, 0x00000010U);
2286
2287 mmio_write_32(QOSCTRL_RAEN, 0x00000001U);
2288#endif /* ddr_qos_init_setting */
2289 /* H3 Ver.1.1 need to set monitor function */
Marek Vasut38dc7562019-08-07 19:17:42 +02002290 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002291 mmio_write_32(DBSC_DBMONCONF4, 0x00700000);
2292 }
2293
Marek Vasut38dc7562019-08-07 19:17:42 +02002294 if (prr_product == PRR_PRODUCT_H3) {
2295 if (prr_cut == PRR_PRODUCT_10) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002296 /* resrdis, simple mode, sc off */
2297 mmio_write_32(DBSC_DBBCAMDIS, 0x00000007);
Marek Vasut38dc7562019-08-07 19:17:42 +02002298 } else if (prr_cut == PRR_PRODUCT_11) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002299 /* resrdis, simple mode */
2300 mmio_write_32(DBSC_DBBCAMDIS, 0x00000005);
Marek Vasut38dc7562019-08-07 19:17:42 +02002301 } else if (prr_cut < PRR_PRODUCT_30) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002302 /* H3 Ver.2.0 */
2303 /* resrdis */
2304 mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
2305 } else { /* H3 Ver.3.0(include H3N) */
2306 /* exprespque */
2307 mmio_write_32(DBSC_DBBCAMDIS, 0x00000010);
2308 }
2309 } else { /* M3-W/M3-N/V3H */
2310 /* resrdis */
2311 mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
2312 }
2313}
2314
2315static void dbsc_regset_post(void)
2316{
2317 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02002318 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002319 uint32_t slice, rdlat_max, rdlat_min;
2320
2321 rdlat_max = 0;
2322 rdlat_min = 0xffff;
2323 foreach_vch(ch) {
2324 for (cs = 0; cs < CS_CNT; cs++) {
2325 if ((ch_have_this_cs[cs] & (1U << ch)) != 0) {
2326 for (slice = 0; slice < SLICE_CNT; slice++) {
2327 ddr_setval_s(ch, slice,
2328 _reg_PHY_PER_CS_TRAINING_INDEX,
2329 cs);
Marek Vasut6ad74c32019-08-08 16:34:22 +02002330 data_l = ddr_getval_s(ch, slice,
2331 _reg_PHY_RDDQS_LATENCY_ADJUST);
Marek Vasut38dc7562019-08-07 19:17:42 +02002332 if (data_l > rdlat_max)
2333 rdlat_max = data_l;
2334 if (data_l < rdlat_min)
2335 rdlat_min = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002336 }
2337 }
2338 }
2339 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002340 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002341 mmio_write_32(DBSC_DBTR(24),
2342 ((rdlat_max * 2 - rdlat_min + 4) << 24) +
2343 ((rdlat_min + 2) << 16) +
2344 mmio_read_32(DBSC_DBTR(24)));
2345 } else {
2346 mmio_write_32(DBSC_DBTR(24),
2347 ((rdlat_max + 2) << 24) +
2348 ((rdlat_max + 2) << 16) +
2349 mmio_read_32(DBSC_DBTR(24)));
2350 }
2351
2352 /* set ddr density information */
2353 foreach_ech(ch) {
2354 for (cs = 0; cs < CS_CNT; cs++) {
2355 if (ddr_density[ch][cs] == 0xff) {
2356 mmio_write_32(DBSC_DBMEMCONF(ch, cs), 0x00);
2357 } else {
2358 mmio_write_32(DBSC_DBMEMCONF(ch, cs),
2359 DBMEMCONF_REGD(ddr_density[ch]
2360 [cs]));
2361 }
2362 }
2363 mmio_write_32(DBSC_DBMEMCONF(ch, 2), 0x00000000);
2364 mmio_write_32(DBSC_DBMEMCONF(ch, 3), 0x00000000);
2365 }
2366
2367 mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010);
2368
2369 /*set DBI */
Marek Vasut38dc7562019-08-07 19:17:42 +02002370 if (board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002371 mmio_write_32(DBSC_DBDBICNT, 0x00000003);
2372
2373 /* H3 Ver.2.0 or later/M3-N/V3H DBI wa */
Marek Vasut6a131772019-08-07 19:56:09 +02002374 if ((((prr_product == PRR_PRODUCT_H3) &&
2375 (prr_cut > PRR_PRODUCT_11)) ||
2376 (prr_product == PRR_PRODUCT_M3N) ||
2377 (prr_product == PRR_PRODUCT_V3H)) &&
2378 board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002379 reg_ddrphy_write_a(0x00001010, 0x01000000);
2380
2381 /*set REFCYCLE */
Marek Vasut38dc7562019-08-07 19:17:42 +02002382 data_l = (get_refperiod()) * ddr_mbps / 2000 / ddr_mbpsdiv;
2383 mmio_write_32(DBSC_DBRFCNF1, 0x00080000 | (data_l & 0x0000ffff));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002384 mmio_write_32(DBSC_DBRFCNF2, 0x00010000 | DBSC_REFINTS);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002385
2386#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02002387 if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002388#ifdef DDR_BACKUPMODE_HALF /* for Half channel(ch0,1 only) */
Marek Vasut38dc7562019-08-07 19:17:42 +02002389 DEBUG(" DEBUG_MESS : DDR_BACKUPMODE_HALF ", 1);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002390 send_dbcmd(0x08040001);
2391 wait_dbcmd();
2392 send_dbcmd(0x0A040001);
2393 wait_dbcmd();
2394 send_dbcmd(0x04040010);
2395 wait_dbcmd();
2396
Marek Vasut38dc7562019-08-07 19:17:42 +02002397 if (prr_product == PRR_PRODUCT_H3) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002398 send_dbcmd(0x08140001);
2399 wait_dbcmd();
2400 send_dbcmd(0x0A140001);
2401 wait_dbcmd();
2402 send_dbcmd(0x04140010);
2403 wait_dbcmd();
2404 }
2405#else /* DDR_BACKUPMODE_HALF //for All channels */
2406 send_dbcmd(0x08840001);
2407 wait_dbcmd();
2408 send_dbcmd(0x0A840001);
2409 wait_dbcmd();
2410
2411 send_dbcmd(0x04840010);
2412 wait_dbcmd();
2413#endif /* DDR_BACKUPMODE_HALF */
2414 }
2415#endif /* DDR_BACKUPMODE */
2416
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002417#if RCAR_REWT_TRAINING != 0
2418 /* Periodic-WriteDQ Training seeting */
Marek Vasut6a131772019-08-07 19:56:09 +02002419 if (((prr_product == PRR_PRODUCT_H3) &&
2420 (prr_cut <= PRR_PRODUCT_11)) ||
2421 ((prr_product == PRR_PRODUCT_M3) &&
2422 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002423 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2424 } else {
Marek Vasut6a131772019-08-07 19:56:09 +02002425 /*
2426 * H3 Ver.2.0 or later/M3-W Ver.1.1 or
2427 * later/M3-N/V3H -> Periodic-WriteDQ Training seeting
2428 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002429
2430 /* Periodic WriteDQ Training seeting */
2431 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000);
2432
2433 ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04);
2434 ddr_setval_ach_as(_reg_PHY_WDQLVL_QTR_DLY_STEP, 0x0F);
2435 ddr_setval_ach_as(_reg_PHY_WDQLVL_DLY_STEP, 0x50);
2436 ddr_setval_ach_as(_reg_PHY_WDQLVL_DQDM_SLV_DLY_START, 0x0300);
2437
2438 ddr_setval_ach(_reg_PI_WDQLVL_CS_MAP,
2439 ddrtbl_getval(_cnf_DDR_PI_REGSET,
2440 _reg_PI_WDQLVL_CS_MAP));
2441 ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f);
2442 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
2443 ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
2444 ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01);
2445 ddr_setval_ach(_reg_PI_TREF_F0, 0x0000);
2446 ddr_setval_ach(_reg_PI_TREF_F1, 0x0000);
2447 ddr_setval_ach(_reg_PI_TREF_F2, 0x0000);
2448
Marek Vasut38dc7562019-08-07 19:17:42 +02002449 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002450 ddr_setval_ach(_reg_PI_WDQLVL_EN, 0x02);
2451 } else {
2452 ddr_setval_ach(_reg_PI_WDQLVL_EN_F1, 0x02);
2453 }
2454 ddr_setval_ach(_reg_PI_WDQLVL_PERIODIC, 0x01);
2455
2456 /* DFI_PHYMSTR_ACK , WTmode setting */
Marek Vasut6ad74c32019-08-08 16:34:22 +02002457 /* DFI_PHYMSTR_ACK: WTmode =b'01 */
2458 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002459 }
2460#endif /* RCAR_REWT_TRAINING */
2461 /* periodic dram zqcal and phy ctrl update enable */
2462 mmio_write_32(DBSC_DBCALCNF, 0x01000010);
Marek Vasut6a131772019-08-07 19:56:09 +02002463 if (((prr_product == PRR_PRODUCT_H3) &&
2464 (prr_cut <= PRR_PRODUCT_11)) ||
2465 ((prr_product == PRR_PRODUCT_M3) &&
2466 (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002467 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
2468 } else {
2469#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02002470 if ((prr_product == PRR_PRODUCT_H3) &&
2471 (board_cnf->phyvalid == 0x05))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002472 mmio_write_32(DBSC_DBDFICUPDCNF, 0x2a240001);
2473 else
2474 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2475#else /* RCAR_DRAM_SPLIT == 2 */
2476 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2477#endif /* RCAR_DRAM_SPLIT == 2 */
2478 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002479
2480 mmio_write_32(DBSC_DBRFEN, 0x00000001);
2481 /* dram access enable */
2482 mmio_write_32(DBSC_DBACEN, 0x00000001);
2483
Marek Vasut6ad74c32019-08-08 16:34:22 +02002484 MSG_LF(__func__ "(done)");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002485}
2486
Marek Vasut6a131772019-08-07 19:56:09 +02002487/* DFI_INIT_START */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002488static uint32_t dfi_init_start(void)
2489{
2490 uint32_t ch;
2491 uint32_t phytrainingok;
2492 uint32_t retry;
Marek Vasut38dc7562019-08-07 19:17:42 +02002493 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002494 const uint32_t RETRY_MAX = 0x10000;
2495
Marek Vasut38dc7562019-08-07 19:17:42 +02002496 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002497 /* PLL3 Disable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002498 /* protect register interface */
2499 ddrphy_regif_idle();
2500
2501 pll3_control(0);
2502
Marek Vasut6a131772019-08-07 19:56:09 +02002503 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002504 /* dbdficnt0:
2505 * dfi_dram_clk_disable=1
2506 * dfi_frequency = 0
2507 * freq_ratio = 01 (2:1)
2508 * init_start =0
2509 */
2510 foreach_vch(ch)
2511 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
2512 dsb_sev();
2513
2514 /* dbdficnt0:
2515 * dfi_dram_clk_disable=1
2516 * dfi_frequency = 0
2517 * freq_ratio = 01 (2:1)
2518 * init_start =1
2519 */
2520 foreach_vch(ch)
2521 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
2522 dsb_sev();
2523
2524 } else {
2525 ddr_setval_ach_as(_reg_PHY_DLL_RST_EN, 0x02);
2526 dsb_sev();
2527 ddrphy_regif_idle();
2528 }
2529
2530 /* dll_rst negate */
2531 foreach_vch(ch)
2532 mmio_write_32(DBSC_DBPDCNT3(ch), 0x0000CF01);
2533 dsb_sev();
2534
Marek Vasut6a131772019-08-07 19:56:09 +02002535 /* wait init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002536 phytrainingok = 0;
2537 retry = 0;
2538 while (retry++ < RETRY_MAX) {
2539 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002540 data_l = mmio_read_32(DBSC_DBDFISTAT(ch));
2541 if (data_l & 0x00000001)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002542 phytrainingok |= (1U << ch);
2543 }
2544 dsb_sev();
2545 if (phytrainingok == ddr_phyvalid)
2546 break;
2547 if (retry % 256 == 0)
2548 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
2549 }
2550
Marek Vasut6a131772019-08-07 19:56:09 +02002551 /* all ch ok? */
2552 if ((phytrainingok & ddr_phyvalid) != ddr_phyvalid)
2553 return 0xff;
2554
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002555 /* dbdficnt0:
2556 * dfi_dram_clk_disable=0
2557 * dfi_frequency = 0
2558 * freq_ratio = 01 (2:1)
2559 * init_start =0
2560 */
2561 foreach_vch(ch)
2562 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000010);
2563 dsb_sev();
2564
2565 return 0;
2566}
2567
Marek Vasut6a131772019-08-07 19:56:09 +02002568/* drivablity setting : CMOS MODE ON/OFF */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002569static void change_lpddr4_en(uint32_t mode)
2570{
2571 uint32_t ch;
2572 uint32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002573 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002574 const uint32_t _reg_PHY_PAD_DRIVE_X[3] = {
2575 _reg_PHY_PAD_ADDR_DRIVE,
2576 _reg_PHY_PAD_CLK_DRIVE,
2577 _reg_PHY_PAD_CS_DRIVE
2578 };
2579
Marek Vasut6c245a52018-12-12 18:06:39 +01002580 foreach_vch(ch) {
2581 for (i = 0; i < 3; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002582 data_l = ddr_getval(ch, _reg_PHY_PAD_DRIVE_X[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002583 if (mode) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002584 data_l |= (1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002585 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002586 data_l &= ~(1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002587 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002588 ddr_setval(ch, _reg_PHY_PAD_DRIVE_X[i], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002589 }
2590 }
2591}
2592
Marek Vasut6a131772019-08-07 19:56:09 +02002593/* drivablity setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002594static uint32_t set_term_code(void)
2595{
2596 int32_t i;
2597 uint32_t ch, index;
Marek Vasut38dc7562019-08-07 19:17:42 +02002598 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002599 uint32_t chip_id[2];
2600 uint32_t term_code;
2601 uint32_t override;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002602 uint32_t pvtr;
2603 uint32_t pvtp;
2604 uint32_t pvtn;
Marek Vasut80784f92019-08-07 19:02:26 +02002605
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002606 term_code = ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2607 _reg_PHY_PAD_DATA_TERM);
2608 override = 0;
2609 for (i = 0; i < 2; i++)
2610 chip_id[i] = mmio_read_32(LIFEC_CHIPID(i));
2611
2612 index = 0;
2613 while (1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002614 if (termcode_by_sample[index][0] == 0xffffffff) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002615 break;
2616 }
Marek Vasut6a131772019-08-07 19:56:09 +02002617 if ((termcode_by_sample[index][0] == chip_id[0]) &&
2618 (termcode_by_sample[index][1] == chip_id[1])) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002619 term_code = termcode_by_sample[index][2];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002620 override = 1;
2621 break;
2622 }
2623 index++;
2624 }
2625
2626 if (override) {
2627 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002628 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002629 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2630 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002631 data_l = (data_l & 0xfffe0000) | term_code;
2632 ddr_setval_ach(_reg_PHY_PAD_TERM_X[index], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002633 }
Marek Vasut6a131772019-08-07 19:56:09 +02002634 } else if ((prr_product == PRR_PRODUCT_M3) &&
2635 (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002636 /* non */
2637 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002638 ddr_setval_ach(_reg_PHY_PAD_TERM_X[0],
2639 (ddrtbl_getval
2640 (_cnf_DDR_PHY_ADR_G_REGSET,
2641 _reg_PHY_PAD_TERM_X[0]) & 0xFFFE0000));
2642 ddr_setval_ach(_reg_PHY_CAL_CLEAR_0, 0x01);
2643 ddr_setval_ach(_reg_PHY_CAL_START_0, 0x01);
2644 foreach_vch(ch) {
2645 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002646 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002647 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002648 } while (!(data_l & 0x00800000));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002649 }
Marek Vasut6a131772019-08-07 19:56:09 +02002650 if ((prr_product == PRR_PRODUCT_H3) &&
2651 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002652 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002653 data_l = ddr_getval(ch, _reg_PHY_PAD_TERM_X[0]);
2654 pvtr = (data_l >> 12) & 0x1f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002655 pvtr += 8;
2656 if (pvtr > 0x1f)
2657 pvtr = 0x1f;
Marek Vasut38dc7562019-08-07 19:17:42 +02002658 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002659 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002660 pvtn = (data_l >> 6) & 0x03f;
2661 pvtp = (data_l >> 0) & 0x03f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002662
2663 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2664 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002665 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002666 ddrtbl_getval
2667 (_cnf_DDR_PHY_ADR_G_REGSET,
2668 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002669 data_l = (data_l & 0xfffe0000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002670 | (pvtr << 12)
2671 | (pvtn << 6)
2672 | (pvtp);
2673 ddr_setval(ch,
2674 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002675 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002676 }
2677 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02002678 } else {
2679 /* M3-W Ver.1.1 or later/H3 Ver.2.0 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002680 foreach_vch(ch) {
2681 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2682 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002683 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002684 ddr_getval(ch,
2685 _reg_PHY_PAD_TERM_X
2686 [index]);
2687 ddr_setval(ch,
2688 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002689 (data_l & 0xFFFE0FFF) |
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002690 0x00015000);
2691 }
2692 }
2693 }
2694 }
Marek Vasut6a131772019-08-07 19:56:09 +02002695
Marek Vasut38dc7562019-08-07 19:17:42 +02002696 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002697 /* non */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002698 } else {
2699 ddr_padcal_tcompensate_getinit(override);
2700 }
Marek Vasut6a131772019-08-07 19:56:09 +02002701
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002702 return 0;
2703}
2704
Marek Vasut6a131772019-08-07 19:56:09 +02002705/* DDR mode register setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01002706static void ddr_register_set(void)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002707{
2708 int32_t fspwp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002709 uint32_t tmp;
2710
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002711 for (fspwp = 1; fspwp >= 0; fspwp--) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002712 /*MR13, fspwp */
2713 send_dbcmd(0x0e840d08 | ((2 - fspwp) << 6));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002714
2715 tmp =
2716 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002717 reg_pi_mr1_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002718 send_dbcmd(0x0e840100 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002719
2720 tmp =
2721 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002722 reg_pi_mr2_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002723 send_dbcmd(0x0e840200 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002724
2725 tmp =
2726 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002727 reg_pi_mr3_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002728 send_dbcmd(0x0e840300 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002729
2730 tmp =
2731 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002732 reg_pi_mr11_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002733 send_dbcmd(0x0e840b00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002734
2735 tmp =
2736 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002737 reg_pi_mr12_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002738 send_dbcmd(0x0e840c00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002739
2740 tmp =
2741 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002742 reg_pi_mr14_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002743 send_dbcmd(0x0e840e00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002744 /* MR22 */
Marek Vasut6c245a52018-12-12 18:06:39 +01002745 send_dbcmd(0x0e841616);
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002746
2747 /* ZQCAL start */
2748 send_dbcmd(0x0d84004F);
2749
2750 /* ZQLAT */
2751 send_dbcmd(0x0d840051);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002752 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002753
2754 /* MR13, fspwp */
2755 send_dbcmd(0x0e840d08);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002756}
2757
Marek Vasut6a131772019-08-07 19:56:09 +02002758/* Training handshake functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002759static inline uint32_t wait_freqchgreq(uint32_t assert)
2760{
Marek Vasut38dc7562019-08-07 19:17:42 +02002761 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002762 uint32_t count;
2763 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002764
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002765 count = 100000;
2766
2767 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut38dc7562019-08-07 19:17:42 +02002768 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002769 return 0;
2770 }
2771
2772 if (assert) {
2773 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002774 data_l = 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002775 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002776 data_l &= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002777 }
2778 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002779 } while (((data_l & 0x01) != 0x01) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002780 } else {
2781 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002782 data_l = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002783 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002784 data_l |= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002785 }
2786 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002787 } while (((data_l & 0x01) != 0x00) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002788 }
2789
2790 return (count == 0);
2791}
2792
2793static inline void set_freqchgack(uint32_t assert)
2794{
2795 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002796 uint32_t data_l;
Marek Vasut80784f92019-08-07 19:02:26 +02002797
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002798 if (assert)
Marek Vasut38dc7562019-08-07 19:17:42 +02002799 data_l = 0x0CF20000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002800 else
Marek Vasut38dc7562019-08-07 19:17:42 +02002801 data_l = 0x00000000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002802
2803 foreach_vch(ch)
Marek Vasut38dc7562019-08-07 19:17:42 +02002804 mmio_write_32(DBSC_DBPDCNT2(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002805}
2806
2807static inline void set_dfifrequency(uint32_t freq)
2808{
2809 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002810
Marek Vasut38dc7562019-08-07 19:17:42 +02002811 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002812 foreach_vch(ch)
2813 mmio_clrsetbits_32(DBSC_DBPDCNT1(ch), 0x1fU, freq);
2814 } else {
2815 foreach_vch(ch) {
2816 mmio_clrsetbits_32(DBSC_DBDFICNT(ch), 0x1fU << 24,
2817 (freq << 24));
2818 }
2819 }
2820 dsb_sev();
2821}
2822
2823static uint32_t pll3_freq(uint32_t on)
2824{
2825 uint32_t timeout;
2826
2827 timeout = wait_freqchgreq(1);
2828
2829 if (timeout) {
Marek Vasut6a131772019-08-07 19:56:09 +02002830 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002831 }
2832
2833 pll3_control(on);
2834 set_dfifrequency(on);
2835
2836 set_freqchgack(1);
2837 timeout = wait_freqchgreq(0);
2838 set_freqchgack(0);
2839
2840 if (timeout) {
Marek Vasut56519892019-01-21 23:11:33 +01002841 FATAL_MSG("BL2: Time out[2]\n");
Marek Vasut6a131772019-08-07 19:56:09 +02002842 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002843 }
Marek Vasut6a131772019-08-07 19:56:09 +02002844 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002845}
2846
Marek Vasut6a131772019-08-07 19:56:09 +02002847/* update dly */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002848static void update_dly(void)
2849{
2850 ddr_setval_ach(_reg_SC_PHY_MANUAL_UPDATE, 0x01);
2851 ddr_setval_ach(_reg_PHY_ADRCTL_MANUAL_UPDATE, 0x01);
2852}
2853
Marek Vasut6a131772019-08-07 19:56:09 +02002854/* training by pi */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002855static uint32_t pi_training_go(void)
2856{
2857 uint32_t flag;
Marek Vasut38dc7562019-08-07 19:17:42 +02002858 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002859 uint32_t retry;
2860 const uint32_t RETRY_MAX = 4096 * 16;
2861 uint32_t ch;
2862
2863 uint32_t mst_ch;
2864 uint32_t cur_frq;
2865 uint32_t complete;
2866 uint32_t frqchg_req;
2867
Marek Vasut6a131772019-08-07 19:56:09 +02002868 /* pi_start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002869 ddr_setval_ach(_reg_PI_START, 0x01);
2870 foreach_vch(ch)
2871 ddr_getval(ch, _reg_PI_INT_STATUS);
2872
2873 /* set dfi_phymstr_ack = 1 */
2874 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000001);
2875 dsb_sev();
2876
Marek Vasut6a131772019-08-07 19:56:09 +02002877 /* wait pi_int_status[0] */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002878 mst_ch = 0;
2879 flag = 0;
2880 complete = 0;
2881 cur_frq = 0;
2882 retry = RETRY_MAX;
2883 do {
2884 frqchg_req = mmio_read_32(DBSC_DBPDSTAT(mst_ch)) & 0x01;
2885
2886 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut6a131772019-08-07 19:56:09 +02002887 if ((prr_product == PRR_PRODUCT_H3) &&
2888 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002889 if ((retry % 4096) == 1) {
2890 frqchg_req = 1;
2891 } else {
2892 frqchg_req = 0;
2893 }
2894 }
2895
2896 if (frqchg_req) {
2897 if (cur_frq) {
2898 /* Low frequency */
2899 flag = pll3_freq(0);
2900 cur_frq = 0;
2901 } else {
2902 /* High frequency */
2903 flag = pll3_freq(1);
2904 cur_frq = 1;
2905 }
2906 if (flag)
2907 break;
2908 } else {
2909 if (cur_frq) {
2910 foreach_vch(ch) {
2911 if (complete & (1U << ch))
2912 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02002913 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002914 ddr_getval(ch, _reg_PI_INT_STATUS);
Marek Vasut38dc7562019-08-07 19:17:42 +02002915 if (data_l & 0x01) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002916 complete |= (1U << ch);
2917 }
2918 }
2919 if (complete == ddr_phyvalid)
2920 break;
2921 }
2922 }
2923 } while (--retry);
2924 foreach_vch(ch) {
2925 /* dummy read */
Marek Vasut38dc7562019-08-07 19:17:42 +02002926 data_l = ddr_getval_s(ch, 0, _reg_PHY_CAL_RESULT2_OBS_0);
2927 data_l = ddr_getval(ch, _reg_PI_INT_STATUS);
2928 ddr_setval(ch, _reg_PI_INT_ACK, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002929 }
2930 if (ddrphy_regif_chk()) {
Marek Vasut6a131772019-08-07 19:56:09 +02002931 return 0xfd;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002932 }
2933 return complete;
2934}
2935
Marek Vasut6a131772019-08-07 19:56:09 +02002936/* Initialize DDR */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002937static uint32_t init_ddr(void)
2938{
2939 int32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002940 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002941 uint32_t phytrainingok;
Marek Vasut6c245a52018-12-12 18:06:39 +01002942 uint32_t ch, slice;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002943 uint32_t err;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002944 int16_t adj;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002945
Marek Vasut6ad74c32019-08-08 16:34:22 +02002946 MSG_LF(__func__ ":0\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002947
2948#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02002949 rcar_dram_get_boot_status(&ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002950#endif
2951
Marek Vasut6a131772019-08-07 19:56:09 +02002952 /* unlock phy */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002953 /* Unlock DDRPHY register(AGAIN) */
2954 foreach_vch(ch)
2955 mmio_write_32(DBSC_DBPDLK(ch), 0x0000A55A);
2956 dsb_sev();
2957
Marek Vasut6a131772019-08-07 19:56:09 +02002958 if ((((prr_product == PRR_PRODUCT_H3) &&
2959 (prr_cut > PRR_PRODUCT_11)) ||
2960 (prr_product == PRR_PRODUCT_M3N) ||
2961 (prr_product == PRR_PRODUCT_V3H)) && board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002962 reg_ddrphy_write_a(0x00001010, 0x01000001);
2963 else
2964 reg_ddrphy_write_a(0x00001010, 0x00000001);
Marek Vasut6a131772019-08-07 19:56:09 +02002965 /* DBSC register pre-setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002966 dbsc_regset_pre();
2967
Marek Vasut6a131772019-08-07 19:56:09 +02002968 /* load ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002969
2970 ddrtbl_load();
2971
Marek Vasut6a131772019-08-07 19:56:09 +02002972 /* configure ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002973 ddr_config();
2974
Marek Vasut6a131772019-08-07 19:56:09 +02002975 /* dfi_reset assert */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002976 foreach_vch(ch)
2977 mmio_write_32(DBSC_DBPDCNT0(ch), 0x01);
2978 dsb_sev();
2979
Marek Vasut6a131772019-08-07 19:56:09 +02002980 /* dbsc register set */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002981 dbsc_regset();
Marek Vasut6ad74c32019-08-08 16:34:22 +02002982 MSG_LF(__func__ ":1\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002983
Marek Vasut6a131772019-08-07 19:56:09 +02002984 /* dfi_reset negate */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002985 foreach_vch(ch)
2986 mmio_write_32(DBSC_DBPDCNT0(ch), 0x00);
2987 dsb_sev();
2988
Marek Vasut6a131772019-08-07 19:56:09 +02002989 /* dfi_init_start (start ddrphy) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002990 err = dfi_init_start();
2991 if (err) {
2992 return INITDRAM_ERR_I;
2993 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02002994 MSG_LF(__func__ ":2\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002995
Marek Vasut6a131772019-08-07 19:56:09 +02002996 /* ddr backupmode end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002997#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02002998 if (ddr_backup) {
Marek Vasut56519892019-01-21 23:11:33 +01002999 NOTICE("BL2: [WARM_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003000 } else {
Marek Vasut56519892019-01-21 23:11:33 +01003001 NOTICE("BL2: [COLD_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003002 }
Marek Vasut38dc7562019-08-07 19:17:42 +02003003 err = rcar_dram_update_boot_status(ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003004 if (err) {
Marek Vasut56519892019-01-21 23:11:33 +01003005 NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003006 return INITDRAM_ERR_I;
3007 }
3008#endif
Marek Vasut6ad74c32019-08-08 16:34:22 +02003009 MSG_LF(__func__ ":3\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003010
Marek Vasut6a131772019-08-07 19:56:09 +02003011 /* override term code after dfi_init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003012 err = set_term_code();
3013 if (err) {
3014 return INITDRAM_ERR_I;
3015 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003016 MSG_LF(__func__ ":4\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003017
Marek Vasut6a131772019-08-07 19:56:09 +02003018 /* rx offset calibration */
3019 if ((prr_cut > PRR_PRODUCT_11) || (prr_product == PRR_PRODUCT_M3N) ||
3020 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003021 err = rx_offset_cal_hw();
3022 } else {
3023 err = rx_offset_cal();
3024 }
3025 if (err)
Marek Vasut6a131772019-08-07 19:56:09 +02003026 return INITDRAM_ERR_O;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003027 MSG_LF(__func__ ":5\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003028
Marek Vasut6c245a52018-12-12 18:06:39 +01003029 /* PDX */
3030 send_dbcmd(0x08840001);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003031
Marek Vasut6a131772019-08-07 19:56:09 +02003032 /* check register i/f is alive */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003033 err = ddrphy_regif_chk();
3034 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003035 return INITDRAM_ERR_O;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003036 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003037 MSG_LF(__func__ ":6\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003038
Marek Vasut6a131772019-08-07 19:56:09 +02003039 /* phy initialize end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003040
Marek Vasut6a131772019-08-07 19:56:09 +02003041 /* setup DDR mode registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003042 /* CMOS MODE */
3043 change_lpddr4_en(0);
3044
Marek Vasut6c245a52018-12-12 18:06:39 +01003045 /* MRS */
3046 ddr_register_set();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003047
Marek Vasut6a131772019-08-07 19:56:09 +02003048 /* Thermal sensor setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01003049 /* THCTR Bit6: PONM=0 , Bit0: THSST=1 */
Marek Vasut38dc7562019-08-07 19:17:42 +02003050 data_l = (mmio_read_32(THS1_THCTR) & 0xFFFFFFBF) | 0x00000001;
3051 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003052
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003053 /* LPDDR4 MODE */
3054 change_lpddr4_en(1);
3055
Marek Vasut6ad74c32019-08-08 16:34:22 +02003056 MSG_LF(__func__ ":7\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003057
Marek Vasut6a131772019-08-07 19:56:09 +02003058 /* mask CS_MAP if RANKx is not found */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003059 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003060 data_l = ddr_getval(ch, _reg_PI_CS_MAP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003061 if (!(ch_have_this_cs[1] & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02003062 data_l = data_l & 0x05;
3063 ddr_setval(ch, _reg_PI_CS_MAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003064 }
3065
Marek Vasut6a131772019-08-07 19:56:09 +02003066 /* exec pi_training */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003067 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
3068 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003069 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003070
Marek Vasut38dc7562019-08-07 19:17:42 +02003071 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003072 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_EN, 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003073 } else {
3074 foreach_vch(ch) {
3075 for (slice = 0; slice < SLICE_CNT; slice++) {
3076 ddr_setval_s(ch, slice,
3077 _reg_PHY_PER_CS_TRAINING_EN,
3078 ((ch_have_this_cs[1]) >> ch)
3079 & 0x01);
3080 }
3081 }
3082 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003083
3084 phytrainingok = pi_training_go();
3085
3086 if (ddr_phyvalid != (phytrainingok & ddr_phyvalid)) {
Marek Vasut6a131772019-08-07 19:56:09 +02003087 return INITDRAM_ERR_T | phytrainingok;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003088 }
3089
Marek Vasut6ad74c32019-08-08 16:34:22 +02003090 MSG_LF(__func__ ":8\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003091
Marek Vasut6a131772019-08-07 19:56:09 +02003092 /* CACS DLY ADJUST */
Marek Vasut38dc7562019-08-07 19:17:42 +02003093 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003094 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003095 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003096 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003097 ddr_setval(ch, _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003098 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003099 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003100
3101 if (ddr_phycaslice == 1) {
3102 for (i = 0; i < 6; i++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003103 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj
3104 [i +
3105 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
3106 ddr_setval_s(ch, 2,
3107 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
3108 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003109 data_l + adj
Marek Vasut6c245a52018-12-12 18:06:39 +01003110 );
3111 }
3112 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003113 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003114
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003115 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003116 MSG_LF(__func__ ":9\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003117
Marek Vasut6a131772019-08-07 19:56:09 +02003118 /* H3 fix rd latency to avoid bug in elasitic buffer */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003119 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003120 adjust_rddqs_latency();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003121
Marek Vasut6a131772019-08-07 19:56:09 +02003122 /* Adjust Write path latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003123 if (ddrtbl_getval
3124 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD))
3125 adjust_wpath_latency();
3126
Marek Vasut6a131772019-08-07 19:56:09 +02003127 /* RDQLVL Training */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003128 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003129 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x01);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003130
3131 err = rdqdm_man();
Marek Vasut6c245a52018-12-12 18:06:39 +01003132
Marek Vasut6ad74c32019-08-08 16:34:22 +02003133 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Marek Vasut6c245a52018-12-12 18:06:39 +01003134 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003135
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003136 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003137 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003138 }
3139 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003140 MSG_LF(__func__ ":10\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003141
Marek Vasut6a131772019-08-07 19:56:09 +02003142 /* WDQLVL Training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003143 err = wdqdm_man();
3144 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003145 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003146 }
3147 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003148 MSG_LF(__func__ ":11\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003149
Marek Vasut6a131772019-08-07 19:56:09 +02003150 /* training complete, setup DBSC */
3151 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3152 (prr_product == PRR_PRODUCT_M3N) ||
3153 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003154 ddr_setval_ach_as(_reg_PHY_DFI40_POLARITY, 0x00);
3155 ddr_setval_ach(_reg_PI_DFI40_POLARITY, 0x00);
3156 }
3157
3158 dbsc_regset_post();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003159 MSG_LF(__func__ ":12\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003160
3161 return phytrainingok;
3162}
3163
Marek Vasut6a131772019-08-07 19:56:09 +02003164/* SW LEVELING COMMON */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003165static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick)
3166{
3167 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02003168 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003169 uint32_t retry;
3170 uint32_t waiting;
3171 uint32_t err;
3172
3173 const uint32_t RETRY_MAX = 0x1000;
3174
3175 err = 0;
3176 /* set EXIT -> OP_DONE is cleared */
3177 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3178
3179 /* kick */
3180 foreach_vch(ch) {
3181 if (ch_have_this_cs[ddr_csn % 2] & (1U << ch)) {
3182 ddr_setval(ch, reg_cs, ddr_csn);
3183 ddr_setval(ch, reg_kick, 0x01);
3184 }
3185 }
3186 foreach_vch(ch) {
3187 /*PREPARE ADDR REGISTER (for SWLVL_OP_DONE) */
3188 ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3189 }
3190 waiting = ch_have_this_cs[ddr_csn % 2];
3191 dsb_sev();
3192 retry = RETRY_MAX;
3193 do {
3194 foreach_vch(ch) {
3195 if (!(waiting & (1U << ch)))
3196 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02003197 data_l = ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3198 if (data_l & 0x01)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003199 waiting &= ~(1U << ch);
3200 }
3201 retry--;
3202 } while (waiting && (retry > 0));
3203 if (retry == 0) {
3204 err = 1;
3205 }
3206
3207 dsb_sev();
3208 /* set EXIT -> OP_DONE is cleared */
3209 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3210 dsb_sev();
3211
3212 return err;
3213}
3214
Marek Vasut6a131772019-08-07 19:56:09 +02003215/* WDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003216#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003217static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3218{
3219 int32_t i, k;
3220 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003221 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003222
Marek Vasut6a131772019-08-07 19:56:09 +02003223 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003224 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003225 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003226 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003227 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003228 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3229 continue;
3230
3231 for (i = 0; i <= 8; i++) {
3232 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch))
3233 wdqdm_dly[ch][cs][slice][i] =
3234 wdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3235 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003236 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003237 wdqdm_le[ch][cs][slice][i] = 0;
3238 wdqdm_te[ch][cs][slice][i] = 0;
3239 }
3240 wdqdm_st[ch][cs][slice] = 0;
3241 wdqdm_win[ch][cs][slice] = 0;
3242 }
3243}
3244
3245static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3246{
3247 int32_t i, k;
3248 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003249 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003250 uint32_t err;
3251 const uint32_t _par_WDQLVL_RETRY_THRES = 0x7c0;
3252
3253 int32_t min_win;
3254 int32_t win;
3255 int8_t _adj;
3256 int16_t adj;
3257 uint32_t dq;
3258
Marek Vasut6a131772019-08-07 19:56:09 +02003259 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003260 err = 0;
3261 for (slice = 0; slice < SLICE_CNT; slice += 1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003262 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003263 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3264 continue;
3265
3266 cs = ddr_csn % 2;
3267 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003268 for (i = 0; i < 9; i++) {
3269 dq = slice * 8 + i;
3270 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003271 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003272 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003273 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003274 adj = _f_scale_adj(_adj);
3275
Marek Vasut38dc7562019-08-07 19:17:42 +02003276 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003277 ddr_getval_s(ch, slice,
3278 _reg_PHY_CLK_WRX_SLAVE_DELAY[i]) + adj;
3279 ddr_setval_s(ch, slice, _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003280 data_l);
3281 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003282 }
3283 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, 0x00);
Marek Vasut38dc7562019-08-07 19:17:42 +02003284 data_l = ddr_getval_s(ch, slice, _reg_PHY_WDQLVL_STATUS_OBS);
3285 wdqdm_st[ch][cs][slice] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003286 min_win = INT_LEAST32_MAX;
3287 for (i = 0; i <= 8; i++) {
3288 ddr_setval_s(ch, slice, _reg_PHY_WDQLVL_DQDM_OBS_SELECT,
3289 i);
3290
Marek Vasut38dc7562019-08-07 19:17:42 +02003291 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003292 ddr_getval_s(ch, slice,
3293 _reg_PHY_WDQLVL_DQDM_TE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003294 wdqdm_te[ch][cs][slice][i] = data_l;
3295 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003296 ddr_getval_s(ch, slice,
3297 _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003298 wdqdm_le[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003299 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003300 (int32_t)wdqdm_te[ch][cs][slice][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003301 wdqdm_le[ch][cs][slice][i];
3302 if (min_win > win)
3303 min_win = win;
Marek Vasut38dc7562019-08-07 19:17:42 +02003304 if (data_l >= _par_WDQLVL_RETRY_THRES)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003305 err = 2;
3306 }
3307 wdqdm_win[ch][cs][slice] = min_win;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003308 if ((prr_product == PRR_PRODUCT_H3) &&
3309 (prr_cut <= PRR_PRODUCT_11)) {
3310 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3311 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003312 } else {
3313 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3314 ((ch_have_this_cs[1]) >> ch) & 0x01);
3315 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003316 }
3317 return err;
3318}
Marek Vasut6c245a52018-12-12 18:06:39 +01003319#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003320
3321static void wdqdm_cp(uint32_t ddr_csn, uint32_t restore)
3322{
3323 uint32_t i;
3324 uint32_t ch, slice;
3325 uint32_t tgt_cs, src_cs;
3326 uint32_t tmp_r;
3327
Marek Vasut6a131772019-08-07 19:56:09 +02003328 /* copy of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003329 foreach_vch(ch) {
3330 for (tgt_cs = 0; tgt_cs < CS_CNT; tgt_cs++) {
3331 for (slice = 0; slice < SLICE_CNT; slice++) {
3332 ddr_setval_s(ch, slice,
3333 _reg_PHY_PER_CS_TRAINING_INDEX,
3334 tgt_cs);
3335 src_cs = ddr_csn % 2;
3336 if (!(ch_have_this_cs[1] & (1U << ch)))
3337 src_cs = 0;
3338 for (i = 0; i <= 4; i += 4) {
3339 if (restore)
3340 tmp_r =
3341 rdqdm_dly[ch][tgt_cs][slice]
3342 [i];
3343 else
3344 tmp_r =
3345 rdqdm_dly[ch][src_cs][slice]
3346 [i];
3347
3348 ddr_setval_s(ch, slice,
3349 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
3350 [i], tmp_r);
3351 }
3352 }
3353 }
3354 }
3355}
3356
3357static uint32_t wdqdm_man1(void)
3358{
3359 int32_t k;
3360 uint32_t ch, cs, slice;
3361 uint32_t ddr_csn;
Marek Vasut38dc7562019-08-07 19:17:42 +02003362 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003363 uint32_t err;
Marek Vasut6c245a52018-12-12 18:06:39 +01003364 uint32_t high_dq[DRAM_CH_CNT];
3365 uint32_t mr14_csab0_bak[DRAM_CH_CNT];
3366#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003367 uint32_t err_flg;
Marek Vasut6c245a52018-12-12 18:06:39 +01003368#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003369
Marek Vasut6a131772019-08-07 19:56:09 +02003370 /* manual execution of training */
Marek Vasut38dc7562019-08-07 19:17:42 +02003371 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003372 foreach_vch(ch) {
3373 high_dq[ch] = 0;
3374 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003375 k = (board_cnf->ch[ch].dqs_swap >>
3376 (4 * slice)) & 0x0f;
Marek Vasut6c245a52018-12-12 18:06:39 +01003377 if (k >= 2)
3378 high_dq[ch] |= (1U << slice);
3379 }
3380 ddr_setval(ch, _reg_PI_16BIT_DRAM_CONNECT, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003381 }
3382 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003383 err = 0;
3384 /* CLEAR PREV RESULT */
3385 for (cs = 0; cs < CS_CNT; cs++) {
3386 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_INDEX, cs);
Marek Vasut6a131772019-08-07 19:56:09 +02003387 if (((prr_product == PRR_PRODUCT_H3) &&
3388 (prr_cut > PRR_PRODUCT_11)) ||
3389 (prr_product == PRR_PRODUCT_M3N) ||
3390 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003391 ddr_setval_ach_as(_reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS,
3392 0x01);
3393 } else {
3394 ddr_setval_ach_as(_reg_PHY_WDQLVL_CLR_PREV_RESULTS,
3395 0x01);
3396 }
3397 }
3398 ddrphy_regif_idle();
3399
Marek Vasut6c245a52018-12-12 18:06:39 +01003400#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003401 err_flg = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01003402#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003403 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Marek Vasut6a131772019-08-07 19:56:09 +02003404 if ((prr_product == PRR_PRODUCT_H3) &&
3405 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003406 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003407 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3408 data_l &= ~(0x00ffU << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003409
3410 if (ddr_csn >= 2)
3411 k = (high_dq[ch] ^ 0x0f);
3412 else
3413 k = high_dq[ch];
Marek Vasut38dc7562019-08-07 19:17:42 +02003414 data_l |= (k << 16);
3415 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003416 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, k);
3417 }
3418 }
Marek Vasut6a131772019-08-07 19:56:09 +02003419 if (((prr_product == PRR_PRODUCT_H3) &&
3420 (prr_cut <= PRR_PRODUCT_11)) ||
3421 ((prr_product == PRR_PRODUCT_M3) &&
3422 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003423 wdqdm_cp(ddr_csn, 0);
3424 }
3425
3426 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003427 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003428 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003429 reg_pi_mr14_data_fx_csx[1][ddr_csn]);
3430 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003431 }
3432
3433 /* KICK WDQLVL */
3434 err = swlvl1(ddr_csn, _reg_PI_WDQLVL_CS, _reg_PI_WDQLVL_REQ);
3435 if (err)
3436 goto err_exit;
3437
3438 if (ddr_csn == 0)
3439 foreach_vch(ch) {
3440 mr14_csab0_bak[ch] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003441 ddr_getval(ch, reg_pi_mr14_data_fx_csx[1][0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003442 } else
3443 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003444 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0],
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003445 mr14_csab0_bak[ch]);
3446 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003447#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003448 foreach_vch(ch) {
3449 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3450 wdqdm_clr1(ch, ddr_csn);
3451 continue;
3452 }
3453 err = wdqdm_ana1(ch, ddr_csn);
3454 if (err)
3455 err_flg |= (1U << (ddr_csn * 4 + ch));
3456 ddrphy_regif_idle();
3457 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003458#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003459 }
3460err_exit:
Marek Vasut6c245a52018-12-12 18:06:39 +01003461#ifndef DDR_FAST_INIT
3462 err |= err_flg;
3463#endif/* DDR_FAST_INIT */
Marek Vasut38dc7562019-08-07 19:17:42 +02003464 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003465 ddr_setval_ach(_reg_PI_16BIT_DRAM_CONNECT, 0x01);
3466 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003467 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3468 data_l &= ~(0x00ffU << 16);
3469 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01003470 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, 0x00);
3471 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003472 }
Marek Vasut6a131772019-08-07 19:56:09 +02003473 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003474}
3475
3476static uint32_t wdqdm_man(void)
3477{
3478 uint32_t err, retry_cnt;
3479 const uint32_t retry_max = 0x10;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003480 uint32_t ch, ddr_csn, mr14_bkup[4][4];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003481
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003482 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW,
3483 (mmio_read_32(DBSC_DBTR(11)) & 0xFF) + 19);
Marek Vasut6a131772019-08-07 19:56:09 +02003484 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3485 (prr_product == PRR_PRODUCT_M3N) ||
3486 (prr_product == PRR_PRODUCT_V3H)) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003487 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F0,
3488 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003489 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F1,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003490 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003491 } else {
3492 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003493 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003494 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003495 ddr_setval_ach(_reg_PI_TRFC_F0, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
3496 ddr_setval_ach(_reg_PI_TRFC_F1, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003497
3498 retry_cnt = 0;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003499 err = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003500 do {
Marek Vasut6a131772019-08-07 19:56:09 +02003501 if ((prr_product == PRR_PRODUCT_H3) &&
3502 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003503 err = wdqdm_man1();
3504 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003505 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x01);
3506 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3507 0x01);
Marek Vasut6a131772019-08-07 19:56:09 +02003508 if ((prr_product == PRR_PRODUCT_M3N) ||
3509 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003510 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3511 0x0C);
3512 } else {
3513 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x0C);
3514 }
3515 dsb_sev();
3516 err = wdqdm_man1();
3517 foreach_vch(ch) {
3518 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3519 mr14_bkup[ch][ddr_csn] =
3520 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003521 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003522 [1][ddr_csn]);
3523 dsb_sev();
3524 }
3525 }
3526
Marek Vasut6a131772019-08-07 19:56:09 +02003527 if ((prr_product == PRR_PRODUCT_M3N) ||
3528 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003529 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3530 0x04);
3531 } else {
3532 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x04);
3533 }
3534 pvtcode_update();
3535 err = wdqdm_man1();
3536 foreach_vch(ch) {
3537 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3538 mr14_bkup[ch][ddr_csn] =
3539 (mr14_bkup[ch][ddr_csn] +
3540 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003541 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003542 [1][ddr_csn])) / 2;
3543 ddr_setval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003544 reg_pi_mr14_data_fx_csx[1]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003545 [ddr_csn],
3546 mr14_bkup[ch][ddr_csn]);
3547 }
3548 }
3549
3550 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3551 0x00);
Marek Vasut6a131772019-08-07 19:56:09 +02003552 if ((prr_product == PRR_PRODUCT_M3N) ||
3553 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003554 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3555 0x00);
3556 ddr_setval_ach
3557 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1,
3558 0x00);
3559 ddr_setval_ach
3560 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1,
3561 0x00);
3562 } else {
3563 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x00);
3564 ddr_setval_ach
3565 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT,
3566 0x00);
3567 ddr_setval_ach
3568 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT,
3569 0x00);
3570 }
3571 ddr_setval_ach(_reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE,
3572 0x00);
3573
3574 pvtcode_update2();
3575 err = wdqdm_man1();
3576 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
3577 }
3578 } while (err && (++retry_cnt < retry_max));
3579
Marek Vasut6a131772019-08-07 19:56:09 +02003580 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
3581 ((prr_product == PRR_PRODUCT_M3) && (prr_cut <= PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003582 wdqdm_cp(0, 1);
3583 }
3584
3585 return (retry_cnt >= retry_max);
3586}
3587
Marek Vasut6a131772019-08-07 19:56:09 +02003588/* RDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003589#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003590static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3591{
3592 int32_t i, k;
3593 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003594 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003595
Marek Vasut6a131772019-08-07 19:56:09 +02003596 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003597 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003598 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003599 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003600 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003601 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3602 continue;
3603
3604 for (i = 0; i <= 8; i++) {
3605 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) {
3606 rdqdm_dly[ch][cs][slice][i] =
3607 rdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3608 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3609 rdqdm_dly[ch][CS_CNT - 1 - cs][slice +
3610 SLICE_CNT]
3611 [i];
3612 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02003613 rdqdm_dly[ch][cs][slice][i] = data_l;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003614 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3615 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003616 }
3617 rdqdm_le[ch][cs][slice][i] = 0;
3618 rdqdm_le[ch][cs][slice + SLICE_CNT][i] = 0;
3619 rdqdm_te[ch][cs][slice][i] = 0;
3620 rdqdm_te[ch][cs][slice + SLICE_CNT][i] = 0;
3621 rdqdm_nw[ch][cs][slice][i] = 0;
3622 rdqdm_nw[ch][cs][slice + SLICE_CNT][i] = 0;
3623 }
3624 rdqdm_st[ch][cs][slice] = 0;
3625 rdqdm_win[ch][cs][slice] = 0;
3626 }
3627}
3628
3629static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3630{
3631 int32_t i, k;
3632 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003633 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003634 uint32_t err;
3635 int8_t _adj;
3636 int16_t adj;
3637 uint32_t dq;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003638 int32_t min_win;
3639 int32_t win;
3640 uint32_t rdq_status_obs_select;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003641
Marek Vasut6a131772019-08-07 19:56:09 +02003642 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003643 err = 0;
3644 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003645 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003646 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3647 continue;
3648
3649 cs = ddr_csn % 2;
3650 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
3651 ddrphy_regif_idle();
3652
3653 ddr_getval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX);
3654 ddrphy_regif_idle();
3655
3656 for (i = 0; i <= 8; i++) {
3657 dq = slice * 8 + i;
3658 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003659 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003660 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003661 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003662
3663 adj = _f_scale_adj(_adj);
3664
Marek Vasut38dc7562019-08-07 19:17:42 +02003665 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003666 ddr_getval_s(ch, slice,
3667 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) +
3668 adj;
3669 ddr_setval_s(ch, slice,
3670 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003671 data_l);
3672 rdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003673
Marek Vasut38dc7562019-08-07 19:17:42 +02003674 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003675 ddr_getval_s(ch, slice,
3676 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) +
3677 adj;
3678 ddr_setval_s(ch, slice,
3679 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003680 data_l);
3681 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003682 }
3683 min_win = INT_LEAST32_MAX;
3684 for (i = 0; i <= 8; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003685 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003686 ddr_getval_s(ch, slice, _reg_PHY_RDLVL_STATUS_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003687 rdqdm_st[ch][cs][slice] = data_l;
3688 rdqdm_st[ch][cs][slice + SLICE_CNT] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003689 /* k : rise/fall */
3690 for (k = 0; k < 2; k++) {
3691 if (i == 8) {
3692 rdq_status_obs_select = 16 + 8 * k;
3693 } else {
3694 rdq_status_obs_select = i + k * 8;
3695 }
3696 ddr_setval_s(ch, slice,
3697 _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT,
3698 rdq_status_obs_select);
3699
Marek Vasut38dc7562019-08-07 19:17:42 +02003700 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003701 ddr_getval_s(ch, slice,
3702 _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS);
3703 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003704 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003705
Marek Vasut38dc7562019-08-07 19:17:42 +02003706 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003707 ddr_getval_s(ch, slice,
3708 _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS);
3709 rdqdm_te[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003710 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003711
Marek Vasut38dc7562019-08-07 19:17:42 +02003712 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003713 ddr_getval_s(ch, slice,
3714 _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS);
3715 rdqdm_nw[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003716 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003717
3718 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003719 (int32_t)rdqdm_te[ch][cs][slice +
Marek Vasut6ad74c32019-08-08 16:34:22 +02003720 SLICE_CNT *
3721 k][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003722 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i];
3723 if (i != 8) {
3724 if (min_win > win)
3725 min_win = win;
3726 }
3727 }
3728 }
3729 rdqdm_win[ch][cs][slice] = min_win;
3730 if (min_win <= 0) {
3731 err = 2;
3732 }
3733 }
Marek Vasut6a131772019-08-07 19:56:09 +02003734 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003735}
Marek Vasut6c245a52018-12-12 18:06:39 +01003736#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003737
3738static uint32_t rdqdm_man1(void)
3739{
3740 uint32_t ch;
3741 uint32_t ddr_csn;
Marek Vasut6c245a52018-12-12 18:06:39 +01003742#ifdef DDR_FAST_INIT
3743 uint32_t slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003744 uint32_t i, adj, data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003745#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003746 uint32_t err;
3747
Marek Vasut6a131772019-08-07 19:56:09 +02003748 /* manual execution of training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003749 err = 0;
3750
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003751 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003752 /* KICK RDQLVL */
3753 err = swlvl1(ddr_csn, _reg_PI_RDLVL_CS, _reg_PI_RDLVL_REQ);
3754 if (err)
3755 goto err_exit;
Marek Vasut6c245a52018-12-12 18:06:39 +01003756#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003757 foreach_vch(ch) {
3758 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3759 rdqdm_clr1(ch, ddr_csn);
3760 ddrphy_regif_idle();
3761 continue;
3762 }
3763 err = rdqdm_ana1(ch, ddr_csn);
3764 ddrphy_regif_idle();
3765 if (err)
3766 goto err_exit;
3767 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003768#else/* DDR_FAST_INIT */
3769 foreach_vch(ch) {
3770 if (ch_have_this_cs[ddr_csn] & (1U << ch)) {
3771 for (slice = 0; slice < SLICE_CNT; slice++) {
3772 if (ddr_getval_s(ch, slice,
Marek Vasut80784f92019-08-07 19:02:26 +02003773 _reg_PHY_RDLVL_STATUS_OBS) !=
Marek Vasut6c245a52018-12-12 18:06:39 +01003774 0x0D00FFFF) {
3775 err = (1U << ch) |
3776 (0x10U << slice);
3777 goto err_exit;
3778 }
3779 }
3780 }
Marek Vasut6a131772019-08-07 19:56:09 +02003781 if (((prr_product == PRR_PRODUCT_H3) &&
3782 (prr_cut <= PRR_PRODUCT_11)) ||
3783 ((prr_product == PRR_PRODUCT_M3) &&
3784 (prr_cut <= PRR_PRODUCT_10))) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003785 for (slice = 0; slice < SLICE_CNT; slice++) {
3786 for (i = 0; i <= 8; i++) {
3787 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003788 adj = _f_scale_adj(board_cnf->ch[ch].dm_adj_r[slice]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003789 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003790 adj = _f_scale_adj(board_cnf->ch[ch].dq_adj_r[slice * 8 + i]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003791 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, ddr_csn);
Marek Vasut38dc7562019-08-07 19:17:42 +02003792 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + adj;
3793 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], data_l);
3794 rdqdm_dly[ch][ddr_csn][slice][i] = data_l;
3795 rdqdm_dly[ch][ddr_csn | 1][slice][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003796
Marek Vasut38dc7562019-08-07 19:17:42 +02003797 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + adj;
3798 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], data_l);
3799 rdqdm_dly[ch][ddr_csn][slice + SLICE_CNT][i] = data_l;
3800 rdqdm_dly[ch][ddr_csn | 1][slice + SLICE_CNT][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003801 }
3802 }
3803 }
3804 }
3805 ddrphy_regif_idle();
3806
3807#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003808 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003809
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003810err_exit:
Marek Vasut6a131772019-08-07 19:56:09 +02003811 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003812}
3813
3814static uint32_t rdqdm_man(void)
3815{
3816 uint32_t err, retry_cnt;
3817 const uint32_t retry_max = 0x01;
3818
3819 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3820 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3821 _reg_PHY_DQ_TSEL_ENABLE));
3822 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3823 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3824 _reg_PHY_DQS_TSEL_ENABLE));
3825 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3826 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3827 _reg_PHY_DQ_TSEL_SELECT));
3828 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3829 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3830 _reg_PHY_DQS_TSEL_SELECT));
3831
3832 retry_cnt = 0;
3833 do {
3834 err = rdqdm_man1();
3835 ddrphy_regif_idle();
3836 } while (err && (++retry_cnt < retry_max));
3837 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3838 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3839 _reg_PHY_DQ_TSEL_ENABLE));
3840 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3841 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3842 _reg_PHY_DQS_TSEL_ENABLE));
3843 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3844 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3845 _reg_PHY_DQ_TSEL_SELECT));
3846 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3847 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3848 _reg_PHY_DQS_TSEL_SELECT));
3849
3850 return (retry_cnt >= retry_max);
3851}
3852
Marek Vasut6a131772019-08-07 19:56:09 +02003853/* rx offset calibration */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003854static int32_t _find_change(uint64_t val, uint32_t dir)
3855{
3856 int32_t i;
3857 uint32_t startval;
3858 uint32_t curval;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003859 const int32_t VAL_END = 0x3f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003860
3861 if (dir == 0) {
3862 startval = (val & 0x01);
3863 for (i = 1; i <= VAL_END; i++) {
3864 curval = (val >> i) & 0x01;
3865 if (curval != startval)
Marek Vasut6a131772019-08-07 19:56:09 +02003866 return i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003867 }
Marek Vasut6a131772019-08-07 19:56:09 +02003868 return VAL_END;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003869 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003870
3871 startval = (val >> dir) & 0x01;
3872 for (i = dir - 1; i >= 0; i--) {
3873 curval = (val >> i) & 0x01;
3874 if (curval != startval)
3875 return i;
3876 }
3877 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003878}
3879
3880static uint32_t _rx_offset_cal_updn(uint32_t code)
3881{
3882 const uint32_t CODE_MAX = 0x40;
3883 uint32_t tmp;
3884
Marek Vasut38dc7562019-08-07 19:17:42 +02003885 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003886 if (code == 0)
3887 tmp = (1U << 6) | (CODE_MAX - 1);
3888 else if (code <= 0x20)
3889 tmp =
3890 ((CODE_MAX - 1 -
3891 (0x20 - code) * 2) << 6) | (CODE_MAX - 1);
3892 else
3893 tmp =
3894 ((CODE_MAX - 1) << 6) | (CODE_MAX - 1 -
3895 (code - 0x20) * 2);
3896 } else {
3897 if (code == 0)
3898 tmp = (1U << 6) | (CODE_MAX - 1);
3899 else
3900 tmp = (code << 6) | (CODE_MAX - code);
3901 }
3902 return tmp;
3903}
3904
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003905static uint32_t rx_offset_cal(void)
3906{
3907 uint32_t index;
3908 uint32_t code;
3909 const uint32_t CODE_MAX = 0x40;
3910 const uint32_t CODE_STEP = 2;
3911 uint32_t ch, slice;
3912 uint32_t tmp;
3913 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
3914 uint64_t val[DRAM_CH_CNT][SLICE_CNT][_reg_PHY_RX_CAL_X_NUM];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003915 uint64_t tmpval;
3916 int32_t lsb, msb;
Marek Vasut6c245a52018-12-12 18:06:39 +01003917
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003918 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x01);
3919 foreach_vch(ch) {
3920 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003921 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003922 val[ch][slice][index] = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003923 }
3924 }
3925
3926 for (code = 0; code < CODE_MAX / CODE_STEP; code++) {
3927 tmp = _rx_offset_cal_updn(code * CODE_STEP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003928 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) {
3929 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[index], tmp);
3930 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003931 dsb_sev();
Marek Vasut80784f92019-08-07 19:02:26 +02003932 ddr_getval_ach_as(_reg_PHY_RX_CAL_OBS, (uint32_t *)tmp_ach_as);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003933
3934 foreach_vch(ch) {
3935 for (slice = 0; slice < SLICE_CNT; slice++) {
3936 tmp = tmp_ach_as[ch][slice];
3937 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3938 index++) {
3939 if (tmp & (1U << index)) {
3940 val[ch][slice][index] |=
3941 (1ULL << code);
3942 } else {
3943 val[ch][slice][index] &=
3944 ~(1ULL << code);
3945 }
3946 }
3947 }
3948 }
3949 }
3950 foreach_vch(ch) {
3951 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003952 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3953 index++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003954 tmpval = val[ch][slice][index];
3955 lsb = _find_change(tmpval, 0);
3956 msb =
3957 _find_change(tmpval,
3958 (CODE_MAX / CODE_STEP) - 1);
3959 tmp = (lsb + msb) >> 1;
3960
3961 tmp = _rx_offset_cal_updn(tmp * CODE_STEP);
3962 ddr_setval_s(ch, slice,
3963 _reg_PHY_RX_CAL_X[index], tmp);
3964 }
3965 }
3966 }
3967 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003968
3969 return 0;
3970}
3971
3972static uint32_t rx_offset_cal_hw(void)
3973{
3974 uint32_t ch, slice;
3975 uint32_t retry;
3976 uint32_t complete;
3977 uint32_t tmp;
3978 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
3979
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003980 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[9], 0x00);
3981 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
3982 ddr_setval_ach_as(_reg_PHY_RX_CAL_SAMPLE_WAIT, 0x0f);
3983
3984 retry = 0;
3985 while (retry < 4096) {
3986 if ((retry & 0xff) == 0) {
3987 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
3988 }
3989 foreach_vch(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02003990 for (slice = 0; slice < SLICE_CNT; slice++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003991 tmp_ach_as[ch][slice] =
3992 ddr_getval_s(ch, slice, _reg_PHY_RX_CAL_X[9]);
3993
3994 complete = 1;
3995 foreach_vch(ch) {
3996 for (slice = 0; slice < SLICE_CNT; slice++) {
3997 tmp = tmp_ach_as[ch][slice];
3998 tmp = (tmp & 0x3f) + ((tmp >> 6) & 0x3f);
Marek Vasut6a131772019-08-07 19:56:09 +02003999 if (((prr_product == PRR_PRODUCT_H3) &&
4000 (prr_cut > PRR_PRODUCT_11)) ||
4001 (prr_product == PRR_PRODUCT_M3N) ||
4002 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004003 if (tmp != 0x3E)
4004 complete = 0;
4005 } else {
4006 if (tmp != 0x40)
4007 complete = 0;
4008 }
4009 }
4010 }
4011 if (complete)
4012 break;
4013
4014 retry++;
4015 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004016
4017 return (complete == 0);
4018}
4019
Marek Vasut6a131772019-08-07 19:56:09 +02004020/* adjust rddqs latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004021static void adjust_rddqs_latency(void)
4022{
4023 uint32_t ch, slice;
4024 uint32_t dly;
4025 uint32_t maxlatx2;
4026 uint32_t tmp;
4027 uint32_t rdlat_adjx2[SLICE_CNT];
Marek Vasut80784f92019-08-07 19:02:26 +02004028
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004029 foreach_vch(ch) {
4030 maxlatx2 = 0;
4031 for (slice = 0; slice < SLICE_CNT; slice++) {
4032 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX,
4033 0x00);
4034
4035 dly =
4036 ddr_getval_s(ch, slice,
4037 _reg_PHY_RDDQS_GATE_SLAVE_DELAY);
4038 tmp =
4039 ddr_getval_s(ch, slice,
4040 _reg_PHY_RDDQS_LATENCY_ADJUST);
4041 /* note gate_slave_delay[9] is always 0 */
4042 tmp = (tmp << 1) + (dly >> 8);
4043 rdlat_adjx2[slice] = tmp;
4044 if (maxlatx2 < tmp)
4045 maxlatx2 = tmp;
4046 }
4047 maxlatx2 = ((maxlatx2 + 1) >> 1) << 1;
4048 for (slice = 0; slice < SLICE_CNT; slice++) {
4049 tmp = maxlatx2 - rdlat_adjx2[slice];
4050 tmp = (tmp >> 1);
4051 if (tmp) {
4052 ddr_setval_s(ch, slice, _reg_PHY_RPTR_UPDATE,
4053 ddr_getval_s(ch, slice,
4054 _reg_PHY_RPTR_UPDATE)
4055 + 1);
4056 }
4057 }
4058 }
4059}
4060
Marek Vasut6a131772019-08-07 19:56:09 +02004061/* adjust wpath latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004062static void adjust_wpath_latency(void)
4063{
4064 uint32_t ch, cs, slice;
4065 uint32_t dly;
4066 uint32_t wpath_add;
4067 const uint32_t _par_EARLY_THRESHOLD_VAL = 0x180;
4068
4069 foreach_vch(ch) {
4070 for (slice = 0; slice < SLICE_CNT; slice += 1) {
4071 for (cs = 0; cs < CS_CNT; cs++) {
4072 ddr_setval_s(ch, slice,
4073 _reg_PHY_PER_CS_TRAINING_INDEX,
4074 cs);
4075 ddr_getval_s(ch, slice,
4076 _reg_PHY_PER_CS_TRAINING_INDEX);
4077 dly =
4078 ddr_getval_s(ch, slice,
4079 _reg_PHY_CLK_WRDQS_SLAVE_DELAY);
4080 if (dly <= _par_EARLY_THRESHOLD_VAL)
4081 continue;
4082
4083 wpath_add =
4084 ddr_getval_s(ch, slice,
4085 _reg_PHY_WRITE_PATH_LAT_ADD);
4086 ddr_setval_s(ch, slice,
4087 _reg_PHY_WRITE_PATH_LAT_ADD,
4088 wpath_add - 1);
4089 }
4090 }
4091 }
4092}
4093
Marek Vasut6a131772019-08-07 19:56:09 +02004094/* DDR Initialize entry */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004095int32_t rcar_dram_init(void)
4096{
4097 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02004098 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004099 uint32_t bus_mbps, bus_mbpsdiv;
4100 uint32_t tmp_tccd;
4101 uint32_t failcount;
Marek Vasut38dc7562019-08-07 19:17:42 +02004102 uint32_t cnf_boardtype;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004103
Marek Vasut6a131772019-08-07 19:56:09 +02004104 /* Thermal sensor setting */
Marek Vasut38dc7562019-08-07 19:17:42 +02004105 data_l = mmio_read_32(CPG_MSTPSR5);
4106 if (data_l & BIT(22)) { /* case THS/TSC Standby */
Marek Vasut6a131772019-08-07 19:56:09 +02004107 data_l &= ~BIT(22);
Marek Vasut38dc7562019-08-07 19:17:42 +02004108 cpg_write_32(CPG_SMSTPCR5, data_l);
Marek Vasut6a131772019-08-07 19:56:09 +02004109 while (mmio_read_32(CPG_MSTPSR5) & BIT(22))
4110 ; /* wait bit=0 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004111 }
4112
4113 /* THCTR Bit6: PONM=0 , Bit0: THSST=0 */
Marek Vasut38dc7562019-08-07 19:17:42 +02004114 data_l = mmio_read_32(THS1_THCTR) & 0xFFFFFFBE;
4115 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004116
Marek Vasut6a131772019-08-07 19:56:09 +02004117 /* Judge product and cut */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004118#ifdef RCAR_DDR_FIXED_LSI_TYPE
Marek Vasut80784f92019-08-07 19:02:26 +02004119#if (RCAR_LSI == RCAR_AUTO)
Marek Vasut38dc7562019-08-07 19:17:42 +02004120 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4121 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004122#else /* RCAR_LSI */
4123#ifndef RCAR_LSI_CUT
Marek Vasut38dc7562019-08-07 19:17:42 +02004124 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004125#endif /* RCAR_LSI_CUT */
4126#endif /* RCAR_LSI */
4127#else /* RCAR_DDR_FIXED_LSI_TYPE */
Marek Vasut38dc7562019-08-07 19:17:42 +02004128 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4129 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004130#endif /* RCAR_DDR_FIXED_LSI_TYPE */
4131
Marek Vasut38dc7562019-08-07 19:17:42 +02004132 if (prr_product == PRR_PRODUCT_H3) {
4133 if (prr_cut <= PRR_PRODUCT_11) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004134 p_ddr_regdef_tbl =
4135 (const uint32_t *)&DDR_REGDEF_TBL[0][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004136 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004137 p_ddr_regdef_tbl =
4138 (const uint32_t *)&DDR_REGDEF_TBL[2][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004139 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004140 } else if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004141 p_ddr_regdef_tbl =
4142 (const uint32_t *)&DDR_REGDEF_TBL[1][0];
Marek Vasut6a131772019-08-07 19:56:09 +02004143 } else if ((prr_product == PRR_PRODUCT_M3N) ||
4144 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004145 p_ddr_regdef_tbl =
4146 (const uint32_t *)&DDR_REGDEF_TBL[3][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004147 } else {
Marek Vasut6c245a52018-12-12 18:06:39 +01004148 FATAL_MSG("BL2: DDR:Unknown Product\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004149 return 0xff;
4150 }
4151
Marek Vasut6a131772019-08-07 19:56:09 +02004152 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4153 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004154 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4155 } else {
4156 mmio_write_32(DBSC_DBSYSCNT0, 0x00001234);
4157 }
4158
Marek Vasut6a131772019-08-07 19:56:09 +02004159 /* Judge board type */
Marek Vasut38dc7562019-08-07 19:17:42 +02004160 cnf_boardtype = boardcnf_get_brd_type();
4161 if (cnf_boardtype >= BOARDNUM) {
Marek Vasut6c245a52018-12-12 18:06:39 +01004162 FATAL_MSG("BL2: DDR:Unknown Board\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004163 return 0xff;
4164 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004165 board_cnf = (const struct _boardcnf *)&boardcnfs[cnf_boardtype];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004166
4167/* RCAR_DRAM_SPLIT_2CH (2U) */
4168#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02004169 /* H3(Test for future H3-N): Swap ch2 and ch1 for 2ch-split */
Marek Vasut38dc7562019-08-07 19:17:42 +02004170 if ((prr_product == PRR_PRODUCT_H3) && (board_cnf->phyvalid == 0x05)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004171 mmio_write_32(DBSC_DBMEMSWAPCONF0, 0x00000006);
4172 ddr_phyvalid = 0x03;
4173 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004174 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004175 }
4176#else /* RCAR_DRAM_SPLIT_2CH */
Marek Vasut38dc7562019-08-07 19:17:42 +02004177 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004178#endif /* RCAR_DRAM_SPLIT_2CH */
4179
4180 max_density = 0;
4181
4182 for (cs = 0; cs < CS_CNT; cs++) {
4183 ch_have_this_cs[cs] = 0;
4184 }
4185
4186 foreach_ech(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02004187 for (cs = 0; cs < CS_CNT; cs++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004188 ddr_density[ch][cs] = 0xff;
4189
4190 foreach_vch(ch) {
4191 for (cs = 0; cs < CS_CNT; cs++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004192 data_l = board_cnf->ch[ch].ddr_density[cs];
4193 ddr_density[ch][cs] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004194
Marek Vasut38dc7562019-08-07 19:17:42 +02004195 if (data_l == 0xff)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004196 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02004197 if (data_l > max_density)
4198 max_density = data_l;
Marek Vasut6a131772019-08-07 19:56:09 +02004199 if ((cs == 1) && (prr_product == PRR_PRODUCT_H3) &&
4200 (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004201 continue;
4202 ch_have_this_cs[cs] |= (1U << ch);
4203 }
4204 }
4205
Marek Vasut6a131772019-08-07 19:56:09 +02004206 /* Judge board clock frequency (in MHz) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004207 boardcnf_get_brd_clk(cnf_boardtype, &brd_clk, &brd_clkdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004208 if ((brd_clk / brd_clkdiv) > 25) {
4209 brd_clkdiva = 1;
4210 } else {
4211 brd_clkdiva = 0;
4212 }
4213
Marek Vasut6a131772019-08-07 19:56:09 +02004214 /* Judge ddr operating frequency clock(in Mbps) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004215 boardcnf_get_ddr_mbps(cnf_boardtype, &ddr_mbps, &ddr_mbpsdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004216
4217 ddr0800_mul = CLK_DIV(800, 2, brd_clk, brd_clkdiv * (brd_clkdiva + 1));
4218
Marek Vasut80784f92019-08-07 19:02:26 +02004219 ddr_mul = CLK_DIV(ddr_mbps, ddr_mbpsdiv * 2, brd_clk,
4220 brd_clkdiv * (brd_clkdiva + 1));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004221
Marek Vasut6a131772019-08-07 19:56:09 +02004222 /* Adjust tccd */
Marek Vasut38dc7562019-08-07 19:17:42 +02004223 data_l = (0x00006000 & mmio_read_32(RST_MODEMR)) >> 13;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09004224 bus_mbps = 0;
4225 bus_mbpsdiv = 0;
Marek Vasut38dc7562019-08-07 19:17:42 +02004226 switch (data_l) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004227 case 0:
4228 bus_mbps = brd_clk * 0x60 * 2;
4229 bus_mbpsdiv = brd_clkdiv * 1;
4230 break;
4231 case 1:
4232 bus_mbps = brd_clk * 0x50 * 2;
4233 bus_mbpsdiv = brd_clkdiv * 1;
4234 break;
4235 case 2:
4236 bus_mbps = brd_clk * 0x40 * 2;
4237 bus_mbpsdiv = brd_clkdiv * 1;
4238 break;
4239 case 3:
4240 bus_mbps = brd_clk * 0x60 * 2;
4241 bus_mbpsdiv = brd_clkdiv * 2;
4242 break;
4243 default:
4244 bus_mbps = brd_clk * 0x60 * 2;
4245 bus_mbpsdiv = brd_clkdiv * 2;
4246 break;
4247 }
4248 tmp_tccd = CLK_DIV(ddr_mbps * 8, ddr_mbpsdiv, bus_mbps, bus_mbpsdiv);
4249 if (8 * ddr_mbps * bus_mbpsdiv != tmp_tccd * bus_mbps * ddr_mbpsdiv)
4250 tmp_tccd = tmp_tccd + 1;
4251
4252 if (tmp_tccd < 8)
4253 ddr_tccd = 8;
4254 else
4255 ddr_tccd = tmp_tccd;
4256
Marek Vasut6c245a52018-12-12 18:06:39 +01004257 NOTICE("BL2: DDR%d(%s)\n", ddr_mbps / ddr_mbpsdiv, RCAR_DDR_VERSION);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004258
4259 MSG_LF("Start\n");
4260
Marek Vasut6a131772019-08-07 19:56:09 +02004261 /* PLL Setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004262 pll3_control(1);
4263
Marek Vasut6a131772019-08-07 19:56:09 +02004264 /* initialize DDR */
Marek Vasut38dc7562019-08-07 19:17:42 +02004265 data_l = init_ddr();
4266 if (data_l == ddr_phyvalid) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004267 failcount = 0;
4268 } else {
4269 failcount = 1;
4270 }
4271
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004272 foreach_vch(ch)
4273 mmio_write_32(DBSC_DBPDLK(ch), 0x00000000);
Marek Vasut6a131772019-08-07 19:56:09 +02004274 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4275 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004276 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4277 } else {
4278 mmio_write_32(DBSC_DBSYSCNT0, 0x00000000);
4279 }
4280
4281 if (failcount == 0) {
4282 return INITDRAM_OK;
4283 } else {
4284 return INITDRAM_NG;
4285 }
4286}
4287
4288void pvtcode_update(void)
4289{
4290 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004291 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004292 uint32_t pvtp[4], pvtn[4], pvtp_init, pvtn_init;
4293 int32_t pvtp_tmp, pvtn_tmp;
4294
4295 foreach_vch(ch) {
4296 pvtn_init = (tcal.tcomp_cal[ch] & 0xFC0) >> 6;
4297 pvtp_init = (tcal.tcomp_cal[ch] & 0x03F) >> 0;
4298
4299 if (8912 * pvtp_init > 44230) {
4300 pvtp_tmp = (5000 + 8912 * pvtp_init - 44230) / 10000;
4301 } else {
4302 pvtp_tmp =
4303 -((-(5000 + 8912 * pvtp_init - 44230)) / 10000);
4304 }
4305 pvtn_tmp = (5000 + 5776 * pvtn_init + 30280) / 10000;
4306
4307 pvtn[ch] = pvtn_tmp + pvtn_init;
4308 pvtp[ch] = pvtp_tmp + pvtp_init;
4309
4310 if (pvtn[ch] > 63) {
4311 pvtn[ch] = 63;
4312 pvtp[ch] =
4313 (pvtp_tmp) * (63 - 6 * pvtn_tmp -
4314 pvtn_init) / (pvtn_tmp) +
4315 6 * pvtp_tmp + pvtp_init;
4316 }
Marek Vasut6a131772019-08-07 19:56:09 +02004317 if ((prr_product == PRR_PRODUCT_H3) &&
4318 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004319 data_l = pvtp[ch] | (pvtn[ch] << 6) |
4320 (tcal.tcomp_cal[ch] & 0xfffff000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004321 reg_ddrphy_write(ch,
4322 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004323 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004324 reg_ddrphy_write(ch,
4325 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004326 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004327 reg_ddrphy_write(ch,
4328 ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004329 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004330 reg_ddrphy_write(ch,
4331 ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004332 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004333 reg_ddrphy_write(ch,
4334 ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004335 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004336 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004337 data_l = pvtp[ch] | (pvtn[ch] << 6) | 0x00015000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004338 reg_ddrphy_write(ch,
4339 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004340 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004341 reg_ddrphy_write(ch,
4342 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004343 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004344 reg_ddrphy_write(ch,
4345 ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004346 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004347 reg_ddrphy_write(ch,
4348 ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004349 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004350 reg_ddrphy_write(ch,
4351 ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004352 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004353 }
4354 }
4355}
4356
4357void pvtcode_update2(void)
4358{
4359 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02004360
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004361 foreach_vch(ch) {
4362 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
4363 tcal.init_cal[ch] | 0x00020000);
4364 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
4365 tcal.init_cal[ch]);
4366 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
4367 tcal.init_cal[ch]);
4368 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
4369 tcal.init_cal[ch]);
4370 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
4371 tcal.init_cal[ch]);
4372 }
4373}
4374
4375void ddr_padcal_tcompensate_getinit(uint32_t override)
4376{
4377 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004378 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004379 uint32_t pvtp, pvtn;
4380
4381 tcal.init_temp = 0;
4382 for (ch = 0; ch < 4; ch++) {
4383 tcal.init_cal[ch] = 0;
4384 tcal.tcomp_cal[ch] = 0;
4385 }
4386
4387 foreach_vch(ch) {
4388 tcal.init_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4389 tcal.tcomp_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4390 }
4391
4392 if (!override) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004393 data_l = mmio_read_32(THS1_TEMP);
4394 if (data_l < 2800) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004395 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004396 (143 * (int32_t)data_l - 359000) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004397 } else {
4398 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004399 (121 * (int32_t)data_l - 296300) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004400 }
4401
4402 foreach_vch(ch) {
4403 pvtp = (tcal.init_cal[ch] >> 0) & 0x000003F;
4404 pvtn = (tcal.init_cal[ch] >> 6) & 0x000003F;
Marek Vasut80784f92019-08-07 19:02:26 +02004405 if ((int32_t)pvtp >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004406 ((tcal.init_temp * 29 - 3625) / 1000))
4407 pvtp =
Marek Vasut80784f92019-08-07 19:02:26 +02004408 (int32_t)pvtp +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004409 ((3625 - tcal.init_temp * 29) / 1000);
4410 else
4411 pvtp = 0;
4412
Marek Vasut80784f92019-08-07 19:02:26 +02004413 if ((int32_t)pvtn >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004414 ((tcal.init_temp * 54 - 6750) / 1000))
4415 pvtn =
Marek Vasut80784f92019-08-07 19:02:26 +02004416 (int32_t)pvtn +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004417 ((6750 - tcal.init_temp * 54) / 1000);
4418 else
4419 pvtn = 0;
4420
Marek Vasut6a131772019-08-07 19:56:09 +02004421 if ((prr_product == PRR_PRODUCT_H3) &&
4422 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004423 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004424 (tcal.init_cal[ch] & 0xfffff000) |
4425 (pvtn << 6) |
4426 pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004427 } else {
4428 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004429 0x00015000 | (pvtn << 6) | pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004430 }
4431 }
4432 tcal.init_temp = 125;
4433 }
4434}
4435
4436#ifndef ddr_qos_init_setting
Marek Vasut6ad74c32019-08-08 16:34:22 +02004437/* For QoS init */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004438uint8_t get_boardcnf_phyvalid(void)
4439{
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004440 return ddr_phyvalid;
4441}
4442#endif /* ddr_qos_init_setting */