blob: 77a07f72abf1fe7a48d24e8f94bb23d18e56d015 [file] [log] [blame]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001/*
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002 * Copyright (c) 2015-2020, Renesas Electronics Corporation.
Marek Vasut6ad74c32019-08-08 16:34:22 +02003 * 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
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002386#if RCAR_REWT_TRAINING != 0
2387 /* Periodic-WriteDQ Training seeting */
Marek Vasut6a131772019-08-07 19:56:09 +02002388 if (((prr_product == PRR_PRODUCT_H3) &&
2389 (prr_cut <= PRR_PRODUCT_11)) ||
2390 ((prr_product == PRR_PRODUCT_M3) &&
2391 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002392 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2393 } else {
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002394 /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002395 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000);
2396
2397 ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04);
2398 ddr_setval_ach_as(_reg_PHY_WDQLVL_QTR_DLY_STEP, 0x0F);
2399 ddr_setval_ach_as(_reg_PHY_WDQLVL_DLY_STEP, 0x50);
2400 ddr_setval_ach_as(_reg_PHY_WDQLVL_DQDM_SLV_DLY_START, 0x0300);
2401
2402 ddr_setval_ach(_reg_PI_WDQLVL_CS_MAP,
2403 ddrtbl_getval(_cnf_DDR_PI_REGSET,
2404 _reg_PI_WDQLVL_CS_MAP));
2405 ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f);
2406 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002407 ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01);
2408 ddr_setval_ach(_reg_PI_TREF_F0, 0x0000);
2409 ddr_setval_ach(_reg_PI_TREF_F1, 0x0000);
2410 ddr_setval_ach(_reg_PI_TREF_F2, 0x0000);
2411
Marek Vasut38dc7562019-08-07 19:17:42 +02002412 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002413 ddr_setval_ach(_reg_PI_WDQLVL_EN, 0x02);
2414 } else {
2415 ddr_setval_ach(_reg_PI_WDQLVL_EN_F1, 0x02);
2416 }
2417 ddr_setval_ach(_reg_PI_WDQLVL_PERIODIC, 0x01);
2418
2419 /* DFI_PHYMSTR_ACK , WTmode setting */
Marek Vasut6ad74c32019-08-08 16:34:22 +02002420 /* DFI_PHYMSTR_ACK: WTmode =b'01 */
2421 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002422 }
2423#endif /* RCAR_REWT_TRAINING */
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002424 /* periodic dram zqcal enable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002425 mmio_write_32(DBSC_DBCALCNF, 0x01000010);
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002426
2427 /* periodic phy ctrl update enable */
Marek Vasut6a131772019-08-07 19:56:09 +02002428 if (((prr_product == PRR_PRODUCT_H3) &&
2429 (prr_cut <= PRR_PRODUCT_11)) ||
2430 ((prr_product == PRR_PRODUCT_M3) &&
2431 (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002432 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
2433 } else {
2434#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02002435 if ((prr_product == PRR_PRODUCT_H3) &&
2436 (board_cnf->phyvalid == 0x05))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002437 mmio_write_32(DBSC_DBDFICUPDCNF, 0x2a240001);
2438 else
2439 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2440#else /* RCAR_DRAM_SPLIT == 2 */
2441 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2442#endif /* RCAR_DRAM_SPLIT == 2 */
2443 }
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002444
2445#ifdef DDR_BACKUPMODE
2446 /* SRX */
2447 if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
2448#ifdef DDR_BACKUPMODE_HALF /* for Half channel(ch0, 1 only) */
2449 NOTICE("BL2: [DEBUG_MESS] DDR_BACKUPMODE_HALF\n");
2450 send_dbcmd(0x0A040001);
2451 if (Prr_Product == PRR_PRODUCT_H3)
2452 send_dbcmd(0x0A140001);
2453#else /* DDR_BACKUPMODE_HALF */ /* for All channels */
2454 send_dbcmd(0x0A840001);
2455#endif /* DDR_BACKUPMODE_HALF */
2456 }
2457#endif /* DDR_BACKUPMODE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002458
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002459 /* set Auto Refresh */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002460 mmio_write_32(DBSC_DBRFEN, 0x00000001);
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002461
2462#if RCAR_REWT_TRAINING != 0
2463 /* Periodic WriteDQ Traning */
2464 if (((prr_product == PRR_PRODUCT_H3) &&
2465 (prr_cut <= PRR_PRODUCT_11)) ||
2466 ((prr_product == PRR_PRODUCT_M3) &&
2467 (prr_cut == PRR_PRODUCT_10))) {
2468 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2469 } else {
2470 /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
2471 ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
2472 }
2473#endif /* RCAR_REWT_TRAINING */
2474
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002475 /* dram access enable */
2476 mmio_write_32(DBSC_DBACEN, 0x00000001);
2477
Marek Vasut6ad74c32019-08-08 16:34:22 +02002478 MSG_LF(__func__ "(done)");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002479}
2480
Marek Vasut6a131772019-08-07 19:56:09 +02002481/* DFI_INIT_START */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002482static uint32_t dfi_init_start(void)
2483{
2484 uint32_t ch;
2485 uint32_t phytrainingok;
2486 uint32_t retry;
Marek Vasut38dc7562019-08-07 19:17:42 +02002487 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002488 const uint32_t RETRY_MAX = 0x10000;
2489
Marek Vasut38dc7562019-08-07 19:17:42 +02002490 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002491 /* PLL3 Disable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002492 /* protect register interface */
2493 ddrphy_regif_idle();
2494
2495 pll3_control(0);
2496
Marek Vasut6a131772019-08-07 19:56:09 +02002497 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002498 /* dbdficnt0:
2499 * dfi_dram_clk_disable=1
2500 * dfi_frequency = 0
2501 * freq_ratio = 01 (2:1)
2502 * init_start =0
2503 */
2504 foreach_vch(ch)
2505 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
2506 dsb_sev();
2507
2508 /* dbdficnt0:
2509 * dfi_dram_clk_disable=1
2510 * dfi_frequency = 0
2511 * freq_ratio = 01 (2:1)
2512 * init_start =1
2513 */
2514 foreach_vch(ch)
2515 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
2516 dsb_sev();
2517
2518 } else {
2519 ddr_setval_ach_as(_reg_PHY_DLL_RST_EN, 0x02);
2520 dsb_sev();
2521 ddrphy_regif_idle();
2522 }
2523
2524 /* dll_rst negate */
2525 foreach_vch(ch)
2526 mmio_write_32(DBSC_DBPDCNT3(ch), 0x0000CF01);
2527 dsb_sev();
2528
Marek Vasut6a131772019-08-07 19:56:09 +02002529 /* wait init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002530 phytrainingok = 0;
2531 retry = 0;
2532 while (retry++ < RETRY_MAX) {
2533 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002534 data_l = mmio_read_32(DBSC_DBDFISTAT(ch));
2535 if (data_l & 0x00000001)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002536 phytrainingok |= (1U << ch);
2537 }
2538 dsb_sev();
2539 if (phytrainingok == ddr_phyvalid)
2540 break;
2541 if (retry % 256 == 0)
2542 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
2543 }
2544
Marek Vasut6a131772019-08-07 19:56:09 +02002545 /* all ch ok? */
2546 if ((phytrainingok & ddr_phyvalid) != ddr_phyvalid)
2547 return 0xff;
2548
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002549 /* dbdficnt0:
2550 * dfi_dram_clk_disable=0
2551 * dfi_frequency = 0
2552 * freq_ratio = 01 (2:1)
2553 * init_start =0
2554 */
2555 foreach_vch(ch)
2556 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000010);
2557 dsb_sev();
2558
2559 return 0;
2560}
2561
Marek Vasut6a131772019-08-07 19:56:09 +02002562/* drivablity setting : CMOS MODE ON/OFF */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002563static void change_lpddr4_en(uint32_t mode)
2564{
2565 uint32_t ch;
2566 uint32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002567 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002568 const uint32_t _reg_PHY_PAD_DRIVE_X[3] = {
2569 _reg_PHY_PAD_ADDR_DRIVE,
2570 _reg_PHY_PAD_CLK_DRIVE,
2571 _reg_PHY_PAD_CS_DRIVE
2572 };
2573
Marek Vasut6c245a52018-12-12 18:06:39 +01002574 foreach_vch(ch) {
2575 for (i = 0; i < 3; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002576 data_l = ddr_getval(ch, _reg_PHY_PAD_DRIVE_X[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002577 if (mode) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002578 data_l |= (1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002579 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002580 data_l &= ~(1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002581 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002582 ddr_setval(ch, _reg_PHY_PAD_DRIVE_X[i], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002583 }
2584 }
2585}
2586
Marek Vasut6a131772019-08-07 19:56:09 +02002587/* drivablity setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002588static uint32_t set_term_code(void)
2589{
2590 int32_t i;
2591 uint32_t ch, index;
Marek Vasut38dc7562019-08-07 19:17:42 +02002592 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002593 uint32_t chip_id[2];
2594 uint32_t term_code;
2595 uint32_t override;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002596 uint32_t pvtr;
2597 uint32_t pvtp;
2598 uint32_t pvtn;
Marek Vasut80784f92019-08-07 19:02:26 +02002599
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002600 term_code = ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2601 _reg_PHY_PAD_DATA_TERM);
2602 override = 0;
2603 for (i = 0; i < 2; i++)
2604 chip_id[i] = mmio_read_32(LIFEC_CHIPID(i));
2605
2606 index = 0;
2607 while (1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002608 if (termcode_by_sample[index][0] == 0xffffffff) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002609 break;
2610 }
Marek Vasut6a131772019-08-07 19:56:09 +02002611 if ((termcode_by_sample[index][0] == chip_id[0]) &&
2612 (termcode_by_sample[index][1] == chip_id[1])) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002613 term_code = termcode_by_sample[index][2];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002614 override = 1;
2615 break;
2616 }
2617 index++;
2618 }
2619
2620 if (override) {
2621 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002622 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002623 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2624 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002625 data_l = (data_l & 0xfffe0000) | term_code;
2626 ddr_setval_ach(_reg_PHY_PAD_TERM_X[index], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002627 }
Marek Vasut6a131772019-08-07 19:56:09 +02002628 } else if ((prr_product == PRR_PRODUCT_M3) &&
2629 (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002630 /* non */
2631 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002632 ddr_setval_ach(_reg_PHY_PAD_TERM_X[0],
2633 (ddrtbl_getval
2634 (_cnf_DDR_PHY_ADR_G_REGSET,
2635 _reg_PHY_PAD_TERM_X[0]) & 0xFFFE0000));
2636 ddr_setval_ach(_reg_PHY_CAL_CLEAR_0, 0x01);
2637 ddr_setval_ach(_reg_PHY_CAL_START_0, 0x01);
2638 foreach_vch(ch) {
2639 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002640 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002641 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002642 } while (!(data_l & 0x00800000));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002643 }
Marek Vasut6a131772019-08-07 19:56:09 +02002644 if ((prr_product == PRR_PRODUCT_H3) &&
2645 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002646 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002647 data_l = ddr_getval(ch, _reg_PHY_PAD_TERM_X[0]);
2648 pvtr = (data_l >> 12) & 0x1f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002649 pvtr += 8;
2650 if (pvtr > 0x1f)
2651 pvtr = 0x1f;
Marek Vasut38dc7562019-08-07 19:17:42 +02002652 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002653 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002654 pvtn = (data_l >> 6) & 0x03f;
2655 pvtp = (data_l >> 0) & 0x03f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002656
2657 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2658 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002659 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002660 ddrtbl_getval
2661 (_cnf_DDR_PHY_ADR_G_REGSET,
2662 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002663 data_l = (data_l & 0xfffe0000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002664 | (pvtr << 12)
2665 | (pvtn << 6)
2666 | (pvtp);
2667 ddr_setval(ch,
2668 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002669 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002670 }
2671 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02002672 } else {
2673 /* M3-W Ver.1.1 or later/H3 Ver.2.0 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002674 foreach_vch(ch) {
2675 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2676 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002677 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002678 ddr_getval(ch,
2679 _reg_PHY_PAD_TERM_X
2680 [index]);
2681 ddr_setval(ch,
2682 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002683 (data_l & 0xFFFE0FFF) |
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002684 0x00015000);
2685 }
2686 }
2687 }
2688 }
Marek Vasut6a131772019-08-07 19:56:09 +02002689
Marek Vasut38dc7562019-08-07 19:17:42 +02002690 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002691 /* non */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002692 } else {
2693 ddr_padcal_tcompensate_getinit(override);
2694 }
Marek Vasut6a131772019-08-07 19:56:09 +02002695
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002696 return 0;
2697}
2698
Marek Vasut6a131772019-08-07 19:56:09 +02002699/* DDR mode register setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01002700static void ddr_register_set(void)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002701{
2702 int32_t fspwp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002703 uint32_t tmp;
2704
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002705 for (fspwp = 1; fspwp >= 0; fspwp--) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002706 /*MR13, fspwp */
2707 send_dbcmd(0x0e840d08 | ((2 - fspwp) << 6));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002708
2709 tmp =
2710 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002711 reg_pi_mr1_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002712 send_dbcmd(0x0e840100 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002713
2714 tmp =
2715 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002716 reg_pi_mr2_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002717 send_dbcmd(0x0e840200 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002718
2719 tmp =
2720 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002721 reg_pi_mr3_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002722 send_dbcmd(0x0e840300 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002723
2724 tmp =
2725 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002726 reg_pi_mr11_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002727 send_dbcmd(0x0e840b00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002728
2729 tmp =
2730 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002731 reg_pi_mr12_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002732 send_dbcmd(0x0e840c00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002733
2734 tmp =
2735 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002736 reg_pi_mr14_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002737 send_dbcmd(0x0e840e00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002738 /* MR22 */
Marek Vasut6c245a52018-12-12 18:06:39 +01002739 send_dbcmd(0x0e841616);
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002740
2741 /* ZQCAL start */
2742 send_dbcmd(0x0d84004F);
2743
2744 /* ZQLAT */
2745 send_dbcmd(0x0d840051);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002746 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002747
2748 /* MR13, fspwp */
2749 send_dbcmd(0x0e840d08);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002750}
2751
Marek Vasut6a131772019-08-07 19:56:09 +02002752/* Training handshake functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002753static inline uint32_t wait_freqchgreq(uint32_t assert)
2754{
Marek Vasut38dc7562019-08-07 19:17:42 +02002755 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002756 uint32_t count;
2757 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002758
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002759 count = 100000;
2760
2761 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut38dc7562019-08-07 19:17:42 +02002762 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002763 return 0;
2764 }
2765
2766 if (assert) {
2767 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002768 data_l = 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002769 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002770 data_l &= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002771 }
2772 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002773 } while (((data_l & 0x01) != 0x01) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002774 } else {
2775 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002776 data_l = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002777 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002778 data_l |= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002779 }
2780 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002781 } while (((data_l & 0x01) != 0x00) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002782 }
2783
2784 return (count == 0);
2785}
2786
2787static inline void set_freqchgack(uint32_t assert)
2788{
2789 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002790 uint32_t data_l;
Marek Vasut80784f92019-08-07 19:02:26 +02002791
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002792 if (assert)
Marek Vasut38dc7562019-08-07 19:17:42 +02002793 data_l = 0x0CF20000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002794 else
Marek Vasut38dc7562019-08-07 19:17:42 +02002795 data_l = 0x00000000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002796
2797 foreach_vch(ch)
Marek Vasut38dc7562019-08-07 19:17:42 +02002798 mmio_write_32(DBSC_DBPDCNT2(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002799}
2800
2801static inline void set_dfifrequency(uint32_t freq)
2802{
2803 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002804
Marek Vasut38dc7562019-08-07 19:17:42 +02002805 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002806 foreach_vch(ch)
2807 mmio_clrsetbits_32(DBSC_DBPDCNT1(ch), 0x1fU, freq);
2808 } else {
2809 foreach_vch(ch) {
2810 mmio_clrsetbits_32(DBSC_DBDFICNT(ch), 0x1fU << 24,
2811 (freq << 24));
2812 }
2813 }
2814 dsb_sev();
2815}
2816
2817static uint32_t pll3_freq(uint32_t on)
2818{
2819 uint32_t timeout;
2820
2821 timeout = wait_freqchgreq(1);
2822
2823 if (timeout) {
Marek Vasut6a131772019-08-07 19:56:09 +02002824 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002825 }
2826
2827 pll3_control(on);
2828 set_dfifrequency(on);
2829
2830 set_freqchgack(1);
2831 timeout = wait_freqchgreq(0);
2832 set_freqchgack(0);
2833
2834 if (timeout) {
Marek Vasut56519892019-01-21 23:11:33 +01002835 FATAL_MSG("BL2: Time out[2]\n");
Marek Vasut6a131772019-08-07 19:56:09 +02002836 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002837 }
Marek Vasut6a131772019-08-07 19:56:09 +02002838 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002839}
2840
Marek Vasut6a131772019-08-07 19:56:09 +02002841/* update dly */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002842static void update_dly(void)
2843{
2844 ddr_setval_ach(_reg_SC_PHY_MANUAL_UPDATE, 0x01);
2845 ddr_setval_ach(_reg_PHY_ADRCTL_MANUAL_UPDATE, 0x01);
2846}
2847
Marek Vasut6a131772019-08-07 19:56:09 +02002848/* training by pi */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002849static uint32_t pi_training_go(void)
2850{
2851 uint32_t flag;
Marek Vasut38dc7562019-08-07 19:17:42 +02002852 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002853 uint32_t retry;
2854 const uint32_t RETRY_MAX = 4096 * 16;
2855 uint32_t ch;
2856
2857 uint32_t mst_ch;
2858 uint32_t cur_frq;
2859 uint32_t complete;
2860 uint32_t frqchg_req;
2861
Marek Vasut6a131772019-08-07 19:56:09 +02002862 /* pi_start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002863 ddr_setval_ach(_reg_PI_START, 0x01);
2864 foreach_vch(ch)
2865 ddr_getval(ch, _reg_PI_INT_STATUS);
2866
2867 /* set dfi_phymstr_ack = 1 */
2868 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000001);
2869 dsb_sev();
2870
Marek Vasut6a131772019-08-07 19:56:09 +02002871 /* wait pi_int_status[0] */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002872 mst_ch = 0;
2873 flag = 0;
2874 complete = 0;
2875 cur_frq = 0;
2876 retry = RETRY_MAX;
2877 do {
2878 frqchg_req = mmio_read_32(DBSC_DBPDSTAT(mst_ch)) & 0x01;
2879
2880 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut6a131772019-08-07 19:56:09 +02002881 if ((prr_product == PRR_PRODUCT_H3) &&
2882 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002883 if ((retry % 4096) == 1) {
2884 frqchg_req = 1;
2885 } else {
2886 frqchg_req = 0;
2887 }
2888 }
2889
2890 if (frqchg_req) {
2891 if (cur_frq) {
2892 /* Low frequency */
2893 flag = pll3_freq(0);
2894 cur_frq = 0;
2895 } else {
2896 /* High frequency */
2897 flag = pll3_freq(1);
2898 cur_frq = 1;
2899 }
2900 if (flag)
2901 break;
2902 } else {
2903 if (cur_frq) {
2904 foreach_vch(ch) {
2905 if (complete & (1U << ch))
2906 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02002907 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002908 ddr_getval(ch, _reg_PI_INT_STATUS);
Marek Vasut38dc7562019-08-07 19:17:42 +02002909 if (data_l & 0x01) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002910 complete |= (1U << ch);
2911 }
2912 }
2913 if (complete == ddr_phyvalid)
2914 break;
2915 }
2916 }
2917 } while (--retry);
2918 foreach_vch(ch) {
2919 /* dummy read */
Marek Vasut38dc7562019-08-07 19:17:42 +02002920 data_l = ddr_getval_s(ch, 0, _reg_PHY_CAL_RESULT2_OBS_0);
2921 data_l = ddr_getval(ch, _reg_PI_INT_STATUS);
2922 ddr_setval(ch, _reg_PI_INT_ACK, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002923 }
2924 if (ddrphy_regif_chk()) {
Marek Vasut6a131772019-08-07 19:56:09 +02002925 return 0xfd;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002926 }
2927 return complete;
2928}
2929
Marek Vasut6a131772019-08-07 19:56:09 +02002930/* Initialize DDR */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002931static uint32_t init_ddr(void)
2932{
2933 int32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002934 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002935 uint32_t phytrainingok;
Marek Vasut6c245a52018-12-12 18:06:39 +01002936 uint32_t ch, slice;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002937 uint32_t err;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002938 int16_t adj;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002939
Marek Vasut6ad74c32019-08-08 16:34:22 +02002940 MSG_LF(__func__ ":0\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002941
2942#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02002943 rcar_dram_get_boot_status(&ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002944#endif
2945
Marek Vasut6a131772019-08-07 19:56:09 +02002946 /* unlock phy */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002947 /* Unlock DDRPHY register(AGAIN) */
2948 foreach_vch(ch)
2949 mmio_write_32(DBSC_DBPDLK(ch), 0x0000A55A);
2950 dsb_sev();
2951
Marek Vasut6a131772019-08-07 19:56:09 +02002952 if ((((prr_product == PRR_PRODUCT_H3) &&
2953 (prr_cut > PRR_PRODUCT_11)) ||
2954 (prr_product == PRR_PRODUCT_M3N) ||
2955 (prr_product == PRR_PRODUCT_V3H)) && board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002956 reg_ddrphy_write_a(0x00001010, 0x01000001);
2957 else
2958 reg_ddrphy_write_a(0x00001010, 0x00000001);
Marek Vasut6a131772019-08-07 19:56:09 +02002959 /* DBSC register pre-setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002960 dbsc_regset_pre();
2961
Marek Vasut6a131772019-08-07 19:56:09 +02002962 /* load ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002963
2964 ddrtbl_load();
2965
Marek Vasut6a131772019-08-07 19:56:09 +02002966 /* configure ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002967 ddr_config();
2968
Marek Vasut6a131772019-08-07 19:56:09 +02002969 /* dfi_reset assert */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002970 foreach_vch(ch)
2971 mmio_write_32(DBSC_DBPDCNT0(ch), 0x01);
2972 dsb_sev();
2973
Marek Vasut6a131772019-08-07 19:56:09 +02002974 /* dbsc register set */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002975 dbsc_regset();
Marek Vasut6ad74c32019-08-08 16:34:22 +02002976 MSG_LF(__func__ ":1\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002977
Marek Vasut6a131772019-08-07 19:56:09 +02002978 /* dfi_reset negate */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002979 foreach_vch(ch)
2980 mmio_write_32(DBSC_DBPDCNT0(ch), 0x00);
2981 dsb_sev();
2982
Marek Vasut6a131772019-08-07 19:56:09 +02002983 /* dfi_init_start (start ddrphy) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002984 err = dfi_init_start();
2985 if (err) {
2986 return INITDRAM_ERR_I;
2987 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02002988 MSG_LF(__func__ ":2\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002989
Marek Vasut6a131772019-08-07 19:56:09 +02002990 /* ddr backupmode end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002991#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02002992 if (ddr_backup) {
Marek Vasut56519892019-01-21 23:11:33 +01002993 NOTICE("BL2: [WARM_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002994 } else {
Marek Vasut56519892019-01-21 23:11:33 +01002995 NOTICE("BL2: [COLD_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002996 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002997 err = rcar_dram_update_boot_status(ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002998 if (err) {
Marek Vasut56519892019-01-21 23:11:33 +01002999 NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003000 return INITDRAM_ERR_I;
3001 }
3002#endif
Marek Vasut6ad74c32019-08-08 16:34:22 +02003003 MSG_LF(__func__ ":3\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003004
Marek Vasut6a131772019-08-07 19:56:09 +02003005 /* override term code after dfi_init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003006 err = set_term_code();
3007 if (err) {
3008 return INITDRAM_ERR_I;
3009 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003010 MSG_LF(__func__ ":4\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003011
Marek Vasut6a131772019-08-07 19:56:09 +02003012 /* rx offset calibration */
3013 if ((prr_cut > PRR_PRODUCT_11) || (prr_product == PRR_PRODUCT_M3N) ||
3014 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003015 err = rx_offset_cal_hw();
3016 } else {
3017 err = rx_offset_cal();
3018 }
3019 if (err)
Marek Vasut6a131772019-08-07 19:56:09 +02003020 return INITDRAM_ERR_O;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003021 MSG_LF(__func__ ":5\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003022
Chiaki Fujiiaea02862019-09-18 13:10:00 +09003023 /* Dummy PDE */
3024 send_dbcmd(0x08840000);
3025
Marek Vasut6c245a52018-12-12 18:06:39 +01003026 /* PDX */
3027 send_dbcmd(0x08840001);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003028
Marek Vasut6a131772019-08-07 19:56:09 +02003029 /* check register i/f is alive */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003030 err = ddrphy_regif_chk();
3031 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003032 return INITDRAM_ERR_O;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003033 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003034 MSG_LF(__func__ ":6\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003035
Marek Vasut6a131772019-08-07 19:56:09 +02003036 /* phy initialize end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003037
Marek Vasut6a131772019-08-07 19:56:09 +02003038 /* setup DDR mode registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003039 /* CMOS MODE */
3040 change_lpddr4_en(0);
3041
Marek Vasut6c245a52018-12-12 18:06:39 +01003042 /* MRS */
3043 ddr_register_set();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003044
Marek Vasut6a131772019-08-07 19:56:09 +02003045 /* Thermal sensor setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01003046 /* THCTR Bit6: PONM=0 , Bit0: THSST=1 */
Marek Vasut38dc7562019-08-07 19:17:42 +02003047 data_l = (mmio_read_32(THS1_THCTR) & 0xFFFFFFBF) | 0x00000001;
3048 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003049
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003050 /* LPDDR4 MODE */
3051 change_lpddr4_en(1);
3052
Marek Vasut6ad74c32019-08-08 16:34:22 +02003053 MSG_LF(__func__ ":7\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003054
Marek Vasut6a131772019-08-07 19:56:09 +02003055 /* mask CS_MAP if RANKx is not found */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003056 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003057 data_l = ddr_getval(ch, _reg_PI_CS_MAP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003058 if (!(ch_have_this_cs[1] & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02003059 data_l = data_l & 0x05;
3060 ddr_setval(ch, _reg_PI_CS_MAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003061 }
3062
Marek Vasut6a131772019-08-07 19:56:09 +02003063 /* exec pi_training */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003064 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
3065 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003066 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003067
Marek Vasut38dc7562019-08-07 19:17:42 +02003068 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003069 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_EN, 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003070 } else {
3071 foreach_vch(ch) {
3072 for (slice = 0; slice < SLICE_CNT; slice++) {
3073 ddr_setval_s(ch, slice,
3074 _reg_PHY_PER_CS_TRAINING_EN,
3075 ((ch_have_this_cs[1]) >> ch)
3076 & 0x01);
3077 }
3078 }
3079 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003080
3081 phytrainingok = pi_training_go();
3082
3083 if (ddr_phyvalid != (phytrainingok & ddr_phyvalid)) {
Marek Vasut6a131772019-08-07 19:56:09 +02003084 return INITDRAM_ERR_T | phytrainingok;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003085 }
3086
Marek Vasut6ad74c32019-08-08 16:34:22 +02003087 MSG_LF(__func__ ":8\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003088
Marek Vasut6a131772019-08-07 19:56:09 +02003089 /* CACS DLY ADJUST */
Marek Vasut38dc7562019-08-07 19:17:42 +02003090 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003091 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003092 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003093 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003094 ddr_setval(ch, _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003095 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003096 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003097
3098 if (ddr_phycaslice == 1) {
3099 for (i = 0; i < 6; i++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003100 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj
3101 [i +
3102 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
3103 ddr_setval_s(ch, 2,
3104 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
3105 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003106 data_l + adj
Marek Vasut6c245a52018-12-12 18:06:39 +01003107 );
3108 }
3109 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003110 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003111
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003112 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003113 MSG_LF(__func__ ":9\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003114
Marek Vasut6a131772019-08-07 19:56:09 +02003115 /* H3 fix rd latency to avoid bug in elasitic buffer */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003116 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003117 adjust_rddqs_latency();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003118
Marek Vasut6a131772019-08-07 19:56:09 +02003119 /* Adjust Write path latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003120 if (ddrtbl_getval
3121 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD))
3122 adjust_wpath_latency();
3123
Marek Vasut6a131772019-08-07 19:56:09 +02003124 /* RDQLVL Training */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003125 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003126 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x01);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003127
3128 err = rdqdm_man();
Marek Vasut6c245a52018-12-12 18:06:39 +01003129
Marek Vasut6ad74c32019-08-08 16:34:22 +02003130 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Marek Vasut6c245a52018-12-12 18:06:39 +01003131 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003132
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003133 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003134 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003135 }
3136 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003137 MSG_LF(__func__ ":10\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003138
Marek Vasut6a131772019-08-07 19:56:09 +02003139 /* WDQLVL Training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003140 err = wdqdm_man();
3141 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003142 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003143 }
3144 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003145 MSG_LF(__func__ ":11\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003146
Marek Vasut6a131772019-08-07 19:56:09 +02003147 /* training complete, setup DBSC */
3148 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3149 (prr_product == PRR_PRODUCT_M3N) ||
3150 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003151 ddr_setval_ach_as(_reg_PHY_DFI40_POLARITY, 0x00);
3152 ddr_setval_ach(_reg_PI_DFI40_POLARITY, 0x00);
3153 }
3154
3155 dbsc_regset_post();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003156 MSG_LF(__func__ ":12\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003157
3158 return phytrainingok;
3159}
3160
Marek Vasut6a131772019-08-07 19:56:09 +02003161/* SW LEVELING COMMON */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003162static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick)
3163{
3164 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02003165 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003166 uint32_t retry;
3167 uint32_t waiting;
3168 uint32_t err;
3169
3170 const uint32_t RETRY_MAX = 0x1000;
3171
3172 err = 0;
3173 /* set EXIT -> OP_DONE is cleared */
3174 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3175
3176 /* kick */
3177 foreach_vch(ch) {
3178 if (ch_have_this_cs[ddr_csn % 2] & (1U << ch)) {
3179 ddr_setval(ch, reg_cs, ddr_csn);
3180 ddr_setval(ch, reg_kick, 0x01);
3181 }
3182 }
3183 foreach_vch(ch) {
3184 /*PREPARE ADDR REGISTER (for SWLVL_OP_DONE) */
3185 ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3186 }
3187 waiting = ch_have_this_cs[ddr_csn % 2];
3188 dsb_sev();
3189 retry = RETRY_MAX;
3190 do {
3191 foreach_vch(ch) {
3192 if (!(waiting & (1U << ch)))
3193 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02003194 data_l = ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3195 if (data_l & 0x01)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003196 waiting &= ~(1U << ch);
3197 }
3198 retry--;
3199 } while (waiting && (retry > 0));
3200 if (retry == 0) {
3201 err = 1;
3202 }
3203
3204 dsb_sev();
3205 /* set EXIT -> OP_DONE is cleared */
3206 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3207 dsb_sev();
3208
3209 return err;
3210}
3211
Marek Vasut6a131772019-08-07 19:56:09 +02003212/* WDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003213#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003214static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3215{
3216 int32_t i, k;
3217 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003218 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003219
Marek Vasut6a131772019-08-07 19:56:09 +02003220 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003221 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003222 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003223 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003224 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003225 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3226 continue;
3227
3228 for (i = 0; i <= 8; i++) {
3229 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch))
3230 wdqdm_dly[ch][cs][slice][i] =
3231 wdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3232 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003233 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003234 wdqdm_le[ch][cs][slice][i] = 0;
3235 wdqdm_te[ch][cs][slice][i] = 0;
3236 }
3237 wdqdm_st[ch][cs][slice] = 0;
3238 wdqdm_win[ch][cs][slice] = 0;
3239 }
3240}
3241
3242static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3243{
3244 int32_t i, k;
3245 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003246 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003247 uint32_t err;
3248 const uint32_t _par_WDQLVL_RETRY_THRES = 0x7c0;
3249
3250 int32_t min_win;
3251 int32_t win;
3252 int8_t _adj;
3253 int16_t adj;
3254 uint32_t dq;
3255
Marek Vasut6a131772019-08-07 19:56:09 +02003256 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003257 err = 0;
3258 for (slice = 0; slice < SLICE_CNT; slice += 1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003259 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003260 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3261 continue;
3262
3263 cs = ddr_csn % 2;
3264 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003265 for (i = 0; i < 9; i++) {
3266 dq = slice * 8 + i;
3267 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003268 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003269 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003270 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003271 adj = _f_scale_adj(_adj);
3272
Marek Vasut38dc7562019-08-07 19:17:42 +02003273 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003274 ddr_getval_s(ch, slice,
3275 _reg_PHY_CLK_WRX_SLAVE_DELAY[i]) + adj;
3276 ddr_setval_s(ch, slice, _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003277 data_l);
3278 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003279 }
3280 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, 0x00);
Marek Vasut38dc7562019-08-07 19:17:42 +02003281 data_l = ddr_getval_s(ch, slice, _reg_PHY_WDQLVL_STATUS_OBS);
3282 wdqdm_st[ch][cs][slice] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003283 min_win = INT_LEAST32_MAX;
3284 for (i = 0; i <= 8; i++) {
3285 ddr_setval_s(ch, slice, _reg_PHY_WDQLVL_DQDM_OBS_SELECT,
3286 i);
3287
Marek Vasut38dc7562019-08-07 19:17:42 +02003288 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003289 ddr_getval_s(ch, slice,
3290 _reg_PHY_WDQLVL_DQDM_TE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003291 wdqdm_te[ch][cs][slice][i] = data_l;
3292 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003293 ddr_getval_s(ch, slice,
3294 _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003295 wdqdm_le[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003296 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003297 (int32_t)wdqdm_te[ch][cs][slice][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003298 wdqdm_le[ch][cs][slice][i];
3299 if (min_win > win)
3300 min_win = win;
Marek Vasut38dc7562019-08-07 19:17:42 +02003301 if (data_l >= _par_WDQLVL_RETRY_THRES)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003302 err = 2;
3303 }
3304 wdqdm_win[ch][cs][slice] = min_win;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003305 if ((prr_product == PRR_PRODUCT_H3) &&
3306 (prr_cut <= PRR_PRODUCT_11)) {
3307 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3308 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003309 } else {
3310 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3311 ((ch_have_this_cs[1]) >> ch) & 0x01);
3312 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003313 }
3314 return err;
3315}
Marek Vasut6c245a52018-12-12 18:06:39 +01003316#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003317
3318static void wdqdm_cp(uint32_t ddr_csn, uint32_t restore)
3319{
3320 uint32_t i;
3321 uint32_t ch, slice;
3322 uint32_t tgt_cs, src_cs;
3323 uint32_t tmp_r;
3324
Marek Vasut6a131772019-08-07 19:56:09 +02003325 /* copy of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003326 foreach_vch(ch) {
3327 for (tgt_cs = 0; tgt_cs < CS_CNT; tgt_cs++) {
3328 for (slice = 0; slice < SLICE_CNT; slice++) {
3329 ddr_setval_s(ch, slice,
3330 _reg_PHY_PER_CS_TRAINING_INDEX,
3331 tgt_cs);
3332 src_cs = ddr_csn % 2;
3333 if (!(ch_have_this_cs[1] & (1U << ch)))
3334 src_cs = 0;
3335 for (i = 0; i <= 4; i += 4) {
3336 if (restore)
3337 tmp_r =
3338 rdqdm_dly[ch][tgt_cs][slice]
3339 [i];
3340 else
3341 tmp_r =
3342 rdqdm_dly[ch][src_cs][slice]
3343 [i];
3344
3345 ddr_setval_s(ch, slice,
3346 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
3347 [i], tmp_r);
3348 }
3349 }
3350 }
3351 }
3352}
3353
3354static uint32_t wdqdm_man1(void)
3355{
3356 int32_t k;
3357 uint32_t ch, cs, slice;
3358 uint32_t ddr_csn;
Marek Vasut38dc7562019-08-07 19:17:42 +02003359 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003360 uint32_t err;
Marek Vasut6c245a52018-12-12 18:06:39 +01003361 uint32_t high_dq[DRAM_CH_CNT];
3362 uint32_t mr14_csab0_bak[DRAM_CH_CNT];
3363#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003364 uint32_t err_flg;
Marek Vasut6c245a52018-12-12 18:06:39 +01003365#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003366
Marek Vasut6a131772019-08-07 19:56:09 +02003367 /* manual execution of training */
Marek Vasut38dc7562019-08-07 19:17:42 +02003368 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003369 foreach_vch(ch) {
3370 high_dq[ch] = 0;
3371 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003372 k = (board_cnf->ch[ch].dqs_swap >>
3373 (4 * slice)) & 0x0f;
Marek Vasut6c245a52018-12-12 18:06:39 +01003374 if (k >= 2)
3375 high_dq[ch] |= (1U << slice);
3376 }
3377 ddr_setval(ch, _reg_PI_16BIT_DRAM_CONNECT, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003378 }
3379 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003380 err = 0;
3381 /* CLEAR PREV RESULT */
3382 for (cs = 0; cs < CS_CNT; cs++) {
3383 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_INDEX, cs);
Marek Vasut6a131772019-08-07 19:56:09 +02003384 if (((prr_product == PRR_PRODUCT_H3) &&
3385 (prr_cut > PRR_PRODUCT_11)) ||
3386 (prr_product == PRR_PRODUCT_M3N) ||
3387 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003388 ddr_setval_ach_as(_reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS,
3389 0x01);
3390 } else {
3391 ddr_setval_ach_as(_reg_PHY_WDQLVL_CLR_PREV_RESULTS,
3392 0x01);
3393 }
3394 }
3395 ddrphy_regif_idle();
3396
Marek Vasut6c245a52018-12-12 18:06:39 +01003397#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003398 err_flg = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01003399#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003400 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Marek Vasut6a131772019-08-07 19:56:09 +02003401 if ((prr_product == PRR_PRODUCT_H3) &&
3402 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003403 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003404 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3405 data_l &= ~(0x00ffU << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003406
3407 if (ddr_csn >= 2)
3408 k = (high_dq[ch] ^ 0x0f);
3409 else
3410 k = high_dq[ch];
Marek Vasut38dc7562019-08-07 19:17:42 +02003411 data_l |= (k << 16);
3412 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003413 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, k);
3414 }
3415 }
Marek Vasut6a131772019-08-07 19:56:09 +02003416 if (((prr_product == PRR_PRODUCT_H3) &&
3417 (prr_cut <= PRR_PRODUCT_11)) ||
3418 ((prr_product == PRR_PRODUCT_M3) &&
3419 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003420 wdqdm_cp(ddr_csn, 0);
3421 }
3422
3423 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003424 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003425 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003426 reg_pi_mr14_data_fx_csx[1][ddr_csn]);
3427 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003428 }
3429
3430 /* KICK WDQLVL */
3431 err = swlvl1(ddr_csn, _reg_PI_WDQLVL_CS, _reg_PI_WDQLVL_REQ);
3432 if (err)
3433 goto err_exit;
3434
3435 if (ddr_csn == 0)
3436 foreach_vch(ch) {
3437 mr14_csab0_bak[ch] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003438 ddr_getval(ch, reg_pi_mr14_data_fx_csx[1][0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003439 } else
3440 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003441 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0],
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003442 mr14_csab0_bak[ch]);
3443 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003444#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003445 foreach_vch(ch) {
3446 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3447 wdqdm_clr1(ch, ddr_csn);
3448 continue;
3449 }
3450 err = wdqdm_ana1(ch, ddr_csn);
3451 if (err)
3452 err_flg |= (1U << (ddr_csn * 4 + ch));
3453 ddrphy_regif_idle();
3454 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003455#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003456 }
3457err_exit:
Marek Vasut6c245a52018-12-12 18:06:39 +01003458#ifndef DDR_FAST_INIT
3459 err |= err_flg;
3460#endif/* DDR_FAST_INIT */
Marek Vasut38dc7562019-08-07 19:17:42 +02003461 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003462 ddr_setval_ach(_reg_PI_16BIT_DRAM_CONNECT, 0x01);
3463 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003464 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3465 data_l &= ~(0x00ffU << 16);
3466 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01003467 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, 0x00);
3468 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003469 }
Marek Vasut6a131772019-08-07 19:56:09 +02003470 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003471}
3472
3473static uint32_t wdqdm_man(void)
3474{
3475 uint32_t err, retry_cnt;
3476 const uint32_t retry_max = 0x10;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003477 uint32_t ch, ddr_csn, mr14_bkup[4][4];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003478
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003479 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW,
3480 (mmio_read_32(DBSC_DBTR(11)) & 0xFF) + 19);
Marek Vasut6a131772019-08-07 19:56:09 +02003481 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3482 (prr_product == PRR_PRODUCT_M3N) ||
3483 (prr_product == PRR_PRODUCT_V3H)) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003484 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F0,
3485 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003486 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F1,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003487 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003488 } else {
3489 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR,
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 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003492 ddr_setval_ach(_reg_PI_TRFC_F0, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
3493 ddr_setval_ach(_reg_PI_TRFC_F1, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003494
3495 retry_cnt = 0;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003496 err = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003497 do {
Marek Vasut6a131772019-08-07 19:56:09 +02003498 if ((prr_product == PRR_PRODUCT_H3) &&
3499 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003500 err = wdqdm_man1();
3501 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003502 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x01);
3503 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3504 0x01);
Marek Vasut6a131772019-08-07 19:56:09 +02003505 if ((prr_product == PRR_PRODUCT_M3N) ||
3506 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003507 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3508 0x0C);
3509 } else {
3510 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x0C);
3511 }
3512 dsb_sev();
3513 err = wdqdm_man1();
3514 foreach_vch(ch) {
3515 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3516 mr14_bkup[ch][ddr_csn] =
3517 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003518 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003519 [1][ddr_csn]);
3520 dsb_sev();
3521 }
3522 }
3523
Marek Vasut6a131772019-08-07 19:56:09 +02003524 if ((prr_product == PRR_PRODUCT_M3N) ||
3525 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003526 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3527 0x04);
3528 } else {
3529 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x04);
3530 }
3531 pvtcode_update();
3532 err = wdqdm_man1();
3533 foreach_vch(ch) {
3534 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3535 mr14_bkup[ch][ddr_csn] =
3536 (mr14_bkup[ch][ddr_csn] +
3537 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003538 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003539 [1][ddr_csn])) / 2;
3540 ddr_setval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003541 reg_pi_mr14_data_fx_csx[1]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003542 [ddr_csn],
3543 mr14_bkup[ch][ddr_csn]);
3544 }
3545 }
3546
3547 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3548 0x00);
Marek Vasut6a131772019-08-07 19:56:09 +02003549 if ((prr_product == PRR_PRODUCT_M3N) ||
3550 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003551 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3552 0x00);
3553 ddr_setval_ach
3554 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1,
3555 0x00);
3556 ddr_setval_ach
3557 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1,
3558 0x00);
3559 } else {
3560 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x00);
3561 ddr_setval_ach
3562 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT,
3563 0x00);
3564 ddr_setval_ach
3565 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT,
3566 0x00);
3567 }
3568 ddr_setval_ach(_reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE,
3569 0x00);
3570
3571 pvtcode_update2();
3572 err = wdqdm_man1();
3573 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
3574 }
3575 } while (err && (++retry_cnt < retry_max));
3576
Marek Vasut6a131772019-08-07 19:56:09 +02003577 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
3578 ((prr_product == PRR_PRODUCT_M3) && (prr_cut <= PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003579 wdqdm_cp(0, 1);
3580 }
3581
3582 return (retry_cnt >= retry_max);
3583}
3584
Marek Vasut6a131772019-08-07 19:56:09 +02003585/* RDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003586#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003587static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3588{
3589 int32_t i, k;
3590 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003591 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003592
Marek Vasut6a131772019-08-07 19:56:09 +02003593 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003594 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003595 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003596 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003597 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003598 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3599 continue;
3600
3601 for (i = 0; i <= 8; i++) {
3602 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) {
3603 rdqdm_dly[ch][cs][slice][i] =
3604 rdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3605 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3606 rdqdm_dly[ch][CS_CNT - 1 - cs][slice +
3607 SLICE_CNT]
3608 [i];
3609 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02003610 rdqdm_dly[ch][cs][slice][i] = data_l;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003611 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3612 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003613 }
3614 rdqdm_le[ch][cs][slice][i] = 0;
3615 rdqdm_le[ch][cs][slice + SLICE_CNT][i] = 0;
3616 rdqdm_te[ch][cs][slice][i] = 0;
3617 rdqdm_te[ch][cs][slice + SLICE_CNT][i] = 0;
3618 rdqdm_nw[ch][cs][slice][i] = 0;
3619 rdqdm_nw[ch][cs][slice + SLICE_CNT][i] = 0;
3620 }
3621 rdqdm_st[ch][cs][slice] = 0;
3622 rdqdm_win[ch][cs][slice] = 0;
3623 }
3624}
3625
3626static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3627{
3628 int32_t i, k;
3629 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003630 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003631 uint32_t err;
3632 int8_t _adj;
3633 int16_t adj;
3634 uint32_t dq;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003635 int32_t min_win;
3636 int32_t win;
3637 uint32_t rdq_status_obs_select;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003638
Marek Vasut6a131772019-08-07 19:56:09 +02003639 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003640 err = 0;
3641 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003642 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003643 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3644 continue;
3645
3646 cs = ddr_csn % 2;
3647 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
3648 ddrphy_regif_idle();
3649
3650 ddr_getval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX);
3651 ddrphy_regif_idle();
3652
3653 for (i = 0; i <= 8; i++) {
3654 dq = slice * 8 + i;
3655 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003656 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003657 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003658 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003659
3660 adj = _f_scale_adj(_adj);
3661
Marek Vasut38dc7562019-08-07 19:17:42 +02003662 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003663 ddr_getval_s(ch, slice,
3664 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) +
3665 adj;
3666 ddr_setval_s(ch, slice,
3667 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003668 data_l);
3669 rdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003670
Marek Vasut38dc7562019-08-07 19:17:42 +02003671 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003672 ddr_getval_s(ch, slice,
3673 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) +
3674 adj;
3675 ddr_setval_s(ch, slice,
3676 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003677 data_l);
3678 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003679 }
3680 min_win = INT_LEAST32_MAX;
3681 for (i = 0; i <= 8; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003682 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003683 ddr_getval_s(ch, slice, _reg_PHY_RDLVL_STATUS_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003684 rdqdm_st[ch][cs][slice] = data_l;
3685 rdqdm_st[ch][cs][slice + SLICE_CNT] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003686 /* k : rise/fall */
3687 for (k = 0; k < 2; k++) {
3688 if (i == 8) {
3689 rdq_status_obs_select = 16 + 8 * k;
3690 } else {
3691 rdq_status_obs_select = i + k * 8;
3692 }
3693 ddr_setval_s(ch, slice,
3694 _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT,
3695 rdq_status_obs_select);
3696
Marek Vasut38dc7562019-08-07 19:17:42 +02003697 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003698 ddr_getval_s(ch, slice,
3699 _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS);
3700 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003701 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003702
Marek Vasut38dc7562019-08-07 19:17:42 +02003703 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003704 ddr_getval_s(ch, slice,
3705 _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS);
3706 rdqdm_te[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003707 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003708
Marek Vasut38dc7562019-08-07 19:17:42 +02003709 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003710 ddr_getval_s(ch, slice,
3711 _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS);
3712 rdqdm_nw[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003713 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003714
3715 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003716 (int32_t)rdqdm_te[ch][cs][slice +
Marek Vasut6ad74c32019-08-08 16:34:22 +02003717 SLICE_CNT *
3718 k][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003719 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i];
3720 if (i != 8) {
3721 if (min_win > win)
3722 min_win = win;
3723 }
3724 }
3725 }
3726 rdqdm_win[ch][cs][slice] = min_win;
3727 if (min_win <= 0) {
3728 err = 2;
3729 }
3730 }
Marek Vasut6a131772019-08-07 19:56:09 +02003731 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003732}
Marek Vasut6c245a52018-12-12 18:06:39 +01003733#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003734
3735static uint32_t rdqdm_man1(void)
3736{
3737 uint32_t ch;
3738 uint32_t ddr_csn;
Marek Vasut6c245a52018-12-12 18:06:39 +01003739#ifdef DDR_FAST_INIT
3740 uint32_t slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003741 uint32_t i, adj, data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003742#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003743 uint32_t err;
3744
Marek Vasut6a131772019-08-07 19:56:09 +02003745 /* manual execution of training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003746 err = 0;
3747
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003748 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003749 /* KICK RDQLVL */
3750 err = swlvl1(ddr_csn, _reg_PI_RDLVL_CS, _reg_PI_RDLVL_REQ);
3751 if (err)
3752 goto err_exit;
Marek Vasut6c245a52018-12-12 18:06:39 +01003753#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003754 foreach_vch(ch) {
3755 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3756 rdqdm_clr1(ch, ddr_csn);
3757 ddrphy_regif_idle();
3758 continue;
3759 }
3760 err = rdqdm_ana1(ch, ddr_csn);
3761 ddrphy_regif_idle();
3762 if (err)
3763 goto err_exit;
3764 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003765#else/* DDR_FAST_INIT */
3766 foreach_vch(ch) {
3767 if (ch_have_this_cs[ddr_csn] & (1U << ch)) {
3768 for (slice = 0; slice < SLICE_CNT; slice++) {
3769 if (ddr_getval_s(ch, slice,
Marek Vasut80784f92019-08-07 19:02:26 +02003770 _reg_PHY_RDLVL_STATUS_OBS) !=
Marek Vasut6c245a52018-12-12 18:06:39 +01003771 0x0D00FFFF) {
3772 err = (1U << ch) |
3773 (0x10U << slice);
3774 goto err_exit;
3775 }
3776 }
3777 }
Marek Vasut6a131772019-08-07 19:56:09 +02003778 if (((prr_product == PRR_PRODUCT_H3) &&
3779 (prr_cut <= PRR_PRODUCT_11)) ||
3780 ((prr_product == PRR_PRODUCT_M3) &&
3781 (prr_cut <= PRR_PRODUCT_10))) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003782 for (slice = 0; slice < SLICE_CNT; slice++) {
3783 for (i = 0; i <= 8; i++) {
3784 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003785 adj = _f_scale_adj(board_cnf->ch[ch].dm_adj_r[slice]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003786 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003787 adj = _f_scale_adj(board_cnf->ch[ch].dq_adj_r[slice * 8 + i]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003788 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, ddr_csn);
Marek Vasut38dc7562019-08-07 19:17:42 +02003789 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + adj;
3790 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], data_l);
3791 rdqdm_dly[ch][ddr_csn][slice][i] = data_l;
3792 rdqdm_dly[ch][ddr_csn | 1][slice][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003793
Marek Vasut38dc7562019-08-07 19:17:42 +02003794 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + adj;
3795 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], data_l);
3796 rdqdm_dly[ch][ddr_csn][slice + SLICE_CNT][i] = data_l;
3797 rdqdm_dly[ch][ddr_csn | 1][slice + SLICE_CNT][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003798 }
3799 }
3800 }
3801 }
3802 ddrphy_regif_idle();
3803
3804#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003805 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003806
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003807err_exit:
Marek Vasut6a131772019-08-07 19:56:09 +02003808 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003809}
3810
3811static uint32_t rdqdm_man(void)
3812{
3813 uint32_t err, retry_cnt;
3814 const uint32_t retry_max = 0x01;
3815
3816 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3817 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3818 _reg_PHY_DQ_TSEL_ENABLE));
3819 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3820 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3821 _reg_PHY_DQS_TSEL_ENABLE));
3822 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3823 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3824 _reg_PHY_DQ_TSEL_SELECT));
3825 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3826 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3827 _reg_PHY_DQS_TSEL_SELECT));
3828
3829 retry_cnt = 0;
3830 do {
3831 err = rdqdm_man1();
3832 ddrphy_regif_idle();
3833 } while (err && (++retry_cnt < retry_max));
3834 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3835 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3836 _reg_PHY_DQ_TSEL_ENABLE));
3837 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3838 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3839 _reg_PHY_DQS_TSEL_ENABLE));
3840 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3841 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3842 _reg_PHY_DQ_TSEL_SELECT));
3843 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3844 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3845 _reg_PHY_DQS_TSEL_SELECT));
3846
3847 return (retry_cnt >= retry_max);
3848}
3849
Marek Vasut6a131772019-08-07 19:56:09 +02003850/* rx offset calibration */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003851static int32_t _find_change(uint64_t val, uint32_t dir)
3852{
3853 int32_t i;
3854 uint32_t startval;
3855 uint32_t curval;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003856 const int32_t VAL_END = 0x3f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003857
3858 if (dir == 0) {
3859 startval = (val & 0x01);
3860 for (i = 1; i <= VAL_END; i++) {
3861 curval = (val >> i) & 0x01;
3862 if (curval != startval)
Marek Vasut6a131772019-08-07 19:56:09 +02003863 return i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003864 }
Marek Vasut6a131772019-08-07 19:56:09 +02003865 return VAL_END;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003866 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003867
3868 startval = (val >> dir) & 0x01;
3869 for (i = dir - 1; i >= 0; i--) {
3870 curval = (val >> i) & 0x01;
3871 if (curval != startval)
3872 return i;
3873 }
3874 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003875}
3876
3877static uint32_t _rx_offset_cal_updn(uint32_t code)
3878{
3879 const uint32_t CODE_MAX = 0x40;
3880 uint32_t tmp;
3881
Marek Vasut38dc7562019-08-07 19:17:42 +02003882 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003883 if (code == 0)
3884 tmp = (1U << 6) | (CODE_MAX - 1);
3885 else if (code <= 0x20)
3886 tmp =
3887 ((CODE_MAX - 1 -
3888 (0x20 - code) * 2) << 6) | (CODE_MAX - 1);
3889 else
3890 tmp =
3891 ((CODE_MAX - 1) << 6) | (CODE_MAX - 1 -
3892 (code - 0x20) * 2);
3893 } else {
3894 if (code == 0)
3895 tmp = (1U << 6) | (CODE_MAX - 1);
3896 else
3897 tmp = (code << 6) | (CODE_MAX - code);
3898 }
3899 return tmp;
3900}
3901
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003902static uint32_t rx_offset_cal(void)
3903{
3904 uint32_t index;
3905 uint32_t code;
3906 const uint32_t CODE_MAX = 0x40;
3907 const uint32_t CODE_STEP = 2;
3908 uint32_t ch, slice;
3909 uint32_t tmp;
3910 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
3911 uint64_t val[DRAM_CH_CNT][SLICE_CNT][_reg_PHY_RX_CAL_X_NUM];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003912 uint64_t tmpval;
3913 int32_t lsb, msb;
Marek Vasut6c245a52018-12-12 18:06:39 +01003914
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003915 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x01);
3916 foreach_vch(ch) {
3917 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003918 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003919 val[ch][slice][index] = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003920 }
3921 }
3922
3923 for (code = 0; code < CODE_MAX / CODE_STEP; code++) {
3924 tmp = _rx_offset_cal_updn(code * CODE_STEP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003925 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) {
3926 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[index], tmp);
3927 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003928 dsb_sev();
Marek Vasut80784f92019-08-07 19:02:26 +02003929 ddr_getval_ach_as(_reg_PHY_RX_CAL_OBS, (uint32_t *)tmp_ach_as);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003930
3931 foreach_vch(ch) {
3932 for (slice = 0; slice < SLICE_CNT; slice++) {
3933 tmp = tmp_ach_as[ch][slice];
3934 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3935 index++) {
3936 if (tmp & (1U << index)) {
3937 val[ch][slice][index] |=
3938 (1ULL << code);
3939 } else {
3940 val[ch][slice][index] &=
3941 ~(1ULL << code);
3942 }
3943 }
3944 }
3945 }
3946 }
3947 foreach_vch(ch) {
3948 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003949 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3950 index++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003951 tmpval = val[ch][slice][index];
3952 lsb = _find_change(tmpval, 0);
3953 msb =
3954 _find_change(tmpval,
3955 (CODE_MAX / CODE_STEP) - 1);
3956 tmp = (lsb + msb) >> 1;
3957
3958 tmp = _rx_offset_cal_updn(tmp * CODE_STEP);
3959 ddr_setval_s(ch, slice,
3960 _reg_PHY_RX_CAL_X[index], tmp);
3961 }
3962 }
3963 }
3964 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003965
3966 return 0;
3967}
3968
3969static uint32_t rx_offset_cal_hw(void)
3970{
3971 uint32_t ch, slice;
3972 uint32_t retry;
3973 uint32_t complete;
3974 uint32_t tmp;
3975 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
3976
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003977 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[9], 0x00);
3978 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
3979 ddr_setval_ach_as(_reg_PHY_RX_CAL_SAMPLE_WAIT, 0x0f);
3980
3981 retry = 0;
3982 while (retry < 4096) {
3983 if ((retry & 0xff) == 0) {
3984 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
3985 }
3986 foreach_vch(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02003987 for (slice = 0; slice < SLICE_CNT; slice++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003988 tmp_ach_as[ch][slice] =
3989 ddr_getval_s(ch, slice, _reg_PHY_RX_CAL_X[9]);
3990
3991 complete = 1;
3992 foreach_vch(ch) {
3993 for (slice = 0; slice < SLICE_CNT; slice++) {
3994 tmp = tmp_ach_as[ch][slice];
3995 tmp = (tmp & 0x3f) + ((tmp >> 6) & 0x3f);
Marek Vasut6a131772019-08-07 19:56:09 +02003996 if (((prr_product == PRR_PRODUCT_H3) &&
3997 (prr_cut > PRR_PRODUCT_11)) ||
3998 (prr_product == PRR_PRODUCT_M3N) ||
3999 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004000 if (tmp != 0x3E)
4001 complete = 0;
4002 } else {
4003 if (tmp != 0x40)
4004 complete = 0;
4005 }
4006 }
4007 }
4008 if (complete)
4009 break;
4010
4011 retry++;
4012 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004013
4014 return (complete == 0);
4015}
4016
Marek Vasut6a131772019-08-07 19:56:09 +02004017/* adjust rddqs latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004018static void adjust_rddqs_latency(void)
4019{
4020 uint32_t ch, slice;
4021 uint32_t dly;
4022 uint32_t maxlatx2;
4023 uint32_t tmp;
4024 uint32_t rdlat_adjx2[SLICE_CNT];
Marek Vasut80784f92019-08-07 19:02:26 +02004025
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004026 foreach_vch(ch) {
4027 maxlatx2 = 0;
4028 for (slice = 0; slice < SLICE_CNT; slice++) {
4029 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX,
4030 0x00);
4031
4032 dly =
4033 ddr_getval_s(ch, slice,
4034 _reg_PHY_RDDQS_GATE_SLAVE_DELAY);
4035 tmp =
4036 ddr_getval_s(ch, slice,
4037 _reg_PHY_RDDQS_LATENCY_ADJUST);
4038 /* note gate_slave_delay[9] is always 0 */
4039 tmp = (tmp << 1) + (dly >> 8);
4040 rdlat_adjx2[slice] = tmp;
4041 if (maxlatx2 < tmp)
4042 maxlatx2 = tmp;
4043 }
4044 maxlatx2 = ((maxlatx2 + 1) >> 1) << 1;
4045 for (slice = 0; slice < SLICE_CNT; slice++) {
4046 tmp = maxlatx2 - rdlat_adjx2[slice];
4047 tmp = (tmp >> 1);
4048 if (tmp) {
4049 ddr_setval_s(ch, slice, _reg_PHY_RPTR_UPDATE,
4050 ddr_getval_s(ch, slice,
4051 _reg_PHY_RPTR_UPDATE)
4052 + 1);
4053 }
4054 }
4055 }
4056}
4057
Marek Vasut6a131772019-08-07 19:56:09 +02004058/* adjust wpath latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004059static void adjust_wpath_latency(void)
4060{
4061 uint32_t ch, cs, slice;
4062 uint32_t dly;
4063 uint32_t wpath_add;
4064 const uint32_t _par_EARLY_THRESHOLD_VAL = 0x180;
4065
4066 foreach_vch(ch) {
4067 for (slice = 0; slice < SLICE_CNT; slice += 1) {
4068 for (cs = 0; cs < CS_CNT; cs++) {
4069 ddr_setval_s(ch, slice,
4070 _reg_PHY_PER_CS_TRAINING_INDEX,
4071 cs);
4072 ddr_getval_s(ch, slice,
4073 _reg_PHY_PER_CS_TRAINING_INDEX);
4074 dly =
4075 ddr_getval_s(ch, slice,
4076 _reg_PHY_CLK_WRDQS_SLAVE_DELAY);
4077 if (dly <= _par_EARLY_THRESHOLD_VAL)
4078 continue;
4079
4080 wpath_add =
4081 ddr_getval_s(ch, slice,
4082 _reg_PHY_WRITE_PATH_LAT_ADD);
4083 ddr_setval_s(ch, slice,
4084 _reg_PHY_WRITE_PATH_LAT_ADD,
4085 wpath_add - 1);
4086 }
4087 }
4088 }
4089}
4090
Marek Vasut6a131772019-08-07 19:56:09 +02004091/* DDR Initialize entry */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004092int32_t rcar_dram_init(void)
4093{
4094 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02004095 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004096 uint32_t bus_mbps, bus_mbpsdiv;
4097 uint32_t tmp_tccd;
4098 uint32_t failcount;
Marek Vasut38dc7562019-08-07 19:17:42 +02004099 uint32_t cnf_boardtype;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004100
Marek Vasut6a131772019-08-07 19:56:09 +02004101 /* Thermal sensor setting */
Marek Vasut38dc7562019-08-07 19:17:42 +02004102 data_l = mmio_read_32(CPG_MSTPSR5);
4103 if (data_l & BIT(22)) { /* case THS/TSC Standby */
Marek Vasut6a131772019-08-07 19:56:09 +02004104 data_l &= ~BIT(22);
Marek Vasut38dc7562019-08-07 19:17:42 +02004105 cpg_write_32(CPG_SMSTPCR5, data_l);
Marek Vasut6a131772019-08-07 19:56:09 +02004106 while (mmio_read_32(CPG_MSTPSR5) & BIT(22))
4107 ; /* wait bit=0 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004108 }
4109
4110 /* THCTR Bit6: PONM=0 , Bit0: THSST=0 */
Marek Vasut38dc7562019-08-07 19:17:42 +02004111 data_l = mmio_read_32(THS1_THCTR) & 0xFFFFFFBE;
4112 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004113
Marek Vasut6a131772019-08-07 19:56:09 +02004114 /* Judge product and cut */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004115#ifdef RCAR_DDR_FIXED_LSI_TYPE
Marek Vasut80784f92019-08-07 19:02:26 +02004116#if (RCAR_LSI == RCAR_AUTO)
Marek Vasut38dc7562019-08-07 19:17:42 +02004117 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4118 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004119#else /* RCAR_LSI */
4120#ifndef RCAR_LSI_CUT
Marek Vasut38dc7562019-08-07 19:17:42 +02004121 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004122#endif /* RCAR_LSI_CUT */
4123#endif /* RCAR_LSI */
4124#else /* RCAR_DDR_FIXED_LSI_TYPE */
Marek Vasut38dc7562019-08-07 19:17:42 +02004125 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4126 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004127#endif /* RCAR_DDR_FIXED_LSI_TYPE */
4128
Marek Vasut38dc7562019-08-07 19:17:42 +02004129 if (prr_product == PRR_PRODUCT_H3) {
4130 if (prr_cut <= PRR_PRODUCT_11) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004131 p_ddr_regdef_tbl =
4132 (const uint32_t *)&DDR_REGDEF_TBL[0][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004133 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004134 p_ddr_regdef_tbl =
4135 (const uint32_t *)&DDR_REGDEF_TBL[2][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004136 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004137 } else if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004138 p_ddr_regdef_tbl =
4139 (const uint32_t *)&DDR_REGDEF_TBL[1][0];
Marek Vasut6a131772019-08-07 19:56:09 +02004140 } else if ((prr_product == PRR_PRODUCT_M3N) ||
4141 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004142 p_ddr_regdef_tbl =
4143 (const uint32_t *)&DDR_REGDEF_TBL[3][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004144 } else {
Marek Vasut6c245a52018-12-12 18:06:39 +01004145 FATAL_MSG("BL2: DDR:Unknown Product\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004146 return 0xff;
4147 }
4148
Marek Vasut6a131772019-08-07 19:56:09 +02004149 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4150 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004151 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4152 } else {
4153 mmio_write_32(DBSC_DBSYSCNT0, 0x00001234);
4154 }
4155
Marek Vasut6a131772019-08-07 19:56:09 +02004156 /* Judge board type */
Marek Vasut38dc7562019-08-07 19:17:42 +02004157 cnf_boardtype = boardcnf_get_brd_type();
4158 if (cnf_boardtype >= BOARDNUM) {
Marek Vasut6c245a52018-12-12 18:06:39 +01004159 FATAL_MSG("BL2: DDR:Unknown Board\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004160 return 0xff;
4161 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004162 board_cnf = (const struct _boardcnf *)&boardcnfs[cnf_boardtype];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004163
4164/* RCAR_DRAM_SPLIT_2CH (2U) */
4165#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02004166 /* H3(Test for future H3-N): Swap ch2 and ch1 for 2ch-split */
Marek Vasut38dc7562019-08-07 19:17:42 +02004167 if ((prr_product == PRR_PRODUCT_H3) && (board_cnf->phyvalid == 0x05)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004168 mmio_write_32(DBSC_DBMEMSWAPCONF0, 0x00000006);
4169 ddr_phyvalid = 0x03;
4170 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004171 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004172 }
4173#else /* RCAR_DRAM_SPLIT_2CH */
Marek Vasut38dc7562019-08-07 19:17:42 +02004174 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004175#endif /* RCAR_DRAM_SPLIT_2CH */
4176
4177 max_density = 0;
4178
4179 for (cs = 0; cs < CS_CNT; cs++) {
4180 ch_have_this_cs[cs] = 0;
4181 }
4182
4183 foreach_ech(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02004184 for (cs = 0; cs < CS_CNT; cs++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004185 ddr_density[ch][cs] = 0xff;
4186
4187 foreach_vch(ch) {
4188 for (cs = 0; cs < CS_CNT; cs++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004189 data_l = board_cnf->ch[ch].ddr_density[cs];
4190 ddr_density[ch][cs] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004191
Marek Vasut38dc7562019-08-07 19:17:42 +02004192 if (data_l == 0xff)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004193 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02004194 if (data_l > max_density)
4195 max_density = data_l;
Marek Vasut6a131772019-08-07 19:56:09 +02004196 if ((cs == 1) && (prr_product == PRR_PRODUCT_H3) &&
4197 (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004198 continue;
4199 ch_have_this_cs[cs] |= (1U << ch);
4200 }
4201 }
4202
Marek Vasut6a131772019-08-07 19:56:09 +02004203 /* Judge board clock frequency (in MHz) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004204 boardcnf_get_brd_clk(cnf_boardtype, &brd_clk, &brd_clkdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004205 if ((brd_clk / brd_clkdiv) > 25) {
4206 brd_clkdiva = 1;
4207 } else {
4208 brd_clkdiva = 0;
4209 }
4210
Marek Vasut6a131772019-08-07 19:56:09 +02004211 /* Judge ddr operating frequency clock(in Mbps) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004212 boardcnf_get_ddr_mbps(cnf_boardtype, &ddr_mbps, &ddr_mbpsdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004213
4214 ddr0800_mul = CLK_DIV(800, 2, brd_clk, brd_clkdiv * (brd_clkdiva + 1));
4215
Marek Vasut80784f92019-08-07 19:02:26 +02004216 ddr_mul = CLK_DIV(ddr_mbps, ddr_mbpsdiv * 2, brd_clk,
4217 brd_clkdiv * (brd_clkdiva + 1));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004218
Marek Vasut6a131772019-08-07 19:56:09 +02004219 /* Adjust tccd */
Marek Vasut38dc7562019-08-07 19:17:42 +02004220 data_l = (0x00006000 & mmio_read_32(RST_MODEMR)) >> 13;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09004221 bus_mbps = 0;
4222 bus_mbpsdiv = 0;
Marek Vasut38dc7562019-08-07 19:17:42 +02004223 switch (data_l) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004224 case 0:
4225 bus_mbps = brd_clk * 0x60 * 2;
4226 bus_mbpsdiv = brd_clkdiv * 1;
4227 break;
4228 case 1:
4229 bus_mbps = brd_clk * 0x50 * 2;
4230 bus_mbpsdiv = brd_clkdiv * 1;
4231 break;
4232 case 2:
4233 bus_mbps = brd_clk * 0x40 * 2;
4234 bus_mbpsdiv = brd_clkdiv * 1;
4235 break;
4236 case 3:
4237 bus_mbps = brd_clk * 0x60 * 2;
4238 bus_mbpsdiv = brd_clkdiv * 2;
4239 break;
4240 default:
4241 bus_mbps = brd_clk * 0x60 * 2;
4242 bus_mbpsdiv = brd_clkdiv * 2;
4243 break;
4244 }
4245 tmp_tccd = CLK_DIV(ddr_mbps * 8, ddr_mbpsdiv, bus_mbps, bus_mbpsdiv);
4246 if (8 * ddr_mbps * bus_mbpsdiv != tmp_tccd * bus_mbps * ddr_mbpsdiv)
4247 tmp_tccd = tmp_tccd + 1;
4248
4249 if (tmp_tccd < 8)
4250 ddr_tccd = 8;
4251 else
4252 ddr_tccd = tmp_tccd;
4253
Marek Vasut6c245a52018-12-12 18:06:39 +01004254 NOTICE("BL2: DDR%d(%s)\n", ddr_mbps / ddr_mbpsdiv, RCAR_DDR_VERSION);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004255
4256 MSG_LF("Start\n");
4257
Marek Vasut6a131772019-08-07 19:56:09 +02004258 /* PLL Setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004259 pll3_control(1);
4260
Marek Vasut6a131772019-08-07 19:56:09 +02004261 /* initialize DDR */
Marek Vasut38dc7562019-08-07 19:17:42 +02004262 data_l = init_ddr();
4263 if (data_l == ddr_phyvalid) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004264 failcount = 0;
4265 } else {
4266 failcount = 1;
4267 }
4268
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004269 foreach_vch(ch)
4270 mmio_write_32(DBSC_DBPDLK(ch), 0x00000000);
Marek Vasut6a131772019-08-07 19:56:09 +02004271 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4272 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004273 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4274 } else {
4275 mmio_write_32(DBSC_DBSYSCNT0, 0x00000000);
4276 }
4277
4278 if (failcount == 0) {
4279 return INITDRAM_OK;
4280 } else {
4281 return INITDRAM_NG;
4282 }
4283}
4284
4285void pvtcode_update(void)
4286{
4287 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004288 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004289 uint32_t pvtp[4], pvtn[4], pvtp_init, pvtn_init;
4290 int32_t pvtp_tmp, pvtn_tmp;
4291
4292 foreach_vch(ch) {
4293 pvtn_init = (tcal.tcomp_cal[ch] & 0xFC0) >> 6;
4294 pvtp_init = (tcal.tcomp_cal[ch] & 0x03F) >> 0;
4295
4296 if (8912 * pvtp_init > 44230) {
4297 pvtp_tmp = (5000 + 8912 * pvtp_init - 44230) / 10000;
4298 } else {
4299 pvtp_tmp =
4300 -((-(5000 + 8912 * pvtp_init - 44230)) / 10000);
4301 }
4302 pvtn_tmp = (5000 + 5776 * pvtn_init + 30280) / 10000;
4303
4304 pvtn[ch] = pvtn_tmp + pvtn_init;
4305 pvtp[ch] = pvtp_tmp + pvtp_init;
4306
4307 if (pvtn[ch] > 63) {
4308 pvtn[ch] = 63;
4309 pvtp[ch] =
4310 (pvtp_tmp) * (63 - 6 * pvtn_tmp -
4311 pvtn_init) / (pvtn_tmp) +
4312 6 * pvtp_tmp + pvtp_init;
4313 }
Marek Vasut6a131772019-08-07 19:56:09 +02004314 if ((prr_product == PRR_PRODUCT_H3) &&
4315 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004316 data_l = pvtp[ch] | (pvtn[ch] << 6) |
4317 (tcal.tcomp_cal[ch] & 0xfffff000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004318 reg_ddrphy_write(ch,
4319 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004320 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004321 reg_ddrphy_write(ch,
4322 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004323 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004324 reg_ddrphy_write(ch,
4325 ddr_regdef_adr(_reg_PHY_PAD_DQS_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_ADDR_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_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004332 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004333 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004334 data_l = pvtp[ch] | (pvtn[ch] << 6) | 0x00015000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004335 reg_ddrphy_write(ch,
4336 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004337 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004338 reg_ddrphy_write(ch,
4339 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004340 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004341 reg_ddrphy_write(ch,
4342 ddr_regdef_adr(_reg_PHY_PAD_DQS_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_ADDR_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_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004349 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004350 }
4351 }
4352}
4353
4354void pvtcode_update2(void)
4355{
4356 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02004357
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004358 foreach_vch(ch) {
4359 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
4360 tcal.init_cal[ch] | 0x00020000);
4361 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
4362 tcal.init_cal[ch]);
4363 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
4364 tcal.init_cal[ch]);
4365 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
4366 tcal.init_cal[ch]);
4367 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
4368 tcal.init_cal[ch]);
4369 }
4370}
4371
4372void ddr_padcal_tcompensate_getinit(uint32_t override)
4373{
4374 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004375 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004376 uint32_t pvtp, pvtn;
4377
4378 tcal.init_temp = 0;
4379 for (ch = 0; ch < 4; ch++) {
4380 tcal.init_cal[ch] = 0;
4381 tcal.tcomp_cal[ch] = 0;
4382 }
4383
4384 foreach_vch(ch) {
4385 tcal.init_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4386 tcal.tcomp_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4387 }
4388
4389 if (!override) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004390 data_l = mmio_read_32(THS1_TEMP);
4391 if (data_l < 2800) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004392 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004393 (143 * (int32_t)data_l - 359000) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004394 } else {
4395 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004396 (121 * (int32_t)data_l - 296300) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004397 }
4398
4399 foreach_vch(ch) {
4400 pvtp = (tcal.init_cal[ch] >> 0) & 0x000003F;
4401 pvtn = (tcal.init_cal[ch] >> 6) & 0x000003F;
Marek Vasut80784f92019-08-07 19:02:26 +02004402 if ((int32_t)pvtp >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004403 ((tcal.init_temp * 29 - 3625) / 1000))
4404 pvtp =
Marek Vasut80784f92019-08-07 19:02:26 +02004405 (int32_t)pvtp +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004406 ((3625 - tcal.init_temp * 29) / 1000);
4407 else
4408 pvtp = 0;
4409
Marek Vasut80784f92019-08-07 19:02:26 +02004410 if ((int32_t)pvtn >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004411 ((tcal.init_temp * 54 - 6750) / 1000))
4412 pvtn =
Marek Vasut80784f92019-08-07 19:02:26 +02004413 (int32_t)pvtn +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004414 ((6750 - tcal.init_temp * 54) / 1000);
4415 else
4416 pvtn = 0;
4417
Marek Vasut6a131772019-08-07 19:56:09 +02004418 if ((prr_product == PRR_PRODUCT_H3) &&
4419 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004420 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004421 (tcal.init_cal[ch] & 0xfffff000) |
4422 (pvtn << 6) |
4423 pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004424 } else {
4425 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004426 0x00015000 | (pvtn << 6) | pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004427 }
4428 }
4429 tcal.init_temp = 125;
4430 }
4431}
4432
4433#ifndef ddr_qos_init_setting
Marek Vasut6ad74c32019-08-08 16:34:22 +02004434/* For QoS init */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004435uint8_t get_boardcnf_phyvalid(void)
4436{
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004437 return ddr_phyvalid;
4438}
4439#endif /* ddr_qos_init_setting */