blob: 8d002decaa7701f5bde09520fb4aeb38ab8096f2 [file] [log] [blame]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001/*
Lad Prabhakar9f2b5792021-03-10 14:30:20 +00002 * Copyright (c) 2015-2021, 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 ));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001183 }
1184
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001185 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LPDDR3_CS),
Marek Vasut6a131772019-08-07 19:56:09 +02001186 _cnf_DDR_PHY_ADR_G_REGSET
1187 [ddr_regdef_adr(_reg_PHY_LPDDR3_CS) -
1188 DDR_PHY_ADR_G_REGSET_OFS]);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001189
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001190 /* protect register interface */
1191 ddrphy_regif_idle();
1192 pll3_control(0);
1193
Marek Vasut38dc7562019-08-07 19:17:42 +02001194 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001195 /* non */
1196 } else {
1197 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_DLL_RST_EN),
1198 (0x01U <<
1199 ddr_regdef_lsb(_reg_PHY_DLL_RST_EN)));
1200 ddrphy_regif_idle();
1201 }
1202
Marek Vasut6a131772019-08-07 19:56:09 +02001203 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001204 /* dbdficnt0:
1205 * dfi_dram_clk_disable=1
1206 * dfi_frequency = 0
1207 * freq_ratio = 01 (2:1)
1208 * init_start =0
1209 */
1210 foreach_vch(ch)
1211 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
1212 dsb_sev();
1213
1214 /* dbdficnt0:
1215 * dfi_dram_clk_disable=1
1216 * dfi_frequency = 0
1217 * freq_ratio = 01 (2:1)
1218 * init_start =1
1219 */
1220 foreach_vch(ch)
1221 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
1222 dsb_sev();
1223
1224 foreach_ech(ch)
Marek Vasut6a131772019-08-07 19:56:09 +02001225 if ((board_cnf->phyvalid) & BIT(ch))
1226 while ((mmio_read_32(DBSC_PLL_LOCK(ch)) & 0x1f) != 0x1f)
1227 ;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001228 dsb_sev();
1229}
1230
Marek Vasut6a131772019-08-07 19:56:09 +02001231/* load table data into DDR registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001232static void ddrtbl_load(void)
1233{
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001234 uint32_t i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001235 uint32_t slice;
1236 uint32_t csab;
1237 uint32_t adr;
Marek Vasut38dc7562019-08-07 19:17:42 +02001238 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001239 uint32_t tmp[3];
1240 uint16_t dataS;
1241
Marek Vasut6a131772019-08-07 19:56:09 +02001242 /* TIMING REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001243 /* search jedec_spec1 index */
1244 for (i = JS1_USABLEC_SPEC_LO; i < JS1_FREQ_TBL_NUM - 1; i++) {
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001245 if (js1[i].fx3 * 2U * ddr_mbpsdiv >= ddr_mbps * 3U)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001246 break;
1247 }
Marek Vasut80784f92019-08-07 19:02:26 +02001248 if (i > JS1_USABLEC_SPEC_HI)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001249 js1_ind = JS1_USABLEC_SPEC_HI;
1250 else
1251 js1_ind = i;
1252
Marek Vasut38dc7562019-08-07 19:17:42 +02001253 if (board_cnf->dbi_en)
1254 RL = js1[js1_ind].rlwdbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001255 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001256 RL = js1[js1_ind].rlwodbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001257
1258 WL = js1[js1_ind].WL;
1259
1260 /* calculate jedec_spec2 */
1261 _f_scale_js2(ddr_mbps, ddr_mbpsdiv, js2);
1262
Marek Vasut6a131772019-08-07 19:56:09 +02001263 /* PREPARE TBL */
Marek Vasut38dc7562019-08-07 19:17:42 +02001264 if (prr_product == PRR_PRODUCT_H3) {
1265 if (prr_cut <= PRR_PRODUCT_11) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001266 /* H3 Ver.1.x */
1267 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1268 DDR_PHY_SLICE_REGSET_H3,
1269 DDR_PHY_SLICE_REGSET_NUM_H3);
1270 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1271 DDR_PHY_ADR_V_REGSET_H3,
1272 DDR_PHY_ADR_V_REGSET_NUM_H3);
1273 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET,
1274 DDR_PHY_ADR_I_REGSET_H3,
1275 DDR_PHY_ADR_I_REGSET_NUM_H3);
1276 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1277 DDR_PHY_ADR_G_REGSET_H3,
1278 DDR_PHY_ADR_G_REGSET_NUM_H3);
1279 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3,
1280 DDR_PI_REGSET_NUM_H3);
1281
1282 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_H3;
1283 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_H3;
1284 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_H3;
1285 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_H3;
1286 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3;
1287 DDR_PHY_SLICE_REGSET_SIZE =
1288 DDR_PHY_SLICE_REGSET_SIZE_H3;
1289 DDR_PHY_ADR_V_REGSET_SIZE =
1290 DDR_PHY_ADR_V_REGSET_SIZE_H3;
1291 DDR_PHY_ADR_I_REGSET_SIZE =
1292 DDR_PHY_ADR_I_REGSET_SIZE_H3;
1293 DDR_PHY_ADR_G_REGSET_SIZE =
1294 DDR_PHY_ADR_G_REGSET_SIZE_H3;
1295 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3;
1296 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_H3;
1297 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_H3;
1298 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_H3;
1299 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_H3;
1300 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3;
1301
1302 DDR_PHY_ADR_I_NUM = 1;
1303 } else {
1304 /* H3 Ver.2.0 or later */
1305 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1306 DDR_PHY_SLICE_REGSET_H3VER2,
1307 DDR_PHY_SLICE_REGSET_NUM_H3VER2);
1308 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1309 DDR_PHY_ADR_V_REGSET_H3VER2,
1310 DDR_PHY_ADR_V_REGSET_NUM_H3VER2);
1311 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1312 DDR_PHY_ADR_G_REGSET_H3VER2,
1313 DDR_PHY_ADR_G_REGSET_NUM_H3VER2);
1314 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3VER2,
1315 DDR_PI_REGSET_NUM_H3VER2);
1316
1317 DDR_PHY_SLICE_REGSET_OFS =
1318 DDR_PHY_SLICE_REGSET_OFS_H3VER2;
1319 DDR_PHY_ADR_V_REGSET_OFS =
1320 DDR_PHY_ADR_V_REGSET_OFS_H3VER2;
1321 DDR_PHY_ADR_G_REGSET_OFS =
1322 DDR_PHY_ADR_G_REGSET_OFS_H3VER2;
1323 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3VER2;
1324 DDR_PHY_SLICE_REGSET_SIZE =
1325 DDR_PHY_SLICE_REGSET_SIZE_H3VER2;
1326 DDR_PHY_ADR_V_REGSET_SIZE =
1327 DDR_PHY_ADR_V_REGSET_SIZE_H3VER2;
1328 DDR_PHY_ADR_G_REGSET_SIZE =
1329 DDR_PHY_ADR_G_REGSET_SIZE_H3VER2;
1330 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3VER2;
1331 DDR_PHY_SLICE_REGSET_NUM =
1332 DDR_PHY_SLICE_REGSET_NUM_H3VER2;
1333 DDR_PHY_ADR_V_REGSET_NUM =
1334 DDR_PHY_ADR_V_REGSET_NUM_H3VER2;
1335 DDR_PHY_ADR_G_REGSET_NUM =
1336 DDR_PHY_ADR_G_REGSET_NUM_H3VER2;
1337 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3VER2;
1338
1339 DDR_PHY_ADR_I_NUM = 0;
1340 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001341 } else if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001342 /* M3-W */
1343 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1344 DDR_PHY_SLICE_REGSET_M3, DDR_PHY_SLICE_REGSET_NUM_M3);
1345 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1346 DDR_PHY_ADR_V_REGSET_M3, DDR_PHY_ADR_V_REGSET_NUM_M3);
1347 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET,
1348 DDR_PHY_ADR_I_REGSET_M3, DDR_PHY_ADR_I_REGSET_NUM_M3);
1349 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1350 DDR_PHY_ADR_G_REGSET_M3, DDR_PHY_ADR_G_REGSET_NUM_M3);
1351 _tblcopy(_cnf_DDR_PI_REGSET,
1352 DDR_PI_REGSET_M3, DDR_PI_REGSET_NUM_M3);
1353
1354 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3;
1355 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3;
1356 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3;
1357 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3;
1358 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3;
1359 DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3;
1360 DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3;
1361 DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3;
1362 DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3;
1363 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3;
1364 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3;
1365 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3;
1366 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3;
1367 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3;
1368 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3;
1369
1370 DDR_PHY_ADR_I_NUM = 2;
1371 } else {
1372 /* M3-N/V3H */
1373 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1374 DDR_PHY_SLICE_REGSET_M3N,
1375 DDR_PHY_SLICE_REGSET_NUM_M3N);
1376 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, DDR_PHY_ADR_V_REGSET_M3N,
1377 DDR_PHY_ADR_V_REGSET_NUM_M3N);
1378 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, DDR_PHY_ADR_I_REGSET_M3N,
1379 DDR_PHY_ADR_I_REGSET_NUM_M3N);
1380 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, DDR_PHY_ADR_G_REGSET_M3N,
1381 DDR_PHY_ADR_G_REGSET_NUM_M3N);
1382 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_M3N,
1383 DDR_PI_REGSET_NUM_M3N);
1384
1385 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3N;
1386 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3N;
1387 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3N;
1388 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3N;
1389 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3N;
1390 DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3N;
1391 DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3N;
1392 DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3N;
1393 DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3N;
1394 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3N;
1395 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3N;
1396 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3N;
1397 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3N;
1398 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3N;
1399 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3N;
1400
1401 DDR_PHY_ADR_I_NUM = 2;
1402 }
1403
Marek Vasut6a131772019-08-07 19:56:09 +02001404 /* PLL CODE CHANGE */
Marek Vasut38dc7562019-08-07 19:17:42 +02001405 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001406 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, _reg_PHY_PLL_CTRL,
1407 0x1142);
1408 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1409 _reg_PHY_LP4_BOOT_PLL_CTRL, 0x1142);
1410 }
1411
Marek Vasut6a131772019-08-07 19:56:09 +02001412 /* on fly gate adjust */
Marek Vasut38dc7562019-08-07 19:17:42 +02001413 if ((prr_product == PRR_PRODUCT_M3) && (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001414 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1415 _reg_ON_FLY_GATE_ADJUST_EN, 0x00);
1416 }
1417
Marek Vasut6a131772019-08-07 19:56:09 +02001418 /* Adjust PI parameters */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001419#ifdef _def_LPDDR4_ODT
Marek Vasut6c245a52018-12-12 18:06:39 +01001420 for (i = 0; i < 2; i++) {
1421 for (csab = 0; csab < CSAB_CNT; csab++) {
1422 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001423 reg_pi_mr11_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001424 _def_LPDDR4_ODT);
1425 }
1426 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001427#endif /* _def_LPDDR4_ODT */
1428
1429#ifdef _def_LPDDR4_VREFCA
Marek Vasut6c245a52018-12-12 18:06:39 +01001430 for (i = 0; i < 2; i++) {
1431 for (csab = 0; csab < CSAB_CNT; csab++) {
1432 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001433 reg_pi_mr12_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001434 _def_LPDDR4_VREFCA);
1435 }
1436 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001437#endif /* _def_LPDDR4_VREFCA */
Marek Vasut6a131772019-08-07 19:56:09 +02001438 if ((prr_product == PRR_PRODUCT_M3N) ||
1439 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001440 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 7000, 0) + 7U;
1441 if (js2[js2_tiedly] > (RL))
1442 js2[js2_tiedly] = RL;
Marek Vasut6a131772019-08-07 19:56:09 +02001443 } else if ((prr_product == PRR_PRODUCT_H3) &&
1444 (prr_cut > PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001445 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 9000, 0) + 4U;
Marek Vasut6a131772019-08-07 19:56:09 +02001446 } else if ((prr_product == PRR_PRODUCT_H3) &&
1447 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001448 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 10000, 0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001449 }
1450
Marek Vasut6a131772019-08-07 19:56:09 +02001451 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
1452 (prr_product == PRR_PRODUCT_M3N) ||
1453 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001454 if ((js2[js2_tiedly]) >= 0x1e)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001455 dataS = 0x1e;
1456 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001457 dataS = js2[js2_tiedly];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001458 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001459 if ((js2[js2_tiedly]) >= 0x0e)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001460 dataS = 0x0e;
1461 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001462 dataS = js2[js2_tiedly];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001463 }
1464
1465 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_DLY, dataS);
1466 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_TSEL_DLY,
1467 (dataS - 2));
Marek Vasut6a131772019-08-07 19:56:09 +02001468 if ((prr_product == PRR_PRODUCT_M3N) ||
1469 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001470 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001471 _reg_PHY_RDDATA_EN_OE_DLY, dataS - 2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001472 }
1473 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1, RL - dataS);
1474
1475 if (ddrtbl_getval
1476 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001477 data_l = WL - 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001478 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001479 data_l = WL;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001480 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001481 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1, data_l - 2);
1482 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001483
Marek Vasut38dc7562019-08-07 19:17:42 +02001484 if (board_cnf->dbi_en) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001485 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE,
1486 0x01);
1487 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1488 _reg_PHY_WDQLVL_DATADM_MASK, 0x000);
1489 } else {
1490 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE,
1491 0x00);
1492 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1493 _reg_PHY_WDQLVL_DATADM_MASK, 0x100);
1494 }
1495
1496 tmp[0] = js1[js1_ind].MR1;
1497 tmp[1] = js1[js1_ind].MR2;
Marek Vasut38dc7562019-08-07 19:17:42 +02001498 data_l = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_MR3_DATA_F1_0);
1499 if (board_cnf->dbi_en)
1500 tmp[2] = data_l | 0xc0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001501 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001502 tmp[2] = data_l & (~0xc0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001503
1504 for (i = 0; i < 2; i++) {
1505 for (csab = 0; csab < CSAB_CNT; csab++) {
1506 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001507 reg_pi_mr1_data_fx_csx[i][csab], tmp[0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001508 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001509 reg_pi_mr2_data_fx_csx[i][csab], tmp[1]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001510 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001511 reg_pi_mr3_data_fx_csx[i][csab], tmp[2]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001512 }
1513 }
1514
Marek Vasut6a131772019-08-07 19:56:09 +02001515 /* DDRPHY INT START */
Marek Vasut38dc7562019-08-07 19:17:42 +02001516 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001517 /* non */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001518 } else {
1519 regif_pll_wa();
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001520 dbwait_loop(5);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001521 }
1522
Marek Vasut6a131772019-08-07 19:56:09 +02001523 /* FREQ_SEL_MULTICAST & PER_CS_TRAINING_MULTICAST SET (for safety) */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001524 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
Marek Vasut6ad74c32019-08-08 16:34:22 +02001525 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001526 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x01);
1527
Marek Vasut6a131772019-08-07 19:56:09 +02001528 /* SET DATA SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001529 for (slice = 0; slice < SLICE_CNT; slice++) {
1530 adr =
1531 DDR_PHY_SLICE_REGSET_OFS +
1532 DDR_PHY_SLICE_REGSET_SIZE * slice;
1533 for (i = 0; i < DDR_PHY_SLICE_REGSET_NUM; i++) {
1534 reg_ddrphy_write_a(adr + i,
1535 _cnf_DDR_PHY_SLICE_REGSET[i]);
1536 }
1537 }
1538
Marek Vasut6a131772019-08-07 19:56:09 +02001539 /* SET ADR SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001540 adr = DDR_PHY_ADR_V_REGSET_OFS;
1541 for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) {
1542 reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_V_REGSET[i]);
1543 }
1544
Marek Vasut6a131772019-08-07 19:56:09 +02001545 if (((prr_product == PRR_PRODUCT_M3) ||
1546 (prr_product == PRR_PRODUCT_M3N)) &&
Marek Vasut38dc7562019-08-07 19:17:42 +02001547 ((0x00ffffff & (uint32_t)((board_cnf->ch[0].ca_swap) >> 40))
Marek Vasut6c245a52018-12-12 18:06:39 +01001548 != 0x00)) {
1549 adr = DDR_PHY_ADR_I_REGSET_OFS + DDR_PHY_ADR_I_REGSET_SIZE;
1550 for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) {
1551 reg_ddrphy_write_a(adr + i,
1552 _cnf_DDR_PHY_ADR_V_REGSET[i]);
1553 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02001554 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1555 _reg_PHY_ADR_DISABLE, 0x02);
Marek Vasut6c245a52018-12-12 18:06:39 +01001556 DDR_PHY_ADR_I_NUM -= 1;
1557 ddr_phycaslice = 1;
1558
1559#ifndef _def_LPDDR4_ODT
1560 for (i = 0; i < 2; i++) {
1561 for (csab = 0; csab < CSAB_CNT; csab++) {
1562 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001563 reg_pi_mr11_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001564 0x66);
1565 }
1566 }
1567#endif/* _def_LPDDR4_ODT */
1568 } else {
1569 ddr_phycaslice = 0;
1570 }
1571
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001572 if (DDR_PHY_ADR_I_NUM > 0) {
1573 for (slice = 0; slice < DDR_PHY_ADR_I_NUM; slice++) {
1574 adr =
1575 DDR_PHY_ADR_I_REGSET_OFS +
1576 DDR_PHY_ADR_I_REGSET_SIZE * slice;
1577 for (i = 0; i < DDR_PHY_ADR_I_REGSET_NUM; i++) {
1578 reg_ddrphy_write_a(adr + i,
1579 _cnf_DDR_PHY_ADR_I_REGSET
1580 [i]);
1581 }
1582 }
1583 }
1584
Marek Vasut6a131772019-08-07 19:56:09 +02001585 /* SET ADRCTRL SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001586 adr = DDR_PHY_ADR_G_REGSET_OFS;
1587 for (i = 0; i < DDR_PHY_ADR_G_REGSET_NUM; i++) {
1588 reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_G_REGSET[i]);
1589 }
1590
Marek Vasut6a131772019-08-07 19:56:09 +02001591 /* SET PI REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001592 adr = DDR_PI_REGSET_OFS;
1593 for (i = 0; i < DDR_PI_REGSET_NUM; i++) {
1594 reg_ddrphy_write_a(adr + i, _cnf_DDR_PI_REGSET[i]);
1595 }
1596}
1597
Marek Vasut6a131772019-08-07 19:56:09 +02001598/* CONFIGURE DDR REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001599static void ddr_config_sub(void)
1600{
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001601 uint32_t i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001602 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001603 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001604 uint32_t tmp;
1605 uint8_t high_byte[SLICE_CNT];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001606 const uint32_t _par_CALVL_DEVICE_MAP = 1;
Marek Vasut80784f92019-08-07 19:02:26 +02001607
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001608 foreach_vch(ch) {
Marek Vasut6a131772019-08-07 19:56:09 +02001609 /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001610 for (slice = 0; slice < SLICE_CNT; slice++) {
1611 high_byte[slice] =
Marek Vasut38dc7562019-08-07 19:17:42 +02001612 (board_cnf->ch[ch].dqs_swap >> (4 * slice)) % 2;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001613 ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE0,
Marek Vasut38dc7562019-08-07 19:17:42 +02001614 board_cnf->ch[ch].dq_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001615 ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE1,
Marek Vasut38dc7562019-08-07 19:17:42 +02001616 board_cnf->ch[ch].dm_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001617 if (high_byte[slice]) {
1618 /* HIGHER 16 BYTE */
1619 ddr_setval_s(ch, slice,
1620 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1621 0x00);
1622 } else {
1623 /* LOWER 16 BYTE */
1624 ddr_setval_s(ch, slice,
1625 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1626 0x01);
1627 }
1628 }
1629
Marek Vasut6a131772019-08-07 19:56:09 +02001630 /* BOARD SETTINGS (CA,ADDR_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001631 data_l = (0x00ffffff & (uint32_t)(board_cnf->ch[ch].ca_swap)) |
Marek Vasut6c245a52018-12-12 18:06:39 +01001632 0x00888888;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001633
1634 /* --- ADR_CALVL_SWIZZLE --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001635 if (prr_product == PRR_PRODUCT_M3) {
1636 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001637 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0,
1638 0x00000000);
Marek Vasut38dc7562019-08-07 19:17:42 +02001639 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001640 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1,
1641 0x00000000);
1642 ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP,
1643 _par_CALVL_DEVICE_MAP);
1644 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001645 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001646 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1, 0x00000000);
1647 ddr_setval(ch, _reg_PHY_CALVL_DEVICE_MAP,
1648 _par_CALVL_DEVICE_MAP);
1649 }
1650
1651 /* --- ADR_ADDR_SEL --- */
Marek Vasut6a131772019-08-07 19:56:09 +02001652 if ((prr_product == PRR_PRODUCT_H3) &&
1653 (prr_cut > PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001654 data_l = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001655 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001656 data_l = 0;
1657 tmp = board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001658 for (i = 0; i < 6; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001659 data_l |= ((tmp & 0x0f) << (i * 5));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001660 tmp = tmp >> 4;
1661 }
1662 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001663 ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01001664 if (ddr_phycaslice == 1) {
1665 /* ----------- adr slice2 swap ----------- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001666 tmp = (uint32_t)((board_cnf->ch[ch].ca_swap) >> 40);
1667 data_l = (tmp & 0x00ffffff) | 0x00888888;
Marek Vasut6c245a52018-12-12 18:06:39 +01001668
1669 /* --- ADR_CALVL_SWIZZLE --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001670 if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001671 ddr_setval_s(ch, 2,
1672 _reg_PHY_ADR_CALVL_SWIZZLE0_0,
1673 data_l);
1674 ddr_setval_s(ch, 2,
1675 _reg_PHY_ADR_CALVL_SWIZZLE1_0,
Marek Vasut6c245a52018-12-12 18:06:39 +01001676 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001677 ddr_setval_s(ch, 2,
1678 _reg_PHY_ADR_CALVL_SWIZZLE0_1,
1679 data_l);
1680 ddr_setval_s(ch, 2,
1681 _reg_PHY_ADR_CALVL_SWIZZLE1_1,
Marek Vasut6c245a52018-12-12 18:06:39 +01001682 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001683 ddr_setval_s(ch, 2,
1684 _reg_PHY_ADR_CALVL_DEVICE_MAP,
Marek Vasut6c245a52018-12-12 18:06:39 +01001685 _par_CALVL_DEVICE_MAP);
1686 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001687 ddr_setval_s(ch, 2,
1688 _reg_PHY_ADR_CALVL_SWIZZLE0,
1689 data_l);
1690 ddr_setval_s(ch, 2,
1691 _reg_PHY_ADR_CALVL_SWIZZLE1,
Marek Vasut6c245a52018-12-12 18:06:39 +01001692 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001693 ddr_setval_s(ch, 2,
1694 _reg_PHY_CALVL_DEVICE_MAP,
Marek Vasut6c245a52018-12-12 18:06:39 +01001695 _par_CALVL_DEVICE_MAP);
1696 }
1697
1698 /* --- ADR_ADDR_SEL --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001699 data_l = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01001700 for (i = 0; i < 6; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001701 data_l |= ((tmp & 0x0f) << (i * 5));
Marek Vasut6c245a52018-12-12 18:06:39 +01001702 tmp = tmp >> 4;
1703 }
1704
Marek Vasut38dc7562019-08-07 19:17:42 +02001705 ddr_setval_s(ch, 2, _reg_PHY_ADR_ADDR_SEL, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01001706 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001707
Marek Vasut6a131772019-08-07 19:56:09 +02001708 /* BOARD SETTINGS (BYTE_ORDER_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001709 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001710 /* --- DATA_BYTE_SWAP --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001711 data_l = 0;
1712 tmp = board_cnf->ch[ch].dqs_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001713 for (i = 0; i < 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001714 data_l |= ((tmp & 0x03) << (i * 2));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001715 tmp = tmp >> 4;
1716 }
1717 } else {
1718 /* --- DATA_BYTE_SWAP --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001719 data_l = board_cnf->ch[ch].dqs_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001720 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_EN, 0x01);
1721 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE0,
Marek Vasut38dc7562019-08-07 19:17:42 +02001722 (data_l) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001723 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE1,
Marek Vasut38dc7562019-08-07 19:17:42 +02001724 (data_l >> 4 * 1) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001725 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE2,
Marek Vasut38dc7562019-08-07 19:17:42 +02001726 (data_l >> 4 * 2) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001727 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE3,
Marek Vasut38dc7562019-08-07 19:17:42 +02001728 (data_l >> 4 * 3) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001729
1730 ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL_HIGH, 0x00);
1731 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001732 ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001733 }
1734}
1735
Marek Vasut80784f92019-08-07 19:02:26 +02001736static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001737{
1738 uint32_t slice;
1739 uint32_t tmp;
1740 uint32_t tgt;
Marek Vasut80784f92019-08-07 19:02:26 +02001741
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001742 if (ddr_csn / 2) {
1743 tgt = 3;
1744 } else {
1745 tgt = 1;
1746 }
1747
1748 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001749 tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001750 if (tgt == tmp)
1751 break;
1752 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001753 tmp = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001754 if (slice % 2)
1755 tmp |= 0x00888888;
1756 *p_swz = tmp;
1757}
1758
1759static void ddr_config_sub_h3v1x(void)
1760{
1761 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001762 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001763 uint32_t tmp;
1764 uint8_t high_byte[SLICE_CNT];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001765 uint32_t ca_swizzle;
1766 uint32_t ca;
1767 uint32_t csmap;
1768 uint32_t o_inv;
1769 uint32_t inv;
1770 uint32_t bit_soc;
1771 uint32_t bit_mem;
1772 uint32_t j;
1773
1774 const uint8_t o_mr15 = 0x55;
1775 const uint8_t o_mr20 = 0x55;
1776 const uint16_t o_mr32_mr40 = 0x5a3c;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001777
1778 foreach_vch(ch) {
Marek Vasut6a131772019-08-07 19:56:09 +02001779 /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001780 csmap = 0;
1781 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001782 tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) &
1783 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001784 high_byte[slice] = tmp % 2;
1785 if (tmp == 1 && (slice >= 2))
1786 csmap |= 0x05;
1787 if (tmp == 3 && (slice >= 2))
1788 csmap |= 0x50;
1789 ddr_setval_s(ch, slice, _reg_PHY_DQ_SWIZZLING,
Marek Vasut38dc7562019-08-07 19:17:42 +02001790 board_cnf->ch[ch].dq_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001791 if (high_byte[slice]) {
1792 /* HIGHER 16 BYTE */
1793 ddr_setval_s(ch, slice,
1794 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1795 0x00);
1796 } else {
1797 /* LOWER 16 BYTE */
1798 ddr_setval_s(ch, slice,
1799 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1800 0x01);
1801 }
1802 }
Marek Vasut6a131772019-08-07 19:56:09 +02001803 /* BOARD SETTINGS (CA,ADDR_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001804 ca = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001805 ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, ca);
1806 ddr_setval(ch, _reg_PHY_CALVL_CS_MAP, csmap);
1807
1808 get_ca_swizzle(ch, 0, &ca_swizzle);
1809
1810 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, ca_swizzle);
1811 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0, 0x00000000);
1812 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, 0x00000000);
1813 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1, 0x00000000);
1814 ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP, 0x01);
1815
1816 for (slice = 0; slice < SLICE_CNT; slice++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001817 ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_NUM,
1818 0x01);
1819 ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_START,
1820 0x08);
1821
1822 if (high_byte[slice])
1823 o_inv = o_mr20;
1824 else
1825 o_inv = o_mr15;
1826
Marek Vasut38dc7562019-08-07 19:17:42 +02001827 tmp = board_cnf->ch[ch].dq_swap[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001828 inv = 0;
1829 j = 0;
1830 for (bit_soc = 0; bit_soc < 8; bit_soc++) {
1831 bit_mem = (tmp >> (4 * bit_soc)) & 0x0f;
1832 j |= (1U << bit_mem);
1833 if (o_inv & (1U << bit_mem))
1834 inv |= (1U << bit_soc);
1835 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001836 data_l = o_mr32_mr40;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001837 if (!high_byte[slice])
Marek Vasut38dc7562019-08-07 19:17:42 +02001838 data_l |= (inv << 24);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001839 if (high_byte[slice])
Marek Vasut38dc7562019-08-07 19:17:42 +02001840 data_l |= (inv << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001841 ddr_setval_s(ch, slice, _reg_PHY_LP4_RDLVL_PATT8,
Marek Vasut38dc7562019-08-07 19:17:42 +02001842 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001843 }
1844 }
1845}
1846
1847static void ddr_config(void)
1848{
1849 int32_t i;
1850 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001851 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001852 uint32_t tmp;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001853 int8_t _adj;
1854 int16_t adj;
1855 uint32_t dq;
1856 union {
1857 uint32_t ui32[4];
1858 uint8_t ui8[16];
1859 } patt;
1860 uint16_t patm;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001861
Marek Vasut6a131772019-08-07 19:56:09 +02001862 /* configure ddrphy registers */
Marek Vasut38dc7562019-08-07 19:17:42 +02001863 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001864 ddr_config_sub_h3v1x();
Marek Vasut6ad74c32019-08-08 16:34:22 +02001865 } else { /* H3 Ver.2.0 or later/M3-N/V3H is same as M3-W */
1866 ddr_config_sub();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001867 }
1868
Marek Vasut6a131772019-08-07 19:56:09 +02001869 /* WDQ_USER_PATT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001870 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001871 for (slice = 0; slice < SLICE_CNT; slice++) {
1872 patm = 0;
1873 for (i = 0; i < 16; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001874 tmp = board_cnf->ch[ch].wdqlvl_patt[i];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001875 patt.ui8[i] = tmp & 0xff;
1876 if (tmp & 0x100)
1877 patm |= (1U << i);
1878 }
1879 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT0,
1880 patt.ui32[0]);
1881 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT1,
1882 patt.ui32[1]);
1883 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT2,
1884 patt.ui32[2]);
1885 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT3,
1886 patt.ui32[3]);
1887 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT4, patm);
1888 }
1889 }
1890
Marek Vasut6a131772019-08-07 19:56:09 +02001891 /* CACS DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001892 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001893 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
1894 0x00U);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001895 foreach_vch(ch) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001896 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001897 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001898 ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET,
1899 _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001900 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001901 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001902 ddr_regdef_adr
1903 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]),
1904 _cnf_DDR_PHY_ADR_V_REGSET
1905 [ddr_regdef_adr
1906 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001907 DDR_PHY_ADR_V_REGSET_OFS]);
1908 }
1909
1910 for (i = (_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4);
1911 i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001912 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001913 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1914 _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001915 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001916 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001917 ddr_regdef_adr
1918 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]),
1919 _cnf_DDR_PHY_ADR_G_REGSET
1920 [ddr_regdef_adr
1921 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001922 DDR_PHY_ADR_G_REGSET_OFS]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001923 }
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001924
Marek Vasut6c245a52018-12-12 18:06:39 +01001925 if (ddr_phycaslice == 1) {
1926 for (i = 0; i < 6; i++) {
Marek Vasut6a131772019-08-07 19:56:09 +02001927 adj = _f_scale_adj
1928 (board_cnf->ch[ch].cacs_adj
1929 [i +
1930 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001931 ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET,
Marek Vasut6ad74c32019-08-08 16:34:22 +02001932 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
1933 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001934 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001935 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001936 ddr_regdef_adr
1937 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) +
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001938 0x0100,
Marek Vasut6a131772019-08-07 19:56:09 +02001939 _cnf_DDR_PHY_ADR_V_REGSET
1940 [ddr_regdef_adr
1941 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001942 DDR_PHY_ADR_V_REGSET_OFS]);
Marek Vasut6c245a52018-12-12 18:06:39 +01001943 }
1944 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001945 }
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001946
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001947 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
Marek Vasut6ad74c32019-08-08 16:34:22 +02001948 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001949
Marek Vasut6a131772019-08-07 19:56:09 +02001950 /* WDQDM DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001951 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001952 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001953 for (slice = 0; slice < SLICE_CNT; slice++) {
1954 for (i = 0; i <= 8; i++) {
1955 dq = slice * 8 + i;
1956 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02001957 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001958 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001959 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001960 adj = _f_scale_adj(_adj);
1961 ddr_setval_s(ch, slice,
1962 _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001963 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001964 }
1965 }
1966 }
1967
Marek Vasut6a131772019-08-07 19:56:09 +02001968 /* RDQDM DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001969 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001970 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001971 for (slice = 0; slice < SLICE_CNT; slice++) {
1972 for (i = 0; i <= 8; i++) {
1973 dq = slice * 8 + i;
1974 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02001975 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001976 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001977 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001978 adj = _f_scale_adj(_adj);
1979 ddr_setval_s(ch, slice,
1980 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY
Marek Vasut38dc7562019-08-07 19:17:42 +02001981 [i], data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001982 ddr_setval_s(ch, slice,
1983 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
Marek Vasut38dc7562019-08-07 19:17:42 +02001984 [i], data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001985 }
1986 }
1987 }
1988}
1989
Marek Vasut6a131772019-08-07 19:56:09 +02001990/* DBSC register setting functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001991static void dbsc_regset_pre(void)
1992{
1993 uint32_t ch, csab;
Marek Vasut38dc7562019-08-07 19:17:42 +02001994 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001995
Marek Vasut6a131772019-08-07 19:56:09 +02001996 /* PRIMARY SETTINGS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001997 /* LPDDR4, BL=16, DFI interface */
1998 mmio_write_32(DBSC_DBKIND, 0x0000000a);
1999 mmio_write_32(DBSC_DBBL, 0x00000002);
2000 mmio_write_32(DBSC_DBPHYCONF0, 0x00000001);
2001
2002 /* FREQRATIO=2 */
2003 mmio_write_32(DBSC_DBSYSCONF1, 0x00000002);
2004
2005 /* Chanel map (H3 Ver.1.x) */
Marek Vasut38dc7562019-08-07 19:17:42 +02002006 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002007 mmio_write_32(DBSC_DBSCHCNT1, 0x00001010);
2008
2009 /* DRAM SIZE REGISTER:
2010 * set all ranks as density=0(4Gb) for PHY initialization
2011 */
Marek Vasut6ad74c32019-08-08 16:34:22 +02002012 foreach_vch(ch) {
2013 for (csab = 0; csab < 4; csab++) {
2014 mmio_write_32(DBSC_DBMEMCONF(ch, csab),
2015 DBMEMCONF_REGD(0));
2016 }
2017 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002018
Marek Vasut38dc7562019-08-07 19:17:42 +02002019 if (prr_product == PRR_PRODUCT_M3) {
2020 data_l = 0xe4e4e4e4;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002021 foreach_ech(ch) {
2022 if ((ddr_phyvalid & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02002023 data_l = (data_l & (~(0x000000FF << (ch * 8))))
2024 | (((board_cnf->ch[ch].dqs_swap & 0x0003)
2025 | ((board_cnf->ch[ch].dqs_swap & 0x0030)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002026 >> 2)
Marek Vasut38dc7562019-08-07 19:17:42 +02002027 | ((board_cnf->ch[ch].dqs_swap & 0x0300)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002028 >> 4)
Marek Vasut38dc7562019-08-07 19:17:42 +02002029 | ((board_cnf->ch[ch].dqs_swap & 0x3000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002030 >> 6)) << (ch * 8));
2031 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002032 mmio_write_32(DBSC_DBBSWAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002033 }
2034}
2035
2036static void dbsc_regset(void)
2037{
2038 int32_t i;
2039 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002040 uint32_t data_l;
2041 uint32_t data_l2;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002042 uint32_t tmp[4];
2043
2044 /* RFC */
Marek Vasut6a131772019-08-07 19:56:09 +02002045 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_20) &&
2046 (max_density == 0)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002047 js2[js2_trfcab] =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002048 _f_scale(ddr_mbps, ddr_mbpsdiv,
Marek Vasut38dc7562019-08-07 19:17:42 +02002049 1UL * jedec_spec2_trfc_ab[1] * 1000, 0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002050 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002051 js2[js2_trfcab] =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002052 _f_scale(ddr_mbps, ddr_mbpsdiv,
Marek Vasut38dc7562019-08-07 19:17:42 +02002053 1UL * jedec_spec2_trfc_ab[max_density] *
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002054 1000, 0);
2055 }
2056
2057 /* DBTR0.CL : RL */
2058 mmio_write_32(DBSC_DBTR(0), RL);
2059
2060 /* DBTR1.CWL : WL */
2061 mmio_write_32(DBSC_DBTR(1), WL);
2062
2063 /* DBTR2.AL : 0 */
2064 mmio_write_32(DBSC_DBTR(2), 0);
2065
2066 /* DBTR3.TRCD: tRCD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002067 mmio_write_32(DBSC_DBTR(3), js2[js2_trcd]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002068
2069 /* DBTR4.TRPA,TRP: tRPab,tRPpb */
Marek Vasut38dc7562019-08-07 19:17:42 +02002070 mmio_write_32(DBSC_DBTR(4), (js2[js2_trpab] << 16) | js2[js2_trppb]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002071
2072 /* DBTR5.TRC : use tRCpb */
Marek Vasut38dc7562019-08-07 19:17:42 +02002073 mmio_write_32(DBSC_DBTR(5), js2[js2_trcpb]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002074
2075 /* DBTR6.TRAS : tRAS */
Marek Vasut38dc7562019-08-07 19:17:42 +02002076 mmio_write_32(DBSC_DBTR(6), js2[js2_tras]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002077
2078 /* DBTR7.TRRD : tRRD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002079 mmio_write_32(DBSC_DBTR(7), (js2[js2_trrd] << 16) | js2[js2_trrd]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002080
2081 /* DBTR8.TFAW : tFAW */
Marek Vasut38dc7562019-08-07 19:17:42 +02002082 mmio_write_32(DBSC_DBTR(8), js2[js2_tfaw]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002083
2084 /* DBTR9.TRDPR : tRTP */
Marek Vasut38dc7562019-08-07 19:17:42 +02002085 mmio_write_32(DBSC_DBTR(9), js2[js2_trtp]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002086
Chiaki Fujii82e9c412019-12-26 12:57:40 +09002087 /* DBTR10.TWR : nWR */
2088 mmio_write_32(DBSC_DBTR(10), js1[js1_ind].nwr);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002089
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002090 /*
2091 * DBTR11.TRDWR : RL + BL / 2 + Rounddown(tRPST) + PHY_ODTLoff -
2092 * odtlon + tDQSCK - tODTon,min +
2093 * PCB delay (out+in) + tPHY_ODToff
2094 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002095 mmio_write_32(DBSC_DBTR(11),
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002096 RL + (16 / 2) + 1 + 2 - js1[js1_ind].odtlon +
2097 js2[js2_tdqsck] - js2[js2_tODTon_min] +
2098 _f_scale(ddr_mbps, ddr_mbpsdiv, 1300, 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002099
2100 /* DBTR12.TWRRD : WL + 1 + BL/2 + tWTR */
Marek Vasut38dc7562019-08-07 19:17:42 +02002101 data_l = WL + 1 + (16 / 2) + js2[js2_twtr];
2102 mmio_write_32(DBSC_DBTR(12), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002103
Marek Vasut6c245a52018-12-12 18:06:39 +01002104 /* DBTR13.TRFCAB : tRFCab */
Marek Vasut38dc7562019-08-07 19:17:42 +02002105 mmio_write_32(DBSC_DBTR(13), (js2[js2_trfcab]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002106
2107 /* DBTR14.TCKEHDLL,tCKEH : tCKEHCMD,tCKEHCMD */
2108 mmio_write_32(DBSC_DBTR(14),
Marek Vasut38dc7562019-08-07 19:17:42 +02002109 (js2[js2_tckehcmd] << 16) | (js2[js2_tckehcmd]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002110
2111 /* DBTR15.TCKESR,TCKEL : tSR,tCKELPD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002112 mmio_write_32(DBSC_DBTR(15), (js2[js2_tsr] << 16) | (js2[js2_tckelpd]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002113
2114 /* DBTR16 */
2115 /* WDQL : tphy_wrlat + tphy_wrdata */
2116 tmp[0] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1);
Marek Vasut3af20052019-02-25 14:57:08 +01002117 /* DQENLTNCY : tphy_wrlat = WL-2 : PHY_WRITE_PATH_LAT_ADD == 0
2118 * tphy_wrlat = WL-3 : PHY_WRITE_PATH_LAT_ADD != 0
2119 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002120 tmp[1] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1);
2121 /* DQL : tphy_rdlat + trdata_en */
2122 /* it is not important for dbsc */
2123 tmp[2] = RL + 16;
2124 /* DQIENLTNCY : trdata_en */
2125 tmp[3] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1) - 1;
2126 mmio_write_32(DBSC_DBTR(16),
2127 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2128
2129 /* DBTR24 */
2130 /* WRCSLAT = WRLAT -5 */
2131 tmp[0] -= 5;
2132 /* WRCSGAP = 5 */
2133 tmp[1] = 5;
2134 /* RDCSLAT = RDLAT_ADJ +2 */
Marek Vasut38dc7562019-08-07 19:17:42 +02002135 if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6c245a52018-12-12 18:06:39 +01002136 tmp[2] = tmp[3];
2137 } else {
2138 tmp[2] = tmp[3] + 2;
2139 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002140 /* RDCSGAP = 6 */
Marek Vasut38dc7562019-08-07 19:17:42 +02002141 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002142 tmp[3] = 4;
2143 } else {
2144 tmp[3] = 6;
2145 }
2146 mmio_write_32(DBSC_DBTR(24),
2147 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2148
2149 /* DBTR17.TMODRD,TMOD,TRDMR: tMRR,tMRD,(0) */
2150 mmio_write_32(DBSC_DBTR(17),
Marek Vasut38dc7562019-08-07 19:17:42 +02002151 (js2[js2_tmrr] << 24) | (js2[js2_tmrd] << 16));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002152
2153 /* DBTR18.RODTL, RODTA, WODTL, WODTA : do not use in LPDDR4 */
2154 mmio_write_32(DBSC_DBTR(18), 0);
2155
2156 /* DBTR19.TZQCL, TZQCS : do not use in LPDDR4 */
2157 mmio_write_32(DBSC_DBTR(19), 0);
2158
2159 /* DBTR20.TXSDLL, TXS : tRFCab+tCKEHCMD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002160 data_l = js2[js2_trfcab] + js2[js2_tckehcmd];
2161 mmio_write_32(DBSC_DBTR(20), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002162
2163 /* DBTR21.TCCD */
2164 /* DBTR23.TCCD */
2165 /* H3 Ver.1.0 cannot use TBTR23 feature */
2166 if (ddr_tccd == 8 &&
Marek Vasut38dc7562019-08-07 19:17:42 +02002167 !((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_10))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002168 ) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002169 data_l = 8;
2170 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002171 mmio_write_32(DBSC_DBTR(23), 0x00000002);
2172 } else if (ddr_tccd <= 11) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002173 data_l = 11;
2174 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002175 mmio_write_32(DBSC_DBTR(23), 0x00000000);
2176 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002177 data_l = ddr_tccd;
2178 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002179 mmio_write_32(DBSC_DBTR(23), 0x00000000);
2180 }
2181
2182 /* DBTR22.ZQLAT : */
Marek Vasut38dc7562019-08-07 19:17:42 +02002183 data_l = js2[js2_tzqcalns] * 100; /* 1000 * 1000 ps */
2184 data_l = (data_l << 16) | (js2[js2_tzqlat] + 24 + 20);
2185 mmio_write_32(DBSC_DBTR(22), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002186
2187 /* DBTR25 : do not use in LPDDR4 */
2188 mmio_write_32(DBSC_DBTR(25), 0);
2189
2190 /* DBRNK : */
2191 /*
2192 * DBSC_DBRNK2 rkrr
2193 * DBSC_DBRNK3 rkrw
2194 * DBSC_DBRNK4 rkwr
2195 * DBSC_DBRNK5 rkww
2196 */
2197#define _par_DBRNK_VAL (0x7007)
2198
2199 for (i = 0; i < 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002200 data_l = (_par_DBRNK_VAL >> (i * 4)) & 0x0f;
Marek Vasut6a131772019-08-07 19:56:09 +02002201 if ((prr_product == PRR_PRODUCT_H3) &&
2202 (prr_cut > PRR_PRODUCT_11) && (i == 0)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002203 data_l += 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002204 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002205 data_l2 = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002206 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002207 data_l2 = data_l2 | (data_l << (4 * ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002208 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002209 mmio_write_32(DBSC_DBRNK(2 + i), data_l2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002210 }
2211 mmio_write_32(DBSC_DBADJ0, 0x00000000);
2212
Marek Vasut6a131772019-08-07 19:56:09 +02002213 /* timing registers for Scheduler */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002214 /* SCFCTST0 */
2215 /* SCFCTST0 ACT-ACT */
Marek Vasut38dc7562019-08-07 19:17:42 +02002216 tmp[3] = 1UL * js2[js2_trcpb] * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002217 /* SCFCTST0 RDA-ACT */
2218 tmp[2] =
Marek Vasut38dc7562019-08-07 19:17:42 +02002219 1UL * ((16 / 2) + js2[js2_trtp] - 8 +
2220 js2[js2_trppb]) * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002221 /* SCFCTST0 WRA-ACT */
2222 tmp[1] =
2223 1UL * (WL + 1 + (16 / 2) +
Marek Vasut38dc7562019-08-07 19:17:42 +02002224 js1[js1_ind].nwr) * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002225 /* SCFCTST0 PRE-ACT */
Marek Vasut38dc7562019-08-07 19:17:42 +02002226 tmp[0] = 1UL * js2[js2_trppb];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002227 mmio_write_32(DBSC_SCFCTST0,
2228 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2229
2230 /* SCFCTST1 */
2231 /* SCFCTST1 RD-WR */
2232 tmp[3] =
2233 1UL * (mmio_read_32(DBSC_DBTR(11)) & 0xff) * 800 * ddr_mbpsdiv /
2234 ddr_mbps;
2235 /* SCFCTST1 WR-RD */
2236 tmp[2] =
2237 1UL * (mmio_read_32(DBSC_DBTR(12)) & 0xff) * 800 * ddr_mbpsdiv /
2238 ddr_mbps;
2239 /* SCFCTST1 ACT-RD/WR */
Marek Vasut38dc7562019-08-07 19:17:42 +02002240 tmp[1] = 1UL * js2[js2_trcd] * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002241 /* SCFCTST1 ASYNCOFS */
2242 tmp[0] = 12;
2243 mmio_write_32(DBSC_SCFCTST1,
2244 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2245
2246 /* DBSCHRW1 */
2247 /* DBSCHRW1 SCTRFCAB */
Marek Vasut38dc7562019-08-07 19:17:42 +02002248 tmp[0] = 1UL * js2[js2_trfcab] * 800 * ddr_mbpsdiv / ddr_mbps;
2249 data_l = (((mmio_read_32(DBSC_DBTR(16)) & 0x00FF0000) >> 16)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002250 + (mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
2251 + (0x28 * 2)) * 400 * 2 * ddr_mbpsdiv / ddr_mbps + 7;
Marek Vasut38dc7562019-08-07 19:17:42 +02002252 if (tmp[0] < data_l)
2253 tmp[0] = data_l;
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002254
Marek Vasut38dc7562019-08-07 19:17:42 +02002255 if ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30)) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002256 mmio_write_32(DBSC_DBSCHRW1, tmp[0]
2257 + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
Marek Vasut6ad74c32019-08-08 16:34:22 +02002258 * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) /
2259 ddr_mbps - 3);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002260 } else {
2261 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);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002265 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002266
Marek Vasut6a131772019-08-07 19:56:09 +02002267 /* QOS and CAM */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002268#ifdef ddr_qos_init_setting /* only for non qos_init */
2269 /*wbkwait(0004), wbkmdhi(4,2),wbkmdlo(1,8) */
2270 mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218);
2271 /*0(fillunit),8(dirtymax),4(dirtymin) */
2272 mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4);
2273 /*stop_tolerance */
2274 mmio_write_32(DBSC_DBSCHRW0, 0x22421111);
2275 /*rd-wr/wr-rd toggle priority */
2276 mmio_write_32(DBSC_SCFCTST2, 0x012F1123);
2277 mmio_write_32(DBSC_DBSCHSZ0, 0x00000001);
2278 mmio_write_32(DBSC_DBSCHCNT0, 0x000F0037);
2279
2280 /* QoS Settings */
2281 mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00U);
2282 mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00U);
2283 mmio_write_32(DBSC_DBSCHQOS02, 0x00000000U);
2284 mmio_write_32(DBSC_DBSCHQOS03, 0x00000000U);
2285 mmio_write_32(DBSC_DBSCHQOS40, 0x00000300U);
2286 mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0U);
2287 mmio_write_32(DBSC_DBSCHQOS42, 0x00000200U);
2288 mmio_write_32(DBSC_DBSCHQOS43, 0x00000100U);
2289 mmio_write_32(DBSC_DBSCHQOS90, 0x00000100U);
2290 mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0U);
2291 mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0U);
2292 mmio_write_32(DBSC_DBSCHQOS93, 0x00000040U);
2293 mmio_write_32(DBSC_DBSCHQOS120, 0x00000040U);
2294 mmio_write_32(DBSC_DBSCHQOS121, 0x00000030U);
2295 mmio_write_32(DBSC_DBSCHQOS122, 0x00000020U);
2296 mmio_write_32(DBSC_DBSCHQOS123, 0x00000010U);
2297 mmio_write_32(DBSC_DBSCHQOS130, 0x00000100U);
2298 mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0U);
2299 mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0U);
2300 mmio_write_32(DBSC_DBSCHQOS133, 0x00000040U);
2301 mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0U);
2302 mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0U);
2303 mmio_write_32(DBSC_DBSCHQOS142, 0x00000080U);
2304 mmio_write_32(DBSC_DBSCHQOS143, 0x00000040U);
2305 mmio_write_32(DBSC_DBSCHQOS150, 0x00000040U);
2306 mmio_write_32(DBSC_DBSCHQOS151, 0x00000030U);
2307 mmio_write_32(DBSC_DBSCHQOS152, 0x00000020U);
2308 mmio_write_32(DBSC_DBSCHQOS153, 0x00000010U);
2309
2310 mmio_write_32(QOSCTRL_RAEN, 0x00000001U);
2311#endif /* ddr_qos_init_setting */
2312 /* H3 Ver.1.1 need to set monitor function */
Marek Vasut38dc7562019-08-07 19:17:42 +02002313 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002314 mmio_write_32(DBSC_DBMONCONF4, 0x00700000);
2315 }
2316
Marek Vasut38dc7562019-08-07 19:17:42 +02002317 if (prr_product == PRR_PRODUCT_H3) {
2318 if (prr_cut == PRR_PRODUCT_10) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002319 /* resrdis, simple mode, sc off */
2320 mmio_write_32(DBSC_DBBCAMDIS, 0x00000007);
Marek Vasut38dc7562019-08-07 19:17:42 +02002321 } else if (prr_cut == PRR_PRODUCT_11) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002322 /* resrdis, simple mode */
2323 mmio_write_32(DBSC_DBBCAMDIS, 0x00000005);
Marek Vasut38dc7562019-08-07 19:17:42 +02002324 } else if (prr_cut < PRR_PRODUCT_30) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002325 /* H3 Ver.2.0 */
2326 /* resrdis */
2327 mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
2328 } else { /* H3 Ver.3.0(include H3N) */
2329 /* exprespque */
2330 mmio_write_32(DBSC_DBBCAMDIS, 0x00000010);
2331 }
2332 } else { /* M3-W/M3-N/V3H */
2333 /* resrdis */
2334 mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
2335 }
2336}
2337
2338static void dbsc_regset_post(void)
2339{
2340 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02002341 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002342 uint32_t slice, rdlat_max, rdlat_min;
2343
2344 rdlat_max = 0;
2345 rdlat_min = 0xffff;
2346 foreach_vch(ch) {
2347 for (cs = 0; cs < CS_CNT; cs++) {
2348 if ((ch_have_this_cs[cs] & (1U << ch)) != 0) {
2349 for (slice = 0; slice < SLICE_CNT; slice++) {
2350 ddr_setval_s(ch, slice,
2351 _reg_PHY_PER_CS_TRAINING_INDEX,
2352 cs);
Marek Vasut6ad74c32019-08-08 16:34:22 +02002353 data_l = ddr_getval_s(ch, slice,
2354 _reg_PHY_RDDQS_LATENCY_ADJUST);
Marek Vasut38dc7562019-08-07 19:17:42 +02002355 if (data_l > rdlat_max)
2356 rdlat_max = data_l;
2357 if (data_l < rdlat_min)
2358 rdlat_min = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002359 }
2360 }
2361 }
2362 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002363 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) {
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002364#if RCAR_DRAM_SPLIT == 2
2365 if (board_cnf->phyvalid == 0x05) {
2366 mmio_write_32(DBSC_DBTR(24),
2367 (rdlat_max << 24) + (rdlat_min << 16) +
2368 mmio_read_32(DBSC_DBTR(24)));
2369 } else {
2370 mmio_write_32(DBSC_DBTR(24),
2371 ((rdlat_max * 2 - rdlat_min + 4) << 24) +
2372 ((rdlat_min + 2) << 16) +
2373 mmio_read_32(DBSC_DBTR(24)));
2374 }
2375#else /*RCAR_DRAM_SPLIT == 2 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002376 mmio_write_32(DBSC_DBTR(24),
2377 ((rdlat_max * 2 - rdlat_min + 4) << 24) +
2378 ((rdlat_min + 2) << 16) +
2379 mmio_read_32(DBSC_DBTR(24)));
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002380#endif /*RCAR_DRAM_SPLIT == 2 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002381 } else {
2382 mmio_write_32(DBSC_DBTR(24),
2383 ((rdlat_max + 2) << 24) +
2384 ((rdlat_max + 2) << 16) +
2385 mmio_read_32(DBSC_DBTR(24)));
2386 }
2387
2388 /* set ddr density information */
2389 foreach_ech(ch) {
2390 for (cs = 0; cs < CS_CNT; cs++) {
2391 if (ddr_density[ch][cs] == 0xff) {
2392 mmio_write_32(DBSC_DBMEMCONF(ch, cs), 0x00);
2393 } else {
2394 mmio_write_32(DBSC_DBMEMCONF(ch, cs),
2395 DBMEMCONF_REGD(ddr_density[ch]
2396 [cs]));
2397 }
2398 }
2399 mmio_write_32(DBSC_DBMEMCONF(ch, 2), 0x00000000);
2400 mmio_write_32(DBSC_DBMEMCONF(ch, 3), 0x00000000);
2401 }
2402
2403 mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010);
2404
2405 /*set DBI */
Marek Vasut38dc7562019-08-07 19:17:42 +02002406 if (board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002407 mmio_write_32(DBSC_DBDBICNT, 0x00000003);
2408
2409 /* H3 Ver.2.0 or later/M3-N/V3H DBI wa */
Marek Vasut6a131772019-08-07 19:56:09 +02002410 if ((((prr_product == PRR_PRODUCT_H3) &&
2411 (prr_cut > PRR_PRODUCT_11)) ||
2412 (prr_product == PRR_PRODUCT_M3N) ||
2413 (prr_product == PRR_PRODUCT_V3H)) &&
2414 board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002415 reg_ddrphy_write_a(0x00001010, 0x01000000);
2416
2417 /*set REFCYCLE */
Marek Vasut38dc7562019-08-07 19:17:42 +02002418 data_l = (get_refperiod()) * ddr_mbps / 2000 / ddr_mbpsdiv;
2419 mmio_write_32(DBSC_DBRFCNF1, 0x00080000 | (data_l & 0x0000ffff));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002420 mmio_write_32(DBSC_DBRFCNF2, 0x00010000 | DBSC_REFINTS);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002421
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002422#if RCAR_REWT_TRAINING != 0
2423 /* Periodic-WriteDQ Training seeting */
Marek Vasut6a131772019-08-07 19:56:09 +02002424 if (((prr_product == PRR_PRODUCT_H3) &&
2425 (prr_cut <= PRR_PRODUCT_11)) ||
2426 ((prr_product == PRR_PRODUCT_M3) &&
2427 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002428 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2429 } else {
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002430 /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002431 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000);
2432
2433 ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04);
2434 ddr_setval_ach_as(_reg_PHY_WDQLVL_QTR_DLY_STEP, 0x0F);
2435 ddr_setval_ach_as(_reg_PHY_WDQLVL_DLY_STEP, 0x50);
2436 ddr_setval_ach_as(_reg_PHY_WDQLVL_DQDM_SLV_DLY_START, 0x0300);
2437
2438 ddr_setval_ach(_reg_PI_WDQLVL_CS_MAP,
2439 ddrtbl_getval(_cnf_DDR_PI_REGSET,
2440 _reg_PI_WDQLVL_CS_MAP));
2441 ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f);
2442 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002443 ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01);
2444 ddr_setval_ach(_reg_PI_TREF_F0, 0x0000);
2445 ddr_setval_ach(_reg_PI_TREF_F1, 0x0000);
2446 ddr_setval_ach(_reg_PI_TREF_F2, 0x0000);
2447
Marek Vasut38dc7562019-08-07 19:17:42 +02002448 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002449 ddr_setval_ach(_reg_PI_WDQLVL_EN, 0x02);
2450 } else {
2451 ddr_setval_ach(_reg_PI_WDQLVL_EN_F1, 0x02);
2452 }
2453 ddr_setval_ach(_reg_PI_WDQLVL_PERIODIC, 0x01);
2454
2455 /* DFI_PHYMSTR_ACK , WTmode setting */
Marek Vasut6ad74c32019-08-08 16:34:22 +02002456 /* DFI_PHYMSTR_ACK: WTmode =b'01 */
2457 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002458 }
2459#endif /* RCAR_REWT_TRAINING */
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002460 /* periodic dram zqcal enable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002461 mmio_write_32(DBSC_DBCALCNF, 0x01000010);
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002462
2463 /* periodic phy ctrl update enable */
Marek Vasut6a131772019-08-07 19:56:09 +02002464 if (((prr_product == PRR_PRODUCT_H3) &&
2465 (prr_cut <= PRR_PRODUCT_11)) ||
2466 ((prr_product == PRR_PRODUCT_M3) &&
2467 (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002468 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
2469 } else {
2470#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02002471 if ((prr_product == PRR_PRODUCT_H3) &&
2472 (board_cnf->phyvalid == 0x05))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002473 mmio_write_32(DBSC_DBDFICUPDCNF, 0x2a240001);
2474 else
2475 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2476#else /* RCAR_DRAM_SPLIT == 2 */
2477 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2478#endif /* RCAR_DRAM_SPLIT == 2 */
2479 }
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002480
2481#ifdef DDR_BACKUPMODE
2482 /* SRX */
2483 if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
2484#ifdef DDR_BACKUPMODE_HALF /* for Half channel(ch0, 1 only) */
2485 NOTICE("BL2: [DEBUG_MESS] DDR_BACKUPMODE_HALF\n");
2486 send_dbcmd(0x0A040001);
2487 if (Prr_Product == PRR_PRODUCT_H3)
2488 send_dbcmd(0x0A140001);
2489#else /* DDR_BACKUPMODE_HALF */ /* for All channels */
2490 send_dbcmd(0x0A840001);
2491#endif /* DDR_BACKUPMODE_HALF */
2492 }
2493#endif /* DDR_BACKUPMODE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002494
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002495 /* set Auto Refresh */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002496 mmio_write_32(DBSC_DBRFEN, 0x00000001);
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002497
2498#if RCAR_REWT_TRAINING != 0
2499 /* Periodic WriteDQ Traning */
2500 if (((prr_product == PRR_PRODUCT_H3) &&
2501 (prr_cut <= PRR_PRODUCT_11)) ||
2502 ((prr_product == PRR_PRODUCT_M3) &&
2503 (prr_cut == PRR_PRODUCT_10))) {
2504 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2505 } else {
2506 /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
2507 ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
2508 }
2509#endif /* RCAR_REWT_TRAINING */
2510
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002511 /* dram access enable */
2512 mmio_write_32(DBSC_DBACEN, 0x00000001);
2513
Marek Vasut6ad74c32019-08-08 16:34:22 +02002514 MSG_LF(__func__ "(done)");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002515}
2516
Marek Vasut6a131772019-08-07 19:56:09 +02002517/* DFI_INIT_START */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002518static uint32_t dfi_init_start(void)
2519{
2520 uint32_t ch;
2521 uint32_t phytrainingok;
2522 uint32_t retry;
Marek Vasut38dc7562019-08-07 19:17:42 +02002523 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002524 const uint32_t RETRY_MAX = 0x10000;
2525
Marek Vasut38dc7562019-08-07 19:17:42 +02002526 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002527 /* PLL3 Disable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002528 /* protect register interface */
2529 ddrphy_regif_idle();
2530
2531 pll3_control(0);
2532
Marek Vasut6a131772019-08-07 19:56:09 +02002533 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002534 /* dbdficnt0:
2535 * dfi_dram_clk_disable=1
2536 * dfi_frequency = 0
2537 * freq_ratio = 01 (2:1)
2538 * init_start =0
2539 */
2540 foreach_vch(ch)
2541 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
2542 dsb_sev();
2543
2544 /* dbdficnt0:
2545 * dfi_dram_clk_disable=1
2546 * dfi_frequency = 0
2547 * freq_ratio = 01 (2:1)
2548 * init_start =1
2549 */
2550 foreach_vch(ch)
2551 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
2552 dsb_sev();
2553
2554 } else {
2555 ddr_setval_ach_as(_reg_PHY_DLL_RST_EN, 0x02);
2556 dsb_sev();
2557 ddrphy_regif_idle();
2558 }
2559
2560 /* dll_rst negate */
2561 foreach_vch(ch)
2562 mmio_write_32(DBSC_DBPDCNT3(ch), 0x0000CF01);
2563 dsb_sev();
2564
Marek Vasut6a131772019-08-07 19:56:09 +02002565 /* wait init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002566 phytrainingok = 0;
2567 retry = 0;
2568 while (retry++ < RETRY_MAX) {
2569 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002570 data_l = mmio_read_32(DBSC_DBDFISTAT(ch));
2571 if (data_l & 0x00000001)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002572 phytrainingok |= (1U << ch);
2573 }
2574 dsb_sev();
2575 if (phytrainingok == ddr_phyvalid)
2576 break;
2577 if (retry % 256 == 0)
2578 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
2579 }
2580
Marek Vasut6a131772019-08-07 19:56:09 +02002581 /* all ch ok? */
2582 if ((phytrainingok & ddr_phyvalid) != ddr_phyvalid)
2583 return 0xff;
2584
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002585 /* dbdficnt0:
2586 * dfi_dram_clk_disable=0
2587 * dfi_frequency = 0
2588 * freq_ratio = 01 (2:1)
2589 * init_start =0
2590 */
2591 foreach_vch(ch)
2592 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000010);
2593 dsb_sev();
2594
2595 return 0;
2596}
2597
Marek Vasut6a131772019-08-07 19:56:09 +02002598/* drivablity setting : CMOS MODE ON/OFF */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002599static void change_lpddr4_en(uint32_t mode)
2600{
2601 uint32_t ch;
2602 uint32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002603 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002604 const uint32_t _reg_PHY_PAD_DRIVE_X[3] = {
2605 _reg_PHY_PAD_ADDR_DRIVE,
2606 _reg_PHY_PAD_CLK_DRIVE,
2607 _reg_PHY_PAD_CS_DRIVE
2608 };
2609
Marek Vasut6c245a52018-12-12 18:06:39 +01002610 foreach_vch(ch) {
2611 for (i = 0; i < 3; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002612 data_l = ddr_getval(ch, _reg_PHY_PAD_DRIVE_X[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002613 if (mode) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002614 data_l |= (1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002615 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002616 data_l &= ~(1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002617 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002618 ddr_setval(ch, _reg_PHY_PAD_DRIVE_X[i], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002619 }
2620 }
2621}
2622
Marek Vasut6a131772019-08-07 19:56:09 +02002623/* drivablity setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002624static uint32_t set_term_code(void)
2625{
2626 int32_t i;
2627 uint32_t ch, index;
Marek Vasut38dc7562019-08-07 19:17:42 +02002628 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002629 uint32_t chip_id[2];
2630 uint32_t term_code;
2631 uint32_t override;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002632 uint32_t pvtr;
2633 uint32_t pvtp;
2634 uint32_t pvtn;
Marek Vasut80784f92019-08-07 19:02:26 +02002635
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002636 term_code = ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2637 _reg_PHY_PAD_DATA_TERM);
2638 override = 0;
2639 for (i = 0; i < 2; i++)
2640 chip_id[i] = mmio_read_32(LIFEC_CHIPID(i));
2641
2642 index = 0;
2643 while (1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002644 if (termcode_by_sample[index][0] == 0xffffffff) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002645 break;
2646 }
Marek Vasut6a131772019-08-07 19:56:09 +02002647 if ((termcode_by_sample[index][0] == chip_id[0]) &&
2648 (termcode_by_sample[index][1] == chip_id[1])) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002649 term_code = termcode_by_sample[index][2];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002650 override = 1;
2651 break;
2652 }
2653 index++;
2654 }
2655
2656 if (override) {
2657 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002658 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002659 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2660 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002661 data_l = (data_l & 0xfffe0000) | term_code;
2662 ddr_setval_ach(_reg_PHY_PAD_TERM_X[index], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002663 }
Marek Vasut6a131772019-08-07 19:56:09 +02002664 } else if ((prr_product == PRR_PRODUCT_M3) &&
2665 (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002666 /* non */
2667 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002668 ddr_setval_ach(_reg_PHY_PAD_TERM_X[0],
2669 (ddrtbl_getval
2670 (_cnf_DDR_PHY_ADR_G_REGSET,
2671 _reg_PHY_PAD_TERM_X[0]) & 0xFFFE0000));
2672 ddr_setval_ach(_reg_PHY_CAL_CLEAR_0, 0x01);
2673 ddr_setval_ach(_reg_PHY_CAL_START_0, 0x01);
2674 foreach_vch(ch) {
2675 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002676 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002677 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002678 } while (!(data_l & 0x00800000));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002679 }
Marek Vasut6a131772019-08-07 19:56:09 +02002680 if ((prr_product == PRR_PRODUCT_H3) &&
2681 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002682 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002683 data_l = ddr_getval(ch, _reg_PHY_PAD_TERM_X[0]);
2684 pvtr = (data_l >> 12) & 0x1f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002685 pvtr += 8;
2686 if (pvtr > 0x1f)
2687 pvtr = 0x1f;
Marek Vasut38dc7562019-08-07 19:17:42 +02002688 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002689 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002690 pvtn = (data_l >> 6) & 0x03f;
2691 pvtp = (data_l >> 0) & 0x03f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002692
2693 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2694 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002695 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002696 ddrtbl_getval
2697 (_cnf_DDR_PHY_ADR_G_REGSET,
2698 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002699 data_l = (data_l & 0xfffe0000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002700 | (pvtr << 12)
2701 | (pvtn << 6)
2702 | (pvtp);
2703 ddr_setval(ch,
2704 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002705 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002706 }
2707 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02002708 } else {
2709 /* M3-W Ver.1.1 or later/H3 Ver.2.0 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002710 foreach_vch(ch) {
2711 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2712 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002713 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002714 ddr_getval(ch,
2715 _reg_PHY_PAD_TERM_X
2716 [index]);
2717 ddr_setval(ch,
2718 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002719 (data_l & 0xFFFE0FFF) |
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002720 0x00015000);
2721 }
2722 }
2723 }
2724 }
Marek Vasut6a131772019-08-07 19:56:09 +02002725
Marek Vasut38dc7562019-08-07 19:17:42 +02002726 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002727 /* non */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002728 } else {
2729 ddr_padcal_tcompensate_getinit(override);
2730 }
Marek Vasut6a131772019-08-07 19:56:09 +02002731
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002732 return 0;
2733}
2734
Marek Vasut6a131772019-08-07 19:56:09 +02002735/* DDR mode register setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01002736static void ddr_register_set(void)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002737{
2738 int32_t fspwp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002739 uint32_t tmp;
2740
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002741 for (fspwp = 1; fspwp >= 0; fspwp--) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002742 /*MR13, fspwp */
2743 send_dbcmd(0x0e840d08 | ((2 - fspwp) << 6));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002744
2745 tmp =
2746 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002747 reg_pi_mr1_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002748 send_dbcmd(0x0e840100 | tmp);
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_mr2_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002753 send_dbcmd(0x0e840200 | 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_mr3_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002758 send_dbcmd(0x0e840300 | 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_mr11_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002763 send_dbcmd(0x0e840b00 | 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_mr12_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002768 send_dbcmd(0x0e840c00 | 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_mr14_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002773 send_dbcmd(0x0e840e00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002774 /* MR22 */
Marek Vasut6c245a52018-12-12 18:06:39 +01002775 send_dbcmd(0x0e841616);
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002776
2777 /* ZQCAL start */
2778 send_dbcmd(0x0d84004F);
2779
2780 /* ZQLAT */
2781 send_dbcmd(0x0d840051);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002782 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002783
2784 /* MR13, fspwp */
2785 send_dbcmd(0x0e840d08);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002786}
2787
Marek Vasut6a131772019-08-07 19:56:09 +02002788/* Training handshake functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002789static inline uint32_t wait_freqchgreq(uint32_t assert)
2790{
Marek Vasut38dc7562019-08-07 19:17:42 +02002791 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002792 uint32_t count;
2793 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002794
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002795 count = 100000;
2796
2797 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut38dc7562019-08-07 19:17:42 +02002798 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002799 return 0;
2800 }
2801
2802 if (assert) {
2803 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002804 data_l = 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002805 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002806 data_l &= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002807 }
2808 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002809 } while (((data_l & 0x01) != 0x01) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002810 } else {
2811 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002812 data_l = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002813 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002814 data_l |= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002815 }
2816 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002817 } while (((data_l & 0x01) != 0x00) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002818 }
2819
2820 return (count == 0);
2821}
2822
2823static inline void set_freqchgack(uint32_t assert)
2824{
2825 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002826 uint32_t data_l;
Marek Vasut80784f92019-08-07 19:02:26 +02002827
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002828 if (assert)
Marek Vasut38dc7562019-08-07 19:17:42 +02002829 data_l = 0x0CF20000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002830 else
Marek Vasut38dc7562019-08-07 19:17:42 +02002831 data_l = 0x00000000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002832
2833 foreach_vch(ch)
Marek Vasut38dc7562019-08-07 19:17:42 +02002834 mmio_write_32(DBSC_DBPDCNT2(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002835}
2836
2837static inline void set_dfifrequency(uint32_t freq)
2838{
2839 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002840
Marek Vasut38dc7562019-08-07 19:17:42 +02002841 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002842 foreach_vch(ch)
2843 mmio_clrsetbits_32(DBSC_DBPDCNT1(ch), 0x1fU, freq);
2844 } else {
2845 foreach_vch(ch) {
2846 mmio_clrsetbits_32(DBSC_DBDFICNT(ch), 0x1fU << 24,
2847 (freq << 24));
2848 }
2849 }
2850 dsb_sev();
2851}
2852
2853static uint32_t pll3_freq(uint32_t on)
2854{
2855 uint32_t timeout;
2856
2857 timeout = wait_freqchgreq(1);
2858
2859 if (timeout) {
Marek Vasut6a131772019-08-07 19:56:09 +02002860 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002861 }
2862
2863 pll3_control(on);
2864 set_dfifrequency(on);
2865
2866 set_freqchgack(1);
2867 timeout = wait_freqchgreq(0);
2868 set_freqchgack(0);
2869
2870 if (timeout) {
Marek Vasut56519892019-01-21 23:11:33 +01002871 FATAL_MSG("BL2: Time out[2]\n");
Marek Vasut6a131772019-08-07 19:56:09 +02002872 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002873 }
Marek Vasut6a131772019-08-07 19:56:09 +02002874 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002875}
2876
Marek Vasut6a131772019-08-07 19:56:09 +02002877/* update dly */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002878static void update_dly(void)
2879{
2880 ddr_setval_ach(_reg_SC_PHY_MANUAL_UPDATE, 0x01);
2881 ddr_setval_ach(_reg_PHY_ADRCTL_MANUAL_UPDATE, 0x01);
2882}
2883
Marek Vasut6a131772019-08-07 19:56:09 +02002884/* training by pi */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002885static uint32_t pi_training_go(void)
2886{
2887 uint32_t flag;
Marek Vasut38dc7562019-08-07 19:17:42 +02002888 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002889 uint32_t retry;
2890 const uint32_t RETRY_MAX = 4096 * 16;
2891 uint32_t ch;
2892
2893 uint32_t mst_ch;
2894 uint32_t cur_frq;
2895 uint32_t complete;
2896 uint32_t frqchg_req;
2897
Marek Vasut6a131772019-08-07 19:56:09 +02002898 /* pi_start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002899 ddr_setval_ach(_reg_PI_START, 0x01);
2900 foreach_vch(ch)
2901 ddr_getval(ch, _reg_PI_INT_STATUS);
2902
2903 /* set dfi_phymstr_ack = 1 */
2904 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000001);
2905 dsb_sev();
2906
Marek Vasut6a131772019-08-07 19:56:09 +02002907 /* wait pi_int_status[0] */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002908 mst_ch = 0;
2909 flag = 0;
2910 complete = 0;
2911 cur_frq = 0;
2912 retry = RETRY_MAX;
2913 do {
2914 frqchg_req = mmio_read_32(DBSC_DBPDSTAT(mst_ch)) & 0x01;
2915
2916 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut6a131772019-08-07 19:56:09 +02002917 if ((prr_product == PRR_PRODUCT_H3) &&
2918 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002919 if ((retry % 4096) == 1) {
2920 frqchg_req = 1;
2921 } else {
2922 frqchg_req = 0;
2923 }
2924 }
2925
2926 if (frqchg_req) {
2927 if (cur_frq) {
2928 /* Low frequency */
2929 flag = pll3_freq(0);
2930 cur_frq = 0;
2931 } else {
2932 /* High frequency */
2933 flag = pll3_freq(1);
2934 cur_frq = 1;
2935 }
2936 if (flag)
2937 break;
2938 } else {
2939 if (cur_frq) {
2940 foreach_vch(ch) {
2941 if (complete & (1U << ch))
2942 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02002943 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002944 ddr_getval(ch, _reg_PI_INT_STATUS);
Marek Vasut38dc7562019-08-07 19:17:42 +02002945 if (data_l & 0x01) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002946 complete |= (1U << ch);
2947 }
2948 }
2949 if (complete == ddr_phyvalid)
2950 break;
2951 }
2952 }
2953 } while (--retry);
2954 foreach_vch(ch) {
2955 /* dummy read */
Marek Vasut38dc7562019-08-07 19:17:42 +02002956 data_l = ddr_getval_s(ch, 0, _reg_PHY_CAL_RESULT2_OBS_0);
2957 data_l = ddr_getval(ch, _reg_PI_INT_STATUS);
2958 ddr_setval(ch, _reg_PI_INT_ACK, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002959 }
2960 if (ddrphy_regif_chk()) {
Marek Vasut6a131772019-08-07 19:56:09 +02002961 return 0xfd;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002962 }
2963 return complete;
2964}
2965
Marek Vasut6a131772019-08-07 19:56:09 +02002966/* Initialize DDR */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002967static uint32_t init_ddr(void)
2968{
2969 int32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002970 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002971 uint32_t phytrainingok;
Marek Vasut6c245a52018-12-12 18:06:39 +01002972 uint32_t ch, slice;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002973 uint32_t err;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002974 int16_t adj;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002975
Marek Vasut6ad74c32019-08-08 16:34:22 +02002976 MSG_LF(__func__ ":0\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002977
2978#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02002979 rcar_dram_get_boot_status(&ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002980#endif
2981
Marek Vasut6a131772019-08-07 19:56:09 +02002982 /* unlock phy */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002983 /* Unlock DDRPHY register(AGAIN) */
2984 foreach_vch(ch)
2985 mmio_write_32(DBSC_DBPDLK(ch), 0x0000A55A);
2986 dsb_sev();
2987
Marek Vasut6a131772019-08-07 19:56:09 +02002988 if ((((prr_product == PRR_PRODUCT_H3) &&
2989 (prr_cut > PRR_PRODUCT_11)) ||
2990 (prr_product == PRR_PRODUCT_M3N) ||
2991 (prr_product == PRR_PRODUCT_V3H)) && board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002992 reg_ddrphy_write_a(0x00001010, 0x01000001);
2993 else
2994 reg_ddrphy_write_a(0x00001010, 0x00000001);
Marek Vasut6a131772019-08-07 19:56:09 +02002995 /* DBSC register pre-setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002996 dbsc_regset_pre();
2997
Marek Vasut6a131772019-08-07 19:56:09 +02002998 /* load ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002999
3000 ddrtbl_load();
3001
Marek Vasut6a131772019-08-07 19:56:09 +02003002 /* configure ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003003 ddr_config();
3004
Marek Vasut6a131772019-08-07 19:56:09 +02003005 /* dfi_reset assert */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003006 foreach_vch(ch)
3007 mmio_write_32(DBSC_DBPDCNT0(ch), 0x01);
3008 dsb_sev();
3009
Marek Vasut6a131772019-08-07 19:56:09 +02003010 /* dbsc register set */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003011 dbsc_regset();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003012 MSG_LF(__func__ ":1\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003013
Marek Vasut6a131772019-08-07 19:56:09 +02003014 /* dfi_reset negate */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003015 foreach_vch(ch)
3016 mmio_write_32(DBSC_DBPDCNT0(ch), 0x00);
3017 dsb_sev();
3018
Marek Vasut6a131772019-08-07 19:56:09 +02003019 /* dfi_init_start (start ddrphy) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003020 err = dfi_init_start();
3021 if (err) {
3022 return INITDRAM_ERR_I;
3023 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003024 MSG_LF(__func__ ":2\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003025
Marek Vasut6a131772019-08-07 19:56:09 +02003026 /* ddr backupmode end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003027#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02003028 if (ddr_backup) {
Marek Vasut56519892019-01-21 23:11:33 +01003029 NOTICE("BL2: [WARM_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003030 } else {
Marek Vasut56519892019-01-21 23:11:33 +01003031 NOTICE("BL2: [COLD_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003032 }
Marek Vasut38dc7562019-08-07 19:17:42 +02003033 err = rcar_dram_update_boot_status(ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003034 if (err) {
Marek Vasut56519892019-01-21 23:11:33 +01003035 NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003036 return INITDRAM_ERR_I;
3037 }
3038#endif
Marek Vasut6ad74c32019-08-08 16:34:22 +02003039 MSG_LF(__func__ ":3\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003040
Marek Vasut6a131772019-08-07 19:56:09 +02003041 /* override term code after dfi_init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003042 err = set_term_code();
3043 if (err) {
3044 return INITDRAM_ERR_I;
3045 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003046 MSG_LF(__func__ ":4\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003047
Marek Vasut6a131772019-08-07 19:56:09 +02003048 /* rx offset calibration */
3049 if ((prr_cut > PRR_PRODUCT_11) || (prr_product == PRR_PRODUCT_M3N) ||
3050 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003051 err = rx_offset_cal_hw();
3052 } else {
3053 err = rx_offset_cal();
3054 }
3055 if (err)
Marek Vasut6a131772019-08-07 19:56:09 +02003056 return INITDRAM_ERR_O;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003057 MSG_LF(__func__ ":5\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003058
Chiaki Fujiiaea02862019-09-18 13:10:00 +09003059 /* Dummy PDE */
3060 send_dbcmd(0x08840000);
3061
Marek Vasut6c245a52018-12-12 18:06:39 +01003062 /* PDX */
3063 send_dbcmd(0x08840001);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003064
Marek Vasut6a131772019-08-07 19:56:09 +02003065 /* check register i/f is alive */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003066 err = ddrphy_regif_chk();
3067 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003068 return INITDRAM_ERR_O;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003069 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003070 MSG_LF(__func__ ":6\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003071
Marek Vasut6a131772019-08-07 19:56:09 +02003072 /* phy initialize end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003073
Marek Vasut6a131772019-08-07 19:56:09 +02003074 /* setup DDR mode registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003075 /* CMOS MODE */
3076 change_lpddr4_en(0);
3077
Marek Vasut6c245a52018-12-12 18:06:39 +01003078 /* MRS */
3079 ddr_register_set();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003080
Marek Vasut6a131772019-08-07 19:56:09 +02003081 /* Thermal sensor setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01003082 /* THCTR Bit6: PONM=0 , Bit0: THSST=1 */
Marek Vasut38dc7562019-08-07 19:17:42 +02003083 data_l = (mmio_read_32(THS1_THCTR) & 0xFFFFFFBF) | 0x00000001;
3084 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003085
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003086 /* LPDDR4 MODE */
3087 change_lpddr4_en(1);
3088
Marek Vasut6ad74c32019-08-08 16:34:22 +02003089 MSG_LF(__func__ ":7\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003090
Marek Vasut6a131772019-08-07 19:56:09 +02003091 /* mask CS_MAP if RANKx is not found */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003092 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003093 data_l = ddr_getval(ch, _reg_PI_CS_MAP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003094 if (!(ch_have_this_cs[1] & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02003095 data_l = data_l & 0x05;
3096 ddr_setval(ch, _reg_PI_CS_MAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003097 }
3098
Marek Vasut6a131772019-08-07 19:56:09 +02003099 /* exec pi_training */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003100 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
3101 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003102 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003103
Marek Vasut38dc7562019-08-07 19:17:42 +02003104 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003105 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_EN, 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003106 } else {
3107 foreach_vch(ch) {
3108 for (slice = 0; slice < SLICE_CNT; slice++) {
3109 ddr_setval_s(ch, slice,
3110 _reg_PHY_PER_CS_TRAINING_EN,
3111 ((ch_have_this_cs[1]) >> ch)
3112 & 0x01);
3113 }
3114 }
3115 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003116
3117 phytrainingok = pi_training_go();
3118
3119 if (ddr_phyvalid != (phytrainingok & ddr_phyvalid)) {
Marek Vasut6a131772019-08-07 19:56:09 +02003120 return INITDRAM_ERR_T | phytrainingok;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003121 }
3122
Marek Vasut6ad74c32019-08-08 16:34:22 +02003123 MSG_LF(__func__ ":8\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003124
Marek Vasut6a131772019-08-07 19:56:09 +02003125 /* CACS DLY ADJUST */
Marek Vasut38dc7562019-08-07 19:17:42 +02003126 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003127 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003128 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003129 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003130 ddr_setval(ch, _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003131 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003132 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003133
3134 if (ddr_phycaslice == 1) {
3135 for (i = 0; i < 6; i++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003136 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj
3137 [i +
3138 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
3139 ddr_setval_s(ch, 2,
3140 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
3141 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003142 data_l + adj
Marek Vasut6c245a52018-12-12 18:06:39 +01003143 );
3144 }
3145 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003146 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003147
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003148 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003149 MSG_LF(__func__ ":9\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003150
Marek Vasut6a131772019-08-07 19:56:09 +02003151 /* H3 fix rd latency to avoid bug in elasitic buffer */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003152 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003153 adjust_rddqs_latency();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003154
Marek Vasut6a131772019-08-07 19:56:09 +02003155 /* Adjust Write path latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003156 if (ddrtbl_getval
3157 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD))
3158 adjust_wpath_latency();
3159
Marek Vasut6a131772019-08-07 19:56:09 +02003160 /* RDQLVL Training */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003161 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003162 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x01);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003163
3164 err = rdqdm_man();
Marek Vasut6c245a52018-12-12 18:06:39 +01003165
Marek Vasut6ad74c32019-08-08 16:34:22 +02003166 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Marek Vasut6c245a52018-12-12 18:06:39 +01003167 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003168
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003169 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003170 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003171 }
3172 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003173 MSG_LF(__func__ ":10\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003174
Marek Vasut6a131772019-08-07 19:56:09 +02003175 /* WDQLVL Training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003176 err = wdqdm_man();
3177 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003178 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003179 }
3180 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003181 MSG_LF(__func__ ":11\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003182
Marek Vasut6a131772019-08-07 19:56:09 +02003183 /* training complete, setup DBSC */
3184 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3185 (prr_product == PRR_PRODUCT_M3N) ||
3186 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003187 ddr_setval_ach_as(_reg_PHY_DFI40_POLARITY, 0x00);
3188 ddr_setval_ach(_reg_PI_DFI40_POLARITY, 0x00);
3189 }
3190
3191 dbsc_regset_post();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003192 MSG_LF(__func__ ":12\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003193
3194 return phytrainingok;
3195}
3196
Marek Vasut6a131772019-08-07 19:56:09 +02003197/* SW LEVELING COMMON */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003198static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick)
3199{
3200 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02003201 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003202 uint32_t retry;
3203 uint32_t waiting;
3204 uint32_t err;
3205
3206 const uint32_t RETRY_MAX = 0x1000;
3207
3208 err = 0;
3209 /* set EXIT -> OP_DONE is cleared */
3210 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3211
3212 /* kick */
3213 foreach_vch(ch) {
3214 if (ch_have_this_cs[ddr_csn % 2] & (1U << ch)) {
3215 ddr_setval(ch, reg_cs, ddr_csn);
3216 ddr_setval(ch, reg_kick, 0x01);
3217 }
3218 }
3219 foreach_vch(ch) {
3220 /*PREPARE ADDR REGISTER (for SWLVL_OP_DONE) */
3221 ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3222 }
3223 waiting = ch_have_this_cs[ddr_csn % 2];
3224 dsb_sev();
3225 retry = RETRY_MAX;
3226 do {
3227 foreach_vch(ch) {
3228 if (!(waiting & (1U << ch)))
3229 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02003230 data_l = ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3231 if (data_l & 0x01)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003232 waiting &= ~(1U << ch);
3233 }
3234 retry--;
3235 } while (waiting && (retry > 0));
3236 if (retry == 0) {
3237 err = 1;
3238 }
3239
3240 dsb_sev();
3241 /* set EXIT -> OP_DONE is cleared */
3242 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3243 dsb_sev();
3244
3245 return err;
3246}
3247
Marek Vasut6a131772019-08-07 19:56:09 +02003248/* WDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003249#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003250static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3251{
3252 int32_t i, k;
3253 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003254 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003255
Marek Vasut6a131772019-08-07 19:56:09 +02003256 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003257 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003258 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003259 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003260 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003261 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3262 continue;
3263
3264 for (i = 0; i <= 8; i++) {
3265 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch))
3266 wdqdm_dly[ch][cs][slice][i] =
3267 wdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3268 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003269 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003270 wdqdm_le[ch][cs][slice][i] = 0;
3271 wdqdm_te[ch][cs][slice][i] = 0;
3272 }
3273 wdqdm_st[ch][cs][slice] = 0;
3274 wdqdm_win[ch][cs][slice] = 0;
3275 }
3276}
3277
3278static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3279{
3280 int32_t i, k;
3281 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003282 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003283 uint32_t err;
3284 const uint32_t _par_WDQLVL_RETRY_THRES = 0x7c0;
3285
3286 int32_t min_win;
3287 int32_t win;
3288 int8_t _adj;
3289 int16_t adj;
3290 uint32_t dq;
3291
Marek Vasut6a131772019-08-07 19:56:09 +02003292 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003293 err = 0;
3294 for (slice = 0; slice < SLICE_CNT; slice += 1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003295 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003296 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3297 continue;
3298
3299 cs = ddr_csn % 2;
3300 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003301 for (i = 0; i < 9; i++) {
3302 dq = slice * 8 + i;
3303 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003304 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003305 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003306 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003307 adj = _f_scale_adj(_adj);
3308
Marek Vasut38dc7562019-08-07 19:17:42 +02003309 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003310 ddr_getval_s(ch, slice,
3311 _reg_PHY_CLK_WRX_SLAVE_DELAY[i]) + adj;
3312 ddr_setval_s(ch, slice, _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003313 data_l);
3314 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003315 }
3316 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, 0x00);
Marek Vasut38dc7562019-08-07 19:17:42 +02003317 data_l = ddr_getval_s(ch, slice, _reg_PHY_WDQLVL_STATUS_OBS);
3318 wdqdm_st[ch][cs][slice] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003319 min_win = INT_LEAST32_MAX;
3320 for (i = 0; i <= 8; i++) {
3321 ddr_setval_s(ch, slice, _reg_PHY_WDQLVL_DQDM_OBS_SELECT,
3322 i);
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_WDQLVL_DQDM_TE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003327 wdqdm_te[ch][cs][slice][i] = data_l;
3328 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003329 ddr_getval_s(ch, slice,
3330 _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003331 wdqdm_le[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003332 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003333 (int32_t)wdqdm_te[ch][cs][slice][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003334 wdqdm_le[ch][cs][slice][i];
3335 if (min_win > win)
3336 min_win = win;
Marek Vasut38dc7562019-08-07 19:17:42 +02003337 if (data_l >= _par_WDQLVL_RETRY_THRES)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003338 err = 2;
3339 }
3340 wdqdm_win[ch][cs][slice] = min_win;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003341 if ((prr_product == PRR_PRODUCT_H3) &&
3342 (prr_cut <= PRR_PRODUCT_11)) {
3343 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3344 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003345 } else {
3346 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3347 ((ch_have_this_cs[1]) >> ch) & 0x01);
3348 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003349 }
3350 return err;
3351}
Marek Vasut6c245a52018-12-12 18:06:39 +01003352#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003353
3354static void wdqdm_cp(uint32_t ddr_csn, uint32_t restore)
3355{
3356 uint32_t i;
3357 uint32_t ch, slice;
3358 uint32_t tgt_cs, src_cs;
3359 uint32_t tmp_r;
3360
Marek Vasut6a131772019-08-07 19:56:09 +02003361 /* copy of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003362 foreach_vch(ch) {
3363 for (tgt_cs = 0; tgt_cs < CS_CNT; tgt_cs++) {
3364 for (slice = 0; slice < SLICE_CNT; slice++) {
3365 ddr_setval_s(ch, slice,
3366 _reg_PHY_PER_CS_TRAINING_INDEX,
3367 tgt_cs);
3368 src_cs = ddr_csn % 2;
3369 if (!(ch_have_this_cs[1] & (1U << ch)))
3370 src_cs = 0;
3371 for (i = 0; i <= 4; i += 4) {
3372 if (restore)
3373 tmp_r =
3374 rdqdm_dly[ch][tgt_cs][slice]
3375 [i];
3376 else
3377 tmp_r =
3378 rdqdm_dly[ch][src_cs][slice]
3379 [i];
3380
3381 ddr_setval_s(ch, slice,
3382 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
3383 [i], tmp_r);
3384 }
3385 }
3386 }
3387 }
3388}
3389
3390static uint32_t wdqdm_man1(void)
3391{
3392 int32_t k;
3393 uint32_t ch, cs, slice;
3394 uint32_t ddr_csn;
Marek Vasut38dc7562019-08-07 19:17:42 +02003395 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003396 uint32_t err;
Marek Vasut6c245a52018-12-12 18:06:39 +01003397 uint32_t high_dq[DRAM_CH_CNT];
3398 uint32_t mr14_csab0_bak[DRAM_CH_CNT];
3399#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003400 uint32_t err_flg;
Marek Vasut6c245a52018-12-12 18:06:39 +01003401#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003402
Marek Vasut6a131772019-08-07 19:56:09 +02003403 /* manual execution of training */
Marek Vasut38dc7562019-08-07 19:17:42 +02003404 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003405 foreach_vch(ch) {
3406 high_dq[ch] = 0;
3407 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003408 k = (board_cnf->ch[ch].dqs_swap >>
3409 (4 * slice)) & 0x0f;
Marek Vasut6c245a52018-12-12 18:06:39 +01003410 if (k >= 2)
3411 high_dq[ch] |= (1U << slice);
3412 }
3413 ddr_setval(ch, _reg_PI_16BIT_DRAM_CONNECT, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003414 }
3415 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003416 err = 0;
3417 /* CLEAR PREV RESULT */
3418 for (cs = 0; cs < CS_CNT; cs++) {
3419 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_INDEX, cs);
Marek Vasut6a131772019-08-07 19:56:09 +02003420 if (((prr_product == PRR_PRODUCT_H3) &&
3421 (prr_cut > PRR_PRODUCT_11)) ||
3422 (prr_product == PRR_PRODUCT_M3N) ||
3423 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003424 ddr_setval_ach_as(_reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS,
3425 0x01);
3426 } else {
3427 ddr_setval_ach_as(_reg_PHY_WDQLVL_CLR_PREV_RESULTS,
3428 0x01);
3429 }
3430 }
3431 ddrphy_regif_idle();
3432
Marek Vasut6c245a52018-12-12 18:06:39 +01003433#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003434 err_flg = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01003435#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003436 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Marek Vasut6a131772019-08-07 19:56:09 +02003437 if ((prr_product == PRR_PRODUCT_H3) &&
3438 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003439 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003440 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3441 data_l &= ~(0x00ffU << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003442
3443 if (ddr_csn >= 2)
3444 k = (high_dq[ch] ^ 0x0f);
3445 else
3446 k = high_dq[ch];
Marek Vasut38dc7562019-08-07 19:17:42 +02003447 data_l |= (k << 16);
3448 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003449 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, k);
3450 }
3451 }
Marek Vasut6a131772019-08-07 19:56:09 +02003452 if (((prr_product == PRR_PRODUCT_H3) &&
3453 (prr_cut <= PRR_PRODUCT_11)) ||
3454 ((prr_product == PRR_PRODUCT_M3) &&
3455 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003456 wdqdm_cp(ddr_csn, 0);
3457 }
3458
3459 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003460 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003461 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003462 reg_pi_mr14_data_fx_csx[1][ddr_csn]);
3463 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003464 }
3465
3466 /* KICK WDQLVL */
3467 err = swlvl1(ddr_csn, _reg_PI_WDQLVL_CS, _reg_PI_WDQLVL_REQ);
3468 if (err)
3469 goto err_exit;
3470
3471 if (ddr_csn == 0)
3472 foreach_vch(ch) {
3473 mr14_csab0_bak[ch] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003474 ddr_getval(ch, reg_pi_mr14_data_fx_csx[1][0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003475 } else
3476 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003477 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0],
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003478 mr14_csab0_bak[ch]);
3479 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003480#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003481 foreach_vch(ch) {
3482 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3483 wdqdm_clr1(ch, ddr_csn);
3484 continue;
3485 }
3486 err = wdqdm_ana1(ch, ddr_csn);
3487 if (err)
3488 err_flg |= (1U << (ddr_csn * 4 + ch));
3489 ddrphy_regif_idle();
3490 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003491#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003492 }
3493err_exit:
Marek Vasut6c245a52018-12-12 18:06:39 +01003494#ifndef DDR_FAST_INIT
3495 err |= err_flg;
3496#endif/* DDR_FAST_INIT */
Marek Vasut38dc7562019-08-07 19:17:42 +02003497 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003498 ddr_setval_ach(_reg_PI_16BIT_DRAM_CONNECT, 0x01);
3499 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003500 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3501 data_l &= ~(0x00ffU << 16);
3502 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01003503 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, 0x00);
3504 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003505 }
Marek Vasut6a131772019-08-07 19:56:09 +02003506 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003507}
3508
3509static uint32_t wdqdm_man(void)
3510{
3511 uint32_t err, retry_cnt;
3512 const uint32_t retry_max = 0x10;
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09003513 uint32_t datal, ch, ddr_csn, mr14_bkup[4][4];
3514
3515 datal = RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2 + 19;
3516 if ((mmio_read_32(DBSC_DBTR(11)) & 0xFF) > datal)
3517 datal = mmio_read_32(DBSC_DBTR(11)) & 0xFF;
3518 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW, datal);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003519
Marek Vasut6a131772019-08-07 19:56:09 +02003520 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3521 (prr_product == PRR_PRODUCT_M3N) ||
3522 (prr_product == PRR_PRODUCT_V3H)) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003523 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F0,
3524 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003525 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F1,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003526 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003527 } else {
3528 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003529 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003530 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003531 ddr_setval_ach(_reg_PI_TRFC_F0, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
3532 ddr_setval_ach(_reg_PI_TRFC_F1, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003533
3534 retry_cnt = 0;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003535 err = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003536 do {
Marek Vasut6a131772019-08-07 19:56:09 +02003537 if ((prr_product == PRR_PRODUCT_H3) &&
3538 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003539 err = wdqdm_man1();
3540 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003541 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x01);
3542 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3543 0x01);
Marek Vasut6a131772019-08-07 19:56:09 +02003544 if ((prr_product == PRR_PRODUCT_M3N) ||
3545 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003546 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3547 0x0C);
3548 } else {
3549 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x0C);
3550 }
3551 dsb_sev();
3552 err = wdqdm_man1();
3553 foreach_vch(ch) {
3554 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3555 mr14_bkup[ch][ddr_csn] =
3556 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003557 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003558 [1][ddr_csn]);
3559 dsb_sev();
3560 }
3561 }
3562
Marek Vasut6a131772019-08-07 19:56:09 +02003563 if ((prr_product == PRR_PRODUCT_M3N) ||
3564 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003565 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3566 0x04);
3567 } else {
3568 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x04);
3569 }
3570 pvtcode_update();
3571 err = wdqdm_man1();
3572 foreach_vch(ch) {
3573 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3574 mr14_bkup[ch][ddr_csn] =
3575 (mr14_bkup[ch][ddr_csn] +
3576 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003577 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003578 [1][ddr_csn])) / 2;
3579 ddr_setval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003580 reg_pi_mr14_data_fx_csx[1]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003581 [ddr_csn],
3582 mr14_bkup[ch][ddr_csn]);
3583 }
3584 }
3585
3586 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3587 0x00);
Marek Vasut6a131772019-08-07 19:56:09 +02003588 if ((prr_product == PRR_PRODUCT_M3N) ||
3589 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003590 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3591 0x00);
3592 ddr_setval_ach
3593 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1,
3594 0x00);
3595 ddr_setval_ach
3596 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1,
3597 0x00);
3598 } else {
3599 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x00);
3600 ddr_setval_ach
3601 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT,
3602 0x00);
3603 ddr_setval_ach
3604 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT,
3605 0x00);
3606 }
3607 ddr_setval_ach(_reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE,
3608 0x00);
3609
3610 pvtcode_update2();
3611 err = wdqdm_man1();
3612 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
3613 }
3614 } while (err && (++retry_cnt < retry_max));
3615
Marek Vasut6a131772019-08-07 19:56:09 +02003616 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
3617 ((prr_product == PRR_PRODUCT_M3) && (prr_cut <= PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003618 wdqdm_cp(0, 1);
3619 }
3620
3621 return (retry_cnt >= retry_max);
3622}
3623
Marek Vasut6a131772019-08-07 19:56:09 +02003624/* RDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003625#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003626static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3627{
3628 int32_t i, k;
3629 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003630 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003631
Marek Vasut6a131772019-08-07 19:56:09 +02003632 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003633 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003634 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003635 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003636 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003637 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3638 continue;
3639
3640 for (i = 0; i <= 8; i++) {
3641 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) {
3642 rdqdm_dly[ch][cs][slice][i] =
3643 rdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3644 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3645 rdqdm_dly[ch][CS_CNT - 1 - cs][slice +
3646 SLICE_CNT]
3647 [i];
3648 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02003649 rdqdm_dly[ch][cs][slice][i] = data_l;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003650 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3651 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003652 }
3653 rdqdm_le[ch][cs][slice][i] = 0;
3654 rdqdm_le[ch][cs][slice + SLICE_CNT][i] = 0;
3655 rdqdm_te[ch][cs][slice][i] = 0;
3656 rdqdm_te[ch][cs][slice + SLICE_CNT][i] = 0;
3657 rdqdm_nw[ch][cs][slice][i] = 0;
3658 rdqdm_nw[ch][cs][slice + SLICE_CNT][i] = 0;
3659 }
3660 rdqdm_st[ch][cs][slice] = 0;
3661 rdqdm_win[ch][cs][slice] = 0;
3662 }
3663}
3664
3665static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3666{
3667 int32_t i, k;
3668 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003669 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003670 uint32_t err;
3671 int8_t _adj;
3672 int16_t adj;
3673 uint32_t dq;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003674 int32_t min_win;
3675 int32_t win;
3676 uint32_t rdq_status_obs_select;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003677
Marek Vasut6a131772019-08-07 19:56:09 +02003678 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003679 err = 0;
3680 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003681 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003682 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3683 continue;
3684
3685 cs = ddr_csn % 2;
3686 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
3687 ddrphy_regif_idle();
3688
3689 ddr_getval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX);
3690 ddrphy_regif_idle();
3691
3692 for (i = 0; i <= 8; i++) {
3693 dq = slice * 8 + i;
3694 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003695 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003696 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003697 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003698
3699 adj = _f_scale_adj(_adj);
3700
Marek Vasut38dc7562019-08-07 19:17:42 +02003701 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003702 ddr_getval_s(ch, slice,
3703 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) +
3704 adj;
3705 ddr_setval_s(ch, slice,
3706 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003707 data_l);
3708 rdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003709
Marek Vasut38dc7562019-08-07 19:17:42 +02003710 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003711 ddr_getval_s(ch, slice,
3712 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) +
3713 adj;
3714 ddr_setval_s(ch, slice,
3715 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003716 data_l);
3717 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003718 }
3719 min_win = INT_LEAST32_MAX;
3720 for (i = 0; i <= 8; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003721 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003722 ddr_getval_s(ch, slice, _reg_PHY_RDLVL_STATUS_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003723 rdqdm_st[ch][cs][slice] = data_l;
3724 rdqdm_st[ch][cs][slice + SLICE_CNT] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003725 /* k : rise/fall */
3726 for (k = 0; k < 2; k++) {
3727 if (i == 8) {
3728 rdq_status_obs_select = 16 + 8 * k;
3729 } else {
3730 rdq_status_obs_select = i + k * 8;
3731 }
3732 ddr_setval_s(ch, slice,
3733 _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT,
3734 rdq_status_obs_select);
3735
Marek Vasut38dc7562019-08-07 19:17:42 +02003736 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003737 ddr_getval_s(ch, slice,
3738 _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS);
3739 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003740 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003741
Marek Vasut38dc7562019-08-07 19:17:42 +02003742 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003743 ddr_getval_s(ch, slice,
3744 _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS);
3745 rdqdm_te[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003746 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003747
Marek Vasut38dc7562019-08-07 19:17:42 +02003748 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003749 ddr_getval_s(ch, slice,
3750 _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS);
3751 rdqdm_nw[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003752 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003753
3754 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003755 (int32_t)rdqdm_te[ch][cs][slice +
Marek Vasut6ad74c32019-08-08 16:34:22 +02003756 SLICE_CNT *
3757 k][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003758 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i];
3759 if (i != 8) {
3760 if (min_win > win)
3761 min_win = win;
3762 }
3763 }
3764 }
3765 rdqdm_win[ch][cs][slice] = min_win;
3766 if (min_win <= 0) {
3767 err = 2;
3768 }
3769 }
Marek Vasut6a131772019-08-07 19:56:09 +02003770 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003771}
Marek Vasut6c245a52018-12-12 18:06:39 +01003772#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003773
3774static uint32_t rdqdm_man1(void)
3775{
3776 uint32_t ch;
3777 uint32_t ddr_csn;
Marek Vasut6c245a52018-12-12 18:06:39 +01003778#ifdef DDR_FAST_INIT
3779 uint32_t slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003780 uint32_t i, adj, data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003781#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003782 uint32_t err;
3783
Marek Vasut6a131772019-08-07 19:56:09 +02003784 /* manual execution of training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003785 err = 0;
3786
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003787 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003788 /* KICK RDQLVL */
3789 err = swlvl1(ddr_csn, _reg_PI_RDLVL_CS, _reg_PI_RDLVL_REQ);
3790 if (err)
3791 goto err_exit;
Marek Vasut6c245a52018-12-12 18:06:39 +01003792#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003793 foreach_vch(ch) {
3794 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3795 rdqdm_clr1(ch, ddr_csn);
3796 ddrphy_regif_idle();
3797 continue;
3798 }
3799 err = rdqdm_ana1(ch, ddr_csn);
3800 ddrphy_regif_idle();
3801 if (err)
3802 goto err_exit;
3803 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003804#else/* DDR_FAST_INIT */
3805 foreach_vch(ch) {
3806 if (ch_have_this_cs[ddr_csn] & (1U << ch)) {
3807 for (slice = 0; slice < SLICE_CNT; slice++) {
3808 if (ddr_getval_s(ch, slice,
Marek Vasut80784f92019-08-07 19:02:26 +02003809 _reg_PHY_RDLVL_STATUS_OBS) !=
Marek Vasut6c245a52018-12-12 18:06:39 +01003810 0x0D00FFFF) {
3811 err = (1U << ch) |
3812 (0x10U << slice);
3813 goto err_exit;
3814 }
3815 }
3816 }
Marek Vasut6a131772019-08-07 19:56:09 +02003817 if (((prr_product == PRR_PRODUCT_H3) &&
3818 (prr_cut <= PRR_PRODUCT_11)) ||
3819 ((prr_product == PRR_PRODUCT_M3) &&
3820 (prr_cut <= PRR_PRODUCT_10))) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003821 for (slice = 0; slice < SLICE_CNT; slice++) {
3822 for (i = 0; i <= 8; i++) {
3823 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003824 adj = _f_scale_adj(board_cnf->ch[ch].dm_adj_r[slice]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003825 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003826 adj = _f_scale_adj(board_cnf->ch[ch].dq_adj_r[slice * 8 + i]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003827 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, ddr_csn);
Marek Vasut38dc7562019-08-07 19:17:42 +02003828 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + adj;
3829 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], data_l);
3830 rdqdm_dly[ch][ddr_csn][slice][i] = data_l;
3831 rdqdm_dly[ch][ddr_csn | 1][slice][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003832
Marek Vasut38dc7562019-08-07 19:17:42 +02003833 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + adj;
3834 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], data_l);
3835 rdqdm_dly[ch][ddr_csn][slice + SLICE_CNT][i] = data_l;
3836 rdqdm_dly[ch][ddr_csn | 1][slice + SLICE_CNT][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003837 }
3838 }
3839 }
3840 }
3841 ddrphy_regif_idle();
3842
3843#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003844 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003845
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003846err_exit:
Marek Vasut6a131772019-08-07 19:56:09 +02003847 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003848}
3849
3850static uint32_t rdqdm_man(void)
3851{
3852 uint32_t err, retry_cnt;
3853 const uint32_t retry_max = 0x01;
3854
3855 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3856 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3857 _reg_PHY_DQ_TSEL_ENABLE));
3858 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3859 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3860 _reg_PHY_DQS_TSEL_ENABLE));
3861 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3862 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3863 _reg_PHY_DQ_TSEL_SELECT));
3864 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3865 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3866 _reg_PHY_DQS_TSEL_SELECT));
3867
3868 retry_cnt = 0;
3869 do {
3870 err = rdqdm_man1();
3871 ddrphy_regif_idle();
3872 } while (err && (++retry_cnt < retry_max));
3873 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3874 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3875 _reg_PHY_DQ_TSEL_ENABLE));
3876 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3877 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3878 _reg_PHY_DQS_TSEL_ENABLE));
3879 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3880 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3881 _reg_PHY_DQ_TSEL_SELECT));
3882 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3883 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3884 _reg_PHY_DQS_TSEL_SELECT));
3885
3886 return (retry_cnt >= retry_max);
3887}
3888
Marek Vasut6a131772019-08-07 19:56:09 +02003889/* rx offset calibration */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003890static int32_t _find_change(uint64_t val, uint32_t dir)
3891{
3892 int32_t i;
3893 uint32_t startval;
3894 uint32_t curval;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003895 const int32_t VAL_END = 0x3f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003896
3897 if (dir == 0) {
3898 startval = (val & 0x01);
3899 for (i = 1; i <= VAL_END; i++) {
3900 curval = (val >> i) & 0x01;
3901 if (curval != startval)
Marek Vasut6a131772019-08-07 19:56:09 +02003902 return i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003903 }
Marek Vasut6a131772019-08-07 19:56:09 +02003904 return VAL_END;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003905 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003906
3907 startval = (val >> dir) & 0x01;
3908 for (i = dir - 1; i >= 0; i--) {
3909 curval = (val >> i) & 0x01;
3910 if (curval != startval)
3911 return i;
3912 }
3913 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003914}
3915
3916static uint32_t _rx_offset_cal_updn(uint32_t code)
3917{
3918 const uint32_t CODE_MAX = 0x40;
3919 uint32_t tmp;
3920
Marek Vasut38dc7562019-08-07 19:17:42 +02003921 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003922 if (code == 0)
3923 tmp = (1U << 6) | (CODE_MAX - 1);
3924 else if (code <= 0x20)
3925 tmp =
3926 ((CODE_MAX - 1 -
3927 (0x20 - code) * 2) << 6) | (CODE_MAX - 1);
3928 else
3929 tmp =
3930 ((CODE_MAX - 1) << 6) | (CODE_MAX - 1 -
3931 (code - 0x20) * 2);
3932 } else {
3933 if (code == 0)
3934 tmp = (1U << 6) | (CODE_MAX - 1);
3935 else
3936 tmp = (code << 6) | (CODE_MAX - code);
3937 }
3938 return tmp;
3939}
3940
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003941static uint32_t rx_offset_cal(void)
3942{
3943 uint32_t index;
3944 uint32_t code;
3945 const uint32_t CODE_MAX = 0x40;
3946 const uint32_t CODE_STEP = 2;
3947 uint32_t ch, slice;
3948 uint32_t tmp;
3949 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
3950 uint64_t val[DRAM_CH_CNT][SLICE_CNT][_reg_PHY_RX_CAL_X_NUM];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003951 uint64_t tmpval;
3952 int32_t lsb, msb;
Marek Vasut6c245a52018-12-12 18:06:39 +01003953
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003954 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x01);
3955 foreach_vch(ch) {
3956 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003957 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003958 val[ch][slice][index] = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003959 }
3960 }
3961
3962 for (code = 0; code < CODE_MAX / CODE_STEP; code++) {
3963 tmp = _rx_offset_cal_updn(code * CODE_STEP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003964 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) {
3965 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[index], tmp);
3966 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003967 dsb_sev();
Marek Vasut80784f92019-08-07 19:02:26 +02003968 ddr_getval_ach_as(_reg_PHY_RX_CAL_OBS, (uint32_t *)tmp_ach_as);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003969
3970 foreach_vch(ch) {
3971 for (slice = 0; slice < SLICE_CNT; slice++) {
3972 tmp = tmp_ach_as[ch][slice];
3973 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3974 index++) {
3975 if (tmp & (1U << index)) {
3976 val[ch][slice][index] |=
3977 (1ULL << code);
3978 } else {
3979 val[ch][slice][index] &=
3980 ~(1ULL << code);
3981 }
3982 }
3983 }
3984 }
3985 }
3986 foreach_vch(ch) {
3987 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003988 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3989 index++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003990 tmpval = val[ch][slice][index];
3991 lsb = _find_change(tmpval, 0);
3992 msb =
3993 _find_change(tmpval,
3994 (CODE_MAX / CODE_STEP) - 1);
3995 tmp = (lsb + msb) >> 1;
3996
3997 tmp = _rx_offset_cal_updn(tmp * CODE_STEP);
3998 ddr_setval_s(ch, slice,
3999 _reg_PHY_RX_CAL_X[index], tmp);
4000 }
4001 }
4002 }
4003 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004004
4005 return 0;
4006}
4007
4008static uint32_t rx_offset_cal_hw(void)
4009{
4010 uint32_t ch, slice;
4011 uint32_t retry;
4012 uint32_t complete;
4013 uint32_t tmp;
4014 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
4015
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004016 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[9], 0x00);
4017 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
4018 ddr_setval_ach_as(_reg_PHY_RX_CAL_SAMPLE_WAIT, 0x0f);
4019
4020 retry = 0;
4021 while (retry < 4096) {
4022 if ((retry & 0xff) == 0) {
4023 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
4024 }
4025 foreach_vch(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02004026 for (slice = 0; slice < SLICE_CNT; slice++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004027 tmp_ach_as[ch][slice] =
4028 ddr_getval_s(ch, slice, _reg_PHY_RX_CAL_X[9]);
4029
4030 complete = 1;
4031 foreach_vch(ch) {
4032 for (slice = 0; slice < SLICE_CNT; slice++) {
4033 tmp = tmp_ach_as[ch][slice];
4034 tmp = (tmp & 0x3f) + ((tmp >> 6) & 0x3f);
Marek Vasut6a131772019-08-07 19:56:09 +02004035 if (((prr_product == PRR_PRODUCT_H3) &&
4036 (prr_cut > PRR_PRODUCT_11)) ||
4037 (prr_product == PRR_PRODUCT_M3N) ||
4038 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004039 if (tmp != 0x3E)
4040 complete = 0;
4041 } else {
4042 if (tmp != 0x40)
4043 complete = 0;
4044 }
4045 }
4046 }
4047 if (complete)
4048 break;
4049
4050 retry++;
4051 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004052
4053 return (complete == 0);
4054}
4055
Marek Vasut6a131772019-08-07 19:56:09 +02004056/* adjust rddqs latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004057static void adjust_rddqs_latency(void)
4058{
4059 uint32_t ch, slice;
4060 uint32_t dly;
4061 uint32_t maxlatx2;
4062 uint32_t tmp;
4063 uint32_t rdlat_adjx2[SLICE_CNT];
Marek Vasut80784f92019-08-07 19:02:26 +02004064
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004065 foreach_vch(ch) {
4066 maxlatx2 = 0;
4067 for (slice = 0; slice < SLICE_CNT; slice++) {
4068 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX,
4069 0x00);
4070
4071 dly =
4072 ddr_getval_s(ch, slice,
4073 _reg_PHY_RDDQS_GATE_SLAVE_DELAY);
4074 tmp =
4075 ddr_getval_s(ch, slice,
4076 _reg_PHY_RDDQS_LATENCY_ADJUST);
4077 /* note gate_slave_delay[9] is always 0 */
4078 tmp = (tmp << 1) + (dly >> 8);
4079 rdlat_adjx2[slice] = tmp;
4080 if (maxlatx2 < tmp)
4081 maxlatx2 = tmp;
4082 }
4083 maxlatx2 = ((maxlatx2 + 1) >> 1) << 1;
4084 for (slice = 0; slice < SLICE_CNT; slice++) {
4085 tmp = maxlatx2 - rdlat_adjx2[slice];
4086 tmp = (tmp >> 1);
4087 if (tmp) {
4088 ddr_setval_s(ch, slice, _reg_PHY_RPTR_UPDATE,
4089 ddr_getval_s(ch, slice,
4090 _reg_PHY_RPTR_UPDATE)
4091 + 1);
4092 }
4093 }
4094 }
4095}
4096
Marek Vasut6a131772019-08-07 19:56:09 +02004097/* adjust wpath latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004098static void adjust_wpath_latency(void)
4099{
4100 uint32_t ch, cs, slice;
4101 uint32_t dly;
4102 uint32_t wpath_add;
4103 const uint32_t _par_EARLY_THRESHOLD_VAL = 0x180;
4104
4105 foreach_vch(ch) {
4106 for (slice = 0; slice < SLICE_CNT; slice += 1) {
4107 for (cs = 0; cs < CS_CNT; cs++) {
4108 ddr_setval_s(ch, slice,
4109 _reg_PHY_PER_CS_TRAINING_INDEX,
4110 cs);
4111 ddr_getval_s(ch, slice,
4112 _reg_PHY_PER_CS_TRAINING_INDEX);
4113 dly =
4114 ddr_getval_s(ch, slice,
4115 _reg_PHY_CLK_WRDQS_SLAVE_DELAY);
4116 if (dly <= _par_EARLY_THRESHOLD_VAL)
4117 continue;
4118
4119 wpath_add =
4120 ddr_getval_s(ch, slice,
4121 _reg_PHY_WRITE_PATH_LAT_ADD);
4122 ddr_setval_s(ch, slice,
4123 _reg_PHY_WRITE_PATH_LAT_ADD,
4124 wpath_add - 1);
4125 }
4126 }
4127 }
4128}
4129
Marek Vasut6a131772019-08-07 19:56:09 +02004130/* DDR Initialize entry */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004131int32_t rcar_dram_init(void)
4132{
4133 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02004134 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004135 uint32_t bus_mbps, bus_mbpsdiv;
4136 uint32_t tmp_tccd;
4137 uint32_t failcount;
Marek Vasut38dc7562019-08-07 19:17:42 +02004138 uint32_t cnf_boardtype;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004139
Marek Vasut6a131772019-08-07 19:56:09 +02004140 /* Thermal sensor setting */
Marek Vasut38dc7562019-08-07 19:17:42 +02004141 data_l = mmio_read_32(CPG_MSTPSR5);
4142 if (data_l & BIT(22)) { /* case THS/TSC Standby */
Marek Vasut6a131772019-08-07 19:56:09 +02004143 data_l &= ~BIT(22);
Marek Vasut38dc7562019-08-07 19:17:42 +02004144 cpg_write_32(CPG_SMSTPCR5, data_l);
Marek Vasut6a131772019-08-07 19:56:09 +02004145 while (mmio_read_32(CPG_MSTPSR5) & BIT(22))
4146 ; /* wait bit=0 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004147 }
4148
4149 /* THCTR Bit6: PONM=0 , Bit0: THSST=0 */
Chiaki Fujii750b5c92020-10-30 10:45:18 +09004150 data_l = mmio_read_32(THS1_THCTR);
4151 if (data_l & 0x00000040U) {
4152 data_l = data_l & 0xFFFFFFBEU;
4153 } else {
4154 data_l = data_l | BIT(1);
4155 }
4156
Marek Vasut38dc7562019-08-07 19:17:42 +02004157 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004158
Marek Vasut6a131772019-08-07 19:56:09 +02004159 /* Judge product and cut */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004160#ifdef RCAR_DDR_FIXED_LSI_TYPE
Marek Vasut80784f92019-08-07 19:02:26 +02004161#if (RCAR_LSI == RCAR_AUTO)
Marek Vasut38dc7562019-08-07 19:17:42 +02004162 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4163 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004164#else /* RCAR_LSI */
4165#ifndef RCAR_LSI_CUT
Marek Vasut38dc7562019-08-07 19:17:42 +02004166 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004167#endif /* RCAR_LSI_CUT */
4168#endif /* RCAR_LSI */
4169#else /* RCAR_DDR_FIXED_LSI_TYPE */
Marek Vasut38dc7562019-08-07 19:17:42 +02004170 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4171 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004172#endif /* RCAR_DDR_FIXED_LSI_TYPE */
4173
Marek Vasut38dc7562019-08-07 19:17:42 +02004174 if (prr_product == PRR_PRODUCT_H3) {
4175 if (prr_cut <= PRR_PRODUCT_11) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004176 p_ddr_regdef_tbl =
4177 (const uint32_t *)&DDR_REGDEF_TBL[0][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004178 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004179 p_ddr_regdef_tbl =
4180 (const uint32_t *)&DDR_REGDEF_TBL[2][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004181 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004182 } else if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004183 p_ddr_regdef_tbl =
4184 (const uint32_t *)&DDR_REGDEF_TBL[1][0];
Marek Vasut6a131772019-08-07 19:56:09 +02004185 } else if ((prr_product == PRR_PRODUCT_M3N) ||
4186 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004187 p_ddr_regdef_tbl =
4188 (const uint32_t *)&DDR_REGDEF_TBL[3][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004189 } else {
Marek Vasut6c245a52018-12-12 18:06:39 +01004190 FATAL_MSG("BL2: DDR:Unknown Product\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004191 return 0xff;
4192 }
4193
Marek Vasut6a131772019-08-07 19:56:09 +02004194 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4195 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004196 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4197 } else {
4198 mmio_write_32(DBSC_DBSYSCNT0, 0x00001234);
4199 }
4200
Marek Vasut6a131772019-08-07 19:56:09 +02004201 /* Judge board type */
Marek Vasut38dc7562019-08-07 19:17:42 +02004202 cnf_boardtype = boardcnf_get_brd_type();
4203 if (cnf_boardtype >= BOARDNUM) {
Marek Vasut6c245a52018-12-12 18:06:39 +01004204 FATAL_MSG("BL2: DDR:Unknown Board\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004205 return 0xff;
4206 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004207 board_cnf = (const struct _boardcnf *)&boardcnfs[cnf_boardtype];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004208
4209/* RCAR_DRAM_SPLIT_2CH (2U) */
4210#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02004211 /* H3(Test for future H3-N): Swap ch2 and ch1 for 2ch-split */
Marek Vasut38dc7562019-08-07 19:17:42 +02004212 if ((prr_product == PRR_PRODUCT_H3) && (board_cnf->phyvalid == 0x05)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004213 mmio_write_32(DBSC_DBMEMSWAPCONF0, 0x00000006);
4214 ddr_phyvalid = 0x03;
4215 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004216 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004217 }
4218#else /* RCAR_DRAM_SPLIT_2CH */
Marek Vasut38dc7562019-08-07 19:17:42 +02004219 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004220#endif /* RCAR_DRAM_SPLIT_2CH */
4221
4222 max_density = 0;
4223
4224 for (cs = 0; cs < CS_CNT; cs++) {
4225 ch_have_this_cs[cs] = 0;
4226 }
4227
4228 foreach_ech(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02004229 for (cs = 0; cs < CS_CNT; cs++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004230 ddr_density[ch][cs] = 0xff;
4231
4232 foreach_vch(ch) {
4233 for (cs = 0; cs < CS_CNT; cs++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004234 data_l = board_cnf->ch[ch].ddr_density[cs];
4235 ddr_density[ch][cs] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004236
Marek Vasut38dc7562019-08-07 19:17:42 +02004237 if (data_l == 0xff)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004238 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02004239 if (data_l > max_density)
4240 max_density = data_l;
Marek Vasut6a131772019-08-07 19:56:09 +02004241 if ((cs == 1) && (prr_product == PRR_PRODUCT_H3) &&
4242 (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004243 continue;
4244 ch_have_this_cs[cs] |= (1U << ch);
4245 }
4246 }
4247
Marek Vasut6a131772019-08-07 19:56:09 +02004248 /* Judge board clock frequency (in MHz) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004249 boardcnf_get_brd_clk(cnf_boardtype, &brd_clk, &brd_clkdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004250 if ((brd_clk / brd_clkdiv) > 25) {
4251 brd_clkdiva = 1;
4252 } else {
4253 brd_clkdiva = 0;
4254 }
4255
Marek Vasut6a131772019-08-07 19:56:09 +02004256 /* Judge ddr operating frequency clock(in Mbps) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004257 boardcnf_get_ddr_mbps(cnf_boardtype, &ddr_mbps, &ddr_mbpsdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004258
4259 ddr0800_mul = CLK_DIV(800, 2, brd_clk, brd_clkdiv * (brd_clkdiva + 1));
4260
Marek Vasut80784f92019-08-07 19:02:26 +02004261 ddr_mul = CLK_DIV(ddr_mbps, ddr_mbpsdiv * 2, brd_clk,
4262 brd_clkdiv * (brd_clkdiva + 1));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004263
Marek Vasut6a131772019-08-07 19:56:09 +02004264 /* Adjust tccd */
Marek Vasut38dc7562019-08-07 19:17:42 +02004265 data_l = (0x00006000 & mmio_read_32(RST_MODEMR)) >> 13;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09004266 bus_mbps = 0;
4267 bus_mbpsdiv = 0;
Marek Vasut38dc7562019-08-07 19:17:42 +02004268 switch (data_l) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004269 case 0:
4270 bus_mbps = brd_clk * 0x60 * 2;
4271 bus_mbpsdiv = brd_clkdiv * 1;
4272 break;
4273 case 1:
4274 bus_mbps = brd_clk * 0x50 * 2;
4275 bus_mbpsdiv = brd_clkdiv * 1;
4276 break;
4277 case 2:
4278 bus_mbps = brd_clk * 0x40 * 2;
4279 bus_mbpsdiv = brd_clkdiv * 1;
4280 break;
4281 case 3:
4282 bus_mbps = brd_clk * 0x60 * 2;
4283 bus_mbpsdiv = brd_clkdiv * 2;
4284 break;
4285 default:
4286 bus_mbps = brd_clk * 0x60 * 2;
4287 bus_mbpsdiv = brd_clkdiv * 2;
4288 break;
4289 }
4290 tmp_tccd = CLK_DIV(ddr_mbps * 8, ddr_mbpsdiv, bus_mbps, bus_mbpsdiv);
4291 if (8 * ddr_mbps * bus_mbpsdiv != tmp_tccd * bus_mbps * ddr_mbpsdiv)
4292 tmp_tccd = tmp_tccd + 1;
4293
4294 if (tmp_tccd < 8)
4295 ddr_tccd = 8;
4296 else
4297 ddr_tccd = tmp_tccd;
4298
Marek Vasut6c245a52018-12-12 18:06:39 +01004299 NOTICE("BL2: DDR%d(%s)\n", ddr_mbps / ddr_mbpsdiv, RCAR_DDR_VERSION);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004300
4301 MSG_LF("Start\n");
4302
Marek Vasut6a131772019-08-07 19:56:09 +02004303 /* PLL Setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004304 pll3_control(1);
4305
Marek Vasut6a131772019-08-07 19:56:09 +02004306 /* initialize DDR */
Marek Vasut38dc7562019-08-07 19:17:42 +02004307 data_l = init_ddr();
4308 if (data_l == ddr_phyvalid) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004309 failcount = 0;
4310 } else {
4311 failcount = 1;
4312 }
4313
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004314 foreach_vch(ch)
4315 mmio_write_32(DBSC_DBPDLK(ch), 0x00000000);
Marek Vasut6a131772019-08-07 19:56:09 +02004316 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4317 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004318 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4319 } else {
4320 mmio_write_32(DBSC_DBSYSCNT0, 0x00000000);
4321 }
4322
4323 if (failcount == 0) {
4324 return INITDRAM_OK;
4325 } else {
4326 return INITDRAM_NG;
4327 }
4328}
4329
4330void pvtcode_update(void)
4331{
4332 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004333 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004334 uint32_t pvtp[4], pvtn[4], pvtp_init, pvtn_init;
4335 int32_t pvtp_tmp, pvtn_tmp;
4336
4337 foreach_vch(ch) {
4338 pvtn_init = (tcal.tcomp_cal[ch] & 0xFC0) >> 6;
4339 pvtp_init = (tcal.tcomp_cal[ch] & 0x03F) >> 0;
4340
4341 if (8912 * pvtp_init > 44230) {
4342 pvtp_tmp = (5000 + 8912 * pvtp_init - 44230) / 10000;
4343 } else {
4344 pvtp_tmp =
4345 -((-(5000 + 8912 * pvtp_init - 44230)) / 10000);
4346 }
4347 pvtn_tmp = (5000 + 5776 * pvtn_init + 30280) / 10000;
4348
4349 pvtn[ch] = pvtn_tmp + pvtn_init;
4350 pvtp[ch] = pvtp_tmp + pvtp_init;
4351
4352 if (pvtn[ch] > 63) {
4353 pvtn[ch] = 63;
4354 pvtp[ch] =
4355 (pvtp_tmp) * (63 - 6 * pvtn_tmp -
4356 pvtn_init) / (pvtn_tmp) +
4357 6 * pvtp_tmp + pvtp_init;
4358 }
Marek Vasut6a131772019-08-07 19:56:09 +02004359 if ((prr_product == PRR_PRODUCT_H3) &&
4360 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004361 data_l = pvtp[ch] | (pvtn[ch] << 6) |
4362 (tcal.tcomp_cal[ch] & 0xfffff000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004363 reg_ddrphy_write(ch,
4364 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004365 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004366 reg_ddrphy_write(ch,
4367 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004368 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004369 reg_ddrphy_write(ch,
4370 ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004371 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004372 reg_ddrphy_write(ch,
4373 ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004374 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004375 reg_ddrphy_write(ch,
4376 ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004377 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004378 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004379 data_l = pvtp[ch] | (pvtn[ch] << 6) | 0x00015000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004380 reg_ddrphy_write(ch,
4381 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004382 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004383 reg_ddrphy_write(ch,
4384 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004385 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004386 reg_ddrphy_write(ch,
4387 ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004388 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004389 reg_ddrphy_write(ch,
4390 ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004391 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004392 reg_ddrphy_write(ch,
4393 ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004394 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004395 }
4396 }
4397}
4398
4399void pvtcode_update2(void)
4400{
4401 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02004402
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004403 foreach_vch(ch) {
4404 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
4405 tcal.init_cal[ch] | 0x00020000);
4406 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
4407 tcal.init_cal[ch]);
4408 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
4409 tcal.init_cal[ch]);
4410 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
4411 tcal.init_cal[ch]);
4412 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
4413 tcal.init_cal[ch]);
4414 }
4415}
4416
4417void ddr_padcal_tcompensate_getinit(uint32_t override)
4418{
4419 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004420 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004421 uint32_t pvtp, pvtn;
4422
4423 tcal.init_temp = 0;
4424 for (ch = 0; ch < 4; ch++) {
4425 tcal.init_cal[ch] = 0;
4426 tcal.tcomp_cal[ch] = 0;
4427 }
4428
4429 foreach_vch(ch) {
4430 tcal.init_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4431 tcal.tcomp_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4432 }
4433
4434 if (!override) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004435 data_l = mmio_read_32(THS1_TEMP);
4436 if (data_l < 2800) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004437 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004438 (143 * (int32_t)data_l - 359000) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004439 } else {
4440 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004441 (121 * (int32_t)data_l - 296300) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004442 }
4443
4444 foreach_vch(ch) {
4445 pvtp = (tcal.init_cal[ch] >> 0) & 0x000003F;
4446 pvtn = (tcal.init_cal[ch] >> 6) & 0x000003F;
Marek Vasut80784f92019-08-07 19:02:26 +02004447 if ((int32_t)pvtp >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004448 ((tcal.init_temp * 29 - 3625) / 1000))
4449 pvtp =
Marek Vasut80784f92019-08-07 19:02:26 +02004450 (int32_t)pvtp +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004451 ((3625 - tcal.init_temp * 29) / 1000);
4452 else
4453 pvtp = 0;
4454
Marek Vasut80784f92019-08-07 19:02:26 +02004455 if ((int32_t)pvtn >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004456 ((tcal.init_temp * 54 - 6750) / 1000))
4457 pvtn =
Marek Vasut80784f92019-08-07 19:02:26 +02004458 (int32_t)pvtn +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004459 ((6750 - tcal.init_temp * 54) / 1000);
4460 else
4461 pvtn = 0;
4462
Marek Vasut6a131772019-08-07 19:56:09 +02004463 if ((prr_product == PRR_PRODUCT_H3) &&
4464 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004465 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004466 (tcal.init_cal[ch] & 0xfffff000) |
4467 (pvtn << 6) |
4468 pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004469 } else {
4470 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004471 0x00015000 | (pvtn << 6) | pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004472 }
4473 }
4474 tcal.init_temp = 125;
4475 }
4476}
4477
4478#ifndef ddr_qos_init_setting
Marek Vasut6ad74c32019-08-08 16:34:22 +02004479/* For QoS init */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004480uint8_t get_boardcnf_phyvalid(void)
4481{
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004482 return ddr_phyvalid;
4483}
4484#endif /* ddr_qos_init_setting */