blob: 3f6a9484de74cf62193883feb79f6029a1f1afb9 [file] [log] [blame]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001/*
Yoshifumi Hosoya39be8282022-07-22 13:04:36 +09002 * Copyright (c) 2015-2023, 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
Lad Prabhakar9f2b5792021-03-10 14:30:20 +000039#define RZ_G2M 100U
Lad Prabhakar9c86f412021-04-19 16:59:55 +010040#define RZ_G2H 101U
Lad Prabhakared2e11d2021-04-19 17:03:56 +010041#define RZ_G2N 102U
Lad Prabhakar9f2b5792021-03-10 14:30:20 +000042
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020043#define RCAR_CUT_10 0
44#define RCAR_CUT_11 1
45#define RCAR_CUT_20 10
46#define RCAR_CUT_30 20
47#endif
48#ifndef RCAR_LSI
49#define RCAR_LSI RCAR_AUTO
50#endif
Marek Vasut38dc7562019-08-07 19:17:42 +020051
Marek Vasut80784f92019-08-07 19:02:26 +020052#if (RCAR_LSI == RCAR_AUTO)
Marek Vasut38dc7562019-08-07 19:17:42 +020053static uint32_t prr_product;
54static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020055#else
Marek Vasut80784f92019-08-07 19:02:26 +020056#if (RCAR_LSI == RCAR_H3)
Marek Vasut38dc7562019-08-07 19:17:42 +020057static const uint32_t prr_product = PRR_PRODUCT_H3;
Lad Prabhakar9f2b5792021-03-10 14:30:20 +000058#elif(RCAR_LSI == RCAR_M3 || RCAR_LSI == RZ_G2M)
Marek Vasut38dc7562019-08-07 19:17:42 +020059static const uint32_t prr_product = PRR_PRODUCT_M3;
Lad Prabhakared2e11d2021-04-19 17:03:56 +010060#elif(RCAR_LSI == RCAR_M3N || RCAR_LSI == RZ_G2N)
Marek Vasut38dc7562019-08-07 19:17:42 +020061static const uint32_t prr_product = PRR_PRODUCT_M3N;
Lad Prabhakar9c86f412021-04-19 16:59:55 +010062#elif(RCAR_LSI == RCAR_H3N || RCAR_LSI == RZ_G2H)
Marek Vasut38dc7562019-08-07 19:17:42 +020063static const uint32_t prr_product = PRR_PRODUCT_H3;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020064#endif /* RCAR_LSI */
65
66#ifndef RCAR_LSI_CUT
Marek Vasut38dc7562019-08-07 19:17:42 +020067static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020068#else /* RCAR_LSI_CUT */
Marek Vasut80784f92019-08-07 19:02:26 +020069#if (RCAR_LSI_CUT == RCAR_CUT_10)
Marek Vasut38dc7562019-08-07 19:17:42 +020070static const uint32_t prr_cut = PRR_PRODUCT_10;
Marek Vasut80784f92019-08-07 19:02:26 +020071#elif(RCAR_LSI_CUT == RCAR_CUT_11)
Marek Vasut38dc7562019-08-07 19:17:42 +020072static const uint32_t prr_cut = PRR_PRODUCT_11;
Marek Vasut80784f92019-08-07 19:02:26 +020073#elif(RCAR_LSI_CUT == RCAR_CUT_20)
Marek Vasut38dc7562019-08-07 19:17:42 +020074static const uint32_t prr_cut = PRR_PRODUCT_20;
Marek Vasut80784f92019-08-07 19:02:26 +020075#elif(RCAR_LSI_CUT == RCAR_CUT_30)
Marek Vasut38dc7562019-08-07 19:17:42 +020076static const uint32_t prr_cut = PRR_PRODUCT_30;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020077#endif /* RCAR_LSI_CUT */
78#endif /* RCAR_LSI_CUT */
79#endif /* RCAR_AUTO_NON */
80#else /* RCAR_DDR_FIXED_LSI_TYPE */
Marek Vasut38dc7562019-08-07 19:17:42 +020081static uint32_t prr_product;
82static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020083#endif /* RCAR_DDR_FIXED_LSI_TYPE */
84
Marek Vasut38dc7562019-08-07 19:17:42 +020085static const uint32_t *p_ddr_regdef_tbl;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020086static uint32_t brd_clk;
87static uint32_t brd_clkdiv;
88static uint32_t brd_clkdiva;
89static uint32_t ddr_mbps;
90static uint32_t ddr_mbpsdiv;
91static uint32_t ddr_tccd;
Marek Vasut6c245a52018-12-12 18:06:39 +010092static uint32_t ddr_phycaslice;
Marek Vasut38dc7562019-08-07 19:17:42 +020093static const struct _boardcnf *board_cnf;
Chiaki Fujii59263ee2019-05-17 10:45:02 +090094static uint32_t ddr_phyvalid;
95static uint32_t ddr_density[DRAM_CH_CNT][CS_CNT];
Marek Vasut6a131772019-08-07 19:56:09 +020096static uint32_t ch_have_this_cs[CS_CNT] __aligned(64);
Chiaki Fujiifd1ec702019-07-08 23:44:56 +090097static uint32_t rdqdm_dly[DRAM_CH_CNT][CSAB_CNT][SLICE_CNT * 2][9];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020098static uint32_t max_density;
99static uint32_t ddr0800_mul;
100static uint32_t ddr_mul;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200101static uint32_t DDR_PHY_SLICE_REGSET_OFS;
102static uint32_t DDR_PHY_ADR_V_REGSET_OFS;
103static uint32_t DDR_PHY_ADR_I_REGSET_OFS;
104static uint32_t DDR_PHY_ADR_G_REGSET_OFS;
105static uint32_t DDR_PI_REGSET_OFS;
106static uint32_t DDR_PHY_SLICE_REGSET_SIZE;
107static uint32_t DDR_PHY_ADR_V_REGSET_SIZE;
108static uint32_t DDR_PHY_ADR_I_REGSET_SIZE;
109static uint32_t DDR_PHY_ADR_G_REGSET_SIZE;
110static uint32_t DDR_PI_REGSET_SIZE;
111static uint32_t DDR_PHY_SLICE_REGSET_NUM;
112static uint32_t DDR_PHY_ADR_V_REGSET_NUM;
113static uint32_t DDR_PHY_ADR_I_REGSET_NUM;
114static uint32_t DDR_PHY_ADR_G_REGSET_NUM;
115static uint32_t DDR_PI_REGSET_NUM;
116static uint32_t DDR_PHY_ADR_I_NUM;
117#define DDR_PHY_REGSET_MAX 128
118#define DDR_PI_REGSET_MAX 320
119static uint32_t _cnf_DDR_PHY_SLICE_REGSET[DDR_PHY_REGSET_MAX];
120static uint32_t _cnf_DDR_PHY_ADR_V_REGSET[DDR_PHY_REGSET_MAX];
121static uint32_t _cnf_DDR_PHY_ADR_I_REGSET[DDR_PHY_REGSET_MAX];
122static uint32_t _cnf_DDR_PHY_ADR_G_REGSET[DDR_PHY_REGSET_MAX];
123static uint32_t _cnf_DDR_PI_REGSET[DDR_PI_REGSET_MAX];
Marek Vasut38dc7562019-08-07 19:17:42 +0200124static uint32_t pll3_mode;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200125static uint32_t loop_max;
126#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +0200127uint32_t ddr_backup;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200128/* #define DDR_BACKUPMODE_HALF //for Half channel(ch0,1 only) */
129#endif
130
131#ifdef ddr_qos_init_setting /* only for non qos_init */
132#define OPERATING_FREQ (400U) /* Mhz */
133#define BASE_SUB_SLOT_NUM (0x6U)
134#define SUB_SLOT_CYCLE (0x7EU) /* 126 */
Marek Vasut6a131772019-08-07 19:56:09 +0200135#define QOSWT_WTSET0_CYCLE \
136 ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / \
137 OPERATING_FREQ) /* unit:ns */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200138
139uint32_t get_refperiod(void)
140{
141 return QOSWT_WTSET0_CYCLE;
142}
143#else /* ddr_qos_init_setting // only for non qos_init */
144extern uint32_t get_refperiod(void);
145#endif /* ddr_qos_init_setting // only for non qos_init */
146
147#define _reg_PHY_RX_CAL_X_NUM 11
148static const uint32_t _reg_PHY_RX_CAL_X[_reg_PHY_RX_CAL_X_NUM] = {
149 _reg_PHY_RX_CAL_DQ0,
150 _reg_PHY_RX_CAL_DQ1,
151 _reg_PHY_RX_CAL_DQ2,
152 _reg_PHY_RX_CAL_DQ3,
153 _reg_PHY_RX_CAL_DQ4,
154 _reg_PHY_RX_CAL_DQ5,
155 _reg_PHY_RX_CAL_DQ6,
156 _reg_PHY_RX_CAL_DQ7,
157 _reg_PHY_RX_CAL_DM,
158 _reg_PHY_RX_CAL_DQS,
159 _reg_PHY_RX_CAL_FDBK
160};
161
162#define _reg_PHY_CLK_WRX_SLAVE_DELAY_NUM 10
Marek Vasut6ad74c32019-08-08 16:34:22 +0200163static const uint32_t _reg_PHY_CLK_WRX_SLAVE_DELAY
164 [_reg_PHY_CLK_WRX_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200165 _reg_PHY_CLK_WRDQ0_SLAVE_DELAY,
166 _reg_PHY_CLK_WRDQ1_SLAVE_DELAY,
167 _reg_PHY_CLK_WRDQ2_SLAVE_DELAY,
168 _reg_PHY_CLK_WRDQ3_SLAVE_DELAY,
169 _reg_PHY_CLK_WRDQ4_SLAVE_DELAY,
170 _reg_PHY_CLK_WRDQ5_SLAVE_DELAY,
171 _reg_PHY_CLK_WRDQ6_SLAVE_DELAY,
172 _reg_PHY_CLK_WRDQ7_SLAVE_DELAY,
173 _reg_PHY_CLK_WRDM_SLAVE_DELAY,
174 _reg_PHY_CLK_WRDQS_SLAVE_DELAY
175};
176
177#define _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM 9
Marek Vasut6ad74c32019-08-08 16:34:22 +0200178static const uint32_t _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY
179 [_reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200180 _reg_PHY_RDDQS_DQ0_FALL_SLAVE_DELAY,
181 _reg_PHY_RDDQS_DQ1_FALL_SLAVE_DELAY,
182 _reg_PHY_RDDQS_DQ2_FALL_SLAVE_DELAY,
183 _reg_PHY_RDDQS_DQ3_FALL_SLAVE_DELAY,
184 _reg_PHY_RDDQS_DQ4_FALL_SLAVE_DELAY,
185 _reg_PHY_RDDQS_DQ5_FALL_SLAVE_DELAY,
186 _reg_PHY_RDDQS_DQ6_FALL_SLAVE_DELAY,
187 _reg_PHY_RDDQS_DQ7_FALL_SLAVE_DELAY,
188 _reg_PHY_RDDQS_DM_FALL_SLAVE_DELAY
189};
190
191#define _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM 9
Marek Vasut6ad74c32019-08-08 16:34:22 +0200192static const uint32_t _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
193 [_reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200194 _reg_PHY_RDDQS_DQ0_RISE_SLAVE_DELAY,
195 _reg_PHY_RDDQS_DQ1_RISE_SLAVE_DELAY,
196 _reg_PHY_RDDQS_DQ2_RISE_SLAVE_DELAY,
197 _reg_PHY_RDDQS_DQ3_RISE_SLAVE_DELAY,
198 _reg_PHY_RDDQS_DQ4_RISE_SLAVE_DELAY,
199 _reg_PHY_RDDQS_DQ5_RISE_SLAVE_DELAY,
200 _reg_PHY_RDDQS_DQ6_RISE_SLAVE_DELAY,
201 _reg_PHY_RDDQS_DQ7_RISE_SLAVE_DELAY,
202 _reg_PHY_RDDQS_DM_RISE_SLAVE_DELAY
203};
204
205#define _reg_PHY_PAD_TERM_X_NUM 8
206static const uint32_t _reg_PHY_PAD_TERM_X[_reg_PHY_PAD_TERM_X_NUM] = {
207 _reg_PHY_PAD_FDBK_TERM,
208 _reg_PHY_PAD_DATA_TERM,
209 _reg_PHY_PAD_DQS_TERM,
210 _reg_PHY_PAD_ADDR_TERM,
211 _reg_PHY_PAD_CLK_TERM,
212 _reg_PHY_PAD_CKE_TERM,
213 _reg_PHY_PAD_RST_TERM,
214 _reg_PHY_PAD_CS_TERM
215};
216
217#define _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM 10
Marek Vasut6ad74c32019-08-08 16:34:22 +0200218static const uint32_t _reg_PHY_CLK_CACS_SLAVE_DELAY_X
219 [_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200220 _reg_PHY_ADR0_CLK_WR_SLAVE_DELAY,
221 _reg_PHY_ADR1_CLK_WR_SLAVE_DELAY,
222 _reg_PHY_ADR2_CLK_WR_SLAVE_DELAY,
223 _reg_PHY_ADR3_CLK_WR_SLAVE_DELAY,
224 _reg_PHY_ADR4_CLK_WR_SLAVE_DELAY,
225 _reg_PHY_ADR5_CLK_WR_SLAVE_DELAY,
226
227 _reg_PHY_GRP_SLAVE_DELAY_0,
228 _reg_PHY_GRP_SLAVE_DELAY_1,
229 _reg_PHY_GRP_SLAVE_DELAY_2,
230 _reg_PHY_GRP_SLAVE_DELAY_3
231};
232
Marek Vasut6a131772019-08-07 19:56:09 +0200233/* Prototypes */
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900234static inline uint32_t vch_nxt(uint32_t pos);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200235static void cpg_write_32(uint32_t a, uint32_t v);
236static void pll3_control(uint32_t high);
237static inline void dsb_sev(void);
238static void wait_dbcmd(void);
239static void send_dbcmd(uint32_t cmd);
240static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd);
241static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata);
242static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata);
243static inline uint32_t ddr_regdef(uint32_t _regdef);
244static inline uint32_t ddr_regdef_adr(uint32_t _regdef);
245static inline uint32_t ddr_regdef_lsb(uint32_t _regdef);
246static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef,
247 uint32_t val);
248static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef);
249static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val);
250static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val);
251static void ddr_setval_ach(uint32_t regdef, uint32_t val);
252static void ddr_setval_ach_as(uint32_t regdef, uint32_t val);
253static uint32_t ddr_getval(uint32_t ch, uint32_t regdef);
Marek Vasut80784f92019-08-07 19:02:26 +0200254static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p);
255static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p);
256static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size);
257static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val);
258static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200259static uint32_t ddrphy_regif_chk(void);
Marek Vasut80784f92019-08-07 19:02:26 +0200260static inline void ddrphy_regif_idle(void);
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +0100261static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200262 uint16_t cyc);
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +0100263static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv,
264 uint16_t *_js2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200265static int16_t _f_scale_adj(int16_t ps);
266static void ddrtbl_load(void);
267static void ddr_config_sub(void);
Marek Vasut80784f92019-08-07 19:02:26 +0200268static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200269static void ddr_config_sub_h3v1x(void);
270static void ddr_config(void);
271static void dbsc_regset(void);
272static void dbsc_regset_post(void);
273static uint32_t dfi_init_start(void);
274static void change_lpddr4_en(uint32_t mode);
275static uint32_t set_term_code(void);
Marek Vasut6c245a52018-12-12 18:06:39 +0100276static void ddr_register_set(void);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200277static inline uint32_t wait_freqchgreq(uint32_t assert);
278static inline void set_freqchgack(uint32_t assert);
279static inline void set_dfifrequency(uint32_t freq);
280static uint32_t pll3_freq(uint32_t on);
281static void update_dly(void);
282static uint32_t pi_training_go(void);
283static uint32_t init_ddr(void);
284static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200285static uint32_t wdqdm_man1(void);
286static uint32_t wdqdm_man(void);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200287static uint32_t rdqdm_man1(void);
288static uint32_t rdqdm_man(void);
289
290static int32_t _find_change(uint64_t val, uint32_t dir);
291static uint32_t _rx_offset_cal_updn(uint32_t code);
292static uint32_t rx_offset_cal(void);
293static uint32_t rx_offset_cal_hw(void);
294static void adjust_rddqs_latency(void);
295static void adjust_wpath_latency(void);
296
Marek Vasut38dc7562019-08-07 19:17:42 +0200297struct ddrt_data {
Marek Vasut6a131772019-08-07 19:56:09 +0200298 int32_t init_temp; /* Initial Temperature (do) */
299 uint32_t init_cal[4]; /* Initial io-code (4 is for H3) */
300 uint32_t tcomp_cal[4]; /* Temp. compensated io-code (4 is for H3) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200301};
Marek Vasut80784f92019-08-07 19:02:26 +0200302
Marek Vasut38dc7562019-08-07 19:17:42 +0200303static struct ddrt_data tcal;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200304
305static void pvtcode_update(void);
306static void pvtcode_update2(void);
307static void ddr_padcal_tcompensate_getinit(uint32_t override);
308
Marek Vasut6a131772019-08-07 19:56:09 +0200309/* load board configuration */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200310#include "boot_init_dram_config.c"
311
Marek Vasut6c245a52018-12-12 18:06:39 +0100312#ifndef DDR_FAST_INIT
313static uint32_t rdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
314static uint32_t rdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
315static uint32_t rdqdm_nw[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
316static uint32_t rdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
317static uint32_t rdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2];
318static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn);
319static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn);
320
321static uint32_t wdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
322static uint32_t wdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
323static uint32_t wdqdm_dly[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
324static uint32_t wdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
325static uint32_t wdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
326static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn);
327static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn);
328#endif/* DDR_FAST_INIT */
329
Marek Vasut6a131772019-08-07 19:56:09 +0200330/* macro for channel selection loop */
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900331static inline uint32_t vch_nxt(uint32_t pos)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200332{
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900333 uint32_t posn;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200334
335 for (posn = pos; posn < DRAM_CH_CNT; posn++) {
336 if (ddr_phyvalid & (1U << posn))
337 break;
338 }
339 return posn;
340}
341
342#define foreach_vch(ch) \
Marek Vasut80784f92019-08-07 19:02:26 +0200343for (ch = vch_nxt(0); ch < DRAM_CH_CNT; ch = vch_nxt(ch + 1))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200344
345#define foreach_ech(ch) \
Marek Vasut80784f92019-08-07 19:02:26 +0200346for (ch = 0; ch < DRAM_CH_CNT; ch++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200347
Marek Vasut6a131772019-08-07 19:56:09 +0200348/* Printing functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200349#define MSG_LF(...)
350
Marek Vasut6a131772019-08-07 19:56:09 +0200351/* clock settings, reset control */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200352static void cpg_write_32(uint32_t a, uint32_t v)
353{
354 mmio_write_32(CPG_CPGWPR, ~v);
355 mmio_write_32(a, v);
356}
357
358static void pll3_control(uint32_t high)
359{
Marek Vasut38dc7562019-08-07 19:17:42 +0200360 uint32_t data_l, data_div, data_mul, tmp_div;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200361
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200362 if (high) {
Marek Vasut38dc7562019-08-07 19:17:42 +0200363 tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) /
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900364 (brd_clk * ddr_mul) / 2;
Chiaki Fujiifd1ec702019-07-08 23:44:56 +0900365 data_mul = ((ddr_mul * tmp_div) - 1) << 24;
Marek Vasut38dc7562019-08-07 19:17:42 +0200366 pll3_mode = 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200367 loop_max = 2;
368 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +0200369 tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) /
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900370 (brd_clk * ddr0800_mul) / 2;
Chiaki Fujiifd1ec702019-07-08 23:44:56 +0900371 data_mul = ((ddr0800_mul * tmp_div) - 1) << 24;
Marek Vasut38dc7562019-08-07 19:17:42 +0200372 pll3_mode = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200373 loop_max = 8;
374 }
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900375
Marek Vasut38dc7562019-08-07 19:17:42 +0200376 switch (tmp_div) {
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900377 case 1:
Marek Vasut38dc7562019-08-07 19:17:42 +0200378 data_div = 0;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900379 break;
380 case 2:
381 case 3:
382 case 4:
Marek Vasut38dc7562019-08-07 19:17:42 +0200383 data_div = tmp_div;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900384 break;
385 default:
Marek Vasut38dc7562019-08-07 19:17:42 +0200386 data_div = 6;
387 data_mul = (data_mul * tmp_div) / 3;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900388 break;
Marek Vasut6c245a52018-12-12 18:06:39 +0100389 }
Marek Vasut38dc7562019-08-07 19:17:42 +0200390 data_mul = data_mul | (brd_clkdiva << 7);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200391
Marek Vasut6c245a52018-12-12 18:06:39 +0100392 /* PLL3 disable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200393 data_l = mmio_read_32(CPG_PLLECR) & ~CPG_PLLECR_PLL3E_BIT;
394 cpg_write_32(CPG_PLLECR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200395 dsb_sev();
396
Marek Vasut38dc7562019-08-07 19:17:42 +0200397 if ((prr_product == PRR_PRODUCT_M3) ||
398 ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_20))) {
Marek Vasut6c245a52018-12-12 18:06:39 +0100399 /* PLL3 DIV resetting(Lowest value:3) */
Marek Vasut38dc7562019-08-07 19:17:42 +0200400 data_l = 0x00030003 | (0xFF80FF80 & mmio_read_32(CPG_FRQCRD));
401 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100402 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200403
Marek Vasut6c245a52018-12-12 18:06:39 +0100404 /* zb3 clk stop */
Marek Vasut38dc7562019-08-07 19:17:42 +0200405 data_l = CPG_ZB3CKCR_ZB3ST_BIT | mmio_read_32(CPG_ZB3CKCR);
406 cpg_write_32(CPG_ZB3CKCR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100407 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200408
Marek Vasut6c245a52018-12-12 18:06:39 +0100409 /* PLL3 enable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200410 data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR);
411 cpg_write_32(CPG_PLLECR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100412 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200413
Marek Vasut6c245a52018-12-12 18:06:39 +0100414 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200415 data_l = mmio_read_32(CPG_PLLECR);
416 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100417 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200418
Marek Vasut6c245a52018-12-12 18:06:39 +0100419 /* PLL3 DIV resetting (Highest value:0) */
Marek Vasut38dc7562019-08-07 19:17:42 +0200420 data_l = (0xFF80FF80 & mmio_read_32(CPG_FRQCRD));
421 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100422 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200423
Marek Vasut6c245a52018-12-12 18:06:39 +0100424 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200425 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
426 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100427 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200428
Marek Vasut6c245a52018-12-12 18:06:39 +0100429 /* PLL3 multiplie set */
Marek Vasut38dc7562019-08-07 19:17:42 +0200430 cpg_write_32(CPG_PLL3CR, data_mul);
Marek Vasut6c245a52018-12-12 18:06:39 +0100431 dsb_sev();
432
433 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200434 data_l = mmio_read_32(CPG_PLLECR);
435 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100436 dsb_sev();
437
438 /* PLL3 DIV resetting(Target value) */
Marek Vasut6a131772019-08-07 19:56:09 +0200439 data_l = (data_div << 16) | data_div |
440 (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80);
Marek Vasut38dc7562019-08-07 19:17:42 +0200441 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100442 dsb_sev();
443
444 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200445 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
446 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100447 dsb_sev();
448
449 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200450 data_l = mmio_read_32(CPG_PLLECR);
451 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100452 dsb_sev();
453
454 /* zb3 clk start */
Marek Vasut38dc7562019-08-07 19:17:42 +0200455 data_l = (~CPG_ZB3CKCR_ZB3ST_BIT) & mmio_read_32(CPG_ZB3CKCR);
456 cpg_write_32(CPG_ZB3CKCR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100457 dsb_sev();
458
459 } else { /* H3Ver.3.0/M3N/V3H */
460
461 /* PLL3 multiplie set */
Marek Vasut38dc7562019-08-07 19:17:42 +0200462 cpg_write_32(CPG_PLL3CR, data_mul);
Marek Vasut6c245a52018-12-12 18:06:39 +0100463 dsb_sev();
464
465 /* PLL3 DIV set(Target value) */
Marek Vasut6a131772019-08-07 19:56:09 +0200466 data_l = (data_div << 16) | data_div |
467 (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80);
Marek Vasut38dc7562019-08-07 19:17:42 +0200468 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100469
470 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200471 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
472 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100473 dsb_sev();
474
475 /* PLL3 enable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200476 data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR);
477 cpg_write_32(CPG_PLLECR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100478 dsb_sev();
479
480 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200481 data_l = mmio_read_32(CPG_PLLECR);
482 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100483 dsb_sev();
484 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200485}
486
Marek Vasut6a131772019-08-07 19:56:09 +0200487/* barrier */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200488static inline void dsb_sev(void)
489{
490 __asm__ __volatile__("dsb sy");
491}
492
Marek Vasut6a131772019-08-07 19:56:09 +0200493/* DDR memory register access */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200494static void wait_dbcmd(void)
495{
Marek Vasut38dc7562019-08-07 19:17:42 +0200496 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200497 /* dummy read */
Marek Vasut38dc7562019-08-07 19:17:42 +0200498 data_l = mmio_read_32(DBSC_DBCMD);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200499 dsb_sev();
500 while (1) {
501 /* wait DBCMD 1=busy, 0=ready */
Marek Vasut38dc7562019-08-07 19:17:42 +0200502 data_l = mmio_read_32(DBSC_DBWAIT);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200503 dsb_sev();
Marek Vasut38dc7562019-08-07 19:17:42 +0200504 if ((data_l & 0x00000001) == 0x00)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200505 break;
506 }
507}
508
509static void send_dbcmd(uint32_t cmd)
510{
511 /* dummy read */
512 wait_dbcmd();
513 mmio_write_32(DBSC_DBCMD, cmd);
514 dsb_sev();
515}
516
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900517static void dbwait_loop(uint32_t wait_loop)
518{
519 uint32_t i;
520
521 for (i = 0; i < wait_loop; i++)
522 wait_dbcmd();
523}
524
Marek Vasut6a131772019-08-07 19:56:09 +0200525/* DDRPHY register access (raw) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200526static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd)
527{
528 uint32_t val;
529 uint32_t loop;
530
531 val = 0;
Marek Vasut6a131772019-08-07 19:56:09 +0200532 if ((prr_product != PRR_PRODUCT_M3N) &&
533 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200534 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
535 dsb_sev();
536
537 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
538 dsb_sev();
539 }
540 dsb_sev();
541
542 for (loop = 0; loop < loop_max; loop++) {
543 val = mmio_read_32(DBSC_DBPDRGD(phyno));
544 dsb_sev();
545 }
546 (void)val;
547 } else {
548 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00004000);
549 dsb_sev();
550 while (mmio_read_32(DBSC_DBPDRGA(phyno)) !=
551 (regadd | 0x0000C000)) {
552 dsb_sev();
553 };
554 val = mmio_read_32(DBSC_DBPDRGA(phyno));
555 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
556 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
557 dsb_sev();
558 };
559 dsb_sev();
560
561 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
562 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
563 dsb_sev();
564 };
565
566 dsb_sev();
567 val = mmio_read_32(DBSC_DBPDRGD(phyno));
568 dsb_sev();
569 (void)val;
570 }
571 return val;
572}
573
574static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata)
575{
576 uint32_t val;
577 uint32_t loop;
578
Marek Vasut6a131772019-08-07 19:56:09 +0200579 if ((prr_product != PRR_PRODUCT_M3N) &&
580 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200581 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
582 dsb_sev();
583 for (loop = 0; loop < loop_max; loop++) {
584 val = mmio_read_32(DBSC_DBPDRGA(phyno));
585 dsb_sev();
586 }
587 mmio_write_32(DBSC_DBPDRGD(phyno), regdata);
588 dsb_sev();
589
590 for (loop = 0; loop < loop_max; loop++) {
591 val = mmio_read_32(DBSC_DBPDRGD(phyno));
592 dsb_sev();
593 }
594 } else {
595 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
596 dsb_sev();
597
598 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
599 dsb_sev();
600 };
601 dsb_sev();
602
603 mmio_write_32(DBSC_DBPDRGD(phyno), regdata);
604 dsb_sev();
605
606 while (mmio_read_32(DBSC_DBPDRGA(phyno)) !=
607 (regadd | 0x00008000)) {
608 dsb_sev();
609 };
610 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
611
612 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
613 dsb_sev();
614 };
615 dsb_sev();
616
617 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
618 }
619 (void)val;
620}
621
622static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata)
623{
624 uint32_t ch;
625 uint32_t val;
626 uint32_t loop;
627
Marek Vasut6a131772019-08-07 19:56:09 +0200628 if ((prr_product != PRR_PRODUCT_M3N) &&
629 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200630 foreach_vch(ch) {
631 mmio_write_32(DBSC_DBPDRGA(ch), regadd);
632 dsb_sev();
633 }
634
635 foreach_vch(ch) {
636 mmio_write_32(DBSC_DBPDRGD(ch), regdata);
637 dsb_sev();
638 }
639
640 for (loop = 0; loop < loop_max; loop++) {
641 val = mmio_read_32(DBSC_DBPDRGD(0));
642 dsb_sev();
643 }
644 (void)val;
645 } else {
646 foreach_vch(ch) {
647 reg_ddrphy_write(ch, regadd, regdata);
648 dsb_sev();
649 }
650 }
651}
652
Marek Vasut80784f92019-08-07 19:02:26 +0200653static inline void ddrphy_regif_idle(void)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200654{
655 uint32_t val;
656
657 val = reg_ddrphy_read(0, ddr_regdef_adr(_reg_PI_INT_STATUS));
658 dsb_sev();
659 (void)val;
660}
661
Marek Vasut6a131772019-08-07 19:56:09 +0200662/* DDRPHY register access (field modify) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200663static inline uint32_t ddr_regdef(uint32_t _regdef)
664{
Marek Vasut38dc7562019-08-07 19:17:42 +0200665 return p_ddr_regdef_tbl[_regdef];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200666}
667
668static inline uint32_t ddr_regdef_adr(uint32_t _regdef)
669{
Marek Vasut38dc7562019-08-07 19:17:42 +0200670 return DDR_REGDEF_ADR(p_ddr_regdef_tbl[_regdef]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200671}
672
673static inline uint32_t ddr_regdef_lsb(uint32_t _regdef)
674{
Marek Vasut38dc7562019-08-07 19:17:42 +0200675 return DDR_REGDEF_LSB(p_ddr_regdef_tbl[_regdef]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200676}
677
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200678static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef,
679 uint32_t val)
680{
681 uint32_t adr;
682 uint32_t lsb;
683 uint32_t len;
684 uint32_t msk;
685 uint32_t tmp;
686 uint32_t regdef;
687
688 regdef = ddr_regdef(_regdef);
689 adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice;
690 len = DDR_REGDEF_LEN(regdef);
691 lsb = DDR_REGDEF_LSB(regdef);
692 if (len == 0x20)
693 msk = 0xffffffff;
694 else
695 msk = ((1U << len) - 1) << lsb;
696
697 tmp = reg_ddrphy_read(ch, adr);
698 tmp = (tmp & (~msk)) | ((val << lsb) & msk);
699 reg_ddrphy_write(ch, adr, tmp);
700}
701
702static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef)
703{
704 uint32_t adr;
705 uint32_t lsb;
706 uint32_t len;
707 uint32_t msk;
708 uint32_t tmp;
709 uint32_t regdef;
710
711 regdef = ddr_regdef(_regdef);
712 adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice;
713 len = DDR_REGDEF_LEN(regdef);
714 lsb = DDR_REGDEF_LSB(regdef);
715 if (len == 0x20)
716 msk = 0xffffffff;
717 else
718 msk = ((1U << len) - 1);
719
720 tmp = reg_ddrphy_read(ch, adr);
721 tmp = (tmp >> lsb) & msk;
722
723 return tmp;
724}
725
726static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val)
727{
728 ddr_setval_s(ch, 0, regdef, val);
729}
730
731static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val)
732{
733 uint32_t ch;
734
735 foreach_vch(ch)
736 ddr_setval_s(ch, slice, regdef, val);
737}
738
739static void ddr_setval_ach(uint32_t regdef, uint32_t val)
740{
741 ddr_setval_ach_s(0, regdef, val);
742}
743
744static void ddr_setval_ach_as(uint32_t regdef, uint32_t val)
745{
746 uint32_t slice;
747
748 for (slice = 0; slice < SLICE_CNT; slice++)
749 ddr_setval_ach_s(slice, regdef, val);
750}
751
752static uint32_t ddr_getval(uint32_t ch, uint32_t regdef)
753{
754 return ddr_getval_s(ch, 0, regdef);
755}
756
Marek Vasut80784f92019-08-07 19:02:26 +0200757static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200758{
759 uint32_t ch;
760
761 foreach_vch(ch)
762 p[ch] = ddr_getval_s(ch, 0, regdef);
763 return p[0];
764}
765
Marek Vasut80784f92019-08-07 19:02:26 +0200766static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200767{
768 uint32_t ch, slice;
769 uint32_t *pp;
770
771 pp = p;
772 foreach_vch(ch)
Marek Vasut6ad74c32019-08-08 16:34:22 +0200773 for (slice = 0; slice < SLICE_CNT; slice++)
774 *pp++ = ddr_getval_s(ch, slice, regdef);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200775 return p[0];
776}
777
Marek Vasut6a131772019-08-07 19:56:09 +0200778/* handling functions for setteing ddrphy value table */
Marek Vasut80784f92019-08-07 19:02:26 +0200779static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200780{
781 uint32_t i;
782
783 for (i = 0; i < size; i++) {
784 to[i] = from[i];
785 }
786}
787
Marek Vasut80784f92019-08-07 19:02:26 +0200788static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200789{
790 uint32_t adr;
791 uint32_t lsb;
792 uint32_t len;
793 uint32_t msk;
794 uint32_t tmp;
795 uint32_t adrmsk;
796 uint32_t regdef;
797
798 regdef = ddr_regdef(_regdef);
799 adr = DDR_REGDEF_ADR(regdef);
800 len = DDR_REGDEF_LEN(regdef);
801 lsb = DDR_REGDEF_LSB(regdef);
802 if (len == 0x20)
803 msk = 0xffffffff;
804 else
805 msk = ((1U << len) - 1) << lsb;
806
807 if (adr < 0x400) {
808 adrmsk = 0xff;
809 } else {
810 adrmsk = 0x7f;
811 }
812
813 tmp = tbl[adr & adrmsk];
814 tmp = (tmp & (~msk)) | ((val << lsb) & msk);
815 tbl[adr & adrmsk] = tmp;
816}
817
Marek Vasut80784f92019-08-07 19:02:26 +0200818static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200819{
820 uint32_t adr;
821 uint32_t lsb;
822 uint32_t len;
823 uint32_t msk;
824 uint32_t tmp;
825 uint32_t adrmsk;
826 uint32_t regdef;
827
828 regdef = ddr_regdef(_regdef);
829 adr = DDR_REGDEF_ADR(regdef);
830 len = DDR_REGDEF_LEN(regdef);
831 lsb = DDR_REGDEF_LSB(regdef);
832 if (len == 0x20)
833 msk = 0xffffffff;
834 else
835 msk = ((1U << len) - 1);
836
837 if (adr < 0x400) {
838 adrmsk = 0xff;
839 } else {
840 adrmsk = 0x7f;
841 }
842
843 tmp = tbl[adr & adrmsk];
844 tmp = (tmp >> lsb) & msk;
845
846 return tmp;
847}
848
Marek Vasut6a131772019-08-07 19:56:09 +0200849/* DDRPHY register access handling */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200850static uint32_t ddrphy_regif_chk(void)
851{
852 uint32_t tmp_ach[DRAM_CH_CNT];
853 uint32_t ch;
854 uint32_t err;
855 uint32_t PI_VERSION_CODE;
856
Marek Vasut6a131772019-08-07 19:56:09 +0200857 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
858 (prr_product == PRR_PRODUCT_M3)) {
859 PI_VERSION_CODE = 0x2041; /* H3 Ver.1.x/M3-W */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200860 } else {
Marek Vasut6a131772019-08-07 19:56:09 +0200861 PI_VERSION_CODE = 0x2040; /* H3 Ver.2.0 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200862 }
863
Marek Vasut80784f92019-08-07 19:02:26 +0200864 ddr_getval_ach(_reg_PI_VERSION, (uint32_t *)tmp_ach);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200865 err = 0;
866 foreach_vch(ch) {
Marek Vasut80784f92019-08-07 19:02:26 +0200867 if (tmp_ach[ch] != PI_VERSION_CODE)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200868 err = 1;
869 }
870 return err;
871}
872
Marek Vasut6a131772019-08-07 19:56:09 +0200873/* functions and parameters for timing setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200874struct _jedec_spec1 {
875 uint16_t fx3;
Marek Vasut38dc7562019-08-07 19:17:42 +0200876 uint8_t rlwodbi;
877 uint8_t rlwdbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200878 uint8_t WL;
Marek Vasut38dc7562019-08-07 19:17:42 +0200879 uint8_t nwr;
880 uint8_t nrtp;
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900881 uint8_t odtlon;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200882 uint8_t MR1;
883 uint8_t MR2;
884};
Marek Vasut80784f92019-08-07 19:02:26 +0200885
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200886#define JS1_USABLEC_SPEC_LO 2
887#define JS1_USABLEC_SPEC_HI 5
888#define JS1_FREQ_TBL_NUM 8
Marek Vasut80784f92019-08-07 19:02:26 +0200889#define JS1_MR1(f) (0x04 | ((f) << 4))
890#define JS1_MR2(f) (0x00 | ((f) << 3) | (f))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200891const struct _jedec_spec1 js1[JS1_FREQ_TBL_NUM] = {
Marek Vasut6ad74c32019-08-08 16:34:22 +0200892 /* 533.333Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900893 { 800, 6, 6, 4, 6, 8, 0, JS1_MR1(0), JS1_MR2(0) | 0x40 },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200894 /* 1066.666Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900895 { 1600, 10, 12, 8, 10, 8, 0, JS1_MR1(1), JS1_MR2(1) | 0x40 },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200896 /* 1600.000Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900897 { 2400, 14, 16, 12, 16, 8, 6, JS1_MR1(2), JS1_MR2(2) | 0x40 },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200898 /* 2133.333Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900899 { 3200, 20, 22, 10, 20, 8, 4, JS1_MR1(3), JS1_MR2(3) },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200900 /* 2666.666Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900901 { 4000, 24, 28, 12, 24, 10, 4, JS1_MR1(4), JS1_MR2(4) },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200902 /* 3200.000Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900903 { 4800, 28, 32, 14, 30, 12, 6, JS1_MR1(5), JS1_MR2(5) },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200904 /* 3733.333Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900905 { 5600, 32, 36, 16, 34, 14, 6, JS1_MR1(6), JS1_MR2(6) },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200906 /* 4266.666Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900907 { 6400, 36, 40, 18, 40, 16, 8, JS1_MR1(7), JS1_MR2(7) }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200908};
909
910struct _jedec_spec2 {
911 uint16_t ps;
912 uint16_t cyc;
913};
914
Marek Vasut38dc7562019-08-07 19:17:42 +0200915#define js2_tsr 0
916#define js2_txp 1
917#define js2_trtp 2
918#define js2_trcd 3
919#define js2_trppb 4
920#define js2_trpab 5
921#define js2_tras 6
922#define js2_twr 7
923#define js2_twtr 8
924#define js2_trrd 9
925#define js2_tppd 10
926#define js2_tfaw 11
927#define js2_tdqsck 12
928#define js2_tckehcmd 13
929#define js2_tckelcmd 14
930#define js2_tckelpd 15
931#define js2_tmrr 16
932#define js2_tmrw 17
933#define js2_tmrd 18
934#define js2_tzqcalns 19
935#define js2_tzqlat 20
936#define js2_tiedly 21
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900937#define js2_tODTon_min 22
938#define JS2_TBLCNT 23
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200939
Marek Vasut38dc7562019-08-07 19:17:42 +0200940#define js2_trcpb (JS2_TBLCNT)
941#define js2_trcab (JS2_TBLCNT + 1)
942#define js2_trfcab (JS2_TBLCNT + 2)
Marek Vasut80784f92019-08-07 19:02:26 +0200943#define JS2_CNT (JS2_TBLCNT + 3)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200944
945#ifndef JS2_DERATE
946#define JS2_DERATE 0
947#endif
948const struct _jedec_spec2 jedec_spec2[2][JS2_TBLCNT] = {
949 {
950/*tSR */ {15000, 3},
951/*tXP */ {7500, 3},
952/*tRTP */ {7500, 8},
953/*tRCD */ {18000, 4},
954/*tRPpb */ {18000, 3},
955/*tRPab */ {21000, 3},
956/*tRAS */ {42000, 3},
957/*tWR */ {18000, 4},
958/*tWTR */ {10000, 8},
959/*tRRD */ {10000, 4},
960/*tPPD */ {0, 0},
961/*tFAW */ {40000, 0},
962/*tDQSCK*/ {3500, 0},
963/*tCKEHCMD*/ {7500, 3},
964/*tCKELCMD*/ {7500, 3},
965/*tCKELPD*/ {7500, 3},
966/*tMRR*/ {0, 8},
967/*tMRW*/ {10000, 10},
968/*tMRD*/ {14000, 10},
969/*tZQCALns*/ {1000 * 10, 0},
970/*tZQLAT*/ {30000, 10},
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900971/*tIEdly*/ {12500, 0},
972/*tODTon_min*/ {1500, 0}
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200973 }, {
974/*tSR */ {15000, 3},
975/*tXP */ {7500, 3},
976/*tRTP */ {7500, 8},
977/*tRCD */ {19875, 4},
978/*tRPpb */ {19875, 3},
979/*tRPab */ {22875, 3},
980/*tRAS */ {43875, 3},
981/*tWR */ {18000, 4},
982/*tWTR */ {10000, 8},
983/*tRRD */ {11875, 4},
984/*tPPD */ {0, 0},
985/*tFAW */ {40000, 0},
986/*tDQSCK*/ {3600, 0},
987/*tCKEHCMD*/ {7500, 3},
988/*tCKELCMD*/ {7500, 3},
989/*tCKELPD*/ {7500, 3},
990/*tMRR*/ {0, 8},
991/*tMRW*/ {10000, 10},
992/*tMRD*/ {14000, 10},
993/*tZQCALns*/ {1000 * 10, 0},
994/*tZQLAT*/ {30000, 10},
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900995/*tIEdly*/ {12500, 0},
996/*tODTon_min*/ {1500, 0}
Marek Vasut80784f92019-08-07 19:02:26 +0200997 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200998};
999
Marek Vasut38dc7562019-08-07 19:17:42 +02001000const uint16_t jedec_spec2_trfc_ab[7] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001001/* 4Gb, 6Gb, 8Gb,12Gb, 16Gb, 24Gb(non), 32Gb(non) */
Marek Vasut6c245a52018-12-12 18:06:39 +01001002 130, 180, 180, 280, 280, 560, 560
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001003};
1004
1005static uint32_t js1_ind;
1006static uint16_t js2[JS2_CNT];
1007static uint8_t RL;
1008static uint8_t WL;
1009
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001010static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001011 uint16_t cyc)
1012{
1013 uint32_t tmp;
1014 uint32_t div;
1015
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001016 tmp = (((uint32_t)(ps) + 9) / 10) * _ddr_mbps;
1017 div = tmp / (200000 * _ddr_mbpsdiv);
1018 if (tmp != (div * 200000 * _ddr_mbpsdiv))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001019 div = div + 1;
1020
1021 if (div > cyc)
Marek Vasut80784f92019-08-07 19:02:26 +02001022 return (uint16_t)div;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001023 return cyc;
1024}
1025
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001026static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv,
1027 uint16_t *_js2)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001028{
1029 int i;
1030
1031 for (i = 0; i < JS2_TBLCNT; i++) {
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001032 _js2[i] = _f_scale(_ddr_mbps, _ddr_mbpsdiv,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001033 1UL * jedec_spec2[JS2_DERATE][i].ps,
1034 jedec_spec2[JS2_DERATE][i].cyc);
1035 }
1036
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001037 _js2[js2_trcpb] = _js2[js2_tras] + _js2[js2_trppb];
1038 _js2[js2_trcab] = _js2[js2_tras] + _js2[js2_trpab];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001039}
1040
1041/* scaler for DELAY value */
1042static int16_t _f_scale_adj(int16_t ps)
1043{
1044 int32_t tmp;
1045 /*
Marek Vasut6a131772019-08-07 19:56:09 +02001046 * tmp = (int32_t)512 * ps * ddr_mbps /2 / ddr_mbpsdiv / 1000 / 1000;
1047 * = ps * ddr_mbps /2 / ddr_mbpsdiv *512 / 8 / 8 / 125 / 125
1048 * = ps * ddr_mbps / ddr_mbpsdiv *4 / 125 / 125
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001049 */
1050 tmp =
Marek Vasut80784f92019-08-07 19:02:26 +02001051 (int32_t)4 * (int32_t)ps * (int32_t)ddr_mbps /
1052 (int32_t)ddr_mbpsdiv;
1053 tmp = (int32_t)tmp / (int32_t)15625;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001054
Marek Vasut80784f92019-08-07 19:02:26 +02001055 return (int16_t)tmp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001056}
1057
Marek Vasut38dc7562019-08-07 19:17:42 +02001058static const uint32_t reg_pi_mr1_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001059 {
1060 _reg_PI_MR1_DATA_F0_0,
1061 _reg_PI_MR1_DATA_F0_1,
1062 _reg_PI_MR1_DATA_F0_2,
1063 _reg_PI_MR1_DATA_F0_3},
1064 {
1065 _reg_PI_MR1_DATA_F1_0,
1066 _reg_PI_MR1_DATA_F1_1,
1067 _reg_PI_MR1_DATA_F1_2,
1068 _reg_PI_MR1_DATA_F1_3}
1069};
1070
Marek Vasut38dc7562019-08-07 19:17:42 +02001071static const uint32_t reg_pi_mr2_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001072 {
1073 _reg_PI_MR2_DATA_F0_0,
1074 _reg_PI_MR2_DATA_F0_1,
1075 _reg_PI_MR2_DATA_F0_2,
1076 _reg_PI_MR2_DATA_F0_3},
1077 {
1078 _reg_PI_MR2_DATA_F1_0,
1079 _reg_PI_MR2_DATA_F1_1,
1080 _reg_PI_MR2_DATA_F1_2,
1081 _reg_PI_MR2_DATA_F1_3}
1082};
1083
Marek Vasut38dc7562019-08-07 19:17:42 +02001084static const uint32_t reg_pi_mr3_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001085 {
1086 _reg_PI_MR3_DATA_F0_0,
1087 _reg_PI_MR3_DATA_F0_1,
1088 _reg_PI_MR3_DATA_F0_2,
1089 _reg_PI_MR3_DATA_F0_3},
1090 {
1091 _reg_PI_MR3_DATA_F1_0,
1092 _reg_PI_MR3_DATA_F1_1,
1093 _reg_PI_MR3_DATA_F1_2,
1094 _reg_PI_MR3_DATA_F1_3}
1095};
1096
Marek Vasut38dc7562019-08-07 19:17:42 +02001097const uint32_t reg_pi_mr11_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001098 {
1099 _reg_PI_MR11_DATA_F0_0,
1100 _reg_PI_MR11_DATA_F0_1,
1101 _reg_PI_MR11_DATA_F0_2,
1102 _reg_PI_MR11_DATA_F0_3},
1103 {
1104 _reg_PI_MR11_DATA_F1_0,
1105 _reg_PI_MR11_DATA_F1_1,
1106 _reg_PI_MR11_DATA_F1_2,
1107 _reg_PI_MR11_DATA_F1_3}
1108};
1109
Marek Vasut38dc7562019-08-07 19:17:42 +02001110const uint32_t reg_pi_mr12_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001111 {
1112 _reg_PI_MR12_DATA_F0_0,
1113 _reg_PI_MR12_DATA_F0_1,
1114 _reg_PI_MR12_DATA_F0_2,
1115 _reg_PI_MR12_DATA_F0_3},
1116 {
1117 _reg_PI_MR12_DATA_F1_0,
1118 _reg_PI_MR12_DATA_F1_1,
1119 _reg_PI_MR12_DATA_F1_2,
1120 _reg_PI_MR12_DATA_F1_3}
1121};
1122
Marek Vasut38dc7562019-08-07 19:17:42 +02001123const uint32_t reg_pi_mr14_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001124 {
1125 _reg_PI_MR14_DATA_F0_0,
1126 _reg_PI_MR14_DATA_F0_1,
1127 _reg_PI_MR14_DATA_F0_2,
1128 _reg_PI_MR14_DATA_F0_3},
1129 {
1130 _reg_PI_MR14_DATA_F1_0,
1131 _reg_PI_MR14_DATA_F1_1,
1132 _reg_PI_MR14_DATA_F1_2,
1133 _reg_PI_MR14_DATA_F1_3}
1134};
1135
Marek Vasut6a131772019-08-07 19:56:09 +02001136/*
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001137 * regif pll w/a ( REGIF H3 Ver.2.0 or later/M3-N/V3H WA )
Marek Vasut6a131772019-08-07 19:56:09 +02001138 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001139static void regif_pll_wa(void)
1140{
1141 uint32_t ch;
1142
Marek Vasut38dc7562019-08-07 19:17:42 +02001143 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001144 // PLL setting for PHY : H3 Ver.1.x
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001145 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT),
1146 (0x0064U <<
1147 ddr_regdef_lsb(_reg_PHY_PLL_WAIT)));
1148 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL),
1149 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1150 _reg_PHY_PLL_CTRL));
1151
1152 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL),
1153 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1154 _reg_PHY_LP4_BOOT_PLL_CTRL));
1155
1156 } else {
1157 /* PLL setting for PHY : M3-W/M3-N/V3H/H3 Ver.2.0 or later */
1158 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT),
1159 (0x5064U <<
1160 ddr_regdef_lsb(_reg_PHY_PLL_WAIT)));
1161
1162 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL),
1163 (ddrtbl_getval
1164 (_cnf_DDR_PHY_ADR_G_REGSET,
1165 _reg_PHY_PLL_CTRL_TOP) << 16) |
1166 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1167 _reg_PHY_PLL_CTRL));
1168 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL_CA),
1169 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1170 _reg_PHY_PLL_CTRL_CA));
1171
1172 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL),
1173 (ddrtbl_getval
1174 (_cnf_DDR_PHY_ADR_G_REGSET,
1175 _reg_PHY_LP4_BOOT_PLL_CTRL_CA) << 16) |
1176 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1177 _reg_PHY_LP4_BOOT_PLL_CTRL));
1178 reg_ddrphy_write_a(ddr_regdef_adr
1179 (_reg_PHY_LP4_BOOT_TOP_PLL_CTRL),
1180 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
Marek Vasut6a131772019-08-07 19:56:09 +02001181 _reg_PHY_LP4_BOOT_TOP_PLL_CTRL
1182 ));
Yoshifumi Hosoya39be8282022-07-22 13:04:36 +09001183 if (ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, _reg_PHY_LP4_BOOT_LOW_FREQ_SEL)) {
1184 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_LOW_FREQ_SEL),
1185 _cnf_DDR_PHY_ADR_G_REGSET[0x7f & ddr_regdef_adr(
1186 _reg_PHY_LP4_BOOT_LOW_FREQ_SEL)]);
1187 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001188 }
1189
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001190 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LPDDR3_CS),
Marek Vasut6a131772019-08-07 19:56:09 +02001191 _cnf_DDR_PHY_ADR_G_REGSET
1192 [ddr_regdef_adr(_reg_PHY_LPDDR3_CS) -
1193 DDR_PHY_ADR_G_REGSET_OFS]);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001194
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001195 /* protect register interface */
1196 ddrphy_regif_idle();
1197 pll3_control(0);
1198
Marek Vasut38dc7562019-08-07 19:17:42 +02001199 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001200 /* non */
1201 } else {
1202 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_DLL_RST_EN),
1203 (0x01U <<
1204 ddr_regdef_lsb(_reg_PHY_DLL_RST_EN)));
1205 ddrphy_regif_idle();
1206 }
1207
Marek Vasut6a131772019-08-07 19:56:09 +02001208 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001209 /* dbdficnt0:
1210 * dfi_dram_clk_disable=1
1211 * dfi_frequency = 0
1212 * freq_ratio = 01 (2:1)
1213 * init_start =0
1214 */
1215 foreach_vch(ch)
1216 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
1217 dsb_sev();
1218
1219 /* dbdficnt0:
1220 * dfi_dram_clk_disable=1
1221 * dfi_frequency = 0
1222 * freq_ratio = 01 (2:1)
1223 * init_start =1
1224 */
1225 foreach_vch(ch)
1226 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
1227 dsb_sev();
1228
1229 foreach_ech(ch)
Marek Vasut6a131772019-08-07 19:56:09 +02001230 if ((board_cnf->phyvalid) & BIT(ch))
1231 while ((mmio_read_32(DBSC_PLL_LOCK(ch)) & 0x1f) != 0x1f)
1232 ;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001233 dsb_sev();
1234}
1235
Marek Vasut6a131772019-08-07 19:56:09 +02001236/* load table data into DDR registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001237static void ddrtbl_load(void)
1238{
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001239 uint32_t i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001240 uint32_t slice;
1241 uint32_t csab;
1242 uint32_t adr;
Marek Vasut38dc7562019-08-07 19:17:42 +02001243 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001244 uint32_t tmp[3];
1245 uint16_t dataS;
1246
Marek Vasut6a131772019-08-07 19:56:09 +02001247 /* TIMING REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001248 /* search jedec_spec1 index */
1249 for (i = JS1_USABLEC_SPEC_LO; i < JS1_FREQ_TBL_NUM - 1; i++) {
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001250 if (js1[i].fx3 * 2U * ddr_mbpsdiv >= ddr_mbps * 3U)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001251 break;
1252 }
Marek Vasut80784f92019-08-07 19:02:26 +02001253 if (i > JS1_USABLEC_SPEC_HI)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001254 js1_ind = JS1_USABLEC_SPEC_HI;
1255 else
1256 js1_ind = i;
1257
Marek Vasut38dc7562019-08-07 19:17:42 +02001258 if (board_cnf->dbi_en)
1259 RL = js1[js1_ind].rlwdbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001260 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001261 RL = js1[js1_ind].rlwodbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001262
1263 WL = js1[js1_ind].WL;
1264
1265 /* calculate jedec_spec2 */
1266 _f_scale_js2(ddr_mbps, ddr_mbpsdiv, js2);
1267
Marek Vasut6a131772019-08-07 19:56:09 +02001268 /* PREPARE TBL */
Marek Vasut38dc7562019-08-07 19:17:42 +02001269 if (prr_product == PRR_PRODUCT_H3) {
1270 if (prr_cut <= PRR_PRODUCT_11) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001271 /* H3 Ver.1.x */
1272 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1273 DDR_PHY_SLICE_REGSET_H3,
1274 DDR_PHY_SLICE_REGSET_NUM_H3);
1275 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1276 DDR_PHY_ADR_V_REGSET_H3,
1277 DDR_PHY_ADR_V_REGSET_NUM_H3);
1278 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET,
1279 DDR_PHY_ADR_I_REGSET_H3,
1280 DDR_PHY_ADR_I_REGSET_NUM_H3);
1281 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1282 DDR_PHY_ADR_G_REGSET_H3,
1283 DDR_PHY_ADR_G_REGSET_NUM_H3);
1284 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3,
1285 DDR_PI_REGSET_NUM_H3);
1286
1287 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_H3;
1288 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_H3;
1289 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_H3;
1290 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_H3;
1291 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3;
1292 DDR_PHY_SLICE_REGSET_SIZE =
1293 DDR_PHY_SLICE_REGSET_SIZE_H3;
1294 DDR_PHY_ADR_V_REGSET_SIZE =
1295 DDR_PHY_ADR_V_REGSET_SIZE_H3;
1296 DDR_PHY_ADR_I_REGSET_SIZE =
1297 DDR_PHY_ADR_I_REGSET_SIZE_H3;
1298 DDR_PHY_ADR_G_REGSET_SIZE =
1299 DDR_PHY_ADR_G_REGSET_SIZE_H3;
1300 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3;
1301 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_H3;
1302 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_H3;
1303 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_H3;
1304 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_H3;
1305 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3;
1306
1307 DDR_PHY_ADR_I_NUM = 1;
1308 } else {
1309 /* H3 Ver.2.0 or later */
1310 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1311 DDR_PHY_SLICE_REGSET_H3VER2,
1312 DDR_PHY_SLICE_REGSET_NUM_H3VER2);
1313 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1314 DDR_PHY_ADR_V_REGSET_H3VER2,
1315 DDR_PHY_ADR_V_REGSET_NUM_H3VER2);
1316 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1317 DDR_PHY_ADR_G_REGSET_H3VER2,
1318 DDR_PHY_ADR_G_REGSET_NUM_H3VER2);
1319 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3VER2,
1320 DDR_PI_REGSET_NUM_H3VER2);
1321
1322 DDR_PHY_SLICE_REGSET_OFS =
1323 DDR_PHY_SLICE_REGSET_OFS_H3VER2;
1324 DDR_PHY_ADR_V_REGSET_OFS =
1325 DDR_PHY_ADR_V_REGSET_OFS_H3VER2;
1326 DDR_PHY_ADR_G_REGSET_OFS =
1327 DDR_PHY_ADR_G_REGSET_OFS_H3VER2;
1328 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3VER2;
1329 DDR_PHY_SLICE_REGSET_SIZE =
1330 DDR_PHY_SLICE_REGSET_SIZE_H3VER2;
1331 DDR_PHY_ADR_V_REGSET_SIZE =
1332 DDR_PHY_ADR_V_REGSET_SIZE_H3VER2;
1333 DDR_PHY_ADR_G_REGSET_SIZE =
1334 DDR_PHY_ADR_G_REGSET_SIZE_H3VER2;
1335 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3VER2;
1336 DDR_PHY_SLICE_REGSET_NUM =
1337 DDR_PHY_SLICE_REGSET_NUM_H3VER2;
1338 DDR_PHY_ADR_V_REGSET_NUM =
1339 DDR_PHY_ADR_V_REGSET_NUM_H3VER2;
1340 DDR_PHY_ADR_G_REGSET_NUM =
1341 DDR_PHY_ADR_G_REGSET_NUM_H3VER2;
1342 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3VER2;
1343
1344 DDR_PHY_ADR_I_NUM = 0;
1345 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001346 } else if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001347 /* M3-W */
1348 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1349 DDR_PHY_SLICE_REGSET_M3, DDR_PHY_SLICE_REGSET_NUM_M3);
1350 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1351 DDR_PHY_ADR_V_REGSET_M3, DDR_PHY_ADR_V_REGSET_NUM_M3);
1352 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET,
1353 DDR_PHY_ADR_I_REGSET_M3, DDR_PHY_ADR_I_REGSET_NUM_M3);
1354 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1355 DDR_PHY_ADR_G_REGSET_M3, DDR_PHY_ADR_G_REGSET_NUM_M3);
1356 _tblcopy(_cnf_DDR_PI_REGSET,
1357 DDR_PI_REGSET_M3, DDR_PI_REGSET_NUM_M3);
1358
1359 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3;
1360 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3;
1361 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3;
1362 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3;
1363 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3;
1364 DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3;
1365 DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3;
1366 DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3;
1367 DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3;
1368 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3;
1369 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3;
1370 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3;
1371 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3;
1372 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3;
1373 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3;
1374
1375 DDR_PHY_ADR_I_NUM = 2;
1376 } else {
1377 /* M3-N/V3H */
1378 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1379 DDR_PHY_SLICE_REGSET_M3N,
1380 DDR_PHY_SLICE_REGSET_NUM_M3N);
1381 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, DDR_PHY_ADR_V_REGSET_M3N,
1382 DDR_PHY_ADR_V_REGSET_NUM_M3N);
1383 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, DDR_PHY_ADR_I_REGSET_M3N,
1384 DDR_PHY_ADR_I_REGSET_NUM_M3N);
1385 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, DDR_PHY_ADR_G_REGSET_M3N,
1386 DDR_PHY_ADR_G_REGSET_NUM_M3N);
1387 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_M3N,
1388 DDR_PI_REGSET_NUM_M3N);
1389
1390 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3N;
1391 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3N;
1392 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3N;
1393 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3N;
1394 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3N;
1395 DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3N;
1396 DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3N;
1397 DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3N;
1398 DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3N;
1399 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3N;
1400 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3N;
1401 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3N;
1402 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3N;
1403 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3N;
1404 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3N;
1405
1406 DDR_PHY_ADR_I_NUM = 2;
1407 }
1408
Marek Vasut6a131772019-08-07 19:56:09 +02001409 /* PLL CODE CHANGE */
Marek Vasut38dc7562019-08-07 19:17:42 +02001410 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001411 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, _reg_PHY_PLL_CTRL,
1412 0x1142);
1413 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1414 _reg_PHY_LP4_BOOT_PLL_CTRL, 0x1142);
1415 }
1416
Marek Vasut6a131772019-08-07 19:56:09 +02001417 /* on fly gate adjust */
Marek Vasut38dc7562019-08-07 19:17:42 +02001418 if ((prr_product == PRR_PRODUCT_M3) && (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001419 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1420 _reg_ON_FLY_GATE_ADJUST_EN, 0x00);
1421 }
1422
Marek Vasut6a131772019-08-07 19:56:09 +02001423 /* Adjust PI parameters */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001424#ifdef _def_LPDDR4_ODT
Marek Vasut6c245a52018-12-12 18:06:39 +01001425 for (i = 0; i < 2; i++) {
1426 for (csab = 0; csab < CSAB_CNT; csab++) {
1427 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001428 reg_pi_mr11_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001429 _def_LPDDR4_ODT);
1430 }
1431 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001432#endif /* _def_LPDDR4_ODT */
1433
1434#ifdef _def_LPDDR4_VREFCA
Marek Vasut6c245a52018-12-12 18:06:39 +01001435 for (i = 0; i < 2; i++) {
1436 for (csab = 0; csab < CSAB_CNT; csab++) {
1437 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001438 reg_pi_mr12_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001439 _def_LPDDR4_VREFCA);
1440 }
1441 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001442#endif /* _def_LPDDR4_VREFCA */
Marek Vasut6a131772019-08-07 19:56:09 +02001443 if ((prr_product == PRR_PRODUCT_M3N) ||
1444 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001445 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 7000, 0) + 7U;
1446 if (js2[js2_tiedly] > (RL))
1447 js2[js2_tiedly] = RL;
Marek Vasut6a131772019-08-07 19:56:09 +02001448 } else if ((prr_product == PRR_PRODUCT_H3) &&
1449 (prr_cut > PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001450 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 9000, 0) + 4U;
Marek Vasut6a131772019-08-07 19:56:09 +02001451 } else if ((prr_product == PRR_PRODUCT_H3) &&
1452 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001453 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 10000, 0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001454 }
1455
Marek Vasut6a131772019-08-07 19:56:09 +02001456 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
1457 (prr_product == PRR_PRODUCT_M3N) ||
1458 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001459 if ((js2[js2_tiedly]) >= 0x1e)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001460 dataS = 0x1e;
1461 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001462 dataS = js2[js2_tiedly];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001463 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001464 if ((js2[js2_tiedly]) >= 0x0e)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001465 dataS = 0x0e;
1466 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001467 dataS = js2[js2_tiedly];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001468 }
1469
1470 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_DLY, dataS);
1471 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_TSEL_DLY,
1472 (dataS - 2));
Marek Vasut6a131772019-08-07 19:56:09 +02001473 if ((prr_product == PRR_PRODUCT_M3N) ||
1474 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001475 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001476 _reg_PHY_RDDATA_EN_OE_DLY, dataS - 2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001477 }
1478 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1, RL - dataS);
1479
1480 if (ddrtbl_getval
1481 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001482 data_l = WL - 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001483 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001484 data_l = WL;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001485 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001486 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1, data_l - 2);
1487 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001488
Marek Vasut38dc7562019-08-07 19:17:42 +02001489 if (board_cnf->dbi_en) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001490 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE,
1491 0x01);
1492 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1493 _reg_PHY_WDQLVL_DATADM_MASK, 0x000);
1494 } else {
1495 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE,
1496 0x00);
1497 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1498 _reg_PHY_WDQLVL_DATADM_MASK, 0x100);
1499 }
1500
1501 tmp[0] = js1[js1_ind].MR1;
1502 tmp[1] = js1[js1_ind].MR2;
Marek Vasut38dc7562019-08-07 19:17:42 +02001503 data_l = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_MR3_DATA_F1_0);
1504 if (board_cnf->dbi_en)
1505 tmp[2] = data_l | 0xc0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001506 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001507 tmp[2] = data_l & (~0xc0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001508
1509 for (i = 0; i < 2; i++) {
1510 for (csab = 0; csab < CSAB_CNT; csab++) {
1511 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001512 reg_pi_mr1_data_fx_csx[i][csab], tmp[0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001513 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001514 reg_pi_mr2_data_fx_csx[i][csab], tmp[1]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001515 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001516 reg_pi_mr3_data_fx_csx[i][csab], tmp[2]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001517 }
1518 }
1519
Marek Vasut6a131772019-08-07 19:56:09 +02001520 /* DDRPHY INT START */
Marek Vasut38dc7562019-08-07 19:17:42 +02001521 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001522 /* non */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001523 } else {
1524 regif_pll_wa();
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001525 dbwait_loop(5);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001526 }
1527
Marek Vasut6a131772019-08-07 19:56:09 +02001528 /* FREQ_SEL_MULTICAST & PER_CS_TRAINING_MULTICAST SET (for safety) */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001529 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
Marek Vasut6ad74c32019-08-08 16:34:22 +02001530 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001531 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x01);
1532
Marek Vasut6a131772019-08-07 19:56:09 +02001533 /* SET DATA SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001534 for (slice = 0; slice < SLICE_CNT; slice++) {
1535 adr =
1536 DDR_PHY_SLICE_REGSET_OFS +
1537 DDR_PHY_SLICE_REGSET_SIZE * slice;
1538 for (i = 0; i < DDR_PHY_SLICE_REGSET_NUM; i++) {
1539 reg_ddrphy_write_a(adr + i,
1540 _cnf_DDR_PHY_SLICE_REGSET[i]);
1541 }
1542 }
1543
Marek Vasut6a131772019-08-07 19:56:09 +02001544 /* SET ADR SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001545 adr = DDR_PHY_ADR_V_REGSET_OFS;
1546 for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) {
1547 reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_V_REGSET[i]);
1548 }
1549
Marek Vasut6a131772019-08-07 19:56:09 +02001550 if (((prr_product == PRR_PRODUCT_M3) ||
1551 (prr_product == PRR_PRODUCT_M3N)) &&
Marek Vasut38dc7562019-08-07 19:17:42 +02001552 ((0x00ffffff & (uint32_t)((board_cnf->ch[0].ca_swap) >> 40))
Marek Vasut6c245a52018-12-12 18:06:39 +01001553 != 0x00)) {
1554 adr = DDR_PHY_ADR_I_REGSET_OFS + DDR_PHY_ADR_I_REGSET_SIZE;
1555 for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) {
1556 reg_ddrphy_write_a(adr + i,
1557 _cnf_DDR_PHY_ADR_V_REGSET[i]);
1558 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02001559 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1560 _reg_PHY_ADR_DISABLE, 0x02);
Marek Vasut6c245a52018-12-12 18:06:39 +01001561 DDR_PHY_ADR_I_NUM -= 1;
1562 ddr_phycaslice = 1;
1563
1564#ifndef _def_LPDDR4_ODT
1565 for (i = 0; i < 2; i++) {
1566 for (csab = 0; csab < CSAB_CNT; csab++) {
1567 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001568 reg_pi_mr11_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001569 0x66);
1570 }
1571 }
1572#endif/* _def_LPDDR4_ODT */
1573 } else {
1574 ddr_phycaslice = 0;
1575 }
1576
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001577 if (DDR_PHY_ADR_I_NUM > 0) {
1578 for (slice = 0; slice < DDR_PHY_ADR_I_NUM; slice++) {
1579 adr =
1580 DDR_PHY_ADR_I_REGSET_OFS +
1581 DDR_PHY_ADR_I_REGSET_SIZE * slice;
1582 for (i = 0; i < DDR_PHY_ADR_I_REGSET_NUM; i++) {
1583 reg_ddrphy_write_a(adr + i,
1584 _cnf_DDR_PHY_ADR_I_REGSET
1585 [i]);
1586 }
1587 }
1588 }
1589
Marek Vasut6a131772019-08-07 19:56:09 +02001590 /* SET ADRCTRL SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001591 adr = DDR_PHY_ADR_G_REGSET_OFS;
1592 for (i = 0; i < DDR_PHY_ADR_G_REGSET_NUM; i++) {
1593 reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_G_REGSET[i]);
1594 }
1595
Marek Vasut6a131772019-08-07 19:56:09 +02001596 /* SET PI REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001597 adr = DDR_PI_REGSET_OFS;
1598 for (i = 0; i < DDR_PI_REGSET_NUM; i++) {
1599 reg_ddrphy_write_a(adr + i, _cnf_DDR_PI_REGSET[i]);
1600 }
1601}
1602
Marek Vasut6a131772019-08-07 19:56:09 +02001603/* CONFIGURE DDR REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001604static void ddr_config_sub(void)
1605{
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001606 uint32_t i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001607 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001608 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001609 uint32_t tmp;
1610 uint8_t high_byte[SLICE_CNT];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001611 const uint32_t _par_CALVL_DEVICE_MAP = 1;
Marek Vasut80784f92019-08-07 19:02:26 +02001612
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001613 foreach_vch(ch) {
Marek Vasut6a131772019-08-07 19:56:09 +02001614 /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001615 for (slice = 0; slice < SLICE_CNT; slice++) {
1616 high_byte[slice] =
Marek Vasut38dc7562019-08-07 19:17:42 +02001617 (board_cnf->ch[ch].dqs_swap >> (4 * slice)) % 2;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001618 ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE0,
Marek Vasut38dc7562019-08-07 19:17:42 +02001619 board_cnf->ch[ch].dq_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001620 ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE1,
Marek Vasut38dc7562019-08-07 19:17:42 +02001621 board_cnf->ch[ch].dm_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001622 if (high_byte[slice]) {
1623 /* HIGHER 16 BYTE */
1624 ddr_setval_s(ch, slice,
1625 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1626 0x00);
1627 } else {
1628 /* LOWER 16 BYTE */
1629 ddr_setval_s(ch, slice,
1630 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1631 0x01);
1632 }
1633 }
1634
Marek Vasut6a131772019-08-07 19:56:09 +02001635 /* BOARD SETTINGS (CA,ADDR_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001636 data_l = (0x00ffffff & (uint32_t)(board_cnf->ch[ch].ca_swap)) |
Marek Vasut6c245a52018-12-12 18:06:39 +01001637 0x00888888;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001638
1639 /* --- ADR_CALVL_SWIZZLE --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001640 if (prr_product == PRR_PRODUCT_M3) {
1641 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001642 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0,
1643 0x00000000);
Marek Vasut38dc7562019-08-07 19:17:42 +02001644 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001645 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1,
1646 0x00000000);
1647 ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP,
1648 _par_CALVL_DEVICE_MAP);
1649 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001650 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001651 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1, 0x00000000);
1652 ddr_setval(ch, _reg_PHY_CALVL_DEVICE_MAP,
1653 _par_CALVL_DEVICE_MAP);
1654 }
1655
1656 /* --- ADR_ADDR_SEL --- */
Marek Vasut6a131772019-08-07 19:56:09 +02001657 if ((prr_product == PRR_PRODUCT_H3) &&
1658 (prr_cut > PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001659 data_l = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001660 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001661 data_l = 0;
1662 tmp = board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001663 for (i = 0; i < 6; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001664 data_l |= ((tmp & 0x0f) << (i * 5));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001665 tmp = tmp >> 4;
1666 }
1667 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001668 ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01001669 if (ddr_phycaslice == 1) {
1670 /* ----------- adr slice2 swap ----------- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001671 tmp = (uint32_t)((board_cnf->ch[ch].ca_swap) >> 40);
1672 data_l = (tmp & 0x00ffffff) | 0x00888888;
Marek Vasut6c245a52018-12-12 18:06:39 +01001673
1674 /* --- ADR_CALVL_SWIZZLE --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001675 if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001676 ddr_setval_s(ch, 2,
1677 _reg_PHY_ADR_CALVL_SWIZZLE0_0,
1678 data_l);
1679 ddr_setval_s(ch, 2,
1680 _reg_PHY_ADR_CALVL_SWIZZLE1_0,
Marek Vasut6c245a52018-12-12 18:06:39 +01001681 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001682 ddr_setval_s(ch, 2,
1683 _reg_PHY_ADR_CALVL_SWIZZLE0_1,
1684 data_l);
1685 ddr_setval_s(ch, 2,
1686 _reg_PHY_ADR_CALVL_SWIZZLE1_1,
Marek Vasut6c245a52018-12-12 18:06:39 +01001687 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001688 ddr_setval_s(ch, 2,
1689 _reg_PHY_ADR_CALVL_DEVICE_MAP,
Marek Vasut6c245a52018-12-12 18:06:39 +01001690 _par_CALVL_DEVICE_MAP);
1691 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001692 ddr_setval_s(ch, 2,
1693 _reg_PHY_ADR_CALVL_SWIZZLE0,
1694 data_l);
1695 ddr_setval_s(ch, 2,
1696 _reg_PHY_ADR_CALVL_SWIZZLE1,
Marek Vasut6c245a52018-12-12 18:06:39 +01001697 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001698 ddr_setval_s(ch, 2,
1699 _reg_PHY_CALVL_DEVICE_MAP,
Marek Vasut6c245a52018-12-12 18:06:39 +01001700 _par_CALVL_DEVICE_MAP);
1701 }
1702
1703 /* --- ADR_ADDR_SEL --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001704 data_l = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01001705 for (i = 0; i < 6; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001706 data_l |= ((tmp & 0x0f) << (i * 5));
Marek Vasut6c245a52018-12-12 18:06:39 +01001707 tmp = tmp >> 4;
1708 }
1709
Marek Vasut38dc7562019-08-07 19:17:42 +02001710 ddr_setval_s(ch, 2, _reg_PHY_ADR_ADDR_SEL, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01001711 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001712
Marek Vasut6a131772019-08-07 19:56:09 +02001713 /* BOARD SETTINGS (BYTE_ORDER_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001714 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001715 /* --- DATA_BYTE_SWAP --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001716 data_l = 0;
1717 tmp = board_cnf->ch[ch].dqs_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001718 for (i = 0; i < 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001719 data_l |= ((tmp & 0x03) << (i * 2));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001720 tmp = tmp >> 4;
1721 }
1722 } else {
1723 /* --- DATA_BYTE_SWAP --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001724 data_l = board_cnf->ch[ch].dqs_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001725 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_EN, 0x01);
1726 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE0,
Marek Vasut38dc7562019-08-07 19:17:42 +02001727 (data_l) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001728 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE1,
Marek Vasut38dc7562019-08-07 19:17:42 +02001729 (data_l >> 4 * 1) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001730 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE2,
Marek Vasut38dc7562019-08-07 19:17:42 +02001731 (data_l >> 4 * 2) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001732 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE3,
Marek Vasut38dc7562019-08-07 19:17:42 +02001733 (data_l >> 4 * 3) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001734
1735 ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL_HIGH, 0x00);
1736 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001737 ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001738 }
1739}
1740
Marek Vasut80784f92019-08-07 19:02:26 +02001741static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001742{
1743 uint32_t slice;
1744 uint32_t tmp;
1745 uint32_t tgt;
Marek Vasut80784f92019-08-07 19:02:26 +02001746
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001747 if (ddr_csn / 2) {
1748 tgt = 3;
1749 } else {
1750 tgt = 1;
1751 }
1752
1753 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001754 tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001755 if (tgt == tmp)
1756 break;
1757 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001758 tmp = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001759 if (slice % 2)
1760 tmp |= 0x00888888;
1761 *p_swz = tmp;
1762}
1763
1764static void ddr_config_sub_h3v1x(void)
1765{
1766 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001767 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001768 uint32_t tmp;
1769 uint8_t high_byte[SLICE_CNT];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001770 uint32_t ca_swizzle;
1771 uint32_t ca;
1772 uint32_t csmap;
1773 uint32_t o_inv;
1774 uint32_t inv;
1775 uint32_t bit_soc;
1776 uint32_t bit_mem;
1777 uint32_t j;
1778
1779 const uint8_t o_mr15 = 0x55;
1780 const uint8_t o_mr20 = 0x55;
1781 const uint16_t o_mr32_mr40 = 0x5a3c;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001782
1783 foreach_vch(ch) {
Marek Vasut6a131772019-08-07 19:56:09 +02001784 /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001785 csmap = 0;
1786 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001787 tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) &
1788 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001789 high_byte[slice] = tmp % 2;
1790 if (tmp == 1 && (slice >= 2))
1791 csmap |= 0x05;
1792 if (tmp == 3 && (slice >= 2))
1793 csmap |= 0x50;
1794 ddr_setval_s(ch, slice, _reg_PHY_DQ_SWIZZLING,
Marek Vasut38dc7562019-08-07 19:17:42 +02001795 board_cnf->ch[ch].dq_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001796 if (high_byte[slice]) {
1797 /* HIGHER 16 BYTE */
1798 ddr_setval_s(ch, slice,
1799 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1800 0x00);
1801 } else {
1802 /* LOWER 16 BYTE */
1803 ddr_setval_s(ch, slice,
1804 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1805 0x01);
1806 }
1807 }
Marek Vasut6a131772019-08-07 19:56:09 +02001808 /* BOARD SETTINGS (CA,ADDR_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001809 ca = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001810 ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, ca);
1811 ddr_setval(ch, _reg_PHY_CALVL_CS_MAP, csmap);
1812
1813 get_ca_swizzle(ch, 0, &ca_swizzle);
1814
1815 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, ca_swizzle);
1816 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0, 0x00000000);
1817 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, 0x00000000);
1818 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1, 0x00000000);
1819 ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP, 0x01);
1820
1821 for (slice = 0; slice < SLICE_CNT; slice++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001822 ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_NUM,
1823 0x01);
1824 ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_START,
1825 0x08);
1826
1827 if (high_byte[slice])
1828 o_inv = o_mr20;
1829 else
1830 o_inv = o_mr15;
1831
Marek Vasut38dc7562019-08-07 19:17:42 +02001832 tmp = board_cnf->ch[ch].dq_swap[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001833 inv = 0;
1834 j = 0;
1835 for (bit_soc = 0; bit_soc < 8; bit_soc++) {
1836 bit_mem = (tmp >> (4 * bit_soc)) & 0x0f;
1837 j |= (1U << bit_mem);
1838 if (o_inv & (1U << bit_mem))
1839 inv |= (1U << bit_soc);
1840 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001841 data_l = o_mr32_mr40;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001842 if (!high_byte[slice])
Marek Vasut38dc7562019-08-07 19:17:42 +02001843 data_l |= (inv << 24);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001844 if (high_byte[slice])
Marek Vasut38dc7562019-08-07 19:17:42 +02001845 data_l |= (inv << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001846 ddr_setval_s(ch, slice, _reg_PHY_LP4_RDLVL_PATT8,
Marek Vasut38dc7562019-08-07 19:17:42 +02001847 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001848 }
1849 }
1850}
1851
1852static void ddr_config(void)
1853{
1854 int32_t i;
1855 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001856 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001857 uint32_t tmp;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001858 int8_t _adj;
1859 int16_t adj;
1860 uint32_t dq;
1861 union {
1862 uint32_t ui32[4];
1863 uint8_t ui8[16];
1864 } patt;
1865 uint16_t patm;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001866
Marek Vasut6a131772019-08-07 19:56:09 +02001867 /* configure ddrphy registers */
Marek Vasut38dc7562019-08-07 19:17:42 +02001868 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001869 ddr_config_sub_h3v1x();
Marek Vasut6ad74c32019-08-08 16:34:22 +02001870 } else { /* H3 Ver.2.0 or later/M3-N/V3H is same as M3-W */
1871 ddr_config_sub();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001872 }
1873
Marek Vasut6a131772019-08-07 19:56:09 +02001874 /* WDQ_USER_PATT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001875 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001876 for (slice = 0; slice < SLICE_CNT; slice++) {
1877 patm = 0;
1878 for (i = 0; i < 16; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001879 tmp = board_cnf->ch[ch].wdqlvl_patt[i];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001880 patt.ui8[i] = tmp & 0xff;
1881 if (tmp & 0x100)
1882 patm |= (1U << i);
1883 }
1884 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT0,
1885 patt.ui32[0]);
1886 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT1,
1887 patt.ui32[1]);
1888 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT2,
1889 patt.ui32[2]);
1890 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT3,
1891 patt.ui32[3]);
1892 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT4, patm);
1893 }
1894 }
1895
Marek Vasut6a131772019-08-07 19:56:09 +02001896 /* CACS DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001897 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001898 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
1899 0x00U);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001900 foreach_vch(ch) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001901 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001902 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001903 ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET,
1904 _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001905 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001906 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001907 ddr_regdef_adr
1908 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]),
1909 _cnf_DDR_PHY_ADR_V_REGSET
1910 [ddr_regdef_adr
1911 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001912 DDR_PHY_ADR_V_REGSET_OFS]);
1913 }
1914
1915 for (i = (_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4);
1916 i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001917 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001918 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1919 _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001920 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001921 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001922 ddr_regdef_adr
1923 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]),
1924 _cnf_DDR_PHY_ADR_G_REGSET
1925 [ddr_regdef_adr
1926 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001927 DDR_PHY_ADR_G_REGSET_OFS]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001928 }
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001929
Marek Vasut6c245a52018-12-12 18:06:39 +01001930 if (ddr_phycaslice == 1) {
1931 for (i = 0; i < 6; i++) {
Marek Vasut6a131772019-08-07 19:56:09 +02001932 adj = _f_scale_adj
1933 (board_cnf->ch[ch].cacs_adj
1934 [i +
1935 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001936 ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET,
Marek Vasut6ad74c32019-08-08 16:34:22 +02001937 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
1938 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001939 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001940 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001941 ddr_regdef_adr
1942 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) +
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001943 0x0100,
Marek Vasut6a131772019-08-07 19:56:09 +02001944 _cnf_DDR_PHY_ADR_V_REGSET
1945 [ddr_regdef_adr
1946 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001947 DDR_PHY_ADR_V_REGSET_OFS]);
Marek Vasut6c245a52018-12-12 18:06:39 +01001948 }
1949 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001950 }
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001951
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001952 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
Marek Vasut6ad74c32019-08-08 16:34:22 +02001953 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001954
Marek Vasut6a131772019-08-07 19:56:09 +02001955 /* WDQDM DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001956 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001957 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001958 for (slice = 0; slice < SLICE_CNT; slice++) {
1959 for (i = 0; i <= 8; i++) {
1960 dq = slice * 8 + i;
1961 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02001962 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001963 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001964 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001965 adj = _f_scale_adj(_adj);
1966 ddr_setval_s(ch, slice,
1967 _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001968 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001969 }
1970 }
1971 }
1972
Marek Vasut6a131772019-08-07 19:56:09 +02001973 /* RDQDM DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001974 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001975 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001976 for (slice = 0; slice < SLICE_CNT; slice++) {
1977 for (i = 0; i <= 8; i++) {
1978 dq = slice * 8 + i;
1979 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02001980 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001981 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001982 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001983 adj = _f_scale_adj(_adj);
1984 ddr_setval_s(ch, slice,
1985 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY
Marek Vasut38dc7562019-08-07 19:17:42 +02001986 [i], data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001987 ddr_setval_s(ch, slice,
1988 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
Marek Vasut38dc7562019-08-07 19:17:42 +02001989 [i], data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001990 }
1991 }
1992 }
1993}
1994
Marek Vasut6a131772019-08-07 19:56:09 +02001995/* DBSC register setting functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001996static void dbsc_regset_pre(void)
1997{
1998 uint32_t ch, csab;
Marek Vasut38dc7562019-08-07 19:17:42 +02001999 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002000
Marek Vasut6a131772019-08-07 19:56:09 +02002001 /* PRIMARY SETTINGS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002002 /* LPDDR4, BL=16, DFI interface */
2003 mmio_write_32(DBSC_DBKIND, 0x0000000a);
2004 mmio_write_32(DBSC_DBBL, 0x00000002);
2005 mmio_write_32(DBSC_DBPHYCONF0, 0x00000001);
2006
2007 /* FREQRATIO=2 */
2008 mmio_write_32(DBSC_DBSYSCONF1, 0x00000002);
2009
2010 /* Chanel map (H3 Ver.1.x) */
Marek Vasut38dc7562019-08-07 19:17:42 +02002011 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002012 mmio_write_32(DBSC_DBSCHCNT1, 0x00001010);
2013
2014 /* DRAM SIZE REGISTER:
2015 * set all ranks as density=0(4Gb) for PHY initialization
2016 */
Marek Vasut6ad74c32019-08-08 16:34:22 +02002017 foreach_vch(ch) {
2018 for (csab = 0; csab < 4; csab++) {
2019 mmio_write_32(DBSC_DBMEMCONF(ch, csab),
2020 DBMEMCONF_REGD(0));
2021 }
2022 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002023
Marek Vasut38dc7562019-08-07 19:17:42 +02002024 if (prr_product == PRR_PRODUCT_M3) {
2025 data_l = 0xe4e4e4e4;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002026 foreach_ech(ch) {
2027 if ((ddr_phyvalid & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02002028 data_l = (data_l & (~(0x000000FF << (ch * 8))))
2029 | (((board_cnf->ch[ch].dqs_swap & 0x0003)
2030 | ((board_cnf->ch[ch].dqs_swap & 0x0030)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002031 >> 2)
Marek Vasut38dc7562019-08-07 19:17:42 +02002032 | ((board_cnf->ch[ch].dqs_swap & 0x0300)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002033 >> 4)
Marek Vasut38dc7562019-08-07 19:17:42 +02002034 | ((board_cnf->ch[ch].dqs_swap & 0x3000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002035 >> 6)) << (ch * 8));
2036 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002037 mmio_write_32(DBSC_DBBSWAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002038 }
2039}
2040
2041static void dbsc_regset(void)
2042{
2043 int32_t i;
2044 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002045 uint32_t data_l;
2046 uint32_t data_l2;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002047 uint32_t tmp[4];
2048
2049 /* RFC */
Marek Vasut6a131772019-08-07 19:56:09 +02002050 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_20) &&
2051 (max_density == 0)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002052 js2[js2_trfcab] =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002053 _f_scale(ddr_mbps, ddr_mbpsdiv,
Marek Vasut38dc7562019-08-07 19:17:42 +02002054 1UL * jedec_spec2_trfc_ab[1] * 1000, 0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002055 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002056 js2[js2_trfcab] =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002057 _f_scale(ddr_mbps, ddr_mbpsdiv,
Marek Vasut38dc7562019-08-07 19:17:42 +02002058 1UL * jedec_spec2_trfc_ab[max_density] *
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002059 1000, 0);
2060 }
2061
2062 /* DBTR0.CL : RL */
2063 mmio_write_32(DBSC_DBTR(0), RL);
2064
2065 /* DBTR1.CWL : WL */
2066 mmio_write_32(DBSC_DBTR(1), WL);
2067
2068 /* DBTR2.AL : 0 */
2069 mmio_write_32(DBSC_DBTR(2), 0);
2070
2071 /* DBTR3.TRCD: tRCD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002072 mmio_write_32(DBSC_DBTR(3), js2[js2_trcd]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002073
2074 /* DBTR4.TRPA,TRP: tRPab,tRPpb */
Marek Vasut38dc7562019-08-07 19:17:42 +02002075 mmio_write_32(DBSC_DBTR(4), (js2[js2_trpab] << 16) | js2[js2_trppb]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002076
2077 /* DBTR5.TRC : use tRCpb */
Marek Vasut38dc7562019-08-07 19:17:42 +02002078 mmio_write_32(DBSC_DBTR(5), js2[js2_trcpb]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002079
2080 /* DBTR6.TRAS : tRAS */
Marek Vasut38dc7562019-08-07 19:17:42 +02002081 mmio_write_32(DBSC_DBTR(6), js2[js2_tras]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002082
2083 /* DBTR7.TRRD : tRRD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002084 mmio_write_32(DBSC_DBTR(7), (js2[js2_trrd] << 16) | js2[js2_trrd]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002085
2086 /* DBTR8.TFAW : tFAW */
Marek Vasut38dc7562019-08-07 19:17:42 +02002087 mmio_write_32(DBSC_DBTR(8), js2[js2_tfaw]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002088
2089 /* DBTR9.TRDPR : tRTP */
Marek Vasut38dc7562019-08-07 19:17:42 +02002090 mmio_write_32(DBSC_DBTR(9), js2[js2_trtp]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002091
Chiaki Fujii82e9c412019-12-26 12:57:40 +09002092 /* DBTR10.TWR : nWR */
2093 mmio_write_32(DBSC_DBTR(10), js1[js1_ind].nwr);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002094
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002095 /*
2096 * DBTR11.TRDWR : RL + BL / 2 + Rounddown(tRPST) + PHY_ODTLoff -
2097 * odtlon + tDQSCK - tODTon,min +
2098 * PCB delay (out+in) + tPHY_ODToff
2099 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002100 mmio_write_32(DBSC_DBTR(11),
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002101 RL + (16 / 2) + 1 + 2 - js1[js1_ind].odtlon +
2102 js2[js2_tdqsck] - js2[js2_tODTon_min] +
2103 _f_scale(ddr_mbps, ddr_mbpsdiv, 1300, 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002104
2105 /* DBTR12.TWRRD : WL + 1 + BL/2 + tWTR */
Marek Vasut38dc7562019-08-07 19:17:42 +02002106 data_l = WL + 1 + (16 / 2) + js2[js2_twtr];
2107 mmio_write_32(DBSC_DBTR(12), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002108
Marek Vasut6c245a52018-12-12 18:06:39 +01002109 /* DBTR13.TRFCAB : tRFCab */
Marek Vasut38dc7562019-08-07 19:17:42 +02002110 mmio_write_32(DBSC_DBTR(13), (js2[js2_trfcab]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002111
2112 /* DBTR14.TCKEHDLL,tCKEH : tCKEHCMD,tCKEHCMD */
2113 mmio_write_32(DBSC_DBTR(14),
Marek Vasut38dc7562019-08-07 19:17:42 +02002114 (js2[js2_tckehcmd] << 16) | (js2[js2_tckehcmd]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002115
2116 /* DBTR15.TCKESR,TCKEL : tSR,tCKELPD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002117 mmio_write_32(DBSC_DBTR(15), (js2[js2_tsr] << 16) | (js2[js2_tckelpd]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002118
2119 /* DBTR16 */
2120 /* WDQL : tphy_wrlat + tphy_wrdata */
2121 tmp[0] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1);
Marek Vasut3af20052019-02-25 14:57:08 +01002122 /* DQENLTNCY : tphy_wrlat = WL-2 : PHY_WRITE_PATH_LAT_ADD == 0
2123 * tphy_wrlat = WL-3 : PHY_WRITE_PATH_LAT_ADD != 0
2124 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002125 tmp[1] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1);
2126 /* DQL : tphy_rdlat + trdata_en */
2127 /* it is not important for dbsc */
2128 tmp[2] = RL + 16;
2129 /* DQIENLTNCY : trdata_en */
2130 tmp[3] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1) - 1;
2131 mmio_write_32(DBSC_DBTR(16),
2132 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2133
2134 /* DBTR24 */
2135 /* WRCSLAT = WRLAT -5 */
2136 tmp[0] -= 5;
2137 /* WRCSGAP = 5 */
2138 tmp[1] = 5;
2139 /* RDCSLAT = RDLAT_ADJ +2 */
Marek Vasut38dc7562019-08-07 19:17:42 +02002140 if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6c245a52018-12-12 18:06:39 +01002141 tmp[2] = tmp[3];
2142 } else {
2143 tmp[2] = tmp[3] + 2;
2144 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002145 /* RDCSGAP = 6 */
Marek Vasut38dc7562019-08-07 19:17:42 +02002146 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002147 tmp[3] = 4;
2148 } else {
2149 tmp[3] = 6;
2150 }
2151 mmio_write_32(DBSC_DBTR(24),
2152 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2153
2154 /* DBTR17.TMODRD,TMOD,TRDMR: tMRR,tMRD,(0) */
2155 mmio_write_32(DBSC_DBTR(17),
Marek Vasut38dc7562019-08-07 19:17:42 +02002156 (js2[js2_tmrr] << 24) | (js2[js2_tmrd] << 16));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002157
2158 /* DBTR18.RODTL, RODTA, WODTL, WODTA : do not use in LPDDR4 */
2159 mmio_write_32(DBSC_DBTR(18), 0);
2160
2161 /* DBTR19.TZQCL, TZQCS : do not use in LPDDR4 */
2162 mmio_write_32(DBSC_DBTR(19), 0);
2163
2164 /* DBTR20.TXSDLL, TXS : tRFCab+tCKEHCMD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002165 data_l = js2[js2_trfcab] + js2[js2_tckehcmd];
2166 mmio_write_32(DBSC_DBTR(20), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002167
2168 /* DBTR21.TCCD */
2169 /* DBTR23.TCCD */
2170 /* H3 Ver.1.0 cannot use TBTR23 feature */
2171 if (ddr_tccd == 8 &&
Marek Vasut38dc7562019-08-07 19:17:42 +02002172 !((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_10))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002173 ) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002174 data_l = 8;
2175 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002176 mmio_write_32(DBSC_DBTR(23), 0x00000002);
2177 } else if (ddr_tccd <= 11) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002178 data_l = 11;
2179 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002180 mmio_write_32(DBSC_DBTR(23), 0x00000000);
2181 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002182 data_l = ddr_tccd;
2183 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002184 mmio_write_32(DBSC_DBTR(23), 0x00000000);
2185 }
2186
2187 /* DBTR22.ZQLAT : */
Marek Vasut38dc7562019-08-07 19:17:42 +02002188 data_l = js2[js2_tzqcalns] * 100; /* 1000 * 1000 ps */
2189 data_l = (data_l << 16) | (js2[js2_tzqlat] + 24 + 20);
2190 mmio_write_32(DBSC_DBTR(22), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002191
2192 /* DBTR25 : do not use in LPDDR4 */
2193 mmio_write_32(DBSC_DBTR(25), 0);
2194
2195 /* DBRNK : */
2196 /*
2197 * DBSC_DBRNK2 rkrr
2198 * DBSC_DBRNK3 rkrw
2199 * DBSC_DBRNK4 rkwr
2200 * DBSC_DBRNK5 rkww
2201 */
2202#define _par_DBRNK_VAL (0x7007)
2203
2204 for (i = 0; i < 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002205 data_l = (_par_DBRNK_VAL >> (i * 4)) & 0x0f;
Marek Vasut6a131772019-08-07 19:56:09 +02002206 if ((prr_product == PRR_PRODUCT_H3) &&
2207 (prr_cut > PRR_PRODUCT_11) && (i == 0)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002208 data_l += 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002209 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002210 data_l2 = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002211 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002212 data_l2 = data_l2 | (data_l << (4 * ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002213 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002214 mmio_write_32(DBSC_DBRNK(2 + i), data_l2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002215 }
2216 mmio_write_32(DBSC_DBADJ0, 0x00000000);
2217
Marek Vasut6a131772019-08-07 19:56:09 +02002218 /* timing registers for Scheduler */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002219 /* SCFCTST0 */
2220 /* SCFCTST0 ACT-ACT */
Marek Vasut38dc7562019-08-07 19:17:42 +02002221 tmp[3] = 1UL * js2[js2_trcpb] * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002222 /* SCFCTST0 RDA-ACT */
2223 tmp[2] =
Marek Vasut38dc7562019-08-07 19:17:42 +02002224 1UL * ((16 / 2) + js2[js2_trtp] - 8 +
2225 js2[js2_trppb]) * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002226 /* SCFCTST0 WRA-ACT */
2227 tmp[1] =
2228 1UL * (WL + 1 + (16 / 2) +
Marek Vasut38dc7562019-08-07 19:17:42 +02002229 js1[js1_ind].nwr) * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002230 /* SCFCTST0 PRE-ACT */
Marek Vasut38dc7562019-08-07 19:17:42 +02002231 tmp[0] = 1UL * js2[js2_trppb];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002232 mmio_write_32(DBSC_SCFCTST0,
2233 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2234
2235 /* SCFCTST1 */
2236 /* SCFCTST1 RD-WR */
2237 tmp[3] =
2238 1UL * (mmio_read_32(DBSC_DBTR(11)) & 0xff) * 800 * ddr_mbpsdiv /
2239 ddr_mbps;
2240 /* SCFCTST1 WR-RD */
2241 tmp[2] =
2242 1UL * (mmio_read_32(DBSC_DBTR(12)) & 0xff) * 800 * ddr_mbpsdiv /
2243 ddr_mbps;
2244 /* SCFCTST1 ACT-RD/WR */
Marek Vasut38dc7562019-08-07 19:17:42 +02002245 tmp[1] = 1UL * js2[js2_trcd] * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002246 /* SCFCTST1 ASYNCOFS */
2247 tmp[0] = 12;
2248 mmio_write_32(DBSC_SCFCTST1,
2249 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2250
2251 /* DBSCHRW1 */
2252 /* DBSCHRW1 SCTRFCAB */
Marek Vasut38dc7562019-08-07 19:17:42 +02002253 tmp[0] = 1UL * js2[js2_trfcab] * 800 * ddr_mbpsdiv / ddr_mbps;
2254 data_l = (((mmio_read_32(DBSC_DBTR(16)) & 0x00FF0000) >> 16)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002255 + (mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
2256 + (0x28 * 2)) * 400 * 2 * ddr_mbpsdiv / ddr_mbps + 7;
Marek Vasut38dc7562019-08-07 19:17:42 +02002257 if (tmp[0] < data_l)
2258 tmp[0] = data_l;
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002259
Marek Vasut38dc7562019-08-07 19:17:42 +02002260 if ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30)) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002261 mmio_write_32(DBSC_DBSCHRW1, tmp[0]
2262 + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
Marek Vasut6ad74c32019-08-08 16:34:22 +02002263 * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) /
2264 ddr_mbps - 3);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002265 } else {
2266 mmio_write_32(DBSC_DBSCHRW1, tmp[0]
2267 + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
Marek Vasut6ad74c32019-08-08 16:34:22 +02002268 * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) /
2269 ddr_mbps);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002270 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002271
Marek Vasut6a131772019-08-07 19:56:09 +02002272 /* QOS and CAM */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002273#ifdef ddr_qos_init_setting /* only for non qos_init */
2274 /*wbkwait(0004), wbkmdhi(4,2),wbkmdlo(1,8) */
2275 mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218);
2276 /*0(fillunit),8(dirtymax),4(dirtymin) */
2277 mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4);
2278 /*stop_tolerance */
2279 mmio_write_32(DBSC_DBSCHRW0, 0x22421111);
2280 /*rd-wr/wr-rd toggle priority */
2281 mmio_write_32(DBSC_SCFCTST2, 0x012F1123);
2282 mmio_write_32(DBSC_DBSCHSZ0, 0x00000001);
2283 mmio_write_32(DBSC_DBSCHCNT0, 0x000F0037);
2284
2285 /* QoS Settings */
2286 mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00U);
2287 mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00U);
2288 mmio_write_32(DBSC_DBSCHQOS02, 0x00000000U);
2289 mmio_write_32(DBSC_DBSCHQOS03, 0x00000000U);
2290 mmio_write_32(DBSC_DBSCHQOS40, 0x00000300U);
2291 mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0U);
2292 mmio_write_32(DBSC_DBSCHQOS42, 0x00000200U);
2293 mmio_write_32(DBSC_DBSCHQOS43, 0x00000100U);
2294 mmio_write_32(DBSC_DBSCHQOS90, 0x00000100U);
2295 mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0U);
2296 mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0U);
2297 mmio_write_32(DBSC_DBSCHQOS93, 0x00000040U);
2298 mmio_write_32(DBSC_DBSCHQOS120, 0x00000040U);
2299 mmio_write_32(DBSC_DBSCHQOS121, 0x00000030U);
2300 mmio_write_32(DBSC_DBSCHQOS122, 0x00000020U);
2301 mmio_write_32(DBSC_DBSCHQOS123, 0x00000010U);
2302 mmio_write_32(DBSC_DBSCHQOS130, 0x00000100U);
2303 mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0U);
2304 mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0U);
2305 mmio_write_32(DBSC_DBSCHQOS133, 0x00000040U);
2306 mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0U);
2307 mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0U);
2308 mmio_write_32(DBSC_DBSCHQOS142, 0x00000080U);
2309 mmio_write_32(DBSC_DBSCHQOS143, 0x00000040U);
2310 mmio_write_32(DBSC_DBSCHQOS150, 0x00000040U);
2311 mmio_write_32(DBSC_DBSCHQOS151, 0x00000030U);
2312 mmio_write_32(DBSC_DBSCHQOS152, 0x00000020U);
2313 mmio_write_32(DBSC_DBSCHQOS153, 0x00000010U);
2314
2315 mmio_write_32(QOSCTRL_RAEN, 0x00000001U);
2316#endif /* ddr_qos_init_setting */
2317 /* H3 Ver.1.1 need to set monitor function */
Marek Vasut38dc7562019-08-07 19:17:42 +02002318 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002319 mmio_write_32(DBSC_DBMONCONF4, 0x00700000);
2320 }
2321
Marek Vasut38dc7562019-08-07 19:17:42 +02002322 if (prr_product == PRR_PRODUCT_H3) {
2323 if (prr_cut == PRR_PRODUCT_10) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002324 /* resrdis, simple mode, sc off */
2325 mmio_write_32(DBSC_DBBCAMDIS, 0x00000007);
Marek Vasut38dc7562019-08-07 19:17:42 +02002326 } else if (prr_cut == PRR_PRODUCT_11) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002327 /* resrdis, simple mode */
2328 mmio_write_32(DBSC_DBBCAMDIS, 0x00000005);
Marek Vasut38dc7562019-08-07 19:17:42 +02002329 } else if (prr_cut < PRR_PRODUCT_30) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002330 /* H3 Ver.2.0 */
2331 /* resrdis */
2332 mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
2333 } else { /* H3 Ver.3.0(include H3N) */
2334 /* exprespque */
2335 mmio_write_32(DBSC_DBBCAMDIS, 0x00000010);
2336 }
2337 } else { /* M3-W/M3-N/V3H */
2338 /* resrdis */
2339 mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
2340 }
2341}
2342
2343static void dbsc_regset_post(void)
2344{
2345 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02002346 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002347 uint32_t slice, rdlat_max, rdlat_min;
2348
2349 rdlat_max = 0;
2350 rdlat_min = 0xffff;
2351 foreach_vch(ch) {
2352 for (cs = 0; cs < CS_CNT; cs++) {
2353 if ((ch_have_this_cs[cs] & (1U << ch)) != 0) {
2354 for (slice = 0; slice < SLICE_CNT; slice++) {
2355 ddr_setval_s(ch, slice,
2356 _reg_PHY_PER_CS_TRAINING_INDEX,
2357 cs);
Marek Vasut6ad74c32019-08-08 16:34:22 +02002358 data_l = ddr_getval_s(ch, slice,
2359 _reg_PHY_RDDQS_LATENCY_ADJUST);
Marek Vasut38dc7562019-08-07 19:17:42 +02002360 if (data_l > rdlat_max)
2361 rdlat_max = data_l;
2362 if (data_l < rdlat_min)
2363 rdlat_min = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002364 }
2365 }
2366 }
2367 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002368 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) {
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002369#if RCAR_DRAM_SPLIT == 2
2370 if (board_cnf->phyvalid == 0x05) {
2371 mmio_write_32(DBSC_DBTR(24),
2372 (rdlat_max << 24) + (rdlat_min << 16) +
2373 mmio_read_32(DBSC_DBTR(24)));
2374 } else {
2375 mmio_write_32(DBSC_DBTR(24),
2376 ((rdlat_max * 2 - rdlat_min + 4) << 24) +
2377 ((rdlat_min + 2) << 16) +
2378 mmio_read_32(DBSC_DBTR(24)));
2379 }
2380#else /*RCAR_DRAM_SPLIT == 2 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002381 mmio_write_32(DBSC_DBTR(24),
2382 ((rdlat_max * 2 - rdlat_min + 4) << 24) +
2383 ((rdlat_min + 2) << 16) +
2384 mmio_read_32(DBSC_DBTR(24)));
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002385#endif /*RCAR_DRAM_SPLIT == 2 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002386 } else {
2387 mmio_write_32(DBSC_DBTR(24),
2388 ((rdlat_max + 2) << 24) +
2389 ((rdlat_max + 2) << 16) +
2390 mmio_read_32(DBSC_DBTR(24)));
2391 }
2392
2393 /* set ddr density information */
2394 foreach_ech(ch) {
2395 for (cs = 0; cs < CS_CNT; cs++) {
2396 if (ddr_density[ch][cs] == 0xff) {
2397 mmio_write_32(DBSC_DBMEMCONF(ch, cs), 0x00);
2398 } else {
2399 mmio_write_32(DBSC_DBMEMCONF(ch, cs),
2400 DBMEMCONF_REGD(ddr_density[ch]
2401 [cs]));
2402 }
2403 }
2404 mmio_write_32(DBSC_DBMEMCONF(ch, 2), 0x00000000);
2405 mmio_write_32(DBSC_DBMEMCONF(ch, 3), 0x00000000);
2406 }
2407
2408 mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010);
2409
2410 /*set DBI */
Marek Vasut38dc7562019-08-07 19:17:42 +02002411 if (board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002412 mmio_write_32(DBSC_DBDBICNT, 0x00000003);
2413
2414 /* H3 Ver.2.0 or later/M3-N/V3H DBI wa */
Marek Vasut6a131772019-08-07 19:56:09 +02002415 if ((((prr_product == PRR_PRODUCT_H3) &&
2416 (prr_cut > PRR_PRODUCT_11)) ||
2417 (prr_product == PRR_PRODUCT_M3N) ||
2418 (prr_product == PRR_PRODUCT_V3H)) &&
2419 board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002420 reg_ddrphy_write_a(0x00001010, 0x01000000);
2421
2422 /*set REFCYCLE */
Marek Vasut38dc7562019-08-07 19:17:42 +02002423 data_l = (get_refperiod()) * ddr_mbps / 2000 / ddr_mbpsdiv;
2424 mmio_write_32(DBSC_DBRFCNF1, 0x00080000 | (data_l & 0x0000ffff));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002425 mmio_write_32(DBSC_DBRFCNF2, 0x00010000 | DBSC_REFINTS);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002426
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002427#if RCAR_REWT_TRAINING != 0
2428 /* Periodic-WriteDQ Training seeting */
Marek Vasut6a131772019-08-07 19:56:09 +02002429 if (((prr_product == PRR_PRODUCT_H3) &&
2430 (prr_cut <= PRR_PRODUCT_11)) ||
2431 ((prr_product == PRR_PRODUCT_M3) &&
2432 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002433 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2434 } else {
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002435 /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002436 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000);
2437
2438 ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04);
2439 ddr_setval_ach_as(_reg_PHY_WDQLVL_QTR_DLY_STEP, 0x0F);
2440 ddr_setval_ach_as(_reg_PHY_WDQLVL_DLY_STEP, 0x50);
2441 ddr_setval_ach_as(_reg_PHY_WDQLVL_DQDM_SLV_DLY_START, 0x0300);
2442
2443 ddr_setval_ach(_reg_PI_WDQLVL_CS_MAP,
2444 ddrtbl_getval(_cnf_DDR_PI_REGSET,
2445 _reg_PI_WDQLVL_CS_MAP));
2446 ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f);
2447 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002448 ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01);
2449 ddr_setval_ach(_reg_PI_TREF_F0, 0x0000);
2450 ddr_setval_ach(_reg_PI_TREF_F1, 0x0000);
2451 ddr_setval_ach(_reg_PI_TREF_F2, 0x0000);
2452
Marek Vasut38dc7562019-08-07 19:17:42 +02002453 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002454 ddr_setval_ach(_reg_PI_WDQLVL_EN, 0x02);
2455 } else {
2456 ddr_setval_ach(_reg_PI_WDQLVL_EN_F1, 0x02);
2457 }
2458 ddr_setval_ach(_reg_PI_WDQLVL_PERIODIC, 0x01);
2459
2460 /* DFI_PHYMSTR_ACK , WTmode setting */
Marek Vasut6ad74c32019-08-08 16:34:22 +02002461 /* DFI_PHYMSTR_ACK: WTmode =b'01 */
2462 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002463 }
2464#endif /* RCAR_REWT_TRAINING */
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002465 /* periodic dram zqcal enable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002466 mmio_write_32(DBSC_DBCALCNF, 0x01000010);
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002467
2468 /* periodic phy ctrl update enable */
Marek Vasut6a131772019-08-07 19:56:09 +02002469 if (((prr_product == PRR_PRODUCT_H3) &&
2470 (prr_cut <= PRR_PRODUCT_11)) ||
2471 ((prr_product == PRR_PRODUCT_M3) &&
2472 (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002473 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
2474 } else {
2475#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02002476 if ((prr_product == PRR_PRODUCT_H3) &&
2477 (board_cnf->phyvalid == 0x05))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002478 mmio_write_32(DBSC_DBDFICUPDCNF, 0x2a240001);
2479 else
2480 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2481#else /* RCAR_DRAM_SPLIT == 2 */
2482 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2483#endif /* RCAR_DRAM_SPLIT == 2 */
2484 }
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002485
2486#ifdef DDR_BACKUPMODE
2487 /* SRX */
2488 if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
2489#ifdef DDR_BACKUPMODE_HALF /* for Half channel(ch0, 1 only) */
2490 NOTICE("BL2: [DEBUG_MESS] DDR_BACKUPMODE_HALF\n");
2491 send_dbcmd(0x0A040001);
2492 if (Prr_Product == PRR_PRODUCT_H3)
2493 send_dbcmd(0x0A140001);
2494#else /* DDR_BACKUPMODE_HALF */ /* for All channels */
2495 send_dbcmd(0x0A840001);
2496#endif /* DDR_BACKUPMODE_HALF */
2497 }
2498#endif /* DDR_BACKUPMODE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002499
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002500 /* set Auto Refresh */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002501 mmio_write_32(DBSC_DBRFEN, 0x00000001);
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002502
2503#if RCAR_REWT_TRAINING != 0
2504 /* Periodic WriteDQ Traning */
2505 if (((prr_product == PRR_PRODUCT_H3) &&
2506 (prr_cut <= PRR_PRODUCT_11)) ||
2507 ((prr_product == PRR_PRODUCT_M3) &&
2508 (prr_cut == PRR_PRODUCT_10))) {
2509 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2510 } else {
2511 /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
2512 ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
2513 }
2514#endif /* RCAR_REWT_TRAINING */
2515
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002516 /* dram access enable */
2517 mmio_write_32(DBSC_DBACEN, 0x00000001);
2518
Marek Vasut6ad74c32019-08-08 16:34:22 +02002519 MSG_LF(__func__ "(done)");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002520}
2521
Marek Vasut6a131772019-08-07 19:56:09 +02002522/* DFI_INIT_START */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002523static uint32_t dfi_init_start(void)
2524{
2525 uint32_t ch;
2526 uint32_t phytrainingok;
2527 uint32_t retry;
Marek Vasut38dc7562019-08-07 19:17:42 +02002528 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002529 const uint32_t RETRY_MAX = 0x10000;
2530
Marek Vasut38dc7562019-08-07 19:17:42 +02002531 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002532 /* PLL3 Disable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002533 /* protect register interface */
2534 ddrphy_regif_idle();
2535
2536 pll3_control(0);
2537
Marek Vasut6a131772019-08-07 19:56:09 +02002538 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002539 /* dbdficnt0:
2540 * dfi_dram_clk_disable=1
2541 * dfi_frequency = 0
2542 * freq_ratio = 01 (2:1)
2543 * init_start =0
2544 */
2545 foreach_vch(ch)
2546 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
2547 dsb_sev();
2548
2549 /* dbdficnt0:
2550 * dfi_dram_clk_disable=1
2551 * dfi_frequency = 0
2552 * freq_ratio = 01 (2:1)
2553 * init_start =1
2554 */
2555 foreach_vch(ch)
2556 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
2557 dsb_sev();
2558
2559 } else {
2560 ddr_setval_ach_as(_reg_PHY_DLL_RST_EN, 0x02);
2561 dsb_sev();
2562 ddrphy_regif_idle();
2563 }
2564
2565 /* dll_rst negate */
2566 foreach_vch(ch)
2567 mmio_write_32(DBSC_DBPDCNT3(ch), 0x0000CF01);
2568 dsb_sev();
2569
Marek Vasut6a131772019-08-07 19:56:09 +02002570 /* wait init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002571 phytrainingok = 0;
2572 retry = 0;
2573 while (retry++ < RETRY_MAX) {
2574 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002575 data_l = mmio_read_32(DBSC_DBDFISTAT(ch));
2576 if (data_l & 0x00000001)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002577 phytrainingok |= (1U << ch);
2578 }
2579 dsb_sev();
2580 if (phytrainingok == ddr_phyvalid)
2581 break;
2582 if (retry % 256 == 0)
2583 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
2584 }
2585
Marek Vasut6a131772019-08-07 19:56:09 +02002586 /* all ch ok? */
2587 if ((phytrainingok & ddr_phyvalid) != ddr_phyvalid)
2588 return 0xff;
2589
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002590 /* dbdficnt0:
2591 * dfi_dram_clk_disable=0
2592 * dfi_frequency = 0
2593 * freq_ratio = 01 (2:1)
2594 * init_start =0
2595 */
2596 foreach_vch(ch)
2597 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000010);
2598 dsb_sev();
2599
2600 return 0;
2601}
2602
Marek Vasut6a131772019-08-07 19:56:09 +02002603/* drivablity setting : CMOS MODE ON/OFF */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002604static void change_lpddr4_en(uint32_t mode)
2605{
2606 uint32_t ch;
2607 uint32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002608 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002609 const uint32_t _reg_PHY_PAD_DRIVE_X[3] = {
2610 _reg_PHY_PAD_ADDR_DRIVE,
2611 _reg_PHY_PAD_CLK_DRIVE,
2612 _reg_PHY_PAD_CS_DRIVE
2613 };
2614
Marek Vasut6c245a52018-12-12 18:06:39 +01002615 foreach_vch(ch) {
2616 for (i = 0; i < 3; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002617 data_l = ddr_getval(ch, _reg_PHY_PAD_DRIVE_X[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002618 if (mode) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002619 data_l |= (1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002620 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002621 data_l &= ~(1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002622 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002623 ddr_setval(ch, _reg_PHY_PAD_DRIVE_X[i], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002624 }
2625 }
2626}
2627
Marek Vasut6a131772019-08-07 19:56:09 +02002628/* drivablity setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002629static uint32_t set_term_code(void)
2630{
2631 int32_t i;
2632 uint32_t ch, index;
Marek Vasut38dc7562019-08-07 19:17:42 +02002633 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002634 uint32_t chip_id[2];
2635 uint32_t term_code;
2636 uint32_t override;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002637 uint32_t pvtr;
2638 uint32_t pvtp;
2639 uint32_t pvtn;
Marek Vasut80784f92019-08-07 19:02:26 +02002640
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002641 term_code = ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2642 _reg_PHY_PAD_DATA_TERM);
2643 override = 0;
2644 for (i = 0; i < 2; i++)
2645 chip_id[i] = mmio_read_32(LIFEC_CHIPID(i));
2646
2647 index = 0;
2648 while (1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002649 if (termcode_by_sample[index][0] == 0xffffffff) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002650 break;
2651 }
Marek Vasut6a131772019-08-07 19:56:09 +02002652 if ((termcode_by_sample[index][0] == chip_id[0]) &&
2653 (termcode_by_sample[index][1] == chip_id[1])) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002654 term_code = termcode_by_sample[index][2];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002655 override = 1;
2656 break;
2657 }
2658 index++;
2659 }
2660
2661 if (override) {
2662 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002663 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002664 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2665 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002666 data_l = (data_l & 0xfffe0000) | term_code;
2667 ddr_setval_ach(_reg_PHY_PAD_TERM_X[index], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002668 }
Marek Vasut6a131772019-08-07 19:56:09 +02002669 } else if ((prr_product == PRR_PRODUCT_M3) &&
2670 (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002671 /* non */
2672 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002673 ddr_setval_ach(_reg_PHY_PAD_TERM_X[0],
2674 (ddrtbl_getval
2675 (_cnf_DDR_PHY_ADR_G_REGSET,
2676 _reg_PHY_PAD_TERM_X[0]) & 0xFFFE0000));
2677 ddr_setval_ach(_reg_PHY_CAL_CLEAR_0, 0x01);
2678 ddr_setval_ach(_reg_PHY_CAL_START_0, 0x01);
2679 foreach_vch(ch) {
2680 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002681 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002682 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002683 } while (!(data_l & 0x00800000));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002684 }
Marek Vasut6a131772019-08-07 19:56:09 +02002685 if ((prr_product == PRR_PRODUCT_H3) &&
2686 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002687 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002688 data_l = ddr_getval(ch, _reg_PHY_PAD_TERM_X[0]);
2689 pvtr = (data_l >> 12) & 0x1f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002690 pvtr += 8;
2691 if (pvtr > 0x1f)
2692 pvtr = 0x1f;
Marek Vasut38dc7562019-08-07 19:17:42 +02002693 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002694 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002695 pvtn = (data_l >> 6) & 0x03f;
2696 pvtp = (data_l >> 0) & 0x03f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002697
2698 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2699 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002700 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002701 ddrtbl_getval
2702 (_cnf_DDR_PHY_ADR_G_REGSET,
2703 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002704 data_l = (data_l & 0xfffe0000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002705 | (pvtr << 12)
2706 | (pvtn << 6)
2707 | (pvtp);
2708 ddr_setval(ch,
2709 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002710 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002711 }
2712 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02002713 } else {
2714 /* M3-W Ver.1.1 or later/H3 Ver.2.0 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002715 foreach_vch(ch) {
2716 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2717 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002718 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002719 ddr_getval(ch,
2720 _reg_PHY_PAD_TERM_X
2721 [index]);
2722 ddr_setval(ch,
2723 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002724 (data_l & 0xFFFE0FFF) |
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002725 0x00015000);
2726 }
2727 }
2728 }
2729 }
Marek Vasut6a131772019-08-07 19:56:09 +02002730
Marek Vasut38dc7562019-08-07 19:17:42 +02002731 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002732 /* non */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002733 } else {
2734 ddr_padcal_tcompensate_getinit(override);
2735 }
Marek Vasut6a131772019-08-07 19:56:09 +02002736
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002737 return 0;
2738}
2739
Marek Vasut6a131772019-08-07 19:56:09 +02002740/* DDR mode register setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01002741static void ddr_register_set(void)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002742{
2743 int32_t fspwp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002744 uint32_t tmp;
2745
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002746 for (fspwp = 1; fspwp >= 0; fspwp--) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002747 /*MR13, fspwp */
2748 send_dbcmd(0x0e840d08 | ((2 - fspwp) << 6));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002749
2750 tmp =
2751 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002752 reg_pi_mr1_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002753 send_dbcmd(0x0e840100 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002754
2755 tmp =
2756 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002757 reg_pi_mr2_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002758 send_dbcmd(0x0e840200 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002759
2760 tmp =
2761 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002762 reg_pi_mr3_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002763 send_dbcmd(0x0e840300 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002764
2765 tmp =
2766 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002767 reg_pi_mr11_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002768 send_dbcmd(0x0e840b00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002769
2770 tmp =
2771 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002772 reg_pi_mr12_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002773 send_dbcmd(0x0e840c00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002774
2775 tmp =
2776 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002777 reg_pi_mr14_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002778 send_dbcmd(0x0e840e00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002779 /* MR22 */
Marek Vasut6c245a52018-12-12 18:06:39 +01002780 send_dbcmd(0x0e841616);
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002781
2782 /* ZQCAL start */
2783 send_dbcmd(0x0d84004F);
2784
2785 /* ZQLAT */
2786 send_dbcmd(0x0d840051);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002787 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002788
2789 /* MR13, fspwp */
2790 send_dbcmd(0x0e840d08);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002791}
2792
Marek Vasut6a131772019-08-07 19:56:09 +02002793/* Training handshake functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002794static inline uint32_t wait_freqchgreq(uint32_t assert)
2795{
Marek Vasut38dc7562019-08-07 19:17:42 +02002796 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002797 uint32_t count;
2798 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002799
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002800 count = 100000;
2801
2802 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut38dc7562019-08-07 19:17:42 +02002803 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002804 return 0;
2805 }
2806
2807 if (assert) {
2808 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002809 data_l = 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002810 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002811 data_l &= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002812 }
2813 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002814 } while (((data_l & 0x01) != 0x01) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002815 } else {
2816 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002817 data_l = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002818 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002819 data_l |= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002820 }
2821 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002822 } while (((data_l & 0x01) != 0x00) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002823 }
2824
2825 return (count == 0);
2826}
2827
2828static inline void set_freqchgack(uint32_t assert)
2829{
2830 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002831 uint32_t data_l;
Marek Vasut80784f92019-08-07 19:02:26 +02002832
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002833 if (assert)
Marek Vasut38dc7562019-08-07 19:17:42 +02002834 data_l = 0x0CF20000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002835 else
Marek Vasut38dc7562019-08-07 19:17:42 +02002836 data_l = 0x00000000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002837
2838 foreach_vch(ch)
Marek Vasut38dc7562019-08-07 19:17:42 +02002839 mmio_write_32(DBSC_DBPDCNT2(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002840}
2841
2842static inline void set_dfifrequency(uint32_t freq)
2843{
2844 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002845
Marek Vasut38dc7562019-08-07 19:17:42 +02002846 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002847 foreach_vch(ch)
2848 mmio_clrsetbits_32(DBSC_DBPDCNT1(ch), 0x1fU, freq);
2849 } else {
2850 foreach_vch(ch) {
2851 mmio_clrsetbits_32(DBSC_DBDFICNT(ch), 0x1fU << 24,
2852 (freq << 24));
2853 }
2854 }
2855 dsb_sev();
2856}
2857
2858static uint32_t pll3_freq(uint32_t on)
2859{
2860 uint32_t timeout;
2861
2862 timeout = wait_freqchgreq(1);
2863
Yoshifumi Hosoya39be8282022-07-22 13:04:36 +09002864 if ((!((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))) && (on)) {
2865 if (((1600U * ddr_mbpsdiv) < ddr_mbps) || (prr_product == PRR_PRODUCT_M3)) {
2866 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL), 0x01421142U);
2867 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL_CA), 0x00000142U);
2868 } else {
2869 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL), 0x03421342U);
2870 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL_CA), 0x00000342U);
2871 }
2872 }
2873
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002874 if (timeout) {
Marek Vasut6a131772019-08-07 19:56:09 +02002875 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002876 }
2877
2878 pll3_control(on);
2879 set_dfifrequency(on);
2880
2881 set_freqchgack(1);
2882 timeout = wait_freqchgreq(0);
2883 set_freqchgack(0);
2884
2885 if (timeout) {
Marek Vasut56519892019-01-21 23:11:33 +01002886 FATAL_MSG("BL2: Time out[2]\n");
Marek Vasut6a131772019-08-07 19:56:09 +02002887 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002888 }
Marek Vasut6a131772019-08-07 19:56:09 +02002889 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002890}
2891
Marek Vasut6a131772019-08-07 19:56:09 +02002892/* update dly */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002893static void update_dly(void)
2894{
2895 ddr_setval_ach(_reg_SC_PHY_MANUAL_UPDATE, 0x01);
2896 ddr_setval_ach(_reg_PHY_ADRCTL_MANUAL_UPDATE, 0x01);
2897}
2898
Marek Vasut6a131772019-08-07 19:56:09 +02002899/* training by pi */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002900static uint32_t pi_training_go(void)
2901{
2902 uint32_t flag;
Marek Vasut38dc7562019-08-07 19:17:42 +02002903 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002904 uint32_t retry;
2905 const uint32_t RETRY_MAX = 4096 * 16;
2906 uint32_t ch;
2907
2908 uint32_t mst_ch;
2909 uint32_t cur_frq;
2910 uint32_t complete;
2911 uint32_t frqchg_req;
2912
Marek Vasut6a131772019-08-07 19:56:09 +02002913 /* pi_start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002914 ddr_setval_ach(_reg_PI_START, 0x01);
2915 foreach_vch(ch)
2916 ddr_getval(ch, _reg_PI_INT_STATUS);
2917
2918 /* set dfi_phymstr_ack = 1 */
2919 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000001);
2920 dsb_sev();
2921
Marek Vasut6a131772019-08-07 19:56:09 +02002922 /* wait pi_int_status[0] */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002923 mst_ch = 0;
2924 flag = 0;
2925 complete = 0;
2926 cur_frq = 0;
2927 retry = RETRY_MAX;
2928 do {
2929 frqchg_req = mmio_read_32(DBSC_DBPDSTAT(mst_ch)) & 0x01;
2930
2931 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut6a131772019-08-07 19:56:09 +02002932 if ((prr_product == PRR_PRODUCT_H3) &&
2933 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002934 if ((retry % 4096) == 1) {
2935 frqchg_req = 1;
2936 } else {
2937 frqchg_req = 0;
2938 }
2939 }
2940
2941 if (frqchg_req) {
2942 if (cur_frq) {
2943 /* Low frequency */
2944 flag = pll3_freq(0);
2945 cur_frq = 0;
2946 } else {
2947 /* High frequency */
2948 flag = pll3_freq(1);
2949 cur_frq = 1;
2950 }
2951 if (flag)
2952 break;
2953 } else {
2954 if (cur_frq) {
2955 foreach_vch(ch) {
2956 if (complete & (1U << ch))
2957 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02002958 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002959 ddr_getval(ch, _reg_PI_INT_STATUS);
Marek Vasut38dc7562019-08-07 19:17:42 +02002960 if (data_l & 0x01) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002961 complete |= (1U << ch);
2962 }
2963 }
2964 if (complete == ddr_phyvalid)
2965 break;
2966 }
2967 }
2968 } while (--retry);
2969 foreach_vch(ch) {
2970 /* dummy read */
Marek Vasut38dc7562019-08-07 19:17:42 +02002971 data_l = ddr_getval_s(ch, 0, _reg_PHY_CAL_RESULT2_OBS_0);
2972 data_l = ddr_getval(ch, _reg_PI_INT_STATUS);
2973 ddr_setval(ch, _reg_PI_INT_ACK, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002974 }
2975 if (ddrphy_regif_chk()) {
Marek Vasut6a131772019-08-07 19:56:09 +02002976 return 0xfd;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002977 }
2978 return complete;
2979}
2980
Marek Vasut6a131772019-08-07 19:56:09 +02002981/* Initialize DDR */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002982static uint32_t init_ddr(void)
2983{
2984 int32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002985 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002986 uint32_t phytrainingok;
Marek Vasut6c245a52018-12-12 18:06:39 +01002987 uint32_t ch, slice;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002988 uint32_t err;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002989 int16_t adj;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002990
Marek Vasut6ad74c32019-08-08 16:34:22 +02002991 MSG_LF(__func__ ":0\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002992
2993#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02002994 rcar_dram_get_boot_status(&ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002995#endif
2996
Marek Vasut6a131772019-08-07 19:56:09 +02002997 /* unlock phy */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002998 /* Unlock DDRPHY register(AGAIN) */
2999 foreach_vch(ch)
3000 mmio_write_32(DBSC_DBPDLK(ch), 0x0000A55A);
3001 dsb_sev();
3002
Marek Vasut6a131772019-08-07 19:56:09 +02003003 if ((((prr_product == PRR_PRODUCT_H3) &&
3004 (prr_cut > PRR_PRODUCT_11)) ||
3005 (prr_product == PRR_PRODUCT_M3N) ||
3006 (prr_product == PRR_PRODUCT_V3H)) && board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003007 reg_ddrphy_write_a(0x00001010, 0x01000001);
3008 else
3009 reg_ddrphy_write_a(0x00001010, 0x00000001);
Marek Vasut6a131772019-08-07 19:56:09 +02003010 /* DBSC register pre-setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003011 dbsc_regset_pre();
3012
Marek Vasut6a131772019-08-07 19:56:09 +02003013 /* load ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003014
3015 ddrtbl_load();
3016
Marek Vasut6a131772019-08-07 19:56:09 +02003017 /* configure ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003018 ddr_config();
3019
Marek Vasut6a131772019-08-07 19:56:09 +02003020 /* dfi_reset assert */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003021 foreach_vch(ch)
3022 mmio_write_32(DBSC_DBPDCNT0(ch), 0x01);
3023 dsb_sev();
3024
Marek Vasut6a131772019-08-07 19:56:09 +02003025 /* dbsc register set */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003026 dbsc_regset();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003027 MSG_LF(__func__ ":1\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003028
Marek Vasut6a131772019-08-07 19:56:09 +02003029 /* dfi_reset negate */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003030 foreach_vch(ch)
3031 mmio_write_32(DBSC_DBPDCNT0(ch), 0x00);
3032 dsb_sev();
3033
Marek Vasut6a131772019-08-07 19:56:09 +02003034 /* dfi_init_start (start ddrphy) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003035 err = dfi_init_start();
3036 if (err) {
3037 return INITDRAM_ERR_I;
3038 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003039 MSG_LF(__func__ ":2\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003040
Marek Vasut6a131772019-08-07 19:56:09 +02003041 /* ddr backupmode end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003042#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02003043 if (ddr_backup) {
Marek Vasut56519892019-01-21 23:11:33 +01003044 NOTICE("BL2: [WARM_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003045 } else {
Marek Vasut56519892019-01-21 23:11:33 +01003046 NOTICE("BL2: [COLD_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003047 }
Marek Vasut38dc7562019-08-07 19:17:42 +02003048 err = rcar_dram_update_boot_status(ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003049 if (err) {
Marek Vasut56519892019-01-21 23:11:33 +01003050 NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003051 return INITDRAM_ERR_I;
3052 }
3053#endif
Marek Vasut6ad74c32019-08-08 16:34:22 +02003054 MSG_LF(__func__ ":3\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003055
Marek Vasut6a131772019-08-07 19:56:09 +02003056 /* override term code after dfi_init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003057 err = set_term_code();
3058 if (err) {
3059 return INITDRAM_ERR_I;
3060 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003061 MSG_LF(__func__ ":4\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003062
Marek Vasut6a131772019-08-07 19:56:09 +02003063 /* rx offset calibration */
3064 if ((prr_cut > PRR_PRODUCT_11) || (prr_product == PRR_PRODUCT_M3N) ||
3065 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003066 err = rx_offset_cal_hw();
3067 } else {
3068 err = rx_offset_cal();
3069 }
3070 if (err)
Marek Vasut6a131772019-08-07 19:56:09 +02003071 return INITDRAM_ERR_O;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003072 MSG_LF(__func__ ":5\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003073
Chiaki Fujiiaea02862019-09-18 13:10:00 +09003074 /* Dummy PDE */
3075 send_dbcmd(0x08840000);
3076
Marek Vasut6c245a52018-12-12 18:06:39 +01003077 /* PDX */
3078 send_dbcmd(0x08840001);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003079
Marek Vasut6a131772019-08-07 19:56:09 +02003080 /* check register i/f is alive */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003081 err = ddrphy_regif_chk();
3082 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003083 return INITDRAM_ERR_O;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003084 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003085 MSG_LF(__func__ ":6\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003086
Marek Vasut6a131772019-08-07 19:56:09 +02003087 /* phy initialize end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003088
Marek Vasut6a131772019-08-07 19:56:09 +02003089 /* setup DDR mode registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003090 /* CMOS MODE */
3091 change_lpddr4_en(0);
3092
Marek Vasut6c245a52018-12-12 18:06:39 +01003093 /* MRS */
3094 ddr_register_set();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003095
Marek Vasut6a131772019-08-07 19:56:09 +02003096 /* Thermal sensor setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01003097 /* THCTR Bit6: PONM=0 , Bit0: THSST=1 */
Marek Vasut38dc7562019-08-07 19:17:42 +02003098 data_l = (mmio_read_32(THS1_THCTR) & 0xFFFFFFBF) | 0x00000001;
3099 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003100
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003101 /* LPDDR4 MODE */
3102 change_lpddr4_en(1);
3103
Marek Vasut6ad74c32019-08-08 16:34:22 +02003104 MSG_LF(__func__ ":7\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003105
Marek Vasut6a131772019-08-07 19:56:09 +02003106 /* mask CS_MAP if RANKx is not found */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003107 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003108 data_l = ddr_getval(ch, _reg_PI_CS_MAP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003109 if (!(ch_have_this_cs[1] & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02003110 data_l = data_l & 0x05;
3111 ddr_setval(ch, _reg_PI_CS_MAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003112 }
3113
Marek Vasut6a131772019-08-07 19:56:09 +02003114 /* exec pi_training */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003115 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
3116 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003117 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003118
Marek Vasut38dc7562019-08-07 19:17:42 +02003119 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003120 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_EN, 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003121 } else {
3122 foreach_vch(ch) {
3123 for (slice = 0; slice < SLICE_CNT; slice++) {
3124 ddr_setval_s(ch, slice,
3125 _reg_PHY_PER_CS_TRAINING_EN,
3126 ((ch_have_this_cs[1]) >> ch)
3127 & 0x01);
3128 }
3129 }
3130 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003131
3132 phytrainingok = pi_training_go();
3133
3134 if (ddr_phyvalid != (phytrainingok & ddr_phyvalid)) {
Marek Vasut6a131772019-08-07 19:56:09 +02003135 return INITDRAM_ERR_T | phytrainingok;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003136 }
3137
Marek Vasut6ad74c32019-08-08 16:34:22 +02003138 MSG_LF(__func__ ":8\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003139
Marek Vasut6a131772019-08-07 19:56:09 +02003140 /* CACS DLY ADJUST */
Marek Vasut38dc7562019-08-07 19:17:42 +02003141 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003142 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003143 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003144 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003145 ddr_setval(ch, _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003146 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003147 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003148
3149 if (ddr_phycaslice == 1) {
3150 for (i = 0; i < 6; i++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003151 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj
3152 [i +
3153 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
3154 ddr_setval_s(ch, 2,
3155 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
3156 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003157 data_l + adj
Marek Vasut6c245a52018-12-12 18:06:39 +01003158 );
3159 }
3160 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003161 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003162
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003163 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003164 MSG_LF(__func__ ":9\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003165
Marek Vasut6a131772019-08-07 19:56:09 +02003166 /* H3 fix rd latency to avoid bug in elasitic buffer */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003167 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003168 adjust_rddqs_latency();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003169
Marek Vasut6a131772019-08-07 19:56:09 +02003170 /* Adjust Write path latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003171 if (ddrtbl_getval
3172 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD))
3173 adjust_wpath_latency();
3174
Marek Vasut6a131772019-08-07 19:56:09 +02003175 /* RDQLVL Training */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003176 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003177 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x01);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003178
3179 err = rdqdm_man();
Marek Vasut6c245a52018-12-12 18:06:39 +01003180
Marek Vasut6ad74c32019-08-08 16:34:22 +02003181 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Marek Vasut6c245a52018-12-12 18:06:39 +01003182 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003183
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003184 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003185 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003186 }
3187 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003188 MSG_LF(__func__ ":10\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003189
Marek Vasut6a131772019-08-07 19:56:09 +02003190 /* WDQLVL Training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003191 err = wdqdm_man();
3192 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003193 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003194 }
3195 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003196 MSG_LF(__func__ ":11\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003197
Marek Vasut6a131772019-08-07 19:56:09 +02003198 /* training complete, setup DBSC */
3199 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3200 (prr_product == PRR_PRODUCT_M3N) ||
3201 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003202 ddr_setval_ach_as(_reg_PHY_DFI40_POLARITY, 0x00);
3203 ddr_setval_ach(_reg_PI_DFI40_POLARITY, 0x00);
3204 }
3205
3206 dbsc_regset_post();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003207 MSG_LF(__func__ ":12\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003208
3209 return phytrainingok;
3210}
3211
Marek Vasut6a131772019-08-07 19:56:09 +02003212/* SW LEVELING COMMON */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003213static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick)
3214{
3215 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02003216 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003217 uint32_t retry;
3218 uint32_t waiting;
3219 uint32_t err;
3220
3221 const uint32_t RETRY_MAX = 0x1000;
3222
3223 err = 0;
3224 /* set EXIT -> OP_DONE is cleared */
3225 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3226
3227 /* kick */
3228 foreach_vch(ch) {
3229 if (ch_have_this_cs[ddr_csn % 2] & (1U << ch)) {
3230 ddr_setval(ch, reg_cs, ddr_csn);
3231 ddr_setval(ch, reg_kick, 0x01);
3232 }
3233 }
3234 foreach_vch(ch) {
3235 /*PREPARE ADDR REGISTER (for SWLVL_OP_DONE) */
3236 ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3237 }
3238 waiting = ch_have_this_cs[ddr_csn % 2];
3239 dsb_sev();
3240 retry = RETRY_MAX;
3241 do {
3242 foreach_vch(ch) {
3243 if (!(waiting & (1U << ch)))
3244 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02003245 data_l = ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3246 if (data_l & 0x01)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003247 waiting &= ~(1U << ch);
3248 }
3249 retry--;
3250 } while (waiting && (retry > 0));
3251 if (retry == 0) {
3252 err = 1;
3253 }
3254
3255 dsb_sev();
3256 /* set EXIT -> OP_DONE is cleared */
3257 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3258 dsb_sev();
3259
3260 return err;
3261}
3262
Marek Vasut6a131772019-08-07 19:56:09 +02003263/* WDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003264#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003265static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3266{
3267 int32_t i, k;
3268 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003269 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003270
Marek Vasut6a131772019-08-07 19:56:09 +02003271 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003272 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003273 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003274 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003275 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003276 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3277 continue;
3278
3279 for (i = 0; i <= 8; i++) {
3280 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch))
3281 wdqdm_dly[ch][cs][slice][i] =
3282 wdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3283 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003284 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003285 wdqdm_le[ch][cs][slice][i] = 0;
3286 wdqdm_te[ch][cs][slice][i] = 0;
3287 }
3288 wdqdm_st[ch][cs][slice] = 0;
3289 wdqdm_win[ch][cs][slice] = 0;
3290 }
3291}
3292
3293static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3294{
3295 int32_t i, k;
3296 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003297 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003298 uint32_t err;
3299 const uint32_t _par_WDQLVL_RETRY_THRES = 0x7c0;
3300
3301 int32_t min_win;
3302 int32_t win;
3303 int8_t _adj;
3304 int16_t adj;
3305 uint32_t dq;
3306
Marek Vasut6a131772019-08-07 19:56:09 +02003307 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003308 err = 0;
3309 for (slice = 0; slice < SLICE_CNT; slice += 1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003310 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003311 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3312 continue;
3313
3314 cs = ddr_csn % 2;
3315 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003316 for (i = 0; i < 9; i++) {
3317 dq = slice * 8 + i;
3318 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003319 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003320 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003321 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003322 adj = _f_scale_adj(_adj);
3323
Marek Vasut38dc7562019-08-07 19:17:42 +02003324 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003325 ddr_getval_s(ch, slice,
3326 _reg_PHY_CLK_WRX_SLAVE_DELAY[i]) + adj;
3327 ddr_setval_s(ch, slice, _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003328 data_l);
3329 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003330 }
3331 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, 0x00);
Marek Vasut38dc7562019-08-07 19:17:42 +02003332 data_l = ddr_getval_s(ch, slice, _reg_PHY_WDQLVL_STATUS_OBS);
3333 wdqdm_st[ch][cs][slice] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003334 min_win = INT_LEAST32_MAX;
3335 for (i = 0; i <= 8; i++) {
3336 ddr_setval_s(ch, slice, _reg_PHY_WDQLVL_DQDM_OBS_SELECT,
3337 i);
3338
Marek Vasut38dc7562019-08-07 19:17:42 +02003339 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003340 ddr_getval_s(ch, slice,
3341 _reg_PHY_WDQLVL_DQDM_TE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003342 wdqdm_te[ch][cs][slice][i] = data_l;
3343 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003344 ddr_getval_s(ch, slice,
3345 _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003346 wdqdm_le[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003347 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003348 (int32_t)wdqdm_te[ch][cs][slice][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003349 wdqdm_le[ch][cs][slice][i];
3350 if (min_win > win)
3351 min_win = win;
Marek Vasut38dc7562019-08-07 19:17:42 +02003352 if (data_l >= _par_WDQLVL_RETRY_THRES)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003353 err = 2;
3354 }
3355 wdqdm_win[ch][cs][slice] = min_win;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003356 if ((prr_product == PRR_PRODUCT_H3) &&
3357 (prr_cut <= PRR_PRODUCT_11)) {
3358 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3359 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003360 } else {
3361 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3362 ((ch_have_this_cs[1]) >> ch) & 0x01);
3363 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003364 }
3365 return err;
3366}
Marek Vasut6c245a52018-12-12 18:06:39 +01003367#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003368
3369static void wdqdm_cp(uint32_t ddr_csn, uint32_t restore)
3370{
3371 uint32_t i;
3372 uint32_t ch, slice;
3373 uint32_t tgt_cs, src_cs;
3374 uint32_t tmp_r;
3375
Marek Vasut6a131772019-08-07 19:56:09 +02003376 /* copy of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003377 foreach_vch(ch) {
3378 for (tgt_cs = 0; tgt_cs < CS_CNT; tgt_cs++) {
3379 for (slice = 0; slice < SLICE_CNT; slice++) {
3380 ddr_setval_s(ch, slice,
3381 _reg_PHY_PER_CS_TRAINING_INDEX,
3382 tgt_cs);
3383 src_cs = ddr_csn % 2;
3384 if (!(ch_have_this_cs[1] & (1U << ch)))
3385 src_cs = 0;
3386 for (i = 0; i <= 4; i += 4) {
3387 if (restore)
3388 tmp_r =
3389 rdqdm_dly[ch][tgt_cs][slice]
3390 [i];
3391 else
3392 tmp_r =
3393 rdqdm_dly[ch][src_cs][slice]
3394 [i];
3395
3396 ddr_setval_s(ch, slice,
3397 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
3398 [i], tmp_r);
3399 }
3400 }
3401 }
3402 }
3403}
3404
3405static uint32_t wdqdm_man1(void)
3406{
3407 int32_t k;
3408 uint32_t ch, cs, slice;
3409 uint32_t ddr_csn;
Marek Vasut38dc7562019-08-07 19:17:42 +02003410 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003411 uint32_t err;
Marek Vasut6c245a52018-12-12 18:06:39 +01003412 uint32_t high_dq[DRAM_CH_CNT];
3413 uint32_t mr14_csab0_bak[DRAM_CH_CNT];
3414#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003415 uint32_t err_flg;
Marek Vasut6c245a52018-12-12 18:06:39 +01003416#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003417
Marek Vasut6a131772019-08-07 19:56:09 +02003418 /* manual execution of training */
Marek Vasut38dc7562019-08-07 19:17:42 +02003419 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003420 foreach_vch(ch) {
3421 high_dq[ch] = 0;
3422 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003423 k = (board_cnf->ch[ch].dqs_swap >>
3424 (4 * slice)) & 0x0f;
Marek Vasut6c245a52018-12-12 18:06:39 +01003425 if (k >= 2)
3426 high_dq[ch] |= (1U << slice);
3427 }
3428 ddr_setval(ch, _reg_PI_16BIT_DRAM_CONNECT, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003429 }
3430 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003431 err = 0;
3432 /* CLEAR PREV RESULT */
3433 for (cs = 0; cs < CS_CNT; cs++) {
3434 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_INDEX, cs);
Marek Vasut6a131772019-08-07 19:56:09 +02003435 if (((prr_product == PRR_PRODUCT_H3) &&
3436 (prr_cut > PRR_PRODUCT_11)) ||
3437 (prr_product == PRR_PRODUCT_M3N) ||
3438 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003439 ddr_setval_ach_as(_reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS,
3440 0x01);
3441 } else {
3442 ddr_setval_ach_as(_reg_PHY_WDQLVL_CLR_PREV_RESULTS,
3443 0x01);
3444 }
3445 }
3446 ddrphy_regif_idle();
3447
Marek Vasut6c245a52018-12-12 18:06:39 +01003448#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003449 err_flg = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01003450#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003451 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Marek Vasut6a131772019-08-07 19:56:09 +02003452 if ((prr_product == PRR_PRODUCT_H3) &&
3453 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003454 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003455 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3456 data_l &= ~(0x00ffU << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003457
3458 if (ddr_csn >= 2)
3459 k = (high_dq[ch] ^ 0x0f);
3460 else
3461 k = high_dq[ch];
Marek Vasut38dc7562019-08-07 19:17:42 +02003462 data_l |= (k << 16);
3463 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003464 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, k);
3465 }
3466 }
Marek Vasut6a131772019-08-07 19:56:09 +02003467 if (((prr_product == PRR_PRODUCT_H3) &&
3468 (prr_cut <= PRR_PRODUCT_11)) ||
3469 ((prr_product == PRR_PRODUCT_M3) &&
3470 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003471 wdqdm_cp(ddr_csn, 0);
3472 }
3473
3474 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003475 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003476 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003477 reg_pi_mr14_data_fx_csx[1][ddr_csn]);
3478 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003479 }
3480
3481 /* KICK WDQLVL */
3482 err = swlvl1(ddr_csn, _reg_PI_WDQLVL_CS, _reg_PI_WDQLVL_REQ);
3483 if (err)
3484 goto err_exit;
3485
3486 if (ddr_csn == 0)
3487 foreach_vch(ch) {
3488 mr14_csab0_bak[ch] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003489 ddr_getval(ch, reg_pi_mr14_data_fx_csx[1][0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003490 } else
3491 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003492 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0],
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003493 mr14_csab0_bak[ch]);
3494 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003495#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003496 foreach_vch(ch) {
3497 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3498 wdqdm_clr1(ch, ddr_csn);
3499 continue;
3500 }
3501 err = wdqdm_ana1(ch, ddr_csn);
3502 if (err)
3503 err_flg |= (1U << (ddr_csn * 4 + ch));
3504 ddrphy_regif_idle();
3505 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003506#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003507 }
3508err_exit:
Marek Vasut6c245a52018-12-12 18:06:39 +01003509#ifndef DDR_FAST_INIT
3510 err |= err_flg;
3511#endif/* DDR_FAST_INIT */
Marek Vasut38dc7562019-08-07 19:17:42 +02003512 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003513 ddr_setval_ach(_reg_PI_16BIT_DRAM_CONNECT, 0x01);
3514 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003515 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3516 data_l &= ~(0x00ffU << 16);
3517 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01003518 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, 0x00);
3519 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003520 }
Marek Vasut6a131772019-08-07 19:56:09 +02003521 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003522}
3523
3524static uint32_t wdqdm_man(void)
3525{
3526 uint32_t err, retry_cnt;
3527 const uint32_t retry_max = 0x10;
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09003528 uint32_t datal, ch, ddr_csn, mr14_bkup[4][4];
3529
3530 datal = RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2 + 19;
3531 if ((mmio_read_32(DBSC_DBTR(11)) & 0xFF) > datal)
3532 datal = mmio_read_32(DBSC_DBTR(11)) & 0xFF;
3533 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW, datal);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003534
Marek Vasut6a131772019-08-07 19:56:09 +02003535 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3536 (prr_product == PRR_PRODUCT_M3N) ||
3537 (prr_product == PRR_PRODUCT_V3H)) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003538 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F0,
3539 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003540 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F1,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003541 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003542 } else {
3543 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003544 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003545 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003546 ddr_setval_ach(_reg_PI_TRFC_F0, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
3547 ddr_setval_ach(_reg_PI_TRFC_F1, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003548
3549 retry_cnt = 0;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003550 err = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003551 do {
Marek Vasut6a131772019-08-07 19:56:09 +02003552 if ((prr_product == PRR_PRODUCT_H3) &&
3553 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003554 err = wdqdm_man1();
3555 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003556 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x01);
3557 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3558 0x01);
Marek Vasut6a131772019-08-07 19:56:09 +02003559 if ((prr_product == PRR_PRODUCT_M3N) ||
3560 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003561 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3562 0x0C);
3563 } else {
3564 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x0C);
3565 }
3566 dsb_sev();
3567 err = wdqdm_man1();
3568 foreach_vch(ch) {
3569 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3570 mr14_bkup[ch][ddr_csn] =
3571 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003572 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003573 [1][ddr_csn]);
3574 dsb_sev();
3575 }
3576 }
3577
Marek Vasut6a131772019-08-07 19:56:09 +02003578 if ((prr_product == PRR_PRODUCT_M3N) ||
3579 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003580 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3581 0x04);
3582 } else {
3583 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x04);
3584 }
3585 pvtcode_update();
3586 err = wdqdm_man1();
3587 foreach_vch(ch) {
3588 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3589 mr14_bkup[ch][ddr_csn] =
3590 (mr14_bkup[ch][ddr_csn] +
3591 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003592 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003593 [1][ddr_csn])) / 2;
3594 ddr_setval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003595 reg_pi_mr14_data_fx_csx[1]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003596 [ddr_csn],
3597 mr14_bkup[ch][ddr_csn]);
3598 }
3599 }
3600
3601 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3602 0x00);
Marek Vasut6a131772019-08-07 19:56:09 +02003603 if ((prr_product == PRR_PRODUCT_M3N) ||
3604 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003605 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3606 0x00);
3607 ddr_setval_ach
3608 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1,
3609 0x00);
3610 ddr_setval_ach
3611 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1,
3612 0x00);
3613 } else {
3614 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x00);
3615 ddr_setval_ach
3616 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT,
3617 0x00);
3618 ddr_setval_ach
3619 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT,
3620 0x00);
3621 }
3622 ddr_setval_ach(_reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE,
3623 0x00);
3624
3625 pvtcode_update2();
3626 err = wdqdm_man1();
3627 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
3628 }
3629 } while (err && (++retry_cnt < retry_max));
3630
Marek Vasut6a131772019-08-07 19:56:09 +02003631 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
3632 ((prr_product == PRR_PRODUCT_M3) && (prr_cut <= PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003633 wdqdm_cp(0, 1);
3634 }
3635
3636 return (retry_cnt >= retry_max);
3637}
3638
Marek Vasut6a131772019-08-07 19:56:09 +02003639/* RDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003640#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003641static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3642{
3643 int32_t i, k;
3644 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003645 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003646
Marek Vasut6a131772019-08-07 19:56:09 +02003647 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003648 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003649 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003650 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003651 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003652 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3653 continue;
3654
3655 for (i = 0; i <= 8; i++) {
3656 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) {
3657 rdqdm_dly[ch][cs][slice][i] =
3658 rdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3659 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3660 rdqdm_dly[ch][CS_CNT - 1 - cs][slice +
3661 SLICE_CNT]
3662 [i];
3663 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02003664 rdqdm_dly[ch][cs][slice][i] = data_l;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003665 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3666 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003667 }
3668 rdqdm_le[ch][cs][slice][i] = 0;
3669 rdqdm_le[ch][cs][slice + SLICE_CNT][i] = 0;
3670 rdqdm_te[ch][cs][slice][i] = 0;
3671 rdqdm_te[ch][cs][slice + SLICE_CNT][i] = 0;
3672 rdqdm_nw[ch][cs][slice][i] = 0;
3673 rdqdm_nw[ch][cs][slice + SLICE_CNT][i] = 0;
3674 }
3675 rdqdm_st[ch][cs][slice] = 0;
3676 rdqdm_win[ch][cs][slice] = 0;
3677 }
3678}
3679
3680static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3681{
3682 int32_t i, k;
3683 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003684 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003685 uint32_t err;
3686 int8_t _adj;
3687 int16_t adj;
3688 uint32_t dq;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003689 int32_t min_win;
3690 int32_t win;
3691 uint32_t rdq_status_obs_select;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003692
Marek Vasut6a131772019-08-07 19:56:09 +02003693 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003694 err = 0;
3695 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003696 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003697 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3698 continue;
3699
3700 cs = ddr_csn % 2;
3701 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
3702 ddrphy_regif_idle();
3703
3704 ddr_getval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX);
3705 ddrphy_regif_idle();
3706
3707 for (i = 0; i <= 8; i++) {
3708 dq = slice * 8 + i;
3709 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003710 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003711 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003712 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003713
3714 adj = _f_scale_adj(_adj);
3715
Marek Vasut38dc7562019-08-07 19:17:42 +02003716 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003717 ddr_getval_s(ch, slice,
3718 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) +
3719 adj;
3720 ddr_setval_s(ch, slice,
3721 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003722 data_l);
3723 rdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003724
Marek Vasut38dc7562019-08-07 19:17:42 +02003725 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003726 ddr_getval_s(ch, slice,
3727 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) +
3728 adj;
3729 ddr_setval_s(ch, slice,
3730 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003731 data_l);
3732 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003733 }
3734 min_win = INT_LEAST32_MAX;
3735 for (i = 0; i <= 8; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003736 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003737 ddr_getval_s(ch, slice, _reg_PHY_RDLVL_STATUS_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003738 rdqdm_st[ch][cs][slice] = data_l;
3739 rdqdm_st[ch][cs][slice + SLICE_CNT] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003740 /* k : rise/fall */
3741 for (k = 0; k < 2; k++) {
3742 if (i == 8) {
3743 rdq_status_obs_select = 16 + 8 * k;
3744 } else {
3745 rdq_status_obs_select = i + k * 8;
3746 }
3747 ddr_setval_s(ch, slice,
3748 _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT,
3749 rdq_status_obs_select);
3750
Marek Vasut38dc7562019-08-07 19:17:42 +02003751 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003752 ddr_getval_s(ch, slice,
3753 _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS);
3754 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003755 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003756
Marek Vasut38dc7562019-08-07 19:17:42 +02003757 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003758 ddr_getval_s(ch, slice,
3759 _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS);
3760 rdqdm_te[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003761 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003762
Marek Vasut38dc7562019-08-07 19:17:42 +02003763 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003764 ddr_getval_s(ch, slice,
3765 _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS);
3766 rdqdm_nw[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003767 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003768
3769 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003770 (int32_t)rdqdm_te[ch][cs][slice +
Marek Vasut6ad74c32019-08-08 16:34:22 +02003771 SLICE_CNT *
3772 k][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003773 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i];
3774 if (i != 8) {
3775 if (min_win > win)
3776 min_win = win;
3777 }
3778 }
3779 }
3780 rdqdm_win[ch][cs][slice] = min_win;
3781 if (min_win <= 0) {
3782 err = 2;
3783 }
3784 }
Marek Vasut6a131772019-08-07 19:56:09 +02003785 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003786}
Marek Vasut6c245a52018-12-12 18:06:39 +01003787#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003788
3789static uint32_t rdqdm_man1(void)
3790{
3791 uint32_t ch;
3792 uint32_t ddr_csn;
Marek Vasut6c245a52018-12-12 18:06:39 +01003793#ifdef DDR_FAST_INIT
3794 uint32_t slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003795 uint32_t i, adj, data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003796#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003797 uint32_t err;
3798
Marek Vasut6a131772019-08-07 19:56:09 +02003799 /* manual execution of training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003800 err = 0;
3801
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003802 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003803 /* KICK RDQLVL */
3804 err = swlvl1(ddr_csn, _reg_PI_RDLVL_CS, _reg_PI_RDLVL_REQ);
3805 if (err)
3806 goto err_exit;
Marek Vasut6c245a52018-12-12 18:06:39 +01003807#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003808 foreach_vch(ch) {
3809 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3810 rdqdm_clr1(ch, ddr_csn);
3811 ddrphy_regif_idle();
3812 continue;
3813 }
3814 err = rdqdm_ana1(ch, ddr_csn);
3815 ddrphy_regif_idle();
3816 if (err)
3817 goto err_exit;
3818 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003819#else/* DDR_FAST_INIT */
3820 foreach_vch(ch) {
3821 if (ch_have_this_cs[ddr_csn] & (1U << ch)) {
3822 for (slice = 0; slice < SLICE_CNT; slice++) {
3823 if (ddr_getval_s(ch, slice,
Marek Vasut80784f92019-08-07 19:02:26 +02003824 _reg_PHY_RDLVL_STATUS_OBS) !=
Marek Vasut6c245a52018-12-12 18:06:39 +01003825 0x0D00FFFF) {
3826 err = (1U << ch) |
3827 (0x10U << slice);
3828 goto err_exit;
3829 }
3830 }
3831 }
Marek Vasut6a131772019-08-07 19:56:09 +02003832 if (((prr_product == PRR_PRODUCT_H3) &&
3833 (prr_cut <= PRR_PRODUCT_11)) ||
3834 ((prr_product == PRR_PRODUCT_M3) &&
3835 (prr_cut <= PRR_PRODUCT_10))) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003836 for (slice = 0; slice < SLICE_CNT; slice++) {
3837 for (i = 0; i <= 8; i++) {
3838 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003839 adj = _f_scale_adj(board_cnf->ch[ch].dm_adj_r[slice]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003840 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003841 adj = _f_scale_adj(board_cnf->ch[ch].dq_adj_r[slice * 8 + i]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003842 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, ddr_csn);
Marek Vasut38dc7562019-08-07 19:17:42 +02003843 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + adj;
3844 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], data_l);
3845 rdqdm_dly[ch][ddr_csn][slice][i] = data_l;
3846 rdqdm_dly[ch][ddr_csn | 1][slice][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003847
Marek Vasut38dc7562019-08-07 19:17:42 +02003848 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + adj;
3849 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], data_l);
3850 rdqdm_dly[ch][ddr_csn][slice + SLICE_CNT][i] = data_l;
3851 rdqdm_dly[ch][ddr_csn | 1][slice + SLICE_CNT][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003852 }
3853 }
3854 }
3855 }
3856 ddrphy_regif_idle();
3857
3858#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003859 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003860
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003861err_exit:
Marek Vasut6a131772019-08-07 19:56:09 +02003862 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003863}
3864
3865static uint32_t rdqdm_man(void)
3866{
3867 uint32_t err, retry_cnt;
3868 const uint32_t retry_max = 0x01;
3869
3870 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3871 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3872 _reg_PHY_DQ_TSEL_ENABLE));
3873 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3874 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3875 _reg_PHY_DQS_TSEL_ENABLE));
3876 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3877 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3878 _reg_PHY_DQ_TSEL_SELECT));
3879 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3880 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3881 _reg_PHY_DQS_TSEL_SELECT));
3882
3883 retry_cnt = 0;
3884 do {
3885 err = rdqdm_man1();
3886 ddrphy_regif_idle();
3887 } while (err && (++retry_cnt < retry_max));
3888 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3889 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3890 _reg_PHY_DQ_TSEL_ENABLE));
3891 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3892 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3893 _reg_PHY_DQS_TSEL_ENABLE));
3894 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3895 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3896 _reg_PHY_DQ_TSEL_SELECT));
3897 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3898 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3899 _reg_PHY_DQS_TSEL_SELECT));
3900
3901 return (retry_cnt >= retry_max);
3902}
3903
Marek Vasut6a131772019-08-07 19:56:09 +02003904/* rx offset calibration */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003905static int32_t _find_change(uint64_t val, uint32_t dir)
3906{
3907 int32_t i;
3908 uint32_t startval;
3909 uint32_t curval;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003910 const int32_t VAL_END = 0x3f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003911
3912 if (dir == 0) {
3913 startval = (val & 0x01);
3914 for (i = 1; i <= VAL_END; i++) {
3915 curval = (val >> i) & 0x01;
3916 if (curval != startval)
Marek Vasut6a131772019-08-07 19:56:09 +02003917 return i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003918 }
Marek Vasut6a131772019-08-07 19:56:09 +02003919 return VAL_END;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003920 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003921
3922 startval = (val >> dir) & 0x01;
3923 for (i = dir - 1; i >= 0; i--) {
3924 curval = (val >> i) & 0x01;
3925 if (curval != startval)
3926 return i;
3927 }
3928 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003929}
3930
3931static uint32_t _rx_offset_cal_updn(uint32_t code)
3932{
3933 const uint32_t CODE_MAX = 0x40;
3934 uint32_t tmp;
3935
Marek Vasut38dc7562019-08-07 19:17:42 +02003936 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003937 if (code == 0)
3938 tmp = (1U << 6) | (CODE_MAX - 1);
3939 else if (code <= 0x20)
3940 tmp =
3941 ((CODE_MAX - 1 -
3942 (0x20 - code) * 2) << 6) | (CODE_MAX - 1);
3943 else
3944 tmp =
3945 ((CODE_MAX - 1) << 6) | (CODE_MAX - 1 -
3946 (code - 0x20) * 2);
3947 } else {
3948 if (code == 0)
3949 tmp = (1U << 6) | (CODE_MAX - 1);
3950 else
3951 tmp = (code << 6) | (CODE_MAX - code);
3952 }
3953 return tmp;
3954}
3955
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003956static uint32_t rx_offset_cal(void)
3957{
3958 uint32_t index;
3959 uint32_t code;
3960 const uint32_t CODE_MAX = 0x40;
3961 const uint32_t CODE_STEP = 2;
3962 uint32_t ch, slice;
3963 uint32_t tmp;
3964 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
3965 uint64_t val[DRAM_CH_CNT][SLICE_CNT][_reg_PHY_RX_CAL_X_NUM];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003966 uint64_t tmpval;
3967 int32_t lsb, msb;
Marek Vasut6c245a52018-12-12 18:06:39 +01003968
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003969 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x01);
3970 foreach_vch(ch) {
3971 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003972 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003973 val[ch][slice][index] = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003974 }
3975 }
3976
3977 for (code = 0; code < CODE_MAX / CODE_STEP; code++) {
3978 tmp = _rx_offset_cal_updn(code * CODE_STEP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003979 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) {
3980 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[index], tmp);
3981 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003982 dsb_sev();
Marek Vasut80784f92019-08-07 19:02:26 +02003983 ddr_getval_ach_as(_reg_PHY_RX_CAL_OBS, (uint32_t *)tmp_ach_as);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003984
3985 foreach_vch(ch) {
3986 for (slice = 0; slice < SLICE_CNT; slice++) {
3987 tmp = tmp_ach_as[ch][slice];
3988 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3989 index++) {
3990 if (tmp & (1U << index)) {
3991 val[ch][slice][index] |=
3992 (1ULL << code);
3993 } else {
3994 val[ch][slice][index] &=
3995 ~(1ULL << code);
3996 }
3997 }
3998 }
3999 }
4000 }
4001 foreach_vch(ch) {
4002 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004003 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
4004 index++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004005 tmpval = val[ch][slice][index];
4006 lsb = _find_change(tmpval, 0);
4007 msb =
4008 _find_change(tmpval,
4009 (CODE_MAX / CODE_STEP) - 1);
4010 tmp = (lsb + msb) >> 1;
4011
4012 tmp = _rx_offset_cal_updn(tmp * CODE_STEP);
4013 ddr_setval_s(ch, slice,
4014 _reg_PHY_RX_CAL_X[index], tmp);
4015 }
4016 }
4017 }
4018 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004019
4020 return 0;
4021}
4022
4023static uint32_t rx_offset_cal_hw(void)
4024{
4025 uint32_t ch, slice;
4026 uint32_t retry;
4027 uint32_t complete;
4028 uint32_t tmp;
4029 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
4030
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004031 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[9], 0x00);
4032 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
4033 ddr_setval_ach_as(_reg_PHY_RX_CAL_SAMPLE_WAIT, 0x0f);
4034
4035 retry = 0;
4036 while (retry < 4096) {
4037 if ((retry & 0xff) == 0) {
4038 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
4039 }
4040 foreach_vch(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02004041 for (slice = 0; slice < SLICE_CNT; slice++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004042 tmp_ach_as[ch][slice] =
4043 ddr_getval_s(ch, slice, _reg_PHY_RX_CAL_X[9]);
4044
4045 complete = 1;
4046 foreach_vch(ch) {
4047 for (slice = 0; slice < SLICE_CNT; slice++) {
4048 tmp = tmp_ach_as[ch][slice];
4049 tmp = (tmp & 0x3f) + ((tmp >> 6) & 0x3f);
Marek Vasut6a131772019-08-07 19:56:09 +02004050 if (((prr_product == PRR_PRODUCT_H3) &&
4051 (prr_cut > PRR_PRODUCT_11)) ||
4052 (prr_product == PRR_PRODUCT_M3N) ||
4053 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004054 if (tmp != 0x3E)
4055 complete = 0;
4056 } else {
4057 if (tmp != 0x40)
4058 complete = 0;
4059 }
4060 }
4061 }
4062 if (complete)
4063 break;
4064
4065 retry++;
4066 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004067
4068 return (complete == 0);
4069}
4070
Marek Vasut6a131772019-08-07 19:56:09 +02004071/* adjust rddqs latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004072static void adjust_rddqs_latency(void)
4073{
4074 uint32_t ch, slice;
4075 uint32_t dly;
4076 uint32_t maxlatx2;
4077 uint32_t tmp;
4078 uint32_t rdlat_adjx2[SLICE_CNT];
Marek Vasut80784f92019-08-07 19:02:26 +02004079
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004080 foreach_vch(ch) {
4081 maxlatx2 = 0;
4082 for (slice = 0; slice < SLICE_CNT; slice++) {
4083 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX,
4084 0x00);
4085
4086 dly =
4087 ddr_getval_s(ch, slice,
4088 _reg_PHY_RDDQS_GATE_SLAVE_DELAY);
4089 tmp =
4090 ddr_getval_s(ch, slice,
4091 _reg_PHY_RDDQS_LATENCY_ADJUST);
4092 /* note gate_slave_delay[9] is always 0 */
4093 tmp = (tmp << 1) + (dly >> 8);
4094 rdlat_adjx2[slice] = tmp;
4095 if (maxlatx2 < tmp)
4096 maxlatx2 = tmp;
4097 }
4098 maxlatx2 = ((maxlatx2 + 1) >> 1) << 1;
4099 for (slice = 0; slice < SLICE_CNT; slice++) {
4100 tmp = maxlatx2 - rdlat_adjx2[slice];
4101 tmp = (tmp >> 1);
4102 if (tmp) {
4103 ddr_setval_s(ch, slice, _reg_PHY_RPTR_UPDATE,
4104 ddr_getval_s(ch, slice,
4105 _reg_PHY_RPTR_UPDATE)
4106 + 1);
4107 }
4108 }
4109 }
4110}
4111
Marek Vasut6a131772019-08-07 19:56:09 +02004112/* adjust wpath latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004113static void adjust_wpath_latency(void)
4114{
4115 uint32_t ch, cs, slice;
4116 uint32_t dly;
4117 uint32_t wpath_add;
4118 const uint32_t _par_EARLY_THRESHOLD_VAL = 0x180;
4119
4120 foreach_vch(ch) {
4121 for (slice = 0; slice < SLICE_CNT; slice += 1) {
4122 for (cs = 0; cs < CS_CNT; cs++) {
4123 ddr_setval_s(ch, slice,
4124 _reg_PHY_PER_CS_TRAINING_INDEX,
4125 cs);
4126 ddr_getval_s(ch, slice,
4127 _reg_PHY_PER_CS_TRAINING_INDEX);
4128 dly =
4129 ddr_getval_s(ch, slice,
4130 _reg_PHY_CLK_WRDQS_SLAVE_DELAY);
4131 if (dly <= _par_EARLY_THRESHOLD_VAL)
4132 continue;
4133
4134 wpath_add =
4135 ddr_getval_s(ch, slice,
4136 _reg_PHY_WRITE_PATH_LAT_ADD);
4137 ddr_setval_s(ch, slice,
4138 _reg_PHY_WRITE_PATH_LAT_ADD,
4139 wpath_add - 1);
4140 }
4141 }
4142 }
4143}
4144
Marek Vasut6a131772019-08-07 19:56:09 +02004145/* DDR Initialize entry */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004146int32_t rcar_dram_init(void)
4147{
4148 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02004149 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004150 uint32_t bus_mbps, bus_mbpsdiv;
4151 uint32_t tmp_tccd;
4152 uint32_t failcount;
Marek Vasut38dc7562019-08-07 19:17:42 +02004153 uint32_t cnf_boardtype;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004154
Marek Vasut6a131772019-08-07 19:56:09 +02004155 /* Thermal sensor setting */
Marek Vasut38dc7562019-08-07 19:17:42 +02004156 data_l = mmio_read_32(CPG_MSTPSR5);
4157 if (data_l & BIT(22)) { /* case THS/TSC Standby */
Marek Vasut6a131772019-08-07 19:56:09 +02004158 data_l &= ~BIT(22);
Marek Vasut38dc7562019-08-07 19:17:42 +02004159 cpg_write_32(CPG_SMSTPCR5, data_l);
Marek Vasut6a131772019-08-07 19:56:09 +02004160 while (mmio_read_32(CPG_MSTPSR5) & BIT(22))
4161 ; /* wait bit=0 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004162 }
4163
4164 /* THCTR Bit6: PONM=0 , Bit0: THSST=0 */
Chiaki Fujii750b5c92020-10-30 10:45:18 +09004165 data_l = mmio_read_32(THS1_THCTR);
4166 if (data_l & 0x00000040U) {
4167 data_l = data_l & 0xFFFFFFBEU;
4168 } else {
4169 data_l = data_l | BIT(1);
4170 }
4171
Marek Vasut38dc7562019-08-07 19:17:42 +02004172 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004173
Marek Vasut6a131772019-08-07 19:56:09 +02004174 /* Judge product and cut */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004175#ifdef RCAR_DDR_FIXED_LSI_TYPE
Marek Vasut80784f92019-08-07 19:02:26 +02004176#if (RCAR_LSI == RCAR_AUTO)
Marek Vasut38dc7562019-08-07 19:17:42 +02004177 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4178 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004179#else /* RCAR_LSI */
4180#ifndef RCAR_LSI_CUT
Marek Vasut38dc7562019-08-07 19:17:42 +02004181 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004182#endif /* RCAR_LSI_CUT */
4183#endif /* RCAR_LSI */
4184#else /* RCAR_DDR_FIXED_LSI_TYPE */
Marek Vasut38dc7562019-08-07 19:17:42 +02004185 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4186 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004187#endif /* RCAR_DDR_FIXED_LSI_TYPE */
4188
Marek Vasut38dc7562019-08-07 19:17:42 +02004189 if (prr_product == PRR_PRODUCT_H3) {
4190 if (prr_cut <= PRR_PRODUCT_11) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004191 p_ddr_regdef_tbl =
4192 (const uint32_t *)&DDR_REGDEF_TBL[0][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004193 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004194 p_ddr_regdef_tbl =
4195 (const uint32_t *)&DDR_REGDEF_TBL[2][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004196 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004197 } else if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004198 p_ddr_regdef_tbl =
4199 (const uint32_t *)&DDR_REGDEF_TBL[1][0];
Marek Vasut6a131772019-08-07 19:56:09 +02004200 } else if ((prr_product == PRR_PRODUCT_M3N) ||
4201 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004202 p_ddr_regdef_tbl =
4203 (const uint32_t *)&DDR_REGDEF_TBL[3][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004204 } else {
Marek Vasut6c245a52018-12-12 18:06:39 +01004205 FATAL_MSG("BL2: DDR:Unknown Product\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004206 return 0xff;
4207 }
4208
Marek Vasut6a131772019-08-07 19:56:09 +02004209 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4210 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004211 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4212 } else {
4213 mmio_write_32(DBSC_DBSYSCNT0, 0x00001234);
4214 }
4215
Marek Vasut6a131772019-08-07 19:56:09 +02004216 /* Judge board type */
Marek Vasut38dc7562019-08-07 19:17:42 +02004217 cnf_boardtype = boardcnf_get_brd_type();
4218 if (cnf_boardtype >= BOARDNUM) {
Marek Vasut6c245a52018-12-12 18:06:39 +01004219 FATAL_MSG("BL2: DDR:Unknown Board\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004220 return 0xff;
4221 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004222 board_cnf = (const struct _boardcnf *)&boardcnfs[cnf_boardtype];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004223
4224/* RCAR_DRAM_SPLIT_2CH (2U) */
4225#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02004226 /* H3(Test for future H3-N): Swap ch2 and ch1 for 2ch-split */
Marek Vasut38dc7562019-08-07 19:17:42 +02004227 if ((prr_product == PRR_PRODUCT_H3) && (board_cnf->phyvalid == 0x05)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004228 mmio_write_32(DBSC_DBMEMSWAPCONF0, 0x00000006);
4229 ddr_phyvalid = 0x03;
4230 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004231 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004232 }
4233#else /* RCAR_DRAM_SPLIT_2CH */
Marek Vasut38dc7562019-08-07 19:17:42 +02004234 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004235#endif /* RCAR_DRAM_SPLIT_2CH */
4236
4237 max_density = 0;
4238
4239 for (cs = 0; cs < CS_CNT; cs++) {
4240 ch_have_this_cs[cs] = 0;
4241 }
4242
4243 foreach_ech(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02004244 for (cs = 0; cs < CS_CNT; cs++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004245 ddr_density[ch][cs] = 0xff;
4246
4247 foreach_vch(ch) {
4248 for (cs = 0; cs < CS_CNT; cs++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004249 data_l = board_cnf->ch[ch].ddr_density[cs];
4250 ddr_density[ch][cs] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004251
Marek Vasut38dc7562019-08-07 19:17:42 +02004252 if (data_l == 0xff)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004253 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02004254 if (data_l > max_density)
4255 max_density = data_l;
Marek Vasut6a131772019-08-07 19:56:09 +02004256 if ((cs == 1) && (prr_product == PRR_PRODUCT_H3) &&
4257 (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004258 continue;
4259 ch_have_this_cs[cs] |= (1U << ch);
4260 }
4261 }
4262
Marek Vasut6a131772019-08-07 19:56:09 +02004263 /* Judge board clock frequency (in MHz) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004264 boardcnf_get_brd_clk(cnf_boardtype, &brd_clk, &brd_clkdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004265 if ((brd_clk / brd_clkdiv) > 25) {
4266 brd_clkdiva = 1;
4267 } else {
4268 brd_clkdiva = 0;
4269 }
4270
Marek Vasut6a131772019-08-07 19:56:09 +02004271 /* Judge ddr operating frequency clock(in Mbps) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004272 boardcnf_get_ddr_mbps(cnf_boardtype, &ddr_mbps, &ddr_mbpsdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004273
4274 ddr0800_mul = CLK_DIV(800, 2, brd_clk, brd_clkdiv * (brd_clkdiva + 1));
4275
Marek Vasut80784f92019-08-07 19:02:26 +02004276 ddr_mul = CLK_DIV(ddr_mbps, ddr_mbpsdiv * 2, brd_clk,
4277 brd_clkdiv * (brd_clkdiva + 1));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004278
Marek Vasut6a131772019-08-07 19:56:09 +02004279 /* Adjust tccd */
Marek Vasut38dc7562019-08-07 19:17:42 +02004280 data_l = (0x00006000 & mmio_read_32(RST_MODEMR)) >> 13;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09004281 bus_mbps = 0;
4282 bus_mbpsdiv = 0;
Marek Vasut38dc7562019-08-07 19:17:42 +02004283 switch (data_l) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004284 case 0:
4285 bus_mbps = brd_clk * 0x60 * 2;
4286 bus_mbpsdiv = brd_clkdiv * 1;
4287 break;
4288 case 1:
4289 bus_mbps = brd_clk * 0x50 * 2;
4290 bus_mbpsdiv = brd_clkdiv * 1;
4291 break;
4292 case 2:
4293 bus_mbps = brd_clk * 0x40 * 2;
4294 bus_mbpsdiv = brd_clkdiv * 1;
4295 break;
4296 case 3:
4297 bus_mbps = brd_clk * 0x60 * 2;
4298 bus_mbpsdiv = brd_clkdiv * 2;
4299 break;
4300 default:
4301 bus_mbps = brd_clk * 0x60 * 2;
4302 bus_mbpsdiv = brd_clkdiv * 2;
4303 break;
4304 }
4305 tmp_tccd = CLK_DIV(ddr_mbps * 8, ddr_mbpsdiv, bus_mbps, bus_mbpsdiv);
4306 if (8 * ddr_mbps * bus_mbpsdiv != tmp_tccd * bus_mbps * ddr_mbpsdiv)
4307 tmp_tccd = tmp_tccd + 1;
4308
4309 if (tmp_tccd < 8)
4310 ddr_tccd = 8;
4311 else
4312 ddr_tccd = tmp_tccd;
4313
Marek Vasut6c245a52018-12-12 18:06:39 +01004314 NOTICE("BL2: DDR%d(%s)\n", ddr_mbps / ddr_mbpsdiv, RCAR_DDR_VERSION);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004315
4316 MSG_LF("Start\n");
4317
Marek Vasut6a131772019-08-07 19:56:09 +02004318 /* PLL Setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004319 pll3_control(1);
4320
Marek Vasut6a131772019-08-07 19:56:09 +02004321 /* initialize DDR */
Marek Vasut38dc7562019-08-07 19:17:42 +02004322 data_l = init_ddr();
4323 if (data_l == ddr_phyvalid) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004324 failcount = 0;
4325 } else {
4326 failcount = 1;
4327 }
4328
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004329 foreach_vch(ch)
4330 mmio_write_32(DBSC_DBPDLK(ch), 0x00000000);
Marek Vasut6a131772019-08-07 19:56:09 +02004331 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4332 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004333 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4334 } else {
4335 mmio_write_32(DBSC_DBSYSCNT0, 0x00000000);
4336 }
4337
4338 if (failcount == 0) {
4339 return INITDRAM_OK;
4340 } else {
4341 return INITDRAM_NG;
4342 }
4343}
4344
4345void pvtcode_update(void)
4346{
4347 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004348 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004349 uint32_t pvtp[4], pvtn[4], pvtp_init, pvtn_init;
4350 int32_t pvtp_tmp, pvtn_tmp;
4351
4352 foreach_vch(ch) {
4353 pvtn_init = (tcal.tcomp_cal[ch] & 0xFC0) >> 6;
4354 pvtp_init = (tcal.tcomp_cal[ch] & 0x03F) >> 0;
4355
4356 if (8912 * pvtp_init > 44230) {
4357 pvtp_tmp = (5000 + 8912 * pvtp_init - 44230) / 10000;
4358 } else {
4359 pvtp_tmp =
4360 -((-(5000 + 8912 * pvtp_init - 44230)) / 10000);
4361 }
4362 pvtn_tmp = (5000 + 5776 * pvtn_init + 30280) / 10000;
4363
4364 pvtn[ch] = pvtn_tmp + pvtn_init;
4365 pvtp[ch] = pvtp_tmp + pvtp_init;
4366
4367 if (pvtn[ch] > 63) {
4368 pvtn[ch] = 63;
4369 pvtp[ch] =
4370 (pvtp_tmp) * (63 - 6 * pvtn_tmp -
4371 pvtn_init) / (pvtn_tmp) +
4372 6 * pvtp_tmp + pvtp_init;
4373 }
Marek Vasut6a131772019-08-07 19:56:09 +02004374 if ((prr_product == PRR_PRODUCT_H3) &&
4375 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004376 data_l = pvtp[ch] | (pvtn[ch] << 6) |
4377 (tcal.tcomp_cal[ch] & 0xfffff000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004378 reg_ddrphy_write(ch,
4379 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004380 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004381 reg_ddrphy_write(ch,
4382 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004383 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004384 reg_ddrphy_write(ch,
4385 ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004386 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004387 reg_ddrphy_write(ch,
4388 ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004389 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004390 reg_ddrphy_write(ch,
4391 ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004392 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004393 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004394 data_l = pvtp[ch] | (pvtn[ch] << 6) | 0x00015000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004395 reg_ddrphy_write(ch,
4396 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004397 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004398 reg_ddrphy_write(ch,
4399 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004400 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004401 reg_ddrphy_write(ch,
4402 ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004403 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004404 reg_ddrphy_write(ch,
4405 ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004406 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004407 reg_ddrphy_write(ch,
4408 ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004409 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004410 }
4411 }
4412}
4413
4414void pvtcode_update2(void)
4415{
4416 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02004417
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004418 foreach_vch(ch) {
4419 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
4420 tcal.init_cal[ch] | 0x00020000);
4421 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
4422 tcal.init_cal[ch]);
4423 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
4424 tcal.init_cal[ch]);
4425 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
4426 tcal.init_cal[ch]);
4427 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
4428 tcal.init_cal[ch]);
4429 }
4430}
4431
4432void ddr_padcal_tcompensate_getinit(uint32_t override)
4433{
4434 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004435 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004436 uint32_t pvtp, pvtn;
4437
4438 tcal.init_temp = 0;
4439 for (ch = 0; ch < 4; ch++) {
4440 tcal.init_cal[ch] = 0;
4441 tcal.tcomp_cal[ch] = 0;
4442 }
4443
4444 foreach_vch(ch) {
4445 tcal.init_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4446 tcal.tcomp_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4447 }
4448
4449 if (!override) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004450 data_l = mmio_read_32(THS1_TEMP);
4451 if (data_l < 2800) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004452 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004453 (143 * (int32_t)data_l - 359000) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004454 } else {
4455 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004456 (121 * (int32_t)data_l - 296300) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004457 }
4458
4459 foreach_vch(ch) {
4460 pvtp = (tcal.init_cal[ch] >> 0) & 0x000003F;
4461 pvtn = (tcal.init_cal[ch] >> 6) & 0x000003F;
Marek Vasut80784f92019-08-07 19:02:26 +02004462 if ((int32_t)pvtp >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004463 ((tcal.init_temp * 29 - 3625) / 1000))
4464 pvtp =
Marek Vasut80784f92019-08-07 19:02:26 +02004465 (int32_t)pvtp +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004466 ((3625 - tcal.init_temp * 29) / 1000);
4467 else
4468 pvtp = 0;
4469
Marek Vasut80784f92019-08-07 19:02:26 +02004470 if ((int32_t)pvtn >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004471 ((tcal.init_temp * 54 - 6750) / 1000))
4472 pvtn =
Marek Vasut80784f92019-08-07 19:02:26 +02004473 (int32_t)pvtn +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004474 ((6750 - tcal.init_temp * 54) / 1000);
4475 else
4476 pvtn = 0;
4477
Marek Vasut6a131772019-08-07 19:56:09 +02004478 if ((prr_product == PRR_PRODUCT_H3) &&
4479 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004480 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004481 (tcal.init_cal[ch] & 0xfffff000) |
4482 (pvtn << 6) |
4483 pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004484 } else {
4485 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004486 0x00015000 | (pvtn << 6) | pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004487 }
4488 }
4489 tcal.init_temp = 125;
4490 }
4491}
4492
4493#ifndef ddr_qos_init_setting
Marek Vasut6ad74c32019-08-08 16:34:22 +02004494/* For QoS init */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004495uint8_t get_boardcnf_phyvalid(void)
4496{
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004497 return ddr_phyvalid;
4498}
4499#endif /* ddr_qos_init_setting */